+/* FIXME. */
+
+static void
+parse_macro_decl (void)
+{
+ int ch = ungetc (skip_white_space (), finput);
+ char* macro_key;
+ char* macro_value;
+
+ /* Read key. */
+ if (!isalpha (ch) && ch != '_')
+ {
+ complain (_("invalid %s declaration"), "%define");
+ skip_to_char ('%');
+ return;
+ }
+ copy_identifier (finput, ¯o_obstack);
+ obstack_1grow (¯o_obstack, 0);
+ macro_key = obstack_finish (¯o_obstack);
+
+ /* Read value. */
+ ch = skip_white_space ();
+ if (ch != '"')
+ {
+ ungetc (ch, finput);
+ if (ch != EOF)
+ {
+ complain (_("invalid %s declaration"), "%define");
+ skip_to_char ('%');
+ return;
+ }
+ else
+ fatal (_("Premature EOF after %s"), "\"");
+ }
+ copy_string2 (finput, ¯o_obstack, '"', 0);
+ obstack_1grow (¯o_obstack, 0);
+ macro_value = obstack_finish (¯o_obstack);
+
+ /* Store the (key, value) pair in the environment. */
+ macro_insert (macro_key, macro_value);
+}
+
+
+/*----------------------------------.
+| Parse what comes after %skeleton. |
+`----------------------------------*/
+
+void
+parse_skel_decl (void)
+{
+ /* Complete with parse_dquoted_param () on the CVS branch 1.29. */
+}
+
+/*------------------------------------------.
+| Parse what comes after %header_extension. |
+`------------------------------------------*/
+
+static void
+parse_header_extension_decl (void)
+{
+ char buff[32];
+
+ if (header_extension)
+ complain (_("multiple %%header_extension declarations"));
+ fscanf (finput, "%s", buff);
+ header_extension = xstrdup (buff);
+}
+
+/*------------------------------------------.
+| Parse what comes after %source_extension. |
+`------------------------------------------*/
+
+static void
+parse_source_extension_decl (void)
+{
+ char buff[32];
+
+ if (src_extension)
+ complain (_("multiple %%source_extension declarations"));
+ fscanf (finput, "%s", buff);
+ src_extension = xstrdup (buff);
+}
+
+/*----------------------------------------------------------------.
+| Read from finput until `%%' is seen. Discard the `%%'. Handle |
+| any `%' declarations, and copy the contents of any `%{ ... %}' |
+| groups to ATTRS_OBSTACK. |
+`----------------------------------------------------------------*/
+
+static void
+read_declarations (void)
+{
+ int c;
+ int tok;
+
+ for (;;)
+ {
+ c = skip_white_space ();
+
+ if (c == '%')
+ {
+ tok = parse_percent_token ();
+
+ switch (tok)
+ {
+ case tok_two_percents:
+ return;
+
+ case tok_percent_left_curly:
+ copy_definition ();
+ break;
+
+ case tok_token:
+ parse_token_decl (token_sym, nterm_sym);
+ break;
+
+ case tok_nterm:
+ parse_token_decl (nterm_sym, token_sym);
+ break;
+
+ case tok_type:
+ parse_type_decl ();
+ break;
+
+ case tok_start:
+ parse_start_decl ();
+ break;
+
+ case tok_union:
+ parse_union_decl ();
+ break;
+
+ case tok_expect:
+ parse_expect_decl ();
+ break;
+
+ case tok_thong:
+ parse_thong_decl ();
+ break;
+
+ case tok_left:
+ parse_assoc_decl (left_assoc);
+ break;
+
+ case tok_right:
+ parse_assoc_decl (right_assoc);
+ break;
+
+ case tok_nonassoc:
+ parse_assoc_decl (non_assoc);
+ break;
+
+ case tok_hdrext:
+ parse_header_extension_decl ();
+ break;
+
+ case tok_srcext:
+ parse_source_extension_decl ();
+ break;
+
+ case tok_define:
+ parse_macro_decl ();
+ break;
+
+ case tok_skel:
+ parse_skel_decl ();
+ break;
+
+ case tok_noop:
+ break;
+
+ default:
+ complain (_("unrecognized: %s"), token_buffer);
+ skip_to_char ('%');
+ }
+ }
+ else if (c == EOF)
+ fatal (_("no input grammar"));
+ else
+ {
+ char buf[] = "c";
+ buf[0] = c;
+ complain (_("unknown character: %s"), quote (buf));
+ skip_to_char ('%');
+ }
+ }
+}