mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-10 12:53:03 +00:00
muscles: be sure that %code snippets are not glue together on a single line
Recently "braceless" in the parser was changed so that an eol was no longer added to the value. This is not correct when a %code is used multiple times, because the syncline of the next snippet might be appended to the last (and not ended) line of the previous snippet. * src/muscle-tab.h (muscle_grow): Make it private. * src/muscle-tab.c (muscle_grow): Accept a fourth argument: a required terminator. Adjust callers. * tests/input.at (Multiple %code): New.
This commit is contained in:
@@ -153,33 +153,39 @@ muscle_insert (char const *key, char const *value)
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------.
|
||||
| Append VALUE to the current value of KEY. If KEY did not already |
|
||||
| exist, create it. Use MUSCLE_OBSTACK. De-allocate the previously |
|
||||
| associated value. Copy VALUE and SEPARATOR. |
|
||||
`-------------------------------------------------------------------*/
|
||||
/* Append VALUE to the current value of KEY. If KEY did not already
|
||||
exist, create it. Use MUSCLE_OBSTACK. De-allocate the previously
|
||||
associated value. Copy VALUE and SEPARATOR. If VALUE does not end
|
||||
with TERMINATOR, append one. */
|
||||
|
||||
void
|
||||
muscle_grow (const char *key, const char *val, const char *separator)
|
||||
static void
|
||||
muscle_grow (const char *key, const char *val,
|
||||
const char *separator, const char *terminator)
|
||||
{
|
||||
muscle_entry *entry = muscle_lookup (key);
|
||||
size_t vals = strlen (val);
|
||||
size_t terms = strlen (terminator);
|
||||
|
||||
if (entry)
|
||||
{
|
||||
/* Grow the current value. */
|
||||
char *new_val;
|
||||
obstack_printf (&muscle_obstack, "%s%s%s", entry->value, separator, val);
|
||||
obstack_sgrow (&muscle_obstack, entry->value);
|
||||
obstack_sgrow (&muscle_obstack, separator);
|
||||
free (entry->storage);
|
||||
new_val = obstack_finish0 (&muscle_obstack);
|
||||
entry->value = entry->storage = xstrdup (new_val);
|
||||
obstack_free (&muscle_obstack, new_val);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* First insertion in the hash. */
|
||||
entry = muscle_entry_new (key);
|
||||
entry->value = entry->storage = xstrdup (val);
|
||||
}
|
||||
entry = muscle_entry_new (key);
|
||||
|
||||
obstack_sgrow (&muscle_obstack, val);
|
||||
|
||||
if (terms <= vals
|
||||
&& STRNEQ (val + vals - terms, terminator))
|
||||
obstack_sgrow (&muscle_obstack, terminator);
|
||||
|
||||
{
|
||||
char *new_val = obstack_finish0 (&muscle_obstack);
|
||||
entry->value = entry->storage = xstrdup (new_val);
|
||||
obstack_free (&muscle_obstack, new_val);
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------.
|
||||
@@ -196,7 +202,7 @@ muscle_syncline_grow (char const *key, location loc)
|
||||
quotearg_style (c_quoting_style, loc.start.file));
|
||||
obstack_sgrow (&muscle_obstack, ")[");
|
||||
extension = obstack_finish0 (&muscle_obstack);
|
||||
muscle_grow (key, extension, "");
|
||||
muscle_grow (key, extension, "", "");
|
||||
obstack_free (&muscle_obstack, extension);
|
||||
}
|
||||
|
||||
@@ -210,7 +216,7 @@ void
|
||||
muscle_code_grow (const char *key, const char *val, location loc)
|
||||
{
|
||||
muscle_syncline_grow (key, loc);
|
||||
muscle_grow (key, val, "\n");
|
||||
muscle_grow (key, val, "\n", "\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -225,7 +231,7 @@ muscle_pair_list_grow (const char *muscle,
|
||||
obstack_quote (&muscle_obstack, a2);
|
||||
obstack_sgrow (&muscle_obstack, "]");
|
||||
pair = obstack_finish0 (&muscle_obstack);
|
||||
muscle_grow (muscle, pair, ",\n");
|
||||
muscle_grow (muscle, pair, ",\n", "");
|
||||
obstack_free (&muscle_obstack, pair);
|
||||
}
|
||||
|
||||
@@ -262,7 +268,7 @@ muscle_boundary_grow (char const *key, boundary bound)
|
||||
obstack_escape (&muscle_obstack, bound.file);
|
||||
obstack_printf (&muscle_obstack, ":%d.%d]]", bound.line, bound.column);
|
||||
extension = obstack_finish0 (&muscle_obstack);
|
||||
muscle_grow (key, extension, "");
|
||||
muscle_grow (key, extension, "", "");
|
||||
obstack_free (&muscle_obstack, extension);
|
||||
}
|
||||
|
||||
@@ -275,7 +281,7 @@ static void
|
||||
muscle_location_grow (char const *key, location loc)
|
||||
{
|
||||
muscle_boundary_grow (key, loc.start);
|
||||
muscle_grow (key, "", ", ");
|
||||
muscle_grow (key, "", ", ", "");
|
||||
muscle_boundary_grow (key, loc.end);
|
||||
}
|
||||
|
||||
@@ -374,11 +380,11 @@ 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_grow (key, "[[[[", ",", "");
|
||||
muscle_grow (key, user_name, "", "");
|
||||
muscle_grow (key, "]], ", "", "");
|
||||
muscle_location_grow (key, loc);
|
||||
muscle_grow (key, "]]", "");
|
||||
muscle_grow (key, "]]", "", "");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -99,14 +99,9 @@ extern struct obstack muscle_obstack;
|
||||
MUSCLE_INSERT_STRING(Key, quotearg_style (c_quoting_style, Value))
|
||||
|
||||
|
||||
/* Append VALUE to the current value of KEY. If KEY did not already
|
||||
exist, create it. Use MUSCLE_OBSTACK. De-allocate the previously
|
||||
associated value. Copy VALUE and SEPARATOR. */
|
||||
void muscle_grow (const char *key, const char *value, 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. */
|
||||
in addition, issue a synchronization line for the location LOC.
|
||||
Be sure to append on a new line. */
|
||||
void muscle_code_grow (const char *key, const char *value, location loc);
|
||||
|
||||
|
||||
|
||||
@@ -1274,6 +1274,45 @@ special-char-@:>@.y:3.7: error: %code qualifier 'q' is not used
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
## ---------------- ##
|
||||
## Multiple %code. ##
|
||||
## ---------------- ##
|
||||
|
||||
AT_SETUP([Multiple %code])
|
||||
|
||||
# Make sure that repeated arguments to %code are separated by
|
||||
# end-of-lines. At some point, a missing eol would leave synclines
|
||||
# appended to the previous value. Here, we use CPP directive to
|
||||
# introduce dependency on the absence/presence of the eol.
|
||||
AT_BISON_OPTION_PUSHDEFS
|
||||
|
||||
AT_DATA([input.y],
|
||||
[[%code {#include <assert.h>}
|
||||
%code {#define A B}
|
||||
%code {#define B C}
|
||||
%code {#define C D}
|
||||
%code {#define D 42}
|
||||
%code {
|
||||
]AT_YYERROR_DECLARE[
|
||||
]AT_YYLEX_DECLARE[
|
||||
}
|
||||
%%
|
||||
start: %empty;
|
||||
%%
|
||||
]AT_YYERROR_DEFINE[
|
||||
]AT_YYLEX_DEFINE[
|
||||
int main (void)
|
||||
{
|
||||
assert (A == 42);
|
||||
return 0;
|
||||
}
|
||||
]])
|
||||
AT_FULL_COMPILE([input])
|
||||
AT_PARSER_CHECK([./input])
|
||||
|
||||
AT_BISON_OPTION_POPDEFS
|
||||
AT_CLEANUP()
|
||||
|
||||
## ---------------- ##
|
||||
## %define errors. ##
|
||||
## ---------------- ##
|
||||
|
||||
Reference in New Issue
Block a user