[packages/bison] Rel 2. Fix CVE-2026-56389 and CVE-2026-56390 (upstream patches).

arekm arekm at pld-linux.org
Sun Oct 18 20:19:34 CEST 2026


commit d92b0e87cac1a0ec820bcb7f488450089ae86e2a
Author: Arkadiusz Miśkiewicz <arekm at maven.pl>
Date:   Sun Oct 18 20:19:20 2026 +0200

    Rel 2. Fix CVE-2026-56389 and CVE-2026-56390 (upstream patches).
    
    CVE-2026-56389: a grammar could pick the program run by bison --html
    via the undocumented %define tool.xsltproc, allowing arbitrary program
    execution. xsltproc is now always taken from PATH (upstream 3169c1e7).
    
    CVE-2026-56390: %output and %header file names containing '/' could
    direct generated files outside the output directory. Such names are
    now rejected (upstream 8d101c19; parse-gram.[ch] regenerated from the
    patched parse-gram.y with the same bison and flags upstream uses).
    
    Also: switch deprecated %patch1 to %patch -P1 -p1, drop the
    untranslated ro bison-gnulib.mo (find_lang already skips it), and use
    an https URL.

 bison-CVE-2026-56389.patch |   40 ++
 bison-CVE-2026-56390.patch | 1652 ++++++++++++++++++++++++++++++++++++++++++++
 bison.spec                 |   13 +-
 3 files changed, 1702 insertions(+), 3 deletions(-)
---
diff --git a/bison.spec b/bison.spec
index 997361f..3368e88 100644
--- a/bison.spec
+++ b/bison.spec
@@ -13,7 +13,7 @@ Summary(tr.UTF-8):	GNU ayrıştırıcı üreticisi
 Summary(uk.UTF-8):	Bison - генератор парсерів GNU
 Name:		bison
 Version:	3.8.2
-Release:	1
+Release:	2
 License:	GPL v3+
 Group:		Development/Tools
 Source0:	https://ftp.gnu.org/gnu/bison/%{name}-%{version}.tar.lz
@@ -21,7 +21,9 @@ Source0:	https://ftp.gnu.org/gnu/bison/%{name}-%{version}.tar.lz
 Source1:	%{name}.1.pl
 Patch0:		%{name}-info.patch
 Patch1:		no_libtextstyle.patch
-URL:		http://www.gnu.org/software/bison/
+Patch2:		%{name}-CVE-2026-56389.patch
+Patch3:		%{name}-CVE-2026-56390.patch
+URL:		https://www.gnu.org/software/bison/
 BuildRequires:	flex
 BuildRequires:	gcc >= 5:3.2
 BuildRequires:	gettext-tools >= 0.19
@@ -111,7 +113,9 @@ zawierajacych parsery wygenerowane przez bisona.
 %prep
 %setup -q
 %patch -P0 -p1
-%{!?with_libtextstyle:%patch1 -p1}
+%{!?with_libtextstyle:%patch -P1 -p1}
+%patch -P2 -p1
+%patch -P3 -p1
 
 %{__rm} po/stamp-po
 
@@ -141,6 +145,9 @@ install -d $RPM_BUILD_ROOT%{_examplesdir}
 # the rest is packaged as %doc
 %{__rm} -r $RPM_BUILD_ROOT%{_docdir}/bison
 
+# header-only catalog (no translated messages), skipped by find_lang
+%{__rm} $RPM_BUILD_ROOT%{_localedir}/ro/LC_MESSAGES/bison-gnulib.mo
+
 %find_lang %{name}
 %find_lang %{name}-gnulib -a %{name}.lang
 %find_lang %{name}-runtime
