Commit 15404d91 15404d914aec7e80c884fc63dbfa5d3e347b32cb by Sergey Poznyakoff

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.
1 parent a04c6feb
...@@ -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;
......
...@@ -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 }
......
...@@ -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
......