Rewrite sieve parser.
Three objectives: 1. Simplify code. 2. Produce optimized sieve code. 3. Improve error reporting. 4. Prepare for further extensions * include/mailutils/sieve.h (mu_sieve_tag_checker_t): Change signature (take mu_sieve_machine_t as the first arg). All uses changed. (mu_sieve_require): Likewise. (mu_sieve_yydebug): Remove global. * libmu_sieve/sieve-priv.h (mu_locus_range): New struct. (YYLTYPE): New define (mu_sieve_state): New enum. (mu_sieve_machine): New members: string_pool, state. (mu_sieve_node_type): New enum. (mu_sieve_node): New struct. Remove unused prototypes. * libmu_sieve/sieve.l: Keep track of code locations. Use opool for constructing string values. * libmu_sieve/sieve.y: Rewrite. First build the parse tree. Then optimize it. Finally, generate code. * libmu_sieve/tests.c (sieve_test_true,sieve_test_false): Remove. True and false tests are always optimized away. * libmu_sieve/util.c (mu_sv_compile_error): Remove. * libmu_sieve/actions.c: Use mu_diag_at_locus to report errors and mu_i_sv_error to mark sieve machine as being in error state. * libmu_sieve/comparator.c: Likewise. * libmu_sieve/prog.c (mu_sv_code): Replace with mu_i_sv_code. (mu_sv_code_instr,mu_sv_code_handler) (mu_sv_code_list,mu_sv_code_number) (mu_sv_code_string,mu_sv_code_source) (mu_sv_code_line,mu_sv_change_source) (mu_sv_code_action,mu_sv_code_test) (mu_sv_code_anyof,mu_sv_code_allof): Remove. (mu_i_sv_locus,mu_i_sv_code_action) (mu_i_sv_code_test): New function. (mu_sv_code_command): Replace with a static function. * libmu_sieve/require.c (mu_sieve_require): Take ptr to machine as the first arg. * libmu_sieve/runtime.c (mu_sieve_mailbox) (mu_sieve_message): Refuse to run if the machine is in error state. * sieve/sieve.c: Update. * sieve/tests/i-numeric.at: Update expected error message. * libmailutils/diag/diag.c (mu_diag_at_locus): Don't pass locus if mu_file is NULL. * libmu_auth/ldap.c (_mu_entry_to_auth_data): Remove leftover mu_error.
Showing
16 changed files
with
286 additions
and
240 deletions
... | @@ -47,7 +47,8 @@ typedef int (*mu_sieve_comparator_t) (const char *, const char *); | ... | @@ -47,7 +47,8 @@ typedef int (*mu_sieve_comparator_t) (const char *, const char *); |
47 | typedef int (*mu_sieve_retrieve_t) (void *item, void *data, int idx, | 47 | typedef int (*mu_sieve_retrieve_t) (void *item, void *data, int idx, |
48 | char **pval); | 48 | char **pval); |
49 | typedef void (*mu_sieve_destructor_t) (void *data); | 49 | typedef void (*mu_sieve_destructor_t) (void *data); |
50 | typedef int (*mu_sieve_tag_checker_t) (const char *name, | 50 | typedef int (*mu_sieve_tag_checker_t) (mu_sieve_machine_t mach, |
51 | const char *name, | ||
51 | mu_list_t tags, mu_list_t args); | 52 | mu_list_t tags, mu_list_t args); |
52 | 53 | ||
53 | typedef enum | 54 | typedef enum |
... | @@ -121,7 +122,6 @@ typedef struct | ... | @@ -121,7 +122,6 @@ typedef struct |
121 | #define MU_SIEVE_DEBUG_DISAS 0x0004 | 122 | #define MU_SIEVE_DEBUG_DISAS 0x0004 |
122 | #define MU_SIEVE_DRY_RUN 0x0008 | 123 | #define MU_SIEVE_DRY_RUN 0x0008 |
123 | 124 | ||
124 | extern int mu_sieve_yydebug; | ||
125 | extern mu_debug_handle_t mu_sieve_debug_handle; | 125 | extern mu_debug_handle_t mu_sieve_debug_handle; |
126 | extern mu_list_t mu_sieve_include_path; | 126 | extern mu_list_t mu_sieve_include_path; |
127 | extern mu_list_t mu_sieve_library_path; | 127 | extern mu_list_t mu_sieve_library_path; |
... | @@ -190,13 +190,16 @@ int mu_sieve_str_to_relcmp (const char *str, mu_sieve_relcmp_t * test, | ... | @@ -190,13 +190,16 @@ int mu_sieve_str_to_relcmp (const char *str, mu_sieve_relcmp_t * test, |
190 | mu_sieve_relcmp_t mu_sieve_get_relcmp (mu_sieve_machine_t mach, | 190 | mu_sieve_relcmp_t mu_sieve_get_relcmp (mu_sieve_machine_t mach, |
191 | mu_list_t tags); | 191 | mu_list_t tags); |
192 | 192 | ||
193 | void mu_sieve_require (mu_list_t slist); | 193 | void mu_sieve_require (mu_sieve_machine_t mach, mu_list_t slist); |
194 | |||
194 | int mu_sieve_tag_lookup (mu_list_t taglist, char *name, | 195 | int mu_sieve_tag_lookup (mu_list_t taglist, char *name, |
195 | mu_sieve_value_t ** arg); | 196 | mu_sieve_value_t ** arg); |
196 | int mu_sieve_load_ext (mu_sieve_machine_t mach, const char *name); | 197 | int mu_sieve_load_ext (mu_sieve_machine_t mach, const char *name); |
197 | int mu_sieve_match_part_checker (const char *name, mu_list_t tags, | 198 | int mu_sieve_match_part_checker (mu_sieve_machine_t mach, |
199 | const char *name, mu_list_t tags, | ||
198 | mu_list_t args); | 200 | mu_list_t args); |
199 | int mu_sieve_match_part_checker (const char *name, mu_list_t tags, | 201 | int mu_sieve_match_part_checker (mu_sieve_machine_t mach, |
202 | const char *name, mu_list_t tags, | ||
200 | mu_list_t args); | 203 | mu_list_t args); |
201 | /* Operations in value lists */ | 204 | /* Operations in value lists */ |
202 | mu_sieve_value_t *mu_sieve_value_get (mu_list_t vlist, size_t index); | 205 | mu_sieve_value_t *mu_sieve_value_get (mu_list_t vlist, size_t index); | ... | ... |
... | @@ -61,10 +61,11 @@ mu_diag_at_locus (int level, struct mu_locus const *loc, const char *fmt, ...) | ... | @@ -61,10 +61,11 @@ mu_diag_at_locus (int level, struct mu_locus const *loc, const char *fmt, ...) |
61 | va_list ap; | 61 | va_list ap; |
62 | 62 | ||
63 | va_start (ap, fmt); | 63 | va_start (ap, fmt); |
64 | mu_stream_printf (mu_strerr, "\033f<%d>%s\033l<%u>\033c<%u>", | 64 | if (loc && loc->mu_file) |
65 | (unsigned) strlen (loc->mu_file), loc->mu_file, | 65 | mu_stream_printf (mu_strerr, "\033f<%d>%s\033l<%u>\033c<%u>", |
66 | loc->mu_line, | 66 | (unsigned) strlen (loc->mu_file), loc->mu_file, |
67 | loc->mu_col); | 67 | loc->mu_line, |
68 | loc->mu_col); | ||
68 | mu_diag_voutput (level, fmt, ap); | 69 | mu_diag_voutput (level, fmt, ap); |
69 | va_end (ap); | 70 | va_end (ap); |
70 | } | 71 | } | ... | ... |
... | @@ -538,8 +538,6 @@ _mu_entry_to_auth_data (LDAP *ld, LDAPMessage *msg, | ... | @@ -538,8 +538,6 @@ _mu_entry_to_auth_data (LDAP *ld, LDAPMessage *msg, |
538 | 538 | ||
539 | rc = ldap_get_dn_ber (ld, msg, &ber, &bv); | 539 | rc = ldap_get_dn_ber (ld, msg, &ber, &bv); |
540 | ufn = ldap_dn2ufn (bv.bv_val); | 540 | ufn = ldap_dn2ufn (bv.bv_val); |
541 | /* FIXME: Use debug or diag functions */ | ||
542 | mu_error ("INFO: %s", ufn); | ||
543 | ldap_memfree (ufn); | 541 | ldap_memfree (ufn); |
544 | 542 | ||
545 | mu_assoc_get_iterator (ldap_param.field_map, &itr); | 543 | mu_assoc_get_iterator (ldap_param.field_map, &itr); | ... | ... |
... | @@ -17,6 +17,7 @@ | ... | @@ -17,6 +17,7 @@ |
17 | 17 | ||
18 | YLWRAP = $(SHELL) $(mu_aux_dir)/gylwrap | 18 | YLWRAP = $(SHELL) $(mu_aux_dir)/gylwrap |
19 | AM_YFLAGS = -dtv | 19 | AM_YFLAGS = -dtv |
20 | #AM_LEXFLAGS=-dvp | ||
20 | AM_CPPFLAGS =\ | 21 | AM_CPPFLAGS =\ |
21 | @MU_LIB_COMMON_INCLUDES@\ | 22 | @MU_LIB_COMMON_INCLUDES@\ |
22 | -DMU_SIEVE_MODDIR=\"@MU_SIEVE_MODDIR@\" | 23 | -DMU_SIEVE_MODDIR=\"@MU_SIEVE_MODDIR@\" | ... | ... |
... | @@ -522,7 +522,8 @@ mu_sieve_data_type fileinto_args[] = { | ... | @@ -522,7 +522,8 @@ mu_sieve_data_type fileinto_args[] = { |
522 | }; | 522 | }; |
523 | 523 | ||
524 | static int | 524 | static int |
525 | perms_tag_checker (const char *name, mu_list_t tags, mu_list_t args) | 525 | perms_tag_checker (mu_sieve_machine_t mach, |
526 | const char *name, mu_list_t tags, mu_list_t args) | ||
526 | { | 527 | { |
527 | mu_iterator_t itr; | 528 | mu_iterator_t itr; |
528 | int err = 0; | 529 | int err = 0; |
... | @@ -540,8 +541,9 @@ perms_tag_checker (const char *name, mu_list_t tags, mu_list_t args) | ... | @@ -540,8 +541,9 @@ perms_tag_checker (const char *name, mu_list_t tags, mu_list_t args) |
540 | { | 541 | { |
541 | if (mu_parse_stream_perm_string (&flag, t->arg->v.string, &p)) | 542 | if (mu_parse_stream_perm_string (&flag, t->arg->v.string, &p)) |
542 | { | 543 | { |
543 | mu_sv_compile_error (&mu_sieve_locus, | 544 | mu_diag_at_locus (MU_LOG_ERROR, &mach->locus, |
544 | _("invalid permissions (near %s)"), p); | 545 | _("invalid permissions (near %s)"), p); |
546 | mu_i_sv_error (mach); | ||
545 | err = 1; | 547 | err = 1; |
546 | } | 548 | } |
547 | } | 549 | } | ... | ... |
... | @@ -139,7 +139,9 @@ mu_sieve_get_comparator (mu_sieve_machine_t mach, mu_list_t tags) | ... | @@ -139,7 +139,9 @@ mu_sieve_get_comparator (mu_sieve_machine_t mach, mu_list_t tags) |
139 | 139 | ||
140 | /* Compile time support */ | 140 | /* Compile time support */ |
141 | 141 | ||
142 | struct regex_data { | 142 | struct regex_data |
143 | { | ||
144 | mu_sieve_machine_t mach; | ||
143 | int flags; | 145 | int flags; |
144 | mu_list_t list; | 146 | mu_list_t list; |
145 | }; | 147 | }; |
... | @@ -158,7 +160,7 @@ _regex_compile (void *item, void *data) | ... | @@ -158,7 +160,7 @@ _regex_compile (void *item, void *data) |
158 | { | 160 | { |
159 | struct regex_data *rd = data; | 161 | struct regex_data *rd = data; |
160 | int rc; | 162 | int rc; |
161 | regex_t *preg = mu_sieve_malloc (mu_sieve_machine, sizeof (*preg)); | 163 | regex_t *preg = mu_sieve_malloc (rd->mach, sizeof (*preg)); |
162 | 164 | ||
163 | rc = regcomp (preg, (char*)item, rd->flags); | 165 | rc = regcomp (preg, (char*)item, rd->flags); |
164 | if (rc) | 166 | if (rc) |
... | @@ -168,11 +170,13 @@ _regex_compile (void *item, void *data) | ... | @@ -168,11 +170,13 @@ _regex_compile (void *item, void *data) |
168 | if (errbuf) | 170 | if (errbuf) |
169 | { | 171 | { |
170 | regerror (rc, preg, errbuf, size); | 172 | regerror (rc, preg, errbuf, size); |
171 | mu_sv_compile_error (&mu_sieve_locus, _("regex error: %s"), errbuf); | 173 | mu_diag_at_locus (MU_LOG_ERROR, &rd->mach->locus, |
174 | _("regex error: %s"), errbuf); | ||
172 | free (errbuf); | 175 | free (errbuf); |
173 | } | 176 | } |
174 | else | 177 | else |
175 | mu_sv_compile_error (&mu_sieve_locus, _("regex error")); | 178 | mu_diag_at_locus (MU_LOG_ERROR, &rd->mach->locus, _("regex error")); |
179 | mu_i_sv_error (rd->mach); | ||
176 | return rc; | 180 | return rc; |
177 | } | 181 | } |
178 | 182 | ||
... | @@ -203,7 +207,8 @@ comp_false (const char *pattern, const char *text) | ... | @@ -203,7 +207,8 @@ comp_false (const char *pattern, const char *text) |
203 | } | 207 | } |
204 | 208 | ||
205 | int | 209 | int |
206 | mu_sieve_match_part_checker (const char *name, mu_list_t tags, mu_list_t args) | 210 | mu_sieve_match_part_checker (mu_sieve_machine_t mach, |
211 | const char *name, mu_list_t tags, mu_list_t args) | ||
207 | { | 212 | { |
208 | mu_iterator_t itr; | 213 | mu_iterator_t itr; |
209 | mu_sieve_runtime_tag_t *match = NULL; | 214 | mu_sieve_runtime_tag_t *match = NULL; |
... | @@ -233,9 +238,10 @@ mu_sieve_match_part_checker (const char *name, mu_list_t tags, mu_list_t args) | ... | @@ -233,9 +238,10 @@ mu_sieve_match_part_checker (const char *name, mu_list_t tags, mu_list_t args) |
233 | { | 238 | { |
234 | if (match) | 239 | if (match) |
235 | { | 240 | { |
236 | mu_sv_compile_error (&mu_sieve_locus, | 241 | mu_diag_at_locus (MU_LOG_ERROR, &mach->locus, |
237 | _("match type specified twice in call to `%s'"), | 242 | _("match type specified twice in call to `%s'"), |
238 | name); | 243 | name); |
244 | mu_i_sv_error (mach); | ||
239 | err = 1; | 245 | err = 1; |
240 | } | 246 | } |
241 | else | 247 | else |
... | @@ -269,13 +275,14 @@ mu_sieve_match_part_checker (const char *name, mu_list_t tags, mu_list_t args) | ... | @@ -269,13 +275,14 @@ mu_sieve_match_part_checker (const char *name, mu_list_t tags, mu_list_t args) |
269 | 275 | ||
270 | if (comp && strcmp (comp->arg->v.string, "i;ascii-numeric")) | 276 | if (comp && strcmp (comp->arg->v.string, "i;ascii-numeric")) |
271 | { | 277 | { |
272 | mu_sv_compile_error (&mu_sieve_locus, | 278 | mu_diag_at_locus (MU_LOG_ERROR, &mach->locus, |
273 | /* TRANSLATORS: Do not translate ':count'. | 279 | /* TRANSLATORS: Do not translate ':count'. |
274 | It is the name of a Sieve tag */ | 280 | It is the name of a Sieve tag */ |
275 | _("comparator %s is incompatible with " | 281 | _("comparator %s is incompatible with " |
276 | ":count in call to `%s'"), | 282 | ":count in call to `%s'"), |
277 | comp->arg->v.string, | 283 | comp->arg->v.string, |
278 | name); | 284 | name); |
285 | mu_i_sv_error (mach); | ||
279 | return 1; | 286 | return 1; |
280 | } | 287 | } |
281 | 288 | ||
... | @@ -288,16 +295,18 @@ mu_sieve_match_part_checker (const char *name, mu_list_t tags, mu_list_t args) | ... | @@ -288,16 +295,18 @@ mu_sieve_match_part_checker (const char *name, mu_list_t tags, mu_list_t args) |
288 | mu_list_count (val->v.list, &count); | 295 | mu_list_count (val->v.list, &count); |
289 | if (count > 1) | 296 | if (count > 1) |
290 | { | 297 | { |
291 | mu_sv_compile_error (&mu_sieve_locus, | 298 | mu_diag_at_locus (MU_LOG_ERROR, &mach->locus, |
292 | _("second argument must be a list of one element")); | 299 | _("second argument must be a list of one element")); |
300 | mu_i_sv_error (mach); | ||
293 | return 1; | 301 | return 1; |
294 | } | 302 | } |
295 | mu_list_get (val->v.list, 0, (void **) &str); | 303 | mu_list_get (val->v.list, 0, (void **) &str); |
296 | count = strtoul (str, &str, 10); | 304 | count = strtoul (str, &str, 10); |
297 | if (*str) | 305 | if (*str) |
298 | { | 306 | { |
299 | mu_sv_compile_error (&mu_sieve_locus, | 307 | mu_diag_at_locus (MU_LOG_ERROR, &mach->locus, |
300 | _("second argument cannot be converted to number")); | 308 | _("second argument cannot be converted to number")); |
309 | mu_i_sv_error (mach); | ||
301 | return 1; | 310 | return 1; |
302 | } | 311 | } |
303 | } | 312 | } |
... | @@ -306,9 +315,10 @@ mu_sieve_match_part_checker (const char *name, mu_list_t tags, mu_list_t args) | ... | @@ -306,9 +315,10 @@ mu_sieve_match_part_checker (const char *name, mu_list_t tags, mu_list_t args) |
306 | 315 | ||
307 | if (mu_sieve_str_to_relcmp (str, NULL, NULL)) | 316 | if (mu_sieve_str_to_relcmp (str, NULL, NULL)) |
308 | { | 317 | { |
309 | mu_sv_compile_error (&mu_sieve_locus, | 318 | mu_diag_at_locus (MU_LOG_ERROR, &mach->locus, |
310 | _("invalid relational match `%s' in call to `%s'"), | 319 | _("invalid relational match `%s' in call to `%s'"), |
311 | str, name); | 320 | str, name); |
321 | mu_i_sv_error (mach); | ||
312 | return 1; | 322 | return 1; |
313 | } | 323 | } |
314 | } | 324 | } |
... | @@ -316,18 +326,18 @@ mu_sieve_match_part_checker (const char *name, mu_list_t tags, mu_list_t args) | ... | @@ -316,18 +326,18 @@ mu_sieve_match_part_checker (const char *name, mu_list_t tags, mu_list_t args) |
316 | if (!compfun) | 326 | if (!compfun) |
317 | { | 327 | { |
318 | compname = comp ? comp->arg->v.string : "i;ascii-casemap"; | 328 | compname = comp ? comp->arg->v.string : "i;ascii-casemap"; |
319 | compfun = mu_sieve_comparator_lookup (mu_sieve_machine, compname, | 329 | compfun = mu_sieve_comparator_lookup (mach, compname, matchtype); |
320 | matchtype); | ||
321 | if (!compfun) | 330 | if (!compfun) |
322 | { | 331 | { |
323 | mu_sv_compile_error (&mu_sieve_locus, | 332 | mu_diag_at_locus (MU_LOG_ERROR, &mach->locus, |
324 | _("comparator `%s' is incompatible with match type `%s' in call to `%s'"), | 333 | _("comparator `%s' is incompatible with match type `%s' in call to `%s'"), |
325 | compname, match ? match->tag : "is", name); | 334 | compname, match ? match->tag : "is", name); |
335 | mu_i_sv_error (mach); | ||
326 | return 1; | 336 | return 1; |
327 | } | 337 | } |
328 | } | 338 | } |
329 | 339 | ||
330 | tmp = mu_sieve_malloc (mu_sieve_machine, sizeof (*tmp)); | 340 | tmp = mu_sieve_malloc (mach, sizeof (*tmp)); |
331 | tmp->tag = TAG_COMPFUN; | 341 | tmp->tag = TAG_COMPFUN; |
332 | tmp->arg = mu_sieve_value_create (SVT_POINTER, compfun); | 342 | tmp->arg = mu_sieve_value_create (SVT_POINTER, compfun); |
333 | mu_list_append (tags, tmp); | 343 | mu_list_append (tags, tmp); |
... | @@ -343,6 +353,7 @@ mu_sieve_match_part_checker (const char *name, mu_list_t tags, mu_list_t args) | ... | @@ -343,6 +353,7 @@ mu_sieve_match_part_checker (const char *name, mu_list_t tags, mu_list_t args) |
343 | if (mu_list_get (args, 1, (void**)&val)) | 353 | if (mu_list_get (args, 1, (void**)&val)) |
344 | return 0; | 354 | return 0; |
345 | 355 | ||
356 | rd.mach = mach; | ||
346 | rd.flags = REG_EXTENDED; | 357 | rd.flags = REG_EXTENDED; |
347 | if (strcmp (compname, "i;ascii-casemap") == 0) | 358 | if (strcmp (compname, "i;ascii-casemap") == 0) |
348 | rd.flags |= REG_ICASE; | 359 | rd.flags |= REG_ICASE; |
... | @@ -351,8 +362,7 @@ mu_sieve_match_part_checker (const char *name, mu_list_t tags, mu_list_t args) | ... | @@ -351,8 +362,7 @@ mu_sieve_match_part_checker (const char *name, mu_list_t tags, mu_list_t args) |
351 | 362 | ||
352 | rc = mu_sieve_vlist_do (val, _regex_compile, &rd); | 363 | rc = mu_sieve_vlist_do (val, _regex_compile, &rd); |
353 | 364 | ||
354 | mu_sieve_machine_add_destructor (mu_sieve_machine, _free_reglist, | 365 | mu_sieve_machine_add_destructor (rd.mach, _free_reglist, rd.list); |
355 | rd.list); | ||
356 | 366 | ||
357 | if (rc) | 367 | if (rc) |
358 | return rc; | 368 | return rc; | ... | ... |
This diff is collapsed.
Click to expand it.
... | @@ -27,7 +27,7 @@ | ... | @@ -27,7 +27,7 @@ |
27 | #include <sieve-priv.h> | 27 | #include <sieve-priv.h> |
28 | 28 | ||
29 | void | 29 | void |
30 | mu_sieve_require (mu_list_t slist) | 30 | mu_sieve_require (mu_sieve_machine_t mach, mu_list_t slist) |
31 | { | 31 | { |
32 | int status; | 32 | int status; |
33 | mu_iterator_t itr; | 33 | mu_iterator_t itr; |
... | @@ -35,9 +35,10 @@ mu_sieve_require (mu_list_t slist) | ... | @@ -35,9 +35,10 @@ mu_sieve_require (mu_list_t slist) |
35 | status = mu_list_get_iterator (slist, &itr); | 35 | status = mu_list_get_iterator (slist, &itr); |
36 | if (status) | 36 | if (status) |
37 | { | 37 | { |
38 | mu_sv_compile_error (&mu_sieve_locus, | 38 | mu_diag_at_locus (MU_LOG_ERROR, &mach->locus, |
39 | _("cannot create iterator: %s"), | 39 | _("cannot create iterator: %s"), |
40 | mu_strerror (status)); | 40 | mu_strerror (status)); |
41 | mu_i_sv_error (mach); | ||
41 | return; | 42 | return; |
42 | } | 43 | } |
43 | 44 | ||
... | @@ -73,12 +74,12 @@ mu_sieve_require (mu_list_t slist) | ... | @@ -73,12 +74,12 @@ mu_sieve_require (mu_list_t slist) |
73 | text = _("required action"); | 74 | text = _("required action"); |
74 | } | 75 | } |
75 | 76 | ||
76 | if (reqfn (mu_sieve_machine, name)) | 77 | if (reqfn (mach, name)) |
77 | { | 78 | { |
78 | mu_sv_compile_error (&mu_sieve_locus, | 79 | mu_diag_at_locus (MU_LOG_ERROR, &mach->locus, |
79 | _("source for the %s %s is not available"), | 80 | _("source for the %s %s is not available"), |
80 | text, | 81 | text, name); |
81 | name); | 82 | mu_i_sv_error (mach); |
82 | } | 83 | } |
83 | } | 84 | } |
84 | mu_iterator_destroy (&itr); | 85 | mu_iterator_destroy (&itr); | ... | ... |
... | @@ -339,6 +339,10 @@ mu_sieve_mailbox (mu_sieve_machine_t mach, mu_mailbox_t mbox) | ... | @@ -339,6 +339,10 @@ mu_sieve_mailbox (mu_sieve_machine_t mach, mu_mailbox_t mbox) |
339 | if (!mach || !mbox) | 339 | if (!mach || !mbox) |
340 | return EINVAL; | 340 | return EINVAL; |
341 | 341 | ||
342 | if (mach->state != mu_sieve_state_compiled) | ||
343 | return EINVAL; /* FIXME: Error code */ | ||
344 | mach->state = mu_sieve_state_running; | ||
345 | |||
342 | mu_observer_create (&observer, mach); | 346 | mu_observer_create (&observer, mach); |
343 | mu_observer_set_action (observer, _sieve_action, mach); | 347 | mu_observer_set_action (observer, _sieve_action, mach); |
344 | mu_mailbox_get_observable (mbox, &observable); | 348 | mu_mailbox_get_observable (mbox, &observable); |
... | @@ -353,6 +357,7 @@ mu_sieve_mailbox (mu_sieve_machine_t mach, mu_mailbox_t mbox) | ... | @@ -353,6 +357,7 @@ mu_sieve_mailbox (mu_sieve_machine_t mach, mu_mailbox_t mbox) |
353 | mu_observable_detach (observable, observer); | 357 | mu_observable_detach (observable, observer); |
354 | mu_observer_destroy (&observer, mach); | 358 | mu_observer_destroy (&observer, mach); |
355 | 359 | ||
360 | mach->state = mu_sieve_state_compiled; | ||
356 | mach->mailbox = NULL; | 361 | mach->mailbox = NULL; |
357 | 362 | ||
358 | return rc; | 363 | return rc; |
... | @@ -366,10 +371,15 @@ mu_sieve_message (mu_sieve_machine_t mach, mu_message_t msg) | ... | @@ -366,10 +371,15 @@ mu_sieve_message (mu_sieve_machine_t mach, mu_message_t msg) |
366 | if (!mach || !msg) | 371 | if (!mach || !msg) |
367 | return EINVAL; | 372 | return EINVAL; |
368 | 373 | ||
374 | if (mach->state != mu_sieve_state_compiled) | ||
375 | return EINVAL; /* FIXME: Error code */ | ||
376 | mach->state = mu_sieve_state_running; | ||
377 | |||
369 | mach->msgno = 1; | 378 | mach->msgno = 1; |
370 | mach->msg = msg; | 379 | mach->msg = msg; |
371 | mach->mailbox = NULL; | 380 | mach->mailbox = NULL; |
372 | rc = sieve_run (mach); | 381 | rc = sieve_run (mach); |
382 | mach->state = mu_sieve_state_compiled; | ||
373 | mach->msg = NULL; | 383 | mach->msg = NULL; |
374 | 384 | ||
375 | return rc; | 385 | return rc; | ... | ... |
... | @@ -31,20 +31,38 @@ typedef union | ... | @@ -31,20 +31,38 @@ typedef union |
31 | mu_sieve_value_t *val; | 31 | mu_sieve_value_t *val; |
32 | mu_list_t list; | 32 | mu_list_t list; |
33 | long number; | 33 | long number; |
34 | const char *string; | ||
35 | size_t pc; | 34 | size_t pc; |
36 | size_t line; | 35 | size_t line; |
36 | int inum; | ||
37 | char *string; | ||
37 | } sieve_op_t; | 38 | } sieve_op_t; |
38 | 39 | ||
40 | struct mu_locus_range | ||
41 | { | ||
42 | struct mu_locus beg; | ||
43 | struct mu_locus end; | ||
44 | }; | ||
45 | |||
46 | #define YYLTYPE struct mu_locus_range | ||
47 | |||
48 | enum mu_sieve_state | ||
49 | { | ||
50 | mu_sieve_state_init, | ||
51 | mu_sieve_state_error, | ||
52 | mu_sieve_state_compiled, | ||
53 | mu_sieve_state_running | ||
54 | }; | ||
55 | |||
39 | struct mu_sieve_machine | 56 | struct mu_sieve_machine |
40 | { | 57 | { |
41 | /* Static data */ | 58 | /* Static data */ |
42 | struct mu_locus locus; /* Approximate location in the code */ | 59 | struct mu_locus locus; /* Approximate location in the code */ |
43 | 60 | ||
44 | mu_list_t memory_pool; /* Pool of allocated memory objects */ | 61 | mu_list_t memory_pool; /* Pool of allocated memory objects */ |
45 | mu_list_t destr_list; /* List of destructor functions */ | 62 | mu_list_t destr_list; /* List of destructor functions */ |
46 | 63 | ||
47 | /* Symbol space: */ | 64 | /* Symbol space: */ |
65 | mu_opool_t string_pool; /* String constants */ | ||
48 | mu_list_t test_list; /* Tests */ | 66 | mu_list_t test_list; /* Tests */ |
49 | mu_list_t action_list; /* Actions */ | 67 | mu_list_t action_list; /* Actions */ |
50 | mu_list_t comp_list; /* Comparators */ | 68 | mu_list_t comp_list; /* Comparators */ |
... | @@ -54,6 +72,7 @@ struct mu_sieve_machine | ... | @@ -54,6 +72,7 @@ struct mu_sieve_machine |
54 | sieve_op_t *prog; /* Compiled program */ | 72 | sieve_op_t *prog; /* Compiled program */ |
55 | 73 | ||
56 | /* Runtime data */ | 74 | /* Runtime data */ |
75 | enum mu_sieve_state state; | ||
57 | size_t pc; /* Current program counter */ | 76 | size_t pc; /* Current program counter */ |
58 | long reg; /* Numeric register */ | 77 | long reg; /* Numeric register */ |
59 | mu_list_t stack; /* Runtime stack */ | 78 | mu_list_t stack; /* Runtime stack */ |
... | @@ -76,43 +95,68 @@ struct mu_sieve_machine | ... | @@ -76,43 +95,68 @@ struct mu_sieve_machine |
76 | char *daemon_email; | 95 | char *daemon_email; |
77 | void *data; | 96 | void *data; |
78 | }; | 97 | }; |
98 | |||
99 | enum mu_sieve_node_type | ||
100 | { | ||
101 | mu_sieve_node_noop, | ||
102 | mu_sieve_node_false, | ||
103 | mu_sieve_node_true, | ||
104 | mu_sieve_node_test, | ||
105 | mu_sieve_node_action, | ||
106 | mu_sieve_node_cond, | ||
107 | mu_sieve_node_anyof, | ||
108 | mu_sieve_node_allof, | ||
109 | mu_sieve_node_not, | ||
110 | }; | ||
111 | |||
112 | struct mu_sieve_node | ||
113 | { | ||
114 | struct mu_sieve_node *prev, *next; | ||
115 | enum mu_sieve_node_type type; | ||
116 | struct mu_locus_range locus; | ||
117 | union | ||
118 | { | ||
119 | mu_sieve_value_t *value; | ||
120 | mu_list_t list; | ||
121 | struct mu_sieve_node *node; | ||
122 | struct | ||
123 | { | ||
124 | struct mu_sieve_node *expr; | ||
125 | struct mu_sieve_node *iftrue; | ||
126 | struct mu_sieve_node *iffalse; | ||
127 | } cond; | ||
128 | struct | ||
129 | { | ||
130 | mu_sieve_register_t *reg; | ||
131 | mu_list_t arg; | ||
132 | } command; | ||
133 | } v; | ||
134 | }; | ||
135 | |||
136 | int mu_sieve_yyerror (const char *s); | ||
137 | int mu_sieve_yylex (void); | ||
79 | 138 | ||
80 | extern struct mu_locus mu_sieve_locus; | 139 | int mu_i_sv_lex_begin (const char *name); |
140 | int mu_i_sv_lex_begin_string (const char *buf, int bufsize, | ||
141 | const char *fname, int line); | ||
142 | void mu_i_sv_lex_finish (struct mu_sieve_machine *mach); | ||
143 | |||
81 | extern mu_sieve_machine_t mu_sieve_machine; | 144 | extern mu_sieve_machine_t mu_sieve_machine; |
82 | extern int mu_sieve_error_count; | ||
83 | 145 | ||
84 | #define TAG_COMPFUN "__compfun__" | 146 | #define TAG_COMPFUN "__compfun__" |
85 | #define TAG_RELFUN "__relfun__" | ||
86 | |||
87 | void mu_sv_compile_error (struct mu_locus *locus, | ||
88 | const char *fmt, ...) MU_PRINTFLIKE(2,3); | ||
89 | void mu_sv_print_value_list (mu_list_t list, mu_stream_t str); | ||
90 | void mu_sv_print_tag_list (mu_list_t list, mu_stream_t str); | ||
91 | 147 | ||
92 | int mu_sv_lex_begin (const char *name); | 148 | int mu_i_sv_code (struct mu_sieve_machine *mach, sieve_op_t op); |
93 | int mu_sv_lex_begin_string (const char *buf, int bufsize, | ||
94 | const char *fname, int line); | ||
95 | void mu_sv_lex_finish (void); | ||
96 | int mu_sieve_yyerror (const char *s); | ||
97 | int mu_sieve_yylex (); | ||
98 | 149 | ||
99 | void mu_sv_register_standard_actions (mu_sieve_machine_t mach); | 150 | void mu_i_sv_compile_error (struct mu_sieve_machine *mach, |
100 | void mu_sv_register_standard_tests (mu_sieve_machine_t mach); | 151 | const char *fmt, ...) MU_PRINTFLIKE(2,3); |
101 | void mu_sv_register_standard_comparators (mu_sieve_machine_t mach); | ||
102 | 152 | ||
103 | int mu_sv_code (sieve_op_t *op); | 153 | int mu_i_sv_locus (struct mu_sieve_machine *mach, struct mu_locus_range *lr); |
104 | int mu_sv_code_instr (sieve_instr_t instr); | 154 | int mu_i_sv_code_action (struct mu_sieve_machine *mach, |
105 | int mu_sv_code_handler (mu_sieve_handler_t handler); | 155 | mu_sieve_register_t *reg, mu_list_t arglist); |
106 | int mu_sv_code_list (mu_list_t list); | 156 | int mu_i_sv_code_test (struct mu_sieve_machine *mach, |
107 | int mu_sv_code_number (long num); | 157 | mu_sieve_register_t *reg, mu_list_t arglist); |
108 | int mu_sv_code_test (mu_sieve_register_t *reg, mu_list_t arglist); | ||
109 | int mu_sv_code_action (mu_sieve_register_t *reg, mu_list_t arglist); | ||
110 | void mu_sv_code_anyof (size_t start); | ||
111 | void mu_sv_code_allof (size_t start); | ||
112 | int mu_sv_code_source (const char *name); | ||
113 | int mu_sv_code_line (size_t line); | ||
114 | void mu_sv_change_source (void); | ||
115 | 158 | ||
159 | /* Opcodes */ | ||
116 | void _mu_sv_instr_action (mu_sieve_machine_t mach); | 160 | void _mu_sv_instr_action (mu_sieve_machine_t mach); |
117 | void _mu_sv_instr_test (mu_sieve_machine_t mach); | 161 | void _mu_sv_instr_test (mu_sieve_machine_t mach); |
118 | void _mu_sv_instr_push (mu_sieve_machine_t mach); | 162 | void _mu_sv_instr_push (mu_sieve_machine_t mach); |
... | @@ -126,4 +170,13 @@ void _mu_sv_instr_source (mu_sieve_machine_t mach); | ... | @@ -126,4 +170,13 @@ void _mu_sv_instr_source (mu_sieve_machine_t mach); |
126 | void _mu_sv_instr_line (mu_sieve_machine_t mach); | 170 | void _mu_sv_instr_line (mu_sieve_machine_t mach); |
127 | 171 | ||
128 | int mu_sv_load_add_dir (mu_sieve_machine_t mach, const char *name); | 172 | int mu_sv_load_add_dir (mu_sieve_machine_t mach, const char *name); |
129 | 173 | ||
174 | void mu_sv_register_standard_actions (mu_sieve_machine_t mach); | ||
175 | void mu_sv_register_standard_tests (mu_sieve_machine_t mach); | ||
176 | void mu_sv_register_standard_comparators (mu_sieve_machine_t mach); | ||
177 | |||
178 | void mu_sv_print_value_list (mu_list_t list, mu_stream_t str); | ||
179 | void mu_sv_print_tag_list (mu_list_t list, mu_stream_t str); | ||
180 | |||
181 | void mu_i_sv_error (mu_sieve_machine_t mach); | ||
182 | ... | ... |
... | @@ -35,10 +35,6 @@ | ... | @@ -35,10 +35,6 @@ |
35 | #include <sieve-priv.h> | 35 | #include <sieve-priv.h> |
36 | #include <sieve-gram.h> | 36 | #include <sieve-gram.h> |
37 | 37 | ||
38 | struct mu_locus mu_sieve_locus; | ||
39 | ino_t sieve_source_inode; | ||
40 | |||
41 | static mu_list_t string_list; | ||
42 | static char *multiline_delimiter; | 38 | static char *multiline_delimiter; |
43 | static int strip_tabs; | 39 | static int strip_tabs; |
44 | 40 | ||
... | @@ -57,6 +53,11 @@ static void sieve_searchpath (void); | ... | @@ -57,6 +53,11 @@ static void sieve_searchpath (void); |
57 | static char *str_unescape (char *text, size_t len); | 53 | static char *str_unescape (char *text, size_t len); |
58 | static int isemptystr (char *text); | 54 | static int isemptystr (char *text); |
59 | 55 | ||
56 | static ino_t sieve_source_inode; | ||
57 | struct mu_locus mu_sieve_locus; | ||
58 | static int newline; | ||
59 | static mu_list_t file_names; | ||
60 | |||
60 | static mu_stream_t input_stream; | 61 | static mu_stream_t input_stream; |
61 | 62 | ||
62 | static int | 63 | static int |
... | @@ -89,6 +90,61 @@ fillbuf (char *buf, size_t max_size) | ... | @@ -89,6 +90,61 @@ fillbuf (char *buf, size_t max_size) |
89 | yy_switch_to_buffer (s); \ | 90 | yy_switch_to_buffer (s); \ |
90 | } while (0) | 91 | } while (0) |
91 | 92 | ||
93 | static int | ||
94 | file_name_cmp (const void *a, const void *b) | ||
95 | { | ||
96 | return strcmp (a, b); | ||
97 | } | ||
98 | |||
99 | static void | ||
100 | init_locus (char const *name, ino_t ino) | ||
101 | { | ||
102 | mu_sieve_locus.mu_file = NULL; | ||
103 | if (name) | ||
104 | { | ||
105 | if (!file_names) | ||
106 | { | ||
107 | mu_list_create (&file_names); | ||
108 | mu_list_set_comparator (file_names, file_name_cmp); | ||
109 | mu_list_set_destroy_item (file_names, mu_list_free_item); | ||
110 | } | ||
111 | else | ||
112 | { | ||
113 | mu_list_locate (file_names, (void*) name, | ||
114 | (void**) &mu_sieve_locus.mu_file); | ||
115 | } | ||
116 | if (!mu_sieve_locus.mu_file) | ||
117 | { | ||
118 | mu_sieve_locus.mu_file = strdup (name);//FIXME: Error checking | ||
119 | mu_list_append (file_names, mu_sieve_locus.mu_file); | ||
120 | } | ||
121 | } | ||
122 | mu_sieve_locus.mu_line = 1; | ||
123 | mu_sieve_locus.mu_col = 0; | ||
124 | newline = 0; | ||
125 | sieve_source_inode = ino; | ||
126 | } | ||
127 | |||
128 | static void | ||
129 | advance_locus (void) | ||
130 | { | ||
131 | if (newline) | ||
132 | { | ||
133 | mu_sieve_locus.mu_line++; | ||
134 | mu_sieve_locus.mu_col = 0; | ||
135 | yylloc.beg = yylloc.end = mu_sieve_locus; | ||
136 | } | ||
137 | else | ||
138 | { | ||
139 | mu_sieve_locus.mu_col += yyleng; | ||
140 | yylloc.beg = yylloc.end = mu_sieve_locus; | ||
141 | yylloc.beg.mu_col -= yyleng; | ||
142 | } | ||
143 | newline = yytext[yyleng-1] == '\n'; | ||
144 | } | ||
145 | |||
146 | #define YY_USER_ACTION advance_locus (); | ||
147 | |||
92 | struct buffer_ctx | 148 | struct buffer_ctx |
93 | { | 149 | { |
94 | struct buffer_ctx *prev; | 150 | struct buffer_ctx *prev; |
... | @@ -125,8 +181,9 @@ push_source (const char *name) | ... | @@ -125,8 +181,9 @@ push_source (const char *name) |
125 | 181 | ||
126 | if (stat (name, &st)) | 182 | if (stat (name, &st)) |
127 | { | 183 | { |
128 | mu_sv_compile_error (&mu_sieve_locus, | 184 | mu_diag_at_locus (MU_LOG_ERROR, &mu_sieve_locus, |
129 | _("cannot stat `%s': %s"), name, strerror (errno)); | 185 | _("cannot stat `%s': %s"), name, strerror (errno)); |
186 | mu_i_sv_error (mu_sieve_machine); | ||
130 | return 1; | 187 | return 1; |
131 | } | 188 | } |
132 | 189 | ||
... | @@ -139,28 +196,36 @@ push_source (const char *name) | ... | @@ -139,28 +196,36 @@ push_source (const char *name) |
139 | { | 196 | { |
140 | yyerror (_("recursive inclusion")); | 197 | yyerror (_("recursive inclusion")); |
141 | if (ctx->prev) | 198 | if (ctx->prev) |
142 | mu_sv_compile_error (&ctx->prev->locus, | 199 | { |
143 | _("`%s' already included here"), | 200 | mu_diag_at_locus (MU_LOG_ERROR, &ctx->prev->locus, |
144 | name); | 201 | _("`%s' already included here"), |
202 | name); | ||
203 | mu_i_sv_error (mu_sieve_machine); | ||
204 | } | ||
145 | else | 205 | else |
146 | mu_sv_compile_error (&mu_sieve_locus, | 206 | { |
147 | _("`%s' already included at top level"), | 207 | mu_diag_at_locus (MU_LOG_ERROR, &mu_sieve_locus, |
148 | name); | 208 | _("`%s' already included at top level"), |
209 | name); | ||
210 | mu_i_sv_error (mu_sieve_machine); | ||
211 | } | ||
149 | return 1; | 212 | return 1; |
150 | } | 213 | } |
151 | 214 | ||
152 | rc = mu_file_stream_create (&stream, name, MU_STREAM_READ); | 215 | rc = mu_file_stream_create (&stream, name, MU_STREAM_READ); |
153 | if (rc) | 216 | if (rc) |
154 | { | 217 | { |
155 | mu_sv_compile_error (&mu_sieve_locus, | 218 | mu_diag_at_locus (MU_LOG_ERROR, &mu_sieve_locus, |
156 | _("cannot open file `%s': %s"), | 219 | _("cannot open file `%s': %s"), |
157 | name, mu_strerror (rc)); | 220 | name, mu_strerror (rc)); |
221 | mu_i_sv_error (mu_sieve_machine); | ||
158 | return 1; | 222 | return 1; |
159 | } | 223 | } |
160 | 224 | ||
161 | /* Push current context */ | 225 | /* Push current context */ |
162 | if (mu_sieve_locus.mu_file) | 226 | if (mu_sieve_locus.mu_file) |
163 | { | 227 | { |
228 | advance_locus (); | ||
164 | ctx = mu_sieve_alloc (sizeof (*ctx)); | 229 | ctx = mu_sieve_alloc (sizeof (*ctx)); |
165 | ctx->locus = mu_sieve_locus; | 230 | ctx->locus = mu_sieve_locus; |
166 | ctx->i_node = sieve_source_inode; | 231 | ctx->i_node = sieve_source_inode; |
... | @@ -172,14 +237,9 @@ push_source (const char *name) | ... | @@ -172,14 +237,9 @@ push_source (const char *name) |
172 | SET_BUFFER_STATE (ctx->state); | 237 | SET_BUFFER_STATE (ctx->state); |
173 | } | 238 | } |
174 | input_stream = stream; | 239 | input_stream = stream; |
175 | |||
176 | mu_sieve_locus.mu_file = strdup (name); | ||
177 | mu_sieve_locus.mu_line = 1; | ||
178 | mu_sieve_locus.mu_col = 0; /* FIXME: not used */ | ||
179 | sieve_source_inode = st.st_ino; | ||
180 | 240 | ||
181 | mu_sv_change_source (); | 241 | init_locus (name, st.st_ino); |
182 | 242 | ||
183 | return 0; | 243 | return 0; |
184 | } | 244 | } |
185 | 245 | ||
... | @@ -190,26 +250,21 @@ pop_source () | ... | @@ -190,26 +250,21 @@ pop_source () |
190 | 250 | ||
191 | mu_stream_destroy (&input_stream); | 251 | mu_stream_destroy (&input_stream); |
192 | 252 | ||
193 | if (mu_sieve_locus.mu_file) | ||
194 | free (mu_sieve_locus.mu_file); | ||
195 | if (!context_stack) | 253 | if (!context_stack) |
196 | { | 254 | { |
197 | input_stream = NULL; | 255 | input_stream = NULL; |
198 | mu_sieve_locus.mu_file = NULL; | 256 | init_locus (NULL, 0); |
199 | return 1; | 257 | return 1; |
200 | } | 258 | } |
201 | /* Restore previous context */ | 259 | /* Restore previous context */ |
202 | input_stream = context_stack->input; | 260 | input_stream = context_stack->input; |
203 | mu_sieve_locus = context_stack->locus; | 261 | mu_sieve_locus = context_stack->locus; |
204 | mu_sieve_locus.mu_line++; /* #include rule did not increment it */ | ||
205 | sieve_source_inode = context_stack->i_node; | 262 | sieve_source_inode = context_stack->i_node; |
206 | RESTORE_BUFFER_STATE (context_stack->state); | 263 | RESTORE_BUFFER_STATE (context_stack->state); |
207 | ctx = context_stack->prev; | 264 | ctx = context_stack->prev; |
208 | free (context_stack); | 265 | free (context_stack); |
209 | context_stack = ctx; | 266 | context_stack = ctx; |
210 | 267 | ||
211 | mu_sv_change_source (); | ||
212 | |||
213 | return 0; | 268 | return 0; |
214 | } | 269 | } |
215 | %} | 270 | %} |
... | @@ -225,16 +280,16 @@ SIZESUF [kKmMgG] | ... | @@ -225,16 +280,16 @@ SIZESUF [kKmMgG] |
225 | 280 | ||
226 | %% | 281 | %% |
227 | /* C-style comments */ | 282 | /* C-style comments */ |
228 | "/*" BEGIN(COMMENT); | 283 | "/*" { BEGIN(COMMENT); } |
229 | <COMMENT>[^*\n]* /* eat anything that's not a '*' */ | 284 | <COMMENT>[^*\n]* /* eat anything that's not a '*' */ |
230 | <COMMENT>"*"+[^*/\n]* /* eat up '*'s not followed by '/'s */ | 285 | <COMMENT>"*"+[^*/\n]* /* eat up '*'s not followed by '/'s */ |
231 | <COMMENT>\n ++mu_sieve_locus.mu_line; | 286 | <COMMENT>\n ; |
232 | <COMMENT>"*"+"/" BEGIN(INITIAL); | 287 | <COMMENT>"*"+"/" { BEGIN (INITIAL); } |
233 | /* Preprocessor directives (an extension) */ | 288 | /* Preprocessor directives (an extension) */ |
234 | #[ \t]*include.*\n { sieve_include (); } | 289 | #[ \t]*include.*\n { sieve_include (); } |
235 | #[ \t]*searchpath.*\n { sieve_searchpath (); } | 290 | #[ \t]*searchpath.*\n { sieve_searchpath (); } |
236 | /* End-of-line comments */ | 291 | /* End-of-line comments */ |
237 | #.*\n { mu_sieve_locus.mu_line++; } | 292 | #.*\n ; |
238 | #.* /* end-of-file comment */; | 293 | #.* /* end-of-file comment */; |
239 | /* Reserved words */ | 294 | /* Reserved words */ |
240 | require return REQUIRE; | 295 | require return REQUIRE; |
... | @@ -244,6 +299,8 @@ else return ELSE; | ... | @@ -244,6 +299,8 @@ else return ELSE; |
244 | anyof return ANYOF; | 299 | anyof return ANYOF; |
245 | allof return ALLOF; | 300 | allof return ALLOF; |
246 | not return NOT; | 301 | not return NOT; |
302 | false return FALSE; | ||
303 | true return TRUE; | ||
247 | /* Identifiers */ | 304 | /* Identifiers */ |
248 | {IDENT} { ident (yytext); return IDENT; } | 305 | {IDENT} { ident (yytext); return IDENT; } |
249 | :{IDENT} { ident (yytext + 1); return TAG; } | 306 | :{IDENT} { ident (yytext + 1); return TAG; } |
... | @@ -254,34 +311,28 @@ not return NOT; | ... | @@ -254,34 +311,28 @@ not return NOT; |
254 | /* Quoted strings */ | 311 | /* Quoted strings */ |
255 | \"[^\\"\n]*\" { return string (); } | 312 | \"[^\\"\n]*\" { return string (); } |
256 | \"[^\\"\n]*\\. { BEGIN(STR); | 313 | \"[^\\"\n]*\\. { BEGIN(STR); |
257 | line_begin (); | 314 | line_begin (); |
258 | line_add (str_unescape (yytext + 1, yyleng - 1), 0); } | 315 | line_add (str_unescape (yytext + 1, yyleng - 1), 0); } |
259 | <STR>[^\\"\n]*\\. { line_add (str_unescape (yytext, yyleng), 0); } | 316 | <STR>[^\\"\n]*\\. { line_add (str_unescape (yytext, yyleng), 0); } |
260 | <STR>[^\\"\n]*\" { BEGIN(INITIAL); | 317 | <STR>[^\\"\n]*\" { BEGIN(INITIAL); |
261 | if (yyleng > 1) | 318 | if (yyleng > 1) |
262 | line_add (yytext, yyleng - 1); | 319 | line_add (yytext, yyleng - 1); |
263 | line_finish (); | 320 | line_finish (); |
264 | return STRING; } | 321 | return STRING; } |
265 | /* Multiline strings */ | 322 | /* Multiline strings */ |
266 | text:-?[ \t]*#.*\n { BEGIN(ML); | 323 | text:-?[ \t]*#.*\n { BEGIN(ML); |
267 | multiline_begin (); | 324 | multiline_begin (); } |
268 | mu_sieve_locus.mu_line++; } | ||
269 | text:-?[ \t]*\n { BEGIN(ML); | 325 | text:-?[ \t]*\n { BEGIN(ML); |
270 | multiline_begin (); | 326 | multiline_begin (); } |
271 | mu_sieve_locus.mu_line++; } | 327 | text:-?\\?{IDENT}[ \t]*#.*\n { BEGIN(ML); |
272 | text:-?\\?{IDENT}[ \t]*#.*\n { BEGIN(ML); multiline_begin (); | 328 | multiline_begin (); } |
273 | mu_sieve_locus.mu_line++; } | 329 | text:-?\\?{IDENT}[ \t]*\n { BEGIN(ML); |
274 | text:-?\\?{IDENT}[ \t]*\n { BEGIN(ML); multiline_begin (); | 330 | multiline_begin (); } |
275 | mu_sieve_locus.mu_line++; } | ||
276 | <ML>#[ \t]*include.*\n { if (multiline_delimiter[0] == '\\') | 331 | <ML>#[ \t]*include.*\n { if (multiline_delimiter[0] == '\\') |
277 | { | 332 | multiline_add (NULL); |
278 | mu_sieve_locus.mu_line++; | ||
279 | multiline_add (NULL); | ||
280 | } | ||
281 | else | 333 | else |
282 | sieve_include (); } | 334 | sieve_include (); } |
283 | <ML>.*\n { char *p = multiline_strip_tabs (yytext); | 335 | <ML>.*\n { char *p = multiline_strip_tabs (yytext); |
284 | mu_sieve_locus.mu_line++; | ||
285 | 336 | ||
286 | if (strncmp (p, multiline_delimiter, strlen (multiline_delimiter)) | 337 | if (strncmp (p, multiline_delimiter, strlen (multiline_delimiter)) |
287 | == 0 | 338 | == 0 |
... | @@ -296,7 +347,7 @@ text:-?\\?{IDENT}[ \t]*\n { BEGIN(ML); multiline_begin (); | ... | @@ -296,7 +347,7 @@ text:-?\\?{IDENT}[ \t]*\n { BEGIN(ML); multiline_begin (); |
296 | multiline_add (NULL); } | 347 | multiline_add (NULL); } |
297 | {WS} ; | 348 | {WS} ; |
298 | /* Other tokens */ | 349 | /* Other tokens */ |
299 | \n { mu_sieve_locus.mu_line++; } | 350 | \n ; |
300 | . return yytext[0]; | 351 | . return yytext[0]; |
301 | 352 | ||
302 | %% | 353 | %% |
... | @@ -400,7 +451,7 @@ sieve_include () | ... | @@ -400,7 +451,7 @@ sieve_include () |
400 | } | 451 | } |
401 | 452 | ||
402 | static void | 453 | static void |
403 | sieve_searchpath () | 454 | sieve_searchpath (void) |
404 | { | 455 | { |
405 | char *p, *endp = yytext + yyleng, *name; | 456 | char *p, *endp = yytext + yyleng, *name; |
406 | 457 | ||
... | @@ -416,14 +467,14 @@ sieve_searchpath () | ... | @@ -416,14 +467,14 @@ sieve_searchpath () |
416 | } | 467 | } |
417 | 468 | ||
418 | int | 469 | int |
419 | mu_sv_lex_begin (const char *name) | 470 | mu_i_sv_lex_begin (const char *name) |
420 | { | 471 | { |
421 | return push_source (name); | 472 | return push_source (name); |
422 | } | 473 | } |
423 | 474 | ||
424 | int | 475 | int |
425 | mu_sv_lex_begin_string (const char *buf, int bufsize, | 476 | mu_i_sv_lex_begin_string (const char *buf, int bufsize, |
426 | const char *fname, int line) | 477 | const char *fname, int line) |
427 | { | 478 | { |
428 | int rc; | 479 | int rc; |
429 | 480 | ||
... | @@ -439,19 +490,18 @@ mu_sv_lex_begin_string (const char *buf, int bufsize, | ... | @@ -439,19 +490,18 @@ mu_sv_lex_begin_string (const char *buf, int bufsize, |
439 | return 1; | 490 | return 1; |
440 | } | 491 | } |
441 | 492 | ||
442 | mu_sieve_locus.mu_file = strdup (fname); | 493 | init_locus (fname, 0); |
443 | mu_sieve_locus.mu_line = line; | ||
444 | sieve_source_inode = 0; | ||
445 | 494 | ||
446 | mu_sv_change_source (); | ||
447 | return 0; | 495 | return 0; |
448 | } | 496 | } |
449 | 497 | ||
450 | void | 498 | void |
451 | mu_sv_lex_finish () | 499 | mu_i_sv_lex_finish (struct mu_sieve_machine *mach) |
452 | { | 500 | { |
453 | while (pop_source () == 0) | 501 | while (pop_source () == 0) |
454 | ; | 502 | ; |
503 | mach->source_list = file_names; | ||
504 | file_names = NULL; | ||
455 | } | 505 | } |
456 | 506 | ||
457 | static int | 507 | static int |
... | @@ -507,19 +557,7 @@ multiline_strip_tabs (char *text) | ... | @@ -507,19 +557,7 @@ multiline_strip_tabs (char *text) |
507 | static void | 557 | static void |
508 | line_add (char *text, size_t len) | 558 | line_add (char *text, size_t len) |
509 | { | 559 | { |
510 | char *s; | 560 | mu_opool_append (mu_sieve_machine->string_pool, text, len); |
511 | |||
512 | if (len == 0) | ||
513 | len = strlen (text); | ||
514 | s = malloc (len + 1); | ||
515 | if (!s) | ||
516 | { | ||
517 | yyerror (_("not enough memory")); | ||
518 | exit (1); | ||
519 | } | ||
520 | memcpy (s, text, len); | ||
521 | s[len] = 0; | ||
522 | mu_list_append (string_list, s); | ||
523 | } | 561 | } |
524 | 562 | ||
525 | static void | 563 | static void |
... | @@ -527,27 +565,17 @@ multiline_add (char *s) | ... | @@ -527,27 +565,17 @@ multiline_add (char *s) |
527 | { | 565 | { |
528 | if (!s) | 566 | if (!s) |
529 | s = multiline_strip_tabs (yytext); | 567 | s = multiline_strip_tabs (yytext); |
530 | line_add (s, 0); | 568 | mu_opool_appendz (mu_sieve_machine->string_pool, s); |
531 | } | 569 | } |
532 | 570 | ||
533 | static void | 571 | static void |
534 | line_begin () | 572 | line_begin (void) |
535 | { | 573 | { |
536 | int status; | 574 | /* nothing */ |
537 | |||
538 | if (string_list) | ||
539 | mu_sieve_slist_destroy (&string_list); | ||
540 | status = mu_list_create (&string_list); | ||
541 | if (status) | ||
542 | { | ||
543 | mu_sv_compile_error (&mu_sieve_locus, | ||
544 | "mu_list_create: %s", mu_strerror (status)); | ||
545 | exit (1); | ||
546 | } | ||
547 | } | 575 | } |
548 | 576 | ||
549 | static void | 577 | static void |
550 | multiline_begin () | 578 | multiline_begin (void) |
551 | { | 579 | { |
552 | char *p = yytext + 5; /* past the text: keyword */ | 580 | char *p = yytext + 5; /* past the text: keyword */ |
553 | 581 | ||
... | @@ -587,42 +615,14 @@ multiline_begin () | ... | @@ -587,42 +615,14 @@ multiline_begin () |
587 | } | 615 | } |
588 | 616 | ||
589 | static void | 617 | static void |
590 | line_finish () | 618 | line_finish (void) |
591 | { | 619 | { |
592 | mu_iterator_t itr; | 620 | mu_opool_append_char (mu_sieve_machine->string_pool, 0); |
593 | int length = 0; | 621 | yylval.string = mu_opool_finish (mu_sieve_machine->string_pool, NULL); |
594 | char *p; | ||
595 | |||
596 | if (!string_list || mu_list_get_iterator (string_list, &itr)) | ||
597 | return; | ||
598 | |||
599 | /* Count number of characters in the multiline */ | ||
600 | for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next (itr)) | ||
601 | { | ||
602 | char *s; | ||
603 | mu_iterator_current (itr, (void **)&s); | ||
604 | length += strlen (s); | ||
605 | } | ||
606 | |||
607 | /* Copy the contents */ | ||
608 | yylval.string = mu_sieve_malloc (mu_sieve_machine, length + 1); | ||
609 | p = yylval.string; | ||
610 | for (mu_iterator_first (itr); !mu_iterator_is_done (itr); | ||
611 | mu_iterator_next (itr)) | ||
612 | { | ||
613 | char *s; | ||
614 | mu_iterator_current (itr, (void **)&s); | ||
615 | strcpy (p, s); | ||
616 | p += strlen (s); | ||
617 | free (s); | ||
618 | } | ||
619 | *p = 0; | ||
620 | mu_iterator_destroy (&itr); | ||
621 | mu_list_destroy (&string_list); | ||
622 | } | 622 | } |
623 | 623 | ||
624 | static void | 624 | static void |
625 | multiline_finish () | 625 | multiline_finish (void) |
626 | { | 626 | { |
627 | line_finish (); | 627 | line_finish (); |
628 | } | 628 | } | ... | ... |
This diff is collapsed.
Click to expand it.
... | @@ -320,22 +320,6 @@ sieve_test_size (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags) | ... | @@ -320,22 +320,6 @@ sieve_test_size (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags) |
320 | } | 320 | } |
321 | 321 | ||
322 | int | 322 | int |
323 | sieve_test_true (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags) | ||
324 | { | ||
325 | if (mach->debug_level & MU_SIEVE_DEBUG_TRACE) | ||
326 | mu_sieve_debug (mach, "TRUE"); | ||
327 | return 1; | ||
328 | } | ||
329 | |||
330 | int | ||
331 | sieve_test_false (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags) | ||
332 | { | ||
333 | if (mach->debug_level & MU_SIEVE_DEBUG_TRACE) | ||
334 | mu_sieve_debug (mach, "FALSE"); | ||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | int | ||
339 | _test_exists (void *item, void *data) | 323 | _test_exists (void *item, void *data) |
340 | { | 324 | { |
341 | mu_header_t hdr = data; | 325 | mu_header_t hdr = data; |
... | @@ -446,8 +430,7 @@ mu_sieve_tag_group_t header_tag_groups[] = { | ... | @@ -446,8 +430,7 @@ mu_sieve_tag_group_t header_tag_groups[] = { |
446 | void | 430 | void |
447 | mu_sv_register_standard_tests (mu_sieve_machine_t mach) | 431 | mu_sv_register_standard_tests (mu_sieve_machine_t mach) |
448 | { | 432 | { |
449 | mu_sieve_register_test (mach, "false", sieve_test_false, NULL, NULL, 1); | 433 | /* true and false are built-ins */ |
450 | mu_sieve_register_test (mach, "true", sieve_test_true, NULL, NULL, 1); | ||
451 | mu_sieve_register_test (mach, "address", sieve_test_address, | 434 | mu_sieve_register_test (mach, "address", sieve_test_address, |
452 | address_req_args, address_tag_groups, 1); | 435 | address_req_args, address_tag_groups, 1); |
453 | mu_sieve_register_test (mach, "size", sieve_test_size, | 436 | mu_sieve_register_test (mach, "size", sieve_test_size, | ... | ... |
... | @@ -171,7 +171,7 @@ mu_sieve_value_create (mu_sieve_data_type type, void *data) | ... | @@ -171,7 +171,7 @@ mu_sieve_value_create (mu_sieve_data_type type, void *data) |
171 | break; | 171 | break; |
172 | 172 | ||
173 | default: | 173 | default: |
174 | mu_sv_compile_error (&mu_sieve_locus, _("invalid data type")); | 174 | mu_error ("%s", _("invalid data type")); |
175 | abort (); | 175 | abort (); |
176 | } | 176 | } |
177 | return val; | 177 | return val; |
... | @@ -186,24 +186,6 @@ mu_sieve_value_get (mu_list_t vlist, size_t index) | ... | @@ -186,24 +186,6 @@ mu_sieve_value_get (mu_list_t vlist, size_t index) |
186 | } | 186 | } |
187 | 187 | ||
188 | void | 188 | void |
189 | mu_sv_compile_error (struct mu_locus *ploc, const char *fmt, ...) | ||
190 | { | ||
191 | va_list ap; | ||
192 | |||
193 | va_start (ap, fmt); | ||
194 | mu_sieve_error_count++; | ||
195 | mu_stream_ioctl (mu_sieve_machine->errstream, | ||
196 | MU_IOCTL_LOGSTREAM, MU_IOCTL_LOGSTREAM_SET_LOCUS, | ||
197 | ploc); | ||
198 | mu_stream_printf (mu_sieve_machine->errstream, | ||
199 | "\033s<%d>\033O<%d>", | ||
200 | MU_LOG_ERROR, MU_LOGMODE_LOCUS); | ||
201 | mu_stream_vprintf (mu_sieve_machine->errstream, fmt, ap); | ||
202 | mu_stream_write (mu_sieve_machine->errstream, "\n", 1, NULL); | ||
203 | va_end (ap); | ||
204 | } | ||
205 | |||
206 | void | ||
207 | mu_sieve_error (mu_sieve_machine_t mach, const char *fmt, ...) | 189 | mu_sieve_error (mu_sieve_machine_t mach, const char *fmt, ...) |
208 | { | 190 | { |
209 | va_list ap; | 191 | va_list ap; | ... | ... |
... | @@ -83,7 +83,9 @@ set_debug_level (const char *arg) | ... | @@ -83,7 +83,9 @@ set_debug_level (const char *arg) |
83 | break; | 83 | break; |
84 | 84 | ||
85 | case 'g': | 85 | case 'g': |
86 | mu_sieve_yydebug = 1; | 86 | mu_debug_get_category_level (mu_sieve_debug_handle, &lev); |
87 | mu_debug_set_category_level (mu_sieve_debug_handle, | ||
88 | lev | MU_DEBUG_LEVEL_MASK(MU_DEBUG_TRACE1)); | ||
87 | break; | 89 | break; |
88 | 90 | ||
89 | case 't': | 91 | case 't': | ... | ... |
... | @@ -38,7 +38,7 @@ if header :comparator "i;ascii-numeric" :contains "X-Number" "15" | ... | @@ -38,7 +38,7 @@ if header :comparator "i;ascii-numeric" :contains "X-Number" "15" |
38 | discard; | 38 | discard; |
39 | } | 39 | } |
40 | ],[78],[], | 40 | ],[78],[], |
41 | [sieve: prog:5: comparator `i;ascii-numeric' is incompatible with match type `contains' in call to `header' | 41 | [sieve: prog:4:1: comparator `i;ascii-numeric' is incompatible with match type `contains' in call to `header' |
42 | ]) | 42 | ]) |
43 | AT_CLEANUP | 43 | AT_CLEANUP |
44 | 44 | ... | ... |
-
Please register or sign in to post a comment