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