diff --git a/bison-CVE-2026-56389.patch b/bison-CVE-2026-56389.patch
new file mode 100644
index 0000000..7bc8929
--- /dev/null
+++ b/bison-CVE-2026-56389.patch
@@ -0,0 +1,40 @@
+CVE-2026-56389: always run xsltproc from PATH for --html; a grammar could
+pick any executable via the undocumented %define tool.xsltproc.
+Upstream commit 3169c1e7a2c6acc4c59dfcf8b089896d6881925b
+https://cgit.git.savannah.gnu.org/cgit/bison.git/commit/?id=3169c1e7a2c6acc4c59dfcf8b089896d6881925b
+
+diff --git a/src/print-xml.c b/src/print-xml.c
+index 8da6da0d..79bfa88d 100644
+--- a/src/print-xml.c
++++ b/src/print-xml.c
+@@ -543,10 +543,9 @@ print_html (void)
+   assert (xml_flag);
+ 
+   char *xml2html = xpath_join (pkgdatadir (), "xslt/xml2xhtml.xsl");
+-  char *xsltproc = muscle_percent_define_get ("tool.xsltproc");
+   char const *argv[11];
+   int i = 0;
+-  argv[i++] = xsltproc;
++  argv[i++] = "xsltproc";
+   argv[i++] = "-o";
+   argv[i++] = spec_html_file;
+   argv[i++] = xml2html;
+@@ -573,6 +572,5 @@ print_html (void)
+                /* termsigp */ NULL);
+   if (status)
+     complain (NULL, complaint, _("%s failed with status %d"), argv[0], status);
+-  free (xsltproc);
+   free (xml2html);
+ }
+diff --git a/src/reader.c b/src/reader.c
+index 862d7293..cb2a7f69 100644
+--- a/src/reader.c
++++ b/src/reader.c
+@@ -788,7 +788,6 @@ prepare_percent_define_front_end_variables (void)
+       muscle_percent_define_default ("lr.default-reduction", "accepting");
+     free (lr_type);
+   }
+-  muscle_percent_define_default ("tool.xsltproc", "xsltproc");
+ 
+   /* Check %define front-end variables.  */
+   {
diff --git a/bison-CVE-2026-56390.patch b/bison-CVE-2026-56390.patch
new file mode 100644
index 0000000..876509d
--- /dev/null
+++ b/bison-CVE-2026-56390.patch
@@ -0,0 +1,1652 @@
+CVE-2026-56390: reject '/' in %output and %header file names, so a grammar
+cannot write outside the output directory.
+Upstream commit 8d101c19d4d9aaedf83a448c925513742d4efcf0
+https://cgit.git.savannah.gnu.org/cgit/bison.git/commit/?id=8d101c19d4d9aaedf83a448c925513742d4efcf0
+src/parse-gram.[ch] regenerated from the patched parse-gram.y with bison 3.8.2
+(--defines -Werror -Wall,dangling-alias --report=all, as in Makefile.am),
+parse-gram.y comes first so that make does not try to regenerate the parser.
+
+--- bison-3.8.2.orig/THANKS
++++ bison-3.8.2/THANKS
+@@ -128,6 +128,7 @@
+ Michael Felt              mamfelt at gmail.com
+ Michael Hayes             m.hayes at elec.canterbury.ac.nz
+ Michael Raskin            7c6f434c at mail.ru
++Michał Majchrowicz        mmajchrowicz at afine.com
+ Michel d'Hooge            michel.dhooge at gmail.com
+ Michiel De Wilde          mdewilde.agilent at gmail.com
+ Mickael Labau             labau_m at epita.fr
+--- bison-3.8.2.orig/doc/bison.texi
++++ bison-3.8.2/doc/bison.texi
+@@ -5973,6 +5973,7 @@
+ 
+ @deffn {Directive} %header @var{header-file}
+ Same as above, but save in the file @file{@var{header-file}}.
++The @var{header-file} name should not contain slashes.
+ @end deffn
+ 
+ @deffn {Directive} %language "@var{language}"
+@@ -6026,6 +6027,7 @@
+ 
+ @deffn {Directive} %output "@var{file}"
+ Generate the parser implementation in @file{@var{file}}.
++The @var{file} name should not contain slashes.
+ @end deffn
+ 
+ @deffn {Directive} %pure-parser
+--- bison-3.8.2.orig/src/parse-gram.y
++++ bison-3.8.2/src/parse-gram.y
+@@ -95,8 +95,11 @@
+      string from the scanner (should be CODE). */
+   static char const *translate_code_braceless (char *code, location loc);
+ 
++  /* Is FILE a valid output file name?  */
++  static bool valid_output_file_name (char const *file);
++
+   /* Handle a %header directive.  */
+-  static void handle_header (char const *value);
++  static void handle_header (location const *loc, char const *value);
+ 
+   /* Handle a %error-verbose directive.  */
+   static void handle_error_verbose (location const *loc, char const *directive);
+@@ -337,7 +340,7 @@
+       muscle_percent_define_insert ($2, @$, $3.kind, $3.chars,
+                                     MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
+     }
+-| "%header" string.opt             { handle_header ($2); }
++| "%header" string.opt             { handle_header (&@2, $2); }
+ | "%error-verbose"                 { handle_error_verbose (&@$, $1); }
+ | "%expect" INT_LITERAL            { expected_sr_conflicts = $2; }
+ | "%expect-rr" INT_LITERAL         { expected_rr_conflicts = $2; }
+@@ -356,7 +359,15 @@
+ | "%name-prefix" STRING         { handle_name_prefix (&@$, $1, $2); }
+ | "%no-lines"                   { no_lines_flag = true; }
+ | "%nondeterministic-parser"    { nondeterministic_parser = true; }
+-| "%output" STRING              { spec_outfile = unquote ($2); gram_scanner_last_string_free (); }
++| "%output" STRING
++    {
++      char *file = unquote ($2);
++      if (valid_output_file_name (file))
++        spec_outfile = file;
++      else
++        complain (&@2, complaint, _("invalid %%output file name ignored"));
++      gram_scanner_last_string_free ();
++    }
+ | "%param" { current_param = $1; } params { current_param = param_none; }
+ | "%pure-parser"                { handle_pure_parser (&@$, $1); }
+ | "%require" STRING             { handle_require (&@2, $2); }
+@@ -952,14 +963,24 @@
+ }
+ 
+ 
++static bool
++valid_output_file_name (char const *file)
++{
++  return !strchr (file, '/');
++}
++
++
+ static void
+-handle_header (char const *value)
++handle_header (location const *loc, char const *value)
+ {
+   header_flag = true;
+   if (value)
+     {
+       char *file = unquote (value);
+-      spec_header_file = xstrdup (file);
++      if (valid_output_file_name (file))
++        spec_header_file = xstrdup (file);
++      else
++        complain (loc, complaint, _("invalid %%header file name ignored"));
+       gram_scanner_last_string_free ();
+       unquote_free (file);
+     }
+--- bison-3.8.2.orig/src/parse-gram.c
++++ bison-3.8.2/src/parse-gram.c
+@@ -276,8 +276,11 @@
+      string from the scanner (should be CODE). */
+   static char const *translate_code_braceless (char *code, location loc);
+ 
++  /* Is FILE a valid output file name?  */
++  static bool valid_output_file_name (char const *file);
++
+   /* Handle a %header directive.  */
+-  static void handle_header (char const *value);
++  static void handle_header (location const *loc, char const *value);
+ 
+   /* Handle a %error-verbose directive.  */
+   static void handle_error_verbose (location const *loc, char const *directive);
+@@ -322,7 +325,7 @@
+ 
+   /* Discard the latest unquoted string.  */
+   static void unquote_free (char *last_string);
+-#line 278 "src/parse-gram.y"
++#line 281 "src/parse-gram.y"
+ 
+   /** Add a lex-param and/or a parse-param.
+    *
+@@ -333,7 +336,7 @@
+   static void add_param (param_type type, char *decl, location loc);
+   static param_type current_param = param_none;
+ 
+-#line 337 "src/parse-gram.c"
++#line 340 "src/parse-gram.c"
+ 
+ #ifdef short
+ # undef short
+@@ -663,19 +666,19 @@
+ /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
+ static const yytype_int16 yyrline[] =
+ {
+-       0,   310,   310,   319,   320,   324,   325,   331,   335,   340,
+-     341,   342,   343,   344,   345,   350,   355,   356,   357,   358,
+-     359,   360,   360,   361,   362,   363,   364,   365,   366,   367,
+-     368,   372,   373,   382,   383,   387,   398,   402,   406,   414,
+-     424,   425,   435,   436,   442,   455,   455,   460,   460,   465,
+-     465,   470,   480,   481,   482,   483,   488,   489,   493,   494,
+-     499,   500,   504,   505,   509,   510,   511,   524,   533,   537,
+-     541,   549,   550,   554,   567,   568,   573,   574,   575,   593,
+-     597,   601,   609,   611,   616,   623,   633,   637,   641,   649,
+-     655,   668,   669,   675,   676,   677,   684,   684,   692,   693,
+-     694,   699,   702,   704,   706,   708,   710,   712,   714,   716,
+-     718,   723,   724,   733,   757,   758,   759,   760,   772,   774,
+-     798,   803,   804,   809,   817,   818
++       0,   313,   313,   322,   323,   327,   328,   334,   338,   343,
++     344,   345,   346,   347,   348,   353,   358,   359,   360,   361,
++     362,   371,   371,   372,   373,   374,   375,   376,   377,   378,
++     379,   383,   384,   393,   394,   398,   409,   413,   417,   425,
++     435,   436,   446,   447,   453,   466,   466,   471,   471,   476,
++     476,   481,   491,   492,   493,   494,   499,   500,   504,   505,
++     510,   511,   515,   516,   520,   521,   522,   535,   544,   548,
++     552,   560,   561,   565,   578,   579,   584,   585,   586,   604,
++     608,   612,   620,   622,   627,   634,   644,   648,   652,   660,
++     666,   679,   680,   686,   687,   688,   695,   695,   703,   704,
++     705,   710,   713,   715,   717,   719,   721,   723,   725,   727,
++     729,   734,   735,   744,   768,   769,   770,   771,   783,   785,
++     809,   814,   815,   820,   828,   829
+ };
+ #endif
+ 
+@@ -1093,117 +1096,117 @@
+   if (!yyvaluep)
+     return;
+ /* "%code pre-printer" blocks.  */
+-#line 230 "src/parse-gram.y"
++#line 233 "src/parse-gram.y"
+ tron (yyo);
+ 
+-#line 1100 "src/parse-gram.c"
++#line 1103 "src/parse-gram.c"
+   YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+   switch (yykind)
+     {
+     case YYSYMBOL_STRING: /* "string"  */
+-#line 237 "src/parse-gram.y"
++#line 240 "src/parse-gram.y"
+          { fputs (((*yyvaluep).STRING), yyo); }
+-#line 1107 "src/parse-gram.c"
++#line 1110 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_TSTRING: /* "translatable string"  */
+-#line 237 "src/parse-gram.y"
++#line 240 "src/parse-gram.y"
+          { fputs (((*yyvaluep).TSTRING), yyo); }
+-#line 1113 "src/parse-gram.c"
++#line 1116 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_PERCENT_ERROR_VERBOSE: /* "%error-verbose"  */
+-#line 244 "src/parse-gram.y"
++#line 247 "src/parse-gram.y"
+          { fputs (((*yyvaluep).PERCENT_ERROR_VERBOSE), yyo); }
+-#line 1119 "src/parse-gram.c"
++#line 1122 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_PERCENT_FILE_PREFIX: /* "%file-prefix"  */
+-#line 244 "src/parse-gram.y"
++#line 247 "src/parse-gram.y"
+          { fputs (((*yyvaluep).PERCENT_FILE_PREFIX), yyo); }
+-#line 1125 "src/parse-gram.c"
++#line 1128 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_PERCENT_FLAG: /* "%<flag>"  */
+-#line 247 "src/parse-gram.y"
++#line 250 "src/parse-gram.y"
+          { fprintf (yyo, "%%%s", ((*yyvaluep).PERCENT_FLAG)); }
+-#line 1131 "src/parse-gram.c"
++#line 1134 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_PERCENT_NAME_PREFIX: /* "%name-prefix"  */
+-#line 244 "src/parse-gram.y"
++#line 247 "src/parse-gram.y"
+          { fputs (((*yyvaluep).PERCENT_NAME_PREFIX), yyo); }
+-#line 1137 "src/parse-gram.c"
++#line 1140 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_PERCENT_PURE_PARSER: /* "%pure-parser"  */
+-#line 244 "src/parse-gram.y"
++#line 247 "src/parse-gram.y"
+          { fputs (((*yyvaluep).PERCENT_PURE_PARSER), yyo); }
+-#line 1143 "src/parse-gram.c"
++#line 1146 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_BRACED_CODE: /* "{...}"  */
+-#line 237 "src/parse-gram.y"
++#line 240 "src/parse-gram.y"
+          { fputs (((*yyvaluep).BRACED_CODE), yyo); }
+-#line 1149 "src/parse-gram.c"
++#line 1152 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_BRACED_PREDICATE: /* "%?{...}"  */
+-#line 237 "src/parse-gram.y"
++#line 240 "src/parse-gram.y"
+          { fputs (((*yyvaluep).BRACED_PREDICATE), yyo); }
+-#line 1155 "src/parse-gram.c"
++#line 1158 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_BRACKETED_ID: /* "[identifier]"  */
+-#line 245 "src/parse-gram.y"
++#line 248 "src/parse-gram.y"
+          { fprintf (yyo, "[%s]", ((*yyvaluep).BRACKETED_ID)); }
+-#line 1161 "src/parse-gram.c"
++#line 1164 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_CHAR_LITERAL: /* "character literal"  */
+-#line 234 "src/parse-gram.y"
++#line 237 "src/parse-gram.y"
+          { fputs (char_name (((*yyvaluep).CHAR_LITERAL)), yyo); }
+-#line 1167 "src/parse-gram.c"
++#line 1170 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_EPILOGUE: /* "epilogue"  */
+-#line 237 "src/parse-gram.y"
++#line 240 "src/parse-gram.y"
+          { fputs (((*yyvaluep).EPILOGUE), yyo); }
+-#line 1173 "src/parse-gram.c"
++#line 1176 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_ID: /* "identifier"  */
+-#line 244 "src/parse-gram.y"
++#line 247 "src/parse-gram.y"
+          { fputs (((*yyvaluep).ID), yyo); }
+-#line 1179 "src/parse-gram.c"
++#line 1182 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_ID_COLON: /* "identifier:"  */
+-#line 246 "src/parse-gram.y"
++#line 249 "src/parse-gram.y"
+          { fprintf (yyo, "%s:", ((*yyvaluep).ID_COLON)); }
+-#line 1185 "src/parse-gram.c"
++#line 1188 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_PROLOGUE: /* "%{...%}"  */
+-#line 237 "src/parse-gram.y"
++#line 240 "src/parse-gram.y"
+          { fputs (((*yyvaluep).PROLOGUE), yyo); }
+-#line 1191 "src/parse-gram.c"
++#line 1194 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_TAG: /* "<tag>"  */
+-#line 248 "src/parse-gram.y"
++#line 251 "src/parse-gram.y"
+          { fprintf (yyo, "<%s>", ((*yyvaluep).TAG)); }
+-#line 1197 "src/parse-gram.c"
++#line 1200 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_INT_LITERAL: /* "integer literal"  */
+-#line 251 "src/parse-gram.y"
++#line 254 "src/parse-gram.y"
+          { fprintf (yyo, "%d", ((*yyvaluep).INT_LITERAL)); }
+-#line 1203 "src/parse-gram.c"
++#line 1206 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_PERCENT_PARAM: /* "%param"  */
+-#line 290 "src/parse-gram.y"
++#line 293 "src/parse-gram.y"
+ {
+   switch (((*yyvaluep).PERCENT_PARAM))
+     {
+@@ -1216,119 +1219,119 @@
+       case param_none: aver (false); break;
+     }
+ }
+-#line 1220 "src/parse-gram.c"
++#line 1223 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_code_props_type: /* code_props_type  */
+-#line 422 "src/parse-gram.y"
++#line 433 "src/parse-gram.y"
+          { fprintf (yyo, "%s", code_props_type_string (((*yyvaluep).code_props_type))); }
+-#line 1226 "src/parse-gram.c"
++#line 1229 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_75_string_opt: /* string.opt  */
+-#line 237 "src/parse-gram.y"
++#line 240 "src/parse-gram.y"
+          { fputs (((*yyvaluep).yykind_75), yyo); }
+-#line 1232 "src/parse-gram.c"
++#line 1235 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_76_tag_opt: /* tag.opt  */
+-#line 244 "src/parse-gram.y"
++#line 247 "src/parse-gram.y"
+          { fputs (((*yyvaluep).yykind_76), yyo); }
+-#line 1238 "src/parse-gram.c"
++#line 1241 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_generic_symlist: /* generic_symlist  */
+-#line 260 "src/parse-gram.y"
++#line 263 "src/parse-gram.y"
+          { symbol_list_syms_print (((*yyvaluep).generic_symlist), yyo); }
+-#line 1244 "src/parse-gram.c"
++#line 1247 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_generic_symlist_item: /* generic_symlist_item  */
+-#line 260 "src/parse-gram.y"
++#line 263 "src/parse-gram.y"
+          { symbol_list_syms_print (((*yyvaluep).generic_symlist_item), yyo); }
+-#line 1250 "src/parse-gram.c"
++#line 1253 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_tag: /* tag  */
+-#line 248 "src/parse-gram.y"
++#line 251 "src/parse-gram.y"
+          { fprintf (yyo, "<%s>", ((*yyvaluep).tag)); }
+-#line 1256 "src/parse-gram.c"
++#line 1259 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_nterm_decls: /* nterm_decls  */
+-#line 260 "src/parse-gram.y"
++#line 263 "src/parse-gram.y"
+          { symbol_list_syms_print (((*yyvaluep).nterm_decls), yyo); }
+-#line 1262 "src/parse-gram.c"
++#line 1265 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_token_decls: /* token_decls  */
+-#line 260 "src/parse-gram.y"
++#line 263 "src/parse-gram.y"
+          { symbol_list_syms_print (((*yyvaluep).token_decls), yyo); }
+-#line 1268 "src/parse-gram.c"
++#line 1271 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_82_token_decl_1: /* token_decl.1  */
+-#line 260 "src/parse-gram.y"
++#line 263 "src/parse-gram.y"
+          { symbol_list_syms_print (((*yyvaluep).yykind_82), yyo); }
+-#line 1274 "src/parse-gram.c"
++#line 1277 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_token_decl: /* token_decl  */
+-#line 254 "src/parse-gram.y"
++#line 257 "src/parse-gram.y"
+          { fprintf (yyo, "%s", ((*yyvaluep).token_decl) ? ((*yyvaluep).token_decl)->tag : "<NULL>"); }
+-#line 1280 "src/parse-gram.c"
++#line 1283 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_84_int_opt: /* int.opt  */
+-#line 251 "src/parse-gram.y"
++#line 254 "src/parse-gram.y"
+          { fprintf (yyo, "%d", ((*yyvaluep).yykind_84)); }
+-#line 1286 "src/parse-gram.c"
++#line 1289 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_alias: /* alias  */
+-#line 254 "src/parse-gram.y"
++#line 257 "src/parse-gram.y"
+          { fprintf (yyo, "%s", ((*yyvaluep).alias) ? ((*yyvaluep).alias)->tag : "<NULL>"); }
+-#line 1292 "src/parse-gram.c"
++#line 1295 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_token_decls_for_prec: /* token_decls_for_prec  */
+-#line 260 "src/parse-gram.y"
++#line 263 "src/parse-gram.y"
+          { symbol_list_syms_print (((*yyvaluep).token_decls_for_prec), yyo); }
+-#line 1298 "src/parse-gram.c"
++#line 1301 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_87_token_decl_for_prec_1: /* token_decl_for_prec.1  */
+-#line 260 "src/parse-gram.y"
++#line 263 "src/parse-gram.y"
+          { symbol_list_syms_print (((*yyvaluep).yykind_87), yyo); }
+-#line 1304 "src/parse-gram.c"
++#line 1307 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_token_decl_for_prec: /* token_decl_for_prec  */
+-#line 254 "src/parse-gram.y"
++#line 257 "src/parse-gram.y"
+          { fprintf (yyo, "%s", ((*yyvaluep).token_decl_for_prec) ? ((*yyvaluep).token_decl_for_prec)->tag : "<NULL>"); }
+-#line 1310 "src/parse-gram.c"
++#line 1313 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_symbol_decls: /* symbol_decls  */
+-#line 260 "src/parse-gram.y"
++#line 263 "src/parse-gram.y"
+          { symbol_list_syms_print (((*yyvaluep).symbol_decls), yyo); }
+-#line 1316 "src/parse-gram.c"
++#line 1319 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_90_symbols_1: /* symbols.1  */
+-#line 260 "src/parse-gram.y"
++#line 263 "src/parse-gram.y"
+          { symbol_list_syms_print (((*yyvaluep).yykind_90), yyo); }
+-#line 1322 "src/parse-gram.c"
++#line 1325 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_variable: /* variable  */
+-#line 244 "src/parse-gram.y"
++#line 247 "src/parse-gram.y"
+          { fputs (((*yyvaluep).variable), yyo); }
+-#line 1328 "src/parse-gram.c"
++#line 1331 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_value: /* value  */
+-#line 747 "src/parse-gram.y"
++#line 758 "src/parse-gram.y"
+ {
+   switch (((*yyvaluep).value).kind)
+     {
+@@ -1337,31 +1340,31 @@
+     case muscle_string:  fprintf (yyo, "\"%s\"", ((*yyvaluep).value).chars); break;
+     }
+ }
+-#line 1341 "src/parse-gram.c"
++#line 1344 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_id: /* id  */
+-#line 254 "src/parse-gram.y"
++#line 257 "src/parse-gram.y"
+          { fprintf (yyo, "%s", ((*yyvaluep).id) ? ((*yyvaluep).id)->tag : "<NULL>"); }
+-#line 1347 "src/parse-gram.c"
++#line 1350 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_id_colon: /* id_colon  */
+-#line 255 "src/parse-gram.y"
++#line 258 "src/parse-gram.y"
+          { fprintf (yyo, "%s:", ((*yyvaluep).id_colon)->tag); }
+-#line 1353 "src/parse-gram.c"
++#line 1356 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_symbol: /* symbol  */
+-#line 254 "src/parse-gram.y"
++#line 257 "src/parse-gram.y"
+          { fprintf (yyo, "%s", ((*yyvaluep).symbol) ? ((*yyvaluep).symbol)->tag : "<NULL>"); }
+-#line 1359 "src/parse-gram.c"
++#line 1362 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_string_as_id: /* string_as_id  */
+-#line 254 "src/parse-gram.y"
++#line 257 "src/parse-gram.y"
+          { fprintf (yyo, "%s", ((*yyvaluep).string_as_id) ? ((*yyvaluep).string_as_id)->tag : "<NULL>"); }
+-#line 1365 "src/parse-gram.c"
++#line 1368 "src/parse-gram.c"
+         break;
+ 
+       default:
+@@ -1369,10 +1372,10 @@
+     }
+   YY_IGNORE_MAYBE_UNINITIALIZED_END
+ /* "%code post-printer" blocks.  */
+-#line 231 "src/parse-gram.y"
++#line 234 "src/parse-gram.y"
+ troff (yyo);
+ 
+-#line 1376 "src/parse-gram.c"
++#line 1379 "src/parse-gram.c"
+ }
+ 
+ 
+@@ -1813,57 +1816,57 @@
+   switch (yykind)
+     {
+     case YYSYMBOL_generic_symlist: /* generic_symlist  */
+-#line 259 "src/parse-gram.y"
++#line 262 "src/parse-gram.y"
+             { symbol_list_free (((*yyvaluep).generic_symlist)); }
+-#line 1819 "src/parse-gram.c"
++#line 1822 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_generic_symlist_item: /* generic_symlist_item  */
+-#line 259 "src/parse-gram.y"
++#line 262 "src/parse-gram.y"
+             { symbol_list_free (((*yyvaluep).generic_symlist_item)); }
+-#line 1825 "src/parse-gram.c"
++#line 1828 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_nterm_decls: /* nterm_decls  */
+-#line 259 "src/parse-gram.y"
++#line 262 "src/parse-gram.y"
+             { symbol_list_free (((*yyvaluep).nterm_decls)); }
+-#line 1831 "src/parse-gram.c"
++#line 1834 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_token_decls: /* token_decls  */
+-#line 259 "src/parse-gram.y"
++#line 262 "src/parse-gram.y"
+             { symbol_list_free (((*yyvaluep).token_decls)); }
+-#line 1837 "src/parse-gram.c"
++#line 1840 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_82_token_decl_1: /* token_decl.1  */
+-#line 259 "src/parse-gram.y"
++#line 262 "src/parse-gram.y"
+             { symbol_list_free (((*yyvaluep).yykind_82)); }
+-#line 1843 "src/parse-gram.c"
++#line 1846 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_token_decls_for_prec: /* token_decls_for_prec  */
+-#line 259 "src/parse-gram.y"
++#line 262 "src/parse-gram.y"
+             { symbol_list_free (((*yyvaluep).token_decls_for_prec)); }
+-#line 1849 "src/parse-gram.c"
++#line 1852 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_87_token_decl_for_prec_1: /* token_decl_for_prec.1  */
+-#line 259 "src/parse-gram.y"
++#line 262 "src/parse-gram.y"
+             { symbol_list_free (((*yyvaluep).yykind_87)); }
+-#line 1855 "src/parse-gram.c"
++#line 1858 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_symbol_decls: /* symbol_decls  */
+-#line 259 "src/parse-gram.y"
++#line 262 "src/parse-gram.y"
+             { symbol_list_free (((*yyvaluep).symbol_decls)); }
+-#line 1861 "src/parse-gram.c"
++#line 1864 "src/parse-gram.c"
+         break;
+ 
+     case YYSYMBOL_90_symbols_1: /* symbols.1  */
+-#line 259 "src/parse-gram.y"
++#line 262 "src/parse-gram.y"
+             { symbol_list_free (((*yyvaluep).yykind_90)); }
+-#line 1867 "src/parse-gram.c"
++#line 1870 "src/parse-gram.c"
+         break;
+ 
+       default:
+@@ -1963,7 +1966,7 @@
+ 
+ 
+ /* User initialization code.  */
+-#line 160 "src/parse-gram.y"
++#line 163 "src/parse-gram.y"
+ {
+   /* Bison's grammar can initial empty locations, hence a default
+      location is needed. */
+@@ -1971,7 +1974,7 @@
+   boundary_set (&yylloc.end, grammar_file, 1, 1, 1);
+ }
+ 
+-#line 1975 "src/parse-gram.c"
++#line 1978 "src/parse-gram.c"
+ 
+   yylsp[0] = yylloc;
+   goto yysetstate;
+@@ -2189,186 +2192,193 @@
+     switch (yyn)
+       {
+   case 6: /* prologue_declaration: "%{...%}"  */
+-#line 326 "src/parse-gram.y"
++#line 329 "src/parse-gram.y"
+     {
+       muscle_code_grow (union_seen ? "post_prologue" : "pre_prologue",
+                         translate_code ((yyvsp[0].PROLOGUE), (yylsp[0]), true), (yylsp[0]));
+       code_scanner_last_string_free ();
+     }
+-#line 2199 "src/parse-gram.c"
++#line 2202 "src/parse-gram.c"
+     break;
+ 
+   case 7: /* prologue_declaration: "%<flag>"  */
+-#line 332 "src/parse-gram.y"
++#line 335 "src/parse-gram.y"
+     {
+       muscle_percent_define_ensure ((yyvsp[0].PERCENT_FLAG), (yylsp[0]), true);
+     }
+-#line 2207 "src/parse-gram.c"
++#line 2210 "src/parse-gram.c"
+     break;
+ 
+   case 8: /* prologue_declaration: "%define" variable value  */
+-#line 336 "src/parse-gram.y"
++#line 339 "src/parse-gram.y"
+     {
+       muscle_percent_define_insert ((yyvsp[-1].variable), (yyloc), (yyvsp[0].value).kind, (yyvsp[0].value).chars,
+                                     MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
+     }
+-#line 2216 "src/parse-gram.c"
++#line 2219 "src/parse-gram.c"
+     break;
+ 
+   case 9: /* prologue_declaration: "%header" string.opt  */
+-#line 340 "src/parse-gram.y"
+-                                   { handle_header ((yyvsp[0].yykind_75)); }
+-#line 2222 "src/parse-gram.c"
++#line 343 "src/parse-gram.y"
++                                   { handle_header (&(yylsp[0]), (yyvsp[0].yykind_75)); }
++#line 2225 "src/parse-gram.c"
+     break;
+ 
+   case 10: /* prologue_declaration: "%error-verbose"  */
+-#line 341 "src/parse-gram.y"
++#line 344 "src/parse-gram.y"
+                                    { handle_error_verbose (&(yyloc), (yyvsp[0].PERCENT_ERROR_VERBOSE)); }
+-#line 2228 "src/parse-gram.c"
++#line 2231 "src/parse-gram.c"
+     break;
+ 
+   case 11: /* prologue_declaration: "%expect" "integer literal"  */
+-#line 342 "src/parse-gram.y"
++#line 345 "src/parse-gram.y"
+                                    { expected_sr_conflicts = (yyvsp[0].INT_LITERAL); }
+-#line 2234 "src/parse-gram.c"
++#line 2237 "src/parse-gram.c"
+     break;
+ 
+   case 12: /* prologue_declaration: "%expect-rr" "integer literal"  */
+-#line 343 "src/parse-gram.y"
++#line 346 "src/parse-gram.y"
+                                    { expected_rr_conflicts = (yyvsp[0].INT_LITERAL); }
+-#line 2240 "src/parse-gram.c"
++#line 2243 "src/parse-gram.c"
+     break;
+ 
+   case 13: /* prologue_declaration: "%file-prefix" "string"  */
+-#line 344 "src/parse-gram.y"
++#line 347 "src/parse-gram.y"
+                                    { handle_file_prefix (&(yyloc), &(yylsp[-1]), (yyvsp[-1].PERCENT_FILE_PREFIX), (yyvsp[0].STRING)); }
+-#line 2246 "src/parse-gram.c"
++#line 2249 "src/parse-gram.c"
+     break;
+ 
+   case 14: /* prologue_declaration: "%glr-parser"  */
+-#line 346 "src/parse-gram.y"
++#line 349 "src/parse-gram.y"
+     {
+       nondeterministic_parser = true;
+       glr_parser = true;
+     }
+-#line 2255 "src/parse-gram.c"
++#line 2258 "src/parse-gram.c"
+     break;
+ 
+   case 15: /* prologue_declaration: "%initial-action" "{...}"  */
+-#line 351 "src/parse-gram.y"
++#line 354 "src/parse-gram.y"
+     {
+       muscle_code_grow ("initial_action", translate_code ((yyvsp[0].BRACED_CODE), (yylsp[0]), false), (yylsp[0]));
+       code_scanner_last_string_free ();
+     }
+-#line 2264 "src/parse-gram.c"
++#line 2267 "src/parse-gram.c"
+     break;
+ 
+   case 16: /* prologue_declaration: "%language" "string"  */
+-#line 355 "src/parse-gram.y"
++#line 358 "src/parse-gram.y"
+                                 { handle_language (&(yylsp[-1]), (yyvsp[0].STRING)); }
+-#line 2270 "src/parse-gram.c"
++#line 2273 "src/parse-gram.c"
+     break;
+ 
+   case 17: /* prologue_declaration: "%name-prefix" "string"  */
+-#line 356 "src/parse-gram.y"
++#line 359 "src/parse-gram.y"
+                                 { handle_name_prefix (&(yyloc), (yyvsp[-1].PERCENT_NAME_PREFIX), (yyvsp[0].STRING)); }
+-#line 2276 "src/parse-gram.c"
++#line 2279 "src/parse-gram.c"
+     break;
+ 
+   case 18: /* prologue_declaration: "%no-lines"  */
+-#line 357 "src/parse-gram.y"
++#line 360 "src/parse-gram.y"
+                                 { no_lines_flag = true; }
+-#line 2282 "src/parse-gram.c"
++#line 2285 "src/parse-gram.c"
+     break;
+ 
+   case 19: /* prologue_declaration: "%nondeterministic-parser"  */
+-#line 358 "src/parse-gram.y"
++#line 361 "src/parse-gram.y"
+                                 { nondeterministic_parser = true; }
+-#line 2288 "src/parse-gram.c"
++#line 2291 "src/parse-gram.c"
+     break;
+ 
+   case 20: /* prologue_declaration: "%output" "string"  */
+-#line 359 "src/parse-gram.y"
+-                                { spec_outfile = unquote ((yyvsp[0].STRING)); gram_scanner_last_string_free (); }
+-#line 2294 "src/parse-gram.c"
++#line 363 "src/parse-gram.y"
++    {
++      char *file = unquote ((yyvsp[0].STRING));
++      if (valid_output_file_name (file))
++        spec_outfile = file;
++      else
++        complain (&(yylsp[0]), complaint, _("invalid %%output file name ignored"));
++      gram_scanner_last_string_free ();
++    }
++#line 2304 "src/parse-gram.c"
+     break;
+ 
+   case 21: /* $@1: %empty  */
+-#line 360 "src/parse-gram.y"
++#line 371 "src/parse-gram.y"
+            { current_param = (yyvsp[0].PERCENT_PARAM); }
+-#line 2300 "src/parse-gram.c"
++#line 2310 "src/parse-gram.c"
+     break;
+ 
+   case 22: /* prologue_declaration: "%param" $@1 params  */
+-#line 360 "src/parse-gram.y"
++#line 371 "src/parse-gram.y"
+                                           { current_param = param_none; }
+-#line 2306 "src/parse-gram.c"
++#line 2316 "src/parse-gram.c"
+     break;
+ 
+   case 23: /* prologue_declaration: "%pure-parser"  */
+-#line 361 "src/parse-gram.y"
++#line 372 "src/parse-gram.y"
+                                 { handle_pure_parser (&(yyloc), (yyvsp[0].PERCENT_PURE_PARSER)); }
+-#line 2312 "src/parse-gram.c"
++#line 2322 "src/parse-gram.c"
+     break;
+ 
+   case 24: /* prologue_declaration: "%require" "string"  */
+-#line 362 "src/parse-gram.y"
++#line 373 "src/parse-gram.y"
+                                 { handle_require (&(yylsp[0]), (yyvsp[0].STRING)); }
+-#line 2318 "src/parse-gram.c"
++#line 2328 "src/parse-gram.c"
+     break;
+ 
+   case 25: /* prologue_declaration: "%skeleton" "string"  */
+-#line 363 "src/parse-gram.y"
++#line 374 "src/parse-gram.y"
+                                 { handle_skeleton (&(yylsp[0]), (yyvsp[0].STRING)); }
+-#line 2324 "src/parse-gram.c"
++#line 2334 "src/parse-gram.c"
+     break;
+ 
+   case 26: /* prologue_declaration: "%token-table"  */
+-#line 364 "src/parse-gram.y"
++#line 375 "src/parse-gram.y"
+                                 { token_table_flag = true; }
+-#line 2330 "src/parse-gram.c"
++#line 2340 "src/parse-gram.c"
+     break;
+ 
+   case 27: /* prologue_declaration: "%verbose"  */
+-#line 365 "src/parse-gram.y"
++#line 376 "src/parse-gram.y"
+                                 { report_flag |= report_states; }
+-#line 2336 "src/parse-gram.c"
++#line 2346 "src/parse-gram.c"
+     break;
+ 
+   case 28: /* prologue_declaration: "%yacc"  */
+-#line 366 "src/parse-gram.y"
++#line 377 "src/parse-gram.y"
+                                 { handle_yacc (&(yyloc)); }
+-#line 2342 "src/parse-gram.c"
++#line 2352 "src/parse-gram.c"
+     break;
+ 
+   case 29: /* prologue_declaration: error ";"  */
+-#line 367 "src/parse-gram.y"
++#line 378 "src/parse-gram.y"
+                                 { current_class = unknown_sym; yyerrok; }
+-#line 2348 "src/parse-gram.c"
++#line 2358 "src/parse-gram.c"
+     break;
+ 
+   case 31: /* params: params "{...}"  */
+-#line 372 "src/parse-gram.y"
++#line 383 "src/parse-gram.y"
+                    { add_param (current_param, (yyvsp[0].BRACED_CODE), (yylsp[0])); }
+-#line 2354 "src/parse-gram.c"
++#line 2364 "src/parse-gram.c"
+     break;
+ 
+   case 32: /* params: "{...}"  */
+-#line 373 "src/parse-gram.y"
++#line 384 "src/parse-gram.y"
+                    { add_param (current_param, (yyvsp[0].BRACED_CODE), (yylsp[0])); }
+-#line 2360 "src/parse-gram.c"
++#line 2370 "src/parse-gram.c"
+     break;
+ 
+   case 34: /* grammar_declaration: "%start" symbols.1  */
+-#line 384 "src/parse-gram.y"
++#line 395 "src/parse-gram.y"
+     {
+       grammar_start_symbols_add ((yyvsp[0].yykind_90));
+     }
+-#line 2368 "src/parse-gram.c"
++#line 2378 "src/parse-gram.c"
+     break;
+ 
+   case 35: /* grammar_declaration: code_props_type "{...}" generic_symlist  */
+-#line 388 "src/parse-gram.y"
++#line 399 "src/parse-gram.y"
+     {
+       code_props code;
+       code_props_symbol_action_init (&code, (yyvsp[-1].BRACED_CODE), (yylsp[-1]));
+@@ -2379,27 +2389,27 @@
+         symbol_list_free ((yyvsp[0].generic_symlist));
+       }
+     }
+-#line 2383 "src/parse-gram.c"
++#line 2393 "src/parse-gram.c"
+     break;
+ 
+   case 36: /* grammar_declaration: "%default-prec"  */
+-#line 399 "src/parse-gram.y"
++#line 410 "src/parse-gram.y"
+     {
+       default_prec = true;
+     }
+-#line 2391 "src/parse-gram.c"
++#line 2401 "src/parse-gram.c"
+     break;
+ 
+   case 37: /* grammar_declaration: "%no-default-prec"  */
+-#line 403 "src/parse-gram.y"
++#line 414 "src/parse-gram.y"
+     {
+       default_prec = false;
+     }
+-#line 2399 "src/parse-gram.c"
++#line 2409 "src/parse-gram.c"
+     break;
+ 
+   case 38: /* grammar_declaration: "%code" "{...}"  */
+-#line 407 "src/parse-gram.y"
++#line 418 "src/parse-gram.y"
+     {
+       /* Do not invoke muscle_percent_code_grow here since it invokes
+          muscle_user_name_list_grow.  */
+@@ -2407,226 +2417,226 @@
+                         translate_code_braceless ((yyvsp[0].BRACED_CODE), (yylsp[0])), (yylsp[0]));
+       code_scanner_last_string_free ();
+     }
+-#line 2411 "src/parse-gram.c"
++#line 2421 "src/parse-gram.c"
+     break;
+ 
+   case 39: /* grammar_declaration: "%code" "identifier" "{...}"  */
+-#line 415 "src/parse-gram.y"
++#line 426 "src/parse-gram.y"
+     {
+       muscle_percent_code_grow ((yyvsp[-1].ID), (yylsp[-1]), translate_code_braceless ((yyvsp[0].BRACED_CODE), (yylsp[0])), (yylsp[0]));
+       code_scanner_last_string_free ();
+     }
+-#line 2420 "src/parse-gram.c"
++#line 2430 "src/parse-gram.c"
+     break;
+ 
+   case 40: /* code_props_type: "%destructor"  */
+-#line 424 "src/parse-gram.y"
++#line 435 "src/parse-gram.y"
+                  { (yyval.code_props_type) = destructor; }
+-#line 2426 "src/parse-gram.c"
++#line 2436 "src/parse-gram.c"
+     break;
+ 
+   case 41: /* code_props_type: "%printer"  */
+-#line 425 "src/parse-gram.y"
++#line 436 "src/parse-gram.y"
+                  { (yyval.code_props_type) = printer; }
+-#line 2432 "src/parse-gram.c"
++#line 2442 "src/parse-gram.c"
+     break;
+ 
+   case 42: /* union_name: %empty  */
+-#line 435 "src/parse-gram.y"
++#line 446 "src/parse-gram.y"
+          {}
+-#line 2438 "src/parse-gram.c"
++#line 2448 "src/parse-gram.c"
+     break;
+ 
+   case 43: /* union_name: "identifier"  */
+-#line 436 "src/parse-gram.y"
++#line 447 "src/parse-gram.y"
+          { muscle_percent_define_insert ("api.value.union.name",
+                                          (yylsp[0]), muscle_keyword, (yyvsp[0].ID),
+                                          MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE); }
+-#line 2446 "src/parse-gram.c"
++#line 2456 "src/parse-gram.c"
+     break;
+ 
+   case 44: /* grammar_declaration: "%union" union_name "{...}"  */
+-#line 443 "src/parse-gram.y"
++#line 454 "src/parse-gram.y"
+     {
+       union_seen = true;
+       muscle_code_grow ("union_members", translate_code_braceless ((yyvsp[0].BRACED_CODE), (yylsp[0])), (yylsp[0]));
+       code_scanner_last_string_free ();
+     }
+-#line 2456 "src/parse-gram.c"
++#line 2466 "src/parse-gram.c"
+     break;
+ 
+   case 45: /* $@2: %empty  */
+-#line 455 "src/parse-gram.y"
++#line 466 "src/parse-gram.y"
+            { current_class = nterm_sym; }
+-#line 2462 "src/parse-gram.c"
++#line 2472 "src/parse-gram.c"
+     break;
+ 
+   case 46: /* symbol_declaration: "%nterm" $@2 nterm_decls  */
+-#line 456 "src/parse-gram.y"
++#line 467 "src/parse-gram.y"
+     {
+       current_class = unknown_sym;
+       symbol_list_free ((yyvsp[0].nterm_decls));
+     }
+-#line 2471 "src/parse-gram.c"
++#line 2481 "src/parse-gram.c"
+     break;
+ 
+   case 47: /* $@3: %empty  */
+-#line 460 "src/parse-gram.y"
++#line 471 "src/parse-gram.y"
+            { current_class = token_sym; }
+-#line 2477 "src/parse-gram.c"
++#line 2487 "src/parse-gram.c"
+     break;
+ 
+   case 48: /* symbol_declaration: "%token" $@3 token_decls  */
+-#line 461 "src/parse-gram.y"
++#line 472 "src/parse-gram.y"
+     {
+       current_class = unknown_sym;
+       symbol_list_free ((yyvsp[0].token_decls));
+     }
+-#line 2486 "src/parse-gram.c"
++#line 2496 "src/parse-gram.c"
+     break;
+ 
+   case 49: /* $@4: %empty  */
+-#line 465 "src/parse-gram.y"
++#line 476 "src/parse-gram.y"
+           { current_class = pct_type_sym; }
+-#line 2492 "src/parse-gram.c"
++#line 2502 "src/parse-gram.c"
+     break;
+ 
+   case 50: /* symbol_declaration: "%type" $@4 symbol_decls  */
+-#line 466 "src/parse-gram.y"
++#line 477 "src/parse-gram.y"
+     {
+       current_class = unknown_sym;
+       symbol_list_free ((yyvsp[0].symbol_decls));
+     }
+-#line 2501 "src/parse-gram.c"
++#line 2511 "src/parse-gram.c"
+     break;
+ 
+   case 51: /* symbol_declaration: precedence_declarator token_decls_for_prec  */
+-#line 471 "src/parse-gram.y"
++#line 482 "src/parse-gram.y"
+     {
+       ++current_prec;
+       for (symbol_list *list = (yyvsp[0].token_decls_for_prec); list; list = list->next)
+         symbol_precedence_set (list->content.sym, current_prec, (yyvsp[-1].precedence_declarator), (yylsp[-1]));
+       symbol_list_free ((yyvsp[0].token_decls_for_prec));
+     }
+-#line 2512 "src/parse-gram.c"
++#line 2522 "src/parse-gram.c"
+     break;
+ 
+   case 52: /* precedence_declarator: "%left"  */
+-#line 480 "src/parse-gram.y"
++#line 491 "src/parse-gram.y"
+                 { (yyval.precedence_declarator) = left_assoc; }
+-#line 2518 "src/parse-gram.c"
++#line 2528 "src/parse-gram.c"
+     break;
+ 
+   case 53: /* precedence_declarator: "%right"  */
+-#line 481 "src/parse-gram.y"
++#line 492 "src/parse-gram.y"
+                 { (yyval.precedence_declarator) = right_assoc; }
+-#line 2524 "src/parse-gram.c"
++#line 2534 "src/parse-gram.c"
+     break;
+ 
+   case 54: /* precedence_declarator: "%nonassoc"  */
+-#line 482 "src/parse-gram.y"
++#line 493 "src/parse-gram.y"
+                 { (yyval.precedence_declarator) = non_assoc; }
+-#line 2530 "src/parse-gram.c"
++#line 2540 "src/parse-gram.c"
+     break;
+ 
+   case 55: /* precedence_declarator: "%precedence"  */
+-#line 483 "src/parse-gram.y"
++#line 494 "src/parse-gram.y"
+                 { (yyval.precedence_declarator) = precedence_assoc; }
+-#line 2536 "src/parse-gram.c"
++#line 2546 "src/parse-gram.c"
+     break;
+ 
+   case 56: /* string.opt: %empty  */
+-#line 488 "src/parse-gram.y"
++#line 499 "src/parse-gram.y"
+           { (yyval.yykind_75) = NULL; }
+-#line 2542 "src/parse-gram.c"
++#line 2552 "src/parse-gram.c"
+     break;
+ 
+   case 57: /* string.opt: "string"  */
+-#line 489 "src/parse-gram.y"
++#line 500 "src/parse-gram.y"
+           { (yyval.yykind_75) = (yyvsp[0].STRING); }
+-#line 2548 "src/parse-gram.c"
++#line 2558 "src/parse-gram.c"
+     break;
+ 
+   case 58: /* tag.opt: %empty  */
+-#line 493 "src/parse-gram.y"
++#line 504 "src/parse-gram.y"
+          { (yyval.yykind_76) = NULL; }
+-#line 2554 "src/parse-gram.c"
++#line 2564 "src/parse-gram.c"
+     break;
+ 
+   case 59: /* tag.opt: "<tag>"  */
+-#line 494 "src/parse-gram.y"
++#line 505 "src/parse-gram.y"
+          { (yyval.yykind_76) = (yyvsp[0].TAG); }
+-#line 2560 "src/parse-gram.c"
++#line 2570 "src/parse-gram.c"
+     break;
+ 
+   case 61: /* generic_symlist: generic_symlist generic_symlist_item  */
+-#line 500 "src/parse-gram.y"
++#line 511 "src/parse-gram.y"
+                                          { (yyval.generic_symlist) = symbol_list_append ((yyvsp[-1].generic_symlist), (yyvsp[0].generic_symlist_item)); }
+-#line 2566 "src/parse-gram.c"
++#line 2576 "src/parse-gram.c"
+     break;
+ 
+   case 62: /* generic_symlist_item: symbol  */
+-#line 504 "src/parse-gram.y"
++#line 515 "src/parse-gram.y"
+             { (yyval.generic_symlist_item) = symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0])); }
+-#line 2572 "src/parse-gram.c"
++#line 2582 "src/parse-gram.c"
+     break;
+ 
+   case 63: /* generic_symlist_item: tag  */
+-#line 505 "src/parse-gram.y"
++#line 516 "src/parse-gram.y"
+             { (yyval.generic_symlist_item) = symbol_list_type_new ((yyvsp[0].tag), (yylsp[0])); }
+-#line 2578 "src/parse-gram.c"
++#line 2588 "src/parse-gram.c"
+     break;
+ 
+   case 65: /* tag: "<*>"  */
+-#line 510 "src/parse-gram.y"
++#line 521 "src/parse-gram.y"
+         { (yyval.tag) = uniqstr_new ("*"); }
+-#line 2584 "src/parse-gram.c"
++#line 2594 "src/parse-gram.c"
+     break;
+ 
+   case 66: /* tag: "<>"  */
+-#line 511 "src/parse-gram.y"
++#line 522 "src/parse-gram.y"
+         { (yyval.tag) = uniqstr_new (""); }
+-#line 2590 "src/parse-gram.c"
++#line 2600 "src/parse-gram.c"
+     break;
+ 
+   case 68: /* token_decls: token_decl.1  */
+-#line 534 "src/parse-gram.y"
++#line 545 "src/parse-gram.y"
+     {
+       (yyval.token_decls) = (yyvsp[0].yykind_82);
+     }
+-#line 2598 "src/parse-gram.c"
++#line 2608 "src/parse-gram.c"
+     break;
+ 
+   case 69: /* token_decls: "<tag>" token_decl.1  */
+-#line 538 "src/parse-gram.y"
++#line 549 "src/parse-gram.y"
+     {
+       (yyval.token_decls) = symbol_list_type_set ((yyvsp[0].yykind_82), (yyvsp[-1].TAG));
+     }
+-#line 2606 "src/parse-gram.c"
++#line 2616 "src/parse-gram.c"
+     break;
+ 
+   case 70: /* token_decls: token_decls "<tag>" token_decl.1  */
+-#line 542 "src/parse-gram.y"
++#line 553 "src/parse-gram.y"
+     {
+       (yyval.token_decls) = symbol_list_append ((yyvsp[-2].token_decls), symbol_list_type_set ((yyvsp[0].yykind_82), (yyvsp[-1].TAG)));
+     }
+-#line 2614 "src/parse-gram.c"
++#line 2624 "src/parse-gram.c"
+     break;
+ 
+   case 71: /* token_decl.1: token_decl  */
+-#line 549 "src/parse-gram.y"
++#line 560 "src/parse-gram.y"
+                             { (yyval.yykind_82) = symbol_list_sym_new ((yyvsp[0].token_decl), (yylsp[0])); }
+-#line 2620 "src/parse-gram.c"
++#line 2630 "src/parse-gram.c"
+     break;
+ 
+   case 72: /* token_decl.1: token_decl.1 token_decl  */
+-#line 550 "src/parse-gram.y"
++#line 561 "src/parse-gram.y"
+                             { (yyval.yykind_82) = symbol_list_append ((yyvsp[-1].yykind_82), symbol_list_sym_new ((yyvsp[0].token_decl), (yylsp[0]))); }
+-#line 2626 "src/parse-gram.c"
++#line 2636 "src/parse-gram.c"
+     break;
+ 
+   case 73: /* token_decl: id int.opt alias  */
+-#line 555 "src/parse-gram.y"
++#line 566 "src/parse-gram.y"
+     {
+       (yyval.token_decl) = (yyvsp[-2].id);
+       symbol_class_set ((yyvsp[-2].id), current_class, (yylsp[-2]), true);
+@@ -2635,268 +2645,268 @@
+       if ((yyvsp[0].alias))
+         symbol_make_alias ((yyvsp[-2].id), (yyvsp[0].alias), (yylsp[0]));
+     }
+-#line 2639 "src/parse-gram.c"
++#line 2649 "src/parse-gram.c"
+     break;
+ 
+   case 74: /* int.opt: %empty  */
+-#line 567 "src/parse-gram.y"
++#line 578 "src/parse-gram.y"
+           { (yyval.yykind_84) = -1; }
+-#line 2645 "src/parse-gram.c"
++#line 2655 "src/parse-gram.c"
+     break;
+ 
+   case 76: /* alias: %empty  */
+-#line 573 "src/parse-gram.y"
++#line 584 "src/parse-gram.y"
+                  { (yyval.alias) = NULL; }
+-#line 2651 "src/parse-gram.c"
++#line 2661 "src/parse-gram.c"
+     break;
+ 
+   case 77: /* alias: string_as_id  */
+-#line 574 "src/parse-gram.y"
++#line 585 "src/parse-gram.y"
+                  { (yyval.alias) = (yyvsp[0].string_as_id); }
+-#line 2657 "src/parse-gram.c"
++#line 2667 "src/parse-gram.c"
+     break;
+ 
+   case 78: /* alias: "translatable string"  */
+-#line 576 "src/parse-gram.y"
++#line 587 "src/parse-gram.y"
+     {
+       (yyval.alias) = symbol_get ((yyvsp[0].TSTRING), (yylsp[0]));
+       symbol_class_set ((yyval.alias), token_sym, (yylsp[0]), false);
+       (yyval.alias)->translatable = true;
+     }
+-#line 2667 "src/parse-gram.c"
++#line 2677 "src/parse-gram.c"
+     break;
+ 
+   case 79: /* token_decls_for_prec: token_decl_for_prec.1  */
+-#line 594 "src/parse-gram.y"
++#line 605 "src/parse-gram.y"
+     {
+       (yyval.token_decls_for_prec) = (yyvsp[0].yykind_87);
+     }
+-#line 2675 "src/parse-gram.c"
++#line 2685 "src/parse-gram.c"
+     break;
+ 
+   case 80: /* token_decls_for_prec: "<tag>" token_decl_for_prec.1  */
+-#line 598 "src/parse-gram.y"
++#line 609 "src/parse-gram.y"
+     {
+       (yyval.token_decls_for_prec) = symbol_list_type_set ((yyvsp[0].yykind_87), (yyvsp[-1].TAG));
+     }
+-#line 2683 "src/parse-gram.c"
++#line 2693 "src/parse-gram.c"
+     break;
+ 
+   case 81: /* token_decls_for_prec: token_decls_for_prec "<tag>" token_decl_for_prec.1  */
+-#line 602 "src/parse-gram.y"
++#line 613 "src/parse-gram.y"
+     {
+       (yyval.token_decls_for_prec) = symbol_list_append ((yyvsp[-2].token_decls_for_prec), symbol_list_type_set ((yyvsp[0].yykind_87), (yyvsp[-1].TAG)));
+     }
+-#line 2691 "src/parse-gram.c"
++#line 2701 "src/parse-gram.c"
+     break;
+ 
+   case 82: /* token_decl_for_prec.1: token_decl_for_prec  */
+-#line 610 "src/parse-gram.y"
++#line 621 "src/parse-gram.y"
+     { (yyval.yykind_87) = symbol_list_sym_new ((yyvsp[0].token_decl_for_prec), (yylsp[0])); }
+-#line 2697 "src/parse-gram.c"
++#line 2707 "src/parse-gram.c"
+     break;
+ 
+   case 83: /* token_decl_for_prec.1: token_decl_for_prec.1 token_decl_for_prec  */
+-#line 612 "src/parse-gram.y"
++#line 623 "src/parse-gram.y"
+     { (yyval.yykind_87) = symbol_list_append ((yyvsp[-1].yykind_87), symbol_list_sym_new ((yyvsp[0].token_decl_for_prec), (yylsp[0]))); }
+-#line 2703 "src/parse-gram.c"
++#line 2713 "src/parse-gram.c"
+     break;
+ 
+   case 84: /* token_decl_for_prec: id int.opt  */
+-#line 617 "src/parse-gram.y"
++#line 628 "src/parse-gram.y"
+     {
+       (yyval.token_decl_for_prec) = (yyvsp[-1].id);
+       symbol_class_set ((yyvsp[-1].id), token_sym, (yylsp[-1]), false);
+       if (0 <= (yyvsp[0].yykind_84))
+         symbol_code_set ((yyvsp[-1].id), (yyvsp[0].yykind_84), (yylsp[0]));
+     }
+-#line 2714 "src/parse-gram.c"
++#line 2724 "src/parse-gram.c"
+     break;
+ 
+   case 86: /* symbol_decls: symbols.1  */
+-#line 634 "src/parse-gram.y"
++#line 645 "src/parse-gram.y"
+     {
+       (yyval.symbol_decls) = (yyvsp[0].yykind_90);
+     }
+-#line 2722 "src/parse-gram.c"
++#line 2732 "src/parse-gram.c"
+     break;
+ 
+   case 87: /* symbol_decls: "<tag>" symbols.1  */
+-#line 638 "src/parse-gram.y"
++#line 649 "src/parse-gram.y"
+     {
+       (yyval.symbol_decls) = symbol_list_type_set ((yyvsp[0].yykind_90), (yyvsp[-1].TAG));
+     }
+-#line 2730 "src/parse-gram.c"
++#line 2740 "src/parse-gram.c"
+     break;
+ 
+   case 88: /* symbol_decls: symbol_decls "<tag>" symbols.1  */
+-#line 642 "src/parse-gram.y"
++#line 653 "src/parse-gram.y"
+     {
+       (yyval.symbol_decls) = symbol_list_append ((yyvsp[-2].symbol_decls), symbol_list_type_set ((yyvsp[0].yykind_90), (yyvsp[-1].TAG)));
+     }
+-#line 2738 "src/parse-gram.c"
++#line 2748 "src/parse-gram.c"
+     break;
+ 
+   case 89: /* symbols.1: symbol  */
+-#line 650 "src/parse-gram.y"
++#line 661 "src/parse-gram.y"
+     {
+       if (current_class != unknown_sym)
+         symbol_class_set ((yyvsp[0].symbol), current_class, (yylsp[0]), false);
+       (yyval.yykind_90) = symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0]));
+     }
+-#line 2748 "src/parse-gram.c"
++#line 2758 "src/parse-gram.c"
+     break;
+ 
+   case 90: /* symbols.1: symbols.1 symbol  */
+-#line 656 "src/parse-gram.y"
++#line 667 "src/parse-gram.y"
+     {
+       if (current_class != unknown_sym)
+         symbol_class_set ((yyvsp[0].symbol), current_class, (yylsp[0]), false);
+       (yyval.yykind_90) = symbol_list_append ((yyvsp[-1].yykind_90), symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0])));
+     }
+-#line 2758 "src/parse-gram.c"
++#line 2768 "src/parse-gram.c"
+     break;
+ 
+   case 95: /* rules_or_grammar_declaration: error ";"  */
+-#line 678 "src/parse-gram.y"
++#line 689 "src/parse-gram.y"
+     {
+       yyerrok;
+     }
+-#line 2766 "src/parse-gram.c"
++#line 2776 "src/parse-gram.c"
+     break;
+ 
+   case 96: /* $@5: %empty  */
+-#line 684 "src/parse-gram.y"
++#line 695 "src/parse-gram.y"
+                          { current_lhs ((yyvsp[-1].id_colon), (yylsp[-1]), (yyvsp[0].yykind_97)); }
+-#line 2772 "src/parse-gram.c"
++#line 2782 "src/parse-gram.c"
+     break;
+ 
+   case 97: /* rules: id_colon named_ref.opt $@5 ":" rhses.1  */
+-#line 685 "src/parse-gram.y"
++#line 696 "src/parse-gram.y"
+     {
+       /* Free the current lhs. */
+       current_lhs (0, (yylsp[-4]), 0);
+     }
+-#line 2781 "src/parse-gram.c"
++#line 2791 "src/parse-gram.c"
+     break;
+ 
+   case 98: /* rhses.1: rhs  */
+-#line 692 "src/parse-gram.y"
++#line 703 "src/parse-gram.y"
+                      { grammar_current_rule_end ((yylsp[0])); }
+-#line 2787 "src/parse-gram.c"
++#line 2797 "src/parse-gram.c"
+     break;
+ 
+   case 99: /* rhses.1: rhses.1 "|" rhs  */
+-#line 693 "src/parse-gram.y"
++#line 704 "src/parse-gram.y"
+                      { grammar_current_rule_end ((yylsp[0])); }
+-#line 2793 "src/parse-gram.c"
++#line 2803 "src/parse-gram.c"
+     break;
+ 
+   case 101: /* rhs: %empty  */
+-#line 700 "src/parse-gram.y"
++#line 711 "src/parse-gram.y"
+     { grammar_current_rule_begin (current_lhs_symbol, current_lhs_loc,
+                                   current_lhs_named_ref); }
+-#line 2800 "src/parse-gram.c"
++#line 2810 "src/parse-gram.c"
+     break;
+ 
+   case 102: /* rhs: rhs symbol named_ref.opt  */
+-#line 703 "src/parse-gram.y"
++#line 714 "src/parse-gram.y"
+     { grammar_current_rule_symbol_append ((yyvsp[-1].symbol), (yylsp[-1]), (yyvsp[0].yykind_97)); }
+-#line 2806 "src/parse-gram.c"
++#line 2816 "src/parse-gram.c"
+     break;
+ 
+   case 103: /* rhs: rhs tag.opt "{...}" named_ref.opt  */
+-#line 705 "src/parse-gram.y"
++#line 716 "src/parse-gram.y"
+     { grammar_current_rule_action_append ((yyvsp[-1].BRACED_CODE), (yylsp[-1]), (yyvsp[0].yykind_97), (yyvsp[-2].yykind_76)); }
+-#line 2812 "src/parse-gram.c"
++#line 2822 "src/parse-gram.c"
+     break;
+ 
+   case 104: /* rhs: rhs "%?{...}"  */
+-#line 707 "src/parse-gram.y"
++#line 718 "src/parse-gram.y"
+     { grammar_current_rule_predicate_append ((yyvsp[0].BRACED_PREDICATE), (yylsp[0])); }
+-#line 2818 "src/parse-gram.c"
++#line 2828 "src/parse-gram.c"
+     break;
+ 
+   case 105: /* rhs: rhs "%empty"  */
+-#line 709 "src/parse-gram.y"
++#line 720 "src/parse-gram.y"
+     { grammar_current_rule_empty_set ((yylsp[0])); }
+-#line 2824 "src/parse-gram.c"
++#line 2834 "src/parse-gram.c"
+     break;
+ 
+   case 106: /* rhs: rhs "%prec" symbol  */
+-#line 711 "src/parse-gram.y"
++#line 722 "src/parse-gram.y"
+     { grammar_current_rule_prec_set ((yyvsp[0].symbol), (yylsp[0])); }
+-#line 2830 "src/parse-gram.c"
++#line 2840 "src/parse-gram.c"
+     break;
+ 
+   case 107: /* rhs: rhs "%dprec" "integer literal"  */
+-#line 713 "src/parse-gram.y"
++#line 724 "src/parse-gram.y"
+     { grammar_current_rule_dprec_set ((yyvsp[0].INT_LITERAL), (yylsp[0])); }
+-#line 2836 "src/parse-gram.c"
++#line 2846 "src/parse-gram.c"
+     break;
+ 
+   case 108: /* rhs: rhs "%merge" "<tag>"  */
+-#line 715 "src/parse-gram.y"
++#line 726 "src/parse-gram.y"
+     { grammar_current_rule_merge_set ((yyvsp[0].TAG), (yylsp[0])); }
+-#line 2842 "src/parse-gram.c"
++#line 2852 "src/parse-gram.c"
+     break;
+ 
+   case 109: /* rhs: rhs "%expect" "integer literal"  */
+-#line 717 "src/parse-gram.y"
++#line 728 "src/parse-gram.y"
+     { grammar_current_rule_expect_sr ((yyvsp[0].INT_LITERAL), (yylsp[0])); }
+-#line 2848 "src/parse-gram.c"
++#line 2858 "src/parse-gram.c"
+     break;
+ 
+   case 110: /* rhs: rhs "%expect-rr" "integer literal"  */
+-#line 719 "src/parse-gram.y"
++#line 730 "src/parse-gram.y"
+     { grammar_current_rule_expect_rr ((yyvsp[0].INT_LITERAL), (yylsp[0])); }
+-#line 2854 "src/parse-gram.c"
++#line 2864 "src/parse-gram.c"
+     break;
+ 
+   case 111: /* named_ref.opt: %empty  */
+-#line 723 "src/parse-gram.y"
++#line 734 "src/parse-gram.y"
+                  { (yyval.yykind_97) = NULL; }
+-#line 2860 "src/parse-gram.c"
++#line 2870 "src/parse-gram.c"
+     break;
+ 
+   case 112: /* named_ref.opt: "[identifier]"  */
+-#line 724 "src/parse-gram.y"
++#line 735 "src/parse-gram.y"
+                  { (yyval.yykind_97) = named_ref_new ((yyvsp[0].BRACKETED_ID), (yylsp[0])); }
+-#line 2866 "src/parse-gram.c"
++#line 2876 "src/parse-gram.c"
+     break;
+ 
+   case 114: /* value: %empty  */
+-#line 757 "src/parse-gram.y"
++#line 768 "src/parse-gram.y"
+           { (yyval.value).kind = muscle_keyword; (yyval.value).chars = ""; }
+-#line 2872 "src/parse-gram.c"
++#line 2882 "src/parse-gram.c"
+     break;
+ 
+   case 115: /* value: "identifier"  */
+-#line 758 "src/parse-gram.y"
++#line 769 "src/parse-gram.y"
+           { (yyval.value).kind = muscle_keyword; (yyval.value).chars = (yyvsp[0].ID); }
+-#line 2878 "src/parse-gram.c"
++#line 2888 "src/parse-gram.c"
+     break;
+ 
+   case 116: /* value: "string"  */
+-#line 759 "src/parse-gram.y"
++#line 770 "src/parse-gram.y"
+           { (yyval.value).kind = muscle_string;  (yyval.value).chars = unquote ((yyvsp[0].STRING)); gram_scanner_last_string_free ();}
+-#line 2884 "src/parse-gram.c"
++#line 2894 "src/parse-gram.c"
+     break;
+ 
+   case 117: /* value: "{...}"  */
+-#line 760 "src/parse-gram.y"
++#line 771 "src/parse-gram.y"
+           { (yyval.value).kind = muscle_code;    (yyval.value).chars = strip_braces ((yyvsp[0].BRACED_CODE)); gram_scanner_last_string_free (); }
+-#line 2890 "src/parse-gram.c"
++#line 2900 "src/parse-gram.c"
+     break;
+ 
+   case 118: /* id: "identifier"  */
+-#line 773 "src/parse-gram.y"
++#line 784 "src/parse-gram.y"
+     { (yyval.id) = symbol_from_uniqstr ((yyvsp[0].ID), (yylsp[0])); }
+-#line 2896 "src/parse-gram.c"
++#line 2906 "src/parse-gram.c"
+     break;
+ 
+   case 119: /* id: "character literal"  */
+-#line 775 "src/parse-gram.y"
++#line 786 "src/parse-gram.y"
+     {
+       const char *var = "api.token.raw";
+       if (current_class == nterm_sym)
+@@ -2917,35 +2927,35 @@
+       symbol_class_set ((yyval.id), token_sym, (yylsp[0]), false);
+       symbol_code_set ((yyval.id), (yyvsp[0].CHAR_LITERAL), (yylsp[0]));
+     }
+-#line 2921 "src/parse-gram.c"
++#line 2931 "src/parse-gram.c"
+     break;
+ 
+   case 120: /* id_colon: "identifier:"  */
+-#line 798 "src/parse-gram.y"
++#line 809 "src/parse-gram.y"
+            { (yyval.id_colon) = symbol_from_uniqstr ((yyvsp[0].ID_COLON), (yylsp[0])); }
+-#line 2927 "src/parse-gram.c"
++#line 2937 "src/parse-gram.c"
+     break;
+ 
+   case 123: /* string_as_id: "string"  */
+-#line 810 "src/parse-gram.y"
++#line 821 "src/parse-gram.y"
+     {
+       (yyval.string_as_id) = symbol_get ((yyvsp[0].STRING), (yylsp[0]));
+       symbol_class_set ((yyval.string_as_id), token_sym, (yylsp[0]), false);
+     }
+-#line 2936 "src/parse-gram.c"
++#line 2946 "src/parse-gram.c"
+     break;
+ 
+   case 125: /* epilogue.opt: "%%" "epilogue"  */
+-#line 819 "src/parse-gram.y"
++#line 830 "src/parse-gram.y"
+     {
+       muscle_code_grow ("epilogue", translate_code ((yyvsp[0].EPILOGUE), (yylsp[0]), true), (yylsp[0]));
+       code_scanner_last_string_free ();
+     }
+-#line 2945 "src/parse-gram.c"
++#line 2955 "src/parse-gram.c"
+     break;
+ 
+ 
+-#line 2949 "src/parse-gram.c"
++#line 2959 "src/parse-gram.c"
+ 
+         default: break;
+       }
+@@ -3159,7 +3169,7 @@
+   return yyresult;
+ }
+ 
+-#line 825 "src/parse-gram.y"
++#line 836 "src/parse-gram.y"
+ 
+ 
+ int
+@@ -3290,14 +3300,24 @@
+ }
+ 
+ 
++static bool
++valid_output_file_name (char const *file)
++{
++  return !strchr (file, '/');
++}
++
++
+ static void
+-handle_header (char const *value)
++handle_header (location const *loc, char const *value)
+ {
+   header_flag = true;
+   if (value)
+     {
+       char *file = unquote (value);
+-      spec_header_file = xstrdup (file);
++      if (valid_output_file_name (file))
++        spec_header_file = xstrdup (file);
++      else
++        complain (loc, complaint, _("invalid %%header file name ignored"));
+       gram_scanner_last_string_free ();
+       unquote_free (file);
+     }
+--- bison-3.8.2.orig/src/parse-gram.h
++++ bison-3.8.2/src/parse-gram.h
+@@ -57,7 +57,7 @@
+ 
+   #include "symlist.h"
+   #include "symtab.h"
+-#line 268 "src/parse-gram.y"
++#line 271 "src/parse-gram.y"
+ 
+   typedef enum
+   {
+@@ -66,7 +66,7 @@
+     param_parse  = 1 << 1,
+     param_both   = param_lex | param_parse
+   } param_type;
+-#line 737 "src/parse-gram.y"
++#line 748 "src/parse-gram.y"
+ 
+   #include "muscle-tab.h"
+   typedef struct
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/bison.git/commitdiff/d92b0e87cac1a0ec820bcb7f488450089ae86e2a



More information about the pld-cvs-commit mailing list