]> git.saurik.com Git - bison.git/blobdiff - src/muscle_tab.c
2007-11-08 Paolo Bonzini <bonzini@gnu.org>
[bison.git] / src / muscle_tab.c
index f096dc0bc539f2595b1d8405bd57fb511d77a660..afe59becab0be10d0f144e2b3d0b61d2c6fda364 100644 (file)
@@ -5,20 +5,18 @@
 
    This file is part of Bison, the GNU Compiler Compiler.
 
-   Bison is free software; you can redistribute it and/or modify
+   This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
 
-   Bison is distributed in the hope that it will be useful,
+   This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with Bison; see the file COPYING.  If not, write to
-   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 #include "system.h"
@@ -170,27 +168,38 @@ muscle_grow (const char *key, const char *val, 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.   |
+| Using muscle_grow, append a synchronization line for the location |
+| LOC to the current value of KEY.                                  |
 `------------------------------------------------------------------*/
 
-void
-muscle_code_grow (const char *key, const char *val, location loc)
+static void
+muscle_syncline_grow (char const *key, location loc)
 {
   char *extension = NULL;
   obstack_fgrow1 (&muscle_obstack, "]b4_syncline(%d, [[", loc.start.line);
   MUSCLE_OBSTACK_SGROW (&muscle_obstack,
                        quotearg_style (c_quoting_style, loc.start.file));
-  obstack_sgrow (&muscle_obstack, "]])[\n");
-  obstack_sgrow (&muscle_obstack, val);
+  obstack_sgrow (&muscle_obstack, "]])[");
   obstack_1grow (&muscle_obstack, 0);
   extension = obstack_finish (&muscle_obstack);
   muscle_grow (key, extension, "");
   obstack_free (&muscle_obstack, extension);
 }
 
+/*------------------------------------------------------------------.
+| Append VALUE to the current value of KEY, using muscle_grow.  But |
+| in addition, issue a synchronization line for the location LOC    |
+| using muscle_syncline_grow.                                       |
+`------------------------------------------------------------------*/
+
+void
+muscle_code_grow (const char *key, const char *val, location loc)
+{
+  muscle_syncline_grow (key, loc);
+  muscle_grow (key, val, "\n");
+}
+
 
 void muscle_pair_list_grow (const char *muscle,
                            const char *a1, const char *a2)
@@ -275,6 +284,52 @@ muscle_location_grow (char const *key, location loc)
   muscle_grow (key, "]]", "");
 }
 
+#define MUSCLE_COMMON_DECODE(Value)                                           \
+  case '$':                                                                   \
+    aver (*++(Value) == ']');                                                 \
+    aver (*++(Value) == '[');                                                 \
+    obstack_sgrow (&muscle_obstack, "$");                                     \
+    break;                                                                    \
+  case '@':                                                                   \
+    switch (*++(Value))                                                       \
+      {                                                                       \
+        case '@': obstack_sgrow (&muscle_obstack, "@" ); break;               \
+        case '{': obstack_sgrow (&muscle_obstack, "[" ); break;               \
+        case '}': obstack_sgrow (&muscle_obstack, "]" ); break;               \
+        default: aver (false); break;                                         \
+      }                                                                       \
+    break;                                                                    \
+  default:                                                                    \
+    obstack_1grow (&muscle_obstack, *(Value));                                \
+    break;
+
+/* Reverse of MUSCLE_OBSTACK_SGROW.  */
+static char *
+muscle_string_decode (char const *key)
+{
+  char const *value;
+  char *value_decoded;
+  char *result;
+
+  value = muscle_find_const (key);
+  if (!value)
+    return NULL;
+  do {
+    switch (*value)
+      {
+        MUSCLE_COMMON_DECODE (value)
+        case '[':
+        case ']':
+          aver (false);
+          break;
+      }
+  } while (*value++);
+  value_decoded = obstack_finish (&muscle_obstack);
+  result = xstrdup (value_decoded);
+  obstack_free (&muscle_obstack, value_decoded);
+  return result;
+}
+
 /* Reverse of muscle_location_grow.  */
 static location
 muscle_location_decode (char const *key)
