better support for mime/digest
[claws.git] / src / quote_fmt_parse.y
1 %{
2
3 #include "defs.h"
4
5 #include <glib.h>
6 #include <ctype.h>
7
8 #include "procmsg.h"
9 #include "procmime.h"
10 #include "utils.h"
11 #include "intl.h"
12
13 #include "quote_fmt.h"
14 #include "quote_fmt_lex.h"
15
16 /* decl */
17 /*
18 flex quote_fmt.l
19 bison -p quote_fmt quote_fmt.y
20 */
21
22 int yylex(void);
23
24 static MsgInfo *msginfo = NULL;
25 static gboolean *visible = NULL;
26 static gint maxsize = 0;
27 static gint stacksize = 0;
28
29 static gchar *buffer = NULL;
30 static gint bufmax = 0;
31 static gint bufsize = 0;
32 static gchar *quote_str = NULL;
33 static gint error = 0;
34
35 static void add_visibility(gboolean val)
36 {
37         stacksize++;
38         if (maxsize < stacksize) {
39                 maxsize += 128;
40                 visible = g_realloc(visible, maxsize * sizeof(gboolean));
41                 if (visible == NULL)
42                         maxsize = 0;
43         }
44
45         visible[stacksize - 1] = val;
46 }
47
48 static void remove_visibility(void)
49 {
50         stacksize--;
51 }
52
53 static void add_buffer(gchar *s)
54 {
55         gint len;
56
57         len = strlen(s);
58         if (bufsize + len + 1 > bufmax) {
59                 if (bufmax == 0)
60                         bufmax = 128;
61                 while (bufsize + len + 1 > bufmax)
62                         bufmax *= 2;
63                 buffer = g_realloc(buffer, bufmax);
64         }
65         strcpy(buffer + bufsize, s);
66         bufsize += len;
67 }
68
69 static void flush_buffer(void)
70 {
71         if (buffer != NULL)
72                 *buffer = '\0';
73         bufsize = 0;
74 }
75
76 gchar *quote_fmt_get_buffer(void)
77 {
78         if (error != 0)
79                 return NULL;
80         else
81                 return buffer;
82 }
83
84 #define INSERT(buf) \
85         if (stacksize != 0 && visible[stacksize - 1]) \
86                 add_buffer(buf)
87
88 #define INSERT_CHARACTER(chr) \
89         if (stacksize != 0 && visible[stacksize - 1]) { \
90                 gchar tmp[2]; \
91                 tmp[0] = (chr); \
92                 tmp[1] = '\0'; \
93                 add_buffer(tmp); \
94         }
95
96 void quote_fmt_init(MsgInfo *info, gchar *my_quote_str)
97 {
98         quote_str = my_quote_str;
99         msginfo = info;
100         stacksize = 0;
101         add_visibility(TRUE);
102         if (buffer != NULL)
103                 *buffer = 0;
104         bufsize = 0;
105         error = 0;
106 }
107
108 void quote_fmterror(char *str)
109 {
110         g_warning(_("Error: %s\n"), str);
111         error = 1;
112 }
113
114 int quote_fmtwrap(void)
115 {
116         return 1;
117 }
118
119 static int isseparator(char ch)
120 {
121         return isspace(ch) || ch == '.' || ch == '-';
122 }
123 %}
124
125 %union {
126         char chr;
127 }
128
129 %token SHOW_NEWSGROUPS
130 %token SHOW_DATE SHOW_FROM SHOW_FULLNAME SHOW_FIRST_NAME
131 %token SHOW_SENDER_INITIAL SHOW_SUBJECT SHOW_TO SHOW_MESSAGEID
132 %token SHOW_PERCENT SHOW_CC SHOW_REFERENCES SHOW_MESSAGE
133 %token SHOW_QUOTED_MESSAGE SHOW_BACKSLASH SHOW_TAB
134 %token SHOW_QUOTED_MESSAGE_NO_SIGNATURE SHOW_MESSAGE_NO_SIGNATURE
135 %token SHOW_EOL SHOW_QUESTION_MARK SHOW_OPARENT SHOW_CPARENT
136 %token QUERY_DATE QUERY_FROM
137 %token QUERY_FULLNAME QUERY_SUBJECT QUERY_TO QUERY_NEWSGROUPS
138 %token QUERY_MESSAGEID QUERY_CC QUERY_REFERENCES
139 %token OPARENT CPARENT
140 %token CHARACTER
141
142 %start quote_fmt
143
144 %token <chr> CHARACTER
145 %type <chr> character
146
147 %%
148
149 quote_fmt:
150         character_or_special_or_query_list;
151
152 character_or_special_or_query_list:
153         character_or_special_or_query character_or_special_or_query_list
154         | character_or_special_or_query ;
155
156 character_or_special_or_query:
157         special ;
158         | character
159         {
160                 INSERT_CHARACTER($1);
161         }
162         | query ;
163
164
165 character:
166         CHARACTER
167         ;
168
169 special:
170         SHOW_NEWSGROUPS
171         {
172                 if (msginfo->newsgroups)
173                         INSERT(msginfo->newsgroups);
174         }
175         | SHOW_DATE
176         {
177                 if (msginfo->date)
178                         INSERT(msginfo->date);
179         }
180         | SHOW_FROM
181         {
182                 if (msginfo->from)
183                         INSERT(msginfo->from);
184         }
185         | SHOW_FULLNAME
186         {
187                 if (msginfo->fromname)
188                         INSERT(msginfo->fromname);
189         }
190         | SHOW_FIRST_NAME
191         {
192                 if (msginfo->fromname) {
193                         gchar *p;
194                         gchar *str;
195
196                         str = alloca(strlen(msginfo->fromname) + 1);
197                         if (str != NULL) {
198                                 strcpy(str, msginfo->fromname);
199                                 p = str;
200                                 while (*p && !isspace(*p)) p++;
201                                 *p = '\0';
202                                 INSERT(str);
203                         }
204                 }
205         }
206         | SHOW_SENDER_INITIAL
207         {
208 #define MAX_SENDER_INITIAL 20
209                 if (msginfo->fromname) {
210                         gchar tmp[MAX_SENDER_INITIAL];
211                         gchar *p;
212                         gchar *cur;
213                         gint len = 0;
214
215                         p = msginfo->fromname;
216                         cur = tmp;
217                         while (*p) {
218                                 if (*p && isalnum(*p)) {
219                                         *cur = toupper(*p);
220                                                 cur++;
221                                         len++;
222                                         if (len >= MAX_SENDER_INITIAL - 1)
223                                                 break;
224                                 } else
225                                         break;
226                                 while (*p && !isseparator(*p)) p++;
227                                 while (*p && isseparator(*p)) p++;
228                         }
229                         *cur = '\0';
230                         INSERT(tmp);
231                 }
232         }
233         | SHOW_SUBJECT
234         {
235                 if (msginfo->subject)
236                         INSERT(msginfo->subject);
237         }
238         | SHOW_TO
239         {
240                 if (msginfo->to)
241                         INSERT(msginfo->to);
242         }
243         | SHOW_MESSAGEID
244         {
245                 if (msginfo->msgid)
246                         INSERT(msginfo->msgid);
247         }
248         | SHOW_PERCENT
249         {
250                 INSERT("%");
251         }
252         | SHOW_CC
253         {
254                 if (msginfo->cc)
255                         INSERT(msginfo->cc);
256         }
257         | SHOW_REFERENCES
258         {
259                 /* if (msginfo->references)
260                         INSERT(msginfo->references); */
261         }
262         | SHOW_MESSAGE
263         {
264                 if (msginfo->folder) {
265                         gchar buf[BUFFSIZE];
266                         FILE *fp;
267
268                         if ((fp = procmime_get_first_text_content(msginfo))
269                             == NULL)
270                                 g_warning(_("Can't get text part\n"));
271                         else {
272                                 while (fgets(buf, sizeof(buf), fp) != NULL) {
273                                         strcrchomp(buf);
274                                         INSERT(buf);
275                                 }
276                                 fclose(fp);
277                         }
278                 }
279         }
280         | SHOW_QUOTED_MESSAGE
281         {
282                 if (msginfo->folder) {
283                         gchar buf[BUFFSIZE];
284                         FILE *fp;
285
286                         if ((fp = procmime_get_first_text_content(msginfo))
287                             == NULL)
288                                 g_warning(_("Can't get text part\n"));
289                         else {
290                                 while (fgets(buf, sizeof(buf), fp) != NULL) {
291                                         strcrchomp(buf);
292                                         if (quote_str)
293                                                 INSERT(quote_str);
294                                         INSERT(buf);
295                                 }
296                                 fclose(fp);
297                         }
298                 }
299         }
300         | SHOW_MESSAGE_NO_SIGNATURE
301         {
302                 if (msginfo->folder) {
303                         gchar buf[BUFFSIZE];
304                         FILE *fp;
305
306                         if ((fp = procmime_get_first_text_content(msginfo))
307                             == NULL)
308                                 g_warning(_("Can't get text part\n"));
309                         else {
310                                 while (fgets(buf, sizeof(buf), fp) != NULL) {
311                                         strcrchomp(buf);
312                                         if (strncmp(buf, "-- ", 3) == 0)
313                                                 break;
314                                         INSERT(buf);
315                                 }
316                                 fclose(fp);
317                         }
318                 }
319         }
320         | SHOW_QUOTED_MESSAGE_NO_SIGNATURE
321         {
322                 if (msginfo->folder) {
323                         gchar buf[BUFFSIZE];
324                         FILE *fp;
325
326                         if ((fp = procmime_get_first_text_content(msginfo))
327                             == NULL)
328                                 g_warning(_("Can't get text part\n"));
329                         else {
330                                 while (fgets(buf, sizeof(buf), fp) != NULL) {
331                                         strcrchomp(buf);
332                                         if (strncmp(buf, "-- ", 3) == 0)
333                                                 break;
334                                         if (quote_str)
335                                                 INSERT(quote_str);
336                                         INSERT(buf);
337                                 }
338                                 fclose(fp);
339                         }
340                 }
341         }
342         | SHOW_BACKSLASH
343         {
344                 INSERT("\\");
345         }
346         | SHOW_TAB
347         {
348                 INSERT("\t");
349         }
350         | SHOW_EOL
351         {
352                 INSERT("\n");
353         }
354         | SHOW_QUESTION_MARK
355         {
356                 INSERT("?");
357         }
358         | SHOW_OPARENT
359         {
360                 INSERT("{");
361         }
362         | SHOW_CPARENT
363         {
364                 INSERT("}");
365         };
366
367 query:
368         QUERY_DATE
369         {
370                 add_visibility(msginfo->date != NULL);
371         }
372         OPARENT quote_fmt CPARENT
373         {
374                 remove_visibility();
375         }
376         | QUERY_FROM
377         {
378                 add_visibility(msginfo->from != NULL);
379         }
380         OPARENT quote_fmt CPARENT
381         {
382                 remove_visibility();
383         }
384         | QUERY_FULLNAME
385         {
386                 add_visibility(msginfo->fromname != NULL);
387         }
388         OPARENT quote_fmt CPARENT
389         {
390                 remove_visibility();
391         }
392         | QUERY_SUBJECT
393         {
394                 add_visibility(msginfo->subject != NULL);
395         }
396         OPARENT quote_fmt CPARENT
397         {
398                 remove_visibility();
399         }
400         | QUERY_TO
401         {
402                 add_visibility(msginfo->to != NULL);
403         }
404         OPARENT quote_fmt CPARENT
405         {
406                 remove_visibility();
407         }
408         | QUERY_NEWSGROUPS
409         {
410                 add_visibility(msginfo->newsgroups != NULL);
411         }
412         OPARENT quote_fmt CPARENT
413         {
414                 remove_visibility();
415         }
416         | QUERY_MESSAGEID
417         {
418                 add_visibility(msginfo->msgid != NULL);
419         }
420         OPARENT quote_fmt CPARENT
421         {
422                 remove_visibility();
423         }
424         | QUERY_CC
425         {
426                 add_visibility(msginfo->cc != NULL);
427         }
428         OPARENT quote_fmt CPARENT
429         {
430                 remove_visibility();
431         }
432         | QUERY_REFERENCES
433         {
434                 /* add_visibility(msginfo->references != NULL); */
435         }
436         OPARENT quote_fmt CPARENT
437         {
438                 remove_visibility();
439         };