[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