2012-10-03 [mones] 3.8.1cvs82
[claws.git] / src / matcher_parser_parse.y
1 %{
2 /*
3  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
4  * Copyright (c) 2001-2007 by Hiroyuki Yamamoto & The Claws Mail Team
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  * 
19  */
20
21 #include "defs.h"
22
23 #include <glib.h>
24 #include <glib/gi18n.h>
25
26 #include "utils.h"
27 #include "filtering.h"
28 #include "matcher.h"
29 #include "matcher_parser.h"
30 #include "matcher_parser_lex.h"
31 #include "colorlabel.h"
32 #include "folder_item_prefs.h"
33
34 static gint error = 0;
35 static gint bool_op = 0;
36 static gint match_type = 0;
37 static gchar *header = NULL;
38
39 static MatcherProp *prop;
40
41 static GSList *matchers_list = NULL;
42
43 static gboolean enabled = TRUE;
44 static gchar *name = NULL;
45 static gint account_id = 0;
46 static MatcherList *cond;
47 static GSList *action_list = NULL;
48 static FilteringAction *action = NULL;
49 static gboolean matcher_is_fast = TRUE;
50 static gboolean disable_warnings = FALSE;
51
52 static FilteringProp *filtering;
53
54 static GSList **prefs_filtering = NULL;
55 static int enable_compatibility = 0;
56
57 enum {
58         MATCHER_PARSE_FILE,
59         MATCHER_PARSE_NO_EOL,
60         MATCHER_PARSE_ENABLED,
61         MATCHER_PARSE_NAME,
62         MATCHER_PARSE_ACCOUNT,
63         MATCHER_PARSE_CONDITION,
64         MATCHER_PARSE_FILTERING_ACTION,
65 };
66
67 static int matcher_parse_op = MATCHER_PARSE_FILE;
68
69
70 /* ******************************************************************** */
71 /* redeclarations to avoid warnings */
72 void matcher_parserrestart(FILE *input_file);
73 void matcher_parser_init(void);
74 void matcher_parser_switch_to_buffer(void * new_buffer);
75 void matcher_parser_delete_buffer(void * b);
76 void matcher_parserpop_buffer_state(void);
77 int matcher_parserlex(void);
78
79 void matcher_parser_disable_warnings(const gboolean disable)
80 {
81         disable_warnings = disable;
82 }
83
84 void matcher_parser_start_parsing(FILE *f)
85 {
86         matcher_parserlineno = 1;
87         matcher_parserrestart(f);
88         account_id = 0;
89         matcher_parserparse();
90 }
91
92  
93 void * matcher_parser_scan_string(const char * str);
94  
95 FilteringProp *matcher_parser_get_filtering(gchar *str)
96 {
97         void *bufstate;
98         void *tmp_str = NULL;
99         
100         /* little hack to allow passing rules with no names */
101         if (!strncmp(str, "rulename ", 9))
102                 tmp_str = g_strdup(str);
103         else 
104                 tmp_str = g_strconcat("rulename \"\" ", str, NULL);
105
106         /* bad coding to enable the sub-grammar matching
107            in yacc */
108         matcher_parserlineno = 1;
109         matcher_parse_op = MATCHER_PARSE_NO_EOL;
110         matcher_parserrestart(NULL);
111         matcher_parserpop_buffer_state();
112         matcher_parser_init();
113         bufstate = matcher_parser_scan_string((const char *) tmp_str);
114         matcher_parser_switch_to_buffer(bufstate);
115         if (matcher_parserparse() != 0)
116                 filtering = NULL;
117         matcher_parse_op = MATCHER_PARSE_FILE;
118         matcher_parser_delete_buffer(bufstate);
119         g_free(tmp_str);
120         return filtering;
121 }
122
123 static gboolean check_quote_symetry(gchar *str)
124 {
125         const gchar *walk;
126         int ret = 0;
127         
128         if (str == NULL)
129                 return TRUE; /* heh, that's symetric */
130         if (*str == '\0')
131                 return TRUE;
132         for (walk = str; *walk; walk++) {
133                 if (*walk == '\"') {
134                         if (walk == str         /* first char */
135                         || *(walk - 1) != '\\') /* not escaped */
136                                 ret ++;
137                 }
138         }
139         return !(ret % 2);
140 }
141
142 MatcherList *matcher_parser_get_name(gchar *str)
143 {
144         void *bufstate;
145
146         if (!check_quote_symetry(str)) {
147                 cond = NULL;
148                 return cond;
149         }
150         
151         /* bad coding to enable the sub-grammar matching
152            in yacc */
153         matcher_parserlineno = 1;
154         matcher_parse_op = MATCHER_PARSE_NAME;
155         matcher_parserrestart(NULL);
156         matcher_parserpop_buffer_state();
157         matcher_parser_init();
158         bufstate = matcher_parser_scan_string(str);
159         matcher_parserparse();
160         matcher_parse_op = MATCHER_PARSE_FILE;
161         matcher_parser_delete_buffer(bufstate);
162         return cond;
163 }
164
165 MatcherList *matcher_parser_get_enabled(gchar *str)
166 {
167         void *bufstate;
168
169         if (!check_quote_symetry(str)) {
170                 cond = NULL;
171                 return cond;
172         }
173         
174         /* bad coding to enable the sub-grammar matching
175            in yacc */
176         matcher_parserlineno = 1;
177         matcher_parse_op = MATCHER_PARSE_ENABLED;
178         matcher_parserrestart(NULL);
179         matcher_parserpop_buffer_state();
180         matcher_parser_init();
181         bufstate = matcher_parser_scan_string(str);
182         matcher_parserparse();
183         matcher_parse_op = MATCHER_PARSE_FILE;
184         matcher_parser_delete_buffer(bufstate);
185         return cond;
186 }
187
188 MatcherList *matcher_parser_get_account(gchar *str)
189 {
190         void *bufstate;
191
192         if (!check_quote_symetry(str)) {
193                 cond = NULL;
194                 return cond;
195         }
196         
197         /* bad coding to enable the sub-grammar matching
198            in yacc */
199         matcher_parserlineno = 1;
200         matcher_parse_op = MATCHER_PARSE_ACCOUNT;
201         matcher_parserrestart(NULL);
202         matcher_parserpop_buffer_state();
203         matcher_parser_init();
204         bufstate = matcher_parser_scan_string(str);
205         matcher_parserparse();
206         matcher_parse_op = MATCHER_PARSE_FILE;
207         matcher_parser_delete_buffer(bufstate);
208         return cond;
209 }
210
211 MatcherList *matcher_parser_get_cond(gchar *str, gboolean *is_fast)
212 {
213         void *bufstate;
214
215         if (!check_quote_symetry(str)) {
216                 cond = NULL;
217                 return cond;
218         }
219         
220         matcher_is_fast = TRUE;
221         /* bad coding to enable the sub-grammar matching
222            in yacc */
223         matcher_parserlineno = 1;
224         matcher_parse_op = MATCHER_PARSE_CONDITION;
225         matcher_parserrestart(NULL);
226         matcher_parserpop_buffer_state();
227         matcher_parser_init();
228         bufstate = matcher_parser_scan_string(str);
229         matcher_parserparse();
230         matcher_parse_op = MATCHER_PARSE_FILE;
231         matcher_parser_delete_buffer(bufstate);
232         if (is_fast)
233                 *is_fast = matcher_is_fast;
234         return cond;
235 }
236
237 GSList *matcher_parser_get_action_list(gchar *str)
238 {
239         void *bufstate;
240
241         if (!check_quote_symetry(str)) {
242                 action_list = NULL;
243                 return action_list;
244         }
245         
246         /* bad coding to enable the sub-grammar matching
247            in yacc */
248         matcher_parserlineno = 1;
249         matcher_parse_op = MATCHER_PARSE_FILTERING_ACTION;
250         matcher_parserrestart(NULL);
251         matcher_parserpop_buffer_state();
252         matcher_parser_init();
253         bufstate = matcher_parser_scan_string(str);
254         matcher_parserparse();
255         matcher_parse_op = MATCHER_PARSE_FILE;
256         matcher_parser_delete_buffer(bufstate);
257         return action_list;
258 }
259
260 MatcherProp *matcher_parser_get_prop(gchar *str)
261 {
262         MatcherList *list;
263         MatcherProp *prop;
264
265         matcher_parserlineno = 1;
266         list = matcher_parser_get_cond(str, NULL);
267         if (list == NULL)
268                 return NULL;
269
270         if (list->matchers == NULL)
271                 return NULL;
272
273         if (list->matchers->next != NULL)
274                 return NULL;
275
276         prop = list->matchers->data;
277
278         g_slist_free(list->matchers);
279         g_free(list);
280
281         return prop;
282 }
283
284 void matcher_parsererror(char *str)
285 {
286         GSList *l;
287
288         if (matchers_list) {
289                 for (l = matchers_list; l != NULL; l = g_slist_next(l)) {
290                         matcherprop_free((MatcherProp *)
291                                          l->data);
292                         l->data = NULL;
293                 }
294                 g_slist_free(matchers_list);
295                 matchers_list = NULL;
296         }
297         cond = NULL;
298         if (!disable_warnings)
299                 g_warning("filtering parsing: %i: %s\n",
300                         matcher_parserlineno, str);
301         error = 1;
302 }
303
304 int matcher_parserwrap(void)
305 {
306         return 1;
307 }
308 %}
309
310 %union {
311         char *str;
312         int value;
313 }
314 %token MATCHER_ALL MATCHER_UNREAD  MATCHER_NOT_UNREAD 
315 %token MATCHER_NEW  MATCHER_NOT_NEW  MATCHER_MARKED
316 %token MATCHER_NOT_MARKED  MATCHER_DELETED  MATCHER_NOT_DELETED
317 %token MATCHER_REPLIED  MATCHER_NOT_REPLIED  MATCHER_FORWARDED
318 %token MATCHER_NOT_FORWARDED  MATCHER_SUBJECT  MATCHER_NOT_SUBJECT
319 %token MATCHER_FROM  MATCHER_NOT_FROM  MATCHER_TO  MATCHER_NOT_TO
320 %token MATCHER_CC  MATCHER_NOT_CC  MATCHER_TO_OR_CC  MATCHER_NOT_TO_AND_NOT_CC
321 %token MATCHER_AGE_GREATER  MATCHER_AGE_LOWER  MATCHER_NEWSGROUPS
322 %token MATCHER_NOT_NEWSGROUPS  MATCHER_INREPLYTO  MATCHER_NOT_INREPLYTO
323 %token MATCHER_REFERENCES  MATCHER_NOT_REFERENCES  MATCHER_SCORE_GREATER
324 %token MATCHER_SCORE_LOWER  MATCHER_HEADER  MATCHER_NOT_HEADER
325 %token MATCHER_HEADERS_PART  MATCHER_NOT_HEADERS_PART  MATCHER_MESSAGE
326 %token MATCHER_NOT_MESSAGE  MATCHER_BODY_PART  MATCHER_NOT_BODY_PART
327 %token MATCHER_TEST  MATCHER_NOT_TEST  MATCHER_MATCHCASE  MATCHER_MATCH
328 %token MATCHER_REGEXPCASE  MATCHER_REGEXP  MATCHER_SCORE  MATCHER_MOVE
329 %token MATCHER_FOUND_IN_ADDRESSBOOK MATCHER_NOT_FOUND_IN_ADDRESSBOOK MATCHER_IN
330 %token MATCHER_COPY  MATCHER_DELETE  MATCHER_MARK  MATCHER_UNMARK
331 %token MATCHER_LOCK MATCHER_UNLOCK
332 %token MATCHER_EXECUTE
333 %token MATCHER_MARK_AS_READ  MATCHER_MARK_AS_UNREAD  MATCHER_FORWARD
334 %token MATCHER_MARK_AS_SPAM MATCHER_MARK_AS_HAM
335 %token MATCHER_FORWARD_AS_ATTACHMENT  MATCHER_EOL
336 %token MATCHER_OR MATCHER_AND  
337 %token MATCHER_COLOR MATCHER_SCORE_EQUAL MATCHER_REDIRECT 
338 %token MATCHER_SIZE_GREATER MATCHER_SIZE_SMALLER MATCHER_SIZE_EQUAL
339 %token MATCHER_LOCKED MATCHER_NOT_LOCKED
340 %token MATCHER_PARTIAL MATCHER_NOT_PARTIAL
341 %token MATCHER_COLORLABEL MATCHER_NOT_COLORLABEL
342 %token MATCHER_IGNORE_THREAD MATCHER_NOT_IGNORE_THREAD
343 %token MATCHER_WATCH_THREAD MATCHER_NOT_WATCH_THREAD
344 %token MATCHER_CHANGE_SCORE MATCHER_SET_SCORE
345 %token MATCHER_ADD_TO_ADDRESSBOOK
346 %token MATCHER_STOP MATCHER_HIDE MATCHER_IGNORE MATCHER_WATCH
347 %token MATCHER_SPAM MATCHER_NOT_SPAM
348 %token MATCHER_HAS_ATTACHMENT MATCHER_HAS_NO_ATTACHMENT
349 %token MATCHER_SIGNED MATCHER_NOT_SIGNED
350 %token MATCHER_TAG MATCHER_NOT_TAG MATCHER_SET_TAG MATCHER_UNSET_TAG
351 %token MATCHER_TAGGED MATCHER_NOT_TAGGED MATCHER_CLEAR_TAGS
352
353 %start file
354
355 %token MATCHER_ENABLED MATCHER_DISABLED
356 %token MATCHER_RULENAME
357 %token MATCHER_ACCOUNT
358 %token <str> MATCHER_STRING
359 %token <str> MATCHER_SECTION
360 %token <str> MATCHER_INTEGER
361
362 %%
363
364 file:
365 {
366         if (matcher_parse_op == MATCHER_PARSE_FILE) {
367                 prefs_filtering = &pre_global_processing;
368         }
369 }
370 file_line_list;
371
372 file_line_list:
373 file_line
374 file_line_list
375 | file_line
376 ;
377
378 file_line:
379 section_notification
380
381 { action_list = NULL; }
382 instruction
383 | error MATCHER_EOL
384 {
385         yyerrok;
386 };
387
388 section_notification:
389 MATCHER_SECTION MATCHER_EOL
390 {
391         gchar *folder = $1;
392         FolderItem *item = NULL;
393
394         if (matcher_parse_op == MATCHER_PARSE_FILE) {
395                 enable_compatibility = 0;
396                 if (!strcmp(folder, "global")) {
397                         /* backward compatibility */
398                         enable_compatibility = 1;
399                 }
400                 else if (!strcmp(folder, "preglobal")) {
401                         prefs_filtering = &pre_global_processing;
402                 }
403                 else if (!strcmp(folder, "postglobal")) {
404                         prefs_filtering = &post_global_processing;
405                 }
406                 else if (!strcmp(folder, "filtering")) {
407                         prefs_filtering = &filtering_rules;
408                 }
409                 else {
410                         item = folder_find_item_from_identifier(folder);
411                         if (item != NULL) {
412                                 prefs_filtering = &item->prefs->processing;
413                         } else {
414                                 prefs_filtering = NULL;
415                         }
416                 }
417         }
418 }
419 ;
420
421 instruction:
422 enabled name account condition filtering MATCHER_EOL
423 | enabled name account condition filtering
424 | enabled name condition filtering MATCHER_EOL
425 | enabled name condition filtering
426 | name condition filtering MATCHER_EOL
427 | name condition filtering
428 {
429         if (matcher_parse_op == MATCHER_PARSE_NO_EOL)
430                 YYACCEPT;
431         else {
432                 matcher_parsererror("parse error [no eol]");
433                 YYERROR;
434         }
435 }
436 | enabled
437 {
438         if (matcher_parse_op == MATCHER_PARSE_ENABLED)
439                 YYACCEPT;
440         else {
441                 matcher_parsererror("parse error [enabled]");
442                 YYERROR;
443         }
444 }
445 | account
446 {
447         if (matcher_parse_op == MATCHER_PARSE_ACCOUNT)
448                 YYACCEPT;
449         else {
450                 matcher_parsererror("parse error [account]");
451                 YYERROR;
452         }
453 }
454 | name
455 {
456         if (matcher_parse_op == MATCHER_PARSE_NAME)
457                 YYACCEPT;
458         else {
459                 matcher_parsererror("parse error [name]");
460                 YYERROR;
461         }
462 }
463 | condition
464 {
465         if (matcher_parse_op == MATCHER_PARSE_CONDITION)
466                 YYACCEPT;
467         else {
468                 matcher_parsererror("parse error [condition]");
469                 YYERROR;
470         }
471 }
472 | filtering_action_list
473 {
474         if (matcher_parse_op == MATCHER_PARSE_FILTERING_ACTION)
475                 YYACCEPT;
476         else {
477                 matcher_parsererror("parse error [filtering action]");
478                 YYERROR;
479         }
480 }
481 | MATCHER_EOL
482 ;
483
484 enabled:
485 MATCHER_ENABLED
486 {
487         enabled = TRUE;
488 }
489 | MATCHER_DISABLED
490 {
491         enabled = FALSE;
492 }
493 ;
494
495 name:
496 MATCHER_RULENAME MATCHER_STRING
497 {
498         name = g_strdup($2);
499 }
500 ;
501
502 account:
503 MATCHER_ACCOUNT MATCHER_INTEGER
504 {
505         account_id = strtol($2, NULL, 10);
506 }
507 ;
508
509 filtering:
510 filtering_action_list
511 {
512         filtering = filteringprop_new(enabled, name, account_id, cond, action_list);
513         enabled = TRUE;
514         account_id = 0;
515         g_free(name);
516         name = NULL;
517         if (enable_compatibility) {
518                 prefs_filtering = &filtering_rules;
519                 if (action_list != NULL) {
520                         FilteringAction * first_action;
521                         
522                         first_action = action_list->data;
523                         
524                         if (first_action->type == MATCHACTION_CHANGE_SCORE)
525                                 prefs_filtering = &pre_global_processing;
526                 }
527         }
528         
529         cond = NULL;
530         action_list = NULL;
531         
532         if ((matcher_parse_op == MATCHER_PARSE_FILE) &&
533             (prefs_filtering != NULL)) {
534                 *prefs_filtering = g_slist_append(*prefs_filtering,
535                                                   filtering);
536                 filtering = NULL;
537         }
538 }
539 ;
540
541 filtering_action_list:
542 filtering_action_b filtering_action_list
543 | filtering_action_b
544 ;
545
546 filtering_action_b:
547 filtering_action
548 {
549         action_list = g_slist_append(action_list, action);
550         action = NULL;
551 }
552 ;
553
554 match_type:
555 MATCHER_MATCHCASE
556 {
557         match_type = MATCHTYPE_MATCHCASE;
558 }
559 | MATCHER_MATCH
560 {
561         match_type = MATCHTYPE_MATCH;
562 }
563 | MATCHER_REGEXPCASE
564 {
565         match_type = MATCHTYPE_REGEXPCASE;
566 }
567 | MATCHER_REGEXP
568 {
569         match_type = MATCHTYPE_REGEXP;
570 }
571 ;
572
573 condition:
574 condition_list
575 {
576         cond = matcherlist_new(matchers_list, (bool_op == MATCHERBOOL_AND));
577         matchers_list = NULL;
578 }
579 ;
580
581 condition_list:
582 condition_list bool_op one_condition
583 {
584         matchers_list = g_slist_append(matchers_list, prop);
585 }
586 | one_condition
587 {
588         matchers_list = NULL;
589         matchers_list = g_slist_append(matchers_list, prop);
590 }
591 ;
592
593 bool_op:
594 MATCHER_AND
595 {
596         bool_op = MATCHERBOOL_AND;
597 }
598 | MATCHER_OR
599 {
600         bool_op = MATCHERBOOL_OR;
601 }
602 ;
603
604 one_condition:
605 MATCHER_ALL
606 {
607         gint criteria = 0;
608
609         criteria = MATCHCRITERIA_ALL;
610         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
611 }
612 | MATCHER_UNREAD
613 {
614         gint criteria = 0;
615
616         criteria = MATCHCRITERIA_UNREAD;
617         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
618 }
619 | MATCHER_NOT_UNREAD 
620 {
621         gint criteria = 0;
622
623         criteria = MATCHCRITERIA_NOT_UNREAD;
624         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
625 }
626 | MATCHER_NEW
627 {
628         gint criteria = 0;
629
630         criteria = MATCHCRITERIA_NEW;
631         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
632 }
633 | MATCHER_NOT_NEW
634 {
635         gint criteria = 0;
636
637         criteria = MATCHCRITERIA_NOT_NEW;
638         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
639 }
640 | MATCHER_MARKED
641 {
642         gint criteria = 0;
643
644         criteria = MATCHCRITERIA_MARKED;
645         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
646 }
647 | MATCHER_NOT_MARKED
648 {
649         gint criteria = 0;
650
651         criteria = MATCHCRITERIA_NOT_MARKED;
652         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
653 }
654 | MATCHER_DELETED
655 {
656         gint criteria = 0;
657
658         criteria = MATCHCRITERIA_DELETED;
659         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
660 }
661 | MATCHER_NOT_DELETED
662 {
663         gint criteria = 0;
664
665         criteria = MATCHCRITERIA_NOT_DELETED;
666         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
667 }
668 | MATCHER_REPLIED
669 {
670         gint criteria = 0;
671
672         criteria = MATCHCRITERIA_REPLIED;
673         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
674 }
675 | MATCHER_NOT_REPLIED
676 {
677         gint criteria = 0;
678
679         criteria = MATCHCRITERIA_NOT_REPLIED;
680         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
681 }
682 | MATCHER_FORWARDED
683 {
684         gint criteria = 0;
685
686         criteria = MATCHCRITERIA_FORWARDED;
687         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
688 }
689 | MATCHER_NOT_FORWARDED
690 {
691         gint criteria = 0;
692
693         criteria = MATCHCRITERIA_NOT_FORWARDED;
694         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
695 }
696 | MATCHER_LOCKED
697 {
698         gint criteria = 0;
699
700         criteria = MATCHCRITERIA_LOCKED;
701         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
702 }
703 | MATCHER_NOT_LOCKED
704 {
705         gint criteria = 0;
706
707         criteria = MATCHCRITERIA_NOT_LOCKED;
708         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
709 }
710 | MATCHER_SPAM
711 {
712         gint criteria = 0;
713
714         criteria = MATCHCRITERIA_SPAM;
715         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
716 }
717 | MATCHER_NOT_SPAM 
718 {
719         gint criteria = 0;
720
721         criteria = MATCHCRITERIA_NOT_SPAM;
722         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
723 }
724 | MATCHER_HAS_ATTACHMENT
725 {
726         gint criteria = 0;
727
728         criteria = MATCHCRITERIA_HAS_ATTACHMENT;
729         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
730 }
731 | MATCHER_HAS_NO_ATTACHMENT
732 {
733         gint criteria = 0;
734
735         criteria = MATCHCRITERIA_HAS_NO_ATTACHMENT;
736         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
737 }
738 | MATCHER_SIGNED
739 {
740         gint criteria = 0;
741
742         criteria = MATCHCRITERIA_SIGNED;
743         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
744 }
745 | MATCHER_NOT_SIGNED
746 {
747         gint criteria = 0;
748
749         criteria = MATCHCRITERIA_NOT_SIGNED;
750         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
751 }
752 | MATCHER_PARTIAL
753 {
754         gint criteria = 0;
755
756         criteria = MATCHCRITERIA_PARTIAL;
757         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
758 }
759 | MATCHER_NOT_PARTIAL
760 {
761         gint criteria = 0;
762
763         criteria = MATCHCRITERIA_NOT_PARTIAL;
764         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
765 }
766 | MATCHER_COLORLABEL MATCHER_INTEGER
767 {
768         gint criteria = 0;
769         gint value = 0;
770
771         criteria = MATCHCRITERIA_COLORLABEL;
772         value = strtol($2, NULL, 10);
773         if (value < 0) value = 0;
774         else if (value > COLORLABELS) value = COLORLABELS;
775         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
776 }
777 | MATCHER_NOT_COLORLABEL MATCHER_INTEGER
778 {
779         gint criteria = 0;
780         gint value = 0;
781
782         criteria = MATCHCRITERIA_NOT_COLORLABEL;
783         value = strtol($2, NULL, 0);
784         if (value < 0) value = 0;
785         else if (value > COLORLABELS) value = COLORLABELS;
786         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
787 }
788 | MATCHER_IGNORE_THREAD
789 {
790         gint criteria = 0;
791
792         criteria = MATCHCRITERIA_IGNORE_THREAD;
793         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
794 }
795 | MATCHER_NOT_IGNORE_THREAD
796 {
797         gint criteria = 0;
798
799         criteria = MATCHCRITERIA_NOT_IGNORE_THREAD;
800         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
801 }
802 | MATCHER_WATCH_THREAD
803 {
804         gint criteria = 0;
805
806         criteria = MATCHCRITERIA_WATCH_THREAD;
807         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
808 }
809 | MATCHER_NOT_WATCH_THREAD
810 {
811         gint criteria = 0;
812
813         criteria = MATCHCRITERIA_NOT_WATCH_THREAD;
814         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
815 }
816 | MATCHER_SUBJECT match_type MATCHER_STRING
817 {
818         gint criteria = 0;
819         gchar *expr = NULL;
820
821         criteria = MATCHCRITERIA_SUBJECT;
822         expr = $3;
823         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
824 }
825 | MATCHER_NOT_SUBJECT match_type MATCHER_STRING
826 {
827         gint criteria = 0;
828         gchar *expr = NULL;
829
830         criteria = MATCHCRITERIA_NOT_SUBJECT;
831         expr = $3;
832         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
833 }
834 | MATCHER_FROM match_type MATCHER_STRING
835 {
836         gint criteria = 0;
837         gchar *expr = NULL;
838
839         criteria = MATCHCRITERIA_FROM;
840         expr = $3;
841         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
842 }
843 | MATCHER_NOT_FROM match_type MATCHER_STRING
844 {
845         gint criteria = 0;
846         gchar *expr = NULL;
847
848         criteria = MATCHCRITERIA_NOT_FROM;
849         expr = $3;
850         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
851 }
852 | MATCHER_TO match_type MATCHER_STRING
853 {
854         gint criteria = 0;
855         gchar *expr = NULL;
856
857         criteria = MATCHCRITERIA_TO;
858         expr = $3;
859         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
860 }
861 | MATCHER_NOT_TO match_type MATCHER_STRING
862 {
863         gint criteria = 0;
864         gchar *expr = NULL;
865
866         criteria = MATCHCRITERIA_NOT_TO;
867         expr = $3;
868         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
869 }
870 | MATCHER_CC match_type MATCHER_STRING
871 {
872         gint criteria = 0;
873         gchar *expr = NULL;
874
875         criteria = MATCHCRITERIA_CC;
876         expr = $3;
877         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
878 }
879 | MATCHER_NOT_CC match_type MATCHER_STRING
880 {
881         gint criteria = 0;
882         gchar *expr = NULL;
883
884         criteria = MATCHCRITERIA_NOT_CC;
885         expr = $3;
886         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
887 }
888 | MATCHER_TO_OR_CC match_type MATCHER_STRING
889 {
890         gint criteria = 0;
891         gchar *expr = NULL;
892
893         criteria = MATCHCRITERIA_TO_OR_CC;
894         expr = $3;
895         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
896 }
897 | MATCHER_NOT_TO_AND_NOT_CC match_type MATCHER_STRING
898 {
899         gint criteria = 0;
900         gchar *expr = NULL;
901
902         criteria = MATCHCRITERIA_NOT_TO_AND_NOT_CC;
903         expr = $3;
904         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
905 }
906 | MATCHER_TAG match_type MATCHER_STRING
907 {
908         gint criteria = 0;
909         gchar *expr = NULL;
910
911         criteria = MATCHCRITERIA_TAG;
912         expr = $3;
913         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
914 }
915 | MATCHER_NOT_TAG match_type MATCHER_STRING
916 {
917         gint criteria = 0;
918         gchar *expr = NULL;
919
920         criteria = MATCHCRITERIA_NOT_TAG;
921         expr = $3;
922         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
923 }
924 | MATCHER_TAGGED
925 {
926         gint criteria = 0;
927
928         criteria = MATCHCRITERIA_TAGGED;
929         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
930 }
931 | MATCHER_NOT_TAGGED
932 {
933         gint criteria = 0;
934
935         criteria = MATCHCRITERIA_NOT_TAGGED;
936         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
937 }
938 | MATCHER_AGE_GREATER MATCHER_INTEGER
939 {
940         gint criteria = 0;
941         gint value = 0;
942
943         criteria = MATCHCRITERIA_AGE_GREATER;
944         value = strtol($2, NULL, 0);
945         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
946 }
947 | MATCHER_AGE_LOWER MATCHER_INTEGER
948 {
949         gint criteria = 0;
950         gint value = 0;
951
952         criteria = MATCHCRITERIA_AGE_LOWER;
953         value = strtol($2, NULL, 0);
954         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
955 }
956 | MATCHER_NEWSGROUPS match_type MATCHER_STRING
957 {
958         gint criteria = 0;
959         gchar *expr = NULL;
960
961         criteria = MATCHCRITERIA_NEWSGROUPS;
962         expr = $3;
963         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
964 }
965 | MATCHER_NOT_NEWSGROUPS match_type MATCHER_STRING
966 {
967         gint criteria = 0;
968         gchar *expr = NULL;
969
970         criteria = MATCHCRITERIA_NOT_NEWSGROUPS;
971         expr = $3;
972         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
973 }
974 | MATCHER_INREPLYTO match_type MATCHER_STRING
975 {
976         gint criteria = 0;
977         gchar *expr = NULL;
978
979         criteria = MATCHCRITERIA_INREPLYTO;
980         expr = $3;
981         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
982 }
983 | MATCHER_NOT_INREPLYTO match_type MATCHER_STRING
984 {
985         gint criteria = 0;
986         gchar *expr = NULL;
987
988         criteria = MATCHCRITERIA_NOT_INREPLYTO;
989         expr = $3;
990         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
991 }
992 | MATCHER_REFERENCES match_type MATCHER_STRING
993 {
994         gint criteria = 0;
995         gchar *expr = NULL;
996
997         criteria = MATCHCRITERIA_REFERENCES;
998         expr = $3;
999         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
1000 }
1001 | MATCHER_NOT_REFERENCES match_type MATCHER_STRING
1002 {
1003         gint criteria = 0;
1004         gchar *expr = NULL;
1005
1006         criteria = MATCHCRITERIA_NOT_REFERENCES;
1007         expr = $3;
1008         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
1009 }
1010 | MATCHER_SCORE_GREATER MATCHER_INTEGER
1011 {
1012         gint criteria = 0;
1013         gint value = 0;
1014
1015         criteria = MATCHCRITERIA_SCORE_GREATER;
1016         value = strtol($2, NULL, 0);
1017         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
1018 }
1019 | MATCHER_SCORE_LOWER MATCHER_INTEGER
1020 {
1021         gint criteria = 0;
1022         gint value = 0;
1023
1024         criteria = MATCHCRITERIA_SCORE_LOWER;
1025         value = strtol($2, NULL, 0);
1026         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
1027 }
1028 | MATCHER_SCORE_EQUAL MATCHER_INTEGER
1029 {
1030         gint criteria = 0;
1031         gint value = 0;
1032
1033         criteria = MATCHCRITERIA_SCORE_EQUAL;
1034         value = strtol($2, NULL, 0);
1035         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
1036 }
1037 | MATCHER_SIZE_GREATER MATCHER_INTEGER 
1038 {
1039         gint criteria = 0;
1040         gint value    = 0;
1041         criteria = MATCHCRITERIA_SIZE_GREATER;
1042         value = strtol($2, NULL, 0);
1043         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
1044 }
1045 | MATCHER_SIZE_SMALLER MATCHER_INTEGER
1046 {
1047         gint criteria = 0;
1048         gint value    = 0;
1049         criteria = MATCHCRITERIA_SIZE_SMALLER;
1050         value = strtol($2, NULL, 0);
1051         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
1052 }
1053 | MATCHER_SIZE_EQUAL MATCHER_INTEGER
1054 {
1055         gint criteria = 0;
1056         gint value    = 0;
1057         criteria = MATCHCRITERIA_SIZE_EQUAL;
1058         value = strtol($2, NULL, 0);
1059         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
1060 }
1061 | MATCHER_HEADER MATCHER_STRING
1062 {
1063         header = g_strdup($2);
1064 } match_type MATCHER_STRING
1065 {
1066         gint criteria = 0;
1067         gchar *expr = NULL;
1068         matcher_is_fast = FALSE;
1069         criteria = MATCHCRITERIA_HEADER;
1070         expr = $2;
1071         prop = matcherprop_new(criteria, header, match_type, expr, 0);
1072         g_free(header);
1073 }
1074 | MATCHER_NOT_HEADER MATCHER_STRING
1075 {
1076         header = g_strdup($2);
1077 } match_type MATCHER_STRING
1078 {
1079         gint criteria = 0;
1080         gchar *expr = NULL;
1081         matcher_is_fast = FALSE;
1082         criteria = MATCHCRITERIA_NOT_HEADER;
1083         expr = $2;
1084         prop = matcherprop_new(criteria, header, match_type, expr, 0);
1085         g_free(header);
1086 }
1087 | MATCHER_HEADERS_PART match_type MATCHER_STRING
1088 {
1089         gint criteria = 0;
1090         gchar *expr = NULL;
1091         matcher_is_fast = FALSE;
1092         criteria = MATCHCRITERIA_HEADERS_PART;
1093         expr = $3;
1094         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
1095 }
1096 | MATCHER_NOT_HEADERS_PART match_type MATCHER_STRING
1097 {
1098         gint criteria = 0;
1099         gchar *expr = NULL;
1100         matcher_is_fast = FALSE;
1101         criteria = MATCHCRITERIA_NOT_HEADERS_PART;
1102         expr = $3;
1103         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
1104 }
1105 | MATCHER_FOUND_IN_ADDRESSBOOK MATCHER_STRING
1106 {
1107         header = g_strdup($2);
1108 } MATCHER_IN MATCHER_STRING
1109 {
1110         gint criteria = 0;
1111         gchar *expr = NULL;
1112
1113         criteria = MATCHCRITERIA_FOUND_IN_ADDRESSBOOK;
1114         expr = $2;
1115         prop = matcherprop_new(criteria, header, match_type, expr, 0);
1116         g_free(header);
1117 }
1118 | MATCHER_NOT_FOUND_IN_ADDRESSBOOK MATCHER_STRING
1119 {
1120         header = g_strdup($2);
1121 } MATCHER_IN MATCHER_STRING
1122 {
1123         gint criteria = 0;
1124         gchar *expr = NULL;
1125
1126         criteria = MATCHCRITERIA_NOT_FOUND_IN_ADDRESSBOOK;
1127         expr = $2;
1128         prop = matcherprop_new(criteria, header, match_type, expr, 0);
1129         g_free(header);
1130 }
1131 | MATCHER_MESSAGE match_type MATCHER_STRING
1132 {
1133         gint criteria = 0;
1134         gchar *expr = NULL;
1135         matcher_is_fast = FALSE;
1136         criteria = MATCHCRITERIA_MESSAGE;
1137         expr = $3;
1138         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
1139 }
1140 | MATCHER_NOT_MESSAGE match_type MATCHER_STRING
1141 {
1142         gint criteria = 0;
1143         gchar *expr = NULL;
1144         matcher_is_fast = FALSE;
1145         criteria = MATCHCRITERIA_NOT_MESSAGE;
1146         expr = $3;
1147         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
1148 }
1149 | MATCHER_BODY_PART match_type MATCHER_STRING
1150 {
1151         gint criteria = 0;
1152         gchar *expr = NULL;
1153         matcher_is_fast = FALSE;
1154         criteria = MATCHCRITERIA_BODY_PART;
1155         expr = $3;
1156         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
1157 }
1158 | MATCHER_NOT_BODY_PART match_type MATCHER_STRING
1159 {
1160         gint criteria = 0;
1161         gchar *expr = NULL;
1162         matcher_is_fast = FALSE;
1163         criteria = MATCHCRITERIA_NOT_BODY_PART;
1164         expr = $3;
1165         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
1166 }
1167 | MATCHER_TEST MATCHER_STRING
1168 {
1169         gint criteria = 0;
1170         gchar *expr = NULL;
1171         matcher_is_fast = FALSE;
1172         criteria = MATCHCRITERIA_TEST;
1173         expr = $2;
1174         prop = matcherprop_new(criteria, NULL, MATCHTYPE_MATCH, expr, 0);
1175 }
1176 | MATCHER_NOT_TEST MATCHER_STRING
1177 {
1178         gint criteria = 0;
1179         gchar *expr = NULL;
1180         matcher_is_fast = FALSE;
1181         criteria = MATCHCRITERIA_NOT_TEST;
1182         expr = $2;
1183         prop = matcherprop_new(criteria, NULL, MATCHTYPE_MATCH, expr, 0);
1184 }
1185 ;
1186
1187 filtering_action:
1188 MATCHER_EXECUTE MATCHER_STRING
1189 {
1190         gchar *cmd = NULL;
1191         gint action_type = 0;
1192
1193         action_type = MATCHACTION_EXECUTE;
1194         cmd = $2;
1195         action = filteringaction_new(action_type, 0, cmd, 0, 0, NULL);
1196 }
1197 | MATCHER_MOVE MATCHER_STRING
1198 {
1199         gchar *destination = NULL;
1200         gint action_type = 0;
1201
1202         action_type = MATCHACTION_MOVE;
1203         destination = $2;
1204         action = filteringaction_new(action_type, 0, destination, 0, 0, NULL);
1205 }
1206 | MATCHER_SET_TAG MATCHER_STRING
1207 {
1208         gchar *destination = NULL;
1209         gint action_type = 0;
1210
1211         action_type = MATCHACTION_SET_TAG;
1212         destination = $2;
1213         action = filteringaction_new(action_type, 0, destination, 0, 0, NULL);
1214 }
1215 | MATCHER_UNSET_TAG MATCHER_STRING
1216 {
1217         gchar *destination = NULL;
1218         gint action_type = 0;
1219
1220         action_type = MATCHACTION_UNSET_TAG;
1221         destination = $2;
1222         action = filteringaction_new(action_type, 0, destination, 0, 0, NULL);
1223 }
1224 | MATCHER_CLEAR_TAGS
1225 {
1226         gint action_type = 0;
1227
1228         action_type = MATCHACTION_CLEAR_TAGS;
1229         action = filteringaction_new(action_type, 0, NULL, 0, 0, NULL);
1230 }
1231 | MATCHER_COPY MATCHER_STRING
1232 {
1233         gchar *destination = NULL;
1234         gint action_type = 0;
1235
1236         action_type = MATCHACTION_COPY;
1237         destination = $2;
1238         action = filteringaction_new(action_type, 0, destination, 0, 0, NULL);
1239 }
1240 | MATCHER_DELETE
1241 {
1242         gint action_type = 0;
1243
1244         action_type = MATCHACTION_DELETE;
1245         action = filteringaction_new(action_type, 0, NULL, 0, 0, NULL);
1246 }
1247 | MATCHER_MARK
1248 {
1249         gint action_type = 0;
1250
1251         action_type = MATCHACTION_MARK;
1252         action = filteringaction_new(action_type, 0, NULL, 0, 0, NULL);
1253 }
1254 | MATCHER_UNMARK
1255 {
1256         gint action_type = 0;
1257
1258         action_type = MATCHACTION_UNMARK;
1259         action = filteringaction_new(action_type, 0, NULL, 0, 0, NULL);
1260 }
1261 | MATCHER_LOCK
1262 {
1263         gint action_type = 0;
1264
1265         action_type = MATCHACTION_LOCK;
1266         action = filteringaction_new(action_type, 0, NULL, 0, 0, NULL);
1267 }
1268 | MATCHER_UNLOCK
1269 {
1270         gint action_type = 0;
1271
1272         action_type = MATCHACTION_UNLOCK;
1273         action = filteringaction_new(action_type, 0, NULL, 0, 0, NULL);
1274 }
1275 | MATCHER_MARK_AS_READ
1276 {
1277         gint action_type = 0;
1278
1279         action_type = MATCHACTION_MARK_AS_READ;
1280         action = filteringaction_new(action_type, 0, NULL, 0, 0, NULL);
1281 }
1282 | MATCHER_MARK_AS_UNREAD
1283 {
1284         gint action_type = 0;
1285
1286         action_type = MATCHACTION_MARK_AS_UNREAD;
1287         action = filteringaction_new(action_type, 0, NULL, 0, 0, NULL);
1288 }
1289 | MATCHER_MARK_AS_SPAM
1290 {
1291         gint action_type = 0;
1292
1293         action_type = MATCHACTION_MARK_AS_SPAM;
1294         action = filteringaction_new(action_type, 0, NULL, 0, 0, NULL);
1295 }
1296 | MATCHER_MARK_AS_HAM
1297 {
1298         gint action_type = 0;
1299
1300         action_type = MATCHACTION_MARK_AS_HAM;
1301         action = filteringaction_new(action_type, 0, NULL, 0, 0, NULL);
1302 }
1303 | MATCHER_FORWARD MATCHER_INTEGER MATCHER_STRING
1304 {
1305         gchar *destination = NULL;
1306         gint action_type = 0;
1307         gint account_id = 0;
1308
1309         action_type = MATCHACTION_FORWARD;
1310         account_id = strtol($2, NULL, 10);
1311         destination = $3;
1312         action = filteringaction_new(action_type,
1313             account_id, destination, 0, 0, NULL);
1314 }
1315 | MATCHER_FORWARD_AS_ATTACHMENT MATCHER_INTEGER MATCHER_STRING
1316 {
1317         gchar *destination = NULL;
1318         gint action_type = 0;
1319         gint account_id = 0;
1320
1321         action_type = MATCHACTION_FORWARD_AS_ATTACHMENT;
1322         account_id = strtol($2, NULL, 10);
1323         destination = $3;
1324         action = filteringaction_new(action_type,
1325             account_id, destination, 0, 0, NULL);
1326 }
1327 | MATCHER_REDIRECT MATCHER_INTEGER MATCHER_STRING
1328 {
1329         gchar *destination = NULL;
1330         gint action_type = 0;
1331         gint account_id = 0;
1332
1333         action_type = MATCHACTION_REDIRECT;
1334         account_id = strtol($2, NULL, 10);
1335         destination = $3;
1336         action = filteringaction_new(action_type,
1337             account_id, destination, 0, 0, NULL);
1338 }
1339 | MATCHER_COLOR MATCHER_INTEGER
1340 {
1341         gint action_type = 0;
1342         gint color = 0;
1343
1344         action_type = MATCHACTION_COLOR;
1345         color = strtol($2, NULL, 10);
1346         action = filteringaction_new(action_type, 0, NULL, color, 0, NULL);
1347 }
1348 | MATCHER_CHANGE_SCORE MATCHER_INTEGER
1349 {
1350         gint score = 0;
1351         
1352         score = strtol($2, NULL, 10);
1353         action = filteringaction_new(MATCHACTION_CHANGE_SCORE, 0,
1354                                      NULL, 0, score, NULL);
1355 }
1356 /* backward compatibility */
1357 | MATCHER_SCORE MATCHER_INTEGER
1358 {
1359         gint score = 0;
1360         
1361         score = strtol($2, NULL, 10);
1362         action = filteringaction_new(MATCHACTION_CHANGE_SCORE, 0,
1363                                      NULL, 0, score, NULL);
1364 }
1365 | MATCHER_SET_SCORE MATCHER_INTEGER
1366 {
1367         gint score = 0;
1368         
1369         score = strtol($2, NULL, 10);
1370         action = filteringaction_new(MATCHACTION_SET_SCORE, 0,
1371                                      NULL, 0, score, NULL);
1372 }
1373 | MATCHER_HIDE
1374 {
1375         action = filteringaction_new(MATCHACTION_HIDE, 0, NULL, 0, 0, NULL);
1376 }
1377 | MATCHER_IGNORE
1378 {
1379         action = filteringaction_new(MATCHACTION_IGNORE, 0, NULL, 0, 0, NULL);
1380 }
1381 | MATCHER_WATCH
1382 {
1383         action = filteringaction_new(MATCHACTION_WATCH, 0, NULL, 0, 0, NULL);
1384 }
1385 | MATCHER_ADD_TO_ADDRESSBOOK MATCHER_STRING
1386 {
1387         header = g_strdup($2);
1388 } MATCHER_STRING
1389 {
1390         gchar *addressbook = NULL;
1391         gint action_type = 0;
1392
1393         action_type = MATCHACTION_ADD_TO_ADDRESSBOOK;
1394         addressbook = $2;
1395         action = filteringaction_new(action_type, 0, addressbook, 0, 0, header);
1396         g_free(header);
1397 }
1398 | MATCHER_STOP
1399 {
1400         action = filteringaction_new(MATCHACTION_STOP, 0, NULL, 0, 0, NULL);
1401 }
1402 ;