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