diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-03-09 11:00:12 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-03-09 11:47:52 +0200 |
commit | 30dfac6b8bc411481c9dd333bd8baab9e15c2d00 (patch) | |
tree | 08209280450a3c569f6d57088f97db482f956d40 /src | |
parent | fedbf1d7be7a92ae10bd2e2c05f0bf5c10b933ce (diff) | |
download | mailfromd-30dfac6b8bc411481c9dd333bd8baab9e15c2d00.tar.gz mailfromd-30dfac6b8bc411481c9dd333bd8baab9e15c2d00.tar.bz2 |
Fix deferred variable initialization.
The bug was spotted by Brian Kroth.
* src/gram.y (deferred_decl) <locus>: 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.
Diffstat (limited to 'src')
-rw-r--r-- | src/gram.y | 19 | ||||
-rw-r--r-- | src/mailfromd.h | 3 | ||||
-rw-r--r-- | src/main.c | 28 |
3 files changed, 38 insertions, 12 deletions
@@ -3754,33 +3754,37 @@ externdecl(const char *name, struct value *value, struct locus *loc) 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; } static void apply_deferred_init() @@ -3791,15 +3795,16 @@ apply_deferred_init() if (!var) { mu_error(_("<command line>: warning: " "no such variable: %s"), 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); } } struct declvar { struct declvar *next; diff --git a/src/mailfromd.h b/src/mailfromd.h index e45f26e2..7be3fabf 100644 --- a/src/mailfromd.h +++ b/src/mailfromd.h @@ -570,13 +570,14 @@ struct variable *variable_lookup(const char *name); struct variable *variable_replace(const char *name, struct variable *newvar); void variable_remove(struct variable *var); 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); struct function *function_install(const char *name, size_t parmcnt, size_t optcnt, int varargs, data_type_t *parmtypes, @@ -547,20 +547,21 @@ parse_opt(int key, char *arg, struct argp_state *state) need_script = 1; break; case 'v': { char *p; + struct locus locus = { "<command line>", 1, 0 }; p = strchr(arg, '='); if (!p) argp_error(state, _("expected assignment, but found `%s'"), arg); *p++ = 0; - defer_initialize_variable(arg, p); + defer_initialize_variable(arg, p, &locus); break; } case OPTION_DAEMON: mode = MAILFROMD_DAEMON; need_script = 1; @@ -713,13 +714,15 @@ cb_timeout(void *data, mu_config_value_t *arg) static int 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) { mu_error(_("not enough arguments")); return 1; } else if (arg->v.arg.c > 2) { @@ -746,14 +749,31 @@ cb_set_variable(void *data, mu_config_value_t *arg) default: mu_error (_("INTERNAL ERROR at %s:%d: please report"), __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 = "<unknown>"; + 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 = "<unknown>"; + 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; } static int cb_include_path(void *data, mu_config_value_t *val) |