]> git.saurik.com Git - bison.git/blobdiff - src/output.c
Fix last warning from --enable-gcc-warnings.
[bison.git] / src / output.c
index d59429b03977966286a58276cdee590a002cb24e..73e634855e6c2a4a184e2e2b2d9e38a4a6d4a493 100644 (file)
@@ -143,6 +143,7 @@ prepare_symbols (void)
   MUSCLE_INSERT_BOOL ("token_table", token_table_flag);
   MUSCLE_INSERT_INT ("tokens_number", ntokens);
   MUSCLE_INSERT_INT ("nterms_number", nvars);
+  MUSCLE_INSERT_INT ("symbols_number", nsyms);
   MUSCLE_INSERT_INT ("undef_token_number", undeftoken->number);
   MUSCLE_INSERT_INT ("user_token_number_max", max_user_token_number);
 
@@ -282,28 +283,71 @@ prepare_states (void)
 }
 
 
+/*-------------------------------------------------------.
+| Compare two symbols by type-name, and then by number.  |
+`-------------------------------------------------------*/
+
+static int
+symbol_type_name_cmp (const symbol **lhs, const symbol **rhs)
+{
+  int res = UNIQSTR_CMP((*lhs)->type_name, (*rhs)->type_name);
+  if (res)
+    return res;
+  return (*lhs)->number - (*rhs)->number;
+}
+
+
+/*----------------------------------------------------------------.
+| Return a (malloc'ed) table of the symbols sorted by type-name.  |
+`----------------------------------------------------------------*/
+
+static symbol **
+symbols_by_type_name (void)
+{
+  typedef int (*qcmp_type) (const void *, const void *);
+  symbol **res = xmemdup (symbols, nsyms * sizeof *res);
+  qsort (res, nsyms, sizeof *res, (qcmp_type) &symbol_type_name_cmp);
+  return res;
+}
 
-/*-----------------------------------------------.
-| For each symbol type, its tags and type name.  |
-`-----------------------------------------------*/
+
+/*------------------------------------------------------------------.
+| Define b4_type_names, which is a list of (lists of the numbers of |
+| symbols with same type-name).                                     |
+`------------------------------------------------------------------*/
 
 static void
 type_names_output (FILE *out)
 {
   int i;
-
+  symbol **syms = symbols_by_type_name ();
   fputs ("m4_define([b4_type_names],\n[", out);
-  for (i = 0; i < nsyms; ++i)
+  for (i = 0; i < nsyms; /* nothing */)
     {
-      symbol *sym = symbols[i];
-      /* Symbol-name, Symbol-number, optional typename.  */
-      fprintf (out, "%s[", i ? ",\n" : "");
-      escaped_output (out, sym->tag);
-      fprintf (out, ", %d, [[%s]]]",
-               sym->number,
-               sym->type_name ? sym->type_name : "");
+      // The index of the first symbol of the current type-name.
+      int i0 = i;
+      fputs (i ? ",\n[" : "[", out);
+      for (; i < nsyms && syms[i]->type_name == syms[i0]->type_name; ++i)
+        fprintf (out, "%s%d", i != i0 ? ", " : "", syms[i]->number);
+      fputs ("]", out);
     }
   fputs ("])\n\n", out);
+  free (syms);
+}
+
+
+/*-------------------------------------.
+| The list of all the symbol numbers.  |
+`-------------------------------------*/
+
+static void
+symbol_numbers_output (FILE *out)
+{
+  int i;
+  fputs ("m4_define([b4_symbol_numbers],\n[", out);
+  for (i = 0; i < nsyms; ++i)
+    fprintf (out, "%s[%d]", i ? ", " : "", i);
+  fputs ("])\n\n", out);
 }
 
 
@@ -351,6 +395,60 @@ merger_output (FILE *out)
   fputs ("]])\n\n", out);
 }
 
