mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-18 16:53:02 +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
|
||||||
| Append VALUE to the current value of KEY. If KEY did not already |
|
exist, create it. Use MUSCLE_OBSTACK. De-allocate the previously
|
||||||
| exist, create it. Use MUSCLE_OBSTACK. De-allocate the previously |
|
associated value. Copy VALUE and SEPARATOR. If VALUE does not end
|
||||||
| associated value. Copy VALUE and SEPARATOR. |
|
with TERMINATOR, append one. */
|
||||||
`-------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void
|
static void
|
||||||
muscle_grow (const char *key, const char *val, const char *separator)
|
muscle_grow (const char *key, const char *val,
|
||||||
|
const char *separator, const char *terminator)
|
||||||
{
|
{
|
||||||
muscle_entry *entry = muscle_lookup (key);
|
muscle_entry *entry = muscle_lookup (key);
|
||||||
|
size_t vals = strlen (val);
|
||||||
|
size_t terms = strlen (terminator);
|
||||||
|
|
||||||
if (entry)
|
if (entry)
|
||||||
{
|
{
|
||||||
/* Grow the current value. */
|
obstack_sgrow (&muscle_obstack, entry->value);
|
||||||
char *new_val;
|
obstack_sgrow (&muscle_obstack, separator);
|
||||||
obstack_printf (&muscle_obstack, "%s%s%s", entry->value, separator, val);
|
|
||||||
free (entry->storage);
|
free (entry->storage);
|
||||||
new_val = obstack_finish0 (&muscle_obstack);
|
|
||||||
entry->value = entry->storage = xstrdup (new_val);
|
|
||||||
obstack_free (&muscle_obstack, new_val);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
entry = muscle_entry_new (key);
|
||||||
/* First insertion in the hash. */
|
|
||||||
entry = muscle_entry_new (key);
|
obstack_sgrow (&muscle_obstack, val);
|
||||||
entry->value = entry->storage = xstrdup (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));
|
quotearg_style (c_quoting_style, loc.start.file));
|
||||||
obstack_sgrow (&muscle_obstack, ")[");
|
obstack_sgrow (&muscle_obstack, ")[");
|
||||||
extension = obstack_finish0 (&muscle_obstack);
|
extension = obstack_finish0 (&muscle_obstack);
|
||||||
muscle_grow (key, extension, "");
|
muscle_grow (key, extension, "", "");
|
||||||
obstack_free (&muscle_obstack, extension);
|
obstack_free (&muscle_obstack, extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,7 +216,7 @@ void
|
|||||||
muscle_code_grow (const char *key, const char *val, location loc)
|
muscle_code_grow (const char *key, const char *val, location loc)
|
||||||
{
|
{
|
||||||
muscle_syncline_grow (key, 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_quote (&muscle_obstack, a2);
|
||||||
obstack_sgrow (&muscle_obstack, "]");
|
obstack_sgrow (&muscle_obstack, "]");
|
||||||
pair = obstack_finish0 (&muscle_obstack);
|
pair = obstack_finish0 (&muscle_obstack);
|
||||||
muscle_grow (muscle, pair, ",\n");
|
muscle_grow (muscle, pair, ",\n", "");
|
||||||
obstack_free (&muscle_obstack, pair);
|
obstack_free (&muscle_obstack, pair);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,7 +268,7 @@ muscle_boundary_grow (char const *key, boundary bound)
|
|||||||
obstack_escape (&muscle_obstack, bound.file);
|
obstack_escape (&muscle_obstack, bound.file);
|
||||||
obstack_printf (&muscle_obstack, ":%d.%d]]", bound.line, bound.column);
|
obstack_printf (&muscle_obstack, ":%d.%d]]", bound.line, bound.column);
|
||||||
extension = obstack_finish0 (&muscle_obstack);
|
extension = obstack_finish0 (&muscle_obstack);
|
||||||
muscle_grow (key, extension, "");
|
muscle_grow (key, extension, "", "");
|
||||||
obstack_free (&muscle_obstack, extension);
|
obstack_free (&muscle_obstack, extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,7 +281,7 @@ static void
|
|||||||
muscle_location_grow (char const *key, location loc)
|
muscle_location_grow (char const *key, location loc)
|
||||||
{
|
{
|
||||||
muscle_boundary_grow (key, loc.start);
|
muscle_boundary_grow (key, loc.start);
|
||||||
muscle_grow (key, "", ", ");
|
muscle_grow (key, "", ", ", "");
|
||||||
muscle_boundary_grow (key, loc.end);
|
muscle_boundary_grow (key, loc.end);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,11 +380,11 @@ void
|
|||||||
muscle_user_name_list_grow (char const *key, char const *user_name,
|
muscle_user_name_list_grow (char const *key, char const *user_name,
|
||||||
location loc)
|
location loc)
|
||||||
{
|
{
|
||||||
muscle_grow (key, "[[[[", ",");
|
muscle_grow (key, "[[[[", ",", "");
|
||||||
muscle_grow (key, user_name, "");
|
muscle_grow (key, user_name, "", "");
|
||||||
muscle_grow (key, "]], ", "");
|
muscle_grow (key, "]], ", "", "");
|
||||||
muscle_location_grow (key, loc);
|
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))
|
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
|
/* 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);
|
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
|
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. ##
|
## %define errors. ##
|
||||||
## ---------------- ##
|
## ---------------- ##
|
||||||
|
|||||||
Reference in New Issue
Block a user