Commit 4f24c098 4f24c098704dd28622d1d653945388a4abbfb434 by Sergey Poznyakoff

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.
1 parent fa5d4812
......@@ -88,6 +88,7 @@ typedef struct
{
mu_sieve_data_type type;
char *tag;
struct mu_locus_range locus;
union mu_sieve_value_storage v;
} mu_sieve_value_t;
......@@ -163,7 +164,9 @@ void mu_sieve_reclaim_default (void *p);
void mu_sieve_reclaim_value (void *p);
size_t mu_sieve_value_create (mu_sieve_machine_t mach,
mu_sieve_data_type type, void *data);
mu_sieve_data_type type,
struct mu_locus_range const *locus,
void *data);
/* Symbol space functions */
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)
{
if (mu_parse_stream_perm_string (&flag, t->v.string, &p))
{
mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus,
mu_diag_at_locus_range (MU_LOG_ERROR, &t->locus,
_("invalid permissions (near %s)"), p);
mu_i_sv_error (mach);
err = 1;
......
......@@ -174,7 +174,7 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach)
{
if (match)
{
mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus,
mu_diag_at_locus_range (MU_LOG_ERROR, &t->locus,
_("match type specified twice in call to `%s'"),
mach->identifier);
mu_i_sv_error (mach);
......@@ -209,7 +209,7 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach)
if (compname && strcmp (compname, "i;ascii-numeric"))
{
mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus,
mu_diag_at_locus_range (MU_LOG_ERROR, &match->locus,
/* TRANSLATORS: Do not translate ':count'.
It is the name of a Sieve tag */
_("comparator %s is incompatible with "
......@@ -235,7 +235,7 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach)
break;
/* fall through */
default:
mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus,
mu_diag_at_locus_range (MU_LOG_ERROR, &val->locus,
_(":count requires second argument to be a list of one element"));
mu_i_sv_error (mach);
return 1;
......@@ -246,7 +246,7 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach)
char *p = mu_str_skip_class (argstr->orig, MU_CTYPE_DIGIT);
if (*p)
{
mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus,
mu_diag_at_locus_range (MU_LOG_ERROR, &val->locus,
_("second argument cannot be converted to number"));
mu_i_sv_error (mach);
return 1;
......@@ -258,7 +258,7 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach)
if (mu_sieve_str_to_relcmp (str, NULL, NULL))
{
mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus,
mu_diag_at_locus_range (MU_LOG_ERROR, &match->locus,
_("invalid relational match `%s' in call to `%s'"),
str, mach->identifier);
mu_i_sv_error (mach);
......@@ -278,10 +278,16 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach)
compfun = mu_sieve_comparator_lookup (mach, compname, matchtype);
if (!compfun)
{
mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus,
if (match)
mu_diag_at_locus_range (MU_LOG_ERROR, &match->locus,
_("comparator `%s' is incompatible with match type `%s' in call to `%s'"),
compname, match->tag,
mach->identifier);
else
mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus,
_("comparator `%s' is incompatible with match type `%s' in call to `%s'"),
compname, match ? match->tag : "is",
mach->identifier);
compname, "is",
mach->identifier);
mu_i_sv_error (mach);
return 1;
}
......
......@@ -171,7 +171,7 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach,
if (!tag)
{
mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus,
mu_diag_at_locus_range (MU_LOG_ERROR, &val->locus,
_("invalid tag name `%s' for `%s'"),
val->v.string, reg->name);
mu_i_sv_error (mach);
......@@ -191,6 +191,7 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach,
{
if (i + 1 == node->v.command.argcount)
{
/* FIXME: more exact locus */
mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus,
_("required argument for tag %s is missing"),
tag->name);
......@@ -208,11 +209,11 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach,
if (val->type != tag->argtype)
{
mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus,
mu_diag_at_locus_range (MU_LOG_ERROR, &val->locus,
_("type mismatch in argument to "
"tag `%s'"),
tag->name);
mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus,
mu_diag_at_locus_range (MU_LOG_ERROR, &val->locus,
_("expected %s but passed %s"),
mu_sieve_type_str (tag->argtype),
mu_sieve_type_str (val->type));
......@@ -274,11 +275,11 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach,
/* compatible types */;
else
{
mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus,
mu_diag_at_locus_range (MU_LOG_ERROR, &val->locus,
_("type mismatch in argument %lu to `%s'"),
(unsigned long) (exp_arg - reg->v.command.req_args + 1),
reg->name);
mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus,
mu_diag_at_locus_range (MU_LOG_ERROR, &val->locus,
_("expected %s but passed %s"),
mu_sieve_type_str (*exp_arg),
mu_sieve_type_str (val->type));
......@@ -294,8 +295,8 @@ mu_i_sv_lint_command (struct mu_sieve_machine *mach,
if (!err && !opt_args && *exp_arg != SVT_VOID)
{
mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus,
_("too few arguments in call to `%s'"),
reg->name);
_("too few arguments in call to `%s'"),
reg->name);
mu_i_sv_error (mach);
err = 1;
}
......
......@@ -305,23 +305,27 @@ arglist : arg
arg : stringlist
{
$$ = mu_sieve_value_create (mu_sieve_machine,
SVT_STRING_LIST, &$1);
SVT_STRING_LIST, &@1, &$1);
}
| STRING
{
$$ = mu_sieve_value_create (mu_sieve_machine, SVT_STRING, $1);
$$ = mu_sieve_value_create (mu_sieve_machine, SVT_STRING,
&@1, $1);
}
| MULTILINE
{
$$ = mu_sieve_value_create (mu_sieve_machine, SVT_STRING, $1);
$$ = mu_sieve_value_create (mu_sieve_machine, SVT_STRING,
&@1, $1);
}
| NUMBER
{
$$ = mu_sieve_value_create (mu_sieve_machine, SVT_NUMBER, &$1);
$$ = mu_sieve_value_create (mu_sieve_machine, SVT_NUMBER,
&@1, &$1);
}
| TAG
{
$$ = mu_sieve_value_create (mu_sieve_machine, SVT_TAG, $1);
$$ = mu_sieve_value_create (mu_sieve_machine, SVT_TAG,
&@1, $1);
}
;
......
......@@ -28,6 +28,7 @@
size_t
mu_sieve_value_create (mu_sieve_machine_t mach, mu_sieve_data_type type,
struct mu_locus_range const *locus,
void *data)
{
size_t idx;
......@@ -43,6 +44,18 @@ mu_sieve_value_create (mu_sieve_machine_t mach, mu_sieve_data_type type,
memset (val, 0, sizeof *val);
val->type = type;
/* Copy locus. */
val->locus.beg.mu_file =
mu_i_sv_id_str (mach, mu_i_sv_id_num (mach, locus->beg.mu_file));
val->locus.beg.mu_line = locus->beg.mu_line;
val->locus.beg.mu_col = locus->beg.mu_col;
val->locus.end.mu_file =
mu_i_sv_id_str (mach, mu_i_sv_id_num (mach, locus->end.mu_file));
val->locus.end.mu_line = locus->end.mu_line;
val->locus.end.mu_col = locus->end.mu_col;
mu_locus_range_copy (&val->locus, locus);
switch (type)
{
case SVT_NUMBER:
......
......@@ -226,9 +226,12 @@ set_tag_checker (mu_sieve_machine_t mach)
*mu_sieve_get_tag_n (mach, j + 1) = *t;
else if (prec == tmp_prec)
{
mu_diag_at_locus_range (MU_LOG_ERROR, &mach->locus,
_("%s and %s can't be used together"),
tmp.tag, t->tag);
mu_diag_at_locus_range (MU_LOG_ERROR, &t->locus,
_("%s and %s can't be used together"),
tmp.tag, t->tag);
mu_diag_at_locus_range (MU_LOG_ERROR, &tmp.locus,
_("%s encountered here"),
tmp.tag);
mu_i_sv_error (mach);
return 1;
}
......
......@@ -38,7 +38,7 @@ if header :comparator "i;ascii-numeric" :contains "X-Number" "15"
discard;
}
],[78],[],
[sieve: prog:4.4-65: comparator `i;ascii-numeric' is incompatible with match type `contains' in call to `header'
[sieve: prog:4.41-49: comparator `i;ascii-numeric' is incompatible with match type `contains' in call to `header'
])
AT_CLEANUP
......