aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2011-03-09 11:00:12 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2011-03-09 11:47:52 +0200
commit30dfac6b8bc411481c9dd333bd8baab9e15c2d00 (patch)
tree08209280450a3c569f6d57088f97db482f956d40 /src
parentfedbf1d7be7a92ae10bd2e2c05f0bf5c10b933ce (diff)
downloadmailfromd-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.y19
-rw-r--r--src/mailfromd.h3
-rw-r--r--src/main.c28
3 files changed, 38 insertions, 12 deletions
diff --git a/src/gram.y b/src/gram.y
index be8dc2f8..990fa13b 100644
--- a/src/gram.y
+++ b/src/gram.y
@@ -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,
diff --git a/src/main.c b/src/main.c
index 01fd14b6..3d0264c9 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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)

Return to:

Send suggestions and report system problems to the System administrator.