Try to display exact error locations in Sieve diagnostics
* include/mailutils/sieve.h (mu_sieve_value_t)<locus>: New field. * libmu_sieve/util.c (mu_sieve_value_create): Take a pointer to mu_locus_range. Use it to initialize the locus field. * libmu_sieve/sieve-gram.y: Pass loci in calls to mu_sieve_value_create. * libmu_sieve/actions.c: Use the most specific locus when displaying the message. * libmu_sieve/comparator.c: Likewise. * libmu_sieve/prog.c: Likewise. * libmu_sieve/variables.c: Likewise. * sieve/tests/i-numeric.at: Update the expected error location.
Showing
8 changed files
with
56 additions
and
26 deletions
... | @@ -88,6 +88,7 @@ typedef struct | ... | @@ -88,6 +88,7 @@ typedef struct |
88 | { | 88 | { |
89 | mu_sieve_data_type type; | 89 | mu_sieve_data_type type; |
90 | char *tag; | 90 | char *tag; |
91 | struct mu_locus_range locus; | ||
91 | union mu_sieve_value_storage v; | 92 | union mu_sieve_value_storage v; |
92 | } mu_sieve_value_t; | 93 | } mu_sieve_value_t; |
93 | 94 | ||
... | @@ -163,7 +164,9 @@ void mu_sieve_reclaim_default (void *p); | ... | @@ -163,7 +164,9 @@ void mu_sieve_reclaim_default (void *p); |
163 | void mu_sieve_reclaim_value (void *p); | 164 | void mu_sieve_reclaim_value (void *p); |
164 | 165 | ||
165 | size_t mu_sieve_value_create (mu_sieve_machine_t mach, | 166 | size_t mu_sieve_value_create (mu_sieve_machine_t mach, |
166 | mu_sieve_data_type type, void *data); | 167 | mu_sieve_data_type type, |
168 | struct mu_locus_range const *locus, | ||
169 | void *data); | ||
167 | 170 | ||
168 | /* Symbol space functions */ | 171 | /* Symbol space functions */ |
169 | mu_sieve_registry_t *mu_sieve_registry_add (mu_sieve_machine_t mach, | 172 | mu_sieve_registry_t *mu_sieve_registry_add (mu_sieve_machine_t mach, | ... | ... |
... | @@ -528,7 +528,7 @@ perms_tag_checker (mu_sieve_machine_t mach) | ... | @@ -528,7 +528,7 @@ perms_tag_checker (mu_sieve_machine_t mach) |
528 | { | 528 | { |
529 | if (mu_parse_stream_perm_string (&flag, t->v.string, &p)) | 529 | if (mu_parse_stream_perm_string (&flag, t->v.string, &p)) |
530 | { | 530 | { |
531 | mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus, | 531 | mu_diag_at_locus_range (MU_LOG_ERROR, &t->locus, |
532 | _("invalid permissions (near %s)"), p); | 532 | _("invalid permissions (near %s)"), p); |
533 | mu_i_sv_error (mach); | 533 | mu_i_sv_error (mach); |
534 | err = 1; | 534 | err = 1; | ... | ... |
... | @@ -174,7 +174,7 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach) | ... | @@ -174,7 +174,7 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach) |
174 | { | 174 | { |
175 | if (match) | 175 | if (match) |
176 | { | 176 | { |
177 | mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus, | 177 | mu_diag_at_locus_range (MU_LOG_ERROR, &t->locus, |
178 | _("match type specified twice in call to `%s'"), | 178 | _("match type specified twice in call to `%s'"), |
179 | mach->identifier); | 179 | mach->identifier); |
180 | mu_i_sv_error (mach); | 180 | mu_i_sv_error (mach); |
... | @@ -209,7 +209,7 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach) | ... | @@ -209,7 +209,7 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach) |
209 | 209 | ||
210 | if (compname && strcmp (compname, "i;ascii-numeric")) | 210 | if (compname && strcmp (compname, "i;ascii-numeric")) |
211 | { | 211 | { |
212 | mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus, | 212 | mu_diag_at_locus_range (MU_LOG_ERROR, &match->locus, |
213 | /* TRANSLATORS: Do not translate ':count'. | 213 | /* TRANSLATORS: Do not translate ':count'. |
214 | It is the name of a Sieve tag */ | 214 | It is the name of a Sieve tag */ |
215 | _("comparator %s is incompatible with " | 215 | _("comparator %s is incompatible with " |
... | @@ -235,7 +235,7 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach) | ... | @@ -235,7 +235,7 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach) |
235 | break; | 235 | break; |
236 | /* fall through */ | 236 | /* fall through */ |
237 | default: | 237 | default: |
238 | mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus, | 238 | mu_diag_at_locus_range (MU_LOG_ERROR, &val->locus, |
239 | _(":count requires second argument to be a list of one element")); | 239 | _(":count requires second argument to be a list of one element")); |
240 | mu_i_sv_error (mach); | 240 | mu_i_sv_error (mach); |
241 | return 1; | 241 | return 1; |
... | @@ -246,7 +246,7 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach) | ... | @@ -246,7 +246,7 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach) |
246 | char *p = mu_str_skip_class (argstr->orig, MU_CTYPE_DIGIT); | 246 | char *p = mu_str_skip_class (argstr->orig, MU_CTYPE_DIGIT); |
247 | if (*p) | 247 | if (*p) |
248 | { | 248 | { |
249 | mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus, | 249 | mu_diag_at_locus_range (MU_LOG_ERROR, &val->locus, |
250 | _("second argument cannot be converted to number")); | 250 | _("second argument cannot be converted to number")); |
251 | mu_i_sv_error (mach); | 251 | mu_i_sv_error (mach); |
252 | return 1; | 252 | return 1; |
... | @@ -258,7 +258,7 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach) | ... | @@ -258,7 +258,7 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach) |
258 | 258 | ||
259 | if (mu_sieve_str_to_relcmp (str, NULL, NULL)) | 259 | if (mu_sieve_str_to_relcmp (str, NULL, NULL)) |
260 | { | 260 | { |
261 | mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus, | 261 | mu_diag_at_locus_range (MU_LOG_ERROR, &match->locus, |
262 | _("invalid relational match `%s' in call to `%s'"), | 262 | _("invalid relational match `%s' in call to `%s'"), |
263 | str, mach->identifier); | 263 | str, mach->identifier); |
264 | mu_i_sv_error (mach); | 264 | mu_i_sv_error (mach); |
... | @@ -278,10 +278,16 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach) | ... | @@ -278,10 +278,16 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach) |
278 | compfun = mu_sieve_comparator_lookup (mach, compname, matchtype); | 278 | compfun = mu_sieve_comparator_lookup (mach, compname, matchtype); |
279 | if (!compfun) | 279 | if (!compfun) |
280 | { | 280 | { |
281 | mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus, | 281 | if (match) |
282 | mu_diag_at_locus_range (MU_LOG_ERROR, &match->locus, | ||
283 | _("comparator `%s' is incompatible with match type `%s' in call to `%s'"), | ||
284 | compname, match->tag, | ||
285 | mach->identifier); | ||
286 | else | ||
287 | mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus, | ||
282 | _("comparator `%s' is incompatible with match type `%s' in call to `%s'"), | 288 | _("comparator `%s' is incompatible with match type `%s' in call to `%s'"), |
283 | compname, match ? match->tag : "is", | 289 | compname, "is", |
284 | mach->identifier); | 290 | mach->identifier); |
285 | mu_i_sv_error (mach); | 291 | mu_i_sv_error (mach); |
286 | return 1; | 292 | return 1; |
287 | } | 293 | } | ... | ... |
... | @@ -171,7 +171,7 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach, | ... | @@ -171,7 +171,7 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach, |
171 | 171 | ||
172 | if (!tag) | 172 | if (!tag) |
173 | { | 173 | { |
174 | mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus, | 174 | mu_diag_at_locus_range (MU_LOG_ERROR, &val->locus, |
175 | _("invalid tag name `%s' for `%s'"), | 175 | _("invalid tag name `%s' for `%s'"), |
176 | val->v.string, reg->name); | 176 | val->v.string, reg->name); |
177 | mu_i_sv_error (mach); | 177 | mu_i_sv_error (mach); |
... | @@ -191,6 +191,7 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach, | ... | @@ -191,6 +191,7 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach, |
191 | { | 191 | { |
192 | if (i + 1 == node->v.command.argcount) | 192 | if (i + 1 == node->v.command.argcount) |
193 | { | 193 | { |
194 | /* FIXME: more exact locus */ | ||
194 | mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus, | 195 | mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus, |
195 | _("required argument for tag %s is missing"), | 196 | _("required argument for tag %s is missing"), |
196 | tag->name); | 197 | tag->name); |
... | @@ -208,11 +209,11 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach, | ... | @@ -208,11 +209,11 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach, |
208 | 209 | ||
209 | if (val->type != tag->argtype) | 210 | if (val->type != tag->argtype) |
210 | { | 211 | { |
211 | mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus, | 212 | mu_diag_at_locus_range (MU_LOG_ERROR, &val->locus, |
212 | _("type mismatch in argument to " | 213 | _("type mismatch in argument to " |
213 | "tag `%s'"), | 214 | "tag `%s'"), |
214 | tag->name); | 215 | tag->name); |
215 | mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus, | 216 | mu_diag_at_locus_range (MU_LOG_ERROR, &val->locus, |
216 | _("expected %s but passed %s"), | 217 | _("expected %s but passed %s"), |
217 | mu_sieve_type_str (tag->argtype), | 218 | mu_sieve_type_str (tag->argtype), |
218 | mu_sieve_type_str (val->type)); | 219 | mu_sieve_type_str (val->type)); |
... | @@ -274,11 +275,11 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach, | ... | @@ -274,11 +275,11 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach, |
274 | /* compatible types */; | 275 | /* compatible types */; |
275 | else | 276 | else |
276 | { | 277 | { |
277 | mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus, | 278 | mu_diag_at_locus_range (MU_LOG_ERROR, &val->locus, |
278 | _("type mismatch in argument %lu to `%s'"), | 279 | _("type mismatch in argument %lu to `%s'"), |
279 | (unsigned long) (exp_arg - reg->v.command.req_args + 1), | 280 | (unsigned long) (exp_arg - reg->v.command.req_args + 1), |
280 | reg->name); | 281 | reg->name); |
281 | mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus, | 282 | mu_diag_at_locus_range (MU_LOG_ERROR, &val->locus, |
282 | _("expected %s but passed %s"), | 283 | _("expected %s but passed %s"), |
283 | mu_sieve_type_str (*exp_arg), | 284 | mu_sieve_type_str (*exp_arg), |
284 | mu_sieve_type_str (val->type)); | 285 | mu_sieve_type_str (val->type)); |
... | @@ -294,8 +295,8 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach, | ... | @@ -294,8 +295,8 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach, |
294 | if (!err && !opt_args && *exp_arg != SVT_VOID) | 295 | if (!err && !opt_args && *exp_arg != SVT_VOID) |
295 | { | 296 | { |
296 | mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus, | 297 | mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus, |
297 | _("too few arguments in call to `%s'"), | 298 | _("too few arguments in call to `%s'"), |
298 | reg->name); | 299 | reg->name); |
299 | mu_i_sv_error (mach); | 300 | mu_i_sv_error (mach); |
300 | err = 1; | 301 | err = 1; |
301 | } | 302 | } | ... | ... |
... | @@ -305,23 +305,27 @@ arglist : arg | ... | @@ -305,23 +305,27 @@ arglist : arg |
305 | arg : stringlist | 305 | arg : stringlist |
306 | { | 306 | { |
307 | $$ = mu_sieve_value_create (mu_sieve_machine, | 307 | $$ = mu_sieve_value_create (mu_sieve_machine, |
308 | SVT_STRING_LIST, &$1); | 308 | SVT_STRING_LIST, &@1, &$1); |
309 | } | 309 | } |
310 | | STRING | 310 | | STRING |
311 | { | 311 | { |
312 | $$ = mu_sieve_value_create (mu_sieve_machine, SVT_STRING, $1); | 312 | $$ = mu_sieve_value_create (mu_sieve_machine, SVT_STRING, |
313 | &@1, $1); | ||
313 | } | 314 | } |
314 | | MULTILINE | 315 | | MULTILINE |
315 | { | 316 | { |
316 | $$ = mu_sieve_value_create (mu_sieve_machine, SVT_STRING, $1); | 317 | $$ = mu_sieve_value_create (mu_sieve_machine, SVT_STRING, |
318 | &@1, $1); | ||
317 | } | 319 | } |
318 | | NUMBER | 320 | | NUMBER |
319 | { | 321 | { |
320 | $$ = mu_sieve_value_create (mu_sieve_machine, SVT_NUMBER, &$1); | 322 | $$ = mu_sieve_value_create (mu_sieve_machine, SVT_NUMBER, |
323 | &@1, &$1); | ||
321 | } | 324 | } |
322 | | TAG | 325 | | TAG |
323 | { | 326 | { |
324 | $$ = mu_sieve_value_create (mu_sieve_machine, SVT_TAG, $1); | 327 | $$ = mu_sieve_value_create (mu_sieve_machine, SVT_TAG, |
328 | &@1, $1); | ||
325 | } | 329 | } |
326 | ; | 330 | ; |
327 | 331 | ... | ... |
... | @@ -28,6 +28,7 @@ | ... | @@ -28,6 +28,7 @@ |
28 | 28 | ||
29 | size_t | 29 | size_t |
30 | mu_sieve_value_create (mu_sieve_machine_t mach, mu_sieve_data_type type, | 30 | mu_sieve_value_create (mu_sieve_machine_t mach, mu_sieve_data_type type, |
31 | struct mu_locus_range const *locus, | ||
31 | void *data) | 32 | void *data) |
32 | { | 33 | { |
33 | size_t idx; | 34 | size_t idx; |
... | @@ -43,6 +44,18 @@ mu_sieve_value_create (mu_sieve_machine_t mach, mu_sieve_data_type type, | ... | @@ -43,6 +44,18 @@ mu_sieve_value_create (mu_sieve_machine_t mach, mu_sieve_data_type type, |
43 | memset (val, 0, sizeof *val); | 44 | memset (val, 0, sizeof *val); |
44 | 45 | ||
45 | val->type = type; | 46 | val->type = type; |
47 | |||
48 | /* Copy locus. */ | ||
49 | val->locus.beg.mu_file = | ||
50 | mu_i_sv_id_str (mach, mu_i_sv_id_num (mach, locus->beg.mu_file)); | ||
51 | val->locus.beg.mu_line = locus->beg.mu_line; | ||
52 | val->locus.beg.mu_col = locus->beg.mu_col; | ||
53 | val->locus.end.mu_file = | ||
54 | mu_i_sv_id_str (mach, mu_i_sv_id_num (mach, locus->end.mu_file)); | ||
55 | val->locus.end.mu_line = locus->end.mu_line; | ||
56 | val->locus.end.mu_col = locus->end.mu_col; | ||
57 | |||
58 | mu_locus_range_copy (&val->locus, locus); | ||
46 | switch (type) | 59 | switch (type) |
47 | { | 60 | { |
48 | case SVT_NUMBER: | 61 | case SVT_NUMBER: | ... | ... |
... | @@ -226,9 +226,12 @@ set_tag_checker (mu_sieve_machine_t mach) | ... | @@ -226,9 +226,12 @@ set_tag_checker (mu_sieve_machine_t mach) |
226 | *mu_sieve_get_tag_n (mach, j + 1) = *t; | 226 | *mu_sieve_get_tag_n (mach, j + 1) = *t; |
227 | else if (prec == tmp_prec) | 227 | else if (prec == tmp_prec) |
228 | { | 228 | { |
229 | mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus, | 229 | mu_diag_at_locus_range (MU_LOG_ERROR, &t->locus, |
230 | _("%s and %s can't be used together"), | 230 | _("%s and %s can't be used together"), |
231 | tmp.tag, t->tag); | 231 | tmp.tag, t->tag); |
232 | mu_diag_at_locus_range (MU_LOG_ERROR, &tmp.locus, | ||
233 | _("%s encountered here"), | ||
234 | tmp.tag); | ||
232 | mu_i_sv_error (mach); | 235 | mu_i_sv_error (mach); |
233 | return 1; | 236 | return 1; |
234 | } | 237 | } | ... | ... |
... | @@ -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:4.4-65: comparator `i;ascii-numeric' is incompatible with match type `contains' in call to `header' | 41 | [sieve: prog:4.41-49: 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