+
+/*---------------------------------------------.
+| Prepare the muscles for symbol definitions.  |
+`---------------------------------------------*/
+
+static void
+prepare_symbol_definitions (void)
+{
+  int i;
+  for (i = 0; i < nsyms; ++i)
+    {
+      symbol *sym = symbols[i];
+      const char *key;
+      const char *value;
+
+#define SET_KEY(Entry)                                                  \
+      obstack_fgrow2 (&format_obstack, "symbol(%d, %s)", i, Entry);     \
+      obstack_1grow (&format_obstack, 0);                               \
+      key = obstack_finish (&format_obstack);
+
+      // Whether the symbol has an identifier.
+      value = symbol_id_get (sym);
+      SET_KEY("has_id");
+      MUSCLE_INSERT_INT (key, !!value);
+
+      // Its identifier.
+      SET_KEY("id");
+      MUSCLE_INSERT_STRING (key, value ? value : "");
+
+      // Its tag.  Typically for documentation purpose.
+      SET_KEY("tag");
+      MUSCLE_INSERT_STRING (key, sym->tag);
+
+      SET_KEY("user_number");
+      MUSCLE_INSERT_INT (key, sym->user_token_number);
+
+      SET_KEY("is_token");
+      MUSCLE_INSERT_INT (key,
+                         i < ntokens && sym != errtoken && sym != undeftoken);
+
+      SET_KEY("number");
+      MUSCLE_INSERT_INT (key, sym->number);
+
+      SET_KEY("has_type");
+      MUSCLE_INSERT_INT (key, !!sym->type_name);
+
+      SET_KEY("type");
+      MUSCLE_INSERT_STRING (key, sym->type_name ? sym->type_name : "");
+
+#undef SET_KEY
+    }
+}
+
+
 /*--------------------------------------.
 | Output the tokens definition to OUT.  |
 `--------------------------------------*/
@@ -485,6 +583,26 @@ prepare_actions (void)
   muscle_insert_unsigned_int_table ("conflicting_rules", conflict_list,
                                    0, 1, conflict_list_cnt);
 }
+
+
+/*--------------------------------------------.
+| Output the definitions of all the muscles.  |
+`--------------------------------------------*/
+
+static void
+muscles_output (FILE *out)
+{
+  fputs ("m4_init()\n", out);
+  merger_output (out);
+  symbol_code_props_output (out, "destructors", &symbol_destructor_get);
+  symbol_code_props_output (out, "printers", &symbol_printer_get);
+  symbol_numbers_output (out);
+  token_definitions_output (out);
+  type_names_output (out);
+  user_actions_output (out);
+  // Must be last.
+  muscles_m4_output (out);
+}
 \f
 /*---------------------------.
 | Call the skeleton parser.  |
@@ -494,7 +612,6 @@ static void
 output_skeleton (void)
 {
   FILE *in;
-  FILE *out;
   int filter_fd[2];
   char const *argv[9];
   pid_t pid;
@@ -582,23 +699,16 @@ output_skeleton (void)
   free (full_m4bison);
   free (full_skeleton);
 
-  out = fdopen (filter_fd[0], "w");
-  if (! out)
-    error (EXIT_FAILURE, get_errno (),
-          "fdopen");
-
-  /* Output the definitions of all the muscles.  */
-  fputs ("m4_init()\n", out);
-
-  type_names_output (out);
-  user_actions_output (out);
-  merger_output (out);
-  token_definitions_output (out);
-  symbol_code_props_output (out, "destructors", &symbol_destructor_get);
-  symbol_code_props_output (out, "printers", &symbol_printer_get);
-
-  muscles_m4_output (out);
-  xfclose (out);
+  if (trace_flag & trace_muscles)
+    muscles_output (stderr);
+  {
+    FILE *out = fdopen (filter_fd[0], "w");
+    if (! out)
+      error (EXIT_FAILURE, get_errno (),
+             "fdopen");
+    muscles_output (out);
+    xfclose (out);
+  }
 
   /* Read and process m4's output.  */
   timevar_push (TV_M4);
@@ -683,6 +793,7 @@ output (void)
   prepare_rules ();
   prepare_states ();
   prepare_actions ();
+  prepare_symbol_definitions ();
 
   prepare ();