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
@@ -3757,27 +3757,31 @@ struct deferred_decl { | |||
3757 | struct deferred_decl *next; | 3757 | struct deferred_decl *next; |
3758 | struct literal *name; | 3758 | struct literal *name; |
3759 | struct value value; | 3759 | struct value value; |
3760 | struct locus locus; | ||
3760 | }; | 3761 | }; |
3761 | 3762 | ||
3762 | struct deferred_decl *deferred_decl; | 3763 | struct deferred_decl *deferred_decl; |
3763 | 3764 | ||
3764 | void | 3765 | void |
3765 | defer_initialize_variable(const char *arg, const char *val) | 3766 | defer_initialize_variable(const char *arg, const char *val, |
3767 | struct locus *ploc) | ||
3766 | { | 3768 | { |
3767 | struct deferred_decl *p; | 3769 | struct deferred_decl *p; |
3768 | struct literal *name = literal_lookup(arg); | 3770 | struct literal *name = string_alloc(arg, strlen(arg)); |
3769 | for (p = deferred_decl; p; p = p->next) | 3771 | for (p = deferred_decl; p; p = p->next) |
3770 | if (p->name == name) { | 3772 | if (p->name == name) { |
3771 | parse_warning_locus(NULL, _("redefining variable %s"), | 3773 | parse_warning_locus(NULL, _("redefining variable %s"), |
3772 | name->text); | 3774 | name->text); |
3773 | p->value.type = dtype_string; | 3775 | p->value.type = dtype_string; |
3774 | p->value.v.literal = literal_lookup(val); | 3776 | p->value.v.literal = string_alloc(val, strlen(val)); |
3777 | p->locus = *ploc; | ||
3775 | return; | 3778 | return; |
3776 | } | 3779 | } |
3777 | p = xmalloc(sizeof *p); | 3780 | p = xmalloc(sizeof *p); |
3778 | p->name = name; | 3781 | p->name = name; |
3779 | p->value.type = dtype_string; | 3782 | p->value.type = dtype_string; |
3780 | p->value.v.literal = literal_lookup(val); | 3783 | p->value.v.literal = string_alloc(val, strlen(val)); |
3784 | p->locus = *ploc; | ||
3781 | p->next = deferred_decl; | 3785 | p->next = deferred_decl; |
3782 | deferred_decl = p; | 3786 | deferred_decl = p; |
3783 | } | 3787 | } |
@@ -3794,9 +3798,10 @@ apply_deferred_init() | |||
3794 | p->name->text); | 3798 | p->name->text); |
3795 | continue; | 3799 | continue; |
3796 | } | 3800 | } |
3797 | if (initialize_variable(var, &p->value, NULL)) | 3801 | if (initialize_variable(var, &p->value, &p->locus)) |
3798 | mu_error(_("error initialising variable %s: incompatible types"), | 3802 | parse_error_locus(&p->locus, |
3799 | p->name->text); | 3803 | _("error initialising variable %s: incompatible types"), |
3804 | p->name->text); | ||
3800 | } | 3805 | } |
3801 | } | 3806 | } |
3802 | 3807 | ||
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, | |||
573 | data_type_t type, | 573 | data_type_t type, |
574 | unsigned flags, | 574 | unsigned flags, |
575 | size_t *addrptr); | 575 | size_t *addrptr); |
576 | void defer_initialize_variable(const char *arg, const char *val); | 576 | void defer_initialize_variable(const char *arg, const char *val, |
577 | struct locus *locus); | ||
577 | 578 | ||
578 | int variable_or_constant_lookup(const char *name, void **dptr); | 579 | int variable_or_constant_lookup(const char *name, void **dptr); |
579 | 580 | ||
@@ -550,6 +550,7 @@ parse_opt(int key, char *arg, struct argp_state *state) | |||
550 | case 'v': | 550 | case 'v': |
551 | { | 551 | { |
552 | char *p; | 552 | char *p; |
553 | struct locus locus = { "<command line>", 1, 0 }; | ||
553 | 554 | ||
554 | p = strchr(arg, '='); | 555 | p = strchr(arg, '='); |
555 | if (!p) | 556 | if (!p) |
@@ -557,7 +558,7 @@ parse_opt(int key, char *arg, struct argp_state *state) | |||
557 | _("expected assignment, but found `%s'"), | 558 | _("expected assignment, but found `%s'"), |
558 | arg); | 559 | arg); |
559 | *p++ = 0; | 560 | *p++ = 0; |
560 | defer_initialize_variable(arg, p); | 561 | defer_initialize_variable(arg, p, &locus); |
561 | break; | 562 | break; |
562 | } | 563 | } |
563 | 564 | ||
@@ -716,7 +717,9 @@ cb_set_variable(void *data, mu_config_value_t *arg) | |||
716 | { | 717 | { |
717 | const char *value; | 718 | const char *value; |
718 | char *alloc_str = NULL; | 719 | char *alloc_str = NULL; |
719 | 720 | struct mu_locus mloc; | |
721 | struct locus locus; | ||
722 | |||
720 | if (mu_cfg_assert_value_type(arg, MU_CFG_ARRAY)) | 723 | if (mu_cfg_assert_value_type(arg, MU_CFG_ARRAY)) |
721 | return 1; | 724 | return 1; |
722 | if (arg->v.arg.c < 2) { | 725 | if (arg->v.arg.c < 2) { |
@@ -749,8 +752,25 @@ cb_set_variable(void *data, mu_config_value_t *arg) | |||
749 | __FILE__, __LINE__); | 752 | __FILE__, __LINE__); |
750 | abort(); | 753 | abort(); |
751 | } | 754 | } |
752 | 755 | ||
753 | defer_initialize_variable(arg->v.arg.v[0].v.string, value); | 756 | locus.leng = 0; |
757 | if (mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, | ||
758 | MU_IOCTL_LOGSTREAM_GET_LOCUS, &mloc)) { | ||
759 | locus.file = "<unknown>"; | ||
760 | locus.line = 0; | ||
761 | locus.point = 0; | ||
762 | } else { | ||
763 | if (mloc.mu_file) { | ||
764 | struct literal *lit = string_alloc(mloc.mu_file, | ||
765 | strlen(mloc.mu_file)); | ||
766 | free(mloc.mu_file); | ||
767 | locus.file = lit->text; | ||
768 | } else | ||
769 | locus.file = "<unknown>"; | ||
770 | locus.line = mloc.mu_line; | ||
771 | locus.point = mloc.mu_col; | ||
772 | } | ||
773 | defer_initialize_variable(arg->v.arg.v[0].v.string, value, &locus); | ||
754 | free(alloc_str); | 774 | free(alloc_str); |
755 | return 0; | 775 | return 0; |
756 | } | 776 | } |