This commit was manufactured by cvs2svn to create branch 'gtk2'.
[claws.git] / src / matcher_parser_parse.y
1
2 %{
3
4 /*
5  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
6  * Copyright (c) 2001-2002 by Hiroyuki Yamamoto & The Sylpheed Claws Team.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21  */
22
23 #include "defs.h"
24
25 #include <glib.h>
26
27 #include "intl.h"
28 #include "utils.h"
29 #include "filtering.h"
30 #include "matcher.h"
31 #include "matcher_parser.h"
32 #include "matcher_parser_lex.h"
33 #include "procmsg.h"
34
35 #define MAX_COLORLABELS (MSG_CLABEL_7 - MSG_CLABEL_NONE)
36
37 static gint error = 0;
38 static gint bool_op = 0;
39 static gint match_type = 0;
40 static gchar *header = NULL;
41
42 static MatcherProp *prop;
43
44 static GSList *matchers_list = NULL;
45
46 static MatcherList *cond;
47 static gint score = 0;
48 static GSList *action_list = NULL;
49 static FilteringAction *action = NULL;
50
51 static FilteringProp *filtering;
52
53 static GSList **prefs_filtering = NULL;
54 static int enable_compatibility = 0;
55
56 enum {
57         MATCHER_PARSE_FILE,
58         MATCHER_PARSE_NO_EOL,
59         MATCHER_PARSE_CONDITION,
60         MATCHER_PARSE_FILTERING_ACTION,
61 };
62
63 static int matcher_parse_op = MATCHER_PARSE_FILE;
64
65
66 /* ******************************************************************** */
67
68 void matcher_parser_start_parsing(FILE *f)
69 {
70         matcher_parserrestart(f);
71         matcher_parserparse();
72 }
73
74  
75 void * matcher_parser_scan_string(const char * str);
76  
77 FilteringProp *matcher_parser_get_filtering(const gchar *str)
78 {
79         void *bufstate;
80
81         /* bad coding to enable the sub-grammar matching
82            in yacc */
83         matcher_parserlineno = 1;
84         matcher_parse_op = MATCHER_PARSE_NO_EOL;
85         matcher_parserrestart(NULL);
86         matcher_parser_init();
87         bufstate = matcher_parser_scan_string((const char *) str);
88         matcher_parser_switch_to_buffer(bufstate);
89         if (matcher_parserparse() != 0)
90                 filtering = NULL;
91         matcher_parse_op = MATCHER_PARSE_FILE;
92         matcher_parser_delete_buffer(bufstate);
93         return filtering;
94 }
95
96 static gboolean check_quote_symetry(gchar *str)
97 {
98         const gchar *walk;
99         int ret = 0;
100         
101         if (str == NULL)
102                 return TRUE; /* heh, that's symetric */
103         if (*str == '\0')
104                 return TRUE;
105         for (walk = str; *walk; walk++) {
106                 if (*walk == '\"') {
107                         if (walk == str         /* first char */
108                         || *(walk - 1) != '\\') /* not escaped */
109                                 ret ++;
110                 }
111         }
112         return !(ret % 2);
113 }
114
115 MatcherList *matcher_parser_get_cond(const gchar *str)
116 {
117         void *bufstate;
118
119         if (!check_quote_symetry(str)) {
120                 cond = NULL;
121                 return cond;
122         }
123         
124         /* bad coding to enable the sub-grammar matching
125            in yacc */
126         matcher_parserlineno = 1;
127         matcher_parse_op = MATCHER_PARSE_CONDITION;
128         matcher_parserrestart(NULL);
129         matcher_parser_init();
130         bufstate = matcher_parser_scan_string(str);
131         matcher_parserparse();
132         matcher_parse_op = MATCHER_PARSE_FILE;
133         matcher_parser_delete_buffer(bufstate);
134         return cond;
135 }
136
137 GSList *matcher_parser_get_action_list(const gchar *str)
138 {
139         void *bufstate;
140
141         if (!check_quote_symetry(str)) {
142                 action_list = NULL;
143                 return action_list;
144         }
145         
146         /* bad coding to enable the sub-grammar matching
147            in yacc */
148         matcher_parserlineno = 1;
149         matcher_parse_op = MATCHER_PARSE_FILTERING_ACTION;
150         matcher_parserrestart(NULL);
151         matcher_parser_init();
152         bufstate = matcher_parser_scan_string(str);
153         matcher_parserparse();
154         matcher_parse_op = MATCHER_PARSE_FILE;
155         matcher_parser_delete_buffer(bufstate);
156         return action_list;
157 }
158
159 MatcherProp *matcher_parser_get_prop(const gchar *str)
160 {
161         MatcherList *list;
162         MatcherProp *prop;
163
164         matcher_parserlineno = 1;
165         list = matcher_parser_get_cond(str);
166         if (list == NULL)
167                 return NULL;
168
169         if (list->matchers == NULL)
170                 return NULL;
171
172         if (list->matchers->next != NULL)
173                 return NULL;
174
175         prop = list->matchers->data;
176
177         g_slist_free(list->matchers);
178         g_free(list);
179
180         return prop;
181 }
182
183 void matcher_parsererror(char *str)
184 {
185         GSList *l;
186
187         if (matchers_list) {
188                 for (l = matchers_list; l != NULL; l = g_slist_next(l)) {
189                         matcherprop_free((MatcherProp *)
190                                          l->data);
191                         l->data = NULL;
192                 }
193                 g_slist_free(matchers_list);
194                 matchers_list = NULL;
195         }
196         cond = NULL;
197         g_warning("filtering parsing: %i: %s\n",
198                   matcher_parserlineno, str);
199         error = 1;
200 }
201
202 int matcher_parserwrap(void)
203 {
204         return 1;
205 }
206 %}
207
208 %union {
209         char *str;
210         int value;
211 }
212
213 %token MATCHER_ALL MATCHER_UNREAD  MATCHER_NOT_UNREAD 
214 %token MATCHER_NEW  MATCHER_NOT_NEW  MATCHER_MARKED
215 %token MATCHER_NOT_MARKED  MATCHER_DELETED  MATCHER_NOT_DELETED
216 %token MATCHER_REPLIED  MATCHER_NOT_REPLIED  MATCHER_FORWARDED
217 %token MATCHER_NOT_FORWARDED  MATCHER_SUBJECT  MATCHER_NOT_SUBJECT
218 %token MATCHER_FROM  MATCHER_NOT_FROM  MATCHER_TO  MATCHER_NOT_TO
219 %token MATCHER_CC  MATCHER_NOT_CC  MATCHER_TO_OR_CC  MATCHER_NOT_TO_AND_NOT_CC
220 %token MATCHER_AGE_GREATER  MATCHER_AGE_LOWER  MATCHER_NEWSGROUPS
221 %token MATCHER_NOT_NEWSGROUPS  MATCHER_INREPLYTO  MATCHER_NOT_INREPLYTO
222 %token MATCHER_REFERENCES  MATCHER_NOT_REFERENCES  MATCHER_SCORE_GREATER
223 %token MATCHER_SCORE_LOWER  MATCHER_HEADER  MATCHER_NOT_HEADER
224 %token MATCHER_HEADERS_PART  MATCHER_NOT_HEADERS_PART  MATCHER_MESSAGE
225 %token MATCHER_NOT_MESSAGE  MATCHER_BODY_PART  MATCHER_NOT_BODY_PART
226 %token MATCHER_TEST  MATCHER_NOT_TEST  MATCHER_MATCHCASE  MATCHER_MATCH
227 %token MATCHER_REGEXPCASE  MATCHER_REGEXP  MATCHER_SCORE  MATCHER_MOVE
228 %token MATCHER_ANY_IN_ADDRESSBOOK MATCHER_ALL_IN_ADDRESSBOOK
229 %token MATCHER_COPY  MATCHER_DELETE  MATCHER_MARK  MATCHER_UNMARK
230 %token MATCHER_LOCK MATCHER_UNLOCK
231 %token MATCHER_EXECUTE
232 %token MATCHER_MARK_AS_READ  MATCHER_MARK_AS_UNREAD  MATCHER_FORWARD
233 %token MATCHER_FORWARD_AS_ATTACHMENT  MATCHER_EOL  MATCHER_STRING  
234 %token MATCHER_OR MATCHER_AND  
235 %token MATCHER_COLOR MATCHER_SCORE_EQUAL MATCHER_REDIRECT 
236 %token MATCHER_SIZE_GREATER MATCHER_SIZE_SMALLER MATCHER_SIZE_EQUAL
237 %token MATCHER_LOCKED MATCHER_NOT_LOCKED
238 %token MATCHER_PARTIAL MATCHER_NOT_PARTIAL
239 %token MATCHER_COLORLABEL MATCHER_NOT_COLORLABEL
240 %token MATCHER_IGNORE_THREAD MATCHER_NOT_IGNORE_THREAD
241 %token MATCHER_CHANGE_SCORE MATCHER_SET_SCORE
242 %token MATCHER_STOP MATCHER_HIDE
243
244 %start file
245
246 %token <str> MATCHER_STRING
247 %token <str> MATCHER_SECTION
248 %token <str> MATCHER_INTEGER
249
250 %%
251
252 file:
253 {
254         if (matcher_parse_op == MATCHER_PARSE_FILE) {
255                 prefs_filtering = &pre_global_processing;
256         }
257 }
258 file_line_list;
259
260 file_line_list:
261 file_line
262 file_line_list
263 | file_line
264 ;
265
266 file_line:
267 section_notification
268
269 { action_list = NULL; }
270 instruction
271 | error MATCHER_EOL
272 {
273         yyerrok;
274 };
275
276 section_notification:
277 MATCHER_SECTION MATCHER_EOL
278 {
279         gchar *folder = $1;
280         FolderItem *item = NULL;
281
282         if (matcher_parse_op == MATCHER_PARSE_FILE) {
283                 enable_compatibility = 0;
284                 if (!strcmp(folder, "global")) {
285                         /* backward compatibility */
286                         enable_compatibility = 1;
287                 }
288                 else if (!strcmp(folder, "preglobal")) {
289                         prefs_filtering = &pre_global_processing;
290                 }
291                 else if (!strcmp(folder, "postglobal")) {
292                         prefs_filtering = &post_global_processing;
293                 }
294                 else if (!strcmp(folder, "filtering")) {
295                         prefs_filtering = &filtering_rules;
296                 }
297                 else {
298                         item = folder_find_item_from_identifier(folder);
299                         if (item != NULL) {
300                                 prefs_filtering = &item->prefs->processing;
301                         } else {
302                                 prefs_filtering = NULL;
303                         }
304                 }
305         }
306 }
307 ;
308
309 instruction:
310 condition filtering MATCHER_EOL
311 | condition filtering
312 {
313         if (matcher_parse_op == MATCHER_PARSE_NO_EOL)
314                 YYACCEPT;
315         else {
316                 matcher_parsererror("parse error");
317                 YYERROR;
318         }
319 }
320 | condition
321 {
322         if (matcher_parse_op == MATCHER_PARSE_CONDITION)
323                 YYACCEPT;
324         else {
325                 matcher_parsererror("parse error");
326                 YYERROR;
327         }
328 }
329 | filtering_action_list
330 {
331         if (matcher_parse_op == MATCHER_PARSE_FILTERING_ACTION)
332                 YYACCEPT;
333         else {
334                 matcher_parsererror("parse error");
335                 YYERROR;
336         }
337 }
338 | MATCHER_EOL
339 ;
340
341 filtering:
342 filtering_action_list
343 {
344         filtering = filteringprop_new(cond, action_list);
345         
346         if (enable_compatibility) {
347                 prefs_filtering = &filtering_rules;
348                 if (action_list != NULL) {
349                         FilteringAction * first_action;
350                         
351                         first_action = action_list->data;
352                         
353                         if (first_action->type == MATCHACTION_CHANGE_SCORE)
354                                 prefs_filtering = &pre_global_processing;
355                 }
356         }
357         
358         cond = NULL;
359         action_list = NULL;
360         
361         if ((matcher_parse_op == MATCHER_PARSE_FILE) &&
362             (prefs_filtering != NULL)) {
363                 *prefs_filtering = g_slist_append(*prefs_filtering,
364                                                   filtering);
365                 filtering = NULL;
366         }
367 }
368 ;
369
370 filtering_action_list:
371 filtering_action_b filtering_action_list
372 | filtering_action_b
373 ;
374
375 filtering_action_b:
376 filtering_action
377 {
378         action_list = g_slist_append(action_list, action);
379         action = NULL;
380 }
381 ;
382
383 match_type:
384 MATCHER_MATCHCASE
385 {
386         match_type = MATCHTYPE_MATCHCASE;
387 }
388 | MATCHER_MATCH
389 {
390         match_type = MATCHTYPE_MATCH;
391 }
392 | MATCHER_REGEXPCASE
393 {
394         match_type = MATCHTYPE_REGEXPCASE;
395 }
396 | MATCHER_REGEXP
397 {
398         match_type = MATCHTYPE_REGEXP;
399 }
400 | MATCHER_ANY_IN_ADDRESSBOOK
401 {
402         match_type = MATCHTYPE_ANY_IN_ADDRESSBOOK;
403 }
404 | MATCHER_ALL_IN_ADDRESSBOOK
405 {
406         match_type = MATCHTYPE_ALL_IN_ADDRESSBOOK;
407 }
408 ;
409
410 condition:
411 condition_list
412 {
413         cond = matcherlist_new(matchers_list, (bool_op == MATCHERBOOL_AND));
414         matchers_list = NULL;
415 }
416 ;
417
418 condition_list:
419 condition_list bool_op one_condition
420 {
421         matchers_list = g_slist_append(matchers_list, prop);
422 }
423 | one_condition
424 {
425         matchers_list = NULL;
426         matchers_list = g_slist_append(matchers_list, prop);
427 }
428 ;
429
430 bool_op:
431 MATCHER_AND
432 {
433         bool_op = MATCHERBOOL_AND;
434 }
435 | MATCHER_OR
436 {
437         bool_op = MATCHERBOOL_OR;
438 }
439 ;
440
441 one_condition:
442 MATCHER_ALL
443 {
444         gint criteria = 0;
445
446         criteria = MATCHCRITERIA_ALL;
447         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
448 }
449 | MATCHER_UNREAD
450 {
451         gint criteria = 0;
452
453         criteria = MATCHCRITERIA_UNREAD;
454         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
455 }
456 | MATCHER_NOT_UNREAD 
457 {
458         gint criteria = 0;
459
460         criteria = MATCHCRITERIA_NOT_UNREAD;
461         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
462 }
463 | MATCHER_NEW
464 {
465         gint criteria = 0;
466
467         criteria = MATCHCRITERIA_NEW;
468         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
469 }
470 | MATCHER_NOT_NEW
471 {
472         gint criteria = 0;
473
474         criteria = MATCHCRITERIA_NOT_NEW;
475         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
476 }
477 | MATCHER_MARKED
478 {
479         gint criteria = 0;
480
481         criteria = MATCHCRITERIA_MARKED;
482         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
483 }
484 | MATCHER_NOT_MARKED
485 {
486         gint criteria = 0;
487
488         criteria = MATCHCRITERIA_NOT_MARKED;
489         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
490 }
491 | MATCHER_DELETED
492 {
493         gint criteria = 0;
494
495         criteria = MATCHCRITERIA_DELETED;
496         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
497 }
498 | MATCHER_NOT_DELETED
499 {
500         gint criteria = 0;
501
502         criteria = MATCHCRITERIA_NOT_DELETED;
503         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
504 }
505 | MATCHER_REPLIED
506 {
507         gint criteria = 0;
508
509         criteria = MATCHCRITERIA_REPLIED;
510         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
511 }
512 | MATCHER_NOT_REPLIED
513 {
514         gint criteria = 0;
515
516         criteria = MATCHCRITERIA_NOT_REPLIED;
517         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
518 }
519 | MATCHER_FORWARDED
520 {
521         gint criteria = 0;
522
523         criteria = MATCHCRITERIA_FORWARDED;
524         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
525 }
526 | MATCHER_NOT_FORWARDED
527 {
528         gint criteria = 0;
529
530         criteria = MATCHCRITERIA_NOT_FORWARDED;
531         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
532 }
533 | MATCHER_LOCKED
534 {
535         gint criteria = 0;
536
537         criteria = MATCHCRITERIA_LOCKED;
538         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
539 }
540 | MATCHER_NOT_LOCKED
541 {
542         gint criteria = 0;
543
544         criteria = MATCHCRITERIA_NOT_LOCKED;
545         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
546 }
547 | MATCHER_PARTIAL
548 {
549         gint criteria = 0;
550
551         criteria = MATCHCRITERIA_PARTIAL;
552         prop = matcherprop_new(criteria, NULL, MATCHTYPE_MATCH, "SC-Partially-Retrieved", 0);
553 }
554 | MATCHER_NOT_PARTIAL
555 {
556         gint criteria = 0;
557
558         criteria = MATCHCRITERIA_NOT_PARTIAL;
559         prop = matcherprop_new(criteria, NULL, MATCHTYPE_MATCH, "SC-Partially-Retrieved", 0);
560 }
561 | MATCHER_COLORLABEL MATCHER_INTEGER
562 {
563         gint criteria = 0;
564         gint value = 0;
565
566         criteria = MATCHCRITERIA_COLORLABEL;
567         value = strtol($2, NULL, 10);
568         if (value < 0) value = 0;
569         else if (value > MAX_COLORLABELS) value = MAX_COLORLABELS;
570         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
571 }
572 | MATCHER_NOT_COLORLABEL MATCHER_INTEGER
573 {
574         gint criteria = 0;
575         gint value = 0;
576
577         criteria = MATCHCRITERIA_NOT_COLORLABEL;
578         value = strtol($2, NULL, 0);
579         if (value < 0) value = 0;
580         else if (value > MAX_COLORLABELS) value = MAX_COLORLABELS;
581         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
582 }
583 | MATCHER_IGNORE_THREAD
584 {
585         gint criteria = 0;
586
587         criteria = MATCHCRITERIA_IGNORE_THREAD;
588         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
589 }
590 | MATCHER_NOT_IGNORE_THREAD
591 {
592         gint criteria = 0;
593
594         criteria = MATCHCRITERIA_NOT_IGNORE_THREAD;
595         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
596 }
597 | MATCHER_SUBJECT match_type MATCHER_STRING
598 {
599         gint criteria = 0;
600         gchar *expr = NULL;
601
602         criteria = MATCHCRITERIA_SUBJECT;
603         expr = $3;
604         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
605 }
606 | MATCHER_NOT_SUBJECT match_type MATCHER_STRING
607 {
608         gint criteria = 0;
609         gchar *expr = NULL;
610
611         criteria = MATCHCRITERIA_NOT_SUBJECT;
612         expr = $3;
613         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
614 }
615 | MATCHER_FROM match_type MATCHER_STRING
616 {
617         gint criteria = 0;
618         gchar *expr = NULL;
619
620         criteria = MATCHCRITERIA_FROM;
621         expr = $3;
622         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
623 }
624 | MATCHER_NOT_FROM match_type MATCHER_STRING
625 {
626         gint criteria = 0;
627         gchar *expr = NULL;
628
629         criteria = MATCHCRITERIA_NOT_FROM;
630         expr = $3;
631         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
632 }
633 | MATCHER_TO match_type MATCHER_STRING
634 {
635         gint criteria = 0;
636         gchar *expr = NULL;
637
638         criteria = MATCHCRITERIA_TO;
639         expr = $3;
640         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
641 }
642 | MATCHER_NOT_TO match_type MATCHER_STRING
643 {
644         gint criteria = 0;
645         gchar *expr = NULL;
646
647         criteria = MATCHCRITERIA_NOT_TO;
648         expr = $3;
649         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
650 }
651 | MATCHER_CC match_type MATCHER_STRING
652 {
653         gint criteria = 0;
654         gchar *expr = NULL;
655
656         criteria = MATCHCRITERIA_CC;
657         expr = $3;
658         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
659 }
660 | MATCHER_NOT_CC match_type MATCHER_STRING
661 {
662         gint criteria = 0;
663         gchar *expr = NULL;
664
665         criteria = MATCHCRITERIA_NOT_CC;
666         expr = $3;
667         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
668 }
669 | MATCHER_TO_OR_CC match_type MATCHER_STRING
670 {
671         gint criteria = 0;
672         gchar *expr = NULL;
673
674         criteria = MATCHCRITERIA_TO_OR_CC;
675         expr = $3;
676         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
677 }
678 | MATCHER_NOT_TO_AND_NOT_CC match_type MATCHER_STRING
679 {
680         gint criteria = 0;
681         gchar *expr = NULL;
682
683         criteria = MATCHCRITERIA_NOT_TO_AND_NOT_CC;
684         expr = $3;
685         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
686 }
687 | MATCHER_AGE_GREATER MATCHER_INTEGER
688 {
689         gint criteria = 0;
690         gint value = 0;
691
692         criteria = MATCHCRITERIA_AGE_GREATER;
693         value = strtol($2, NULL, 0);
694         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
695 }
696 | MATCHER_AGE_LOWER MATCHER_INTEGER
697 {
698         gint criteria = 0;
699         gint value = 0;
700
701         criteria = MATCHCRITERIA_AGE_LOWER;
702         value = strtol($2, NULL, 0);
703         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
704 }
705 | MATCHER_NEWSGROUPS match_type MATCHER_STRING
706 {
707         gint criteria = 0;
708         gchar *expr = NULL;
709
710         criteria = MATCHCRITERIA_NEWSGROUPS;
711         expr = $3;
712         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
713 }
714 | MATCHER_NOT_NEWSGROUPS match_type MATCHER_STRING
715 {
716         gint criteria = 0;
717         gchar *expr = NULL;
718
719         criteria = MATCHCRITERIA_NOT_NEWSGROUPS;
720         expr = $3;
721         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
722 }
723 | MATCHER_INREPLYTO match_type MATCHER_STRING
724 {
725         gint criteria = 0;
726         gchar *expr = NULL;
727
728         criteria = MATCHCRITERIA_INREPLYTO;
729         expr = $3;
730         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
731 }
732 | MATCHER_NOT_INREPLYTO match_type MATCHER_STRING
733 {
734         gint criteria = 0;
735         gchar *expr = NULL;
736
737         criteria = MATCHCRITERIA_NOT_INREPLYTO;
738         expr = $3;
739         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
740 }
741 | MATCHER_REFERENCES match_type MATCHER_STRING
742 {
743         gint criteria = 0;
744         gchar *expr = NULL;
745
746         criteria = MATCHCRITERIA_REFERENCES;
747         expr = $3;
748         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
749 }
750 | MATCHER_NOT_REFERENCES match_type MATCHER_STRING
751 {
752         gint criteria = 0;
753         gchar *expr = NULL;
754
755         criteria = MATCHCRITERIA_NOT_REFERENCES;
756         expr = $3;
757         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
758 }
759 | MATCHER_SCORE_GREATER MATCHER_INTEGER
760 {
761         gint criteria = 0;
762         gint value = 0;
763
764         criteria = MATCHCRITERIA_SCORE_GREATER;
765         value = strtol($2, NULL, 0);
766         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
767 }
768 | MATCHER_SCORE_LOWER MATCHER_INTEGER
769 {
770         gint criteria = 0;
771         gint value = 0;
772
773         criteria = MATCHCRITERIA_SCORE_LOWER;
774         value = strtol($2, NULL, 0);
775         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
776 }
777 | MATCHER_SCORE_EQUAL MATCHER_INTEGER
778 {
779         gint criteria = 0;
780         gint value = 0;
781
782         criteria = MATCHCRITERIA_SCORE_EQUAL;
783         value = strtol($2, NULL, 0);
784         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
785 }
786 | MATCHER_SIZE_GREATER MATCHER_INTEGER 
787 {
788         gint criteria = 0;
789         gint value    = 0;
790         criteria = MATCHCRITERIA_SIZE_GREATER;
791         value = strtol($2, NULL, 0);
792         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
793 }
794 | MATCHER_SIZE_SMALLER MATCHER_INTEGER
795 {
796         gint criteria = 0;
797         gint value    = 0;
798         criteria = MATCHCRITERIA_SIZE_SMALLER;
799         value = strtol($2, NULL, 0);
800         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
801 }
802 | MATCHER_SIZE_EQUAL MATCHER_INTEGER
803 {
804         gint criteria = 0;
805         gint value    = 0;
806         criteria = MATCHCRITERIA_SIZE_EQUAL;
807         value = strtol($2, NULL, 0);
808         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
809 }
810 | MATCHER_HEADER MATCHER_STRING
811 {
812         header = g_strdup($2);
813 } match_type MATCHER_STRING
814 {
815         gint criteria = 0;
816         gchar *expr = NULL;
817
818         criteria = MATCHCRITERIA_HEADER;
819         expr = $2;
820         prop = matcherprop_new(criteria, header, match_type, expr, 0);
821         g_free(header);
822 }
823 | MATCHER_NOT_HEADER MATCHER_STRING
824 {
825         header = g_strdup($2);
826 } match_type MATCHER_STRING
827 {
828         gint criteria = 0;
829         gchar *expr = NULL;
830
831         criteria = MATCHCRITERIA_NOT_HEADER;
832         expr = $2;
833         prop = matcherprop_new(criteria, header, match_type, expr, 0);
834         g_free(header);
835 }
836 | MATCHER_HEADERS_PART match_type MATCHER_STRING
837 {
838         gint criteria = 0;
839         gchar *expr = NULL;
840
841         criteria = MATCHCRITERIA_HEADERS_PART;
842         expr = $3;
843         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
844 }
845 | MATCHER_NOT_HEADERS_PART match_type MATCHER_STRING
846 {
847         gint criteria = 0;
848         gchar *expr = NULL;
849
850         criteria = MATCHCRITERIA_NOT_HEADERS_PART;
851         expr = $3;
852         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
853 }
854 | MATCHER_MESSAGE match_type MATCHER_STRING
855 {
856         gint criteria = 0;
857         gchar *expr = NULL;
858
859         criteria = MATCHCRITERIA_MESSAGE;
860         expr = $3;
861         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
862 }
863 | MATCHER_NOT_MESSAGE match_type MATCHER_STRING
864 {
865         gint criteria = 0;
866         gchar *expr = NULL;
867
868         criteria = MATCHCRITERIA_NOT_MESSAGE;
869         expr = $3;
870         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
871 }
872 | MATCHER_BODY_PART match_type MATCHER_STRING
873 {
874         gint criteria = 0;
875         gchar *expr = NULL;
876
877         criteria = MATCHCRITERIA_BODY_PART;
878         expr = $3;
879         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
880 }
881 | MATCHER_NOT_BODY_PART match_type MATCHER_STRING
882 {
883         gint criteria = 0;
884         gchar *expr = NULL;
885
886         criteria = MATCHCRITERIA_NOT_BODY_PART;
887         expr = $3;
888         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
889 }
890 | MATCHER_TEST MATCHER_STRING
891 {
892         gint criteria = 0;
893         gchar *expr = NULL;
894
895         criteria = MATCHCRITERIA_TEST;
896         expr = $2;
897         prop = matcherprop_new(criteria, NULL, 0, expr, 0);
898 }
899 | MATCHER_NOT_TEST MATCHER_STRING
900 {
901         gint criteria = 0;
902         gchar *expr = NULL;
903
904         criteria = MATCHCRITERIA_NOT_TEST;
905         expr = $2;
906         prop = matcherprop_new(criteria, NULL, 0, expr, 0);
907 }
908 ;
909
910 filtering_action:
911 MATCHER_EXECUTE MATCHER_STRING
912 {
913         gchar *cmd = NULL;
914         gint action_type = 0;
915
916         action_type = MATCHACTION_EXECUTE;
917         cmd = $2;
918         action = filteringaction_new(action_type, 0, cmd, 0, 0);
919 }
920 | MATCHER_MOVE MATCHER_STRING
921 {
922         gchar *destination = NULL;
923         gint action_type = 0;
924
925         action_type = MATCHACTION_MOVE;
926         destination = $2;
927         action = filteringaction_new(action_type, 0, destination, 0, 0);
928 }
929 | MATCHER_COPY MATCHER_STRING
930 {
931         gchar *destination = NULL;
932         gint action_type = 0;
933
934         action_type = MATCHACTION_COPY;
935         destination = $2;
936         action = filteringaction_new(action_type, 0, destination, 0, 0);
937 }
938 | MATCHER_DELETE
939 {
940         gint action_type = 0;
941
942         action_type = MATCHACTION_DELETE;
943         action = filteringaction_new(action_type, 0, NULL, 0, 0);
944 }
945 | MATCHER_MARK
946 {
947         gint action_type = 0;
948
949         action_type = MATCHACTION_MARK;
950         action = filteringaction_new(action_type, 0, NULL, 0, 0);
951 }
952 | MATCHER_UNMARK
953 {
954         gint action_type = 0;
955
956         action_type = MATCHACTION_UNMARK;
957         action = filteringaction_new(action_type, 0, NULL, 0, 0);
958 }
959 | MATCHER_LOCK
960 {
961         gint action_type = 0;
962
963         action_type = MATCHACTION_LOCK;
964         action = filteringaction_new(action_type, 0, NULL, 0, 0);
965 }
966 | MATCHER_UNLOCK
967 {
968         gint action_type = 0;
969
970         action_type = MATCHACTION_UNLOCK;
971         action = filteringaction_new(action_type, 0, NULL, 0, 0);
972 }
973 | MATCHER_MARK_AS_READ
974 {
975         gint action_type = 0;
976
977         action_type = MATCHACTION_MARK_AS_READ;
978         action = filteringaction_new(action_type, 0, NULL, 0, 0);
979 }
980 | MATCHER_MARK_AS_UNREAD
981 {
982         gint action_type = 0;
983
984         action_type = MATCHACTION_MARK_AS_UNREAD;
985         action = filteringaction_new(action_type, 0, NULL, 0, 0);
986 }
987 | MATCHER_FORWARD MATCHER_INTEGER MATCHER_STRING
988 {
989         gchar *destination = NULL;
990         gint action_type = 0;
991         gint account_id = 0;
992
993         action_type = MATCHACTION_FORWARD;
994         account_id = strtol($2, NULL, 10);
995         destination = $3;
996         action = filteringaction_new(action_type,
997             account_id, destination, 0, 0);
998 }
999 | MATCHER_FORWARD_AS_ATTACHMENT MATCHER_INTEGER MATCHER_STRING
1000 {
1001         gchar *destination = NULL;
1002         gint action_type = 0;
1003         gint account_id = 0;
1004
1005         action_type = MATCHACTION_FORWARD_AS_ATTACHMENT;
1006         account_id = strtol($2, NULL, 10);
1007         destination = $3;
1008         action = filteringaction_new(action_type,
1009             account_id, destination, 0, 0);
1010 }
1011 | MATCHER_REDIRECT MATCHER_INTEGER MATCHER_STRING
1012 {
1013         gchar *destination = NULL;
1014         gint action_type = 0;
1015         gint account_id = 0;
1016
1017         action_type = MATCHACTION_REDIRECT;
1018         account_id = strtol($2, NULL, 10);
1019         destination = $3;
1020         action = filteringaction_new(action_type,
1021             account_id, destination, 0, 0);
1022 }
1023 | MATCHER_COLOR MATCHER_INTEGER
1024 {
1025         gint action_type = 0;
1026         gint color = 0;
1027
1028         action_type = MATCHACTION_COLOR;
1029         color = strtol($2, NULL, 10);
1030         action = filteringaction_new(action_type, 0, NULL, color, 0);
1031 }
1032 | MATCHER_CHANGE_SCORE MATCHER_INTEGER
1033 {
1034         gint score = 0;
1035         
1036         score = strtol($2, NULL, 10);
1037         action = filteringaction_new(MATCHACTION_CHANGE_SCORE, 0,
1038                                      NULL, 0, score);
1039 }
1040 /* backward compatibility */
1041 | MATCHER_SCORE MATCHER_INTEGER
1042 {
1043         gint score = 0;
1044         
1045         score = strtol($2, NULL, 10);
1046         action = filteringaction_new(MATCHACTION_CHANGE_SCORE, 0,
1047                                      NULL, 0, score);
1048 }
1049 | MATCHER_SET_SCORE MATCHER_INTEGER
1050 {
1051         gint score = 0;
1052         
1053         score = strtol($2, NULL, 10);
1054         action = filteringaction_new(MATCHACTION_SET_SCORE, 0,
1055                                      NULL, 0, score);
1056 }
1057 | MATCHER_HIDE
1058 {
1059         action = filteringaction_new(MATCHACTION_HIDE, 0, NULL, 0, 0);
1060 }
1061 | MATCHER_STOP
1062 {
1063         action = filteringaction_new(MATCHACTION_STOP, 0, NULL, 0, 0);
1064 }
1065 ;