make unescaping / escaping in filtering work again
[claws.git] / src / matcher_parser_lex.l
1 %{
2 #include "matcher_parser_lex.h"
3 #include "matcher_parser_parse.h"
4 #include <glib.h>
5
6 #define MAX_STR_CONST 512
7
8 char string_buf[MAX_STR_CONST];
9 char * string_buf_ptr;
10
11 static void add_char(char ch)
12 {
13         if (string_buf_ptr - string_buf < sizeof(string_buf))
14                 *string_buf_ptr++ = ch;
15 }
16 %}
17
18 %option prefix="matcher_parser"
19 %option outfile="lex.yy.c"
20 %option yylineno
21
22 %x string
23 %x section
24
25 %%
26
27 "all"           return MATCHER_ALL;
28 "unread"        return MATCHER_UNREAD;
29 "~unread"       return MATCHER_NOT_UNREAD;
30 "new"           return MATCHER_NEW;
31 "~new"          return MATCHER_NOT_NEW;
32 "marked"        return MATCHER_MARKED;
33 "~marked"       return MATCHER_NOT_MARKED;
34 "deleted"       return MATCHER_DELETED;
35 "~deleted"      return MATCHER_NOT_DELETED;
36 "replied"       return MATCHER_REPLIED;
37 "~replied"      return MATCHER_NOT_REPLIED;
38 "forwarded"     return MATCHER_FORWARDED;
39 "~forwarded"    return MATCHER_NOT_FORWARDED;
40 "subject"       return MATCHER_SUBJECT;
41 "~subject"      return MATCHER_NOT_SUBJECT;
42 "from"          return MATCHER_FROM;
43 "~from"         return MATCHER_NOT_FROM;
44 "to"            return MATCHER_TO;
45 "~to"           return MATCHER_NOT_TO;
46 "cc"            return MATCHER_CC;
47 "~cc"           return MATCHER_NOT_CC;
48 "to_or_cc"      return MATCHER_TO_OR_CC;
49 "~to_or_cc"     return MATCHER_NOT_TO_AND_NOT_CC;
50 "age_greater"   return MATCHER_AGE_GREATER;
51 "age_lower"     return MATCHER_AGE_LOWER;
52 "newsgroups"    return MATCHER_NEWSGROUPS;
53 "~newsgroups"   return MATCHER_NOT_NEWSGROUPS;
54 "inreplyto"     return MATCHER_INREPLYTO;
55 "~inreplyto"    return MATCHER_NOT_INREPLYTO;
56 "references"    return MATCHER_REFERENCES;
57 "~references"   return MATCHER_NOT_REFERENCES;
58 "score_greater" return MATCHER_SCORE_GREATER;
59 "score_lower"   return MATCHER_SCORE_LOWER;
60 "score_equal"   return MATCHER_SCORE_EQUAL;
61 "header"        return MATCHER_HEADER;
62 "~header"       return MATCHER_NOT_HEADER;
63 "headers_part"  return MATCHER_HEADERS_PART;
64 "~headers_part" return MATCHER_NOT_HEADERS_PART;
65 "message"       return MATCHER_MESSAGE;
66 "~message"      return MATCHER_NOT_MESSAGE;
67 "body_part"     return MATCHER_BODY_PART;
68 "~body_part"    return MATCHER_NOT_BODY_PART;
69 "execute"       return MATCHER_EXECUTE;
70 "~execute"      return MATCHER_NOT_EXECUTE;
71 "matchcase"     return MATCHER_MATCHCASE;
72 "match"         return MATCHER_MATCH;
73 "regexpcase"    return MATCHER_REGEXPCASE;
74 "regexp"        return MATCHER_REGEXP;
75 "score"         return MATCHER_SCORE;
76 "move"          return MATCHER_MOVE;
77 "copy"          return MATCHER_COPY;
78 "delete"        return MATCHER_DELETE;
79 "mark"          return MATCHER_MARK;
80 "unmark"        return MATCHER_UNMARK;
81 "mark_as_read"  return MATCHER_MARK_AS_READ;
82 "mark_as_unread"       return MATCHER_MARK_AS_UNREAD;
83 "forward"              return MATCHER_FORWARD;
84 "forward_as_attachment"       return MATCHER_FORWARD_AS_ATTACHMENT;
85 "color"         return MATCHER_COLOR;
86 "bounce"        return MATCHER_BOUNCE;
87 [ \t]+
88 "\n"            return MATCHER_EOL;
89 "&"             return MATCHER_AND;
90 "|"             return MATCHER_OR;
91 \"              {
92                 BEGIN(string);
93                 string_buf_ptr = string_buf;
94                 }
95                 /* the following tokens \n \t \r \b \f \\ could be
96                  * removed from the list, but we let them here for
97                  * the sake of clarity; they are unescaped by 
98                  * matcher.c:unescape_str()) */
99 <string>\\n     {
100                 /* paste as-is */
101                 add_char('\\');
102                 add_char('n');
103                 }
104 <string>\\t     {
105                 /* paste as-is */
106                 add_char('\\');
107                 add_char('t');
108                 }
109 <string>\\r     {
110                 /* paste as-is */
111                 add_char('\\');
112                 add_char('r');
113                 }
114 <string>\\b     {
115                 /* paste as-is */
116                 add_char('\\');
117                 add_char('b');
118                 }
119 <string>\\f     {
120                 /* paste as-is */
121                 add_char('\\');
122                 add_char('f');
123                 }
124 <string>\\\'    {
125                 /* paste as-is */
126                 add_char('\\');
127                 add_char('\'');
128                 }
129 <string>\\\"    {
130                 /* paste as-is */
131                 add_char('\\');
132                 add_char('\"');
133                 }
134                 /* we only miss the thing with nested escaping like
135                  * \\\\" which should mean something like 'forget it, we want a "'
136                  * right here in the token stream.... */
137 <string>\"      {
138                 BEGIN(0);
139                 *string_buf_ptr = '\0';
140                 yylval.str = string_buf;
141                 return MATCHER_STRING;
142                 }
143 <string>.       {
144                 add_char(yytext[0]);
145                 }
146 \[[^\[\]]*\]    {
147                 BEGIN(0);
148                 yylval.str = yytext + 1;
149                 yytext[strlen(yytext) - 1] = '\0';
150                 return MATCHER_SECTION;
151                 }
152 [-+]?[0-9]+     {
153                 yylval.str = yytext;
154                 return MATCHER_INTEGER;
155                 }
156
157 %%