@@ -287,20 +342,7 @@ muscle_location_decode (char const *key)
   while (*++value)
     switch (*value)
       {
-        case '$':
-          aver (*++value == ']');
-          aver (*++value == '[');
-          obstack_sgrow (&muscle_obstack, "$");
-          break;
-        case '@':
-          switch (*++value)
-            {
-              case '@': obstack_sgrow (&muscle_obstack, "@" ); break;
-              case '{': obstack_sgrow (&muscle_obstack, "[" ); break;
-              case '}': obstack_sgrow (&muscle_obstack, "]" ); break;
-              default: aver (false); break;
-            }
-          break;
+        MUSCLE_COMMON_DECODE (value)
         case '[':
           aver (false);
           break;
@@ -330,9 +372,6 @@ muscle_location_decode (char const *key)
               }
           }
           break;
-        default:
-          obstack_1grow (&muscle_obstack, *value);
-          break;
       }
   aver (false);
   return loc;
@@ -367,56 +406,123 @@ muscle_percent_define_insert (char const *variable, location variable_loc,
 {
   char const *name;
   char const *loc_name;
+  char const *syncline_name;
 
   MUSCLE_USER_NAME_CONVERT (name, "percent_define(", variable, ")");
   MUSCLE_USER_NAME_CONVERT (loc_name, "percent_define_loc(", variable, ")");
+  MUSCLE_USER_NAME_CONVERT (syncline_name,
+                            "percent_define_syncline(", variable, ")");
 
   if (muscle_find_const (name))
     {
       warn_at (variable_loc, _("%s `%s' redefined"),
                "%define variable", variable);
-      warn_at (muscle_location_decode (loc_name), _("previous definition"));
+      warn_at (muscle_percent_define_get_loc (variable),
+               _("previous definition"));
     }
   MUSCLE_INSERT_STRING (name, value);
 
   muscle_insert (loc_name, "");
   muscle_location_grow (loc_name, variable_loc);
+  muscle_insert (syncline_name, "");
+  muscle_syncline_grow (syncline_name, variable_loc);
   muscle_user_name_list_grow ("percent_define_user_variables", variable,
                               variable_loc);
 }
 
-bool
-muscle_percent_define_flag_if (char const *variable)
+char *
+muscle_percent_define_get (char const *variable)
 {
   char const *name;
+  char const *usage_name;
+  char *value;
+
+  MUSCLE_USER_NAME_CONVERT (name, "percent_define(", variable, ")");
+  MUSCLE_USER_NAME_CONVERT (usage_name, "percent_define_bison_variables(",
+                            variable, ")");
+
+  muscle_insert (usage_name, "");
+  value = muscle_string_decode (name);
+  if (!value)
+    value = xstrdup ("");
+  return value;
+}
+
+location
+muscle_percent_define_get_loc (char const *variable)
+{
   char const *loc_name;
+  MUSCLE_USER_NAME_CONVERT (loc_name, "percent_define_loc(", variable, ")");
+  if (!muscle_find_const (loc_name))
+    fatal(_("undefined %%define variable `%s' passed to muscle_percent_define_get_loc"),
+          variable);
+  return muscle_location_decode (loc_name);
+}
+
+char const *
+muscle_percent_define_get_syncline (char const *variable)
+{
+  char const *syncline_name;
+  char const *syncline;
+  MUSCLE_USER_NAME_CONVERT (syncline_name,
+                            "percent_define_syncline(", variable, ")");
+  syncline = muscle_find_const (syncline_name);
+  if (!syncline)
+    fatal(_("undefined %%define variable `%s' passed to muscle_percent_define_get_syncline"),
+          variable);
+  return syncline;
+}
+
+bool
+muscle_percent_define_ifdef (char const *variable)
+{
+  char const *name;
   char const *usage_name;
   char const *value;
-  bool result = false;
 
   MUSCLE_USER_NAME_CONVERT (name, "percent_define(", variable, ")");
-  MUSCLE_USER_NAME_CONVERT (loc_name, "percent_define_loc(", variable, ")");
   MUSCLE_USER_NAME_CONVERT (usage_name, "percent_define_bison_variables(",
                             variable, ")");
 
   value = muscle_find_const (name);
   if (value)
     {
+      muscle_insert (usage_name, "");
+      return true;
+    }
+
+  return false;
+}
+
+bool
+muscle_percent_define_flag_if (char const *variable)
+{
+  char const *invalid_boolean_name;
+  bool result = false;
+
+  MUSCLE_USER_NAME_CONVERT (invalid_boolean_name,
+                            "percent_define_invalid_boolean(", variable, ")");
+
+  if (muscle_percent_define_ifdef (variable))
+    {
+      char *value = muscle_percent_define_get (variable);
       if (value[0] == '\0' || 0 == strcmp (value, "true"))
         result = true;
       else if (0 == strcmp (value, "false"))
         result = false;
-      else if (!muscle_find_const (usage_name))
-        complain_at(muscle_location_decode (loc_name),
-                    _("invalid value for %%define boolean variable `%s'"),
-                    variable);
+      else if (!muscle_find_const (invalid_boolean_name))
+        {
+          muscle_insert (invalid_boolean_name, "");
+          complain_at(muscle_percent_define_get_loc (variable),
+                      _("invalid value for %%define Boolean variable `%s'"),
+                      variable);
+        }
+      free (value);
     }
   else
     fatal(_("undefined %%define variable `%s' passed to muscle_percent_define_flag_if"),
           variable);
 
-  muscle_insert (usage_name, "");
-
   return result;
 }
 
@@ -425,17 +531,59 @@ muscle_percent_define_default (char const *variable, char const *value)
 {
   char const *name;
   char const *loc_name;
+  char const *syncline_name;
   MUSCLE_USER_NAME_CONVERT (name, "percent_define(", variable, ")");
   MUSCLE_USER_NAME_CONVERT (loc_name, "percent_define_loc(", variable, ")");
+  MUSCLE_USER_NAME_CONVERT (syncline_name,
+                            "percent_define_syncline(", variable, ")");
   if (!muscle_find_const (name))
     {
       location loc;
       MUSCLE_INSERT_STRING (name, value);
       loc.start.file = loc.end.file = "[Bison:muscle_percent_define_default]";
-      loc.start.line = loc.start.column = 0;
-      loc.end.line = loc.end.column = 0;
+      loc.start.line = loc.end.line = 1;
+      loc.start.column = loc.end.column = 0;
       muscle_insert (loc_name, "");
       muscle_location_grow (loc_name, loc);
+      muscle_insert (syncline_name, "");
+      muscle_syncline_grow (syncline_name, loc);
+    }
+}
+
+void
+muscle_percent_define_check_values (char const * const *values)
+{
+  for (; *values; ++values)
+    {
+      char const *variable = *values;
+      char const *name;
+      char *value;
+
+      MUSCLE_USER_NAME_CONVERT (name, "percent_define(", variable, ")");
+
+      value = muscle_string_decode (name);
+      if (value)
+        {
+          bool valid = false;
+          for (++values; *values; ++values)
+            {
+              if (0 == strcmp (value, *values))
+                {
+                  valid = true;
+                  while (*values)
+                    ++values;
+                  break;
+                }
+            }
+          if (!valid)
+            complain_at(muscle_percent_define_get_loc (variable),
+                        _("invalid value for %%define variable `%s': `%s'"),
+                        variable, value);
+          free (value);
+        }
+      else
+        fatal(_("undefined %%define variable `%s' passed to muscle_percent_define_check_values"),
+              variable);
     }
 }