]> git.saurik.com Git - bison.git/commitdiff
muscles: be sure that %code snippets are not glue together on a single line
authorAkim Demaille <akim@lrde.epita.fr>
Thu, 11 Apr 2013 07:21:08 +0000 (09:21 +0200)
committerAkim Demaille <akim@lrde.epita.fr>
Thu, 11 Apr 2013 07:21:08 +0000 (09:21 +0200)
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.

src/muscle-tab.c
src/muscle-tab.h
tests/input.at

index 10a0a5cbba7d0f68d1e75275a44378e2f60f66b5..9d15cf768dbd53414bc97c94ee585b31a5a16484 100644 (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  |
-| 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, "]]", "", "");
 }
 
 
index af6b615c3195f6a5bb9fb594b4cc7fb5da071f8d..3199a2d43c029124a40fade430ba6a705f71c657 100644 (file)
@@ -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);
 
 
index 322bbe8775b00ceeaf11010c7381597e5e54fb1b..aec855d7c349e00366caaa5b95f739c8f7b9cf39 100644 (file)
@@ -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.  ##
 ## ---------------- ##