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