X-Git-Url: https://git.saurik.com/bison.git/blobdiff_plain/5ab8c47bcf5088cf420db6e03cd44bfa68e92ca0..8be046d7b84f6949ecc0eb80abb4edb02dacae76:/src/output.c diff --git a/src/output.c b/src/output.c index 8457ba19..afcec949 100644 --- a/src/output.c +++ b/src/output.c @@ -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,29 +283,71 @@ prepare_states (void) } +/*-------------------------------------------------------. +| Compare two symbols by type-name, and then by number. | +`-------------------------------------------------------*/ -/*-----------------------------------------------. -| For each symbol type, its tags and type name. | -`-----------------------------------------------*/ +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 () +{ + 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; - char const *sep = ""; - + 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); } @@ -329,9 +372,9 @@ user_actions_output (FILE *out) fputs ("])\n\n", out); } -/*--------------------------------------. -| Output the merge functions to OUT. | -`--------------------------------------*/ +/*------------------------------------. +| Output the merge functions to OUT. | +`------------------------------------*/ static void merger_output (FILE *out) @@ -352,6 +395,74 @@ merger_output (FILE *out) fputs ("]])\n\n", out); } + +/*----------------------------------. +| Whether S is a valid identifier. | +`----------------------------------*/ + +static bool +is_identifier (uniqstr s) +{ + static char const alphanum[26 + 26 + 1 + 10] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "_" + "0123456789"; + if (!s || ! memchr (alphanum, *s, sizeof alphanum - 10)) + return false; + for (++s; *s; ++s) + if (! memchr (alphanum, *s, sizeof alphanum)) + return false; + return true; +} + +/*---------------------------------------. +| Output the symbol definitions to OUT. | +`---------------------------------------*/ + +static void +symbol_definitions_output (FILE *out) +{ + int i; + for (i = 0; i < nsyms; ++i) + { + symbol *sym = symbols[i]; + const char *key; + +#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 tag is a valid identifier. + SET_KEY("tag_is_id"); + MUSCLE_INSERT_INT (key, is_identifier(sym->tag)); + + // The inner tag. + 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_name"); + MUSCLE_INSERT_INT (key, !!sym->type_name); + + SET_KEY("type_name"); + MUSCLE_INSERT_STRING (key, sym->type_name ? sym->type_name : ""); + +#undef SET_KEY + } +} + + /*--------------------------------------. | Output the tokens definition to OUT. | `--------------------------------------*/ @@ -486,6 +597,27 @@ 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_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); +} /*---------------------------. | Call the skeleton parser. | @@ -495,7 +627,6 @@ static void output_skeleton (void) { FILE *in; - FILE *out; int filter_fd[2]; char const *argv[9]; pid_t pid; @@ -583,23 +714,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);