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