]> git.saurik.com Git - bison.git/blobdiff - src/muscle-tab.c
muscle: enforce definition syntax for keyword variables
[bison.git] / src / muscle-tab.c
index 10a0a5cbba7d0f68d1e75275a44378e2f60f66b5..8925d22864dcb814829527770decf0ae4c3ca595 100644 (file)
@@ -63,6 +63,18 @@ typedef struct
   muscle_kind kind;
 } muscle_entry;
 
+
+/* The name of muscle for the %define variable VAR (corresponding to
+   FIELD, if defined).  */
+static uniqstr
+muscle_name (char const *var, char const *field)
+{
+  if (field)
+    return UNIQSTR_CONCAT ("percent_define_", field, "(", var, ")");
+  else
+    return UNIQSTR_CONCAT ("percent_define(", var, ")");
+}
+
 /* An obstack used to create some entries.  */
 struct obstack muscle_obstack;
 
@@ -153,33 +165,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 +214,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 +228,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 +243,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 +280,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 +293,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);
 }
 
@@ -326,10 +344,9 @@ string_decode (char const *key)
 
 /* Reverse of muscle_location_grow.  */
 static location
-location_decode (char const *key)
+location_decode (char const *value)
 {
   location loc;
-  char const *value = muscle_find_const (key);
   aver (value);
   aver (*value == '[');
   aver (*++value == '[');
@@ -374,11 +391,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, "]]", "", "");
 }
 
 
