replace deprecated gtk_signal... functions
[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_COLORLABEL MATCHER_NOT_COLORLABEL
239 %token MATCHER_IGNORE_THREAD MATCHER_NOT_IGNORE_THREAD
240 %token MATCHER_CHANGE_SCORE MATCHER_SET_SCORE
241 %token MATCHER_STOP MATCHER_HIDE
242
243 %start file
244
245 %token <str> MATCHER_STRING
246 %token <str> MATCHER_SECTION
247 %token <str> MATCHER_INTEGER
248
249 %%
250
251 file:
252 {
253         if (matcher_parse_op == MATCHER_PARSE_FILE) {
254                 prefs_filtering = &pre_global_processing;
255         }
256 }
257 file_line_list;
258
259 file_line_list:
260 file_line
261 file_line_list
262 | file_line
263 ;
264
265 file_line:
266 section_notification
267
268 { action_list = NULL; }
269 instruction
270 | error MATCHER_EOL
271 {
272         yyerrok;
273 };
274
275 section_notification:
276 MATCHER_SECTION MATCHER_EOL
277 {
278         gchar *folder = $1;
279         FolderItem *item = NULL;
280
281         if (matcher_parse_op == MATCHER_PARSE_FILE) {
282                 enable_compatibility = 0;
283                 if (!strcmp(folder, "global")) {
284                         /* backward compatibility */
285                         enable_compatibility = 1;
286                 }
287                 else if (!strcmp(folder, "preglobal")) {
288                         prefs_filtering = &pre_global_processing;
289                 }
290                 else if (!strcmp(folder, "postglobal")) {
291                         prefs_filtering = &post_global_processing;
292                 }
293                 else if (!strcmp(folder, "filtering")) {
294                         prefs_filtering = &filtering_rules;
295                 }
296                 else {
297                         item = folder_find_item_from_identifier(folder);
298                         if (item != NULL) {
299                                 prefs_filtering = &item->prefs->processing;
300                         } else {
301                                 prefs_filtering = NULL;
302                         }
303                 }
304         }
305 }
306 ;
307
308 instruction:
309 condition filtering MATCHER_EOL
310 | condition filtering
311 {
312         if (matcher_parse_op == MATCHER_PARSE_NO_EOL)
313                 YYACCEPT;
314         else {
315                 matcher_parsererror("parse error");
316                 YYERROR;
317         }
318 }
319 | condition
320 {
321         if (matcher_parse_op == MATCHER_PARSE_CONDITION)
322                 YYACCEPT;
323         else {
324                 matcher_parsererror("parse error");
325                 YYERROR;
326         }
327 }
328 | filtering_action_list
329 {
330         if (matcher_parse_op == MATCHER_PARSE_FILTERING_ACTION)
331                 YYACCEPT;
332         else {
333                 matcher_parsererror("parse error");
334                 YYERROR;
335         }
336 }
337 | MATCHER_EOL
338 ;
339
340 filtering:
341 filtering_action_list
342 {
343         filtering = filteringprop_new(cond, action_list);
344         
345         if (enable_compatibility) {
346                 prefs_filtering = &filtering_rules;
347                 if (action_list != NULL) {
348                         FilteringAction * first_action;
349                         
350                         first_action = action_list->data;
351                         
352                         if (first_action->type == MATCHACTION_CHANGE_SCORE)
353                                 prefs_filtering = &pre_global_processing;
354                 }
355         }
356         
357         cond = NULL;
358         action_list = NULL;
359         
360         if ((matcher_parse_op == MATCHER_PARSE_FILE) &&
361             (prefs_filtering != NULL)) {
362                 *prefs_filtering = g_slist_append(*prefs_filtering,
363                                                   filtering);
364                 filtering = NULL;
365         }
366 }
367 ;
368
369 filtering_action_list:
370 filtering_action_b filtering_action_list
371 | filtering_action_b
372 ;
373
374 filtering_action_b:
375 filtering_action
376 {
377         action_list = g_slist_append(action_list, action);
378         action = NULL;
379 }
380 ;
381
382 match_type:
383 MATCHER_MATCHCASE
384 {
385         match_type = MATCHTYPE_MATCHCASE;
386 }
387 | MATCHER_MATCH
388 {
389         match_type = MATCHTYPE_MATCH;
390 }
391 | MATCHER_REGEXPCASE
392 {
393         match_type = MATCHTYPE_REGEXPCASE;
394 }
395 | MATCHER_REGEXP
396 {
397         match_type = MATCHTYPE_REGEXP;
398 }
399 | MATCHER_ANY_IN_ADDRESSBOOK
400 {
401         match_type = MATCHTYPE_ANY_IN_ADDRESSBOOK;
402 }
403 | MATCHER_ALL_IN_ADDRESSBOOK
404 {
405         match_type = MATCHTYPE_ALL_IN_ADDRESSBOOK;
406 }
407 ;
408
409 condition:
410 condition_list
411 {
412         cond = matcherlist_new(matchers_list, (bool_op == MATCHERBOOL_AND));
413         matchers_list = NULL;
414 }
415 ;
416
417 condition_list:
418 condition_list bool_op one_condition
419 {
420         matchers_list = g_slist_append(matchers_list, prop);
421 }
422 | one_condition
423 {
424         matchers_list = NULL;
425         matchers_list = g_slist_append(matchers_list, prop);
426 }
427 ;
428
429 bool_op:
430 MATCHER_AND
431 {
432         bool_op = MATCHERBOOL_AND;
433 }
434 | MATCHER_OR
435 {
436         bool_op = MATCHERBOOL_OR;
437 }
438 ;
439
440 one_condition:
441 MATCHER_ALL
442 {
443         gint criteria = 0;
444
445         criteria = MATCHCRITERIA_ALL;
446         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
447 }
448 | MATCHER_UNREAD
449 {
450         gint criteria = 0;
451
452         criteria = MATCHCRITERIA_UNREAD;
453         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
454 }
455 | MATCHER_NOT_UNREAD 
456 {
457         gint criteria = 0;
458
459         criteria = MATCHCRITERIA_NOT_UNREAD;
460         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
461 }
462 | MATCHER_NEW
463 {
464         gint criteria = 0;
465
466         criteria = MATCHCRITERIA_NEW;
467         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
468 }
469 | MATCHER_NOT_NEW
470 {
471         gint criteria = 0;
472
473         criteria = MATCHCRITERIA_NOT_NEW;
474         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
475 }
476 | MATCHER_MARKED
477 {
478         gint criteria = 0;
479
480         criteria = MATCHCRITERIA_MARKED;
481         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
482 }
483 | MATCHER_NOT_MARKED
484 {
485         gint criteria = 0;
486
487         criteria = MATCHCRITERIA_NOT_MARKED;
488         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
489 }
490 | MATCHER_DELETED
491 {
492         gint criteria = 0;
493
494         criteria = MATCHCRITERIA_DELETED;
495         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
496 }
497 | MATCHER_NOT_DELETED
498 {
499         gint criteria = 0;
500
501         criteria = MATCHCRITERIA_NOT_DELETED;
502         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
503 }
504 | MATCHER_REPLIED
505 {
506         gint criteria = 0;
507
508         criteria = MATCHCRITERIA_REPLIED;
509         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
510 }
511 | MATCHER_NOT_REPLIED
512 {
513         gint criteria = 0;
514
515         criteria = MATCHCRITERIA_NOT_REPLIED;
516         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
517 }
518 | MATCHER_FORWARDED
519 {
520         gint criteria = 0;
521
522         criteria = MATCHCRITERIA_FORWARDED;
523         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
524 }
525 | MATCHER_NOT_FORWARDED
526 {
527         gint criteria = 0;
528
529         criteria = MATCHCRITERIA_NOT_FORWARDED;
530         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
531 }
532 | MATCHER_LOCKED
533 {
534         gint criteria = 0;
535
536         criteria = MATCHCRITERIA_LOCKED;
537         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
538 }
539 | MATCHER_NOT_LOCKED
540 {
541         gint criteria = 0;
542
543         criteria = MATCHCRITERIA_NOT_LOCKED;
544         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
545 }
546 | MATCHER_COLORLABEL MATCHER_INTEGER
547 {
548         gint criteria = 0;
549         gint value = 0;
550
551         criteria = MATCHCRITERIA_COLORLABEL;
552         value = strtol($2, NULL, 10);
553         if (value < 0) value = 0;
554         else if (value > MAX_COLORLABELS) value = MAX_COLORLABELS;
555         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
556 }
557 | MATCHER_NOT_COLORLABEL MATCHER_INTEGER
558 {
559         gint criteria = 0;
560         gint value = 0;
561
562         criteria = MATCHCRITERIA_NOT_COLORLABEL;
563         value = strtol($2, NULL, 0);
564         if (value < 0) value = 0;
565         else if (value > MAX_COLORLABELS) value = MAX_COLORLABELS;
566         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
567 }
568 | MATCHER_IGNORE_THREAD
569 {
570         gint criteria = 0;
571
572         criteria = MATCHCRITERIA_IGNORE_THREAD;
573         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
574 }
575 | MATCHER_NOT_IGNORE_THREAD
576 {
577         gint criteria = 0;
578
579         criteria = MATCHCRITERIA_NOT_IGNORE_THREAD;
580         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
581 }
582 | MATCHER_SUBJECT match_type MATCHER_STRING
583 {
584         gint criteria = 0;
585         gchar *expr = NULL;
586
587         criteria = MATCHCRITERIA_SUBJECT;
588         expr = $3;
589         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
590 }
591 | MATCHER_NOT_SUBJECT match_type MATCHER_STRING
592 {
593         gint criteria = 0;
594         gchar *expr = NULL;
595
596         criteria = MATCHCRITERIA_NOT_SUBJECT;
597         expr = $3;
598         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
599 }
600 | MATCHER_FROM match_type MATCHER_STRING
601 {
602         gint criteria = 0;
603         gchar *expr = NULL;
604
605         criteria = MATCHCRITERIA_FROM;
606         expr = $3;
607         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
608 }
609 | MATCHER_NOT_FROM match_type MATCHER_STRING
610 {
611         gint criteria = 0;
612         gchar *expr = NULL;
613
614         criteria = MATCHCRITERIA_NOT_FROM;
615         expr = $3;
616         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
617 }
618 | MATCHER_TO match_type MATCHER_STRING
619 {
620         gint criteria = 0;
621         gchar *expr = NULL;
622
623         criteria = MATCHCRITERIA_TO;
624         expr = $3;
625         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
626 }
627 | MATCHER_NOT_TO match_type MATCHER_STRING
628 {
629         gint criteria = 0;
630         gchar *expr = NULL;
631
632         criteria = MATCHCRITERIA_NOT_TO;
633         expr = $3;
634         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
635 }
636 | MATCHER_CC match_type MATCHER_STRING
637 {
638         gint criteria = 0;
639         gchar *expr = NULL;
640
641         criteria = MATCHCRITERIA_CC;
642         expr = $3;
643         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
644 }
645 | MATCHER_NOT_CC match_type MATCHER_STRING
646 {
647         gint criteria = 0;
648         gchar *expr = NULL;
649
650         criteria = MATCHCRITERIA_NOT_CC;
651         expr = $3;
652         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
653 }
654 | MATCHER_TO_OR_CC match_type MATCHER_STRING
655 {
656         gint criteria = 0;
657         gchar *expr = NULL;
658
659         criteria = MATCHCRITERIA_TO_OR_CC;
660         expr = $3;
661         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
662 }
663 | MATCHER_NOT_TO_AND_NOT_CC match_type MATCHER_STRING
664 {
665         gint criteria = 0;
666         gchar *expr = NULL;
667
668         criteria = MATCHCRITERIA_NOT_TO_AND_NOT_CC;
669         expr = $3;
670         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
671 }
672 | MATCHER_AGE_GREATER MATCHER_INTEGER
673 {
674         gint criteria = 0;
675         gint value = 0;
676
677         criteria = MATCHCRITERIA_AGE_GREATER;
678         value = strtol($2, NULL, 0);
679         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
680 }
681 | MATCHER_AGE_LOWER MATCHER_INTEGER
682 {
683         gint criteria = 0;
684         gint value = 0;
685
686         criteria = MATCHCRITERIA_AGE_LOWER;
687         value = strtol($2, NULL, 0);
688         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
689 }
690 | MATCHER_NEWSGROUPS match_type MATCHER_STRING
691 {
692         gint criteria = 0;
693         gchar *expr = NULL;
694
695         criteria = MATCHCRITERIA_NEWSGROUPS;
696         expr = $3;
697         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
698 }
699 | MATCHER_NOT_NEWSGROUPS match_type MATCHER_STRING
700 {
701         gint criteria = 0;
702         gchar *expr = NULL;
703
704         criteria = MATCHCRITERIA_NOT_NEWSGROUPS;
705         expr = $3;
706         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
707 }
708 | MATCHER_INREPLYTO match_type MATCHER_STRING
709 {
710         gint criteria = 0;
711         gchar *expr = NULL;
712
713         criteria = MATCHCRITERIA_INREPLYTO;
714         expr = $3;
715         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
716 }
717 | MATCHER_NOT_INREPLYTO match_type MATCHER_STRING
718 {
719         gint criteria = 0;
720         gchar *expr = NULL;
721
722         criteria = MATCHCRITERIA_NOT_INREPLYTO;
723         expr = $3;
724         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
725 }
726 | MATCHER_REFERENCES match_type MATCHER_STRING
727 {
728         gint criteria = 0;
729         gchar *expr = NULL;
730
731         criteria = MATCHCRITERIA_REFERENCES;
732         expr = $3;
733         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
734 }
735 | MATCHER_NOT_REFERENCES match_type MATCHER_STRING
736 {
737         gint criteria = 0;
738         gchar *expr = NULL;
739
740         criteria = MATCHCRITERIA_NOT_REFERENCES;
741         expr = $3;
742         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
743 }
744 | MATCHER_SCORE_GREATER MATCHER_INTEGER
745 {
746         gint criteria = 0;
747         gint value = 0;
748
749         criteria = MATCHCRITERIA_SCORE_GREATER;
750         value = strtol($2, NULL, 0);
751         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
752 }
753 | MATCHER_SCORE_LOWER MATCHER_INTEGER
754 {
755         gint criteria = 0;
756         gint value = 0;
757
758         criteria = MATCHCRITERIA_SCORE_LOWER;
759         value = strtol($2, NULL, 0);
760         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
761 }
762 | MATCHER_SCORE_EQUAL MATCHER_INTEGER
763 {
764         gint criteria = 0;
765         gint value = 0;
766
767         criteria = MATCHCRITERIA_SCORE_EQUAL;
768         value = strtol($2, NULL, 0);
769         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
770 }
771 | MATCHER_SIZE_GREATER MATCHER_INTEGER 
772 {
773         gint criteria = 0;
774         gint value    = 0;
775         criteria = MATCHCRITERIA_SIZE_GREATER;
776         value = strtol($2, NULL, 0);
777         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
778 }
779 | MATCHER_SIZE_SMALLER MATCHER_INTEGER
780 {
781         gint criteria = 0;
782         gint value    = 0;
783         criteria = MATCHCRITERIA_SIZE_SMALLER;
784         value = strtol($2, NULL, 0);
785         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
786 }
787 | MATCHER_SIZE_EQUAL MATCHER_INTEGER
788 {
789         gint criteria = 0;
790         gint value    = 0;
791         criteria = MATCHCRITERIA_SIZE_EQUAL;
792         value = strtol($2, NULL, 0);
793         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
794 }
795 | MATCHER_HEADER MATCHER_STRING
796 {
797         header = g_strdup($2);
798 } match_type MATCHER_STRING
799 {
800         gint criteria = 0;
801         gchar *expr = NULL;
802
803         criteria = MATCHCRITERIA_HEADER;
804         expr = $2;
805         prop = matcherprop_new(criteria, header, match_type, expr, 0);
806         g_free(header);
807 }
808 | MATCHER_NOT_HEADER MATCHER_STRING
809 {
810         header = g_strdup($2);
811 } match_type MATCHER_STRING
812 {
813         gint criteria = 0;
814         gchar *expr = NULL;
815
816         criteria = MATCHCRITERIA_NOT_HEADER;
817         expr = $2;
818         prop = matcherprop_new(criteria, header, match_type, expr, 0);
819         g_free(header);
820 }
821 | MATCHER_HEADERS_PART match_type MATCHER_STRING
822 {
823         gint criteria = 0;
824         gchar *expr = NULL;
825
826         criteria = MATCHCRITERIA_HEADERS_PART;
827         expr = $3;
828         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
829 }
830 | MATCHER_NOT_HEADERS_PART match_type MATCHER_STRING
831 {
832         gint criteria = 0;
833         gchar *expr = NULL;
834
835         criteria = MATCHCRITERIA_NOT_HEADERS_PART;
836         expr = $3;
837         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
838 }
839 | MATCHER_MESSAGE match_type MATCHER_STRING
840 {
841         gint criteria = 0;
842         gchar *expr = NULL;
843
844         criteria = MATCHCRITERIA_MESSAGE;
845         expr = $3;
846         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
847 }
848 | MATCHER_NOT_MESSAGE match_type MATCHER_STRING
849 {
850         gint criteria = 0;
851         gchar *expr = NULL;
852
853         criteria = MATCHCRITERIA_NOT_MESSAGE;
854         expr = $3;
855         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
856 }
857 | MATCHER_BODY_PART match_type MATCHER_STRING
858 {
859         gint criteria = 0;
860         gchar *expr = NULL;
861
862         criteria = MATCHCRITERIA_BODY_PART;
863         expr = $3;
864         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
865 }
866 | MATCHER_NOT_BODY_PART match_type MATCHER_STRING
867 {
868         gint criteria = 0;
869         gchar *expr = NULL;
870
871         criteria = MATCHCRITERIA_NOT_BODY_PART;
872         expr = $3;
873         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
874 }
875 | MATCHER_TEST MATCHER_STRING
876 {
877         gint criteria = 0;
878         gchar *expr = NULL;
879
880         criteria = MATCHCRITERIA_TEST;
881         expr = $2;
882         prop = matcherprop_new(criteria, NULL, 0, expr, 0);
883 }
884 | MATCHER_NOT_TEST MATCHER_STRING
885 {
886         gint criteria = 0;
887         gchar *expr = NULL;
888
889         criteria = MATCHCRITERIA_NOT_TEST;
890         expr = $2;
891         prop = matcherprop_new(criteria, NULL, 0, expr, 0);
892 }
893 ;
894
895 filtering_action:
896 MATCHER_EXECUTE MATCHER_STRING
897 {
898         gchar *cmd = NULL;
899         gint action_type = 0;
900
901         action_type = MATCHACTION_EXECUTE;
902         cmd = $2;
903         action = filteringaction_new(action_type, 0, cmd, 0, 0);
904 }
905 | MATCHER_MOVE MATCHER_STRING
906 {
907         gchar *destination = NULL;
908         gint action_type = 0;
909
910         action_type = MATCHACTION_MOVE;
911         destination = $2;
912         action = filteringaction_new(action_type, 0, destination, 0, 0);
913 }
914 | MATCHER_COPY MATCHER_STRING
915 {
916         gchar *destination = NULL;
917         gint action_type = 0;
918
919         action_type = MATCHACTION_COPY;
920         destination = $2;
921         action = filteringaction_new(action_type, 0, destination, 0, 0);
922 }
923 | MATCHER_DELETE
924 {
925         gint action_type = 0;
926
927         action_type = MATCHACTION_DELETE;
928         action = filteringaction_new(action_type, 0, NULL, 0, 0);
929 }
930 | MATCHER_MARK
931 {
932         gint action_type = 0;
933
934         action_type = MATCHACTION_MARK;
935         action = filteringaction_new(action_type, 0, NULL, 0, 0);
936 }
937 | MATCHER_UNMARK
938 {
939         gint action_type = 0;
940
941         action_type = MATCHACTION_UNMARK;
942         action = filteringaction_new(action_type, 0, NULL, 0, 0);
943 }
944 | MATCHER_LOCK
945 {
946         gint action_type = 0;
947
948         action_type = MATCHACTION_LOCK;
949         action = filteringaction_new(action_type, 0, NULL, 0, 0);
950 }
951 | MATCHER_UNLOCK
952 {
953         gint action_type = 0;
954
955         action_type = MATCHACTION_UNLOCK;
956         action = filteringaction_new(action_type, 0, NULL, 0, 0);
957 }
958 | MATCHER_MARK_AS_READ
959 {
960         gint action_type = 0;
961
962         action_type = MATCHACTION_MARK_AS_READ;
963         action = filteringaction_new(action_type, 0, NULL, 0, 0);
964 }
965 | MATCHER_MARK_AS_UNREAD
966 {
967         gint action_type = 0;
968
969         action_type = MATCHACTION_MARK_AS_UNREAD;
970         action = filteringaction_new(action_type, 0, NULL, 0, 0);
971 }
972 | MATCHER_FORWARD MATCHER_INTEGER MATCHER_STRING
973 {
974         gchar *destination = NULL;
975         gint action_type = 0;
976         gint account_id = 0;
977
978         action_type = MATCHACTION_FORWARD;
979         account_id = strtol($2, NULL, 10);
980         destination = $3;
981         action = filteringaction_new(action_type,
982             account_id, destination, 0, 0);
983 }
984 | MATCHER_FORWARD_AS_ATTACHMENT MATCHER_INTEGER MATCHER_STRING
985 {
986         gchar *destination = NULL;
987         gint action_type = 0;
988         gint account_id = 0;
989
990         action_type = MATCHACTION_FORWARD_AS_ATTACHMENT;
991         account_id = strtol($2, NULL, 10);
992         destination = $3;
993         action = filteringaction_new(action_type,
994             account_id, destination, 0, 0);
995 }
996 | MATCHER_REDIRECT MATCHER_INTEGER MATCHER_STRING
997 {
998         gchar *destination = NULL;
999         gint action_type = 0;
1000         gint account_id = 0;
1001
1002         action_type = MATCHACTION_REDIRECT;
1003         account_id = strtol($2, NULL, 10);
1004         destination = $3;
1005         action = filteringaction_new(action_type,
1006             account_id, destination, 0, 0);
1007 }
1008 | MATCHER_COLOR MATCHER_INTEGER
1009 {
1010         gint action_type = 0;
1011         gint color = 0;
1012
1013         action_type = MATCHACTION_COLOR;
1014         color = strtol($2, NULL, 10);
1015         action = filteringaction_new(action_type, 0, NULL, color, 0);
1016 }
1017 | MATCHER_CHANGE_SCORE MATCHER_INTEGER
1018 {
1019         gint score = 0;
1020         
1021         score = strtol($2, NULL, 10);
1022         action = filteringaction_new(MATCHACTION_CHANGE_SCORE, 0,
1023                                      NULL, 0, score);
1024 }
1025 /* backward compatibility */
1026 | MATCHER_SCORE MATCHER_INTEGER
1027 {
1028         gint score = 0;
1029         
1030         score = strtol($2, NULL, 10);
1031         action = filteringaction_new(MATCHACTION_CHANGE_SCORE, 0,
1032                                      NULL, 0, score);
1033 }
1034 | MATCHER_SET_SCORE MATCHER_INTEGER
1035 {
1036         gint score = 0;
1037         
1038         score = strtol($2, NULL, 10);
1039         action = filteringaction_new(MATCHACTION_SET_SCORE, 0,
1040                                      NULL, 0, score);
1041 }
1042 | MATCHER_HIDE
1043 {
1044         action = filteringaction_new(MATCHACTION_HIDE, 0, NULL, 0, 0);
1045 }
1046 | MATCHER_STOP
1047 {
1048         action = filteringaction_new(MATCHACTION_STOP, 0, NULL, 0, 0);
1049 }
1050 ;