mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-14 06:43:03 +00:00
Miscellaneous %define and %code cleanup.
* data/bison.m4 (b4_percent_define_flag_if): Correct comments on how values are interpreted. * doc/bison.texinfo (Decl Summary): Clean up and extend %define documentation a little more. * src/muscle_tab.c (MUSCLE_USER_NAME_CONVERT, muscle_percent_define_insert, muscle_percent_code_grow): New functions/macros. * src/muscle_tab.h (muscle_percent_define_insert, muscle_percent_code_grow): Prototype. * src/parse-gram.y (prologue_declaration): Use muscle_percent_define_insert and muscle_percent_code_grow when parsing %define and %code directives. Make it easy to share %define boolean variables between the front-end and back-end. Though not used yet, this will be useful in the future. * data/bison.m4 (b4_check_user_names): Rewrite comments to talk about Bison uses of names rather than just skeleton uses of names. (b4_percent_define_get, b4_percent_define_ifdef): Rename b4_percent_define_skeleton_variables(VARIABLE) to b4_percent_define_bison_variables(VARIABLE). (b4_percent_code_get, b4_percent_code_ifdef): Rename b4_percent_code_skeleton_qualifiers(QUALIFIER) to b4_percent_code_bison_qualifiers(QUALIFIER). (b4_check_user_names_wrap): Update for renames. * src/muscle_tab.c, src/muscle_tab.h (muscle_percent_define_flag_if, muscle_percent_define_default): New functions mimicking b4_percent_define_flag_if and b4_percent_define_default. For %define variables, report locations for invalid values and redefinitions. * data/bison.m4 (b4_percent_define_flag_if): Read b4_percent_define_loc(VARIABLE) to report the location of an invalid value for VARIABLE. (b4_percent_define_default): Save a special location in b4_percent_define_loc(VARIABLE) in case the default value for VARIABLE must later be reported as invalid. * src/muscle_tab.c (muscle_location_grow, muscle_location_decode): New functions. (muscle_percent_define_insert): Record the location of VARIABLE in muscle percent_define_loc(VARIABLE), and use it to report the previous location for a redefinition. (muscle_percent_define_flag_if): Update like b4_percent_define_flag_if. (muscle_percent_define_default): Update like b4_percent_define_default. (muscle_grow_user_name_list): Rename to... (muscle_user_name_list_grow): ... this for consistency and use muscle_location_grow. * src/muscle_tab.h (muscle_location_grow): Prototype. * tests/input.at (%define errors): Update expected output. * tests/skeletons.at (%define boolean variables: invalid skeleton defaults): New test case.
This commit is contained in:
230
src/muscle_tab.c
230
src/muscle_tab.c
@@ -26,6 +26,7 @@
|
||||
#include <hash.h>
|
||||
#include <quotearg.h>
|
||||
|
||||
#include "complain.h"
|
||||
#include "files.h"
|
||||
#include "muscle_tab.h"
|
||||
#include "getargs.h"
|
||||
@@ -249,6 +250,207 @@ muscle_find (char const *key)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
muscle_boundary_grow (char const *key, boundary bound)
|
||||
{
|
||||
char *extension;
|
||||
MUSCLE_OBSTACK_SGROW (&muscle_obstack, bound.file);
|
||||
obstack_1grow (&muscle_obstack, ':');
|
||||
obstack_fgrow1 (&muscle_obstack, "%d", bound.line);
|
||||
obstack_1grow (&muscle_obstack, '.');
|
||||
obstack_fgrow1 (&muscle_obstack, "%d", bound.column);
|
||||
obstack_1grow (&muscle_obstack, '\0');
|
||||
extension = obstack_finish (&muscle_obstack);
|
||||
muscle_grow (key, extension, "");
|
||||
obstack_free (&muscle_obstack, extension);
|
||||
}
|
||||
|
||||
void
|
||||
muscle_location_grow (char const *key, location loc)
|
||||
{
|
||||
muscle_grow (key, "[[", "");
|
||||
muscle_boundary_grow (key, loc.start);
|
||||
muscle_grow (key, "]], [[", "");
|
||||
muscle_boundary_grow (key, loc.end);
|
||||
muscle_grow (key, "]]", "");
|
||||
}
|
||||
|
||||
/* Reverse of muscle_location_grow. */
|
||||
static location
|
||||
muscle_location_decode (char const *key)
|
||||
{
|
||||
location loc;
|
||||
char const *value = muscle_find_const (key);
|
||||
aver (value);
|
||||
aver (*value == '[');
|
||||
aver (*++value == '[');
|
||||
while (*++value)
|
||||
switch (*value)
|
||||
{
|
||||
case '$':
|
||||
aver (*++value == ']');
|
||||
aver (*++value == '[');
|
||||
obstack_sgrow (&muscle_obstack, "$");
|
||||
break;
|
||||
case '@':
|
||||
switch (*++value)
|
||||
{
|
||||
case '@': obstack_sgrow (&muscle_obstack, "@" ); break;
|
||||
case '{': obstack_sgrow (&muscle_obstack, "[" ); break;
|
||||
case '}': obstack_sgrow (&muscle_obstack, "]" ); break;
|
||||
default: aver (false); break;
|
||||
}
|
||||
break;
|
||||
case '[':
|
||||
aver (false);
|
||||
break;
|
||||
case ']':
|
||||
{
|
||||
char *boundary_str;
|
||||
aver (*++value == ']');
|
||||
obstack_1grow (&muscle_obstack, '\0');
|
||||
boundary_str = obstack_finish (&muscle_obstack);
|
||||
switch (*++value)
|
||||
{
|
||||
case ',':
|
||||
boundary_set_from_string (&loc.start, boundary_str);
|
||||
obstack_free (&muscle_obstack, boundary_str);
|
||||
aver (*++value == ' ');
|
||||
aver (*++value == '[');
|
||||
aver (*++value == '[');
|
||||
break;
|
||||
case '\0':
|
||||
boundary_set_from_string (&loc.end, boundary_str);
|
||||
obstack_free (&muscle_obstack, boundary_str);
|
||||
return loc;
|
||||
break;
|
||||
default:
|
||||
aver (false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
obstack_1grow (&muscle_obstack, *value);
|
||||
break;
|
||||
}
|
||||
aver (false);
|
||||
return loc;
|
||||
}
|
||||
|
||||
void
|
||||
muscle_user_name_list_grow (char const *key, char const *user_name,
|
||||
location loc)
|
||||
{
|
||||
muscle_grow (key, "[[[[", ",");
|
||||
muscle_grow (key, user_name, "");
|
||||
muscle_grow (key, "]], ", "");
|
||||
muscle_location_grow (key, loc);
|
||||
muscle_grow (key, "]]", "");
|
||||
}
|
||||
|
||||
#define MUSCLE_USER_NAME_CONVERT(NAME, PREFIX, USER_NAME, SUFFIX) \
|
||||
do { \
|
||||
char *tmp; \
|
||||
size_t length = strlen ((USER_NAME)); \
|
||||
tmp = xmalloc (sizeof (PREFIX) - 1 + length + sizeof (SUFFIX)); \
|
||||
strcpy (tmp, (PREFIX)); \
|
||||
strcpy (tmp + sizeof (PREFIX) - 1, (USER_NAME)); \
|
||||
strcpy (tmp + sizeof (PREFIX) - 1 + length, (SUFFIX)); \
|
||||
(NAME) = uniqstr_new (tmp); \
|
||||
free (tmp); \
|
||||
} while (0)
|
||||
|
||||
void
|
||||
muscle_percent_define_insert (char const *variable, location variable_loc,
|
||||
char const *value)
|
||||
{
|
||||
char const *name;
|
||||
char const *loc_name;
|
||||
|
||||
MUSCLE_USER_NAME_CONVERT (name, "percent_define(", variable, ")");
|
||||
MUSCLE_USER_NAME_CONVERT (loc_name, "percent_define_loc(", 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"));
|
||||
}
|
||||
MUSCLE_INSERT_STRING (name, value);
|
||||
|
||||
muscle_insert (loc_name, "");
|
||||
muscle_location_grow (loc_name, variable_loc);
|
||||
muscle_user_name_list_grow ("percent_define_user_variables", variable,
|
||||
variable_loc);
|
||||
}
|
||||
|
||||
bool
|
||||
muscle_percent_define_flag_if (char const *variable)
|
||||
{
|
||||
char const *name;
|
||||
char const *loc_name;
|
||||
char const *usage_name;
|
||||
char const *value;
|
||||
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, ")");
|
||||
|
||||
value = muscle_find_const (name);
|
||||
if (value)
|
||||
{
|
||||
if (value[0] == '\0' || 0 == strcmp (value, "true"))
|
||||
result = true;
|
||||
else if (0 == strcmp (value, "false"))
|
||||
result = false;
|
||||
else if (!muscle_find_const (usage_name))
|
||||
complain_at(muscle_location_decode (loc_name),
|
||||
_("invalid value for %%define boolean variable `%s'"),
|
||||
variable);
|
||||
}
|
||||
else
|
||||
fatal(_("undefined %%define variable `%s' passed to muscle_percent_define_flag_if"),
|
||||
variable);
|
||||
|
||||
muscle_insert (usage_name, "");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
muscle_percent_define_default (char const *variable, char const *value)
|
||||
{
|
||||
char const *name;
|
||||
char const *loc_name;
|
||||
MUSCLE_USER_NAME_CONVERT (name, "percent_define(", variable, ")");
|
||||
MUSCLE_USER_NAME_CONVERT (loc_name, "percent_define_loc(", 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;
|
||||
muscle_insert (loc_name, "");
|
||||
muscle_location_grow (loc_name, loc);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
muscle_percent_code_grow (char const *qualifier, location qualifier_loc,
|
||||
char const *code, location code_loc)
|
||||
{
|
||||
char const *name;
|
||||
MUSCLE_USER_NAME_CONVERT (name, "percent_code(", qualifier, ")");
|
||||
muscle_code_grow (name, code, code_loc);
|
||||
muscle_user_name_list_grow ("percent_code_user_qualifiers", qualifier,
|
||||
qualifier_loc);
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------.
|
||||
| Output the definition of ENTRY as a m4_define. |
|
||||
`------------------------------------------------*/
|
||||
@@ -278,31 +480,3 @@ muscles_m4_output (FILE *out)
|
||||
{
|
||||
hash_do_for_each (muscle_table, muscle_m4_output_processor, out);
|
||||
}
|
||||
|
||||
void
|
||||
muscle_boundary_grow (char const *key, boundary bound)
|
||||
{
|
||||
char *extension;
|
||||
MUSCLE_OBSTACK_SGROW (&muscle_obstack, bound.file);
|
||||
obstack_1grow (&muscle_obstack, ':');
|
||||
obstack_fgrow1 (&muscle_obstack, "%d", bound.line);
|
||||
obstack_1grow (&muscle_obstack, '.');
|
||||
obstack_fgrow1 (&muscle_obstack, "%d", bound.column);
|
||||
obstack_1grow (&muscle_obstack, '\0');
|
||||
extension = obstack_finish (&muscle_obstack);
|
||||
muscle_grow (key, extension, "");
|
||||
obstack_free (&muscle_obstack, extension);
|
||||
}
|
||||
|
||||
void
|
||||
muscle_grow_user_name_list (char const *key, char const *user_name,
|
||||
location loc)
|
||||
{
|
||||
muscle_grow (key, "[[[[", ",");
|
||||
muscle_grow (key, user_name, "");
|
||||
muscle_grow (key, "]], [[", "");
|
||||
muscle_boundary_grow (key, loc.start);
|
||||
muscle_grow (key, "]], [[", "");
|
||||
muscle_boundary_grow (key, loc.end);
|
||||
muscle_grow (key, "]]]]", "");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user