@@ -478,13 +495,11 @@ muscle_percent_define_insert (char const *var, location variable_loc,
 {
   /* Backward compatibility.  */
   char *variable = muscle_percent_variable_update (var, variable_loc, &value);
-  char const *name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
-  char const *loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")");
-  char const *syncline_name =
-    UNIQSTR_CONCAT ("percent_define_syncline(", variable, ")");
-  char const *how_name = UNIQSTR_CONCAT ("percent_define_how(", variable, ")");
-  char const *kind_name =
-    UNIQSTR_CONCAT ("percent_define_kind(", variable, ")");
+  uniqstr name = muscle_name (variable, NULL);
+  uniqstr loc_name = muscle_name (variable, "loc");
+  uniqstr syncline_name = muscle_name (variable, "syncline");
+  uniqstr how_name = muscle_name (variable, "how");
+  uniqstr kind_name = muscle_name (variable, "kind");
 
   /* Command-line options are processed before the grammar file.  */
   if (how == MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE
@@ -521,81 +536,119 @@ void
 muscle_percent_define_ensure (char const *variable, location loc,
                               bool value)
 {
-  char const *name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
+  uniqstr name = muscle_name (variable, NULL);
   char const *val = value ? "" : "false";
 
   /* Don't complain is VARIABLE is already defined, but be sure to set
      its value to VAL.  */
-  if (!muscle_find_const (name))
-    muscle_percent_define_insert (variable, loc, muscle_keyword, val,
-                                  MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
-  if (muscle_percent_define_flag_if (variable) != value)
+  if (!muscle_find_const (name)
+      || muscle_percent_define_flag_if (variable) != value)
     muscle_percent_define_insert (variable, loc, muscle_keyword, val,
                                   MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
 }
 
+/* Mark %define VARIABLE as used.  */
+static void
+muscle_percent_define_use (char const *variable)
+{
+  muscle_insert (muscle_name (variable, "bison_variables"), "");
+}
+
+/* The value of %define variable VARIABLE (corresponding to FIELD, if
+   defined).  Do not register as used, but diagnose unset variables.  */
+
+char const *
+muscle_percent_define_get_raw (char const *variable, char const *field)
+{
+  uniqstr name = muscle_name (variable, field);
+  char const *res = muscle_find_const (name);
+  if (!res)
+    complain (NULL, fatal, _("%s: undefined %%define variable %s"),
+              "muscle_percent_define_get_raw", quote (variable));
+  return res;
+}
+
 char *
 muscle_percent_define_get (char const *variable)
 {
-  char const *name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
-  char const *usage_name =
-    UNIQSTR_CONCAT ("percent_define_bison_variables(", variable, ")");
+  uniqstr name = muscle_name (variable, NULL);
   char *value = string_decode (name);
   if (!value)
     value = xstrdup ("");
-
-  muscle_insert (usage_name, "");
+  muscle_percent_define_use (variable);
   return value;
 }
 
+/* The kind of VARIABLE.  An error if undefined.  */
+static muscle_kind
+muscle_percent_define_get_kind (char const *variable)
+{
+  return muscle_kind_new (muscle_percent_define_get_raw (variable, "kind"));
+}
+
+/* Check the kind of VARIABLE.  An error if undefined.  */
+static void
+muscle_percent_define_check_kind (char const *variable, muscle_kind kind)
+{
+  if (muscle_percent_define_get_kind (variable) != kind)
+    {
+      location loc = muscle_percent_define_get_loc (variable);
+      switch (kind)
+        {
+        case muscle_code:
+          complain (&loc, Wdeprecated,
+                    "%%define variable '%s' requires '{...}' values",
+                    variable);
+          break;
+        case muscle_keyword:
+          complain (&loc, Wdeprecated,
+                    "%%define variable '%s' requires keyword values",
+                    variable);
+          break;
+        case muscle_string:
+          complain (&loc, Wdeprecated,
+                    "%%define variable '%s' requires '\"...\"' values",
+                    variable);
+          break;
+        }
+    }
+}
+
+
 location
 muscle_percent_define_get_loc (char const *variable)
 {
-  char const *loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")");
-  if (!muscle_find_const (loc_name))
-    complain (NULL, fatal, _("%s: undefined %%define variable %s"),
-              "muscle_percent_define_get_loc", quote (variable));
-  return location_decode (loc_name);
+  return location_decode (muscle_percent_define_get_raw (variable, "loc"));
 }
 
 char const *
 muscle_percent_define_get_syncline (char const *variable)
 {
-  char const *syncline_name =
-    UNIQSTR_CONCAT ("percent_define_syncline(", variable, ")");
-  char const *syncline = muscle_find_const (syncline_name);
-  if (!syncline)
-    complain (NULL, fatal, _("%s: undefined %%define variable %s"),
-              "muscle_percent_define_get_syncline", quote (variable));
-  return syncline;
+  return muscle_percent_define_get_raw (variable, "syncline");
 }
 
 bool
 muscle_percent_define_ifdef (char const *variable)
 {
-  char const *name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
-  char const *usage_name =
-    UNIQSTR_CONCAT ("percent_define_bison_variables(", variable, ")");
-  char const *value = muscle_find_const (name);
-  if (value)
+  if (muscle_find_const (muscle_name (variable, NULL)))
     {
-      muscle_insert (usage_name, "");
+      muscle_percent_define_use (variable);
       return true;
     }
-
-  return false;
+  else
+    return false;
 }
 
 bool
 muscle_percent_define_flag_if (char const *variable)
 {
-  char const *invalid_boolean_name =
-    UNIQSTR_CONCAT ("percent_define_invalid_boolean(", variable, ")");
+  uniqstr invalid_boolean_name = muscle_name (variable, "invalid_boolean");
   bool result = false;
 
   if (muscle_percent_define_ifdef (variable))
     {
       char *value = muscle_percent_define_get (variable);
+      muscle_percent_define_check_kind (variable, muscle_keyword);
       if (value[0] == '\0' || STREQ (value, "true"))
         result = true;
       else if (STREQ (value, "false"))
@@ -620,20 +673,21 @@ muscle_percent_define_flag_if (char const *variable)
 void
 muscle_percent_define_default (char const *variable, char const *value)
 {
-  char const *name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
-  char const *loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")");
-  char const *syncline_name =
-    UNIQSTR_CONCAT ("percent_define_syncline(", variable, ")");
+  uniqstr name = muscle_name (variable, NULL);
   if (!muscle_find_const (name))
     {
-      location loc;
       MUSCLE_INSERT_STRING (name, value);
-      loc.start.file = loc.end.file = "<default value>";
-      loc.start.line = loc.end.line = -1;
-      loc.start.column = loc.end.column = -1;
-      muscle_insert (loc_name, "");
-      muscle_location_grow (loc_name, loc);
-      muscle_insert (syncline_name, "");
+      MUSCLE_INSERT_STRING (muscle_name (variable, "kind"), "keyword");
+      {
+        uniqstr loc_name = muscle_name (variable, "loc");
+        location loc;
+        loc.start.file = loc.end.file = "<default value>";
+        loc.start.line = loc.end.line = -1;
+        loc.start.column = loc.end.column = -1;
+        muscle_insert (loc_name, "");
+        muscle_location_grow (loc_name, loc);
+      }
+      muscle_insert (muscle_name (variable, "syncline"), "");
     }
 }
 
@@ -643,8 +697,9 @@ muscle_percent_define_check_values (char const * const *values)
   for (; *values; ++values)
     {
       char const * const *variablep = values;
-      char const *name = UNIQSTR_CONCAT ("percent_define(", *variablep, ")");
+      uniqstr name = muscle_name (*variablep, NULL);
       char *value = string_decode (name);
+      muscle_percent_define_check_kind (*variablep, muscle_keyword);
       if (value)
         {
           for (++values; *values; ++values)