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