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:
Akim Demaille
2013-04-11 09:21:08 +02:00
parent edaa22ec15
commit 08cc1a3b18
3 changed files with 74 additions and 34 deletions

View File

@@ -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, "]]", "", "");
} }

View File

@@ -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);

View File

@@ -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. ##
## ---------------- ## ## ---------------- ##