From 30dfac6b8bc411481c9dd333bd8baab9e15c2d00 Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Wed, 9 Mar 2011 11:00:12 +0200 Subject: Fix deferred variable initialization. The bug was spotted by Brian Kroth. * src/gram.y (deferred_decl) : New member. (defer_initialize_variable): Use string_alloc instead of literal_lookup. Take additional argument (ptr to locus). All uses updated. (apply_deferred_init): Pass a ptr to the actual locus to initialize_variable. * src/mailfromd.h (defer_initialize_variable): Change signature. * src/main.c (cb_set_variable): Deduce definition location from mu_strerr. * THANKS: Update. * tests/setvar.at: New testcase. * tests/Makefile.am (TESTSUITE_AT): Add setvar.at. * tests/testsuite.at: Include setvar.at. * tests/invcidr.at: Update experr. * tests/invcidr2.at: Likewise. --- THANKS | 1 + src/gram.y | 19 ++++++++++++------- src/mailfromd.h | 3 ++- src/main.c | 28 ++++++++++++++++++++++++---- tests/Makefile.am | 1 + tests/invcidr.at | 2 +- tests/invcidr2.at | 2 +- tests/setvar.at | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ tests/testsuite.at | 1 + 9 files changed, 94 insertions(+), 14 deletions(-) create mode 100644 tests/setvar.at diff --git a/THANKS b/THANKS index 7c7c9b50..5a857cc6 100644 --- a/THANKS +++ b/THANKS @@ -8,6 +8,7 @@ of errors. Use elisp/obfemail-mode.el to see mail addresses. Alan Dobkin Ben McKeegan Brent Spencer +Brian Kroth Con Tassios Jan Rafaj Jeff Ballard diff --git a/src/gram.y b/src/gram.y index be8dc2f8..990fa13b 100644 --- a/src/gram.y +++ b/src/gram.y @@ -3757,27 +3757,31 @@ struct deferred_decl { struct deferred_decl *next; struct literal *name; struct value value; + struct locus locus; }; struct deferred_decl *deferred_decl; void -defer_initialize_variable(const char *arg, const char *val) +defer_initialize_variable(const char *arg, const char *val, + struct locus *ploc) { struct deferred_decl *p; - struct literal *name = literal_lookup(arg); + struct literal *name = string_alloc(arg, strlen(arg)); for (p = deferred_decl; p; p = p->next) if (p->name == name) { parse_warning_locus(NULL, _("redefining variable %s"), name->text); p->value.type = dtype_string; - p->value.v.literal = literal_lookup(val); + p->value.v.literal = string_alloc(val, strlen(val)); + p->locus = *ploc; return; } p = xmalloc(sizeof *p); p->name = name; p->value.type = dtype_string; - p->value.v.literal = literal_lookup(val); + p->value.v.literal = string_alloc(val, strlen(val)); + p->locus = *ploc; p->next = deferred_decl; deferred_decl = p; } @@ -3794,9 +3798,10 @@ apply_deferred_init() p->name->text); continue; } - if (initialize_variable(var, &p->value, NULL)) - mu_error(_("error initialising variable %s: incompatible types"), - p->name->text); + if (initialize_variable(var, &p->value, &p->locus)) + parse_error_locus(&p->locus, + _("error initialising variable %s: incompatible types"), + p->name->text); } } diff --git a/src/mailfromd.h b/src/mailfromd.h index e45f26e2..7be3fabf 100644 --- a/src/mailfromd.h +++ b/src/mailfromd.h @@ -573,7 +573,8 @@ struct variable *builtin_variable_install(const char *name, data_type_t type, unsigned flags, size_t *addrptr); -void defer_initialize_variable(const char *arg, const char *val); +void defer_initialize_variable(const char *arg, const char *val, + struct locus *locus); int variable_or_constant_lookup(const char *name, void **dptr); diff --git a/src/main.c b/src/main.c index 01fd14b6..3d0264c9 100644 --- a/src/main.c +++ b/src/main.c @@ -550,6 +550,7 @@ parse_opt(int key, char *arg, struct argp_state *state) case 'v': { char *p; + struct locus locus = { "", 1, 0 }; p = strchr(arg, '='); if (!p) @@ -557,7 +558,7 @@ parse_opt(int key, char *arg, struct argp_state *state) _("expected assignment, but found `%s'"), arg); *p++ = 0; - defer_initialize_variable(arg, p); + defer_initialize_variable(arg, p, &locus); break; } @@ -716,7 +717,9 @@ cb_set_variable(void *data, mu_config_value_t *arg) { const char *value; char *alloc_str = NULL; - + struct mu_locus mloc; + struct locus locus; + if (mu_cfg_assert_value_type(arg, MU_CFG_ARRAY)) return 1; if (arg->v.arg.c < 2) { @@ -749,8 +752,25 @@ cb_set_variable(void *data, mu_config_value_t *arg) __FILE__, __LINE__); abort(); } - - defer_initialize_variable(arg->v.arg.v[0].v.string, value); + + locus.leng = 0; + if (mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, + MU_IOCTL_LOGSTREAM_GET_LOCUS, &mloc)) { + locus.file = ""; + locus.line = 0; + locus.point = 0; + } else { + if (mloc.mu_file) { + struct literal *lit = string_alloc(mloc.mu_file, + strlen(mloc.mu_file)); + free(mloc.mu_file); + locus.file = lit->text; + } else + locus.file = ""; + locus.line = mloc.mu_line; + locus.point = mloc.mu_col; + } + defer_initialize_variable(arg->v.arg.v[0].v.string, value, &locus); free(alloc_str); return 0; } diff --git a/tests/Makefile.am b/tests/Makefile.am index 46c59531..14654542 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -110,6 +110,7 @@ TESTSUITE_AT = \ resolve.at\ rset.at\ shadow.at\ + setvar.at\ static01.at\ static02.at\ strings.at\ diff --git a/tests/invcidr.at b/tests/invcidr.at index 950188e0..a87ccdba 100644 --- a/tests/invcidr.at +++ b/tests/invcidr.at @@ -18,7 +18,7 @@ AT_SETUP([Catching exceptions: invcidr]) AT_KEYWORDS([exceptions catch invcidr]) cat > experr <:1: warning: variable \`network' already initialized mailfromd: $ETCDIR/catch.rc:20: warning: this is the location of the previous initialization EOT diff --git a/tests/invcidr2.at b/tests/invcidr2.at index aced767d..b402faa1 100644 --- a/tests/invcidr2.at +++ b/tests/invcidr2.at @@ -18,7 +18,7 @@ AT_SETUP([Catching exceptions: invcidr (2)]) AT_KEYWORDS([exceptions catch invcidr2]) cat > experr <:1: warning: variable \`network' already initialized mailfromd: $ETCDIR/catch01.rc:20: warning: this is the location of the previous initialization EOT diff --git a/tests/setvar.at b/tests/setvar.at new file mode 100644 index 00000000..1d5f55d0 --- /dev/null +++ b/tests/setvar.at @@ -0,0 +1,51 @@ +# This file is part of Mailfromd testsuite. -*- Autotest -*- +# Copyright (C) 2011 Sergey Poznyakoff +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +AT_SETUP([setvar]) +AT_KEYWORDS([setvar variable variables]) + +AT_DATA([mailfromd.conf],[ +setvar stringvar "text"; +setvar numvar 31; +setvar initstringvar "new text"; +]) + +AT_WITH_MAILFROMD_OPTIONS( +[--config-file ./mailfromd.conf], +[MF_CHECK_TEXT([ +string stringvar +number numvar +string initstringvar 'initial text' + +prog envfrom +do + echo stringvar + echo numvar + echo initstringvar +done +], +[], +[EX_OK], +[State envfrom: continue +], +[mailfromd: ./mailfromd.conf:4: warning: variable `initstringvar' already initialized +mailfromd: prog:4: warning: this is the location of the previous initialization +text +31 +new text +])]) + +AT_CLEANUP diff --git a/tests/testsuite.at b/tests/testsuite.at index 2780b34f..d8a697cb 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -270,4 +270,5 @@ m4_include([eof.at]) m4_include([regopt0.at]) m4_include([miltermacros.at]) +m4_include([setvar.at]) -- cgit v1.2.1