- if (n < 0)
- {
- complain (_("invalid $ value"));
- return NULL;
- }
-
- rp = rule;
- i = 0;
-
- while (i < n)
- {
- rp = rp->next;
- if (rp == NULL || rp->sym == NULL)
- {
- complain (_("invalid $ value"));
- return NULL;
- }
- ++i;
- }
-
- return rp->sym->type_name;
-}
-\f
-/*------------------------------------------------------------------.
-| Copy the character C to OOUT, and insert quadigraphs when needed. |
-`------------------------------------------------------------------*/
-
-static inline void
-copy_character (struct obstack *oout, int c)
-{
- switch (c)
- {
- case '[':
- obstack_sgrow (oout, "@<:@");
- break;
-
- case ']':
- obstack_sgrow (oout, "@:>@");
- break;
-
- default:
- obstack_1grow (oout, c);
- }
-}
-
-/*------------------------------------------------------------.
-| Dump the string from FIN to OOUT if non null. MATCH is the |
-| delimiter of the string (either ' or "). |
-`------------------------------------------------------------*/
-
-static inline void
-copy_string2 (FILE *fin, struct obstack *oout, int match, int store)
-{
- int c;
-
- if (store)
- obstack_1grow (oout, match);
-
- c = getc (fin);
-
- while (c != match)
- {
- if (c == EOF)
- fatal (_("unterminated string at end of file"));
- if (c == '\n')
- {
- complain (_("unterminated string"));
- ungetc (c, fin);
- c = match; /* invent terminator */
- continue;
- }
-
- copy_character (oout, c);
-
- if (c == '\\')
- {
- c = getc (fin);
- if (c == EOF)
- fatal (_("unterminated string at end of file"));
- copy_character (oout, c);
-
- if (c == '\n')
- ++lineno;
- }
-
- c = getc (fin);
- }
-
- if (store)
- obstack_1grow (oout, c);
-}
-
-/* FIXME. */
-
-static inline void
-copy_string (FILE *fin, struct obstack *oout, int match)
-{
- copy_string2 (fin, oout, match, 1);
-}
-
-/* FIXME. */
-
-static inline void
-copy_identifier (FILE *fin, struct obstack *oout)
-{
- int c;
-
- while (isalnum (c = getc (fin)) || c == '_')
- obstack_1grow (oout, c);
-
- ungetc (c, fin);
-}
-
-
-/*------------------------------------------------------------------.
-| Dump the wannabee comment from IN to OOUT. In fact we just saw a |
-| `/', which might or might not be a comment. In any case, copy |
-| what we saw. |
-`------------------------------------------------------------------*/
-
-static inline void
-copy_comment (FILE *fin, struct obstack *oout)
-{
- int cplus_comment;
- int ended;
- int c;
-
- /* We read a `/', output it. */
- obstack_1grow (oout, '/');
-
- switch ((c = getc (fin)))
- {
- case '/':
- cplus_comment = 1;
- break;
- case '*':
- cplus_comment = 0;
- break;
- default:
- ungetc (c, fin);
- return;
- }
-
- obstack_1grow (oout, c);
- c = getc (fin);
-
- ended = 0;
- while (!ended)
- {
- if (!cplus_comment && c == '*')
- {
- while (c == '*')
- {
- obstack_1grow (oout, c);
- c = getc (fin);
- }
-
- if (c == '/')
- {
- obstack_1grow (oout, c);
- ended = 1;
- }
- }
- else if (c == '\n')
- {
- ++lineno;
- obstack_1grow (oout, c);
- if (cplus_comment)
- ended = 1;
- else
- c = getc (fin);
- }
- else if (c == EOF)
- fatal (_("unterminated comment"));
- else
- {
- copy_character (oout, c);
- c = getc (fin);
- }
- }
-}
-
-
-/*-------------------------------------------------------------------.
-| FIN is pointing to a location (i.e., a `@'). Output to OOUT a |
-| reference to this location. RULE_LENGTH is the number of values in |
-| the current rule so far, which says where to find `$0' with |
-| respect to the top of the stack. |
-`-------------------------------------------------------------------*/
-
-static inline void
-copy_at (FILE *fin, struct obstack *oout, int rule_length)
-{
- int c = getc (fin);
- locations_flag = 1;
-
- if (c == '$')
- {
- obstack_sgrow (oout, "]b4_lhs_location[");
- }
- else if (isdigit (c) || c == '-')
- {
- int n;
-
- ungetc (c, fin);
- n = read_signed_integer (fin);
- if (n > rule_length)
- complain (_("invalid value: %s%d"), "@", n);
- else
- obstack_fgrow2 (oout, "]b4_rhs_location([%d], [%d])[",
- rule_length, n);
- }
- else
- {
- char buf[] = "@c";
- buf[1] = c;
- complain (_("%s is invalid"), quote (buf));
- }
-}
-
-
-/*------------------------------------------------------------------.
-| FIN is pointing to a wannabee semantic value (i.e., a `$'). |
-| |
-| Possible inputs: $[<TYPENAME>]($|integer) |
-| |
-| Output to OOUT a reference to this semantic value. RULE_LENGTH is |
-| the number of values in the current rule so far, which says where |
-| to find `$0' with respect to the top of the stack. |
-`------------------------------------------------------------------*/
-
-static inline void
-copy_dollar (FILE *fin, struct obstack *oout,
- symbol_list *rule, int rule_length)
-{
- int c = getc (fin);
- const char *type_name = NULL;
-
- /* Get the type name if explicit. */
- if (c == '<')
- {
- read_type_name (fin);
- type_name = token_buffer;
- c = getc (fin);
- }
-
- if (c == '$')
- {
- if (!type_name)
- type_name = get_type_name (0, rule);
- if (!type_name && typed)
- complain (_("$$ of `%s' has no declared type"),
- rule->sym->tag);
- if (!type_name)
- type_name = "";
- obstack_fgrow1 (oout,
- "]b4_lhs_value([%s])[", type_name);
- }
- else if (isdigit (c) || c == '-')
- {
- int n;
- ungetc (c, fin);
- n = read_signed_integer (fin);
-
- if (n > rule_length)
- complain (_("invalid value: %s%d"), "$", n);
- else
- {
- if (!type_name && n > 0)
- type_name = get_type_name (n, rule);
- if (!type_name && typed)
- complain (_("$%d of `%s' has no declared type"),
- n, rule->sym->tag);
- if (!type_name)
- type_name = "";
- obstack_fgrow3 (oout, "]b4_rhs_value([%d], [%d], [%s])[",
- rule_length, n, type_name);
- }
- }
- else
- {
- char buf[] = "$c";
- buf[1] = c;
- complain (_("%s is invalid"), quote (buf));
- }
-}
-\f
-/*-------------------------------------------------------------------.
-| Copy the contents of a `%{ ... %}' into the definitions file. The |
-| `%{' has already been read. Return after reading the `%}'. |
-`-------------------------------------------------------------------*/
-
-static void
-copy_definition (struct obstack *oout)
-{
- int c;
- /* -1 while reading a character if prev char was %. */
- int after_percent;
-
- if (!no_lines_flag)
- {
- obstack_fgrow2 (oout, muscle_find ("linef"),
- lineno, quotearg_style (c_quoting_style,
- muscle_find ("filename")));
- }
-
- after_percent = 0;
-
- c = getc (finput);
-
- for (;;)
- {
- switch (c)
- {
- case '\n':
- obstack_1grow (oout, c);
- ++lineno;
- break;
-
- case '%':
- after_percent = -1;
- break;
-
- case '\'':
- case '"':
- copy_string (finput, oout, c);
- break;
-
- case '/':
- copy_comment (finput, oout);
- break;
-
- case EOF:
- fatal ("%s", _("unterminated `%{' definition"));
-
- default:
- copy_character (oout, c);
- }
-
- c = getc (finput);
-
- if (after_percent)
- {
- if (c == '}')
- return;
- obstack_1grow (oout, '%');
- }
- after_percent = 0;
- }
-}
-
-
-/*------------------------------------------.
-| Parse what comes after %token or %nterm. |
-`------------------------------------------*/
-
-static void
-parse_token_decl (symbol_class class)
-{
- token_t token = tok_undef;
- char *typename = NULL;
-
- /* The symbol being defined. */
- symbol_t *symbol = NULL;
-
- /* After `%token' and `%nterm', any number of symbols maybe be
- defined. */
- for (;;)
- {
- int tmp_char = ungetc (skip_white_space (), finput);
-
- /* `%' (for instance from `%token', or from `%%' etc.) is the
- only valid means to end this declaration. */
- if (tmp_char == '%')
- return;
- if (tmp_char == EOF)
- fatal (_("Premature EOF after %s"), token_buffer);
-
- token = lex ();
- switch (token)
- {
- case tok_comma:
- symbol = NULL;
- break;
-
- case tok_typename:
- typename = xstrdup (token_buffer);
- symbol = NULL;
- break;
-
- case tok_identifier:
- if (*symval->tag == '\"' && symbol)
- {
- symbol_make_alias (symbol, symval, typename);
- symbol = NULL;
- }
- else
- {
- symbol = symval;
- symbol_class_set (symbol, class);
- if (typename)
- symbol_type_set (symbol, typename);
- }
- break;
-
- case tok_number:
- symbol_user_token_number_set (symbol, numval);
- break;
-
- default:
- complain (_("`%s' is invalid in %s"),
- token_buffer,
- (class == token_sym) ? "%token" : "%nterm");
- skip_to_char ('%');
- }
- }
-
-}
-
-
-/*------------------------------.
-| Parse what comes after %start |
-`------------------------------*/
-
-static void
-parse_start_decl (void)