From 35b8730d018b0bb25f7864d0db20f687ebad11b6 Mon Sep 17 00:00:00 2001 From: "Joel E. Denny" Date: Mon, 8 Oct 2007 04:00:13 +0000 Subject: [PATCH] Add syncline support and location accessor to internal %define interfaces. * data/bison.m4 (b4_percent_define_get_loc): New. (b4_percent_define_get_syncline): New. (b4_percent_define_flag_if): Use b4_percent_define_get_loc. (b4_percent_define_default): Record defining location as line 1 rather than 0 for the sake of synchronizing #line's, and define b4_percent_define_syncline(VARIABLE). (b4_percent_define_check_values): Use b4_percent_define_get_loc. * src/muscle_tab.c (muscle_syncline_grow): New. (muscle_code_grow): Use muscle_syncline_grow. (muscle_percent_define_insert): Use muscle_percent_define_get_loc, and define b4_percent_define_syncline(VARIABLE). (muscle_percent_define_get_loc): New. (muscle_percent_define_get_syncline): New. (muscle_percent_define_flag_if): Use muscle_percent_define_get_loc, and remove some unused variables. (muscle_percent_define_default): Record defining location as line 1 rather than 0 for the sake of synchronizing #line's, and define b4_percent_define_syncline(VARIABLE). (muscle_percent_define_check_values): Use muscle_percent_define_get_loc. * src/muscle_tab.h (muscle_percent_define_get_loc): Prototype. (muscle_percent_define_get_syncline): Prototype. * tests/skeletons.at (%define Boolean variables: invalid skeleton defaults): Update output for location change. (Complaining during macro argument expansion): Extend to test b4_percent_define_get_loc and b4_percent_define_get_syncline errors. --- ChangeLog | 31 ++++++++++++++++++ data/bison.m4 | 58 ++++++++++++++++++++++++++------- src/muscle_tab.c | 80 ++++++++++++++++++++++++++++++++++------------ src/muscle_tab.h | 16 ++++++++++ tests/skeletons.at | 30 ++++++++++++++++- 5 files changed, 181 insertions(+), 34 deletions(-) diff --git a/ChangeLog b/ChangeLog index ab280a0c..9072e409 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,34 @@ +2007-10-08 Joel E. Denny + + Add syncline support and location accessor to internal %define + interfaces. + * data/bison.m4 (b4_percent_define_get_loc): New. + (b4_percent_define_get_syncline): New. + (b4_percent_define_flag_if): Use b4_percent_define_get_loc. + (b4_percent_define_default): Record defining location as line 1 rather + than 0 for the sake of synchronizing #line's, and define + b4_percent_define_syncline(VARIABLE). + (b4_percent_define_check_values): Use b4_percent_define_get_loc. + * src/muscle_tab.c (muscle_syncline_grow): New. + (muscle_code_grow): Use muscle_syncline_grow. + (muscle_percent_define_insert): Use muscle_percent_define_get_loc, and + define b4_percent_define_syncline(VARIABLE). + (muscle_percent_define_get_loc): New. + (muscle_percent_define_get_syncline): New. + (muscle_percent_define_flag_if): Use muscle_percent_define_get_loc, and + remove some unused variables. + (muscle_percent_define_default): Record defining location as line 1 + rather than 0 for the sake of synchronizing #line's, and define + b4_percent_define_syncline(VARIABLE). + (muscle_percent_define_check_values): Use + muscle_percent_define_get_loc. + * src/muscle_tab.h (muscle_percent_define_get_loc): Prototype. + (muscle_percent_define_get_syncline): Prototype. + * tests/skeletons.at (%define Boolean variables: invalid skeleton + defaults): Update output for location change. + (Complaining during macro argument expansion): Extend to test + b4_percent_define_get_loc and b4_percent_define_get_syncline errors. + 2007-10-07 Joel E. Denny Fix some error-reporting macro bugs. diff --git a/data/bison.m4 b/data/bison.m4 index 5e503919..fbf375bd 100644 --- a/data/bison.m4 +++ b/data/bison.m4 @@ -375,6 +375,42 @@ m4_define([b4_percent_define_get], [m4_define([b4_percent_define_bison_variables(]$1[)])dnl m4_ifdef([b4_percent_define(]$1[)], [m4_indir([b4_percent_define(]$1[)])])]) +# b4_percent_define_get_loc(VARIABLE) +# ----------------------------------- +# Mimic muscle_percent_define_get_loc in ../src/muscle_tab.h exactly. That is, +# if the %define variable VARIABLE is undefined, complain fatally since that's +# a Bison or skeleton error. Otherwise, return its definition location in a +# form approriate for the first two arguments of b4_warn_at, b4_complain_at, or +# b4_fatal_at. Don't record this as a Bison usage of VARIABLE as there's no +# reason to suspect that the user-supplied value has yet influenced the output. +# +# For example: +# +# b4_complain_at(b4_percent_define_get_loc([[foo]]), [[invalid foo]]) +m4_define([b4_percent_define_get_loc], +[m4_ifdef([b4_percent_define_loc(]$1[)], + [m4_pushdef([b4_loc], m4_indir([b4_percent_define_loc(]$1[)]))dnl +b4_loc[]dnl +m4_popdef([b4_loc])], + [b4_fatal([[undefined %%define variable `%s' passed to b4_percent_define_get_loc]], [$1])])]) + +# b4_percent_define_get_syncline(VARIABLE) +# ---------------------------------------- +# Mimic muscle_percent_define_get_syncline in ../src/muscle_tab.h exactly. +# That is, if the %define variable VARIABLE is undefined, complain fatally +# since that's a Bison or skeleton error. Otherwise, return its definition +# location as a b4_syncline invocation. Don't record this as a Bison usage of +# VARIABLE as there's no reason to suspect that the user-supplied value has yet +# influenced the output. +# +# For example: +# +# b4_percent_define_get_syncline([[foo]]) +m4_define([b4_percent_define_get_syncline], +[m4_ifdef([b4_percent_define_syncline(]$1[)], + [m4_indir([b4_percent_define_syncline(]$1[)])], + [b4_fatal([[undefined %%define variable `%s' passed to b4_percent_define_get_syncline]], [$1])])]) + # b4_percent_define_ifdef(VARIABLE, IF-TRUE, [IF-FALSE]) # ------------------------------------------------------ # Mimic muscle_percent_define_ifdef in ../src/muscle_tab.h exactly. That is, @@ -407,13 +443,10 @@ m4_define([b4_percent_define_flag_if], [b4_percent_define_ifdef([$1], [m4_case(b4_percent_define_get([$1]), [], [$2], [true], [$2], [false], [$3], - [m4_expand_once([dnl - m4_pushdef([b4_loc], m4_indir([b4_percent_define_loc(]$1[)]))dnl - b4_complain_at(b4_loc, - [[invalid value for %%define Boolean variable `%s']], - [$1])dnl - m4_popdef([b4_loc])], - [[b4_percent_define_flag_if($1)]])])], + [m4_expand_once([b4_complain_at(b4_percent_define_get_loc([$1]), + [[invalid value for %%define Boolean variable `%s']], + [$1])], + [[b4_percent_define_flag_if($1)]])])], [b4_fatal([[undefined %%define variable `%s' passed to b4_percent_define_flag_if]], [$1])])]) # b4_percent_define_default(VARIABLE, DEFAULT) @@ -430,7 +463,10 @@ m4_define([b4_percent_define_default], [m4_ifndef([b4_percent_define(]$1[)], [m4_define([b4_percent_define(]$1[)], [$2])dnl m4_define([b4_percent_define_loc(]$1[)], - [[[[[Bison:b4_percent_define_default]:0.0]], [[[Bison:b4_percent_define_default]:0.0]]]])])]) + [[[[[Bison:b4_percent_define_default]:1.0]], [[[Bison:b4_percent_define_default]:1.0]]]])dnl + m4_define([b4_percent_define_syncline(]$1[)], + [[]b4_syncline(1, [["[Bison:b4_percent_define_default]"]])[ +]])])]) # b4_percent_define_check_values(VALUES) # -------------------------------------- @@ -460,12 +496,10 @@ m4_define([_b4_percent_define_check_values], [m4_if(m4_indir([b4_percent_define(]$1[)]), b4_value, [m4_define([b4_good_value], [1])])])])dnl m4_if(b4_good_value, [0], - [m4_pushdef([b4_loc], m4_indir([b4_percent_define_loc(]$1[)]))dnl - b4_complain_at(b4_loc, + [b4_complain_at(b4_percent_define_get_loc([$1]), [[invalid value for %%define variable `%s': `%s']], [$1], - m4_dquote(m4_indir([b4_percent_define(]$1[)])))dnl - m4_popdef([b4_loc])])dnl + m4_dquote(m4_indir([b4_percent_define(]$1[)])))])dnl m4_popdef([b4_good_value])], [b4_fatal([[undefined %%define variable `%s' passed to b4_percent_define_check_values]], [$1])])]) diff --git a/src/muscle_tab.c b/src/muscle_tab.c index 01f80dc4..afe59bec 100644 --- a/src/muscle_tab.c +++ b/src/muscle_tab.c @@ -168,27 +168,38 @@ muscle_grow (const char *key, const char *val, const char *separator) } } - /*------------------------------------------------------------------. -| Append VALUE to the current value of KEY, using muscle_grow. But | -| in addition, issue a synchronization line for the location LOC. | +| Using muscle_grow, append a synchronization line for the location | +| LOC to the current value of KEY. | `------------------------------------------------------------------*/ -void -muscle_code_grow (const char *key, const char *val, location loc) +static void +muscle_syncline_grow (char const *key, location loc) { char *extension = NULL; obstack_fgrow1 (&muscle_obstack, "]b4_syncline(%d, [[", loc.start.line); MUSCLE_OBSTACK_SGROW (&muscle_obstack, quotearg_style (c_quoting_style, loc.start.file)); - obstack_sgrow (&muscle_obstack, "]])[\n"); - obstack_sgrow (&muscle_obstack, val); + obstack_sgrow (&muscle_obstack, "]])["); obstack_1grow (&muscle_obstack, 0); extension = obstack_finish (&muscle_obstack); muscle_grow (key, extension, ""); obstack_free (&muscle_obstack, extension); } +/*------------------------------------------------------------------. +| Append VALUE to the current value of KEY, using muscle_grow. But | +| in addition, issue a synchronization line for the location LOC | +| using muscle_syncline_grow. | +`------------------------------------------------------------------*/ + +void +muscle_code_grow (const char *key, const char *val, location loc) +{ + muscle_syncline_grow (key, loc); + muscle_grow (key, val, "\n"); +} + void muscle_pair_list_grow (const char *muscle, const char *a1, const char *a2) @@ -395,20 +406,26 @@ muscle_percent_define_insert (char const *variable, location variable_loc, { char const *name; char const *loc_name; + char const *syncline_name; MUSCLE_USER_NAME_CONVERT (name, "percent_define(", variable, ")"); MUSCLE_USER_NAME_CONVERT (loc_name, "percent_define_loc(", variable, ")"); + MUSCLE_USER_NAME_CONVERT (syncline_name, + "percent_define_syncline(", variable, ")"); if (muscle_find_const (name)) { warn_at (variable_loc, _("%s `%s' redefined"), "%define variable", variable); - warn_at (muscle_location_decode (loc_name), _("previous definition")); + warn_at (muscle_percent_define_get_loc (variable), + _("previous definition")); } MUSCLE_INSERT_STRING (name, value); muscle_insert (loc_name, ""); muscle_location_grow (loc_name, variable_loc); + muscle_insert (syncline_name, ""); + muscle_syncline_grow (syncline_name, variable_loc); muscle_user_name_list_grow ("percent_define_user_variables", variable, variable_loc); } @@ -431,6 +448,31 @@ muscle_percent_define_get (char const *variable) return value; } +location +muscle_percent_define_get_loc (char const *variable) +{ + char const *loc_name; + MUSCLE_USER_NAME_CONVERT (loc_name, "percent_define_loc(", variable, ")"); + if (!muscle_find_const (loc_name)) + fatal(_("undefined %%define variable `%s' passed to muscle_percent_define_get_loc"), + variable); + return muscle_location_decode (loc_name); +} + +char const * +muscle_percent_define_get_syncline (char const *variable) +{ + char const *syncline_name; + char const *syncline; + MUSCLE_USER_NAME_CONVERT (syncline_name, + "percent_define_syncline(", variable, ")"); + syncline = muscle_find_const (syncline_name); + if (!syncline) + fatal(_("undefined %%define variable `%s' passed to muscle_percent_define_get_syncline"), + variable); + return syncline; +} + bool muscle_percent_define_ifdef (char const *variable) { @@ -455,16 +497,9 @@ muscle_percent_define_ifdef (char const *variable) bool muscle_percent_define_flag_if (char const *variable) { - char const *name; - char const *loc_name; - char const *usage_name; char const *invalid_boolean_name; bool result = false; - MUSCLE_USER_NAME_CONVERT (name, "percent_define(", variable, ")"); - MUSCLE_USER_NAME_CONVERT (loc_name, "percent_define_loc(", variable, ")"); - MUSCLE_USER_NAME_CONVERT (usage_name, "percent_define_bison_variables(", - variable, ")"); MUSCLE_USER_NAME_CONVERT (invalid_boolean_name, "percent_define_invalid_boolean(", variable, ")"); @@ -478,7 +513,7 @@ muscle_percent_define_flag_if (char const *variable) else if (!muscle_find_const (invalid_boolean_name)) { muscle_insert (invalid_boolean_name, ""); - complain_at(muscle_location_decode (loc_name), + complain_at(muscle_percent_define_get_loc (variable), _("invalid value for %%define Boolean variable `%s'"), variable); } @@ -496,17 +531,22 @@ muscle_percent_define_default (char const *variable, char const *value) { char const *name; char const *loc_name; + char const *syncline_name; MUSCLE_USER_NAME_CONVERT (name, "percent_define(", variable, ")"); MUSCLE_USER_NAME_CONVERT (loc_name, "percent_define_loc(", variable, ")"); + MUSCLE_USER_NAME_CONVERT (syncline_name, + "percent_define_syncline(", variable, ")"); if (!muscle_find_const (name)) { location loc; MUSCLE_INSERT_STRING (name, value); loc.start.file = loc.end.file = "[Bison:muscle_percent_define_default]"; - loc.start.line = loc.start.column = 0; - loc.end.line = loc.end.column = 0; + loc.start.line = loc.end.line = 1; + loc.start.column = loc.end.column = 0; muscle_insert (loc_name, ""); muscle_location_grow (loc_name, loc); + muscle_insert (syncline_name, ""); + muscle_syncline_grow (syncline_name, loc); } } @@ -517,11 +557,9 @@ muscle_percent_define_check_values (char const * const *values) { char const *variable = *values; char const *name; - char const *loc_name; char *value; MUSCLE_USER_NAME_CONVERT (name, "percent_define(", variable, ")"); - MUSCLE_USER_NAME_CONVERT (loc_name, "percent_define_loc(", variable, ")"); value = muscle_string_decode (name); if (value) @@ -538,7 +576,7 @@ muscle_percent_define_check_values (char const * const *values) } } if (!valid) - complain_at(muscle_location_decode (loc_name), + complain_at(muscle_percent_define_get_loc (variable), _("invalid value for %%define variable `%s': `%s'"), variable, value); free (value); diff --git a/src/muscle_tab.h b/src/muscle_tab.h index c2881577..19fba8b9 100644 --- a/src/muscle_tab.h +++ b/src/muscle_tab.h @@ -136,6 +136,22 @@ void muscle_percent_define_insert (char const *variable, location variable_loc, freeing the memory of the returned string. */ char *muscle_percent_define_get (char const *variable); +/* Mimic muscle_percent_define_get_loc in ../data/bison.m4 exactly. That is, + if the %define variable VARIABLE is undefined, complain fatally since that's + a Bison error. Otherwise, return its definition location in a form + approriate for the first argument of warn_at, complain_at, or fatal_at. + Don't record this as a Bison usage of VARIABLE as there's no reason to + suspect that the user-supplied value has yet influenced the output. */ +location muscle_percent_define_get_loc (char const *variable); + +/* Mimic muscle_percent_define_get_syncline in ../data/bison.m4 exactly. That + is, if the %define variable VARIABLE is undefined, complain fatally since + that's a Bison error. Otherwise, return its definition location as a + b4_syncline invocation. Don't record this as a Bison usage of VARIABLE as + there's no reason to suspect that the user-supplied value has yet influenced + the output. */ +char const *muscle_percent_define_get_syncline (char const *variable); + /* Mimic b4_percent_define_ifdef in ../data/bison.m4 exactly. That is, if the %define variable VARIABLE is defined, return true. Otherwise, return false. Also, record Bison's usage of VARIABLE by defining diff --git a/tests/skeletons.at b/tests/skeletons.at index 53c3049b..ca0cbb84 100644 --- a/tests/skeletons.at +++ b/tests/skeletons.at @@ -159,7 +159,7 @@ start: ; ]]) AT_CHECK([[bison input.y]], [[1]], [[]], -[[[Bison:b4_percent_define_default]:0.0: invalid value for %define Boolean variable `foo' +[[[Bison:b4_percent_define_default]:1.0: invalid value for %define Boolean variable `foo' ]]) AT_CLEANUP @@ -216,6 +216,34 @@ AT_CHECK([[bison input2.y]], [[1]], [[]], [[foof.y:12.11-100.122: fatal error: foofat fubar ]]) +AT_DATA([[skel3.c]], +[[b4_complain_at(b4_percent_define_get_loc([[bogus]]), [[bad value]]) +]]) + +AT_DATA([[input3.y]], +[[%skeleton "./skel3.c" +%% +start: ; +]]) + +AT_CHECK([[bison input3.y]], [[1]], [[]], +[[input3.y: fatal error: undefined %define variable `bogus' passed to b4_percent_define_get_loc +]]) + +AT_DATA([[skel4.c]], +[[b4_warn_at(b4_percent_define_get_syncline([[bogus]]), [[bad value]]) +]]) + +AT_DATA([[input4.y]], +[[%skeleton "./skel4.c" +%% +start: ; +]]) + +AT_CHECK([[bison input4.y]], [[1]], [[]], +[[input4.y: fatal error: undefined %define variable `bogus' passed to b4_percent_define_get_syncline +]]) + AT_CLEANUP -- 2.45.2