}
+/*-------------------------------------------------------.
+| 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;
+}
+
+
+/*------------------------------------------------------------------.
+| 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; /* nothing */)
+ {
+ // 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. |
}
-/*---------------------------------------.
-| Output the symbol definitions to OUT. |
-`---------------------------------------*/
+/*---------------------------------------------.
+| Prepare the muscles for symbol definitions. |
+`---------------------------------------------*/
static void
-symbol_definitions_output (FILE *out)
+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("type_name");
+ 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
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_definitions_output (out);
symbol_numbers_output (out);
token_definitions_output (out);
+ type_names_output (out);
user_actions_output (out);
-
+ // Must be last.
muscles_m4_output (out);
}
\f
free (full_m4bison);
free (full_skeleton);
-
if (trace_flag & trace_muscles)
muscles_output (stderr);
{
prepare_rules ();
prepare_states ();
prepare_actions ();
+ prepare_symbol_definitions ();
prepare ();