diff options
author | thegeorg <thegeorg@yandex-team.com> | 2024-08-11 11:42:23 +0300 |
---|---|---|
committer | thegeorg <thegeorg@yandex-team.com> | 2024-08-11 11:54:06 +0300 |
commit | cd788243496b69e548998f9e3f9ff80e34977652 (patch) | |
tree | 0fd50f566b69bc2cfd0d9c4c18eea1b77d5ec276 | |
parent | c7230d56fb1b7998da0edb829f1751640da9c8b4 (diff) | |
download | ydb-cd788243496b69e548998f9e3f9ff80e34977652.tar.gz |
Update contrib/tools/bison to 3.7.6
583623e1fb299df0a04a0aecdc47eb759ef412b9
197 files changed, 16560 insertions, 3509 deletions
diff --git a/contrib/tools/bison/AUTHORS b/contrib/tools/bison/AUTHORS index e624c51bc7..b3d8d8edb3 100644 --- a/contrib/tools/bison/AUTHORS +++ b/contrib/tools/bison/AUTHORS @@ -24,7 +24,7 @@ and nasty bugs. ----- -Copyright (C) 1998-2015, 2018-2020 Free Software Foundation, Inc. +Copyright (C) 1998-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -39,4 +39,4 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with this program. If not, see <http://www.gnu.org/licenses/>. +along with this program. If not, see <https://www.gnu.org/licenses/>. diff --git a/contrib/tools/bison/COPYING b/contrib/tools/bison/COPYING index 94a9ed024d..f288702d2f 100644 --- a/contrib/tools/bison/COPYING +++ b/contrib/tools/bison/COPYING @@ -1,7 +1,7 @@ GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 - Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @@ -645,7 +645,7 @@ the "copyright" line and a pointer to where the full notice is found. GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. + along with this program. If not, see <https://www.gnu.org/licenses/>. Also add information on how to contact you by electronic and paper mail. @@ -664,11 +664,11 @@ might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see -<http://www.gnu.org/licenses/>. +<https://www.gnu.org/licenses/>. The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read -<http://www.gnu.org/philosophy/why-not-lgpl.html>. +<https://www.gnu.org/licenses/why-not-lgpl.html>. diff --git a/contrib/tools/bison/NEWS b/contrib/tools/bison/NEWS index 919ff38717..84d27235ef 100644 --- a/contrib/tools/bison/NEWS +++ b/contrib/tools/bison/NEWS @@ -1,5 +1,360 @@ GNU Bison NEWS +* Noteworthy changes in release 3.7.6 (2021-03-08) [stable] + +** Bug fixes + +*** Reused Push Parsers + + When a push-parser state structure is used for multiple parses, it was + possible for some state to leak from one run into the following one. + +*** Fix Table Generation + + In some very rare conditions, when there are many useless tokens, it was + possible to generate incorrect parsers. + + +* Noteworthy changes in release 3.7.5 (2021-01-24) [stable] + +** Bug fixes + +*** Counterexample Generation + + In some cases counterexample generation could crash. This is fixed. + +*** Fix Table Generation + + In some very rare conditions, when there are many useless tokens, it was + possible to generate incorrect parsers. + +*** GLR parsers now support %merge together with api.value.type=union. + +*** C++ parsers use noexcept in more places. + +*** Generated parsers avoid some warnings about signedness issues. + +*** C-language parsers now avoid warnings from pedantic clang. + +*** C-language parsers now work around quirks of HP-UX 11.23 (2003). + + +* Noteworthy changes in release 3.7.4 (2020-11-14) [stable] + +** Bug fixes + +*** Bug fixes in yacc.c + + In Yacc mode, all the tokens are defined twice: once as an enum, and then + as a macro. YYEMPTY was missing its macro. + +*** Bug fixes in lalr1.cc + + The lalr1.cc skeleton used to emit internal assertions (using YY_ASSERT) + even when the `parse.assert` %define variable is not enabled. It no + longer does. + + The private internal macro YY_ASSERT now obeys the `api.prefix` %define + variable. + + When there is a very large number of tokens, some assertions could be long + enough to hit arbitrary limits in Visual C++. They have been rewritten to + work around this limitation. + +** Changes + + The YYBISON macro in generated "regular C parsers" (from the "yacc.c" + skeleton) used to be defined to 1. It is now defined to the version of + Bison as an integer (e.g., 30704 for version 3.7.4). + +* Noteworthy changes in release 3.7.3 (2020-10-13) [stable] + +** Bug fixes + + Fix concurrent build issues. + + The bison executable is no longer linked uselessly against libreadline. + + Fix incorrect use of yytname in glr.cc. + +* Noteworthy changes in release 3.7.2 (2020-09-05) [stable] + + This release of Bison fixes all known bugs reported for Bison in MITRE's + Common Vulnerabilities and Exposures (CVE) system. These vulnerabilities + are only about bison-the-program itself, not the generated code. + + Although these bugs are typically irrelevant to how Bison is used, they + are worth fixing if only to give users peace of mind. + + There is no known vulnerability in the generated parsers. + +** Bug fixes + + Fix concurrent build issues (introduced in Bison 3.5). + + Push parsers always use YYMALLOC/YYFREE (no direct calls to malloc/free). + + Fix portability issues of the test suite, and of bison itself. + + Some unlikely crashes found by fuzzing have been fixed. This is only + about bison itself, not the generated parsers. + + +* Noteworthy changes in release 3.7.1 (2020-08-02) [stable] + +** Bug fixes + + Crash when a token alias contains a NUL byte. + + Portability issues with libtextstyle. + + Portability issues of Bison itself with MSVC. + +** Changes + + Improvements and fixes in the documentation. + + More precise location about symbol type redefinitions. + + +* Noteworthy changes in release 3.7 (2020-07-23) [stable] + +** Deprecated features + + The YYPRINT macro, which works only with yacc.c and only for tokens, was + obsoleted long ago by %printer, introduced in Bison 1.50 (November 2002). + It is deprecated and its support will be removed eventually. + + In conformance with the recommendations of the Graphviz team, in the next + version Bison the option `--graph` will generate a *.gv file by default, + instead of *.dot. A transition started in Bison 3.4. + +** New features + +*** Counterexample Generation + + Contributed by Vincent Imbimbo. + + When given `-Wcounterexamples`/`-Wcex`, bison will now output + counterexamples for conflicts. + +**** Unifying Counterexamples + + Unifying counterexamples are strings which can be parsed in two ways due + to the conflict. For example on a grammar that contains the usual + "dangling else" ambiguity: + + $ bison else.y + else.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] + else.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples + + $ bison else.y -Wcex + else.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] + else.y: warning: shift/reduce conflict on token "else" [-Wcounterexamples] + Example: "if" exp "then" "if" exp "then" exp • "else" exp + Shift derivation + exp + ↳ "if" exp "then" exp + ↳ "if" exp "then" exp • "else" exp + Example: "if" exp "then" "if" exp "then" exp • "else" exp + Reduce derivation + exp + ↳ "if" exp "then" exp "else" exp + ↳ "if" exp "then" exp • + + When text styling is enabled, colors are used in the examples and the + derivations to highlight the structure of both analyses. In this case, + + "if" exp "then" [ "if" exp "then" exp • ] "else" exp + + vs. + + "if" exp "then" [ "if" exp "then" exp • "else" exp ] + + + The counterexamples are "focused", in two different ways. First, they do + not clutter the output with all the derivations from the start symbol, + rather they start on the "conflicted nonterminal". They go straight to the + point. Second, they don't "expand" nonterminal symbols uselessly. + +**** Nonunifying Counterexamples + + In the case of the dangling else, Bison found an example that can be + parsed in two ways (therefore proving that the grammar is ambiguous). + When it cannot find such an example, it instead generates two examples + that are the same up until the dot: + + $ bison foo.y + foo.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] + foo.y: note: rerun with option '-Wcounterexamples' to generate conflict counterexamples + foo.y:4.4-7: warning: rule useless in parser due to conflicts [-Wother] + 4 | a: expr + | ^~~~ + + $ bison -Wcex foo.y + foo.y: warning: 1 shift/reduce conflict [-Wconflicts-sr] + foo.y: warning: shift/reduce conflict on token ID [-Wcounterexamples] + First example: expr • ID ',' ID $end + Shift derivation + $accept + ↳ s $end + ↳ a ID + ↳ expr + ↳ expr • ID ',' + Second example: expr • ID $end + Reduce derivation + $accept + ↳ s $end + ↳ a ID + ↳ expr • + foo.y:4.4-7: warning: rule useless in parser due to conflicts [-Wother] + 4 | a: expr + | ^~~~ + + In these cases, the parser usually doesn't have enough lookahead to + differentiate the two given examples. + +**** Reports + + Counterexamples are also included in the report when given + `--report=counterexamples`/`-rcex` (or `--report=all`), with more + technical details: + + State 7 + + 1 exp: "if" exp "then" exp • [$end, "then", "else"] + 2 | "if" exp "then" exp • "else" exp + + "else" shift, and go to state 8 + + "else" [reduce using rule 1 (exp)] + $default reduce using rule 1 (exp) + + shift/reduce conflict on token "else": + 1 exp: "if" exp "then" exp • + 2 exp: "if" exp "then" exp • "else" exp + Example: "if" exp "then" "if" exp "then" exp • "else" exp + Shift derivation + exp + ↳ "if" exp "then" exp + ↳ "if" exp "then" exp • "else" exp + Example: "if" exp "then" "if" exp "then" exp • "else" exp + Reduce derivation + exp + ↳ "if" exp "then" exp "else" exp + ↳ "if" exp "then" exp • + +*** File prefix mapping + + Contributed by Joshua Watt. + + Bison learned a new argument, `--file-prefix-map OLD=NEW`. Any file path + in the output (specifically `#line` directives and `#ifdef` header guards) + that begins with the prefix OLD will have it replaced with the prefix NEW, + similar to the `-ffile-prefix-map` in GCC. This option can be used to + make bison output reproducible. + +** Changes + +*** Diagnostics + + When text styling is enabled and the terminal supports it, the warnings + now include hyperlinks to the documentation. + +*** Relocatable installation + + When installed to be relocatable (via `configure --enable-relocatable`), + bison will now also look for a relocated m4. + +*** C++ file names + + The `filename_type` %define variable was renamed `api.filename.type`. + Instead of + + %define filename_type "symbol" + + write + + %define api.filename.type {symbol} + + (Or let `bison --update` do it for you). + + It now defaults to `const std::string` instead of `std::string`. + +*** Deprecated %define variable names + + The following variables have been renamed for consistency. Backward + compatibility is ensured, but upgrading is recommended. + + filename_type -> api.filename.type + package -> api.package + +*** Push parsers no longer clear their state when parsing is finished + + Previously push-parsers cleared their state when parsing was finished (on + success and on failure). This made it impossible to check if there were + parse errors, since `yynerrs` was also reset. This can be especially + troublesome when used in autocompletion, since a parser with error + recovery would suggest (irrelevant) expected tokens even if there were + failures. + + Now the parser state can be examined when parsing is finished. The parser + state is reset when starting a new parse. + +** Documentation + +*** Examples + + The bistromathic demonstrates %param and how to quote sources in the error + messages: + + > 123 456 + 1.5-7: syntax error: expected end of file or + or - or * or / or ^ before number + 1 | 123 456 + | ^~~ + +** Bug fixes + +*** Include the generated header (yacc.c) + + Historically, when --defines was used, bison generated a header and pasted + an exact copy of it into the generated parser implementation file. Since + Bison 3.4 it is possible to specify that the header should be `#include`d, + and how. For instance + + %define api.header.include {"parse.h"} + + or + + %define api.header.include {<parser/parse.h>} + + Now api.header.include defaults to `"header-basename"`, as was intended in + Bison 3.4, where `header-basename` is the basename of the generated + header. This is disabled when the generated header is `y.tab.h`, to + comply with Automake's ylwrap. + +*** String aliases are faithfully propagated + + Bison used to interpret user strings (i.e., decoding backslash escapes) + when reading them, and to escape them (i.e., issue non-printable + characters as backslash escapes, taking the locale into account) when + outputting them. As a consequence non-ASCII strings (say in UTF-8) ended + up "ciphered" as sequences of backslash escapes. This happened not only + in the generated sources (where the compiler will reinterpret them), but + also in all the generated reports (text, xml, html, dot, etc.). Reports + were therefore not readable when string aliases were not pure ASCII. + Worse yet: the output depended on the user's locale. + + Now Bison faithfully treats the string aliases exactly the way the user + spelled them. This fixes all the aforementioned problems. However, now, + string aliases semantically equivalent but syntactically different (e.g., + "A", "\x41", "\101") are considered to be different. + +*** Crash when generating IELR + + An old, well hidden, bug in the generation of IELR parsers was fixed. + + * Noteworthy changes in release 3.6.4 (2020-06-15) [stable] ** Bug fixes @@ -7,6 +362,7 @@ GNU Bison NEWS In glr.cc some internal macros leaked in the user's code, and could damage access to the token kinds. + * Noteworthy changes in release 3.6.3 (2020-06-03) [stable] ** Bug fixes @@ -17,6 +373,7 @@ GNU Bison NEWS Incorrect display of gotos in LAC traces (lalr1.cc). + * Noteworthy changes in release 3.6.2 (2020-05-17) [stable] ** Bug fixes @@ -29,6 +386,7 @@ GNU Bison NEWS bison used to emit "nested" comments, which is invalid C. + * Noteworthy changes in release 3.6.1 (2020-05-10) [stable] ** Bug fixes @@ -43,6 +401,7 @@ GNU Bison NEWS In C++, yy::parser::symbol_type now has a public name() member function. + * Noteworthy changes in release 3.6 (2020-05-08) [stable] ** Backward incompatible changes @@ -265,6 +624,7 @@ GNU Bison NEWS autocompletion on the existing variables, rather than of the word "variable". + * Noteworthy changes in release 3.5.4 (2020-04-05) [stable] ** WARNING: Future backward-incompatibilities! @@ -285,6 +645,7 @@ GNU Bison NEWS Fix api.token.raw support in Java. + * Noteworthy changes in release 3.5.3 (2020-03-08) [stable] ** Bug fixes @@ -293,7 +654,9 @@ GNU Bison NEWS \005) with incorrect styling. Fixes for similar issues with unexpectedly short lines (e.g., the file was changed between parsing and diagnosing). - Several unlikely crashes found by fuzzing have been fixed. + Some unlikely crashes found by fuzzing have been fixed. This is only + about bison itself, not the generated parsers. + * Noteworthy changes in release 3.5.2 (2020-02-13) [stable] @@ -304,6 +667,7 @@ GNU Bison NEWS The lalr1.cc skeleton properly rejects unsupported values for parse.lac (as yacc.c does). + * Noteworthy changes in release 3.5.1 (2020-01-19) [stable] ** Bug fixes @@ -312,6 +676,7 @@ GNU Bison NEWS Fix compiler warnings. + * Noteworthy changes in release 3.5 (2019-12-11) [stable] ** Backward incompatible changes @@ -519,6 +884,7 @@ GNU Bison NEWS In Java, %define api.prefix was ignored. It now behaves as expected. + * Noteworthy changes in release 3.4.2 (2019-09-12) [stable] ** Bug fixes @@ -536,12 +902,14 @@ GNU Bison NEWS When lone carriage-return characters appeared in the input file, diagnostics could hang forever. + * Noteworthy changes in release 3.4.1 (2019-05-22) [stable] ** Bug fixes Portability fixes. + * Noteworthy changes in release 3.4 (2019-05-19) [stable] ** Deprecated features @@ -682,6 +1050,7 @@ GNU Bison NEWS system, in December 1987. See the NEWS of Bison 3.3 for the previous oldest bug. + * Noteworthy changes in release 3.3.2 (2019-02-03) [stable] ** Bug fixes @@ -689,6 +1058,7 @@ GNU Bison NEWS Bison 3.3 failed to generate parsers for grammars with unused nonterminal symbols. + * Noteworthy changes in release 3.3.1 (2019-01-27) [stable] ** Changes @@ -696,6 +1066,7 @@ GNU Bison NEWS The option -y/--yacc used to imply -Werror=yacc, which turns uses of Bison extensions into errors. It now makes them simple warnings (-Wyacc). + * Noteworthy changes in release 3.3 (2019-01-26) [stable] A new mailing list was created, Bison Announce. It is low traffic, and is @@ -838,11 +1209,11 @@ GNU Bison NEWS ... - Looking at the output from -v, one can see that the shift-reduce conflict + Looking at the output from -v, one can see that the shift/reduce conflict here is due to the fact that the parser does not know whether to reduce arguments to argument_list until it sees the token _after_ the following ','. By marking the rule with %expect 1 (because there is a conflict in - one state), we document the source of the 1 overall shift-reduce conflict. + one state), we document the source of the 1 overall shift/reduce conflict. In GLR parsers, we can use %expect-rr in a rule for reduce/reduce conflicts. In this case, we mark each of the conflicting rules. For @@ -957,7 +1328,7 @@ GNU Bison NEWS ** Bug fixes -*** Incorrect number of reduce-reduce conflicts +*** Incorrect number of reduce/reduce conflicts On a grammar such as @@ -1011,6 +1382,7 @@ GNU Bison NEWS literal such as ‘"number"’. The post-fix quantifiers are ‘?’ (zero or one), ‘*’ (zero or more) and ‘+’ (one or more). + * Noteworthy changes in release 3.2.4 (2018-12-24) [stable] ** Bug fixes @@ -1019,6 +1391,7 @@ GNU Bison NEWS Always provide a copy constructor for symbol_type, even in modern C++. + * Noteworthy changes in release 3.2.3 (2018-12-18) [stable] ** Bug fixes @@ -1026,12 +1399,14 @@ GNU Bison NEWS Properly support token constructors in C++ with types that include commas (e.g., std::pair<int, int>). A regression introduced in Bison 3.2. + * Noteworthy changes in release 3.2.2 (2018-11-21) [stable] ** Bug fixes C++ portability issues. + * Noteworthy changes in release 3.2.1 (2018-11-09) [stable] ** Bug fixes @@ -1039,6 +1414,7 @@ GNU Bison NEWS Several portability issues have been fixed in the build system, in the test suite, and in the generated parsers in C++. + * Noteworthy changes in release 3.2 (2018-10-29) [stable] ** Backward incompatible changes @@ -1205,6 +1581,7 @@ GNU Bison NEWS Portability/warning issues with Flex. + * Noteworthy changes in release 3.1 (2018-08-27) [stable] ** Backward incompatible changes @@ -1345,6 +1722,7 @@ GNU Bison NEWS Useless code was removed from C++ parsers, and some of the generated constructors are more 'natural'. + * Noteworthy changes in release 3.0.5 (2018-05-27) [stable] ** Bug fixes @@ -1375,6 +1753,7 @@ GNU Bison NEWS On some platforms, some Java and/or C++ tests were failing. + * Noteworthy changes in release 3.0.4 (2015-01-23) [stable] ** Bug fixes @@ -1387,6 +1766,7 @@ GNU Bison NEWS Several portability issues in tests were fixed. + * Noteworthy changes in release 3.0.3 (2015-01-15) [stable] ** Bug fixes @@ -1443,6 +1823,7 @@ GNU Bison NEWS - calc++ a calculator in C++ using variant support and token constructors. + * Noteworthy changes in release 3.0.2 (2013-12-05) [stable] ** Bug fixes @@ -1467,6 +1848,7 @@ GNU Bison NEWS When C++ variant support is enabled, an error triggered via YYERROR, but not caught via error recovery, resulted in a double deletion. + * Noteworthy changes in release 3.0.1 (2013-11-12) [stable] ** Bug fixes @@ -1498,6 +1880,7 @@ GNU Bison NEWS Bugs and portability issues. + * Noteworthy changes in release 3.0 (2013-07-25) [stable] ** WARNING: Future backward-incompatibilities! @@ -1868,7 +2251,7 @@ GNU Bison NEWS %error-verbose directive is deprecated in favor of "%define parse.error verbose". -** Renamed %define variables +** Deprecated %define variable names The following variables have been renamed for consistency. Backward compatibility is ensured, but upgrading is recommended. @@ -2094,6 +2477,7 @@ GNU Bison NEWS There are operator- and operator-= for 'location'. Negative line/column increments can no longer underflow the resulting value. + * Noteworthy changes in release 2.7.1 (2013-04-15) [stable] ** Bug fixes @@ -2104,6 +2488,7 @@ GNU Bison NEWS *** Fix some compiler warnings (lalr1.cc) + * Noteworthy changes in release 2.7 (2012-12-12) [stable] ** Bug fixes @@ -2228,6 +2613,7 @@ GNU Bison NEWS The translation of midrule actions is now described. + * Noteworthy changes in release 2.6.5 (2012-11-07) [stable] We consider compiler warnings about Bison generated parsers to be bugs. @@ -2247,10 +2633,12 @@ GNU Bison NEWS When possible, yylloc is correctly initialized before calling yylex. It is no longer necessary to initialize it in the %initial-action. + * Noteworthy changes in release 2.6.4 (2012-10-23) [stable] Bison 2.6.3's --version was incorrect. This release fixes this issue. + * Noteworthy changes in release 2.6.3 (2012-10-22) [stable] ** Bug fixes @@ -2295,6 +2683,7 @@ GNU Bison NEWS "function declared 'noreturn' should not return") have also been addressed. + * Noteworthy changes in release 2.6.2 (2012-08-03) [stable] ** Bug fixes @@ -2311,6 +2700,7 @@ GNU Bison NEWS The generated files no longer end (nor start) with empty lines. + * Noteworthy changes in release 2.6.1 (2012-07-30) [stable] Bison no longer executes user-specified M4 code when processing a grammar. @@ -2349,6 +2739,7 @@ GNU Bison NEWS will display two values for each typed and untyped symbol (provided that YYSTYPE has both "ival" and "fval" fields). + * Noteworthy changes in release 2.6 (2012-07-19) [stable] ** Future changes @@ -2482,6 +2873,7 @@ GNU Bison NEWS #endif /* !BAR_FOO_H */ #endif /* !BAR_FOO_H */ + * Noteworthy changes in release 2.5.1 (2012-06-05) [stable] ** Future changes: @@ -2579,6 +2971,7 @@ GNU Bison NEWS Running "make install-pdf" (or -dvi, -html, -info, and -ps) no longer halts in the middle of its course. + * Noteworthy changes in release 2.5 (2011-05-14) ** Grammar symbol names can now contain non-initial dashes: @@ -2934,6 +3327,7 @@ GNU Bison NEWS This bug has been fixed. + * Noteworthy changes in release 2.4.3 (2010-08-05) ** Bison now obeys -Werror and --warnings=error for warnings about @@ -2954,6 +3348,7 @@ GNU Bison NEWS ** Minor documentation fixes. + * Noteworthy changes in release 2.4.2 (2010-03-20) ** Some portability problems that resulted in failures and livelocks @@ -3020,7 +3415,7 @@ GNU Bison NEWS inherent flaws when %error-verbose or "#define YYERROR_VERBOSE" is used. For a more detailed discussion, see: - http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html + https://lists.gnu.org/r/bison-patches/2009-12/msg00024.html The upcoming Bison 2.5 will remove YYFAIL from Java parsers, but deterministic parsers in C will continue to implement it. However, @@ -3048,6 +3443,7 @@ GNU Bison NEWS message translations were not installed although supported by the host system. + * Noteworthy changes in release 2.4.1 (2008-12-11) ** In the GLR defines file, unexpanded M4 macros in the yylval and yylloc @@ -3073,6 +3469,7 @@ GNU Bison NEWS ** A few minor improvements to the Bison manual. + * Noteworthy changes in release 2.4 (2008-11-02) ** %language is an experimental feature. @@ -3088,6 +3485,7 @@ GNU Bison NEWS ** Several bugs in the C++ skeleton and the experimental Java skeleton have been fixed. + * Noteworthy changes in release 2.3b (2008-05-27) ** The quotes around NAME that used to be required in the following directive @@ -3274,6 +3672,7 @@ GNU Bison NEWS ** The nonfunctional --no-parser, -n, and %no-parser options have been completely removed from Bison. + * Noteworthy changes in release 2.3a (2006-09-13) ** Instead of %union, you can define and use your own union type @@ -3388,6 +3787,7 @@ GNU Bison NEWS The old spelling still works, but is not documented and may be removed in a future release. + * Noteworthy changes in release 2.3 (2006-06-05) ** GLR grammars should now use "YYRECOVERING ()" instead of "YYRECOVERING", @@ -3396,6 +3796,7 @@ GNU Bison NEWS ** It is now documented that any definition of YYSTYPE or YYLTYPE should be to a type name that does not contain parentheses or brackets. + * Noteworthy changes in release 2.2 (2006-05-19) ** The distribution terms for all Bison-generated parsers now permit @@ -3478,6 +3879,7 @@ GNU Bison NEWS ** DJGPP support added. + * Noteworthy changes in release 2.1 (2005-09-16) ** The C++ lalr1.cc skeleton supports %lex-param. @@ -3504,6 +3906,7 @@ GNU Bison NEWS print 'syntax error, unexpected number' instead of 'syntax error, unexpected "number"'. + * Noteworthy changes in release 2.0 (2004-12-25) ** Possibly-incompatible changes @@ -3567,6 +3970,7 @@ GNU Bison NEWS - Semicolons are now allowed before "|" in grammar rules, as POSIX requires. + * Noteworthy changes in release 1.875 (2003-01-01) ** The documentation license has been upgraded to version 1.2 @@ -3687,6 +4091,7 @@ GNU Bison NEWS ago, but nobody noticed until we recently asked someone to try building Bison with a K&R C compiler. + * Noteworthy changes in release 1.75 (2002-10-14) ** Bison should now work on 64-bit hosts. @@ -3718,6 +4123,7 @@ GNU Bison NEWS was incorrectly rejected: $1 is defined in the second midrule action, and is equal to the $$ of the first midrule action. + * Noteworthy changes in release 1.50 (2002-10-04) ** GLR parsing @@ -3765,7 +4171,7 @@ GNU Bison NEWS error token. The new behavior has long been the documented behavior, and has long been required by POSIX. For more details, please see Paul Eggert, "Reductions during Bison error handling" (2002-05-20) - <http://lists.gnu.org/archive/html/bug-bison/2002-05/msg00038.html>. + <https://lists.gnu.org/r/bug-bison/2002-05/msg00038.html>. ** Traces Popped tokens and nonterminals are now reported. @@ -3862,6 +4268,7 @@ GNU Bison NEWS ** GNU M4 is now required when using Bison. + * Noteworthy changes in release 1.35 (2002-03-25) ** C Skeleton @@ -3877,6 +4284,7 @@ GNU Bison NEWS This kludge also addresses some C++ problems when the stack was extended. + * Noteworthy changes in release 1.34 (2002-03-12) ** File name clashes are detected @@ -3897,6 +4305,7 @@ GNU Bison NEWS ** Fix test suite portability problems. + * Noteworthy changes in release 1.33 (2002-02-07) ** Fix C++ issues @@ -3906,6 +4315,7 @@ GNU Bison NEWS ** Catch invalid @n As is done with $n. + * Noteworthy changes in release 1.32 (2002-01-23) ** Fix Yacc output file names @@ -3914,6 +4324,7 @@ GNU Bison NEWS ** Italian, Dutch translations + * Noteworthy changes in release 1.31 (2002-01-14) ** Many Bug Fixes @@ -4001,6 +4412,7 @@ GNU Bison NEWS ** --output New, aliasing "--output-file". + * Noteworthy changes in release 1.30 (2001-10-26) ** "--defines" and "--graph" have now an optional argument which is the @@ -4012,6 +4424,7 @@ GNU Bison NEWS ** Portability fixes. + * Noteworthy changes in release 1.29 (2001-09-07) ** The output file does not define const, as this caused problems when used @@ -4047,6 +4460,7 @@ GNU Bison NEWS ** @$ Automatic location tracking. + * Noteworthy changes in release 1.28 (1999-07-06) ** Should compile better now with K&R compilers. @@ -4057,11 +4471,13 @@ GNU Bison NEWS ** There is now a FAQ. + * Noteworthy changes in release 1.27 ** The make rule which prevented bison.simple from being created on some systems has been fixed. + * Noteworthy changes in release 1.26 ** Bison now uses Automake. @@ -4079,6 +4495,7 @@ GNU Bison NEWS ** Generated parsers should now work even on operating systems which do not provide alloca(). + * Noteworthy changes in release 1.25 (1995-10-16) ** Errors in the input grammar are not fatal; Bison keeps reading @@ -4104,6 +4521,7 @@ the parser engine; a project can now use its own parser engine. The actions go into a separate file called NAME.act, in the form of a switch statement body. + * Noteworthy changes in release 1.23 The user can define YYPARSE_PARAM as the name of an argument to be @@ -4113,72 +4531,69 @@ by casting it to the proper pointer type. Line numbers in output file corrected. + * Noteworthy changes in release 1.22 --help option added. + * Noteworthy changes in release 1.20 Output file does not redefine const for C++. ----- -Copyright (C) 1995-2015, 2018-2020 Free Software Foundation, Inc. - -This file is part of Bison, the GNU Parser Generator. - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see <http://www.gnu.org/licenses/>. - - LocalWords: yacc YYBACKUP glr GCC lalr ArrayIndexOutOfBoundsException nullptr - LocalWords: cplusplus liby rpl fprintf mfcalc Wyacc stmt cond expr mk sym lr - LocalWords: IELR ielr Lookahead YYERROR nonassoc LALR's api lookaheads yychar - LocalWords: destructor lookahead YYRHSLOC YYLLOC Rhs ifndef YYFAIL cpp sr rr - LocalWords: preprocessor initializer Wno Wnone Werror FreeBSD prec livelocks - LocalWords: Solaris AIX UX RHEL Tru LHS gcc's Wundef YYENABLE NLS YYLTYPE VCG - LocalWords: yyerror cpp's Wunused yylval yylloc prepend yyparse yylex yypush - LocalWords: Graphviz xml nonterminals midrule destructor's YYSTYPE typedef ly - LocalWords: CHR chr printf stdout namespace preprocessing enum pre include's - LocalWords: YYRECOVERING nonfree destructors YYABORT YYACCEPT params enums de - LocalWords: struct yystype DJGPP lex param Haible NUM alloca YYSTACK NUL goto - LocalWords: YYMAXDEPTH Unescaped UCNs YYLTYPE's yyltype typedefs inline Yaccs - LocalWords: Heriyanto Reenable dprec Hilfinger Eggert MYEOF Folle Menezes EOF - LocalWords: Lackovic define's itemset Groff Gettext malloc NEWS'ed YYDEBUG YY - LocalWords: namespaces strerror const autoconfiguration Dconst Autoconf's FDL - LocalWords: Automake TMPDIR LESSEQ ylwrap endif yydebug YYTOKEN YYLSP ival hh - LocalWords: extern YYTOKENTYPE TOKENTYPE yytokentype tokentype STYPE lval pdf - LocalWords: lang yyoutput dvi html ps POSIX lvalp llocp Wother nterm arg init - LocalWords: TOK calc yyo fval Wconflicts parsers yystackp yyval yynerrs - LocalWords: Théophile Ranquet Santet fno fnone stype associativity Tolmer - LocalWords: Wprecedence Rassoul Wempty Paolo Bonzini parser's Michiel loc - LocalWords: redeclaration sval fcaret reentrant XSLT xsl Wmaybe yyvsp Tedi - LocalWords: pragmas noreturn untyped Rozenman unexpanded Wojciech Polak - LocalWords: Alexandre MERCHANTABILITY yytype emplace ptr automove lvalues - LocalWords: nonterminal yy args Pragma dereference yyformat rhs docdir bw - LocalWords: Redeclarations rpcalc Autoconf YFLAGS Makefiles PROG DECL num - LocalWords: Heimbigner AST src ast Makefile srcdir MinGW xxlex XXSTYPE - LocalWords: XXLTYPE strictfp IDEs ffixit fdiagnostics parseable fixits - LocalWords: Wdeprecated yytext Variadic variadic yyrhs yyphrs RCS README - LocalWords: noexcept constexpr ispell american deprecations backend Teoh - LocalWords: YYPRINT Mangold Bonzini's Wdangling exVal baz checkable gcc - LocalWords: fsanitize Vogelsgesang lis redeclared stdint automata yytname - LocalWords: yysymbol yytnamerr yyreport ctx ARGMAX yysyntax stderr LPAREN - LocalWords: symrec yypcontext TOKENMAX yyexpected YYEMPTY yypstate YYEOF - LocalWords: autocompletion bistromathic submessages Cayuela lexcalc hoc - LocalWords: yytoken YYUNDEF YYerror +LocalWords: yacc YYBACKUP glr GCC lalr ArrayIndexOutOfBoundsException nullptr +LocalWords: cplusplus liby rpl fprintf mfcalc Wyacc stmt cond expr mk sym lr +LocalWords: IELR ielr Lookahead YYERROR nonassoc LALR's api lookaheads yychar +LocalWords: destructor lookahead YYRHSLOC YYLLOC Rhs ifndef YYFAIL cpp sr rr +LocalWords: preprocessor initializer Wno Wnone Werror FreeBSD prec livelocks +LocalWords: Solaris AIX UX RHEL Tru LHS gcc's Wundef YYENABLE NLS YYLTYPE VCG +LocalWords: yyerror cpp's Wunused yylval yylloc prepend yyparse yylex yypush +LocalWords: Graphviz xml nonterminals midrule destructor's YYSTYPE typedef ly +LocalWords: CHR chr printf stdout namespace preprocessing enum pre include's +LocalWords: YYRECOVERING nonfree destructors YYABORT YYACCEPT params enums de +LocalWords: struct yystype DJGPP lex param Haible NUM alloca YYSTACK NUL goto +LocalWords: YYMAXDEPTH Unescaped UCNs YYLTYPE's yyltype typedefs inline Yaccs +LocalWords: Heriyanto Reenable dprec Hilfinger Eggert MYEOF Folle Menezes EOF +LocalWords: Lackovic define's itemset Groff Gettext malloc NEWS'ed YYDEBUG YY +LocalWords: namespaces strerror const autoconfiguration Dconst Autoconf's FDL +LocalWords: Automake TMPDIR LESSEQ ylwrap endif yydebug YYTOKEN YYLSP ival hh +LocalWords: extern YYTOKENTYPE TOKENTYPE yytokentype tokentype STYPE lval pdf +LocalWords: lang yyoutput dvi html ps POSIX lvalp llocp Wother nterm arg init +LocalWords: TOK calc yyo fval Wconflicts parsers yystackp yyval yynerrs +LocalWords: Théophile Ranquet Santet fno fnone stype associativity Tolmer +LocalWords: Wprecedence Rassoul Wempty Paolo Bonzini parser's Michiel loc +LocalWords: redeclaration sval fcaret reentrant XSLT xsl Wmaybe yyvsp Tedi +LocalWords: pragmas noreturn untyped Rozenman unexpanded Wojciech Polak +LocalWords: Alexandre MERCHANTABILITY yytype emplace ptr automove lvalues +LocalWords: nonterminal yy args Pragma dereference yyformat rhs docdir bw +LocalWords: Redeclarations rpcalc Autoconf YFLAGS Makefiles PROG DECL num +LocalWords: Heimbigner AST src ast Makefile srcdir MinGW xxlex XXSTYPE +LocalWords: XXLTYPE strictfp IDEs ffixit fdiagnostics parseable fixits +LocalWords: Wdeprecated yytext Variadic variadic yyrhs yyphrs RCS README +LocalWords: noexcept constexpr ispell american deprecations backend Teoh +LocalWords: YYPRINT Mangold Bonzini's Wdangling exVal baz checkable gcc +LocalWords: fsanitize Vogelsgesang lis redeclared stdint automata yytname +LocalWords: yysymbol yytnamerr yyreport ctx ARGMAX yysyntax stderr LPAREN +LocalWords: symrec yypcontext TOKENMAX yyexpected YYEMPTY yypstate YYEOF +LocalWords: autocompletion bistromathic submessages Cayuela lexcalc hoc +LocalWords: yytoken YYUNDEF YYerror basename Automake's UTF ifdef ffile +LocalWords: gotos readline Imbimbo Wcounterexamples Wcex Nonunifying rcex Local Variables: ispell-dictionary: "american" mode: outline fill-column: 76 End: + +Copyright (C) 1995-2015, 2018-2021 Free Software Foundation, Inc. + +This file is part of Bison, the GNU Parser Generator. + +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.3 or +any later version published by the Free Software Foundation; with no +Invariant Sections, with no Front-Cover Texts, and with no Back-Cover +Texts. A copy of the license is included in the "GNU Free +Documentation License" file as part of this distribution. diff --git a/contrib/tools/bison/README b/contrib/tools/bison/README index f5748c3c25..9164450ff3 100644 --- a/contrib/tools/bison/README +++ b/contrib/tools/bison/README @@ -17,17 +17,18 @@ GNU Bison's home page is https://gnu.org/software/bison/. # Installation ## Build from git -Here are basic installation instructions for a repository checkout: +The [README-hacking.md file](README-hacking.md) is about building, modifying +and checking Bison. See its "Working from the Repository" section to build +Bison from the git repo. Roughly, run: $ git submodule update --init $ ./bootstrap then proceed with the usual `configure && make` steps. -The file README-hacking.md is about building, modifying and checking Bison. - ## Build from tarball -See the file INSTALL for generic compilation and installation instructions. +See the [INSTALL file](INSTALL) for generic compilation and installation +instructions. Bison requires GNU m4 1.4.6 or later. See https://ftp.gnu.org/gnu/m4/m4-1.4.6.tar.gz. @@ -41,9 +42,11 @@ installing it. In that case, do not use `src/bison`: it would use the As an experimental feature, diagnostics are now colored, controlled by the `--color` and `--style` options. -To use them, install the libtextstyle library before configuring Bison. It -is available from https://alpha.gnu.org/gnu/gettext/, for instance -https://alpha.gnu.org/pub/gnu/gettext/libtextstyle-0.20.5.tar.gz. +To use them, install the libtextstyle library, 0.20.5 or newer, before +configuring Bison. It is available from https://alpha.gnu.org/gnu/gettext/, +for instance https://alpha.gnu.org/gnu/gettext/libtextstyle-0.20.5.tar.gz, +or as part of Gettext 0.21 or newer, for instance +https://ftp.gnu.org/gnu/gettext/gettext-0.21.tar.gz. The option --color supports the following arguments: - always, yes: Enable colors. @@ -60,6 +63,13 @@ To customize the styles, create a CSS file, say `bison-bw.css`, similar to then invoke bison with `--style=bison-bw.css`, or set the `BISON_STYLE` environment variable to `bison-bw.css`. +In some diagnostics, bison uses libtextstyle to emit special escapes to +generate clickable hyperlinks. The environment variable +`NO_TERM_HYPERLINKS` can be used to suppress them. This may be useful for +terminal emulators which produce garbage output when they receive the escape +sequence for a hyperlink. Currently (as of 2020), this affects some versions +of emacs, guake, konsole, lxterminal, rxvt, yakuake. + ## Relocatability If you pass `--enable-relocatable` to `configure`, Bison is relocatable. @@ -77,7 +87,7 @@ for the user-side parser execution). The requirements between both differ: bison needs ngettext, the generated parsers do not. To simplify the build system, neither are installed if ngettext is not supported, even if generated parsers could have been localized. See -http://lists.gnu.org/archive/html/bug-bison/2009-08/msg00006.html for more +https://lists.gnu.org/r/bug-bison/2009-08/msg00006.html for more details. # Questions @@ -100,7 +110,17 @@ that the range specifies every single year in that closed interval. <!-- -Copyright (C) 1992, 1998-1999, 2003-2005, 2008-2015, 2018-2020 Free +LocalWords: parsers ngettext Texinfo pdf html YYYY ZZZZ ispell american md +LocalWords: MERCHANTABILITY GLR LALR IELR submodule init README src bw +LocalWords: Relocatability symlinks symlink + +Local Variables: +mode: markdown +fill-column: 76 +ispell-dictionary: "american" +End: + +Copyright (C) 1992, 1998-1999, 2003-2005, 2008-2015, 2018-2021 Free Software Foundation, Inc. This file is part of GNU bison, the GNU Compiler Compiler. @@ -112,14 +132,4 @@ Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the "GNU Free Documentation License" file as part of this distribution. -Local Variables: -mode: markdown -fill-column: 76 -ispell-dictionary: "american" -End: - -LocalWords: parsers ngettext Texinfo pdf html YYYY ZZZZ ispell american md -LocalWords: MERCHANTABILITY GLR LALR IELR submodule init README src bw -LocalWords: Relocatability symlinks symlink - --> diff --git a/contrib/tools/bison/README-alpha b/contrib/tools/bison/README-alpha index dbd0e88e20..da7d2648af 100644 --- a/contrib/tools/bison/README-alpha +++ b/contrib/tools/bison/README-alpha @@ -12,7 +12,7 @@ the problems you encounter. ----- -Copyright (C) 2002, 2004, 2009-2015, 2018-2020 Free Software Foundation, +Copyright (C) 2002, 2004, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of GNU Bison. @@ -28,4 +28,4 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with this program. If not, see <http://www.gnu.org/licenses/>. +along with this program. If not, see <https://www.gnu.org/licenses/>. diff --git a/contrib/tools/bison/data/README.md b/contrib/tools/bison/data/README.md index 5d32b75f1a..c1172d1abb 100644 --- a/contrib/tools/bison/data/README.md +++ b/contrib/tools/bison/data/README.md @@ -1,6 +1,6 @@ This directory contains data needed by Bison. -# Directory content +# Directory Content ## Skeletons Bison skeletons: the general shapes of the different parser kinds, that are specialized for specific grammars by the bison program. @@ -48,7 +48,7 @@ various formats. - xml2xhtml.xsl Conversion into XHTML. -# Implementation note about the skeletons +# Implementation Notes About the Skeletons "Skeleton" in Bison parlance means "backend": a skeleton is fed by the bison executable with LR tables, facts about the symbols, etc. and they generate @@ -84,29 +84,35 @@ field), where field can `has_id`, `id`, etc.: see The macro `b4_symbol(NUM, FIELD)` gives access to the following FIELDS: - `has_id`: 0 or 1 - Whether the symbol has an id. + Whether the symbol has an `id`. -- `id`: string - If has_id, the id (prefixed by api.token.prefix if defined), otherwise - defined as empty. Guaranteed to be usable as a C identifier. This is - used to define the token kind (i.e., the enum used by the return value of - yylex). +- `id`: string (e.g., `exp`, `NUM`, or `TOK_NUM` with api.token.prefix) + If `has_id`, the name of the token kind (prefixed by api.token.prefix if + defined), otherwise empty. Guaranteed to be usable as a C identifier. + This is used to define the token kind (i.e., the enum used by the return + value of yylex). Should be named `token_kind`. - `tag`: string - A human representation of the symbol. Can be 'foo', 'foo.id', '"foo"' etc. + A human readable representation of the symbol. Can be `'foo'`, + `'foo.id'`, `'"foo"'` etc. -- `user_number`: integer - The code associated to the `id`. +- `code`: integer + The token code associated to the token kind `id`. The external number as used by yylex. Can be ASCII code when a character, - some number chosen by bison, or some user number in the case of - %token FOO <NUM>. Corresponds to yychar in yacc.c. + some number chosen by bison, or some user number in the case of `%token + FOO <NUM>`. Corresponds to `yychar` in `yacc.c`. - `is_token`: 0 or 1 Whether this is a terminal symbol. +- `kind_base`: string (e.g., `YYSYMBOL_exp`, `YYSYMBOL_NUM`) + The base of the symbol kind, i.e., the enumerator of this symbol (token or + nonterminal) which is mapped to its `number`. + - `kind`: string - The symbol kind, i.e., the enumerator of this symbol (token or nonterminal) - which is mapping to its `number`. + Same as `kind_base`, but possibly with a prefix in some languages. E.g., + EOF's `kind_base` and `kind` are `YYSYMBOL_YYEOF` in C, but are + `S_YYEMPTY` and `symbol_kind::S_YYEMPTY` in C++. - `number`: integer The code associated to the `kind`. @@ -136,11 +142,17 @@ The macro `b4_symbol(NUM, FIELD)` gives access to the following FIELDS: When api.value.type=union, the generated name for the union member. yytype_INT etc. for symbols that has_id, otherwise yytype_1 etc. -- `type` +- `type`: string If it has a semantic value, its type tag, or, if variant are used, its type. In the case of api.value.type=union, type is the real type (e.g. int). +- `slot`: string + If it has a semantic value, the name of the union member (i.e., bounces to + either `type_tag` or `type`). It would be better to fix our mess and + always use `type` for the true type of the member, and `type_tag` for the + name of the union member. + - `has_printer`: 0, 1 - `printer`: string - `printer_file`: string @@ -173,7 +185,7 @@ The data corresponding to the symbol `#POS`, where the current rule has Expansion of `$<TYPE>POS`, where the current rule has `RULE-LENGTH` symbols on RHS. ------ +<!-- Local Variables: mode: markdown @@ -181,7 +193,7 @@ fill-column: 76 ispell-dictionary: "american" End: -Copyright (C) 2002, 2008-2015, 2018-2020 Free Software Foundation, Inc. +Copyright (C) 2002, 2008-2015, 2018-2021 Free Software Foundation, Inc. This file is part of GNU Bison. @@ -196,4 +208,6 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with this program. If not, see <http://www.gnu.org/licenses/>. +along with this program. If not, see <https://www.gnu.org/licenses/>. + +--> diff --git a/contrib/tools/bison/data/m4sugar/foreach.m4 b/contrib/tools/bison/data/m4sugar/foreach.m4 index 7093d0fcc4..2052d44c2a 100644 --- a/contrib/tools/bison/data/m4sugar/foreach.m4 +++ b/contrib/tools/bison/data/m4sugar/foreach.m4 @@ -4,7 +4,7 @@ # Speeds up GNU M4 1.4.x by avoiding quadratic $@ recursion, but penalizes # GNU M4 1.6 by requiring more memory and macro expansions. # -# Copyright (C) 2008-2017 Free Software Foundation, Inc. +# Copyright (C) 2008-2017, 2020 Free Software Foundation, Inc. # This file is part of Autoconf. This program is free # software; you can redistribute it and/or modify it under the diff --git a/contrib/tools/bison/data/m4sugar/m4sugar.m4 b/contrib/tools/bison/data/m4sugar/m4sugar.m4 index bbd695836a..b42fc1a6de 100644 --- a/contrib/tools/bison/data/m4sugar/m4sugar.m4 +++ b/contrib/tools/bison/data/m4sugar/m4sugar.m4 @@ -3,7 +3,7 @@ divert(-1)# -*- Autoconf -*- # Base M4 layer. # Requires GNU M4. # -# Copyright (C) 1999-2017 Free Software Foundation, Inc. +# Copyright (C) 1999-2017, 2020 Free Software Foundation, Inc. # This file is part of Autoconf. This program is free # software; you can redistribute it and/or modify it under the @@ -2412,6 +2412,27 @@ m4_define([m4_normalize], [m4_strip(m4_flatten([$1]))]) +# m4_validate_w(STRING) +# --------------------- +# Expands into m4_normalize(m4_expand([STRING])), but if that is not +# the same as just m4_normalize([STRING]), issue a warning. +# +# This is used in several Autoconf macros that take a +# whitespace-separated list of symbols as an argument. Ideally that +# list would not be expanded before use, but several packages used +# `dnl' to put comments inside those lists, so they must be expanded +# for compatibility's sake. +m4_define([m4_validate_w], +[_m4_validate_w(m4_normalize([$1]), m4_normalize(m4_expand([$1])))]) + +m4_define([_m4_validate_w], +[m4_if([$1], [$2], [], + [m4_warn([obsolete], [whitespace-separated list contains macros; +in a future version of Autoconf they will not be expanded]dnl +m4_if(m4_bregexp([$1], [\bdn[l]\b]), -1, [], [ +note: `dn@&t@l' is a macro]))])dnl +[$2]]) + # m4_join(SEP, ARG1, ARG2...) # --------------------------- diff --git a/contrib/tools/bison/data/skeletons/bison.m4 b/contrib/tools/bison/data/skeletons/bison.m4 index 637d2fcbf2..12946c6917 100644 --- a/contrib/tools/bison/data/skeletons/bison.m4 +++ b/contrib/tools/bison/data/skeletons/bison.m4 @@ -2,7 +2,7 @@ # Language-independent M4 Macros for Bison. -# Copyright (C) 2002, 2004-2015, 2018-2020 Free Software Foundation, +# Copyright (C) 2002, 2004-2015, 2018-2021 Free Software Foundation, # Inc. # This program is free software: you can redistribute it and/or modify @@ -16,7 +16,7 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# along with this program. If not, see <https://www.gnu.org/licenses/>. @@ -38,6 +38,8 @@ m4_define([b4_gsub], [$4], [$5]), [$6], [$7])]) +# m4_shift2 and m4_shift3 are provided by m4sugar. +m4_define([m4_shift4], [m4_shift(m4_shift(m4_shift(m4_shift($@))))]) ## ---------------- ## @@ -47,7 +49,7 @@ m4_define([b4_gsub], # b4_generated_by # --------------- m4_define([b4_generated_by], -[b4_comment([A Bison parser, made by GNU Bison b4_version.]) +[b4_comment([A Bison parser, made by GNU Bison b4_version_string.]) ]) # b4_copyright(TITLE, [YEARS]) @@ -72,7 +74,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with this program. If not, see <http://www.gnu.org/licenses/>.]) +along with this program. If not, see <https://www.gnu.org/licenses/>.]) b4_comment([As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -183,7 +185,7 @@ m4_define([b4_error], [b4_cat([[@complain][(]$1[@,]$2[@,]$3[@,]$4[]]dnl [m4_if([$#], [4], [], [m4_foreach([b4_arg], - m4_dquote(m4_shift(m4_shift(m4_shift(m4_shift($@))))), + m4_dquote(m4_shift4($@)), [[@,]b4_arg])])[@)]])]) # b4_warn(FORMAT, [ARG1], [ARG2], ...) @@ -436,14 +438,14 @@ m4_define([b4_symbol_token_kind], _b4_symbol([$1], [id])]) -# b4_symbol_kind(NUM) -# ------------------- +# b4_symbol_kind_base(NUM) +# ------------------------ # Build the name of the kind of this symbol. It must always exist, # otherwise some symbols might not be represented in the enum, which # might be compiled into too small a type to contain all the symbol # numbers. m4_define([b4_symbol_prefix], [b4_percent_define_get([api.symbol.prefix])]) -m4_define([b4_symbol_kind], +m4_define([b4_symbol_kind_base], [b4_percent_define_get([api.symbol.prefix])dnl m4_case([$1], [-2], [[YYEMPTY]], @@ -456,6 +458,26 @@ m4_case([$1], [m4_bpatsubst([$1-][]_b4_symbol([$1], [tag]), [[^a-zA-Z_0-9]+], [_])])])])]) +# b4_symbol_kind(NUM) +# ------------------- +# Same as b4_symbol_kind, but possibly with a prefix in some +# languages. E.g., EOF's kind_base and kind are YYSYMBOL_YYEOF in C, +# but are S_YYEMPTY and symbol_kind::S_YYEMPTY in C++. +m4_copy([b4_symbol_kind_base], [b4_symbol_kind]) + + +# b4_symbol_slot(NUM) +# ------------------- +# The name of union member that contains the value of these symbols. +# Currently, we are messy, this should actually be type_tag, but type_tag +# has several meanings. +m4_define([b4_symbol_slot], +[m4_case(b4_percent_define_get([[api.value.type]]), + [union], [b4_symbol([$1], [type_tag])], + [variant], [b4_symbol([$1], [type_tag])], + [b4_symbol([$1], [type])])]) + + # b4_symbol(NUM, FIELD) # --------------------- # Fetch FIELD of symbol #NUM (or "orig NUM"). Fail if undefined. @@ -463,8 +485,10 @@ m4_case([$1], # If FIELD = id, prepend the token prefix. m4_define([b4_symbol], [m4_case([$2], - [id], [b4_symbol_token_kind([$1])], - [kind], [b4_symbol_kind([$1])], + [id], [b4_symbol_token_kind([$1])], + [kind_base], [b4_symbol_kind_base([$1])], + [kind], [b4_symbol_kind([$1])], + [slot], [b4_symbol_slot([$1])], [_b4_symbol($@)])]) @@ -527,7 +551,7 @@ m4_defn([b4_actions_])[]dnl break; }dnl ], -[YYUSE (m4_default([$2], [yykind]));])dnl +[YY_USE (m4_default([$2], [yykind]));])dnl m4_popdef([b4_actions_])dnl ]) @@ -537,7 +561,7 @@ m4_popdef([b4_actions_])dnl # easier to use with m4_map, but then, use []dnl to suppress the last # one. m4_define([_b4_symbol_case], -[case b4_symbol([$1], [number]): b4_symbol_tag_comment([$1])]) +[case b4_symbol([$1], [kind]): b4_symbol_tag_comment([$1])]) ]) @@ -585,8 +609,8 @@ m4_define([b4_any_token_visible_if], m4_define([b4_token_format], [b4_token_visible_if([$2], [m4_format([[$1]], - m4_expand(b4_symbol([$2], [id])), - m4_expand(b4_symbol([$2], b4_api_token_raw_if([[number]], [[user_number]]))))])]) + b4_symbol([$2], [id]), + b4_symbol([$2], b4_api_token_raw_if([[number]], [[code]])))])]) # b4_last_enum_token @@ -623,11 +647,11 @@ m4_define([_b4_type_action], ])]) -# b4_type_foreach(MACRO) -# ---------------------- +# b4_type_foreach(MACRO, [SEP]) +# ----------------------------- # Invoke MACRO(SYMBOL-NUMS) for each set of SYMBOL-NUMS for each type set. m4_define([b4_type_foreach], - [m4_map([$1], m4_defn([b4_type_names]))]) + [m4_map_sep([$1], [$2], m4_defn([b4_type_names]))]) @@ -748,7 +772,7 @@ m4_define([b4_check_user_names], [m4_pushdef([b4_occurrence], b4_occurrence)dnl m4_pushdef([b4_user_name], m4_car(b4_occurrence))dnl m4_pushdef([b4_start], m4_car(m4_shift(b4_occurrence)))dnl -m4_pushdef([b4_end], m4_shift(m4_shift(b4_occurrence)))dnl +m4_pushdef([b4_end], m4_shift2(b4_occurrence))dnl m4_ifndef($3[(]m4_quote(b4_user_name)[)], [b4_complain_at([b4_start], [b4_end], [[%s '%s' is not used]], diff --git a/contrib/tools/bison/data/skeletons/c++-skel.m4 b/contrib/tools/bison/data/skeletons/c++-skel.m4 index 6d3becf5e6..f22002b961 100644 --- a/contrib/tools/bison/data/skeletons/c++-skel.m4 +++ b/contrib/tools/bison/data/skeletons/c++-skel.m4 @@ -2,7 +2,7 @@ # C++ skeleton dispatching for Bison. -# Copyright (C) 2006-2007, 2009-2015, 2018-2020 Free Software +# Copyright (C) 2006-2007, 2009-2015, 2018-2021 Free Software # Foundation, Inc. # This program is free software: you can redistribute it and/or modify @@ -16,7 +16,7 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# along with this program. If not, see <https://www.gnu.org/licenses/>. b4_glr_if( [m4_define([b4_used_skeleton], [b4_skeletonsdir/[glr.cc]])]) b4_nondeterministic_if([m4_define([b4_used_skeleton], [b4_skeletonsdir/[glr.cc]])]) diff --git a/contrib/tools/bison/data/skeletons/c++.m4 b/contrib/tools/bison/data/skeletons/c++.m4 index b862bf3ca7..2d1e90d0f4 100644 --- a/contrib/tools/bison/data/skeletons/c++.m4 +++ b/contrib/tools/bison/data/skeletons/c++.m4 @@ -2,7 +2,7 @@ # C++ skeleton for Bison -# Copyright (C) 2002-2020 Free Software Foundation, Inc. +# Copyright (C) 2002-2021 Free Software Foundation, Inc. # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -15,7 +15,7 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# along with this program. If not, see <https://www.gnu.org/licenses/>. # Sanity checks, before defaults installed by c.m4. b4_percent_define_ifdef([[api.value.union.name]], @@ -105,7 +105,7 @@ b4_percent_define_default([[api.parser.class]], [[parser]]) # # b4_percent_define_default([[api.location.type]], [[location]]) -b4_percent_define_default([[filename_type]], [[std::string]]) +b4_percent_define_default([[api.filename.type]], [[const std::string]]) # Make it a warning for those who used betas of Bison 3.0. b4_percent_define_default([[api.namespace]], m4_defn([b4_prefix])) @@ -193,7 +193,7 @@ m4_define([b4_declare_symbol_enum], [[enum symbol_kind_type { YYNTOKENS = ]b4_tokens_number[, ///< Number of tokens. - ]b4_symbol_kind([-2])[ = -2, + ]b4_symbol(-2, kind_base)[ = -2, ]b4_symbol_foreach([ b4_symbol_enum])dnl [ };]]) @@ -321,8 +321,9 @@ m4_define([b4_symbol_type_define], /// Copy constructor. basic_symbol (const basic_symbol& that);]b4_variant_if([[ - /// Constructor for valueless symbols, and symbols from each type. -]b4_type_foreach([b4_basic_symbol_constructor_define])], [[ + /// Constructors for typed symbols. +]b4_type_foreach([b4_basic_symbol_constructor_define], [ +])], [[ /// Constructor for valueless symbols. basic_symbol (typename Base::kind_type t]b4_locations_if([, YY_MOVE_REF (location_type) l])[); @@ -339,7 +340,7 @@ m4_define([b4_symbol_type_define], } /// Destroy contents, and record that is empty. - void clear () + void clear () YY_NOEXCEPT {]b4_variant_if([[ // User destructor. symbol_kind_type yykind = this->kind (); @@ -423,7 +424,7 @@ m4_define([b4_symbol_type_define], by_kind (kind_type t); /// Record that this symbol is empty. - void clear (); + void clear () YY_NOEXCEPT; /// Steal the symbol kind from \a that. void move (by_kind& that); @@ -507,7 +508,7 @@ m4_define([b4_public_types_define], bool ]b4_parser_class[::basic_symbol<Base>::empty () const YY_NOEXCEPT { - return this->kind () == symbol_kind::]b4_symbol_prefix[YYEMPTY; + return this->kind () == ]b4_symbol(-2, kind)[; } template <typename Base> @@ -523,7 +524,7 @@ m4_define([b4_public_types_define], // by_kind. ]b4_inline([$1])b4_parser_class[::by_kind::by_kind () - : kind_ (symbol_kind::]b4_symbol_prefix[YYEMPTY) + : kind_ (]b4_symbol(-2, kind)[) {} #if 201103L <= YY_CPLUSPLUS @@ -543,9 +544,9 @@ m4_define([b4_public_types_define], {} ]b4_inline([$1])[void - ]b4_parser_class[::by_kind::clear () + ]b4_parser_class[::by_kind::clear () YY_NOEXCEPT { - kind_ = symbol_kind::]b4_symbol_prefix[YYEMPTY; + kind_ = ]b4_symbol(-2, kind)[; } ]b4_inline([$1])[void @@ -594,11 +595,12 @@ m4_define([b4_yytranslate_define], { ]b4_translate[ }; - const int user_token_number_max_ = ]b4_user_token_number_max[; + // Last valid token kind. + const int code_max = ]b4_code_max[; if (t <= 0) return symbol_kind::]b4_symbol_prefix[YYEOF; - else if (t <= user_token_number_max_) + else if (t <= code_max) return YY_CAST (symbol_kind_type, translate_table[t]); else return symbol_kind::]b4_symbol_prefix[YYUNDEF;]])[ diff --git a/contrib/tools/bison/data/skeletons/c-like.m4 b/contrib/tools/bison/data/skeletons/c-like.m4 index 1e5ab02c8a..a9bbc2e86e 100644 --- a/contrib/tools/bison/data/skeletons/c-like.m4 +++ b/contrib/tools/bison/data/skeletons/c-like.m4 @@ -2,7 +2,7 @@ # Common code for C-like languages (C, C++, Java, etc.) -# Copyright (C) 2012-2015, 2018-2020 Free Software Foundation, Inc. +# Copyright (C) 2012-2015, 2018-2021 Free Software Foundation, Inc. # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -15,7 +15,7 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# along with this program. If not, see <https://www.gnu.org/licenses/>. # _b4_comment(TEXT, OPEN, CONTINUE, END) diff --git a/contrib/tools/bison/data/skeletons/c-skel.m4 b/contrib/tools/bison/data/skeletons/c-skel.m4 index 68d057cb74..ac6ddd687c 100644 --- a/contrib/tools/bison/data/skeletons/c-skel.m4 +++ b/contrib/tools/bison/data/skeletons/c-skel.m4 @@ -2,7 +2,7 @@ # C skeleton dispatching for Bison. -# Copyright (C) 2006-2007, 2009-2015, 2018-2020 Free Software +# Copyright (C) 2006-2007, 2009-2015, 2018-2021 Free Software # Foundation, Inc. # This program is free software: you can redistribute it and/or modify @@ -16,7 +16,7 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# along with this program. If not, see <https://www.gnu.org/licenses/>. b4_glr_if( [m4_define([b4_used_skeleton], [b4_skeletonsdir/[glr.c]])]) b4_nondeterministic_if([m4_define([b4_used_skeleton], [b4_skeletonsdir/[glr.c]])]) diff --git a/contrib/tools/bison/data/skeletons/c.m4 b/contrib/tools/bison/data/skeletons/c.m4 index 3c6daef23a..f95fc88cdf 100644 --- a/contrib/tools/bison/data/skeletons/c.m4 +++ b/contrib/tools/bison/data/skeletons/c.m4 @@ -2,7 +2,7 @@ # C M4 Macros for Bison. -# Copyright (C) 2002, 2004-2015, 2018-2020 Free Software Foundation, +# Copyright (C) 2002, 2004-2015, 2018-2021 Free Software Foundation, # Inc. # This program is free software: you can redistribute it and/or modify @@ -16,7 +16,7 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# along with this program. If not, see <https://www.gnu.org/licenses/>. m4_include(b4_skeletonsdir/[c-like.m4]) @@ -58,11 +58,11 @@ m4_define([b4_cpp_guard_close], # b4_pull_flag if they use the values of the %define variables api.pure or # api.push-pull. m4_define([b4_identification], -[[/* Identify Bison output. */ -#define YYBISON 1 +[[/* Identify Bison output, and Bison version. */ +#define YYBISON ]b4_version[ -/* Bison version. */ -#define YYBISON_VERSION "]b4_version[" +/* Bison version string. */ +#define YYBISON_VERSION "]b4_version_string[" /* Skeleton name. */ #define YYSKELETON_NAME ]b4_skeleton[]m4_ifdef([b4_pure_flag], [[ @@ -160,11 +160,11 @@ m4_popdef([$1])dnl # b4_parse_param_use([VAL], [LOC]) # -------------------------------- -# 'YYUSE' VAL, LOC if locations are enabled, and all the parse-params. +# 'YY_USE' VAL, LOC if locations are enabled, and all the parse-params. m4_define([b4_parse_param_use], -[m4_ifvaln([$1], [ YYUSE ([$1]);])dnl -b4_locations_if([m4_ifvaln([$2], [ YYUSE ([$2]);])])dnl -b4_parse_param_for([Decl], [Formal], [ YYUSE (Formal); +[m4_ifvaln([$1], [ YY_USE ([$1]);])dnl +b4_locations_if([m4_ifvaln([$2], [ YY_USE ([$2]);])])dnl +b4_parse_param_for([Decl], [Formal], [ YY_USE (Formal); ])dnl ]) @@ -242,6 +242,18 @@ typedef int_least16_t yytype_int16; typedef short yytype_int16; #endif +/* Work around bug in HP-UX 11.23, which defines these macros + incorrectly for preprocessor constants. This workaround can likely + be removed in 2023, as HPE has promised support for HP-UX 11.23 + (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of + <https://h20195.www2.hpe.com/V2/getpdf.aspx/4AA4-7673ENW.pdf>. */ +#ifdef __hpux +# undef UINT_LEAST8_MAX +# undef UINT_LEAST16_MAX +# define UINT_LEAST8_MAX 255 +# define UINT_LEAST16_MAX 65535 +#endif + #if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ typedef __UINT_LEAST8_TYPE__ yytype_uint8; #elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \ @@ -355,17 +367,27 @@ m4_define([b4_attribute_define], #endif ]m4_bmatch([$1], [\bnoreturn\b], [[/* The _Noreturn keyword of C11. */ -]dnl This is an exact copy of lib/_Noreturn.h. +]dnl This is close to lib/_Noreturn.h, except that we do enable +dnl the use of [[noreturn]], because _Noreturn is used in places +dnl where [[noreturn]] works in C++. We need this in particular +dnl because of glr.cc which compiles code from glr.c in C++. +dnl And the C++ compiler chokes on _Noreturn. Also, we do not +dnl use C' _Noreturn in C++, to avoid -Wc11-extensions warnings. [#ifndef _Noreturn # if (defined __cplusplus \ && ((201103 <= __cplusplus && !(__GNUC__ == 4 && __GNUC_MINOR__ == 7)) \ || (defined _MSC_VER && 1900 <= _MSC_VER))) # define _Noreturn [[noreturn]] # elif ((!defined __cplusplus || defined __clang__) \ - && (201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) \ - || 4 < __GNUC__ + (7 <= __GNUC_MINOR__))) + && (201112 <= (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) \ + || (!defined __STRICT_ANSI__ \ + && (__4 < __GNUC__ + (7 <= __GNUC_MINOR__) \ + || (defined __apple_build_version__ \ + ? 6000000 <= __apple_build_version__ \ + : 3 < __clang_major__ + (5 <= __clang_minor__)))))) /* _Noreturn works as-is. */ -# elif 2 < __GNUC__ + (8 <= __GNUC_MINOR__) || 0x5110 <= __SUNPRO_C +# elif (2 < __GNUC__ + (8 <= __GNUC_MINOR__) || defined __clang__ \ + || 0x5110 <= __SUNPRO_C) # define _Noreturn __attribute__ ((__noreturn__)) # elif 1200 <= (defined _MSC_VER ? _MSC_VER : 0) # define _Noreturn __declspec (noreturn) @@ -376,9 +398,9 @@ m4_define([b4_attribute_define], ]])[/* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ -# define YYUSE(E) ((void) (E)) +# define YY_USE(E) ((void) (E)) #else -# define YYUSE(E) /* empty */ +# define YY_USE(E) /* empty */ #endif #if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ @@ -501,10 +523,11 @@ m4_define([b4_token_define], # ---------------- # Output the definition of the tokens. m4_define([b4_token_defines], -[b4_any_token_visible_if([/* Token kinds. */ -m4_join([ +[[/* Token kinds. */ +#define ]b4_symbol([-2], [id])[ -2 +]m4_join([ ], b4_symbol_map([b4_token_define])) -])]) +]) # b4_token_enum(TOKEN-NUM) @@ -515,7 +538,7 @@ m4_define([b4_token_enum], [m4_format([ %-30s %s], m4_format([[%s = %s%s%s]], b4_symbol([$1], [id]), - b4_symbol([$1], b4_api_token_raw_if([[number]], [[user_number]])), + b4_symbol([$1], b4_api_token_raw_if([[number]], [[code]])), m4_if([$1], b4_last_enum_token, [], [[,]])), [b4_symbol_tag_comment([$1])])])]) @@ -564,7 +587,7 @@ m4_define([b4_symbol_translate], m4_define([b4_symbol_enum], [m4_format([ %-40s %s], m4_format([[%s = %s%s%s]], - b4_symbol([$1], [kind]), + b4_symbol([$1], [kind_base]), [$1], m4_if([$1], b4_last_symbol, [], [[,]])), [b4_symbol_tag_comment([$1])])]) @@ -579,7 +602,7 @@ m4_define([b4_declare_symbol_enum], [[/* Symbol kind. */ enum yysymbol_kind_t { - ]b4_symbol_kind([-2])[ = -2, + ]b4_symbol([-2], kind_base)[ = -2, ]b4_symbol_foreach([b4_symbol_enum])dnl [}; typedef enum yysymbol_kind_t yysymbol_kind_t; @@ -658,10 +681,10 @@ m4_define([b4_sync_start], [[#]line $1 $2]) ## User actions. ## ## -------------- ## -# b4_case(LABEL, STATEMENTS) -# -------------------------- +# b4_case(LABEL, STATEMENTS, [COMMENTS]) +# -------------------------------------- m4_define([b4_case], -[ case $1: +[ case $1:m4_ifval([$3], [ b4_comment([$3])]) $2 b4_syncline([@oline@], [@ofile@])dnl break;]) diff --git a/contrib/tools/bison/data/skeletons/glr.cc b/contrib/tools/bison/data/skeletons/glr.cc index 658b9f20ca..ff23cdc5ff 100644 --- a/contrib/tools/bison/data/skeletons/glr.cc +++ b/contrib/tools/bison/data/skeletons/glr.cc @@ -1,6 +1,6 @@ # C++ GLR skeleton for Bison -# Copyright (C) 2002-2015, 2018-2020 Free Software Foundation, Inc. +# Copyright (C) 2002-2015, 2018-2021 Free Software Foundation, Inc. # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# along with this program. If not, see <https://www.gnu.org/licenses/>. # This skeleton produces a C++ class that encapsulates a C glr parser. @@ -66,12 +66,6 @@ m4_defn([b4_parse_param]))], [[b4_namespace_ref::b4_parser_class[& yyparser], [[yyparser]]]]) ]) -# b4_declare_symbol_enum -# ---------------------- -m4_append([b4_declare_symbol_enum], -[[typedef symbol_kind_type yysymbol_kind_t; -]]) - # b4_yy_symbol_print_define # ------------------------- @@ -105,9 +99,9 @@ yyerror (]b4_locations_if([[const ]b4_namespace_ref::b4_parser_class[::location_ ]])[]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param), ])[const char* msg);]])[ -# Hijack the epilogue to define implementations (yyerror, parser member +# Inserted before the epilogue to define implementations (yyerror, parser member # functions etc.). -]m4_append([b4_epilogue], +]m4_define([b4_glr_cc_pre_epilogue], [b4_syncline([@oline@], [@ofile@])dnl [ /*------------------. @@ -150,7 +144,7 @@ m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_orig]))dnl int ]b4_parser_class[::parse () { - return ::yyparse (*this]b4_user_args[); + return ::yy_parse_impl (*this]b4_user_args[); } #if ]b4_api_PREFIX[DEBUG @@ -163,11 +157,11 @@ m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_orig]))dnl const semantic_type* yyvaluep]b4_locations_if([[, const location_type* yylocationp]])[) const {]b4_locations_if([[ - YYUSE (yylocationp);]])[ - YYUSE (yyvaluep); + YY_USE (yylocationp);]])[ + YY_USE (yyvaluep); std::ostream& yyo = debug_stream (); std::ostream& yyoutput = yyo; - YYUSE (yyoutput); + YY_USE (yyoutput); ]b4_symbol_actions([printer])[ } @@ -178,7 +172,7 @@ m4_pushdef([b4_parse_param], m4_defn([b4_parse_param_orig]))dnl const location_type* yylocationp]])[) const { *yycdebug_ << (yykind < YYNTOKENS ? "token" : "nterm") - << ' ' << yytname[yykind] << " ("]b4_locations_if([[ + << ' ' << yysymbol_name (yykind) << " ("]b4_locations_if([[ << *yylocationp << ": "]])[; yy_symbol_value_print_ (yykind, yyvaluep]b4_locations_if([[, yylocationp]])[); *yycdebug_ << ')'; @@ -216,6 +210,12 @@ b4_namespace_close[]dnl ]) +m4_define([b4_define_symbol_kind], +[m4_format([#define %-15s %s], + b4_symbol($][1, kind_base), + b4_namespace_ref[::]b4_parser_class[::symbol_kind::]b4_symbol($1, kind_base)) +]) + # b4_glr_cc_setup # --------------- # Setup redirections for glr.c: Map the names used in c.m4 to the ones used @@ -236,10 +236,15 @@ m4_define([b4_glr_cc_setup], #endif typedef ]b4_namespace_ref[::]b4_parser_class[::symbol_kind_type yysymbol_kind_t; -#define ]b4_symbol_prefix[YYEMPTY ]b4_namespace_ref[::]b4_parser_class[::symbol_kind::]b4_symbol_prefix[YYEMPTY -#define ]b4_symbol_prefix[YYerror ]b4_namespace_ref[::]b4_parser_class[::symbol_kind::]b4_symbol_prefix[YYerror -#define ]b4_symbol_prefix[YYEOF ]b4_namespace_ref[::]b4_parser_class[::symbol_kind::]b4_symbol_prefix[YYEOF -#define ]b4_symbol_prefix[YYUNDEF ]b4_namespace_ref[::]b4_parser_class[::symbol_kind::]b4_symbol_prefix[YYUNDEF + +// Expose C++ symbol kinds to C. +]b4_define_symbol_kind(-2)dnl +b4_symbol_foreach([b4_define_symbol_kind])])[ +]]) + + +m4_define([b4_undef_symbol_kind], +[[#undef ]b4_symbol($1, kind_base)[ ]]) @@ -247,20 +252,13 @@ typedef ]b4_namespace_ref[::]b4_parser_class[::symbol_kind_type yysymbol_kind_t; # ----------------- # Remove redirections for glr.c. m4_define([b4_glr_cc_cleanup], -[b4_percent_define_flag_if([[global_tokens_and_yystype]], [], [[#undef ]b4_symbol(-2, [id])[ #undef ]b4_symbol(0, [id])[ #undef ]b4_symbol(1, [id])[ -]])[ - -#undef ]b4_api_PREFIX[STYPE -#undef ]b4_api_PREFIX[LTYPE -#undef ]b4_symbol_prefix[YYEMPTY -#undef ]b4_symbol_prefix[YYerror -#undef ]b4_symbol_prefix[YYEOF -#undef ]b4_symbol_prefix[YYUNDEF -]]) +]b4_undef_symbol_kind(-2)dnl +b4_symbol_foreach([b4_undef_symbol_kind])dnl +]) # b4_shared_declarations(hh|cc) @@ -374,10 +372,6 @@ b4_percent_code_get([[requires]])[ ]b4_parse_param_vars[ }; -]dnl Redirections for glr.c. -b4_percent_define_flag_if([[global_tokens_and_yystype]], -[b4_token_defines -])[ ]b4_namespace_close[ ]b4_percent_code_get([[provides]])[ @@ -387,13 +381,13 @@ b4_percent_define_flag_if([[global_tokens_and_yystype]], ]b4_defines_if( [b4_output_begin([b4_spec_header_file]) b4_copyright([Skeleton interface for Bison GLR parsers in C++], - [2002-2015, 2018-2020])[ + [2002-2015, 2018-2021])[ // C++ GLR parser skeleton written by Akim Demaille. ]b4_disclaimer[ -]b4_cpp_guard_open([b4_spec_header_file])[ +]b4_cpp_guard_open([b4_spec_mapped_header_file])[ ]b4_shared_declarations[ -]b4_cpp_guard_close([b4_spec_header_file])[ +]b4_cpp_guard_close([b4_spec_mapped_header_file])[ ]b4_output_end]) # Let glr.c (and b4_shared_declarations) believe that the user diff --git a/contrib/tools/bison/data/skeletons/lalr1.cc b/contrib/tools/bison/data/skeletons/lalr1.cc index dfffb74b8e..cc8113e2a0 100644 --- a/contrib/tools/bison/data/skeletons/lalr1.cc +++ b/contrib/tools/bison/data/skeletons/lalr1.cc @@ -1,6 +1,6 @@ # C++ skeleton for Bison -# Copyright (C) 2002-2015, 2018-2020 Free Software Foundation, Inc. +# Copyright (C) 2002-2015, 2018-2021 Free Software Foundation, Inc. # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# along with this program. If not, see <https://www.gnu.org/licenses/>. m4_include(b4_skeletonsdir/[c++.m4]) @@ -59,6 +59,13 @@ m4_define([b4_integral_parser_table_define], };dnl ]) + +# b4_symbol_kind(NUM) +# ------------------- +m4_define([b4_symbol_kind], +[symbol_kind::b4_symbol_kind_base($@)]) + + # b4_symbol_value_template(VAL, SYMBOL-NUM, [TYPE]) # ------------------------------------------------- # Same as b4_symbol_value, but used in a template method. It makes @@ -153,7 +160,7 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param))])]) m4_pushdef([b4_copyright_years], - [2002-2015, 2018-2020]) + [2002-2015, 2018-2021]) m4_define([b4_parser_class], [b4_percent_define_get([[api.parser.class]])]) @@ -264,9 +271,9 @@ m4_define([b4_shared_declarations], { public: context (const ]b4_parser_class[& yyparser, const symbol_type& yyla); - const symbol_type& lookahead () const { return yyla_; } - symbol_kind_type token () const { return yyla_.kind (); }]b4_locations_if([[ - const location_type& location () const { return yyla_.location; } + const symbol_type& lookahead () const YY_NOEXCEPT { return yyla_; } + symbol_kind_type token () const YY_NOEXCEPT { return yyla_.kind (); }]b4_locations_if([[ + const location_type& location () const YY_NOEXCEPT { return yyla_.location; } ]])[ /// Put in YYARG at most YYARGN of the expected tokens, and return the /// number of tokens stored in YYARG. If YYARG is null, return the @@ -486,14 +493,6 @@ m4_define([b4_shared_declarations], ]b4_public_types_define([$1])])[ ]b4_namespace_close[ -]b4_percent_define_flag_if([[global_tokens_and_yystype]], -[b4_token_defines - -#ifndef ]b4_api_PREFIX[STYPE - // Redirection for backward compatibility. -# define ]b4_api_PREFIX[STYPE b4_namespace_ref::b4_parser_class::semantic_type -#endif -])[ ]b4_percent_code_get([[provides]])[ ]]) @@ -506,16 +505,16 @@ b4_defines_if( b4_copyright([Skeleton interface for Bison LALR(1) parsers in C++]) [ /** - ** \file ]b4_spec_header_file[ + ** \file ]b4_spec_mapped_header_file[ ** Define the ]b4_namespace_ref[::parser class. */ // C++ LALR(1) parser skeleton written by Akim Demaille. ]b4_disclaimer[ -]b4_cpp_guard_open([b4_spec_header_file])[ +]b4_cpp_guard_open([b4_spec_mapped_header_file])[ ]b4_shared_declarations(hh)[ -]b4_cpp_guard_close([b4_spec_header_file])[ +]b4_cpp_guard_close([b4_spec_mapped_header_file])[ ]b4_output_end[ ]]) @@ -598,7 +597,7 @@ m4_if(b4_prefix, [yy], [], #else // !]b4_api_PREFIX[DEBUG # define YYCDEBUG if (false) std::cerr -# define YY_SYMBOL_PRINT(Title, Symbol) YYUSE (Symbol) +# define YY_SYMBOL_PRINT(Title, Symbol) YY_USE (Symbol) # define YY_REDUCE_PRINT(Rule) static_cast<void> (0) # define YY_STACK_PRINT() static_cast<void> (0) @@ -666,7 +665,7 @@ m4_if(b4_prefix, [yy], [], ]b4_parser_class[::by_state::kind () const YY_NOEXCEPT { if (state == empty_state) - return symbol_kind::]b4_symbol(-2, kind)[; + return ]b4_symbol(-2, kind)[; else return YY_CAST (symbol_kind_type, yystos_[+state]); } @@ -691,7 +690,7 @@ m4_if(b4_prefix, [yy], [], b4_symbol_variant([that.kind ()], [value], [move], [YY_MOVE (that.value)])])[ // that is emptied. - that.kind_ = symbol_kind::]b4_symbol(-2, kind)[; + that.kind_ = ]b4_symbol(-2, kind)[; } #if YY_CPLUSPLUS < 201103L @@ -737,7 +736,7 @@ m4_if(b4_prefix, [yy], [], ]b4_parser_class[::yy_print_ (std::ostream& yyo, const basic_symbol<Base>& yysym) const { std::ostream& yyoutput = yyo; - YYUSE (yyoutput); + YY_USE (yyoutput); if (yysym.empty ()) yyo << "empty symbol"; else @@ -920,13 +919,13 @@ b4_dollar_popdef])[]dnl } YY_SYMBOL_PRINT ("Next token is", yyla); - if (yyla.kind () == ]symbol_kind::b4_symbol(1, kind)[) + if (yyla.kind () == ]b4_symbol(1, kind)[) { // The scanner already issued an error message, process directly // to error recovery. But do not keep the error token as // lookahead, it is too special and may lead us to an endless // loop in error recovery. */ - yyla.kind_ = ]symbol_kind::b4_symbol(2, kind)[; + yyla.kind_ = ]b4_symbol(2, kind)[; goto yyerrlab1; } @@ -1063,7 +1062,7 @@ b4_dollar_popdef])[]dnl error, discard it. */ // Return failure if at end of input. - if (yyla.kind () == symbol_kind::]b4_symbol_prefix[YYEOF) + if (yyla.kind () == ]b4_symbol(0, kind)[) YYABORT; else if (!yyla.empty ()) { @@ -1104,9 +1103,9 @@ b4_dollar_popdef])[]dnl yyn = yypact_[+yystack_[0].state]; if (!yy_pact_value_is_default_ (yyn)) { - yyn += symbol_kind::]b4_symbol(1, kind)[; + yyn += ]b4_symbol(1, kind)[; if (0 <= yyn && yyn <= yylast_ - && yycheck_[yyn] == symbol_kind::]b4_symbol(1, kind)[) + && yycheck_[yyn] == ]b4_symbol(1, kind)[) { yyn = yytable_[yyn]; if (0 < yyn) @@ -1298,8 +1297,8 @@ b4_dollar_popdef])[]dnl for (int yyx = 0; yyx < YYNTOKENS; ++yyx) { symbol_kind_type yysym = YY_CAST (symbol_kind_type, yyx); - if (yysym != symbol_kind::]b4_symbol(1, kind)[ - && yysym != symbol_kind::]b4_symbol_prefix[YYUNDEF + if (yysym != ]b4_symbol(1, kind)[ + && yysym != ]b4_symbol(2, kind)[ && yyparser_.yy_lac_check_ (yysym)) { if (!yyarg) @@ -1321,7 +1320,7 @@ b4_dollar_popdef])[]dnl int yychecklim = yylast_ - yyn + 1; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; for (int yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck_[yyx + yyn] == yyx && yyx != symbol_kind::]b4_symbol(1, kind)[ + if (yycheck_[yyx + yyn] == yyx && yyx != ]b4_symbol(1, kind)[ && !yy_table_value_is_error_ (yytable_[yyx + yyn])) { if (!yyarg) @@ -1334,7 +1333,7 @@ b4_dollar_popdef])[]dnl } ]])[ if (yyarg && yycount == 0 && 0 < yyargn) - yyarg[0] = symbol_kind::]b4_symbol(-2, kind)[; + yyarg[0] = ]b4_symbol(-2, kind)[; return yycount; } diff --git a/contrib/tools/bison/data/skeletons/location.cc b/contrib/tools/bison/data/skeletons/location.cc index 34db41881c..1ec48de749 100644 --- a/contrib/tools/bison/data/skeletons/location.cc +++ b/contrib/tools/bison/data/skeletons/location.cc @@ -1,6 +1,6 @@ # C++ skeleton for Bison -# Copyright (C) 2002-2015, 2018-2020 Free Software Foundation, Inc. +# Copyright (C) 2002-2015, 2018-2021 Free Software Foundation, Inc. # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -13,16 +13,16 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# along with this program. If not, see <https://www.gnu.org/licenses/>. m4_pushdef([b4_copyright_years], - [2002-2015, 2018-2020]) + [2002-2015, 2018-2021]) # b4_position_file # ---------------- # Name of the file containing the position class, if we want this file. -b4_defines_if([b4_required_version_if([302], [], +b4_defines_if([b4_required_version_if([30200], [], [m4_define([b4_position_file], [position.hh])])])]) @@ -48,7 +48,7 @@ m4_ifdef([b4_location_file], ["b4_location_file"])]) m4_define([b4_location_path], b4_percent_define_get([[api.location.include]], - ["b4_dir_prefix[]b4_location_file"])) + ["b4_mapped_dir_prefix[]b4_location_file"])) m4_define([b4_location_path], m4_substr(m4_defn([b4_location_path]), 1, m4_eval(m4_len(m4_defn([b4_location_path])) - 2))) ]) @@ -63,11 +63,13 @@ m4_define([b4_location_define], class position { public: + /// Type for file name. + typedef ]b4_percent_define_get([[api.filename.type]])[ filename_type; /// Type for line and column numbers. typedef int counter_type; ]m4_ifdef([b4_location_constructors], [[ /// Construct a position. - explicit position (]b4_percent_define_get([[filename_type]])[* f = YY_NULLPTR, + explicit position (filename_type* f = YY_NULLPTR, counter_type l = ]b4_location_initial_line[, counter_type c = ]b4_location_initial_column[) : filename (f) @@ -77,7 +79,7 @@ m4_define([b4_location_define], ]])[ /// Initialization. - void initialize (]b4_percent_define_get([[filename_type]])[* fn = YY_NULLPTR, + void initialize (filename_type* fn = YY_NULLPTR, counter_type l = ]b4_location_initial_line[, counter_type c = ]b4_location_initial_column[) { @@ -106,7 +108,7 @@ m4_define([b4_location_define], /** \} */ /// File name to which this position refers. - ]b4_percent_define_get([[filename_type]])[* filename; + filename_type* filename; /// Current line number. counter_type line; /// Current column number. @@ -184,6 +186,8 @@ m4_define([b4_location_define], class location { public: + /// Type for file name. + typedef position::filename_type filename_type; /// Type for line and column numbers. typedef position::counter_type counter_type; ]m4_ifdef([b4_location_constructors], [ @@ -200,7 +204,7 @@ m4_define([b4_location_define], {} /// Construct a 0-width location in \a f, \a l, \a c. - explicit location (]b4_percent_define_get([[filename_type]])[* f, + explicit location (filename_type* f, counter_type l = ]b4_location_initial_line[, counter_type c = ]b4_location_initial_column[) : begin (f, l, c) @@ -209,7 +213,7 @@ m4_define([b4_location_define], ])[ /// Initialization. - void initialize (]b4_percent_define_get([[filename_type]])[* f = YY_NULLPTR, + void initialize (filename_type* f = YY_NULLPTR, counter_type l = ]b4_location_initial_line[, counter_type c = ]b4_location_initial_column[) { diff --git a/contrib/tools/bison/data/skeletons/stack.hh b/contrib/tools/bison/data/skeletons/stack.hh index 0fd3625836..c76fad599c 100644 --- a/contrib/tools/bison/data/skeletons/stack.hh +++ b/contrib/tools/bison/data/skeletons/stack.hh @@ -1,6 +1,6 @@ # C++ skeleton for Bison -# Copyright (C) 2002-2015, 2018-2020 Free Software Foundation, Inc. +# Copyright (C) 2002-2015, 2018-2021 Free Software Foundation, Inc. # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -13,13 +13,13 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# along with this program. If not, see <https://www.gnu.org/licenses/>. # b4_stack_file # ------------- # Name of the file containing the stack class, if we want this file. -b4_defines_if([b4_required_version_if([302], [], +b4_defines_if([b4_required_version_if([30200], [], [m4_define([b4_stack_file], [stack.hh])])]) diff --git a/contrib/tools/bison/data/skeletons/variant.hh b/contrib/tools/bison/data/skeletons/variant.hh index b594af3808..2f68b0ca3f 100644 --- a/contrib/tools/bison/data/skeletons/variant.hh +++ b/contrib/tools/bison/data/skeletons/variant.hh @@ -1,6 +1,6 @@ # C++ skeleton for Bison -# Copyright (C) 2002-2015, 2018-2020 Free Software Foundation, Inc. +# Copyright (C) 2002-2015, 2018-2021 Free Software Foundation, Inc. # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -13,13 +13,20 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# along with this program. If not, see <https://www.gnu.org/licenses/>. ## --------- ## ## variant. ## ## --------- ## +# b4_assert +# --------- +# The name of YY_ASSERT. +m4_define([b4_assert], + [b4_api_PREFIX[]_ASSERT]) + + # b4_symbol_variant(YYTYPE, YYVAL, ACTION, [ARGS]) # ------------------------------------------------ # Run some ACTION ("build", or "destroy") on YYVAL of symbol type @@ -71,12 +78,12 @@ m4_map([ b4_symbol_tag_comment], [$@])dnl # ------------------- # The needed includes for variants support. m4_define([b4_variant_includes], -[b4_parse_assert_if([[#include <typeinfo>]])[ -#ifndef YY_ASSERT +[b4_parse_assert_if([[#include <typeinfo> +#ifndef ]b4_assert[ # include <cassert> -# define YY_ASSERT assert +# define ]b4_assert[ assert #endif -]]) +]])]) @@ -110,8 +117,8 @@ m4_define([b4_value_type_declare], template <typename T> semantic_type (YY_RVREF (T) t)]b4_parse_assert_if([ : yytypeid_ (&typeid (T))])[ - { - YY_ASSERT (sizeof (T) <= size); + {]b4_parse_assert_if([[ + ]b4_assert[ (sizeof (T) <= size);]])[ new (yyas_<T> ()) T (YY_MOVE (t)); } @@ -125,7 +132,7 @@ m4_define([b4_value_type_declare], /// Destruction, allowed only if empty. ~semantic_type () YY_NOEXCEPT {]b4_parse_assert_if([ - YY_ASSERT (!yytypeid_); + ]b4_assert[ (!yytypeid_); ])[} # if 201103L <= YY_CPLUSPLUS @@ -133,10 +140,10 @@ m4_define([b4_value_type_declare], template <typename T, typename... U> T& emplace (U&&... u) - {]b4_parse_assert_if([ - YY_ASSERT (!yytypeid_); - YY_ASSERT (sizeof (T) <= size); - yytypeid_ = & typeid (T);])[ + {]b4_parse_assert_if([[ + ]b4_assert[ (!yytypeid_); + ]b4_assert[ (sizeof (T) <= size); + yytypeid_ = & typeid (T);]])[ return *new (yyas_<T> ()) T (std::forward <U>(u)...); } # else @@ -144,10 +151,10 @@ m4_define([b4_value_type_declare], template <typename T> T& emplace () - {]b4_parse_assert_if([ - YY_ASSERT (!yytypeid_); - YY_ASSERT (sizeof (T) <= size); - yytypeid_ = & typeid (T);])[ + {]b4_parse_assert_if([[ + ]b4_assert[ (!yytypeid_); + ]b4_assert[ (sizeof (T) <= size); + yytypeid_ = & typeid (T);]])[ return *new (yyas_<T> ()) T (); } @@ -155,10 +162,10 @@ m4_define([b4_value_type_declare], template <typename T> T& emplace (const T& t) - {]b4_parse_assert_if([ - YY_ASSERT (!yytypeid_); - YY_ASSERT (sizeof (T) <= size); - yytypeid_ = & typeid (T);])[ + {]b4_parse_assert_if([[ + ]b4_assert[ (!yytypeid_); + ]b4_assert[ (sizeof (T) <= size); + yytypeid_ = & typeid (T);]])[ return *new (yyas_<T> ()) T (t); } # endif @@ -185,10 +192,10 @@ m4_define([b4_value_type_declare], template <typename T> T& as () YY_NOEXCEPT - {]b4_parse_assert_if([ - YY_ASSERT (yytypeid_); - YY_ASSERT (*yytypeid_ == typeid (T)); - YY_ASSERT (sizeof (T) <= size);])[ + {]b4_parse_assert_if([[ + ]b4_assert[ (yytypeid_); + ]b4_assert[ (*yytypeid_ == typeid (T)); + ]b4_assert[ (sizeof (T) <= size);]])[ return *yyas_<T> (); } @@ -196,10 +203,10 @@ m4_define([b4_value_type_declare], template <typename T> const T& as () const YY_NOEXCEPT - {]b4_parse_assert_if([ - YY_ASSERT (yytypeid_); - YY_ASSERT (*yytypeid_ == typeid (T)); - YY_ASSERT (sizeof (T) <= size);])[ + {]b4_parse_assert_if([[ + ]b4_assert[ (yytypeid_); + ]b4_assert[ (*yytypeid_ == typeid (T)); + ]b4_assert[ (sizeof (T) <= size);]])[ return *yyas_<T> (); } @@ -214,9 +221,9 @@ m4_define([b4_value_type_declare], template <typename T> void swap (self_type& that) YY_NOEXCEPT - {]b4_parse_assert_if([ - YY_ASSERT (yytypeid_); - YY_ASSERT (*yytypeid_ == *that.yytypeid_);])[ + {]b4_parse_assert_if([[ + ]b4_assert[ (yytypeid_); + ]b4_assert[ (*yytypeid_ == *that.yytypeid_);]])[ std::swap (as<T> (), that.as<T> ()); } @@ -388,11 +395,67 @@ m4_define([_b4_token_maker_define], ])]) -m4_define([_b4_type_clause], -[b4_symbol_if([$1], [is_token], - [b4_symbol_if([$1], [has_id], - [tok == token::b4_symbol([$1], [id])], - [tok == b4_symbol([$1], [user_number])])])]) +# b4_token_kind(SYMBOL-NUM) +# ------------------------- +# Some tokens don't have an ID. +m4_define([b4_token_kind], +[b4_symbol_if([$1], [has_id], + [token::b4_symbol([$1], [id])], + [b4_symbol([$1], [code])])]) + + +# _b4_tok_in(SYMBOL-NUM, ...) +# --------------------------- +# See b4_tok_in below. The SYMBOL-NUMs... are tokens only. +# +# We iterate over the tokens to group them by "range" of token numbers (not +# symbols numbers!). +# +# b4_fst is the start of that range. +# b4_prev is the previous value. +# b4_val is the current value. +# If b4_val is the successor of b4_prev in token numbers, update the latter, +# otherwise emit the code for range b4_fst .. b4_prev. +# $1 is also used as a terminator in the foreach, but it will not be printed. +# +m4_define([_b4_tok_in], +[m4_pushdef([b4_prev], [$1])dnl +m4_pushdef([b4_fst], [$1])dnl +m4_pushdef([b4_sep], [])dnl +m4_foreach([b4_val], m4_dquote(m4_shift($@, $1)), + [m4_if(b4_symbol(b4_val, [code]), m4_eval(b4_symbol(b4_prev, [code]) + 1), [], + [b4_sep[]m4_if(b4_fst, b4_prev, + [tok == b4_token_kind(b4_fst)], + [(b4_token_kind(b4_fst) <= tok && tok <= b4_token_kind(b4_prev))])[]dnl +m4_define([b4_fst], b4_val)dnl +m4_define([b4_sep], [ + || ])])dnl +m4_define([b4_prev], b4_val)])dnl +m4_popdef([b4_sep])dnl +m4_popdef([b4_fst])dnl +m4_popdef([b4_prev])dnl +]) + + +# _b4_filter_tokens(SYMBOL-NUM, ...) +# ---------------------------------- +# Expand as the list of tokens amongst SYMBOL-NUM. +m4_define([_b4_filter_tokens], +[m4_pushdef([b4_sep])dnl +m4_foreach([b4_val], [$@], + [b4_symbol_if(b4_val, [is_token], [b4_sep[]b4_val[]m4_define([b4_sep], [,])])])dnl +m4_popdef([b4_sep])dnl +]) + + +# b4_tok_in(SYMBOL-NUM, ...) +# --------------------------- +# A C++ conditional that checks that `tok` is a member of this list of symbol +# numbers. +m4_define([b4_tok_in], + [_$0(_b4_filter_tokens($@))]) + + # _b4_token_constructor_define(SYMBOL-NUM...) @@ -410,9 +473,6 @@ m4_define([_b4_token_constructor_define], : super_type(]b4_join([token_type (tok)], b4_symbol_if([$1], [has_type], [std::move (v)]), b4_locations_if([std::move (l)]))[) - { - YY_ASSERT (]m4_join([ || ], m4_map_sep([_b4_type_clause], [, ], [$@]))[); - } #else symbol_type (]b4_join( [int tok], @@ -422,10 +482,10 @@ m4_define([_b4_token_constructor_define], : super_type(]b4_join([token_type (tok)], b4_symbol_if([$1], [has_type], [v]), b4_locations_if([l]))[) - { - YY_ASSERT (]m4_join([ || ], m4_map_sep([_b4_type_clause], [, ], [$@]))[); - } #endif + {]b4_parse_assert_if([[ + ]b4_assert[ (]b4_tok_in($@)[); + ]])[} ]])]) diff --git a/contrib/tools/bison/data/skeletons/yacc.c b/contrib/tools/bison/data/skeletons/yacc.c index bd5e7d8448..afdb508565 100644 --- a/contrib/tools/bison/data/skeletons/yacc.c +++ b/contrib/tools/bison/data/skeletons/yacc.c @@ -1,11 +1,11 @@ # -*- C -*- # Yacc compatible skeleton for Bison -# Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software +# Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software # Foundation, Inc. m4_pushdef([b4_copyright_years], - [1984, 1989-1990, 2000-2015, 2018-2020]) + [1984, 1989-1990, 2000-2015, 2018-2021]) # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -18,7 +18,7 @@ m4_pushdef([b4_copyright_years], # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. +# along with this program. If not, see <https://www.gnu.org/licenses/>. m4_include(b4_skeletonsdir/[c.m4]) @@ -48,6 +48,10 @@ m4_define([b4_pure_if], ## api.push-pull. ## ## --------------- ## +# b4_pull_if, b4_push_if +# ---------------------- +# Whether the pull/push APIs are needed. Both can be enabled. + b4_percent_define_default([[api.push-pull]], [[pull]]) b4_percent_define_check_values([[[[api.push-pull]], [[pull]], [[push]], [[both]]]]) @@ -155,7 +159,7 @@ m4_define([b4_rhs_location], # Declare the variables that are global, or local to YYPARSE if # pure-parser. m4_define([b4_declare_scanner_communication_variables], [[ -/* The lookahead symbol. */ +/* Lookahead token kind. */ int yychar; ]b4_pure_if([[ @@ -176,68 +180,47 @@ YYLTYPE yylloc]b4_yyloc_default[;]])[ int yynerrs;]])]) -# b4_declare_parser_state_variables -# --------------------------------- +# b4_declare_parser_state_variables([INIT]) +# ----------------------------------------- # Declare all the variables that are needed to maintain the parser state # between calls to yypush_parse. +# If INIT is non-null, initialize these variables. m4_define([b4_declare_parser_state_variables], [b4_pure_if([[ /* Number of syntax errors so far. */ - int yynerrs; + int yynerrs]m4_ifval([$1], [ = 0])[; ]])[ - yy_state_fast_t yystate; + yy_state_fast_t yystate]m4_ifval([$1], [ = 0])[; /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; - - /* The stacks and their tools: - 'yyss': related to states. - 'yyvs': related to semantic values.]b4_locations_if([[ - 'yyls': related to locations.]])[ + int yyerrstatus]m4_ifval([$1], [ = 0])[; - Refer to the stacks through separate pointers, to allow yyoverflow + /* Refer to the stacks through separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* Their size. */ - YYPTRDIFF_T yystacksize; + YYPTRDIFF_T yystacksize]m4_ifval([$1], [ = YYINITDEPTH])[; - /* The state stack. */ + /* The state stack: array, bottom, top. */ yy_state_t yyssa[YYINITDEPTH]; - yy_state_t *yyss; - yy_state_t *yyssp; + yy_state_t *yyss]m4_ifval([$1], [ = yyssa])[; + yy_state_t *yyssp]m4_ifval([$1], [ = yyss])[; - /* The semantic value stack. */ + /* The semantic value stack: array, bottom, top. */ YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs; - YYSTYPE *yyvsp;]b4_locations_if([[ + YYSTYPE *yyvs]m4_ifval([$1], [ = yyvsa])[; + YYSTYPE *yyvsp]m4_ifval([$1], [ = yyvs])[;]b4_locations_if([[ - /* The location stack. */ + /* The location stack: array, bottom, top. */ YYLTYPE yylsa[YYINITDEPTH]; - YYLTYPE *yyls; - YYLTYPE *yylsp;]])[]b4_lac_if([[ + YYLTYPE *yyls]m4_ifval([$1], [ = yylsa])[; + YYLTYPE *yylsp]m4_ifval([$1], [ = yyls])[;]])[]b4_lac_if([[ yy_state_t yyesa@{]b4_percent_define_get([[parse.lac.es-capacity-initial]])[@}; - yy_state_t *yyes; - YYPTRDIFF_T yyes_capacity;]])]) - - -# b4_initialize_parser_state_variables -# ------------------------------------ -# Initialize these variables. -m4_define([b4_initialize_parser_state_variables], -[[ yynerrs = 0; - yystate = 0; - yyerrstatus = 0; - - yystacksize = YYINITDEPTH; - yyssp = yyss = yyssa; - yyvsp = yyvs = yyvsa;]b4_locations_if([[ - yylsp = yyls = yylsa;]])[]b4_lac_if([[ - - yyes = yyesa; - yyes_capacity = ]b4_percent_define_get([[parse.lac.es-capacity-initial]])[; - if (YYMAXDEPTH < yyes_capacity) - yyes_capacity = YYMAXDEPTH;]])[ -]]) + yy_state_t *yyes]m4_ifval([$1], [ = yyesa])[; + YYPTRDIFF_T yyes_capacity][]m4_ifval([$1], + [m4_do([ = b4_percent_define_get([[parse.lac.es-capacity-initial]]) < YYMAXDEPTH], + [ ? b4_percent_define_get([[parse.lac.es-capacity-initial]])], + [ : YYMAXDEPTH])])[;]])]) m4_define([b4_macro_define], @@ -313,14 +296,14 @@ m4_define([b4_declare_yyparse], # Declaration that might either go into the header (if --defines) # or open coded in the parser body. m4_define([b4_shared_declarations], -[b4_cpp_guard_open([b4_spec_header_file])[ +[b4_cpp_guard_open([b4_spec_mapped_header_file])[ ]b4_declare_yydebug[ ]b4_percent_code_get([[requires]])[ ]b4_token_enums_defines[ ]b4_declare_yylstype[ ]b4_declare_yyparse[ ]b4_percent_code_get([[provides]])[ -]b4_cpp_guard_close([b4_spec_header_file])[]dnl +]b4_cpp_guard_close([b4_spec_mapped_header_file])[]dnl ]) @@ -335,7 +318,7 @@ m4_define([b4_header_include_if], [$2])], [$2])]) -m4_if(b4_spec_header_file, [[y.tab.h]], +m4_if(b4_spec_header_file, [y.tab.h], [], [b4_percent_define_default([[api.header.include]], [["@basename(]b4_spec_header_file[@)"]])]) @@ -592,7 +575,8 @@ union yyalloc /* YYNSTATES -- Number of states. */ #define YYNSTATES ]b4_states_number[ -#define YYMAXUTOK ]b4_user_token_number_max[ +/* YYMAXUTOK -- Last valid token kind. */ +#define YYMAXUTOK ]b4_code_max[ /* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM @@ -829,7 +813,8 @@ int yydebug; /* Parser data structure. */ struct yypstate {]b4_declare_parser_state_variables[ - /* Whether this instance has not started parsing yet. */ + /* Whether this instance has not started parsing yet. + * If 2, it corresponds to a finished parsing. */ int yynew; };]b4_pure_if([], [[ @@ -1444,36 +1429,33 @@ yysyntax_error (YYPTRDIFF_T *yymsg_alloc, char **yymsg, int yyparse (]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param)], [void])[) { - return yypull_parse (YY_NULLPTR]b4_user_args[); + yypstate *yyps = yypstate_new (); + if (!yyps) + {]b4_pure_if([b4_locations_if([[ + static YYLTYPE yyloc_default][]b4_yyloc_default[; + YYLTYPE yylloc = yyloc_default;]])[ + yyerror (]b4_yyerror_args[YY_("memory exhausted"));]], [[ + if (!yypstate_allocated) + yyerror (]b4_yyerror_args[YY_("memory exhausted"));]])[ + return 2; + } + int yystatus = yypull_parse (yyps]b4_user_args[); + yypstate_delete (yyps); + return yystatus; } int yypull_parse (yypstate *yyps]b4_user_formals[) -{]b4_pure_if([b4_locations_if([[ +{ + YY_ASSERT (yyps);]b4_pure_if([b4_locations_if([[ static YYLTYPE yyloc_default][]b4_yyloc_default[; YYLTYPE yylloc = yyloc_default;]])])[ - yypstate *yyps_local; - if (yyps) - yyps_local = yyps; - else - { - yyps_local = yypstate_new (); - if (!yyps_local) - {]b4_pure_if([[ - yyerror (]b4_yyerror_args[YY_("memory exhausted"));]], [[ - if (!yypstate_allocated) - yyerror (]b4_yyerror_args[YY_("memory exhausted"));]])[ - return 2; - } - } int yystatus; do { ]b4_pure_if([[ YYSTYPE yylval; int ]])[yychar = ]b4_lex[; - yystatus = yypush_parse (yyps_local]b4_pure_if([[, yychar, &yylval]b4_locations_if([[, &yylloc]])])m4_ifset([b4_parse_param], [, b4_args(b4_parse_param)])[); + yystatus = yypush_parse (yyps]b4_pure_if([[, yychar, &yylval]b4_locations_if([[, &yylloc]])])m4_ifset([b4_parse_param], [, b4_args(b4_parse_param)])[); } while (yystatus == YYPUSH_MORE); - if (!yyps) - yypstate_delete (yyps_local); return yystatus; }]])[ @@ -1483,10 +1465,18 @@ yypull_parse (yypstate *yyps]b4_user_formals[) static void yypstate_clear (yypstate *yyps) { -]b4_initialize_parser_state_variables[ + yynerrs = 0; + yystate = 0; + yyerrstatus = 0; + + yyssp = yyss; + yyvsp = yyvs;]b4_locations_if([[ + yylsp = yyls;]])[ + /* Initialize the state stack, in case yypcontext_expected_tokens is called before the first call to yyparse. */ *yyssp = 0; + yyps->yynew = 1; } /* Initialize the parser data structure. */ @@ -1496,11 +1486,18 @@ yypstate_new (void) yypstate *yyps;]b4_pure_if([], [[ if (yypstate_allocated) return YY_NULLPTR;]])[ - yyps = YY_CAST (yypstate *, malloc (sizeof *yyps)); + yyps = YY_CAST (yypstate *, YYMALLOC (sizeof *yyps)); if (!yyps) - return YY_NULLPTR; - yyps->yynew = 1;]b4_pure_if([], [[ + return YY_NULLPTR;]b4_pure_if([], [[ yypstate_allocated = 1;]])[ + yystacksize = YYINITDEPTH; + yyss = yyssa; + yyvs = yyvsa;]b4_locations_if([[ + yyls = yylsa;]])[]b4_lac_if([[ + yyes = yyesa; + yyes_capacity = ]b4_percent_define_get([[parse.lac.es-capacity-initial]])[; + if (YYMAXDEPTH < yyes_capacity) + yyes_capacity = YYMAXDEPTH;]])[ yypstate_clear (yyps); return yyps; } @@ -1513,12 +1510,12 @@ yypstate_delete (yypstate *yyps) #ifndef yyoverflow /* If the stack was reallocated but the parse did not complete, then the stack still needs to be freed. */ - if (!yyps->yynew && yyss != yyssa) + if (yyss != yyssa) YYSTACK_FREE (yyss); #endif]b4_lac_if([[ - if (!yyps->yynew && yyes != yyesa) + if (yyes != yyesa) YYSTACK_FREE (yyes);]])[ - free (yyps);]b4_pure_if([], [[ + YYFREE (yyps);]b4_pure_if([], [[ yypstate_allocated = 0;]])[ } } @@ -1545,14 +1542,14 @@ yyparse (]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param)], [void])[)]])[ YYSTYPE yypushed_val = yylval;]b4_locations_if([[ YYLTYPE yypushed_loc = yylloc;]]) ])], - [b4_declare_parser_state_variables + [b4_declare_parser_state_variables([init]) ])b4_lac_if([[ /* Whether LAC context is established. A Boolean. */ int yy_lac_established = 0;]])[ int yyn; /* The return value of yyparse. */ int yyresult; - /* Lookahead token as an internal (translated) token number. */ + /* Lookahead symbol kind. */ yysymbol_kind_t yytoken = ]b4_symbol(-2, kind)[; /* The variables used to return semantic value and location from the action routines. */ @@ -1572,14 +1569,21 @@ yyparse (]m4_ifset([b4_parse_param], [b4_formals(b4_parse_param)], [void])[)]])[ /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ - int yylen = 0; -]b4_push_if([[ - if (!yyps->yynew) + int yylen = 0;]b4_push_if([[ + + switch (yyps->yynew) { + case 0: yyn = yypact[yystate]; goto yyread_pushed_token; - }]], [ -b4_initialize_parser_state_variables])[ + + case 2: + yypstate_clear (yyps); + break; + + default: + break; + }]])[ YYDPRINTF ((stderr, "Starting parse\n")); @@ -2048,13 +2052,13 @@ yyabortlab: yyexhaustedlab: yyerror (]b4_yyerror_args[YY_("memory exhausted")); yyresult = 2; - /* Fall through. */ + goto yyreturn; #endif -/*-----------------------------------------------------. -| yyreturn -- parsing is finished, return the result. | -`-----------------------------------------------------*/ +/*-------------------------------------------------------. +| yyreturn -- parsing is finished, clean up and return. | +`-------------------------------------------------------*/ yyreturn: if (yychar != ]b4_symbol(-2, id)[) { @@ -2073,21 +2077,21 @@ yyreturn: yydestruct ("Cleanup: popping", YY_ACCESSING_SYMBOL (+*yyssp), yyvsp]b4_locations_if([, yylsp])[]b4_user_args[); YYPOPSTACK (1); - } + }]b4_push_if([[ + yyps->yynew = 2; + goto yypushreturn; + + +/*-------------------------. +| yypushreturn -- return. | +`-------------------------*/ +yypushreturn:]], [[ #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif]b4_lac_if([[ if (yyes != yyesa) - YYSTACK_FREE (yyes);]])b4_push_if([[ - yypstate_clear (yyps); - yyps->yynew = 1; - - -/*-----------------------------------------. -| yypushreturn -- ask for the next token. | -`-----------------------------------------*/ -yypushreturn:]])[ + YYSTACK_FREE (yyes);]])])[ ]b4_parse_error_bmatch([detailed\|verbose], [[ if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg);]])[ diff --git a/contrib/tools/bison/lib/arg-nonnull.h b/contrib/tools/bison/lib/arg-nonnull.h index ac26ca8cfe..db9d9ae116 100644 --- a/contrib/tools/bison/lib/arg-nonnull.h +++ b/contrib/tools/bison/lib/arg-nonnull.h @@ -18,7 +18,7 @@ that the values passed as arguments n, ..., m must be non-NULL pointers. n = 1 stands for the first argument, n = 2 for the second argument etc. */ #ifndef _GL_ARG_NONNULL -# if (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || __GNUC__ > 3 +# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || defined __clang__ # define _GL_ARG_NONNULL(params) __attribute__ ((__nonnull__ params)) # else # define _GL_ARG_NONNULL(params) diff --git a/contrib/tools/bison/lib/assure.h b/contrib/tools/bison/lib/assure.h index 8ea2f6e480..09a4edfa59 100644 --- a/contrib/tools/bison/lib/assure.h +++ b/contrib/tools/bison/lib/assure.h @@ -21,12 +21,32 @@ #define _GL_ASSURE_H #include <assert.h> +#include "verify.h" + +/* Evaluate an assertion E that is guaranteed to be true. + If NDEBUG is not defined, abort the program if E is false. + If NDEBUG is defined, the compiler can assume E and behavior is + undefined if E is false, fails to evaluate, or has side effects. + + Unlike standard 'assert', this macro evaluates E even when NDEBUG + is defined, so as to catch typos, avoid some GCC warnings, and + improve performance when E is simple enough. + + Also see the documentation for 'assume' in verify.h. */ + +#ifdef NDEBUG +# define affirm(E) assume (E) +#else +# define affirm(E) assert (E) +#endif /* Check E's value at runtime, and report an error and abort if not. However, do nothing if NDEBUG is defined. - Unlike standard 'assert', this macro always compiles E even when NDEBUG - is defined, so as to catch typos and avoid some GCC warnings. */ + Unlike standard 'assert', this macro compiles E even when NDEBUG + is defined, so as to catch typos and avoid some GCC warnings. + Unlike 'affirm', it is OK for E to use hard-to-optimize features, + since E is not executed if NDEBUG is defined. */ #ifdef NDEBUG # define assure(E) ((void) (0 && (E))) diff --git a/contrib/tools/bison/lib/attribute.h b/contrib/tools/bison/lib/attribute.h index 2836b99dad..5afcb8e81f 100644 --- a/contrib/tools/bison/lib/attribute.h +++ b/contrib/tools/bison/lib/attribute.h @@ -80,7 +80,7 @@ /* Attributes for variadic functions. */ /* The variadic function expects a trailing NULL argument. - ATTRIBUTE_SENTINEL () - The last argument is NULL. + ATTRIBUTE_SENTINEL () - The last argument is NULL (requires C99). ATTRIBUTE_SENTINEL ((N)) - The (N+1)st argument from the end is NULL. */ /* Applies to: functions. */ #define ATTRIBUTE_SENTINEL(pos) _GL_ATTRIBUTE_SENTINEL (pos) @@ -170,18 +170,21 @@ /* Applies to: function. */ #define ATTRIBUTE_ALWAYS_INLINE _GL_ATTRIBUTE_ALWAYS_INLINE -/* The function does not affect observable state, and always returns a value. - Compilers can omit duplicate calls with the same arguments if - observable state is not changed between calls. (This attribute is - looser than ATTRIBUTE_CONST.) */ +/* It is OK for a compiler to omit duplicate calls with the same arguments. + This attribute is safe for a function that neither depends on + nor affects observable state, and always returns exactly once - + e.g., does not loop forever, and does not call longjmp. + (This attribute is stricter than ATTRIBUTE_PURE.) */ /* Applies to: functions. */ -#define ATTRIBUTE_PURE _GL_ATTRIBUTE_PURE +#define ATTRIBUTE_CONST _GL_ATTRIBUTE_CONST -/* The function neither depends on nor affects observable state, - and always returns a value. Compilers can omit duplicate calls with - the same arguments. (This attribute is stricter than ATTRIBUTE_PURE.) */ +/* It is OK for a compiler to omit duplicate calls with the same + arguments if observable state is not changed between calls. + This attribute is safe for a function that does not affect + observable state, and always returns exactly once. + (This attribute is looser than ATTRIBUTE_CONST.) */ /* Applies to: functions. */ -#define ATTRIBUTE_CONST _GL_ATTRIBUTE_CONST +#define ATTRIBUTE_PURE _GL_ATTRIBUTE_PURE /* The function is rarely executed. */ /* Applies to: functions. */ diff --git a/contrib/tools/bison/lib/basename-lgpl.c b/contrib/tools/bison/lib/basename-lgpl.c index 565469ea3d..6bb28d45f1 100644 --- a/contrib/tools/bison/lib/basename-lgpl.c +++ b/contrib/tools/bison/lib/basename-lgpl.c @@ -18,20 +18,20 @@ #include <config.h> -#include "dirname.h" +/* Specification. */ +#include "basename-lgpl.h" +#include <stdbool.h> #include <string.h> -/* Return the address of the last file name component of NAME. If - NAME has no relative file name components because it is a file - system root, return the empty string. */ +#include "filename.h" char * last_component (char const *name) { char const *base = name + FILE_SYSTEM_PREFIX_LEN (name); char const *p; - bool saw_slash = false; + bool last_was_slash = false; while (ISSLASH (*base)) base++; @@ -39,21 +39,17 @@ last_component (char const *name) for (p = base; *p; p++) { if (ISSLASH (*p)) - saw_slash = true; - else if (saw_slash) + last_was_slash = true; + else if (last_was_slash) { base = p; - saw_slash = false; + last_was_slash = false; } } return (char *) base; } -/* Return the length of the basename NAME. Typically NAME is the - value returned by base_name or last_component. Act like strlen - (NAME), except omit all trailing slashes. */ - size_t base_len (char const *name) { diff --git a/contrib/tools/bison/lib/basename-lgpl.h b/contrib/tools/bison/lib/basename-lgpl.h new file mode 100644 index 0000000000..38070945ee --- /dev/null +++ b/contrib/tools/bison/lib/basename-lgpl.h @@ -0,0 +1,78 @@ +/* Extract the last component (base name) of a file name. + + Copyright (C) 1998, 2001, 2003-2006, 2009-2020 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _BASENAME_LGPL_H +#define _BASENAME_LGPL_H + +#include <stddef.h> + +#ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT +# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Return the address of the last file name component of FILENAME. + If FILENAME has some trailing slash(es), they are considered to be + part of the last component. + If FILENAME has no relative file name components because it is a file + system root, return the empty string. + Examples: + FILENAME RESULT + "foo.c" "foo.c" + "foo/bar.c" "bar.c" + "/foo/bar.c" "bar.c" + "foo/bar/" "bar/" + "foo/bar//" "bar//" + "/" "" + "//" "" + "" "" + The return value is a tail of the given FILENAME; do NOT free() it! */ + +/* This function was traditionally called 'basename', but we avoid this + function name because + * Various platforms have different functions in their libc. + In particular, the glibc basename(), defined in <string.h>, does + not consider trailing slashes to be part of the component: + FILENAME RESULT + "foo/bar/" "" + "foo/bar//" "" + * The 'basename' command eliminates trailing slashes and for a root + produces a non-empty result: + FILENAME RESULT + "foo/bar/" "bar" + "foo/bar//" "bar" + "/" "/" + "//" "/" + */ +extern char *last_component (char const *filename) _GL_ATTRIBUTE_PURE; + +/* Return the length of the basename FILENAME. + Typically FILENAME is the value returned by base_name or last_component. + Act like strlen (FILENAME), except omit all trailing slashes. */ +extern size_t base_len (char const *filename) _GL_ATTRIBUTE_PURE; + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* _BASENAME_LGPL_H */ diff --git a/contrib/tools/bison/lib/binary-io.h b/contrib/tools/bison/lib/binary-io.h index 05f7986b5f..1cdf92517e 100644 --- a/contrib/tools/bison/lib/binary-io.h +++ b/contrib/tools/bison/lib/binary-io.h @@ -64,7 +64,7 @@ __gl_setmode (int fd _GL_UNUSED, int mode _GL_UNUSED) /* Set FD's mode to MODE, which should be either O_TEXT or O_BINARY. Return the old mode if successful, -1 (setting errno) on failure. Ordinarily this function would be called 'setmode', since that is - its name on MS-Windows, but it is called 'set_binary_mode' here + its old name on MS-Windows, but it is called 'set_binary_mode' here to avoid colliding with a BSD function of another name. */ #if defined __DJGPP__ || defined __EMX__ diff --git a/contrib/tools/bison/lib/bitset/list.c b/contrib/tools/bison/lib/bitset/list.c index ed975ef001..c1f3d9b153 100644 --- a/contrib/tools/bison/lib/bitset/list.c +++ b/contrib/tools/bison/lib/bitset/list.c @@ -122,7 +122,7 @@ lbitset_elt_alloc (void) # define OBSTACK_CHUNK_FREE free #endif -#if ! defined __GNUC__ || __GNUC__ < 2 +#if !(defined __GNUC__ || defined __clang__) # define __alignof__(type) 0 #endif diff --git a/contrib/tools/bison/lib/bitset/stats.c b/contrib/tools/bison/lib/bitset/stats.c index 10aa5d768d..5bd44c06a4 100644 --- a/contrib/tools/bison/lib/bitset/stats.c +++ b/contrib/tools/bison/lib/bitset/stats.c @@ -245,7 +245,7 @@ bitset_stats_read (const char *file_name) if (!file_name) file_name = BITSET_STATS_FILE; - FILE *file = fopen (file_name, "r"); + FILE *file = fopen (file_name, "re"); if (file) { if (fread (&bitset_stats_info_data, sizeof (bitset_stats_info_data), @@ -273,7 +273,7 @@ bitset_stats_write (const char *file_name) if (!file_name) file_name = BITSET_STATS_FILE; - FILE *file = fopen (file_name, "w"); + FILE *file = fopen (file_name, "we"); if (file) { if (fwrite (&bitset_stats_info_data, sizeof (bitset_stats_info_data), diff --git a/contrib/tools/bison/lib/bitset/table.c b/contrib/tools/bison/lib/bitset/table.c index 56f1a860a4..c80eebffa5 100644 --- a/contrib/tools/bison/lib/bitset/table.c +++ b/contrib/tools/bison/lib/bitset/table.c @@ -206,7 +206,7 @@ tbitset_elt_alloc (void) # define OBSTACK_CHUNK_FREE free #endif -#if ! defined __GNUC__ || __GNUC__ < 2 +#if !(defined __GNUC__ || defined __clang__) # define __alignof__(type) 0 #endif diff --git a/contrib/tools/bison/lib/c-strcasecmp.c b/contrib/tools/bison/lib/c-strcasecmp.c index 951220f3e2..f1a4b98fa5 100644 --- a/contrib/tools/bison/lib/c-strcasecmp.c +++ b/contrib/tools/bison/lib/c-strcasecmp.c @@ -52,5 +52,5 @@ c_strcasecmp (const char *s1, const char *s2) /* On machines where 'char' and 'int' are types of the same size, the difference of two 'unsigned char' values - including the sign bit - doesn't fit in an 'int'. */ - return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0); + return _GL_CMP (c1, c2); } diff --git a/contrib/tools/bison/lib/c-strcaseeq.h b/contrib/tools/bison/lib/c-strcaseeq.h index 304c72ea49..0f7c50a161 100644 --- a/contrib/tools/bison/lib/c-strcaseeq.h +++ b/contrib/tools/bison/lib/c-strcaseeq.h @@ -27,7 +27,7 @@ /* Help GCC to generate good code for string comparisons with immediate strings. */ -#if defined (__GNUC__) && defined (__OPTIMIZE__) +#if (defined __GNUC__ || defined __clang__) && defined __OPTIMIZE__ /* Case insensitive comparison of ASCII characters. */ # if C_CTYPE_ASCII diff --git a/contrib/tools/bison/lib/c-strncasecmp.c b/contrib/tools/bison/lib/c-strncasecmp.c index 9ad49191b7..1d6e1411a6 100644 --- a/contrib/tools/bison/lib/c-strncasecmp.c +++ b/contrib/tools/bison/lib/c-strncasecmp.c @@ -52,5 +52,5 @@ c_strncasecmp (const char *s1, const char *s2, size_t n) /* On machines where 'char' and 'int' are types of the same size, the difference of two 'unsigned char' values - including the sign bit - doesn't fit in an 'int'. */ - return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0); + return _GL_CMP (c1, c2); } diff --git a/contrib/tools/bison/lib/careadlinkat.c b/contrib/tools/bison/lib/careadlinkat.c index 1aa04363da..e43aa42d5c 100644 --- a/contrib/tools/bison/lib/careadlinkat.c +++ b/contrib/tools/bison/lib/careadlinkat.c @@ -38,66 +38,41 @@ #include "allocator.h" -/* Assuming the current directory is FD, get the symbolic link value - of FILENAME as a null-terminated string and put it into a buffer. - If FD is AT_FDCWD, FILENAME is interpreted relative to the current - working directory, as in openat. - - If the link is small enough to fit into BUFFER put it there. - BUFFER's size is BUFFER_SIZE, and BUFFER can be null - if BUFFER_SIZE is zero. - - If the link is not small, put it into a dynamically allocated - buffer managed by ALLOC. It is the caller's responsibility to free - the returned value if it is nonnull and is not BUFFER. A null - ALLOC stands for the standard allocator. - - The PREADLINKAT function specifies how to read links. It operates - like POSIX readlinkat() - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/readlink.html> - but can assume that its first argument is the same as FD. - - If successful, return the buffer address; otherwise return NULL and - set errno. */ - -char * -careadlinkat (int fd, char const *filename, +enum { STACK_BUF_SIZE = 1024 }; + +/* Act like careadlinkat (see below), with an additional argument + STACK_BUF that can be used as temporary storage. + + If GCC_LINT is defined, do not inline this function with GCC 10.1 + and later, to avoid creating a pointer to the stack that GCC + -Wreturn-local-addr incorrectly complains about. See: + https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93644 + Although the noinline attribute can hurt performance a bit, no better way + to pacify GCC is known; even an explicit #pragma does not pacify GCC. + When the GCC bug is fixed this workaround should be limited to the + broken GCC versions. */ +#if (defined GCC_LINT || defined lint) && _GL_GNUC_PREREQ (10, 1) +__attribute__ ((__noinline__)) +#endif +static char * +readlink_stk (int fd, char const *filename, char *buffer, size_t buffer_size, struct allocator const *alloc, - ssize_t (*preadlinkat) (int, char const *, char *, size_t)) + ssize_t (*preadlinkat) (int, char const *, char *, size_t), + char stack_buf[STACK_BUF_SIZE]) { char *buf; size_t buf_size; size_t buf_size_max = SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX; - char stack_buf[1024]; - -#if (defined GCC_LINT || defined lint) && _GL_GNUC_PREREQ (10, 1) - /* Pacify preadlinkat without creating a pointer to the stack - that a broken gcc -Wreturn-local-addr would cry wolf about. See: - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95044 - This workaround differs from the mainline code, but - no other way to pacify GCC 10.1.0 is known; even an explicit - #pragma does not pacify GCC. When the GCC bug is fixed this - workaround should be limited to the broken GCC versions. */ -# define WORK_AROUND_GCC_BUG_95044 -#endif if (! alloc) alloc = &stdlib_allocator; if (!buffer) { -#ifdef WORK_AROUND_GCC_BUG_95044 - buffer = alloc->allocate (sizeof stack_buf); -#else - /* Allocate the initial buffer on the stack. This way, in the - common case of a symlink of small size, we get away with a - single small malloc() instead of a big malloc() followed by a - shrinking realloc(). */ buffer = stack_buf; -#endif - buffer_size = sizeof stack_buf; + buffer_size = STACK_BUF_SIZE; } buf = buffer; @@ -172,3 +147,44 @@ careadlinkat (int fd, char const *filename, errno = ENOMEM; return NULL; } + + +/* Assuming the current directory is FD, get the symbolic link value + of FILENAME as a null-terminated string and put it into a buffer. + If FD is AT_FDCWD, FILENAME is interpreted relative to the current + working directory, as in openat. + + If the link is small enough to fit into BUFFER put it there. + BUFFER's size is BUFFER_SIZE, and BUFFER can be null + if BUFFER_SIZE is zero. + + If the link is not small, put it into a dynamically allocated + buffer managed by ALLOC. It is the caller's responsibility to free + the returned value if it is nonnull and is not BUFFER. A null + ALLOC stands for the standard allocator. + + The PREADLINKAT function specifies how to read links. It operates + like POSIX readlinkat() + <https://pubs.opengroup.org/onlinepubs/9699919799/functions/readlink.html> + but can assume that its first argument is the same as FD. + + If successful, return the buffer address; otherwise return NULL and + set errno. */ + +char * +careadlinkat (int fd, char const *filename, + char *buffer, size_t buffer_size, + struct allocator const *alloc, + ssize_t (*preadlinkat) (int, char const *, char *, size_t)) +{ + /* Allocate the initial buffer on the stack. This way, in the + common case of a symlink of small size, we get away with a + single small malloc instead of a big malloc followed by a + shrinking realloc. + + If GCC -Wreturn-local-addr warns about this buffer, the warning + is bogus; see readlink_stk. */ + char stack_buf[STACK_BUF_SIZE]; + return readlink_stk (fd, filename, buffer, buffer_size, alloc, + preadlinkat, stack_buf); +} diff --git a/contrib/tools/bison/lib/close.c b/contrib/tools/bison/lib/close.c index 0c8780dc24..32503c0313 100644 --- a/contrib/tools/bison/lib/close.c +++ b/contrib/tools/bison/lib/close.c @@ -28,7 +28,8 @@ #undef close -#if HAVE_MSVC_INVALID_PARAMETER_HANDLER +#if defined _WIN32 && !defined __CYGWIN__ +# if HAVE_MSVC_INVALID_PARAMETER_HANDLER static int close_nothrow (int fd) { @@ -36,7 +37,7 @@ close_nothrow (int fd) TRY_MSVC_INVAL { - result = close (fd); + result = _close (fd); } CATCH_MSVC_INVAL { @@ -47,6 +48,9 @@ close_nothrow (int fd) return result; } +# else +# define close_nothrow _close +# endif #else # define close_nothrow close #endif diff --git a/contrib/tools/bison/lib/config-linux.h b/contrib/tools/bison/lib/config-linux.h index 7849bfbaea..a3bd3dc892 100644 --- a/contrib/tools/bison/lib/config-linux.h +++ b/contrib/tools/bison/lib/config-linux.h @@ -23,12 +23,7 @@ non-IEEE-754 'long double' values. */ #define CHECK_PRINTF_SAFE 1 -/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP - systems. This function is required for `alloca.c' support on those systems. - */ -/* #undef CRAY_STACKSEG_END */ - -/* Define to 1 if using `alloca.c'. */ +/* Define to 1 if using 'alloca.c'. */ /* #undef C_ALLOCA */ /* Define as the bit index in the word where to find bit 0 of the exponent of @@ -77,9 +72,6 @@ and handles trailing slash correctly. */ #define FUNC_REALPATH_WORKS 1 -/* Define if gettimeofday clobbers the localtime buffer. */ -/* #undef GETTIMEOFDAY_CLOBBERS_LOCALTIME */ - /* Define this to 'void' or 'struct timezone' to match the system's declaration of the second argument to gettimeofday. */ #define GETTIMEOFDAY_TIMEZONE void @@ -101,6 +93,10 @@ #define GNULIB_FD_SAFER_FLAG 1 /* Define to a C preprocessor expression that evaluates to 1 or 0, depending + whether the gnulib module fopen-gnu shall be considered present. */ +#define GNULIB_FOPEN_GNU 1 + +/* Define to a C preprocessor expression that evaluates to 1 or 0, depending whether the gnulib module fopen-safer shall be considered present. */ #define GNULIB_FOPEN_SAFER 1 @@ -343,6 +339,9 @@ /* Define to 1 when the gnulib module stpcpy should be tested. */ #define GNULIB_TEST_STPCPY 1 +/* Define to 1 when the gnulib module stpncpy should be tested. */ +#define GNULIB_TEST_STPNCPY 1 + /* Define to 1 when the gnulib module strchrnul should be tested. */ /* #undef GNULIB_TEST_STRCHRNUL */ @@ -388,6 +387,22 @@ /* Define to 1 when the gnulib module wcwidth should be tested. */ #define GNULIB_TEST_WCWIDTH 1 +/* Define to a C preprocessor expression that evaluates to 1 or 0, depending + whether the gnulib module unistr/u8-mbtoucr shall be considered present. */ +#define GNULIB_UNISTR_U8_MBTOUCR 1 + +/* Define to a C preprocessor expression that evaluates to 1 or 0, depending + whether the gnulib module unistr/u8-uctomb shall be considered present. */ +#define GNULIB_UNISTR_U8_UCTOMB 1 + +/* Define to a C preprocessor expression that evaluates to 1 or 0, depending + whether the gnulib module xalloc shall be considered present. */ +#define GNULIB_XALLOC 1 + +/* Define to a C preprocessor expression that evaluates to 1 or 0, depending + whether the gnulib module xalloc-die shall be considered present. */ +#define GNULIB_XALLOC_DIE 1 + /* Define if your system defines TIOCGWINSZ in sys/ioctl.h. */ #define GWINSZ_IN_SYS_IOCTL 1 @@ -395,8 +410,7 @@ may be supplied by this distribution. */ #define HAVE_ALLOCA 1 -/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix). - */ +/* Define to 1 if <alloca.h> works. */ #define HAVE_ALLOCA_H 1 /* Define if you have an arithmetic hrtime_t type. */ @@ -573,6 +587,10 @@ don't. */ #define HAVE_DECL_SNPRINTF 1 +/* Define to 1 if you have the declaration of `stpncpy', and to 0 if you + don't. */ +#define HAVE_DECL_STPNCPY 1 + /* Define to 1 if you have the declaration of `strdup', and to 0 if you don't. */ #define HAVE_DECL_STRDUP 1 @@ -617,9 +635,6 @@ don't. */ #define HAVE_DECL___FPENDING 1 -/* Define to 1 if you have the 'dup2' function. */ -#define HAVE_DUP2 1 - /* Define if you have the declaration of environ. */ #define HAVE_ENVIRON_DECL 1 @@ -675,7 +690,15 @@ #define HAVE_GETTIMEOFDAY 1 /* Define if you have the iconv() function and it works. */ -/* #undef HAVE_ICONV */ +#define HAVE_ICONV 1 + +/* Define to 1 if you have the <iconv.h> header file. */ +#define HAVE_ICONV_H 1 + +/* Define to 1 if the compiler supports one of the keywords 'inline', + '__inline__', '__inline' and effectively inlines functions marked as such. + */ +#define HAVE_INLINE 1 /* Define if you have the 'intmax_t' type in <stdint.h> or <inttypes.h>. */ #define HAVE_INTMAX_T 1 @@ -761,9 +784,6 @@ /* Define to 1 if <wchar.h> declares mbstate_t. */ #define HAVE_MBSTATE_T 1 -/* Define to 1 if you have the <memory.h> header file. */ -#define HAVE_MEMORY_H 1 - /* Define to 1 if you have the `microuptime' function. */ /* #undef HAVE_MICROUPTIME */ @@ -862,6 +882,9 @@ /* Define to 1 if you have the `sched_setscheduler' function. */ /* #undef HAVE_SCHED_SETSCHEDULER */ +/* Define to 1 if you have the <sdkddkver.h> header file. */ +/* #undef HAVE_SDKDDKVER_H */ + /* Define to 1 if you have the <search.h> header file. */ #define HAVE_SEARCH_H 1 @@ -915,6 +938,10 @@ buffer had been large enough. */ #define HAVE_SNPRINTF_RETVAL_C99 1 +/* Define if the string produced by the snprintf function is always NUL + terminated. */ +#define HAVE_SNPRINTF_TRUNCATION_C99 1 + /* Define to 1 if you have the <spawn.h> header file. */ #define HAVE_SPAWN_H 1 @@ -928,18 +955,21 @@ /* Define to 1 if you have the <stdio_ext.h> header file. */ #define HAVE_STDIO_EXT_H 1 +/* Define to 1 if you have the <stdio.h> header file. */ +#define HAVE_STDIO_H 1 + /* Define to 1 if you have the <stdlib.h> header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `stpcpy' function. */ #define HAVE_STPCPY 1 +/* Define if you have the stpncpy() function and it works. */ +#define HAVE_STPNCPY 1 + /* Define to 1 if you have the `strchrnul' function. */ /* #undef HAVE_STRCHRNUL */ -/* Define to 1 if you have the `strdup' function. */ -#define HAVE_STRDUP 1 - /* Define to 1 if you have the `strerror_r' function. */ #define HAVE_STRERROR_R 1 @@ -997,6 +1027,9 @@ /* Define to 1 if you have the <sys/inttypes.h> header file. */ /* #undef HAVE_SYS_INTTYPES_H */ +/* Define to 1 if you have the <sys/ioctl.h> header file. */ +#define HAVE_SYS_IOCTL_H 1 + /* Define to 1 if you have the <sys/mman.h> header file. */ #define HAVE_SYS_MMAN_H 1 @@ -1006,6 +1039,9 @@ /* Define to 1 if you have the <sys/resource.h> header file. */ #define HAVE_SYS_RESOURCE_H 1 +/* Define to 1 if you have the <sys/single_threaded.h> header file. */ +#define HAVE_SYS_SINGLE_THREADED_H 1 + /* Define to 1 if you have the <sys/socket.h> header file. */ #define HAVE_SYS_SOCKET_H 1 @@ -1027,6 +1063,9 @@ /* Define to 1 if you have the `tcdrain' function. */ #define HAVE_TCDRAIN 1 +/* Define to 1 if you have the <termios.h> header file. */ +#define HAVE_TERMIOS_H 1 + /* Define to 1 if you have the `thrd_create' function. */ /* #undef HAVE_THRD_CREATE */ @@ -1119,6 +1158,16 @@ /* Define to 1 if you have the `_set_invalid_parameter_handler' function. */ /* #undef HAVE__SET_INVALID_PARAMETER_HANDLER */ +/* Define to 1 if the compiler supports __builtin_expect, + and to 2 if <builtins.h> does. */ +#define HAVE___BUILTIN_EXPECT 1 +#ifndef HAVE___BUILTIN_EXPECT +# define __builtin_expect(e, c) (e) +#elif HAVE___BUILTIN_EXPECT == 2 +# include <builtins.h> +#endif + + /* Define to 1 if you have the `__fseterr' function. */ /* #undef HAVE___FSETERR */ @@ -1128,8 +1177,15 @@ /* Define to 1 if you have the `__xpg_strerror_r' function. */ #define HAVE___XPG_STRERROR_R 1 +/* Define as const if the declaration of iconv() needs const. */ +#define ICONV_CONST + +/* Define to a symbolic name denoting the flavor of iconv_open() + implementation. */ +/* #undef ICONV_FLAVOR */ + /* Define to the value of ${prefix}, as a string. */ -#define INSTALLPREFIX "/var/empty/bison-3.6.4" +#define INSTALLPREFIX "/var/empty/bison-3.7.6" /* Define as the bit index in the word where to find bit 0 of the exponent of 'long double'. */ @@ -1191,6 +1247,9 @@ #endif +/* Define to 1 on musl libc. */ +/* #undef MUSL_LIBC */ + /* Define to 1 if assertions should be disabled. */ /* #undef NDEBUG */ @@ -1252,13 +1311,13 @@ #define PACKAGE_BUGREPORT "bug-bison@gnu.org" /* The copyright year for this package */ -#define PACKAGE_COPYRIGHT_YEAR 2020 +#define PACKAGE_COPYRIGHT_YEAR 2021 /* Define to the full name of this package. */ #define PACKAGE_NAME "GNU Bison" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "GNU Bison 3.6.4" +#define PACKAGE_STRING "GNU Bison 3.7.6" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "bison" @@ -1267,10 +1326,7 @@ #define PACKAGE_URL "https://www.gnu.org/software/bison/" /* Define to the version of this package. */ -#define PACKAGE_VERSION "3.6.4" - -/* Define if <inttypes.h> exists and defines unusable PRI* macros. */ -/* #undef PRI_MACROS_BROKEN */ +#define PACKAGE_VERSION "3.7.6" /* Define to the type that is the result of default argument promotions of type mode_t. */ @@ -1369,7 +1425,9 @@ /* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */ /* #undef STAT_MACROS_BROKEN */ -/* Define to 1 if you have the ANSI C header files. */ +/* Define to 1 if all of the C90 standard headers exist (not just the ones + required in a freestanding environment). This macro is provided for + backward compatibility; new code need not use it. */ #define STDC_HEADERS 1 /* Define to 1 if strerror_r returns char *. */ @@ -1482,7 +1540,7 @@ /* #undef USE_WINDOWS_THREADS */ /* Version number of package */ -#define VERSION "3.6.4" +#define VERSION "3.7.6" /* Define to 1 if unsetenv returns void instead of int. */ /* #undef VOID_UNSETENV */ @@ -1561,7 +1619,7 @@ ? 6000000 <= __apple_build_version__ \ : 3 < __clang_major__ + (5 <= __clang_minor__)))) /* _Noreturn works as-is. */ -# elif _GL_GNUC_PREREQ (2, 8) || 0x5110 <= __SUNPRO_C +# elif _GL_GNUC_PREREQ (2, 8) || defined __clang__ || 0x5110 <= __SUNPRO_C # define _Noreturn __attribute__ ((__noreturn__)) # elif 1200 <= (defined _MSC_VER ? _MSC_VER : 0) # define _Noreturn __declspec (noreturn) @@ -1629,6 +1687,7 @@ # define _GL_ATTR_cold _GL_GNUC_PREREQ (4, 3) # define _GL_ATTR_const _GL_GNUC_PREREQ (2, 95) # define _GL_ATTR_deprecated _GL_GNUC_PREREQ (3, 1) +# define _GL_ATTR_diagnose_if 0 # define _GL_ATTR_error _GL_GNUC_PREREQ (4, 3) # define _GL_ATTR_externally_visible _GL_GNUC_PREREQ (4, 1) # define _GL_ATTR_fallthrough _GL_GNUC_PREREQ (7, 0) @@ -1672,9 +1731,14 @@ #endif /* Avoid __attribute__ ((cold)) on MinGW; see thread starting at - <https://lists.gnu.org/r/emacs-devel/2019-04/msg01152.html>. */ + <https://lists.gnu.org/r/emacs-devel/2019-04/msg01152.html>. + Also, Oracle Studio 12.6 requires 'cold' not '__cold__'. */ #if _GL_HAS_ATTRIBUTE (cold) && !defined __MINGW32__ -# define _GL_ATTRIBUTE_COLD __attribute__ ((__cold__)) +# ifndef __SUNPRO_C +# define _GL_ATTRIBUTE_COLD __attribute__ ((__cold__)) +# else +# define _GL_ATTRIBUTE_COLD __attribute__ ((cold)) +# endif #else # define _GL_ATTRIBUTE_COLD #endif @@ -1696,6 +1760,9 @@ #if _GL_HAS_ATTRIBUTE (error) # define _GL_ATTRIBUTE_ERROR(msg) __attribute__ ((__error__ (msg))) # define _GL_ATTRIBUTE_WARNING(msg) __attribute__ ((__warning__ (msg))) +#elif _GL_HAS_ATTRIBUTE (diagnose_if) +# define _GL_ATTRIBUTE_ERROR(msg) __attribute__ ((__diagnose_if__ (1, msg, "error"))) +# define _GL_ATTRIBUTE_WARNING(msg) __attribute__ ((__diagnose_if__ (1, msg, "warning"))) #else # define _GL_ATTRIBUTE_ERROR(msg) # define _GL_ATTRIBUTE_WARNING(msg) @@ -1728,7 +1795,8 @@ # define _GL_ATTRIBUTE_LEAF #endif -#if _GL_HAS_ATTRIBUTE (may_alias) +/* Oracle Studio 12.6 mishandles may_alias despite __has_attribute OK. */ +#if _GL_HAS_ATTRIBUTE (may_alias) && !defined __SUNPRO_C # define _GL_ATTRIBUTE_MAY_ALIAS __attribute__ ((__may_alias__)) #else # define _GL_ATTRIBUTE_MAY_ALIAS @@ -1947,13 +2015,29 @@ /* Define to a type if <wchar.h> does not define. */ /* #undef mbstate_t */ +/* _GL_CMP (n1, n2) performs a three-valued comparison on n1 vs. n2, where + n1 and n2 are expressions without side effects, that evaluate to real + numbers (excluding NaN). + It returns + 1 if n1 > n2 + 0 if n1 == n2 + -1 if n1 < n2 + The naïve code (n1 > n2 ? 1 : n1 < n2 ? -1 : 0) produces a conditional + jump with nearly all GCC versions up to GCC 10. + This variant (n1 < n2 ? -1 : n1 > n2) produces a conditional with many + GCC versions up to GCC 9. + The better code (n1 > n2) - (n1 < n2) from Hacker's Delight § 2-9 + avoids conditional jumps in all GCC versions >= 3.4. */ +#define _GL_CMP(n1, n2) (((n1) > (n2)) - ((n1) < (n2))) + + /* Define to `int' if <sys/types.h> does not define. */ /* #undef mode_t */ /* Define to the type of st_nlink in struct stat, or a supertype. */ /* #undef nlink_t */ -/* Define to `int' if <sys/types.h> does not define. */ +/* Define as a signed integer type capable of holding a process identifier. */ /* #undef pid_t */ /* Define as the type of the result of subtracting two pointers, if the system @@ -1988,4 +2072,5 @@ /* Define to `int' if <sys/types.h> doesn't define. */ /* #undef uid_t */ #undef HAVE_THREADS_H +#undef HAVE_SYS_SINGLE_THREADED_H #define _GL_ATTRIBUTE_FORMAT_PRINTF(...) diff --git a/contrib/tools/bison/lib/config-win.h b/contrib/tools/bison/lib/config-win.h index 69bab546f4..9e445192ea 100644 --- a/contrib/tools/bison/lib/config-win.h +++ b/contrib/tools/bison/lib/config-win.h @@ -1226,7 +1226,7 @@ char *strsignal (int signum); /* #undef PACKAGE_PACKAGER_VERSION */ /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "GNU Bison 3.6.4" +#define PACKAGE_STRING "GNU Bison 3.7.6" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "m4" @@ -1235,7 +1235,7 @@ char *strsignal (int signum); #define PACKAGE_URL "http://www.gnu.org/software/m4/" /* Define to the version of this package. */ -#define PACKAGE_VERSION "3.6.4" +#define PACKAGE_VERSION "3.7.6" /* Define if <inttypes.h> exists and defines unusable PRI* macros. */ /* #undef PRI_MACROS_BROKEN */ @@ -1398,7 +1398,7 @@ char *strsignal (int signum); /* #undef USE_WINDOWS_THREADS */ /* Version number of package */ -#define VERSION "3.6.4" +#define VERSION "3.7.6" /* Define to 1 if unsetenv returns void instead of int. */ /* #undef VOID_UNSETENV */ @@ -1707,6 +1707,7 @@ char *strsignal (int signum); #define _GL_ASYNC_SAFE #define _GL_ATTRIBUTE_ALLOC_SIZE(...) +#define _GL_ATTRIBUTE_DEPRECATED #define _GL_ATTRIBUTE_FALLTHROUGH #define _GL_ATTRIBUTE_FORMAT(...) #define _GL_ATTRIBUTE_FORMAT_PRINTF(...) @@ -1718,3 +1719,6 @@ char *strsignal (int signum); #define HAVE_DECL___ARGV 1 #define HAVE_ISNANL_IN_LIBC 1 #define HAVE_ISNAND_IN_LIBC 1 + +#define GNULIB_XALLOC 1 +#define GNULIB_XALLOC_DIE 1 diff --git a/contrib/tools/bison/lib/configmake-linux.h b/contrib/tools/bison/lib/configmake-linux.h index ff9df1240f..cf0f489fec 100644 --- a/contrib/tools/bison/lib/configmake-linux.h +++ b/contrib/tools/bison/lib/configmake-linux.h @@ -2,30 +2,30 @@ #if HAVE_WINSOCK2_H # include <winsock2.h> /* avoid mingw pollution on DATADIR */ #endif -#define PREFIX "/var/empty/bison-3.6.4" -#define EXEC_PREFIX "/var/empty/bison-3.6.4" -#define BINDIR "/var/empty/bison-3.6.4/bin" -#define SBINDIR "/var/empty/bison-3.6.4/sbin" -#define LIBEXECDIR "/var/empty/bison-3.6.4/libexec" -#define DATAROOTDIR "/var/empty/bison-3.6.4/share" -#define DATADIR "/var/empty/bison-3.6.4/share" -#define SYSCONFDIR "/var/empty/bison-3.6.4/etc" -#define SHAREDSTATEDIR "/var/empty/bison-3.6.4/com" -#define LOCALSTATEDIR "/var/empty/bison-3.6.4/var" -#define RUNSTATEDIR "/var/empty/bison-3.6.4/var/run" -#define INCLUDEDIR "/var/empty/bison-3.6.4/include" +#define PREFIX "/var/empty/bison-3.7.6" +#define EXEC_PREFIX "/var/empty/bison-3.7.6" +#define BINDIR "/var/empty/bison-3.7.6/bin" +#define SBINDIR "/var/empty/bison-3.7.6/sbin" +#define LIBEXECDIR "/var/empty/bison-3.7.6/libexec" +#define DATAROOTDIR "/var/empty/bison-3.7.6/share" +#define DATADIR "/var/empty/bison-3.7.6/share" +#define SYSCONFDIR "/var/empty/bison-3.7.6/etc" +#define SHAREDSTATEDIR "/var/empty/bison-3.7.6/com" +#define LOCALSTATEDIR "/var/empty/bison-3.7.6/var" +#define RUNSTATEDIR "/var/empty/bison-3.7.6/var/run" +#define INCLUDEDIR "/var/empty/bison-3.7.6/include" #define OLDINCLUDEDIR "/usr/include" -#define DOCDIR "/var/empty/bison-3.6.4/share/doc/bison" -#define INFODIR "/var/empty/bison-3.6.4/share/info" -#define HTMLDIR "/var/empty/bison-3.6.4/share/doc/bison" -#define DVIDIR "/var/empty/bison-3.6.4/share/doc/bison" -#define PDFDIR "/var/empty/bison-3.6.4/share/doc/bison" -#define PSDIR "/var/empty/bison-3.6.4/share/doc/bison" -#define LIBDIR "/var/empty/bison-3.6.4/lib" -#define LISPDIR "/var/empty/bison-3.6.4/share/emacs/site-lisp" -#define LOCALEDIR "/var/empty/bison-3.6.4/share/locale" -#define MANDIR "/var/empty/bison-3.6.4/share/man" -#define PKGDATADIR "/var/empty/bison-3.6.4/share/bison" -#define PKGINCLUDEDIR "/var/empty/bison-3.6.4/include/bison" -#define PKGLIBDIR "/var/empty/bison-3.6.4/lib/bison" -#define PKGLIBEXECDIR "/var/empty/bison-3.6.4/libexec/bison" +#define DOCDIR "/var/empty/bison-3.7.6/share/doc/bison" +#define INFODIR "/var/empty/bison-3.7.6/share/info" +#define HTMLDIR "/var/empty/bison-3.7.6/share/doc/bison" +#define DVIDIR "/var/empty/bison-3.7.6/share/doc/bison" +#define PDFDIR "/var/empty/bison-3.7.6/share/doc/bison" +#define PSDIR "/var/empty/bison-3.7.6/share/doc/bison" +#define LIBDIR "/var/empty/bison-3.7.6/lib" +#define LISPDIR "/var/empty/bison-3.7.6/share/emacs/site-lisp" +#define LOCALEDIR "/var/empty/bison-3.7.6/share/locale" +#define MANDIR "/var/empty/bison-3.7.6/share/man" +#define PKGDATADIR "/var/empty/bison-3.7.6/share/bison" +#define PKGINCLUDEDIR "/var/empty/bison-3.7.6/include/bison" +#define PKGLIBDIR "/var/empty/bison-3.7.6/lib/bison" +#define PKGLIBEXECDIR "/var/empty/bison-3.7.6/libexec/bison" diff --git a/contrib/tools/bison/lib/diffseq.h b/contrib/tools/bison/lib/diffseq.h index c89363ac9e..26e10bdd04 100644 --- a/contrib/tools/bison/lib/diffseq.h +++ b/contrib/tools/bison/lib/diffseq.h @@ -51,10 +51,14 @@ EXTRA_CONTEXT_FIELDS Declarations of fields for 'struct context'. NOTE_DELETE(ctxt, xoff) Record the removal of the object xvec[xoff]. NOTE_INSERT(ctxt, yoff) Record the insertion of the object yvec[yoff]. + NOTE_ORDERED (Optional) A boolean expression saying that + NOTE_DELETE and NOTE_INSERT calls must be + issued in offset order. EARLY_ABORT(ctxt) (Optional) A boolean expression that triggers an early abort of the computation. USE_HEURISTIC (Optional) Define if you want to support the heuristic for large vectors. + It is also possible to use this file with abstract arrays. In this case, xvec and yvec are not represented in memory. They only exist conceptually. In this case, the list of defines above is amended as follows: @@ -63,6 +67,7 @@ XVECREF_YVECREF_EQUAL(ctxt, xoff, yoff) A three-argument macro: References xvec[xoff] and yvec[yoff] and tests these elements for equality. + Before including this file, you also need to include: #include <limits.h> #include <stdbool.h> @@ -78,6 +83,10 @@ # define EARLY_ABORT(ctxt) false #endif +#ifndef NOTE_ORDERED +# define NOTE_ORDERED false +#endif + /* Use this to suppress gcc's "...may be used before initialized" warnings. Beware: The Code argument must not contain commas. */ #ifndef IF_LINT @@ -88,15 +97,6 @@ # endif #endif -/* As above, but when Code must contain one comma. */ -#ifndef IF_LINT2 -# if defined GCC_LINT || defined lint -# define IF_LINT2(Code1, Code2) Code1, Code2 -# else -# define IF_LINT2(Code1, Code2) /* empty */ -# endif -#endif - /* * Context of comparison operation. */ @@ -468,49 +468,89 @@ compareseq (OFFSET xoff, OFFSET xlim, OFFSET yoff, OFFSET ylim, #define XREF_YREF_EQUAL(x,y) XVECREF_YVECREF_EQUAL (ctxt, x, y) #endif - /* Slide down the bottom initial diagonal. */ - while (xoff < xlim && yoff < ylim && XREF_YREF_EQUAL (xoff, yoff)) + while (true) { - xoff++; - yoff++; - } + /* Slide down the bottom initial diagonal. */ + while (xoff < xlim && yoff < ylim && XREF_YREF_EQUAL (xoff, yoff)) + { + xoff++; + yoff++; + } - /* Slide up the top initial diagonal. */ - while (xoff < xlim && yoff < ylim && XREF_YREF_EQUAL (xlim - 1, ylim - 1)) - { - xlim--; - ylim--; - } + /* Slide up the top initial diagonal. */ + while (xoff < xlim && yoff < ylim && XREF_YREF_EQUAL (xlim - 1, ylim - 1)) + { + xlim--; + ylim--; + } - /* Handle simple cases. */ - if (xoff == xlim) - while (yoff < ylim) - { - NOTE_INSERT (ctxt, yoff); - if (EARLY_ABORT (ctxt)) - return true; - yoff++; - } - else if (yoff == ylim) - while (xoff < xlim) - { - NOTE_DELETE (ctxt, xoff); - if (EARLY_ABORT (ctxt)) - return true; - xoff++; - } - else - { - struct partition part IF_LINT2 (= { .xmid = 0, .ymid = 0 }); + /* Handle simple cases. */ + if (xoff == xlim) + { + while (yoff < ylim) + { + NOTE_INSERT (ctxt, yoff); + if (EARLY_ABORT (ctxt)) + return true; + yoff++; + } + break; + } + if (yoff == ylim) + { + while (xoff < xlim) + { + NOTE_DELETE (ctxt, xoff); + if (EARLY_ABORT (ctxt)) + return true; + xoff++; + } + break; + } + + struct partition part; /* Find a point of correspondence in the middle of the vectors. */ diag (xoff, xlim, yoff, ylim, find_minimal, &part, ctxt); /* Use the partitions to split this problem into subproblems. */ - if (compareseq (xoff, part.xmid, yoff, part.ymid, part.lo_minimal, ctxt)) - return true; - if (compareseq (part.xmid, xlim, part.ymid, ylim, part.hi_minimal, ctxt)) - return true; + OFFSET xoff1, xlim1, yoff1, ylim1, xoff2, xlim2, yoff2, ylim2; + bool find_minimal1, find_minimal2; + if (!NOTE_ORDERED + && ((xlim + ylim) - (part.xmid + part.ymid) + < (part.xmid + part.ymid) - (xoff + yoff))) + { + /* The second problem is smaller and the caller doesn't + care about order, so do the second problem first to + lessen recursion. */ + xoff1 = part.xmid; xlim1 = xlim; + yoff1 = part.ymid; ylim1 = ylim; + find_minimal1 = part.hi_minimal; + + xoff2 = xoff; xlim2 = part.xmid; + yoff2 = yoff; ylim2 = part.ymid; + find_minimal2 = part.lo_minimal; + } + else + { + xoff1 = xoff; xlim1 = part.xmid; + yoff1 = yoff; ylim1 = part.ymid; + find_minimal1 = part.lo_minimal; + + xoff2 = part.xmid; xlim2 = xlim; + yoff2 = part.ymid; ylim2 = ylim; + find_minimal2 = part.hi_minimal; + } + + /* Recurse to do one subproblem. */ + bool early = compareseq (xoff1, xlim1, yoff1, ylim1, find_minimal1, ctxt); + if (early) + return early; + + /* Iterate to do the other subproblem. */ + xoff = xoff2; xlim = xlim2; + yoff = yoff2; ylim = ylim2; + find_minimal = find_minimal2; } return false; diff --git a/contrib/tools/bison/lib/dirname.h b/contrib/tools/bison/lib/dirname.h index 5379e8e3d2..b2a91fd535 100644 --- a/contrib/tools/bison/lib/dirname.h +++ b/contrib/tools/bison/lib/dirname.h @@ -22,15 +22,12 @@ # include <stdbool.h> # include <stddef.h> # include "filename.h" +# include "basename-lgpl.h" # ifndef DIRECTORY_SEPARATOR # define DIRECTORY_SEPARATOR '/' # endif -# ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT -# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0 -# endif - #ifdef __cplusplus extern "C" { #endif @@ -41,9 +38,7 @@ char *dir_name (char const *file); # endif char *mdir_name (char const *file); -size_t base_len (char const *file) _GL_ATTRIBUTE_PURE; size_t dir_len (char const *file) _GL_ATTRIBUTE_PURE; -char *last_component (char const *file) _GL_ATTRIBUTE_PURE; bool strip_trailing_slashes (char *file); diff --git a/contrib/tools/bison/lib/dup2.c b/contrib/tools/bison/lib/dup2.c index 410064a935..fbc41c0ceb 100644 --- a/contrib/tools/bison/lib/dup2.c +++ b/contrib/tools/bison/lib/dup2.c @@ -25,28 +25,26 @@ #include <errno.h> #include <fcntl.h> -#if HAVE_DUP2 +#undef dup2 -# undef dup2 - -# if defined _WIN32 && ! defined __CYGWIN__ +#if defined _WIN32 && ! defined __CYGWIN__ /* Get declarations of the native Windows API functions. */ -# define WIN32_LEAN_AND_MEAN -# include <windows.h> +# define WIN32_LEAN_AND_MEAN +# include <windows.h> -# if HAVE_MSVC_INVALID_PARAMETER_HANDLER -# include "msvc-inval.h" -# endif +# if HAVE_MSVC_INVALID_PARAMETER_HANDLER +# include "msvc-inval.h" +# endif /* Get _get_osfhandle. */ -# if GNULIB_MSVC_NOTHROW -# include "msvc-nothrow.h" -# else -# include <io.h> -# endif +# if GNULIB_MSVC_NOTHROW +# include "msvc-nothrow.h" +# else +# include <io.h> +# endif -# if HAVE_MSVC_INVALID_PARAMETER_HANDLER +# if HAVE_MSVC_INVALID_PARAMETER_HANDLER static int dup2_nothrow (int fd, int desired_fd) { @@ -54,7 +52,7 @@ dup2_nothrow (int fd, int desired_fd) TRY_MSVC_INVAL { - result = dup2 (fd, desired_fd); + result = _dup2 (fd, desired_fd); } CATCH_MSVC_INVAL { @@ -65,9 +63,9 @@ dup2_nothrow (int fd, int desired_fd) return result; } -# else -# define dup2_nothrow dup2 -# endif +# else +# define dup2_nothrow _dup2 +# endif static int ms_windows_dup2 (int fd, int desired_fd) @@ -103,11 +101,11 @@ ms_windows_dup2 (int fd, int desired_fd) return result; } -# define dup2 ms_windows_dup2 +# define dup2 ms_windows_dup2 -# elif defined __KLIBC__ +#elif defined __KLIBC__ -# error #include <InnoTekLIBC/backend.h> +# error #include <InnoTekLIBC/backend.h> static int klibc_dup2dirfd (int fd, int desired_fd) @@ -155,81 +153,37 @@ klibc_dup2 (int fd, int desired_fd) return dupfd; } -# define dup2 klibc_dup2 -# endif +# define dup2 klibc_dup2 +#endif int rpl_dup2 (int fd, int desired_fd) { int result; -# ifdef F_GETFL +#ifdef F_GETFL /* On Linux kernels 2.6.26-2.6.29, dup2 (fd, fd) returns -EBADF. On Cygwin 1.5.x, dup2 (1, 1) returns 0. On Cygwin 1.7.17, dup2 (1, -1) dumps core. On Cygwin 1.7.25, dup2 (1, 256) can dump core. On Haiku, dup2 (fd, fd) mistakenly clears FD_CLOEXEC. */ -# if HAVE_SETDTABLESIZE +# if HAVE_SETDTABLESIZE setdtablesize (desired_fd + 1); -# endif +# endif if (desired_fd < 0) fd = desired_fd; if (fd == desired_fd) return fcntl (fd, F_GETFL) == -1 ? -1 : fd; -# endif +#endif result = dup2 (fd, desired_fd); /* Correct an errno value on FreeBSD 6.1 and Cygwin 1.5.x. */ if (result == -1 && errno == EMFILE) errno = EBADF; -# if REPLACE_FCHDIR +#if REPLACE_FCHDIR if (fd != desired_fd && result != -1) result = _gl_register_dup (fd, result); -# endif - return result; -} - -#else /* !HAVE_DUP2 */ - -/* On older platforms, dup2 did not exist. */ - -# ifndef F_DUPFD -static int -dupfd (int fd, int desired_fd) -{ - int duplicated_fd = dup (fd); - if (duplicated_fd < 0 || duplicated_fd == desired_fd) - return duplicated_fd; - else - { - int r = dupfd (fd, desired_fd); - int e = errno; - close (duplicated_fd); - errno = e; - return r; - } -} -# endif - -int -dup2 (int fd, int desired_fd) -{ - int result = fcntl (fd, F_GETFL) < 0 ? -1 : fd; - if (result == -1 || fd == desired_fd) - return result; - close (desired_fd); -# ifdef F_DUPFD - result = fcntl (fd, F_DUPFD, desired_fd); -# if REPLACE_FCHDIR - if (0 <= result) - result = _gl_register_dup (fd, result); -# endif -# else - result = dupfd (fd, desired_fd); -# endif - if (result == -1 && (errno == EMFILE || errno == EINVAL)) - errno = EBADF; +#endif return result; } -#endif /* !HAVE_DUP2 */ diff --git a/contrib/tools/bison/lib/fatal-signal.c b/contrib/tools/bison/lib/fatal-signal.c index c8ff338041..14ecfe7a14 100644 --- a/contrib/tools/bison/lib/fatal-signal.c +++ b/contrib/tools/bison/lib/fatal-signal.c @@ -26,6 +26,8 @@ #include <signal.h> #include <unistd.h> +#include "glthread/lock.h" +#include "thread-optim.h" #include "sig-handler.h" #include "xalloc.h" @@ -85,6 +87,10 @@ static int fatal_signals[] = static void init_fatal_signals (void) { + /* This function is multithread-safe even without synchronization, because + if two threads execute it simultaneously, the fatal_signals[] array will + not change any more after the first of the threads has completed this + function. */ static bool fatal_signals_initialized = false; if (!fatal_signals_initialized) { @@ -200,11 +206,18 @@ install_handlers (void) } +/* Lock that makes at_fatal_signal multi-thread safe. */ +gl_lock_define_initialized (static, at_fatal_signal_lock) + /* Register a cleanup function to be executed when a catchable fatal signal occurs. */ void at_fatal_signal (action_t action) { + bool mt = gl_multithreaded (); + + if (mt) gl_lock_lock (at_fatal_signal_lock); + static bool cleanup_initialized = false; if (!cleanup_initialized) { @@ -233,8 +246,15 @@ at_fatal_signal (action_t action) actions = new_actions; actions_allocated = new_actions_allocated; /* Now we can free the old actions array. */ + /* No, we can't do that. If fatal_signal_handler is running in a + different thread and has already fetched the actions pointer (getting + old_actions) but not yet accessed its n-th element, that thread may + crash when accessing an element of the already freed old_actions + array. */ + #if 0 if (old_actions != static_actions) free (old_actions); + #endif } /* The two uses of 'volatile' in the types above (and ISO C 99 section 5.1.2.3.(5)) ensure that we increment the actions_count only after @@ -242,6 +262,8 @@ at_fatal_signal (action_t action) actions[actions_count]. */ actions[actions_count].action = action; actions_count++; + + if (mt) gl_lock_unlock (at_fatal_signal_lock); } @@ -251,38 +273,68 @@ at_fatal_signal (action_t action) static sigset_t fatal_signal_set; static void -init_fatal_signal_set (void) +do_init_fatal_signal_set (void) { - static bool fatal_signal_set_initialized = false; - if (!fatal_signal_set_initialized) - { - size_t i; + size_t i; - init_fatal_signals (); + init_fatal_signals (); - sigemptyset (&fatal_signal_set); - for (i = 0; i < num_fatal_signals; i++) - if (fatal_signals[i] >= 0) - sigaddset (&fatal_signal_set, fatal_signals[i]); + sigemptyset (&fatal_signal_set); + for (i = 0; i < num_fatal_signals; i++) + if (fatal_signals[i] >= 0) + sigaddset (&fatal_signal_set, fatal_signals[i]); +} - fatal_signal_set_initialized = true; - } +/* Ensure that do_init_fatal_signal_set is called once only. */ +gl_once_define(static, fatal_signal_set_once) + +static void +init_fatal_signal_set (void) +{ + gl_once (fatal_signal_set_once, do_init_fatal_signal_set); } +/* Lock and counter that allow block_fatal_signals/unblock_fatal_signals pairs + to occur in different threads and even overlap in time. */ +gl_lock_define_initialized (static, fatal_signals_block_lock) +static unsigned int fatal_signals_block_counter = 0; + /* Temporarily delay the catchable fatal signals. */ void block_fatal_signals (void) { - init_fatal_signal_set (); - sigprocmask (SIG_BLOCK, &fatal_signal_set, NULL); + bool mt = gl_multithreaded (); + + if (mt) gl_lock_lock (fatal_signals_block_lock); + + if (fatal_signals_block_counter++ == 0) + { + init_fatal_signal_set (); + sigprocmask (SIG_BLOCK, &fatal_signal_set, NULL); + } + + if (mt) gl_lock_unlock (fatal_signals_block_lock); } /* Stop delaying the catchable fatal signals. */ void unblock_fatal_signals (void) { - init_fatal_signal_set (); - sigprocmask (SIG_UNBLOCK, &fatal_signal_set, NULL); + bool mt = gl_multithreaded (); + + if (mt) gl_lock_lock (fatal_signals_block_lock); + + if (fatal_signals_block_counter == 0) + /* There are more calls to unblock_fatal_signals() than to + block_fatal_signals(). */ + abort (); + if (--fatal_signals_block_counter == 0) + { + init_fatal_signal_set (); + sigprocmask (SIG_UNBLOCK, &fatal_signal_set, NULL); + } + + if (mt) gl_lock_unlock (fatal_signals_block_lock); } @@ -301,3 +353,10 @@ get_fatal_signals (int signals[64]) return p - signals; } } + +const sigset_t * +get_fatal_signal_set (void) +{ + init_fatal_signal_set (); + return &fatal_signal_set; +} diff --git a/contrib/tools/bison/lib/fatal-signal.h b/contrib/tools/bison/lib/fatal-signal.h index 2c0154ffc3..54270fab92 100644 --- a/contrib/tools/bison/lib/fatal-signal.h +++ b/contrib/tools/bison/lib/fatal-signal.h @@ -16,6 +16,11 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ +#ifndef _FATAL_SIGNAL_H +#define _FATAL_SIGNAL_H + +#include <signal.h> + #ifdef __cplusplus extern "C" { #endif @@ -77,7 +82,13 @@ extern void unblock_fatal_signals (void); Fills signals[0..count-1] and returns count. */ extern unsigned int get_fatal_signals (int signals[64]); +/* Return the list of signals that block_fatal_signals/unblock_fatal_signals + would block or unblock. */ +extern const sigset_t * get_fatal_signal_set (void); + #ifdef __cplusplus } #endif + +#endif /* _FATAL_SIGNAL_H */ diff --git a/contrib/tools/bison/lib/fcntl.c b/contrib/tools/bison/lib/fcntl.c index cc54f62ed7..6a357cc6c4 100644 --- a/contrib/tools/bison/lib/fcntl.c +++ b/contrib/tools/bison/lib/fcntl.c @@ -70,14 +70,14 @@ dupfd (int oldfd, int newfd, int flags) return -1; } if (old_handle == INVALID_HANDLE_VALUE - || (mode = setmode (oldfd, O_BINARY)) == -1) + || (mode = _setmode (oldfd, O_BINARY)) == -1) { /* oldfd is not open, or is an unassigned standard file descriptor. */ errno = EBADF; return -1; } - setmode (oldfd, mode); + _setmode (oldfd, mode); flags |= mode; for (;;) diff --git a/contrib/tools/bison/lib/fpending.c b/contrib/tools/bison/lib/fpending.c index 802ebcba65..836a3a988b 100644 --- a/contrib/tools/bison/lib/fpending.c +++ b/contrib/tools/bison/lib/fpending.c @@ -25,7 +25,8 @@ #include "stdio-impl.h" /* This file is not used on systems that already have the __fpending function, - namely glibc >= 2.2, Solaris >= 7, Android API >= 23. */ + namely glibc >= 2.2, Solaris >= 7, UnixWare >= 7.1.4.MP4, Cygwin >= 1.7.34, + Android API >= 23. */ /* Return the number of pending (aka buffered, unflushed) bytes on the stream, FP, that is open for writing. */ @@ -39,13 +40,13 @@ __fpending (FILE *fp) /* GNU libc, BeOS, Haiku, Linux libc5 */ return fp->_IO_write_ptr - fp->_IO_write_base; #elif defined __sferror || defined __DragonFly__ || defined __ANDROID__ - /* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin, Minix 3, Android */ + /* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin < 1.7.34, Minix 3, Android */ return fp->_p - fp->_bf._base; #elif defined __EMX__ /* emx+gcc */ return fp->_ptr - fp->_buffer; #elif defined __minix /* Minix */ return fp_->_ptr - fp_->_buf; -#elif defined _IOERR /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, mingw, MSVC, NonStop Kernel, OpenVMS */ +#elif defined _IOERR /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, UnixWare, mingw, MSVC, NonStop Kernel, OpenVMS */ return (fp_->_ptr ? fp_->_ptr - fp_->_base : 0); #elif defined __UCLIBC__ /* uClibc */ return (fp->__modeflags & __FLAG_WRITING ? fp->__bufpos - fp->__bufstart : 0); diff --git a/contrib/tools/bison/lib/fpucw.h b/contrib/tools/bison/lib/fpucw.h index 1c6edf6b76..8ef5420223 100644 --- a/contrib/tools/bison/lib/fpucw.h +++ b/contrib/tools/bison/lib/fpucw.h @@ -61,8 +61,8 @@ 'long double' safe operation precision */ -/* Inline assembler like this works only with GNU C. */ -#if (defined __i386__ || defined __x86_64__) && defined __GNUC__ +/* Inline assembler like this works only with GNU C and clang. */ +#if (defined __i386__ || defined __x86_64__) && (defined __GNUC__ || defined __clang__) typedef unsigned short fpucw_t; /* glibc calls this fpu_control_t */ diff --git a/contrib/tools/bison/lib/fseterr.c b/contrib/tools/bison/lib/fseterr.c index 8f32b7e5af..7cf267fa8e 100644 --- a/contrib/tools/bison/lib/fseterr.c +++ b/contrib/tools/bison/lib/fseterr.c @@ -42,7 +42,7 @@ fseterr (FILE *fp) fp->_flags |= _IOERR; #elif defined __minix /* Minix */ fp->_flags |= _IOERR; -#elif defined _IOERR /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, mingw, MSVC, NonStop Kernel, OpenVMS */ +#elif defined _IOERR /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, UnixWare, mingw, MSVC, NonStop Kernel, OpenVMS */ fp_->_flag |= _IOERR; #elif defined __UCLIBC__ /* uClibc */ fp->__modeflags |= __FLAG_ERROR; diff --git a/contrib/tools/bison/lib/fstrcmp.c b/contrib/tools/bison/lib/fstrcmp.c index 1a4fbfdf8d..49ce27a6b0 100644 --- a/contrib/tools/bison/lib/fstrcmp.c +++ b/contrib/tools/bison/lib/fstrcmp.c @@ -46,6 +46,7 @@ ptrdiff_t edit_count; #define NOTE_DELETE(ctxt, xoff) ctxt->edit_count++ #define NOTE_INSERT(ctxt, yoff) ctxt->edit_count++ +#define NOTE_ORDERED false #define EARLY_ABORT(ctxt) ctxt->edit_count > 0 /* We don't need USE_HEURISTIC, since it is unlikely in typical uses of fstrcmp(). */ diff --git a/contrib/tools/bison/lib/get-errno.c b/contrib/tools/bison/lib/get-errno.c index ef3b71b4fb..5be2b68b97 100644 --- a/contrib/tools/bison/lib/get-errno.c +++ b/contrib/tools/bison/lib/get-errno.c @@ -1,6 +1,6 @@ /* get-errno.c - get and set errno. - Copyright (C) 2002, 2006, 2009-2015, 2018-2020 Free Software + Copyright (C) 2002, 2006, 2009-2015, 2018-2021 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -14,7 +14,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ /* Written by Paul Eggert. */ diff --git a/contrib/tools/bison/lib/get-errno.h b/contrib/tools/bison/lib/get-errno.h index b6550852f5..378e44e9fc 100644 --- a/contrib/tools/bison/lib/get-errno.h +++ b/contrib/tools/bison/lib/get-errno.h @@ -1,6 +1,6 @@ /* get-errno.h - get and set errno. - Copyright (C) 2002, 2009-2015, 2018-2020 Free Software Foundation, + Copyright (C) 2002, 2009-2015, 2018-2021 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -14,7 +14,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ extern int get_errno (void); extern void set_errno (int); diff --git a/contrib/tools/bison/lib/getprogname.c b/contrib/tools/bison/lib/getprogname.c index 7507e0d757..0ae5b5a5f0 100644 --- a/contrib/tools/bison/lib/getprogname.c +++ b/contrib/tools/bison/lib/getprogname.c @@ -51,7 +51,13 @@ # include <sys/procfs.h> #endif -#include "dirname.h" +#if defined __SCO_VERSION__ || defined __sysv5__ +# include <fcntl.h> +# include <stdlib.h> +# include <string.h> +#endif + +#include "basename-lgpl.h" #ifndef HAVE_GETPROGNAME /* not Mac OS X, FreeBSD, NetBSD, OpenBSD >= 5.4, Cygwin */ char const * @@ -223,7 +229,7 @@ getprogname (void) int fd; sprintf (filename, "/proc/pinfo/%d", (int) getpid ()); - fd = open (filename, O_RDONLY); + fd = open (filename, O_RDONLY | O_CLOEXEC); if (0 <= fd) { prpsinfo_t buf; @@ -245,6 +251,38 @@ getprogname (void) } } return NULL; +# elif defined __SCO_VERSION__ || defined __sysv5__ /* SCO OpenServer6/UnixWare */ + char buf[80]; + int fd; + sprintf (buf, "/proc/%d/cmdline", getpid()); + fd = open (buf, O_RDONLY); + if (0 <= fd) + { + size_t n = read (fd, buf, 79); + if (n > 0) + { + buf[n] = '\0'; /* Guarantee null-termination */ + char *progname; + progname = strrchr (buf, '/'); + if (progname) + { + progname = progname + 1; /* Skip the '/' */ + } + else + { + progname = buf; + } + char *ret; + ret = malloc (strlen (progname) + 1); + if (ret) + { + strcpy (ret, progname); + return ret; + } + } + close (fd); + } + return "?"; # else # error "getprogname module not ported to this OS" # endif diff --git a/contrib/tools/bison/lib/gl_anyhash1.h b/contrib/tools/bison/lib/gl_anyhash1.h new file mode 100644 index 0000000000..f4176fa82d --- /dev/null +++ b/contrib/tools/bison/lib/gl_anyhash1.h @@ -0,0 +1,31 @@ +/* Hash table for sequential list, set, and map data type. + Copyright (C) 2006, 2009-2020 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Common code of + gl_linkedhash_list.c, gl_avltreehash_list.c, gl_rbtreehash_list.c, + gl_linkedhash_set.c, gl_hash_set.c, + gl_linkedhash_map.c, gl_hash_map.c. */ + +/* Hash table entry. */ +struct gl_hash_entry +{ + struct gl_hash_entry *hash_next; /* chain of entries in same bucket */ + size_t hashcode; /* cache of the hash code of + - the key (for map data type) or + - the value (for list, set data types) */ +}; +typedef struct gl_hash_entry * gl_hash_entry_t; diff --git a/contrib/tools/bison/lib/gl_anyhash2.h b/contrib/tools/bison/lib/gl_anyhash2.h new file mode 100644 index 0000000000..ac70b45bd2 --- /dev/null +++ b/contrib/tools/bison/lib/gl_anyhash2.h @@ -0,0 +1,82 @@ +/* Hash table for sequential list, set, and map data type. + Copyright (C) 2006, 2009-2020 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Common code of + gl_linkedhash_list.c, gl_avltreehash_list.c, gl_rbtreehash_list.c, + gl_linkedhash_set.c, gl_hash_set.c, + gl_linkedhash_map.c, gl_hash_map.c. */ + +#include "gl_anyhash_primes.h" + +/* Resizes the hash table with a new estimated size. */ +static void +hash_resize (CONTAINER_T container, size_t estimate) +{ + size_t new_size = next_prime (estimate); + + if (new_size > container->table_size) + { + gl_hash_entry_t *old_table = container->table; + /* Allocate the new table. */ + gl_hash_entry_t *new_table; + size_t i; + + if (size_overflow_p (xtimes (new_size, sizeof (gl_hash_entry_t)))) + goto fail; + new_table = + (gl_hash_entry_t *) calloc (new_size, sizeof (gl_hash_entry_t)); + if (new_table == NULL) + goto fail; + + /* Iterate through the entries of the old table. */ + for (i = container->table_size; i > 0; ) + { + gl_hash_entry_t node = old_table[--i]; + + while (node != NULL) + { + gl_hash_entry_t next = node->hash_next; + /* Add the entry to the new table. */ + size_t bucket = node->hashcode % new_size; + node->hash_next = new_table[bucket]; + new_table[bucket] = node; + + node = next; + } + } + + container->table = new_table; + container->table_size = new_size; + free (old_table); + } + return; + + fail: + /* Just continue without resizing the table. */ + return; +} + +/* Resizes the hash table if needed, after CONTAINER_COUNT (container) was + incremented. */ +static void +hash_resize_after_add (CONTAINER_T container) +{ + size_t count = CONTAINER_COUNT (container); + size_t estimate = xsum (count, count / 2); /* 1.5 * count */ + if (estimate > container->table_size) + hash_resize (container, estimate); +} diff --git a/contrib/tools/bison/lib/gl_anyhash_primes.h b/contrib/tools/bison/lib/gl_anyhash_primes.h new file mode 100644 index 0000000000..c8f2d8df7c --- /dev/null +++ b/contrib/tools/bison/lib/gl_anyhash_primes.h @@ -0,0 +1,87 @@ +/* Table of primes, for use by hash tables. + Copyright (C) 2006, 2009-2020 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Array of primes, approximately in steps of factor 1.2. + This table was computed by executing the Common Lisp expression + (dotimes (i 244) (format t "nextprime(~D)~%" (ceiling (expt 1.2d0 i)))) + and feeding the result to PARI/gp. */ +static const size_t primes[] = + { + 11, 13, 17, 19, 23, 29, 37, 41, 47, 59, 67, 83, 97, 127, 139, 167, 199, + 239, 293, 347, 419, 499, 593, 709, 853, 1021, 1229, 1471, 1777, 2129, 2543, + 3049, 3659, 4391, 5273, 6323, 7589, 9103, 10937, 13109, 15727, 18899, + 22651, 27179, 32609, 39133, 46957, 56359, 67619, 81157, 97369, 116849, + 140221, 168253, 201907, 242309, 290761, 348889, 418667, 502409, 602887, + 723467, 868151, 1041779, 1250141, 1500181, 1800191, 2160233, 2592277, + 3110741, 3732887, 4479463, 5375371, 6450413, 7740517, 9288589, 11146307, + 13375573, 16050689, 19260817, 23112977, 27735583, 33282701, 39939233, + 47927081, 57512503, 69014987, 82818011, 99381577, 119257891, 143109469, + 171731387, 206077643, 247293161, 296751781, 356102141, 427322587, + 512787097, 615344489, 738413383, 886096061, 1063315271, 1275978331, + 1531174013, 1837408799, 2204890543UL, 2645868653UL, 3175042391UL, + 3810050851UL, +#if SIZE_MAX > 4294967295UL + 4572061027UL, 5486473229UL, 6583767889UL, 7900521449UL, 9480625733UL, + 11376750877UL, 13652101063UL, 16382521261UL, 19659025513UL, 23590830631UL, + 28308996763UL, 33970796089UL, 40764955463UL, 48917946377UL, 58701535657UL, + 70441842749UL, 84530211301UL, 101436253561UL, 121723504277UL, + 146068205131UL, 175281846149UL, 210338215379UL, 252405858521UL, + 302887030151UL, 363464436191UL, 436157323417UL, 523388788231UL, + 628066545713UL, 753679854847UL, 904415825857UL, 1085298991109UL, + 1302358789181UL, 1562830547009UL, 1875396656429UL, 2250475987709UL, + 2700571185239UL, 3240685422287UL, 3888822506759UL, 4666587008147UL, + 5599904409713UL, 6719885291641UL, 8063862349969UL, 9676634819959UL, + 11611961783951UL, 13934354140769UL, 16721224968907UL, 20065469962669UL, + 24078563955191UL, 28894276746229UL, 34673132095507UL, 41607758514593UL, + 49929310217531UL, 59915172260971UL, 71898206713183UL, 86277848055823UL, + 103533417666967UL, 124240101200359UL, 149088121440451UL, 178905745728529UL, + 214686894874223UL, 257624273849081UL, 309149128618903UL, 370978954342639UL, + 445174745211143UL, 534209694253381UL, 641051633104063UL, 769261959724877UL, + 923114351670013UL, 1107737222003791UL, 1329284666404567UL, + 1595141599685509UL, 1914169919622551UL, 2297003903547091UL, + 2756404684256459UL, 3307685621107757UL, 3969222745329323UL, + 4763067294395177UL, 5715680753274209UL, 6858816903929113UL, + 8230580284714831UL, 9876696341657791UL, 11852035609989371UL, + 14222442731987227UL, 17066931278384657UL, 20480317534061597UL, + 24576381040873903UL, 29491657249048679UL, 35389988698858471UL, + 42467986438630267UL, 50961583726356109UL, 61153900471627387UL, + 73384680565952851UL, 88061616679143347UL, 105673940014972061UL, + 126808728017966413UL, 152170473621559703UL, 182604568345871671UL, + 219125482015045997UL, 262950578418055169UL, 315540694101666193UL, + 378648832921999397UL, 454378599506399233UL, 545254319407679131UL, + 654305183289214771UL, 785166219947057701UL, 942199463936469157UL, + 1130639356723763129UL, 1356767228068515623UL, 1628120673682218619UL, + 1953744808418662409UL, 2344493770102394881UL, 2813392524122873857UL, + 3376071028947448339UL, 4051285234736937517UL, 4861542281684325481UL, + 5833850738021191727UL, 7000620885625427969UL, 8400745062750513217UL, + 10080894075300616261UL, 12097072890360739951UL, 14516487468432885797UL, + 17419784962119465179UL, +#endif + SIZE_MAX /* sentinel, to ensure the search terminates */ + }; + +/* Returns a suitable prime >= ESTIMATE. */ +static size_t +next_prime (size_t estimate) +{ + size_t i; + + for (i = 0; i < sizeof (primes) / sizeof (primes[0]); i++) + if (primes[i] >= estimate) + return primes[i]; + return SIZE_MAX; /* not a prime, but better than nothing */ +} diff --git a/contrib/tools/bison/lib/gl_anylinked_list1.h b/contrib/tools/bison/lib/gl_anylinked_list1.h new file mode 100644 index 0000000000..ec75d5080c --- /dev/null +++ b/contrib/tools/bison/lib/gl_anylinked_list1.h @@ -0,0 +1,48 @@ +/* Sequential list data type implemented by a linked list. + Copyright (C) 2006, 2009-2020 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Common code of gl_linked_list.c and gl_linkedhash_list.c. */ + +/* -------------------------- gl_list_t Data Type -------------------------- */ + +/* Concrete list node implementation, valid for this file only. */ +struct gl_list_node_impl +{ +#if WITH_HASHTABLE + struct gl_hash_entry h; /* hash table entry fields; must be first */ +#endif + struct gl_list_node_impl *next; + struct gl_list_node_impl *prev; + const void *value; +}; + +/* Concrete gl_list_impl type, valid for this file only. */ +struct gl_list_impl +{ + struct gl_list_impl_base base; +#if WITH_HASHTABLE + /* A hash table: managed as an array of collision lists. */ + struct gl_hash_entry **table; + size_t table_size; +#endif + /* A circular list anchored at root. + The first node is = root.next, the last node is = root.prev. + The root's value is unused. */ + struct gl_list_node_impl root; + /* Number of list nodes, excluding the root. */ + size_t count; +}; diff --git a/contrib/tools/bison/lib/gl_anylinked_list2.h b/contrib/tools/bison/lib/gl_anylinked_list2.h new file mode 100644 index 0000000000..24ef47ec0c --- /dev/null +++ b/contrib/tools/bison/lib/gl_anylinked_list2.h @@ -0,0 +1,1197 @@ +/* Sequential list data type implemented by a linked list. + Copyright (C) 2006-2020 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Common code of gl_linked_list.c and gl_linkedhash_list.c. */ + +/* If the symbol SIGNAL_SAFE_LIST is defined, the code is compiled in such + a way that a gl_list_t data structure may be used from within a signal + handler. The operations allowed in the signal handler are: + gl_list_iterator, gl_list_iterator_next, gl_list_iterator_free. + The list and node fields that are therefore accessed from the signal handler + are: + list->root, node->next, node->value. + We are careful to make modifications to these fields only in an order + that maintains the consistency of the list data structure at any moment, + and we use 'volatile' assignments to prevent the compiler from reordering + such assignments. */ +#ifdef SIGNAL_SAFE_LIST +# define ASYNCSAFE(type) *(type volatile *)& +#else +# define ASYNCSAFE(type) +#endif + +/* -------------------------- gl_list_t Data Type -------------------------- */ + +static gl_list_t +gl_linked_nx_create_empty (gl_list_implementation_t implementation, + gl_listelement_equals_fn equals_fn, + gl_listelement_hashcode_fn hashcode_fn, + gl_listelement_dispose_fn dispose_fn, + bool allow_duplicates) +{ + struct gl_list_impl *list = + (struct gl_list_impl *) malloc (sizeof (struct gl_list_impl)); + + if (list == NULL) + return NULL; + + list->base.vtable = implementation; + list->base.equals_fn = equals_fn; + list->base.hashcode_fn = hashcode_fn; + list->base.dispose_fn = dispose_fn; + list->base.allow_duplicates = allow_duplicates; +#if WITH_HASHTABLE + list->table_size = 11; + list->table = + (gl_hash_entry_t *) calloc (list->table_size, sizeof (gl_hash_entry_t)); + if (list->table == NULL) + goto fail; +#endif + list->root.next = &list->root; + list->root.prev = &list->root; + list->count = 0; + + return list; + +#if WITH_HASHTABLE + fail: + free (list); + return NULL; +#endif +} + +static gl_list_t +gl_linked_nx_create (gl_list_implementation_t implementation, + gl_listelement_equals_fn equals_fn, + gl_listelement_hashcode_fn hashcode_fn, + gl_listelement_dispose_fn dispose_fn, + bool allow_duplicates, + size_t count, const void **contents) +{ + struct gl_list_impl *list = + (struct gl_list_impl *) malloc (sizeof (struct gl_list_impl)); + gl_list_node_t tail; + + if (list == NULL) + return NULL; + + list->base.vtable = implementation; + list->base.equals_fn = equals_fn; + list->base.hashcode_fn = hashcode_fn; + list->base.dispose_fn = dispose_fn; + list->base.allow_duplicates = allow_duplicates; +#if WITH_HASHTABLE + { + size_t estimate = xsum (count, count / 2); /* 1.5 * count */ + if (estimate < 10) + estimate = 10; + list->table_size = next_prime (estimate); + if (size_overflow_p (xtimes (list->table_size, sizeof (gl_hash_entry_t)))) + goto fail1; + list->table = + (gl_hash_entry_t *) calloc (list->table_size, sizeof (gl_hash_entry_t)); + if (list->table == NULL) + goto fail1; + } +#endif + list->count = count; + tail = &list->root; + for (; count > 0; contents++, count--) + { + gl_list_node_t node = + (struct gl_list_node_impl *) malloc (sizeof (struct gl_list_node_impl)); + + if (node == NULL) + goto fail2; + + node->value = *contents; +#if WITH_HASHTABLE + node->h.hashcode = + (list->base.hashcode_fn != NULL + ? list->base.hashcode_fn (node->value) + : (size_t)(uintptr_t) node->value); + + /* Add node to the hash table. */ + if (add_to_bucket (list, node) < 0) + { + free (node); + goto fail2; + } +#endif + + /* Add node to the list. */ + node->prev = tail; + tail->next = node; + tail = node; + } + tail->next = &list->root; + list->root.prev = tail; + + return list; + + fail2: + { + gl_list_node_t node; + + for (node = tail; node != &list->root; ) + { + gl_list_node_t prev = node->prev; + + free (node); + node = prev; + } + } +#if WITH_HASHTABLE + free (list->table); + fail1: +#endif + free (list); + return NULL; +} + +static size_t _GL_ATTRIBUTE_PURE +gl_linked_size (gl_list_t list) +{ + return list->count; +} + +static const void * _GL_ATTRIBUTE_PURE +gl_linked_node_value (gl_list_t list _GL_ATTRIBUTE_MAYBE_UNUSED, + gl_list_node_t node) +{ + return node->value; +} + +static int +gl_linked_node_nx_set_value (gl_list_t list _GL_ATTRIBUTE_MAYBE_UNUSED, + gl_list_node_t node, + const void *elt) +{ +#if WITH_HASHTABLE + if (elt != node->value) + { + size_t new_hashcode = + (list->base.hashcode_fn != NULL + ? list->base.hashcode_fn (elt) + : (size_t)(uintptr_t) elt); + + if (new_hashcode != node->h.hashcode) + { + remove_from_bucket (list, node); + node->value = elt; + node->h.hashcode = new_hashcode; + if (add_to_bucket (list, node) < 0) + { + /* Out of memory. We removed node from a bucket but cannot add + it to another bucket. In order to avoid inconsistencies, we + must remove node entirely from the list. */ + gl_list_node_t before_removed = node->prev; + gl_list_node_t after_removed = node->next; + ASYNCSAFE(gl_list_node_t) before_removed->next = after_removed; + after_removed->prev = before_removed; + list->count--; + free (node); + return -1; + } + } + else + node->value = elt; + } +#else + node->value = elt; +#endif + return 0; +} + +static gl_list_node_t _GL_ATTRIBUTE_PURE +gl_linked_next_node (gl_list_t list, gl_list_node_t node) +{ + return (node->next != &list->root ? node->next : NULL); +} + +static gl_list_node_t _GL_ATTRIBUTE_PURE +gl_linked_previous_node (gl_list_t list, gl_list_node_t node) +{ + return (node->prev != &list->root ? node->prev : NULL); +} + +static const void * _GL_ATTRIBUTE_PURE +gl_linked_get_at (gl_list_t list, size_t position) +{ + size_t count = list->count; + gl_list_node_t node; + + if (!(position < count)) + /* Invalid argument. */ + abort (); + /* Here we know count > 0. */ + if (position <= ((count - 1) / 2)) + { + node = list->root.next; + for (; position > 0; position--) + node = node->next; + } + else + { + position = count - 1 - position; + node = list->root.prev; + for (; position > 0; position--) + node = node->prev; + } + return node->value; +} + +static gl_list_node_t +gl_linked_nx_set_at (gl_list_t list, size_t position, const void *elt) +{ + size_t count = list->count; + gl_list_node_t node; + + if (!(position < count)) + /* Invalid argument. */ + abort (); + /* Here we know count > 0. */ + if (position <= ((count - 1) / 2)) + { + node = list->root.next; + for (; position > 0; position--) + node = node->next; + } + else + { + position = count - 1 - position; + node = list->root.prev; + for (; position > 0; position--) + node = node->prev; + } +#if WITH_HASHTABLE + if (elt != node->value) + { + size_t new_hashcode = + (list->base.hashcode_fn != NULL + ? list->base.hashcode_fn (elt) + : (size_t)(uintptr_t) elt); + + if (new_hashcode != node->h.hashcode) + { + remove_from_bucket (list, node); + node->value = elt; + node->h.hashcode = new_hashcode; + if (add_to_bucket (list, node) < 0) + { + /* Out of memory. We removed node from a bucket but cannot add + it to another bucket. In order to avoid inconsistencies, we + must remove node entirely from the list. */ + gl_list_node_t before_removed = node->prev; + gl_list_node_t after_removed = node->next; + ASYNCSAFE(gl_list_node_t) before_removed->next = after_removed; + after_removed->prev = before_removed; + list->count--; + free (node); + return NULL; + } + } + else + node->value = elt; + } +#else + node->value = elt; +#endif + return node; +} + +static gl_list_node_t _GL_ATTRIBUTE_PURE +gl_linked_search_from_to (gl_list_t list, size_t start_index, size_t end_index, + const void *elt) +{ + size_t count = list->count; + + if (!(start_index <= end_index && end_index <= count)) + /* Invalid arguments. */ + abort (); + { +#if WITH_HASHTABLE + size_t hashcode = + (list->base.hashcode_fn != NULL + ? list->base.hashcode_fn (elt) + : (size_t)(uintptr_t) elt); + size_t bucket = hashcode % list->table_size; + gl_listelement_equals_fn equals = list->base.equals_fn; + + if (!list->base.allow_duplicates) + { + /* Look for the first match in the hash bucket. */ + gl_list_node_t found = NULL; + gl_list_node_t node; + + for (node = (gl_list_node_t) list->table[bucket]; + node != NULL; + node = (gl_list_node_t) node->h.hash_next) + if (node->h.hashcode == hashcode + && (equals != NULL + ? equals (elt, node->value) + : elt == node->value)) + { + found = node; + break; + } + if (start_index > 0) + /* Look whether found's index is < start_index. */ + for (node = list->root.next; ; node = node->next) + { + if (node == found) + return NULL; + if (--start_index == 0) + break; + } + if (end_index < count) + /* Look whether found's index is >= end_index. */ + { + end_index = count - end_index; + for (node = list->root.prev; ; node = node->prev) + { + if (node == found) + return NULL; + if (--end_index == 0) + break; + } + } + return found; + } + else + { + /* Look whether there is more than one match in the hash bucket. */ + bool multiple_matches = false; + gl_list_node_t first_match = NULL; + gl_list_node_t node; + + for (node = (gl_list_node_t) list->table[bucket]; + node != NULL; + node = (gl_list_node_t) node->h.hash_next) + if (node->h.hashcode == hashcode + && (equals != NULL + ? equals (elt, node->value) + : elt == node->value)) + { + if (first_match == NULL) + first_match = node; + else + { + multiple_matches = true; + break; + } + } + if (multiple_matches) + { + /* We need the match with the smallest index. But we don't have + a fast mapping node -> index. So we have to walk the list. */ + end_index -= start_index; + node = list->root.next; + for (; start_index > 0; start_index--) + node = node->next; + + for (; + end_index > 0; + node = node->next, end_index--) + if (node->h.hashcode == hashcode + && (equals != NULL + ? equals (elt, node->value) + : elt == node->value)) + return node; + /* The matches must have all been at indices < start_index or + >= end_index. */ + return NULL; + } + else + { + if (start_index > 0) + /* Look whether first_match's index is < start_index. */ + for (node = list->root.next; node != &list->root; node = node->next) + { + if (node == first_match) + return NULL; + if (--start_index == 0) + break; + } + if (end_index < list->count) + /* Look whether first_match's index is >= end_index. */ + { + end_index = list->count - end_index; + for (node = list->root.prev; ; node = node->prev) + { + if (node == first_match) + return NULL; + if (--end_index == 0) + break; + } + } + return first_match; + } + } +#else + gl_listelement_equals_fn equals = list->base.equals_fn; + gl_list_node_t node = list->root.next; + + end_index -= start_index; + for (; start_index > 0; start_index--) + node = node->next; + + if (equals != NULL) + { + for (; end_index > 0; node = node->next, end_index--) + if (equals (elt, node->value)) + return node; + } + else + { + for (; end_index > 0; node = node->next, end_index--) + if (elt == node->value) + return node; + } + return NULL; +#endif + } +} + +static size_t _GL_ATTRIBUTE_PURE +gl_linked_indexof_from_to (gl_list_t list, size_t start_index, size_t end_index, + const void *elt) +{ + size_t count = list->count; + + if (!(start_index <= end_index && end_index <= count)) + /* Invalid arguments. */ + abort (); + { +#if WITH_HASHTABLE + /* Here the hash table doesn't help much. It only allows us to minimize + the number of equals() calls, by looking up first the node and then + its index. */ + size_t hashcode = + (list->base.hashcode_fn != NULL + ? list->base.hashcode_fn (elt) + : (size_t)(uintptr_t) elt); + size_t bucket = hashcode % list->table_size; + gl_listelement_equals_fn equals = list->base.equals_fn; + gl_list_node_t node; + + /* First step: Look up the node. */ + if (!list->base.allow_duplicates) + { + /* Look for the first match in the hash bucket. */ + for (node = (gl_list_node_t) list->table[bucket]; + node != NULL; + node = (gl_list_node_t) node->h.hash_next) + if (node->h.hashcode == hashcode + && (equals != NULL + ? equals (elt, node->value) + : elt == node->value)) + break; + } + else + { + /* Look whether there is more than one match in the hash bucket. */ + bool multiple_matches = false; + gl_list_node_t first_match = NULL; + + for (node = (gl_list_node_t) list->table[bucket]; + node != NULL; + node = (gl_list_node_t) node->h.hash_next) + if (node->h.hashcode == hashcode + && (equals != NULL + ? equals (elt, node->value) + : elt == node->value)) + { + if (first_match == NULL) + first_match = node; + else + { + multiple_matches = true; + break; + } + } + if (multiple_matches) + { + /* We need the match with the smallest index. But we don't have + a fast mapping node -> index. So we have to walk the list. */ + size_t index; + + index = start_index; + node = list->root.next; + for (; start_index > 0; start_index--) + node = node->next; + + for (; + index < end_index; + node = node->next, index++) + if (node->h.hashcode == hashcode + && (equals != NULL + ? equals (elt, node->value) + : elt == node->value)) + return index; + /* The matches must have all been at indices < start_index or + >= end_index. */ + return (size_t)(-1); + } + node = first_match; + } + + /* Second step: Look up the index of the node. */ + if (node == NULL) + return (size_t)(-1); + else + { + size_t index = 0; + + for (; node->prev != &list->root; node = node->prev) + index++; + + if (index >= start_index && index < end_index) + return index; + else + return (size_t)(-1); + } +#else + gl_listelement_equals_fn equals = list->base.equals_fn; + size_t index = start_index; + gl_list_node_t node = list->root.next; + + for (; start_index > 0; start_index--) + node = node->next; + + if (equals != NULL) + { + for (; + index < end_index; + node = node->next, index++) + if (equals (elt, node->value)) + return index; + } + else + { + for (; + index < end_index; + node = node->next, index++) + if (elt == node->value) + return index; + } + return (size_t)(-1); +#endif + } +} + +static gl_list_node_t +gl_linked_nx_add_first (gl_list_t list, const void *elt) +{ + gl_list_node_t node = + (struct gl_list_node_impl *) malloc (sizeof (struct gl_list_node_impl)); + + if (node == NULL) + return NULL; + + ASYNCSAFE(const void *) node->value = elt; +#if WITH_HASHTABLE + node->h.hashcode = + (list->base.hashcode_fn != NULL + ? list->base.hashcode_fn (node->value) + : (size_t)(uintptr_t) node->value); + + /* Add node to the hash table. */ + if (add_to_bucket (list, node) < 0) + { + free (node); + return NULL; + } +#endif + + /* Add node to the list. */ + node->prev = &list->root; + ASYNCSAFE(gl_list_node_t) node->next = list->root.next; + node->next->prev = node; + ASYNCSAFE(gl_list_node_t) list->root.next = node; + list->count++; + +#if WITH_HASHTABLE + hash_resize_after_add (list); +#endif + + return node; +} + +static gl_list_node_t +gl_linked_nx_add_last (gl_list_t list, const void *elt) +{ + gl_list_node_t node = + (struct gl_list_node_impl *) malloc (sizeof (struct gl_list_node_impl)); + + if (node == NULL) + return NULL; + + ASYNCSAFE(const void *) node->value = elt; +#if WITH_HASHTABLE + node->h.hashcode = + (list->base.hashcode_fn != NULL + ? list->base.hashcode_fn (node->value) + : (size_t)(uintptr_t) node->value); + + /* Add node to the hash table. */ + if (add_to_bucket (list, node) < 0) + { + free (node); + return NULL; + } +#endif + + /* Add node to the list. */ + ASYNCSAFE(gl_list_node_t) node->next = &list->root; + node->prev = list->root.prev; + ASYNCSAFE(gl_list_node_t) node->prev->next = node; + list->root.prev = node; + list->count++; + +#if WITH_HASHTABLE + hash_resize_after_add (list); +#endif + + return node; +} + +static gl_list_node_t +gl_linked_nx_add_before (gl_list_t list, gl_list_node_t node, const void *elt) +{ + gl_list_node_t new_node = + (struct gl_list_node_impl *) malloc (sizeof (struct gl_list_node_impl)); + + if (new_node == NULL) + return NULL; + + ASYNCSAFE(const void *) new_node->value = elt; +#if WITH_HASHTABLE + new_node->h.hashcode = + (list->base.hashcode_fn != NULL + ? list->base.hashcode_fn (new_node->value) + : (size_t)(uintptr_t) new_node->value); + + /* Add new_node to the hash table. */ + if (add_to_bucket (list, new_node) < 0) + { + free (new_node); + return NULL; + } +#endif + + /* Add new_node to the list. */ + ASYNCSAFE(gl_list_node_t) new_node->next = node; + new_node->prev = node->prev; + ASYNCSAFE(gl_list_node_t) new_node->prev->next = new_node; + node->prev = new_node; + list->count++; + +#if WITH_HASHTABLE + hash_resize_after_add (list); +#endif + + return new_node; +} + +static gl_list_node_t +gl_linked_nx_add_after (gl_list_t list, gl_list_node_t node, const void *elt) +{ + gl_list_node_t new_node = + (struct gl_list_node_impl *) malloc (sizeof (struct gl_list_node_impl)); + + if (new_node == NULL) + return NULL; + + ASYNCSAFE(const void *) new_node->value = elt; +#if WITH_HASHTABLE + new_node->h.hashcode = + (list->base.hashcode_fn != NULL + ? list->base.hashcode_fn (new_node->value) + : (size_t)(uintptr_t) new_node->value); + + /* Add new_node to the hash table. */ + if (add_to_bucket (list, new_node) < 0) + { + free (new_node); + return NULL; + } +#endif + + /* Add new_node to the list. */ + new_node->prev = node; + ASYNCSAFE(gl_list_node_t) new_node->next = node->next; + new_node->next->prev = new_node; + ASYNCSAFE(gl_list_node_t) node->next = new_node; + list->count++; + +#if WITH_HASHTABLE + hash_resize_after_add (list); +#endif + + return new_node; +} + +static gl_list_node_t +gl_linked_nx_add_at (gl_list_t list, size_t position, const void *elt) +{ + size_t count = list->count; + gl_list_node_t new_node; + + if (!(position <= count)) + /* Invalid argument. */ + abort (); + + new_node = (struct gl_list_node_impl *) malloc (sizeof (struct gl_list_node_impl)); + if (new_node == NULL) + return NULL; + + ASYNCSAFE(const void *) new_node->value = elt; +#if WITH_HASHTABLE + new_node->h.hashcode = + (list->base.hashcode_fn != NULL + ? list->base.hashcode_fn (new_node->value) + : (size_t)(uintptr_t) new_node->value); + + /* Add new_node to the hash table. */ + if (add_to_bucket (list, new_node) < 0) + { + free (new_node); + return NULL; + } +#endif + + /* Add new_node to the list. */ + if (position <= (count / 2)) + { + gl_list_node_t node; + + node = &list->root; + for (; position > 0; position--) + node = node->next; + new_node->prev = node; + ASYNCSAFE(gl_list_node_t) new_node->next = node->next; + new_node->next->prev = new_node; + ASYNCSAFE(gl_list_node_t) node->next = new_node; + } + else + { + gl_list_node_t node; + + position = count - position; + node = &list->root; + for (; position > 0; position--) + node = node->prev; + ASYNCSAFE(gl_list_node_t) new_node->next = node; + new_node->prev = node->prev; + ASYNCSAFE(gl_list_node_t) new_node->prev->next = new_node; + node->prev = new_node; + } + list->count++; + +#if WITH_HASHTABLE + hash_resize_after_add (list); +#endif + + return new_node; +} + +static bool +gl_linked_remove_node (gl_list_t list, gl_list_node_t node) +{ + gl_list_node_t prev; + gl_list_node_t next; + +#if WITH_HASHTABLE + /* Remove node from the hash table. */ + remove_from_bucket (list, node); +#endif + + /* Remove node from the list. */ + prev = node->prev; + next = node->next; + + ASYNCSAFE(gl_list_node_t) prev->next = next; + next->prev = prev; + list->count--; + + if (list->base.dispose_fn != NULL) + list->base.dispose_fn (node->value); + free (node); + return true; +} + +static bool +gl_linked_remove_at (gl_list_t list, size_t position) +{ + size_t count = list->count; + gl_list_node_t removed_node; + + if (!(position < count)) + /* Invalid argument. */ + abort (); + /* Here we know count > 0. */ + if (position <= ((count - 1) / 2)) + { + gl_list_node_t node; + gl_list_node_t after_removed; + + node = &list->root; + for (; position > 0; position--) + node = node->next; + removed_node = node->next; + after_removed = node->next->next; + ASYNCSAFE(gl_list_node_t) node->next = after_removed; + after_removed->prev = node; + } + else + { + gl_list_node_t node; + gl_list_node_t before_removed; + + position = count - 1 - position; + node = &list->root; + for (; position > 0; position--) + node = node->prev; + removed_node = node->prev; + before_removed = node->prev->prev; + node->prev = before_removed; + ASYNCSAFE(gl_list_node_t) before_removed->next = node; + } +#if WITH_HASHTABLE + remove_from_bucket (list, removed_node); +#endif + list->count--; + + if (list->base.dispose_fn != NULL) + list->base.dispose_fn (removed_node->value); + free (removed_node); + return true; +} + +static bool +gl_linked_remove (gl_list_t list, const void *elt) +{ + gl_list_node_t node = gl_linked_search_from_to (list, 0, list->count, elt); + + if (node != NULL) + return gl_linked_remove_node (list, node); + else + return false; +} + +static void +gl_linked_list_free (gl_list_t list) +{ + gl_listelement_dispose_fn dispose = list->base.dispose_fn; + gl_list_node_t node; + + for (node = list->root.next; node != &list->root; ) + { + gl_list_node_t next = node->next; + if (dispose != NULL) + dispose (node->value); + free (node); + node = next; + } +#if WITH_HASHTABLE + free (list->table); +#endif + free (list); +} + +/* --------------------- gl_list_iterator_t Data Type --------------------- */ + +static gl_list_iterator_t _GL_ATTRIBUTE_PURE +gl_linked_iterator (gl_list_t list) +{ + gl_list_iterator_t result; + + result.vtable = list->base.vtable; + result.list = list; + result.p = list->root.next; + result.q = &list->root; +#if defined GCC_LINT || defined lint + result.i = 0; + result.j = 0; + result.count = 0; +#endif + + return result; +} + +static gl_list_iterator_t _GL_ATTRIBUTE_PURE +gl_linked_iterator_from_to (gl_list_t list, + size_t start_index, size_t end_index) +{ + gl_list_iterator_t result; + size_t n1, n2, n3; + + if (!(start_index <= end_index && end_index <= list->count)) + /* Invalid arguments. */ + abort (); + result.vtable = list->base.vtable; + result.list = list; + n1 = start_index; + n2 = end_index - start_index; + n3 = list->count - end_index; + /* Find the maximum among n1, n2, n3, so as to reduce the number of + loop iterations to n1 + n2 + n3 - max(n1,n2,n3). */ + if (n1 > n2 && n1 > n3) + { + /* n1 is the maximum, use n2 and n3. */ + gl_list_node_t node; + size_t i; + + node = &list->root; + for (i = n3; i > 0; i--) + node = node->prev; + result.q = node; + for (i = n2; i > 0; i--) + node = node->prev; + result.p = node; + } + else if (n2 > n3) + { + /* n2 is the maximum, use n1 and n3. */ + gl_list_node_t node; + size_t i; + + node = list->root.next; + for (i = n1; i > 0; i--) + node = node->next; + result.p = node; + + node = &list->root; + for (i = n3; i > 0; i--) + node = node->prev; + result.q = node; + } + else + { + /* n3 is the maximum, use n1 and n2. */ + gl_list_node_t node; + size_t i; + + node = list->root.next; + for (i = n1; i > 0; i--) + node = node->next; + result.p = node; + for (i = n2; i > 0; i--) + node = node->next; + result.q = node; + } + +#if defined GCC_LINT || defined lint + result.i = 0; + result.j = 0; + result.count = 0; +#endif + + return result; +} + +static bool +gl_linked_iterator_next (gl_list_iterator_t *iterator, + const void **eltp, gl_list_node_t *nodep) +{ + if (iterator->p != iterator->q) + { + gl_list_node_t node = (gl_list_node_t) iterator->p; + *eltp = node->value; + if (nodep != NULL) + *nodep = node; + iterator->p = node->next; + return true; + } + else + return false; +} + +static void +gl_linked_iterator_free (gl_list_iterator_t *iterator _GL_ATTRIBUTE_MAYBE_UNUSED) +{ +} + +/* ---------------------- Sorted gl_list_t Data Type ---------------------- */ + +static gl_list_node_t _GL_ATTRIBUTE_PURE +gl_linked_sortedlist_search (gl_list_t list, gl_listelement_compar_fn compar, + const void *elt) +{ + gl_list_node_t node; + + for (node = list->root.next; node != &list->root; node = node->next) + { + int cmp = compar (node->value, elt); + + if (cmp > 0) + break; + if (cmp == 0) + return node; + } + return NULL; +} + +static gl_list_node_t _GL_ATTRIBUTE_PURE +gl_linked_sortedlist_search_from_to (gl_list_t list, + gl_listelement_compar_fn compar, + size_t low, size_t high, + const void *elt) +{ + size_t count = list->count; + + if (!(low <= high && high <= list->count)) + /* Invalid arguments. */ + abort (); + + high -= low; + if (high > 0) + { + /* Here we know low < count. */ + size_t position = low; + gl_list_node_t node; + + if (position <= ((count - 1) / 2)) + { + node = list->root.next; + for (; position > 0; position--) + node = node->next; + } + else + { + position = count - 1 - position; + node = list->root.prev; + for (; position > 0; position--) + node = node->prev; + } + + do + { + int cmp = compar (node->value, elt); + + if (cmp > 0) + break; + if (cmp == 0) + return node; + node = node->next; + } + while (--high > 0); + } + return NULL; +} + +static size_t _GL_ATTRIBUTE_PURE +gl_linked_sortedlist_indexof (gl_list_t list, gl_listelement_compar_fn compar, + const void *elt) +{ + gl_list_node_t node; + size_t index; + + for (node = list->root.next, index = 0; + node != &list->root; + node = node->next, index++) + { + int cmp = compar (node->value, elt); + + if (cmp > 0) + break; + if (cmp == 0) + return index; + } + return (size_t)(-1); +} + +static size_t _GL_ATTRIBUTE_PURE +gl_linked_sortedlist_indexof_from_to (gl_list_t list, + gl_listelement_compar_fn compar, + size_t low, size_t high, + const void *elt) +{ + size_t count = list->count; + + if (!(low <= high && high <= list->count)) + /* Invalid arguments. */ + abort (); + + high -= low; + if (high > 0) + { + /* Here we know low < count. */ + size_t index = low; + size_t position = low; + gl_list_node_t node; + + if (position <= ((count - 1) / 2)) + { + node = list->root.next; + for (; position > 0; position--) + node = node->next; + } + else + { + position = count - 1 - position; + node = list->root.prev; + for (; position > 0; position--) + node = node->prev; + } + + do + { + int cmp = compar (node->value, elt); + + if (cmp > 0) + break; + if (cmp == 0) + return index; + node = node->next; + index++; + } + while (--high > 0); + } + return (size_t)(-1); +} + +static gl_list_node_t +gl_linked_sortedlist_nx_add (gl_list_t list, gl_listelement_compar_fn compar, + const void *elt) +{ + gl_list_node_t node; + + for (node = list->root.next; node != &list->root; node = node->next) + if (compar (node->value, elt) >= 0) + return gl_linked_nx_add_before (list, node, elt); + return gl_linked_nx_add_last (list, elt); +} + +static bool +gl_linked_sortedlist_remove (gl_list_t list, gl_listelement_compar_fn compar, + const void *elt) +{ + gl_list_node_t node; + + for (node = list->root.next; node != &list->root; node = node->next) + { + int cmp = compar (node->value, elt); + + if (cmp > 0) + break; + if (cmp == 0) + return gl_linked_remove_node (list, node); + } + return false; +} diff --git a/contrib/tools/bison/lib/gl_anyrbtree_list1.h b/contrib/tools/bison/lib/gl_anyrbtree_list1.h new file mode 100644 index 0000000000..5d0079ad24 --- /dev/null +++ b/contrib/tools/bison/lib/gl_anyrbtree_list1.h @@ -0,0 +1,76 @@ +/* Sequential list data type implemented by a binary tree. + Copyright (C) 2006, 2009-2020 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Common code of gl_rbtree_list.c and gl_rbtreehash_list.c. */ + +/* A red-black tree is a binary tree where every node is colored black or + red such that + 1. The root is black. + 2. No red node has a red parent. + Or equivalently: No red node has a red child. + 3. All paths from the root down to any NULL endpoint contain the same + number of black nodes. + Let's call this the "black-height" bh of the tree. It follows that every + such path contains exactly bh black and between 0 and bh red nodes. (The + extreme cases are a path containing only black nodes, and a path colored + alternately black-red-black-red-...-black-red.) The height of the tree + therefore is >= bh, <= 2*bh. + */ + +/* -------------------------- gl_list_t Data Type -------------------------- */ + +/* Color of a node. */ +typedef enum color { BLACK, RED } color_t; + +/* Concrete list node implementation, valid for this file only. */ +struct gl_list_node_impl +{ +#if WITH_HASHTABLE + struct gl_hash_entry h; /* hash table entry fields; must be first */ +#endif + struct gl_list_node_impl *left; /* left branch, or NULL */ + struct gl_list_node_impl *right; /* right branch, or NULL */ + /* Parent pointer, or NULL. The parent pointer is not needed for most + operations. It is needed so that a gl_list_node_t can be returned + without memory allocation, on which the functions gl_list_remove_node, + gl_list_add_before, gl_list_add_after can be implemented. */ + struct gl_list_node_impl *parent; + color_t color; /* node's color */ + size_t branch_size; /* number of nodes in this branch, + = branchsize(left)+branchsize(right)+1 */ + const void *value; +}; + +/* Concrete gl_list_impl type, valid for this file only. */ +struct gl_list_impl +{ + struct gl_list_impl_base base; +#if WITH_HASHTABLE + /* A hash table: managed as an array of collision lists. */ + struct gl_hash_entry **table; + size_t table_size; +#endif + struct gl_list_node_impl *root; /* root node or NULL */ +}; + +/* A red-black tree of height h has a black-height bh >= ceil(h/2) and + therefore at least 2^ceil(h/2) - 1 elements. So, h <= 116 (because a tree + of height h >= 117 would have at least 2^59 - 1 elements, and because even + on 64-bit machines, + sizeof (gl_list_node_impl) * (2^59 - 1) > 2^64 + this would exceed the address space of the machine. */ +#define MAXHEIGHT 116 diff --git a/contrib/tools/bison/lib/gl_anyrbtree_list2.h b/contrib/tools/bison/lib/gl_anyrbtree_list2.h new file mode 100644 index 0000000000..f14eda0ef4 --- /dev/null +++ b/contrib/tools/bison/lib/gl_anyrbtree_list2.h @@ -0,0 +1,1028 @@ +/* Sequential list data type implemented by a binary tree. + Copyright (C) 2006-2007, 2009-2020 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Common code of gl_rbtree_list.c and gl_rbtreehash_list.c. */ + +/* -------------------------- gl_list_t Data Type -------------------------- */ + +/* Creates a subtree for count >= 1 elements. + Its black-height bh is passed as argument, with + 2^bh - 1 <= count <= 2^(bh+1) - 1. bh == 0 implies count == 1. + Its height is h where 2^(h-1) <= count <= 2^h - 1. + Return NULL upon out-of-memory. */ +static gl_list_node_t +create_subtree_with_contents (unsigned int bh, + size_t count, const void **contents) +{ + size_t half1 = (count - 1) / 2; + size_t half2 = count / 2; + /* Note: half1 + half2 = count - 1. */ + gl_list_node_t node = + (struct gl_list_node_impl *) malloc (sizeof (struct gl_list_node_impl)); + if (node == NULL) + return NULL; + + if (half1 > 0) + { + /* half1 > 0 implies count > 1, implies bh >= 1, implies + 2^(bh-1) - 1 <= half1 <= 2^bh - 1. */ + node->left = + create_subtree_with_contents (bh - 1, half1, contents); + if (node->left == NULL) + goto fail1; + node->left->parent = node; + } + else + node->left = NULL; + + node->value = contents[half1]; + + if (half2 > 0) + { + /* half2 > 0 implies count > 1, implies bh >= 1, implies + 2^(bh-1) - 1 <= half2 <= 2^bh - 1. */ + node->right = + create_subtree_with_contents (bh - 1, half2, contents + half1 + 1); + if (node->right == NULL) + goto fail2; + node->right->parent = node; + } + else + node->right = NULL; + + node->color = (bh == 0 ? RED : BLACK); + + node->branch_size = count; + + return node; + + fail2: + if (node->left != NULL) + free_subtree (node->left); + fail1: + free (node); + return NULL; +} + +static gl_list_t +gl_tree_nx_create (gl_list_implementation_t implementation, + gl_listelement_equals_fn equals_fn, + gl_listelement_hashcode_fn hashcode_fn, + gl_listelement_dispose_fn dispose_fn, + bool allow_duplicates, + size_t count, const void **contents) +{ + struct gl_list_impl *list = + (struct gl_list_impl *) malloc (sizeof (struct gl_list_impl)); + + if (list == NULL) + return NULL; + + list->base.vtable = implementation; + list->base.equals_fn = equals_fn; + list->base.hashcode_fn = hashcode_fn; + list->base.dispose_fn = dispose_fn; + list->base.allow_duplicates = allow_duplicates; +#if WITH_HASHTABLE + { + size_t estimate = xsum (count, count / 2); /* 1.5 * count */ + if (estimate < 10) + estimate = 10; + list->table_size = next_prime (estimate); + if (size_overflow_p (xtimes (list->table_size, sizeof (gl_hash_entry_t)))) + goto fail1; + list->table = + (gl_hash_entry_t *) calloc (list->table_size, sizeof (gl_hash_entry_t)); + if (list->table == NULL) + goto fail1; + } +#endif + if (count > 0) + { + /* Assuming 2^bh - 1 <= count <= 2^(bh+1) - 2, we create a tree whose + upper bh levels are black, and only the partially present lowest + level is red. */ + unsigned int bh; + { + size_t n; + for (n = count + 1, bh = 0; n > 1; n = n >> 1) + bh++; + } + + list->root = create_subtree_with_contents (bh, count, contents); + if (list->root == NULL) + goto fail2; + list->root->parent = NULL; + +#if WITH_HASHTABLE + /* Now that the tree is built, node_position() works. Now we can + add the nodes to the hash table. */ + if (add_nodes_to_buckets (list) < 0) + goto fail3; +#endif + } + else + list->root = NULL; + + return list; + +#if WITH_HASHTABLE + fail3: + free_subtree (list->root); +#endif + fail2: +#if WITH_HASHTABLE + free (list->table); + fail1: +#endif + free (list); + return NULL; +} + +/* Rotates left a subtree. + + B D + / \ / \ + A D --> B E + / \ / \ + C E A C + + Changes the tree structure, updates the branch sizes. + The caller must update the colors and register D as child of its parent. */ +static gl_list_node_t +rotate_left (gl_list_node_t b_node, gl_list_node_t d_node) +{ + gl_list_node_t a_node = b_node->left; + gl_list_node_t c_node = d_node->left; + gl_list_node_t e_node = d_node->right; + + b_node->right = c_node; + d_node->left = b_node; + + d_node->parent = b_node->parent; + b_node->parent = d_node; + if (c_node != NULL) + c_node->parent = b_node; + + b_node->branch_size = + (a_node != NULL ? a_node->branch_size : 0) + + 1 + (c_node != NULL ? c_node->branch_size : 0); + d_node->branch_size = + b_node->branch_size + 1 + (e_node != NULL ? e_node->branch_size : 0); + + return d_node; +} + +/* Rotates right a subtree. + + D B + / \ / \ + B E --> A D + / \ / \ + A C C E + + Changes the tree structure, updates the branch sizes. + The caller must update the colors and register B as child of its parent. */ +static gl_list_node_t +rotate_right (gl_list_node_t b_node, gl_list_node_t d_node) +{ + gl_list_node_t a_node = b_node->left; + gl_list_node_t c_node = b_node->right; + gl_list_node_t e_node = d_node->right; + + d_node->left = c_node; + b_node->right = d_node; + + b_node->parent = d_node->parent; + d_node->parent = b_node; + if (c_node != NULL) + c_node->parent = d_node; + + d_node->branch_size = + (c_node != NULL ? c_node->branch_size : 0) + + 1 + (e_node != NULL ? e_node->branch_size : 0); + b_node->branch_size = + (a_node != NULL ? a_node->branch_size : 0) + 1 + d_node->branch_size; + + return b_node; +} + +/* Ensures the tree is balanced, after an insertion operation. + Also assigns node->color. + parent is the given node's parent, known to be non-NULL. */ +static void +rebalance_after_add (gl_list_t list, gl_list_node_t node, gl_list_node_t parent) +{ + for (;;) + { + /* At this point, parent = node->parent != NULL. + Think of node->color being RED (although node->color is not yet + assigned.) */ + gl_list_node_t grandparent; + gl_list_node_t uncle; + + if (parent->color == BLACK) + { + /* A RED color for node is acceptable. */ + node->color = RED; + return; + } + + grandparent = parent->parent; + /* Since parent is RED, we know that + grandparent is != NULL and colored BLACK. */ + + if (grandparent->left == parent) + uncle = grandparent->right; + else if (grandparent->right == parent) + uncle = grandparent->left; + else + abort (); + + if (uncle != NULL && uncle->color == RED) + { + /* Change grandparent from BLACK to RED, and + change parent and uncle from RED to BLACK. + This makes it acceptable for node to be RED. */ + node->color = RED; + parent->color = uncle->color = BLACK; + node = grandparent; + } + else + { + /* grandparent and uncle are BLACK. parent is RED. node wants + to be RED too. + In this case, recoloring is not sufficient. Need to perform + one or two rotations. */ + gl_list_node_t *grandparentp; + + if (grandparent->parent == NULL) + grandparentp = &list->root; + else if (grandparent->parent->left == grandparent) + grandparentp = &grandparent->parent->left; + else if (grandparent->parent->right == grandparent) + grandparentp = &grandparent->parent->right; + else + abort (); + + if (grandparent->left == parent) + { + if (parent->right == node) + { + /* Rotation between node and parent. */ + grandparent->left = rotate_left (parent, node); + node = parent; + parent = grandparent->left; + } + /* grandparent and uncle are BLACK. parent and node want to be + RED. parent = grandparent->left. node = parent->left. + + grandparent parent + bh+1 bh+1 + / \ / \ + parent uncle --> node grandparent + bh bh bh bh + / \ / \ + node C C uncle + bh bh bh bh + */ + *grandparentp = rotate_right (parent, grandparent); + parent->color = BLACK; + node->color = grandparent->color = RED; + } + else /* grandparent->right == parent */ + { + if (parent->left == node) + { + /* Rotation between node and parent. */ + grandparent->right = rotate_right (node, parent); + node = parent; + parent = grandparent->right; + } + /* grandparent and uncle are BLACK. parent and node want to be + RED. parent = grandparent->right. node = parent->right. + + grandparent parent + bh+1 bh+1 + / \ / \ + uncle parent --> grandparent node + bh bh bh bh + / \ / \ + C node uncle C + bh bh bh bh + */ + *grandparentp = rotate_left (grandparent, parent); + parent->color = BLACK; + node->color = grandparent->color = RED; + } + return; + } + + /* Start again with a new (node, parent) pair. */ + parent = node->parent; + + if (parent == NULL) + { + /* Change node's color from RED to BLACK. This increases the + tree's black-height. */ + node->color = BLACK; + return; + } + } +} + +/* Ensures the tree is balanced, after a deletion operation. + CHILD was a grandchild of PARENT and is now its child. Between them, + a black node was removed. CHILD is also black, or NULL. + (CHILD can also be NULL. But PARENT is non-NULL.) */ +static void +rebalance_after_remove (gl_list_t list, gl_list_node_t child, gl_list_node_t parent) +{ + for (;;) + { + /* At this point, we reduced the black-height of the CHILD subtree by 1. + To make up, either look for a possibility to turn a RED to a BLACK + node, or try to reduce the black-height tree of CHILD's sibling + subtree as well. */ + gl_list_node_t *parentp; + + if (parent->parent == NULL) + parentp = &list->root; + else if (parent->parent->left == parent) + parentp = &parent->parent->left; + else if (parent->parent->right == parent) + parentp = &parent->parent->right; + else + abort (); + + if (parent->left == child) + { + gl_list_node_t sibling = parent->right; + /* sibling's black-height is >= 1. In particular, + sibling != NULL. + + parent + / \ + child sibling + bh bh+1 + */ + + if (sibling->color == RED) + { + /* sibling is RED, hence parent is BLACK and sibling's children + are non-NULL and BLACK. + + parent sibling + bh+2 bh+2 + / \ / \ + child sibling --> parent SR + bh bh+1 bh+1 bh+1 + / \ / \ + SL SR child SL + bh+1 bh+1 bh bh+1 + */ + *parentp = rotate_left (parent, sibling); + parent->color = RED; + sibling->color = BLACK; + + /* Concentrate on the subtree of parent. The new sibling is + one of the old sibling's children, and known to be BLACK. */ + parentp = &sibling->left; + sibling = parent->right; + } + /* Now we know that sibling is BLACK. + + parent + / \ + child sibling + bh bh+1 + */ + if (sibling->right != NULL && sibling->right->color == RED) + { + /* + parent sibling + bh+1|bh+2 bh+1|bh+2 + / \ / \ + child sibling --> parent SR + bh bh+1 bh+1 bh+1 + / \ / \ + SL SR child SL + bh bh bh bh + */ + *parentp = rotate_left (parent, sibling); + sibling->color = parent->color; + parent->color = BLACK; + sibling->right->color = BLACK; + return; + } + else if (sibling->left != NULL && sibling->left->color == RED) + { + /* + parent parent + bh+1|bh+2 bh+1|bh+2 + / \ / \ + child sibling --> child SL + bh bh+1 bh bh+1 + / \ / \ + SL SR SLL sibling + bh bh bh bh + / \ / \ + SLL SLR SLR SR + bh bh bh bh + + where SLL, SLR, SR are all black. + */ + parent->right = rotate_right (sibling->left, sibling); + /* Change sibling from BLACK to RED and SL from RED to BLACK. */ + sibling->color = RED; + sibling = parent->right; + sibling->color = BLACK; + + /* Now do as in the previous case. */ + *parentp = rotate_left (parent, sibling); + sibling->color = parent->color; + parent->color = BLACK; + sibling->right->color = BLACK; + return; + } + else + { + if (parent->color == BLACK) + { + /* Change sibling from BLACK to RED. Then the entire + subtree at parent has decreased its black-height. + parent parent + bh+2 bh+1 + / \ / \ + child sibling --> child sibling + bh bh+1 bh bh + */ + sibling->color = RED; + + child = parent; + } + else + { + /* Change parent from RED to BLACK, but compensate by + changing sibling from BLACK to RED. + parent parent + bh+1 bh+1 + / \ / \ + child sibling --> child sibling + bh bh+1 bh bh + */ + parent->color = BLACK; + sibling->color = RED; + return; + } + } + } + else if (parent->right == child) + { + gl_list_node_t sibling = parent->left; + /* sibling's black-height is >= 1. In particular, + sibling != NULL. + + parent + / \ + sibling child + bh+1 bh + */ + + if (sibling->color == RED) + { + /* sibling is RED, hence parent is BLACK and sibling's children + are non-NULL and BLACK. + + parent sibling + bh+2 bh+2 + / \ / \ + sibling child --> SR parent + bh+1 ch bh+1 bh+1 + / \ / \ + SL SR SL child + bh+1 bh+1 bh+1 bh + */ + *parentp = rotate_right (sibling, parent); + parent->color = RED; + sibling->color = BLACK; + + /* Concentrate on the subtree of parent. The new sibling is + one of the old sibling's children, and known to be BLACK. */ + parentp = &sibling->right; + sibling = parent->left; + } + /* Now we know that sibling is BLACK. + + parent + / \ + sibling child + bh+1 bh + */ + if (sibling->left != NULL && sibling->left->color == RED) + { + /* + parent sibling + bh+1|bh+2 bh+1|bh+2 + / \ / \ + sibling child --> SL parent + bh+1 bh bh+1 bh+1 + / \ / \ + SL SR SR child + bh bh bh bh + */ + *parentp = rotate_right (sibling, parent); + sibling->color = parent->color; + parent->color = BLACK; + sibling->left->color = BLACK; + return; + } + else if (sibling->right != NULL && sibling->right->color == RED) + { + /* + parent parent + bh+1|bh+2 bh+1|bh+2 + / \ / \ + sibling child --> SR child + bh+1 bh bh+1 bh + / \ / \ + SL SR sibling SRR + bh bh bh bh + / \ / \ + SRL SRR SL SRL + bh bh bh bh + + where SL, SRL, SRR are all black. + */ + parent->left = rotate_left (sibling, sibling->right); + /* Change sibling from BLACK to RED and SL from RED to BLACK. */ + sibling->color = RED; + sibling = parent->left; + sibling->color = BLACK; + + /* Now do as in the previous case. */ + *parentp = rotate_right (sibling, parent); + sibling->color = parent->color; + parent->color = BLACK; + sibling->left->color = BLACK; + return; + } + else + { + if (parent->color == BLACK) + { + /* Change sibling from BLACK to RED. Then the entire + subtree at parent has decreased its black-height. + parent parent + bh+2 bh+1 + / \ / \ + sibling child --> sibling child + bh+1 bh bh bh + */ + sibling->color = RED; + + child = parent; + } + else + { + /* Change parent from RED to BLACK, but compensate by + changing sibling from BLACK to RED. + parent parent + bh+1 bh+1 + / \ / \ + sibling child --> sibling child + bh+1 bh bh bh + */ + parent->color = BLACK; + sibling->color = RED; + return; + } + } + } + else + abort (); + + /* Start again with a new (child, parent) pair. */ + parent = child->parent; + +#if 0 /* Already handled. */ + if (child != NULL && child->color == RED) + { + child->color = BLACK; + return; + } +#endif + + if (parent == NULL) + return; + } +} + +static void +gl_tree_remove_node_from_tree (gl_list_t list, gl_list_node_t node) +{ + gl_list_node_t parent = node->parent; + + if (node->left == NULL) + { + /* Replace node with node->right. */ + gl_list_node_t child = node->right; + + if (child != NULL) + { + child->parent = parent; + /* Since node->left == NULL, child must be RED and of height 1, + hence node must have been BLACK. Recolor the child. */ + child->color = BLACK; + } + if (parent == NULL) + list->root = child; + else + { + if (parent->left == node) + parent->left = child; + else /* parent->right == node */ + parent->right = child; + + /* Update branch_size fields of the parent nodes. */ + { + gl_list_node_t p; + + for (p = parent; p != NULL; p = p->parent) + p->branch_size--; + } + + if (child == NULL && node->color == BLACK) + rebalance_after_remove (list, child, parent); + } + } + else if (node->right == NULL) + { + /* It is not absolutely necessary to treat this case. But the more + general case below is more complicated, hence slower. */ + /* Replace node with node->left. */ + gl_list_node_t child = node->left; + + child->parent = parent; + /* Since node->right == NULL, child must be RED and of height 1, + hence node must have been BLACK. Recolor the child. */ + child->color = BLACK; + if (parent == NULL) + list->root = child; + else + { + if (parent->left == node) + parent->left = child; + else /* parent->right == node */ + parent->right = child; + + /* Update branch_size fields of the parent nodes. */ + { + gl_list_node_t p; + + for (p = parent; p != NULL; p = p->parent) + p->branch_size--; + } + } + } + else + { + /* Replace node with the rightmost element of the node->left subtree. */ + gl_list_node_t subst; + gl_list_node_t subst_parent; + gl_list_node_t child; + color_t removed_color; + + for (subst = node->left; subst->right != NULL; ) + subst = subst->right; + + subst_parent = subst->parent; + + child = subst->left; + + removed_color = subst->color; + + /* The case subst_parent == node is special: If we do nothing special, + we get confusion about node->left, subst->left and child->parent. + subst_parent == node + <==> The 'for' loop above terminated immediately. + <==> subst == subst_parent->left + [otherwise subst == subst_parent->right] + In this case, we would need to first set + child->parent = node; node->left = child; + and later - when we copy subst into node's position - again + child->parent = subst; subst->left = child; + Altogether a no-op. */ + if (subst_parent != node) + { + if (child != NULL) + child->parent = subst_parent; + subst_parent->right = child; + } + + /* Update branch_size fields of the parent nodes. */ + { + gl_list_node_t p; + + for (p = subst_parent; p != NULL; p = p->parent) + p->branch_size--; + } + + /* Copy subst into node's position. + (This is safer than to copy subst's value into node, keep node in + place, and free subst.) */ + if (subst_parent != node) + { + subst->left = node->left; + subst->left->parent = subst; + } + subst->right = node->right; + subst->right->parent = subst; + subst->color = node->color; + subst->branch_size = node->branch_size; + subst->parent = parent; + if (parent == NULL) + list->root = subst; + else if (parent->left == node) + parent->left = subst; + else /* parent->right == node */ + parent->right = subst; + + if (removed_color == BLACK) + { + if (child != NULL && child->color == RED) + /* Recolor the child. */ + child->color = BLACK; + else + /* Rebalancing starts at child's parent, that is subst_parent - + except when subst_parent == node. In this case, we need to use + its replacement, subst. */ + rebalance_after_remove (list, child, + subst_parent != node ? subst_parent : subst); + } + } +} + +static gl_list_node_t +gl_tree_nx_add_first (gl_list_t list, const void *elt) +{ + /* Create new node. */ + gl_list_node_t new_node = + (struct gl_list_node_impl *) malloc (sizeof (struct gl_list_node_impl)); + + if (new_node == NULL) + return NULL; + + new_node->left = NULL; + new_node->right = NULL; + new_node->branch_size = 1; + new_node->value = elt; +#if WITH_HASHTABLE + new_node->h.hashcode = + (list->base.hashcode_fn != NULL + ? list->base.hashcode_fn (new_node->value) + : (size_t)(uintptr_t) new_node->value); +#endif + + /* Add it to the tree. */ + if (list->root == NULL) + { + new_node->color = BLACK; + list->root = new_node; + new_node->parent = NULL; + } + else + { + gl_list_node_t node; + + for (node = list->root; node->left != NULL; ) + node = node->left; + + node->left = new_node; + new_node->parent = node; + + /* Update branch_size fields of the parent nodes. */ + { + gl_list_node_t p; + + for (p = node; p != NULL; p = p->parent) + p->branch_size++; + } + + /* Color and rebalance. */ + rebalance_after_add (list, new_node, node); + } + +#if WITH_HASHTABLE + /* Add node to the hash table. + Note that this is only possible _after_ the node has been added to the + tree structure, because add_to_bucket() uses node_position(). */ + if (add_to_bucket (list, new_node) < 0) + { + gl_tree_remove_node_from_tree (list, new_node); + free (new_node); + return NULL; + } + hash_resize_after_add (list); +#endif + + return new_node; +} + +static gl_list_node_t +gl_tree_nx_add_last (gl_list_t list, const void *elt) +{ + /* Create new node. */ + gl_list_node_t new_node = + (struct gl_list_node_impl *) malloc (sizeof (struct gl_list_node_impl)); + + if (new_node == NULL) + return NULL; + + new_node->left = NULL; + new_node->right = NULL; + new_node->branch_size = 1; + new_node->value = elt; +#if WITH_HASHTABLE + new_node->h.hashcode = + (list->base.hashcode_fn != NULL + ? list->base.hashcode_fn (new_node->value) + : (size_t)(uintptr_t) new_node->value); +#endif + + /* Add it to the tree. */ + if (list->root == NULL) + { + new_node->color = BLACK; + list->root = new_node; + new_node->parent = NULL; + } + else + { + gl_list_node_t node; + + for (node = list->root; node->right != NULL; ) + node = node->right; + + node->right = new_node; + new_node->parent = node; + + /* Update branch_size fields of the parent nodes. */ + { + gl_list_node_t p; + + for (p = node; p != NULL; p = p->parent) + p->branch_size++; + } + + /* Color and rebalance. */ + rebalance_after_add (list, new_node, node); + } + +#if WITH_HASHTABLE + /* Add node to the hash table. + Note that this is only possible _after_ the node has been added to the + tree structure, because add_to_bucket() uses node_position(). */ + if (add_to_bucket (list, new_node) < 0) + { + gl_tree_remove_node_from_tree (list, new_node); + free (new_node); + return NULL; + } + hash_resize_after_add (list); +#endif + + return new_node; +} + +static gl_list_node_t +gl_tree_nx_add_before (gl_list_t list, gl_list_node_t node, const void *elt) +{ + /* Create new node. */ + gl_list_node_t new_node = + (struct gl_list_node_impl *) malloc (sizeof (struct gl_list_node_impl)); + + if (new_node == NULL) + return NULL; + + new_node->left = NULL; + new_node->right = NULL; + new_node->branch_size = 1; + new_node->value = elt; +#if WITH_HASHTABLE + new_node->h.hashcode = + (list->base.hashcode_fn != NULL + ? list->base.hashcode_fn (new_node->value) + : (size_t)(uintptr_t) new_node->value); +#endif + + /* Add it to the tree. */ + if (node->left == NULL) + node->left = new_node; + else + { + for (node = node->left; node->right != NULL; ) + node = node->right; + node->right = new_node; + } + new_node->parent = node; + + /* Update branch_size fields of the parent nodes. */ + { + gl_list_node_t p; + + for (p = node; p != NULL; p = p->parent) + p->branch_size++; + } + + /* Color and rebalance. */ + rebalance_after_add (list, new_node, node); + +#if WITH_HASHTABLE + /* Add node to the hash table. + Note that this is only possible _after_ the node has been added to the + tree structure, because add_to_bucket() uses node_position(). */ + if (add_to_bucket (list, new_node) < 0) + { + gl_tree_remove_node_from_tree (list, new_node); + free (new_node); + return NULL; + } + hash_resize_after_add (list); +#endif + + return new_node; +} + +static gl_list_node_t +gl_tree_nx_add_after (gl_list_t list, gl_list_node_t node, const void *elt) +{ + /* Create new node. */ + gl_list_node_t new_node = + (struct gl_list_node_impl *) malloc (sizeof (struct gl_list_node_impl)); + + if (new_node == NULL) + return NULL; + + new_node->left = NULL; + new_node->right = NULL; + new_node->branch_size = 1; + new_node->value = elt; +#if WITH_HASHTABLE + new_node->h.hashcode = + (list->base.hashcode_fn != NULL + ? list->base.hashcode_fn (new_node->value) + : (size_t)(uintptr_t) new_node->value); +#endif + + /* Add it to the tree. */ + if (node->right == NULL) + node->right = new_node; + else + { + for (node = node->right; node->left != NULL; ) + node = node->left; + node->left = new_node; + } + new_node->parent = node; + + /* Update branch_size fields of the parent nodes. */ + { + gl_list_node_t p; + + for (p = node; p != NULL; p = p->parent) + p->branch_size++; + } + + /* Color and rebalance. */ + rebalance_after_add (list, new_node, node); + +#if WITH_HASHTABLE + /* Add node to the hash table. + Note that this is only possible _after_ the node has been added to the + tree structure, because add_to_bucket() uses node_position(). */ + if (add_to_bucket (list, new_node) < 0) + { + gl_tree_remove_node_from_tree (list, new_node); + free (new_node); + return NULL; + } + hash_resize_after_add (list); +#endif + + return new_node; +} diff --git a/contrib/tools/bison/lib/gl_anytree_list1.h b/contrib/tools/bison/lib/gl_anytree_list1.h new file mode 100644 index 0000000000..457df319eb --- /dev/null +++ b/contrib/tools/bison/lib/gl_anytree_list1.h @@ -0,0 +1,41 @@ +/* Sequential list data type implemented by a binary tree. + Copyright (C) 2006, 2009-2020 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Common code of gl_avltree_list.c, gl_rbtree_list.c, + gl_avltreehash_list.c, gl_rbtreehash_list.c. */ + +/* An item on the stack used for iterating across the elements. */ +typedef struct +{ + gl_list_node_t node; + size_t rightp; +} iterstack_item_t; + +/* A stack used for iterating across the elements. */ +typedef iterstack_item_t iterstack_t[MAXHEIGHT]; + +/* Frees a non-empty subtree recursively. + This function is recursive and therefore not very fast. */ +static void +free_subtree (gl_list_node_t node) +{ + if (node->left != NULL) + free_subtree (node->left); + if (node->right != NULL) + free_subtree (node->right); + free (node); +} diff --git a/contrib/tools/bison/lib/gl_anytree_list2.h b/contrib/tools/bison/lib/gl_anytree_list2.h new file mode 100644 index 0000000000..ae4d419be5 --- /dev/null +++ b/contrib/tools/bison/lib/gl_anytree_list2.h @@ -0,0 +1,944 @@ +/* Sequential list data type implemented by a binary tree. + Copyright (C) 2006-2020 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Common code of gl_avltree_list.c, gl_rbtree_list.c, + gl_avltreehash_list.c, gl_rbtreehash_list.c. */ + +static gl_list_t +gl_tree_nx_create_empty (gl_list_implementation_t implementation, + gl_listelement_equals_fn equals_fn, + gl_listelement_hashcode_fn hashcode_fn, + gl_listelement_dispose_fn dispose_fn, + bool allow_duplicates) +{ + struct gl_list_impl *list = (struct gl_list_impl *) malloc (sizeof (struct gl_list_impl)); + + if (list == NULL) + return NULL; + + list->base.vtable = implementation; + list->base.equals_fn = equals_fn; + list->base.hashcode_fn = hashcode_fn; + list->base.dispose_fn = dispose_fn; + list->base.allow_duplicates = allow_duplicates; +#if WITH_HASHTABLE + list->table_size = 11; + list->table = + (gl_hash_entry_t *) calloc (list->table_size, sizeof (gl_hash_entry_t)); + if (list->table == NULL) + goto fail; +#endif + list->root = NULL; + + return list; + +#if WITH_HASHTABLE + fail: + free (list); + return NULL; +#endif +} + +static size_t _GL_ATTRIBUTE_PURE +gl_tree_size (gl_list_t list) +{ + return (list->root != NULL ? list->root->branch_size : 0); +} + +static const void * _GL_ATTRIBUTE_PURE +gl_tree_node_value (gl_list_t list _GL_ATTRIBUTE_MAYBE_UNUSED, + gl_list_node_t node) +{ + return node->value; +} + +static int +gl_tree_node_nx_set_value (gl_list_t list _GL_ATTRIBUTE_MAYBE_UNUSED, + gl_list_node_t node, const void *elt) +{ +#if WITH_HASHTABLE + if (elt != node->value) + { + size_t new_hashcode = + (list->base.hashcode_fn != NULL + ? list->base.hashcode_fn (elt) + : (size_t)(uintptr_t) elt); + + if (new_hashcode != node->h.hashcode) + { + remove_from_bucket (list, node); + node->value = elt; + node->h.hashcode = new_hashcode; + if (add_to_bucket (list, node) < 0) + { + /* Out of memory. We removed node from a bucket but cannot add + it to another bucket. In order to avoid inconsistencies, we + must remove node entirely from the list. */ + gl_tree_remove_node_from_tree (list, node); + free (node); + return -1; + } + } + else + node->value = elt; + } +#else + node->value = elt; +#endif + return 0; +} + +static gl_list_node_t _GL_ATTRIBUTE_PURE +gl_tree_next_node (gl_list_t list _GL_ATTRIBUTE_MAYBE_UNUSED, + gl_list_node_t node) +{ + if (node->right != NULL) + { + node = node->right; + while (node->left != NULL) + node = node->left; + } + else + { + while (node->parent != NULL && node->parent->right == node) + node = node->parent; + node = node->parent; + } + return node; +} + +static gl_list_node_t _GL_ATTRIBUTE_PURE +gl_tree_previous_node (gl_list_t list _GL_ATTRIBUTE_MAYBE_UNUSED, + gl_list_node_t node) +{ + if (node->left != NULL) + { + node = node->left; + while (node->right != NULL) + node = node->right; + } + else + { + while (node->parent != NULL && node->parent->left == node) + node = node->parent; + node = node->parent; + } + return node; +} + +/* Returns the node at the given position < gl_tree_size (list). */ +static gl_list_node_t _GL_ATTRIBUTE_PURE +node_at (gl_list_node_t root, size_t position) +{ + /* Here we know that root != NULL. */ + gl_list_node_t node = root; + + for (;;) + { + if (node->left != NULL) + { + if (position < node->left->branch_size) + { + node = node->left; + continue; + } + position -= node->left->branch_size; + } + if (position == 0) + break; + position--; + node = node->right; + } + return node; +} + +static const void * _GL_ATTRIBUTE_PURE +gl_tree_get_at (gl_list_t list, size_t position) +{ + gl_list_node_t node = list->root; + + if (!(node != NULL && position < node->branch_size)) + /* Invalid argument. */ + abort (); + node = node_at (node, position); + return node->value; +} + +static gl_list_node_t +gl_tree_nx_set_at (gl_list_t list, size_t position, const void *elt) +{ + gl_list_node_t node = list->root; + + if (!(node != NULL && position < node->branch_size)) + /* Invalid argument. */ + abort (); + node = node_at (node, position); +#if WITH_HASHTABLE + if (elt != node->value) + { + size_t new_hashcode = + (list->base.hashcode_fn != NULL + ? list->base.hashcode_fn (elt) + : (size_t)(uintptr_t) elt); + + if (new_hashcode != node->h.hashcode) + { + remove_from_bucket (list, node); + node->value = elt; + node->h.hashcode = new_hashcode; + if (add_to_bucket (list, node) < 0) + { + /* Out of memory. We removed node from a bucket but cannot add + it to another bucket. In order to avoid inconsistencies, we + must remove node entirely from the list. */ + gl_tree_remove_node_from_tree (list, node); + free (node); + return NULL; + } + } + else + node->value = elt; + } +#else + node->value = elt; +#endif + return node; +} + +#if !WITH_HASHTABLE + +static gl_list_node_t _GL_ATTRIBUTE_PURE +gl_tree_search_from_to (gl_list_t list, size_t start_index, size_t end_index, + const void *elt) +{ + if (!(start_index <= end_index + && end_index <= (list->root != NULL ? list->root->branch_size : 0))) + /* Invalid arguments. */ + abort (); + { + gl_listelement_equals_fn equals = list->base.equals_fn; + /* Iterate across all elements. */ + gl_list_node_t node = list->root; + iterstack_t stack; + iterstack_item_t *stack_ptr = &stack[0]; + size_t index = 0; + + if (start_index == 0) + { + /* Consider all elements. */ + for (;;) + { + /* Descend on left branch. */ + for (;;) + { + if (node == NULL) + break; + stack_ptr->node = node; + stack_ptr->rightp = 0; + node = node->left; + stack_ptr++; + } + /* Climb up again. */ + for (;;) + { + if (stack_ptr == &stack[0]) + return NULL; + stack_ptr--; + if (!stack_ptr->rightp) + break; + } + node = stack_ptr->node; + /* Test against current element. */ + if (equals != NULL ? equals (elt, node->value) : elt == node->value) + return node; + index++; + if (index >= end_index) + return NULL; + /* Descend on right branch. */ + stack_ptr->rightp = 1; + node = node->right; + stack_ptr++; + } + } + else + { + /* Consider only elements at indices >= start_index. + In this case, rightp contains the difference between the start_index + for the parent node and the one for the child node (0 when the child + node is the parent's left child, > 0 when the child is the parent's + right child). */ + for (;;) + { + /* Descend on left branch. */ + for (;;) + { + if (node == NULL) + break; + if (node->branch_size <= start_index) + break; + stack_ptr->node = node; + stack_ptr->rightp = 0; + node = node->left; + stack_ptr++; + } + /* Climb up again. */ + for (;;) + { + if (stack_ptr == &stack[0]) + return NULL; + stack_ptr--; + if (!stack_ptr->rightp) + break; + start_index += stack_ptr->rightp; + } + node = stack_ptr->node; + { + size_t left_branch_size1 = + (node->left != NULL ? node->left->branch_size : 0) + 1; + if (start_index < left_branch_size1) + { + /* Test against current element. */ + if (equals != NULL ? equals (elt, node->value) : elt == node->value) + return node; + /* Now that we have considered all indices < left_branch_size1, + we can increment start_index. */ + start_index = left_branch_size1; + } + index++; + if (index >= end_index) + return NULL; + /* Descend on right branch. */ + start_index -= left_branch_size1; + stack_ptr->rightp = left_branch_size1; + } + node = node->right; + stack_ptr++; + } + } + } +} + +static size_t _GL_ATTRIBUTE_PURE +gl_tree_indexof_from_to (gl_list_t list, size_t start_index, size_t end_index, + const void *elt) +{ + if (!(start_index <= end_index + && end_index <= (list->root != NULL ? list->root->branch_size : 0))) + /* Invalid arguments. */ + abort (); + { + gl_listelement_equals_fn equals = list->base.equals_fn; + /* Iterate across all elements. */ + gl_list_node_t node = list->root; + iterstack_t stack; + iterstack_item_t *stack_ptr = &stack[0]; + size_t index = 0; + + if (start_index == 0) + { + /* Consider all elements. */ + for (;;) + { + /* Descend on left branch. */ + for (;;) + { + if (node == NULL) + break; + stack_ptr->node = node; + stack_ptr->rightp = 0; + node = node->left; + stack_ptr++; + } + /* Climb up again. */ + for (;;) + { + if (stack_ptr == &stack[0]) + return (size_t)(-1); + stack_ptr--; + if (!stack_ptr->rightp) + break; + } + node = stack_ptr->node; + /* Test against current element. */ + if (equals != NULL ? equals (elt, node->value) : elt == node->value) + return index; + index++; + if (index >= end_index) + return (size_t)(-1); + /* Descend on right branch. */ + stack_ptr->rightp = 1; + node = node->right; + stack_ptr++; + } + } + else + { + /* Consider only elements at indices >= start_index. + In this case, rightp contains the difference between the start_index + for the parent node and the one for the child node (0 when the child + node is the parent's left child, > 0 when the child is the parent's + right child). */ + for (;;) + { + /* Descend on left branch. */ + for (;;) + { + if (node == NULL) + break; + if (node->branch_size <= start_index) + break; + stack_ptr->node = node; + stack_ptr->rightp = 0; + node = node->left; + stack_ptr++; + } + /* Climb up again. */ + for (;;) + { + if (stack_ptr == &stack[0]) + return (size_t)(-1); + stack_ptr--; + if (!stack_ptr->rightp) + break; + start_index += stack_ptr->rightp; + } + node = stack_ptr->node; + { + size_t left_branch_size1 = + (node->left != NULL ? node->left->branch_size : 0) + 1; + if (start_index < left_branch_size1) + { + /* Test against current element. */ + if (equals != NULL ? equals (elt, node->value) : elt == node->value) + return index; + /* Now that we have considered all indices < left_branch_size1, + we can increment start_index. */ + start_index = left_branch_size1; + } + index++; + if (index >= end_index) + return (size_t)(-1); + /* Descend on right branch. */ + start_index -= left_branch_size1; + stack_ptr->rightp = left_branch_size1; + } + node = node->right; + stack_ptr++; + } + } + } +} + +#endif + +static gl_list_node_t +gl_tree_nx_add_at (gl_list_t list, size_t position, const void *elt) +{ + size_t count = (list->root != NULL ? list->root->branch_size : 0); + + if (!(position <= count)) + /* Invalid argument. */ + abort (); + if (position == count) + return gl_tree_nx_add_last (list, elt); + else + return gl_tree_nx_add_before (list, node_at (list->root, position), elt); +} + +static bool +gl_tree_remove_node (gl_list_t list, gl_list_node_t node) +{ +#if WITH_HASHTABLE + /* Remove node from the hash table. + Note that this is only possible _before_ the node is removed from the + tree structure, because remove_from_bucket() uses node_position(). */ + remove_from_bucket (list, node); +#endif + + gl_tree_remove_node_from_tree (list, node); + + if (list->base.dispose_fn != NULL) + list->base.dispose_fn (node->value); + free (node); + return true; +} + +static bool +gl_tree_remove_at (gl_list_t list, size_t position) +{ + gl_list_node_t node = list->root; + + if (!(node != NULL && position < node->branch_size)) + /* Invalid argument. */ + abort (); + node = node_at (node, position); + return gl_tree_remove_node (list, node); +} + +static bool +gl_tree_remove (gl_list_t list, const void *elt) +{ + if (list->root != NULL) + { + gl_list_node_t node = + gl_tree_search_from_to (list, 0, list->root->branch_size, elt); + + if (node != NULL) + return gl_tree_remove_node (list, node); + } + return false; +} + +#if !WITH_HASHTABLE + +static void +gl_tree_list_free (gl_list_t list) +{ + /* Iterate across all elements in post-order. */ + gl_list_node_t node = list->root; + iterstack_t stack; + iterstack_item_t *stack_ptr = &stack[0]; + + for (;;) + { + /* Descend on left branch. */ + for (;;) + { + if (node == NULL) + break; + stack_ptr->node = node; + stack_ptr->rightp = false; + node = node->left; + stack_ptr++; + } + /* Climb up again. */ + for (;;) + { + if (stack_ptr == &stack[0]) + goto done_iterate; + stack_ptr--; + node = stack_ptr->node; + if (!stack_ptr->rightp) + break; + /* Free the current node. */ + if (list->base.dispose_fn != NULL) + list->base.dispose_fn (node->value); + free (node); + } + /* Descend on right branch. */ + stack_ptr->rightp = true; + node = node->right; + stack_ptr++; + } + done_iterate: + free (list); +} + +#endif + +/* --------------------- gl_list_iterator_t Data Type --------------------- */ + +static gl_list_iterator_t _GL_ATTRIBUTE_PURE +gl_tree_iterator (gl_list_t list) +{ + gl_list_iterator_t result; + gl_list_node_t node; + + result.vtable = list->base.vtable; + result.list = list; + /* Start node is the leftmost node. */ + node = list->root; + if (node != NULL) + while (node->left != NULL) + node = node->left; + result.p = node; + /* End point is past the rightmost node. */ + result.q = NULL; +#if defined GCC_LINT || defined lint + result.i = 0; + result.j = 0; + result.count = 0; +#endif + + return result; +} + +static gl_list_iterator_t _GL_ATTRIBUTE_PURE +gl_tree_iterator_from_to (gl_list_t list, size_t start_index, size_t end_index) +{ + size_t count = (list->root != NULL ? list->root->branch_size : 0); + gl_list_iterator_t result; + + if (!(start_index <= end_index && end_index <= count)) + /* Invalid arguments. */ + abort (); + result.vtable = list->base.vtable; + result.list = list; + /* Start node is the node at position start_index. */ + result.p = (start_index < count ? node_at (list->root, start_index) : NULL); + /* End point is the node at position end_index. */ + result.q = (end_index < count ? node_at (list->root, end_index) : NULL); +#if defined GCC_LINT || defined lint + result.i = 0; + result.j = 0; + result.count = 0; +#endif + + return result; +} + +static bool +gl_tree_iterator_next (gl_list_iterator_t *iterator, + const void **eltp, gl_list_node_t *nodep) +{ + if (iterator->p != iterator->q) + { + gl_list_node_t node = (gl_list_node_t) iterator->p; + *eltp = node->value; + if (nodep != NULL) + *nodep = node; + /* Advance to the next node. */ + if (node->right != NULL) + { + node = node->right; + while (node->left != NULL) + node = node->left; + } + else + { + while (node->parent != NULL && node->parent->right == node) + node = node->parent; + node = node->parent; + } + iterator->p = node; + return true; + } + else + return false; +} + +static void +gl_tree_iterator_free (gl_list_iterator_t *iterator _GL_ATTRIBUTE_MAYBE_UNUSED) +{ +} + +/* ---------------------- Sorted gl_list_t Data Type ---------------------- */ + +static gl_list_node_t _GL_ATTRIBUTE_PURE +gl_tree_sortedlist_search (gl_list_t list, gl_listelement_compar_fn compar, + const void *elt) +{ + gl_list_node_t node; + + for (node = list->root; node != NULL; ) + { + int cmp = compar (node->value, elt); + + if (cmp < 0) + node = node->right; + else if (cmp > 0) + node = node->left; + else /* cmp == 0 */ + { + /* We have an element equal to ELT. But we need the leftmost such + element. */ + gl_list_node_t found = node; + node = node->left; + for (; node != NULL; ) + { + int cmp2 = compar (node->value, elt); + + if (cmp2 < 0) + node = node->right; + else if (cmp2 > 0) + /* The list was not sorted. */ + abort (); + else /* cmp2 == 0 */ + { + found = node; + node = node->left; + } + } + return found; + } + } + return NULL; +} + +static gl_list_node_t _GL_ATTRIBUTE_PURE +gl_tree_sortedlist_search_from_to (gl_list_t list, + gl_listelement_compar_fn compar, + size_t low, size_t high, + const void *elt) +{ + gl_list_node_t node; + + if (!(low <= high + && high <= (list->root != NULL ? list->root->branch_size : 0))) + /* Invalid arguments. */ + abort (); + + for (node = list->root; node != NULL; ) + { + size_t left_branch_size = + (node->left != NULL ? node->left->branch_size : 0); + + if (low > left_branch_size) + { + low -= left_branch_size + 1; + high -= left_branch_size + 1; + node = node->right; + } + else if (high <= left_branch_size) + node = node->left; + else + { + /* Here low <= left_branch_size < high. */ + int cmp = compar (node->value, elt); + + if (cmp < 0) + { + low = 0; + high -= left_branch_size + 1; + node = node->right; + } + else if (cmp > 0) + node = node->left; + else /* cmp == 0 */ + { + /* We have an element equal to ELT. But we need the leftmost + such element. */ + gl_list_node_t found = node; + node = node->left; + for (; node != NULL; ) + { + size_t left_branch_size2 = + (node->left != NULL ? node->left->branch_size : 0); + + if (low > left_branch_size2) + { + low -= left_branch_size2 + 1; + node = node->right; + } + else + { + /* Here low <= left_branch_size2. */ + int cmp2 = compar (node->value, elt); + + if (cmp2 < 0) + { + low = 0; + node = node->right; + } + else if (cmp2 > 0) + /* The list was not sorted. */ + abort (); + else /* cmp2 == 0 */ + { + found = node; + node = node->left; + } + } + } + return found; + } + } + } + return NULL; +} + +static size_t _GL_ATTRIBUTE_PURE +gl_tree_sortedlist_indexof (gl_list_t list, gl_listelement_compar_fn compar, + const void *elt) +{ + gl_list_node_t node; + size_t position; + + for (node = list->root, position = 0; node != NULL; ) + { + int cmp = compar (node->value, elt); + + if (cmp < 0) + { + if (node->left != NULL) + position += node->left->branch_size; + position++; + node = node->right; + } + else if (cmp > 0) + node = node->left; + else /* cmp == 0 */ + { + /* We have an element equal to ELT. But we need the leftmost such + element. */ + size_t found_position = + position + (node->left != NULL ? node->left->branch_size : 0); + node = node->left; + for (; node != NULL; ) + { + int cmp2 = compar (node->value, elt); + + if (cmp2 < 0) + { + if (node->left != NULL) + position += node->left->branch_size; + position++; + node = node->right; + } + else if (cmp2 > 0) + /* The list was not sorted. */ + abort (); + else /* cmp2 == 0 */ + { + found_position = + position + + (node->left != NULL ? node->left->branch_size : 0); + node = node->left; + } + } + return found_position; + } + } + return (size_t)(-1); +} + +static size_t _GL_ATTRIBUTE_PURE +gl_tree_sortedlist_indexof_from_to (gl_list_t list, + gl_listelement_compar_fn compar, + size_t low, size_t high, + const void *elt) +{ + gl_list_node_t node; + size_t position; + + if (!(low <= high + && high <= (list->root != NULL ? list->root->branch_size : 0))) + /* Invalid arguments. */ + abort (); + + for (node = list->root, position = 0; node != NULL; ) + { + size_t left_branch_size = + (node->left != NULL ? node->left->branch_size : 0); + + if (low > left_branch_size) + { + low -= left_branch_size + 1; + high -= left_branch_size + 1; + position += left_branch_size + 1; + node = node->right; + } + else if (high <= left_branch_size) + node = node->left; + else + { + /* Here low <= left_branch_size < high. */ + int cmp = compar (node->value, elt); + + if (cmp < 0) + { + low = 0; + high -= left_branch_size + 1; + position += left_branch_size + 1; + node = node->right; + } + else if (cmp > 0) + node = node->left; + else /* cmp == 0 */ + { + /* We have an element equal to ELT. But we need the leftmost + such element. */ + size_t found_position = + position + (node->left != NULL ? node->left->branch_size : 0); + node = node->left; + for (; node != NULL; ) + { + size_t left_branch_size2 = + (node->left != NULL ? node->left->branch_size : 0); + + if (low > left_branch_size2) + { + low -= left_branch_size2 + 1; + node = node->right; + } + else + { + /* Here low <= left_branch_size2. */ + int cmp2 = compar (node->value, elt); + + if (cmp2 < 0) + { + position += left_branch_size2 + 1; + node = node->right; + } + else if (cmp2 > 0) + /* The list was not sorted. */ + abort (); + else /* cmp2 == 0 */ + { + found_position = position + left_branch_size2; + node = node->left; + } + } + } + return found_position; + } + } + } + return (size_t)(-1); +} + +static gl_list_node_t +gl_tree_sortedlist_nx_add (gl_list_t list, gl_listelement_compar_fn compar, + const void *elt) +{ + gl_list_node_t node = list->root; + + if (node == NULL) + return gl_tree_nx_add_first (list, elt); + + for (;;) + { + int cmp = compar (node->value, elt); + + if (cmp < 0) + { + if (node->right == NULL) + return gl_tree_nx_add_after (list, node, elt); + node = node->right; + } + else if (cmp > 0) + { + if (node->left == NULL) + return gl_tree_nx_add_before (list, node, elt); + node = node->left; + } + else /* cmp == 0 */ + return gl_tree_nx_add_before (list, node, elt); + } +} + +static bool +gl_tree_sortedlist_remove (gl_list_t list, gl_listelement_compar_fn compar, + const void *elt) +{ + gl_list_node_t node = gl_tree_sortedlist_search (list, compar, elt); + if (node != NULL) + return gl_tree_remove_node (list, node); + else + return false; +} diff --git a/contrib/tools/bison/lib/gl_anytree_oset.h b/contrib/tools/bison/lib/gl_anytree_oset.h new file mode 100644 index 0000000000..5b3ab13037 --- /dev/null +++ b/contrib/tools/bison/lib/gl_anytree_oset.h @@ -0,0 +1,443 @@ +/* Ordered set data type implemented by a binary tree. + Copyright (C) 2006-2007, 2009-2020 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Common code of gl_avltree_oset.c and gl_rbtree_oset.c. */ + +/* An item on the stack used for iterating across the elements. */ +typedef struct +{ + gl_oset_node_t node; + bool rightp; +} iterstack_item_t; + +/* A stack used for iterating across the elements. */ +typedef iterstack_item_t iterstack_t[MAXHEIGHT]; + +static gl_oset_t +gl_tree_nx_create_empty (gl_oset_implementation_t implementation, + gl_setelement_compar_fn compar_fn, + gl_setelement_dispose_fn dispose_fn) +{ + struct gl_oset_impl *set = + (struct gl_oset_impl *) malloc (sizeof (struct gl_oset_impl)); + + if (set == NULL) + return NULL; + + set->base.vtable = implementation; + set->base.compar_fn = compar_fn; + set->base.dispose_fn = dispose_fn; + set->root = NULL; + set->count = 0; + + return set; +} + +static size_t _GL_ATTRIBUTE_PURE +gl_tree_size (gl_oset_t set) +{ + return set->count; +} + +/* Returns the next node in the tree, or NULL if there is none. */ +static inline gl_oset_node_t _GL_ATTRIBUTE_PURE +gl_tree_next_node (gl_oset_node_t node) +{ + if (node->right != NULL) + { + node = node->right; + while (node->left != NULL) + node = node->left; + } + else + { + while (node->parent != NULL && node->parent->right == node) + node = node->parent; + node = node->parent; + } + return node; +} + +/* Returns the previous node in the tree, or NULL if there is none. */ +static inline gl_oset_node_t _GL_ATTRIBUTE_PURE +gl_tree_prev_node (gl_oset_node_t node) +{ + if (node->left != NULL) + { + node = node->left; + while (node->right != NULL) + node = node->right; + } + else + { + while (node->parent != NULL && node->parent->left == node) + node = node->parent; + node = node->parent; + } + return node; +} + +static bool +gl_tree_search (gl_oset_t set, const void *elt) +{ + gl_setelement_compar_fn compar = set->base.compar_fn; + gl_oset_node_t node; + + for (node = set->root; node != NULL; ) + { + int cmp = (compar != NULL + ? compar (node->value, elt) + : (node->value > elt ? 1 : + node->value < elt ? -1 : 0)); + + if (cmp < 0) + node = node->right; + else if (cmp > 0) + node = node->left; + else /* cmp == 0 */ + /* We have an element equal to ELT. */ + return true; + } + return false; +} + +static bool +gl_tree_search_atleast (gl_oset_t set, + gl_setelement_threshold_fn threshold_fn, + const void *threshold, + const void **eltp) +{ + gl_oset_node_t node; + + for (node = set->root; node != NULL; ) + { + if (! threshold_fn (node->value, threshold)) + node = node->right; + else + { + /* We have an element >= THRESHOLD. But we need the leftmost such + element. */ + gl_oset_node_t found = node; + node = node->left; + for (; node != NULL; ) + { + if (! threshold_fn (node->value, threshold)) + node = node->right; + else + { + found = node; + node = node->left; + } + } + *eltp = found->value; + return true; + } + } + return false; +} + +static gl_oset_node_t +gl_tree_search_node (gl_oset_t set, const void *elt) +{ + gl_setelement_compar_fn compar = set->base.compar_fn; + gl_oset_node_t node; + + for (node = set->root; node != NULL; ) + { + int cmp = (compar != NULL + ? compar (node->value, elt) + : (node->value > elt ? 1 : + node->value < elt ? -1 : 0)); + + if (cmp < 0) + node = node->right; + else if (cmp > 0) + node = node->left; + else /* cmp == 0 */ + /* We have an element equal to ELT. */ + return node; + } + return NULL; +} + +static int +gl_tree_nx_add (gl_oset_t set, const void *elt) +{ + gl_setelement_compar_fn compar; + gl_oset_node_t node = set->root; + + if (node == NULL) + { + if (gl_tree_nx_add_first (set, elt) == NULL) + return -1; + return true; + } + + compar = set->base.compar_fn; + + for (;;) + { + int cmp = (compar != NULL + ? compar (node->value, elt) + : (node->value > elt ? 1 : + node->value < elt ? -1 : 0)); + + if (cmp < 0) + { + if (node->right == NULL) + { + if (gl_tree_nx_add_after (set, node, elt) == NULL) + return -1; + return true; + } + node = node->right; + } + else if (cmp > 0) + { + if (node->left == NULL) + { + if (gl_tree_nx_add_before (set, node, elt) == NULL) + return -1; + return true; + } + node = node->left; + } + else /* cmp == 0 */ + return false; + } +} + +static bool +gl_tree_remove (gl_oset_t set, const void *elt) +{ + gl_oset_node_t node = gl_tree_search_node (set, elt); + + if (node != NULL) + return gl_tree_remove_node (set, node); + else + return false; +} + +static int +gl_tree_update (gl_oset_t set, const void *elt, + void (*action) (const void * /*elt*/, void * /*action_data*/), + void *action_data) +{ + /* Like gl_tree_remove, action (...), gl_tree_nx_add, except that we don't + actually remove ELT. */ + /* Remember the old node. Don't free it. */ + gl_oset_node_t old_node = gl_tree_search_node (set, elt); + /* Invoke ACTION. */ + action (elt, action_data); + /* Determine where to put the node now. */ + if (old_node != NULL) + { + if (set->count > 1) + { + gl_setelement_compar_fn compar = set->base.compar_fn; + + gl_oset_node_t prev_node = gl_tree_prev_node (old_node); + gl_oset_node_t next_node = gl_tree_next_node (old_node); + if (!(compar != NULL + ? (prev_node == NULL || compar (prev_node->value, elt) < 0) + && (next_node == NULL || compar (next_node->value, elt) > 0) + : (prev_node == NULL || prev_node->value < elt) + && (next_node == NULL || next_node->value > elt))) + { + /* old_node needs to move in the tree. */ + gl_oset_node_t node; + + /* Remove the node from the tree. Don't free it. */ + gl_tree_remove_node_no_free (set, old_node); + + node = set->root; + + for (;;) + { + int cmp = (compar != NULL + ? compar (node->value, elt) + : (node->value > elt ? 1 : + node->value < elt ? -1 : 0)); + + if (cmp < 0) + { + if (node->right == NULL) + { + gl_tree_add_node_after (set, node, old_node); + return true; + } + node = node->right; + } + else if (cmp > 0) + { + if (node->left == NULL) + { + gl_tree_add_node_before (set, node, old_node); + return true; + } + node = node->left; + } + else /* cmp == 0 */ + { + /* Two elements are the same. */ + NODE_PAYLOAD_DISPOSE (set, old_node) + free (old_node); + return -1; + } + } + } + } + } + return 0; +} + +static void +gl_tree_oset_free (gl_oset_t set) +{ + /* Iterate across all elements in post-order. */ + gl_oset_node_t node = set->root; + iterstack_t stack; + iterstack_item_t *stack_ptr = &stack[0]; + + for (;;) + { + /* Descend on left branch. */ + for (;;) + { + if (node == NULL) + break; + stack_ptr->node = node; + stack_ptr->rightp = false; + node = node->left; + stack_ptr++; + } + /* Climb up again. */ + for (;;) + { + if (stack_ptr == &stack[0]) + goto done_iterate; + stack_ptr--; + node = stack_ptr->node; + if (!stack_ptr->rightp) + break; + /* Free the current node. */ + if (set->base.dispose_fn != NULL) + set->base.dispose_fn (node->value); + free (node); + } + /* Descend on right branch. */ + stack_ptr->rightp = true; + node = node->right; + stack_ptr++; + } + done_iterate: + free (set); +} + +/* --------------------- gl_oset_iterator_t Data Type --------------------- */ + +static gl_oset_iterator_t _GL_ATTRIBUTE_PURE +gl_tree_iterator (gl_oset_t set) +{ + gl_oset_iterator_t result; + gl_oset_node_t node; + + result.vtable = set->base.vtable; + result.set = set; + /* Start node is the leftmost node. */ + node = set->root; + if (node != NULL) + while (node->left != NULL) + node = node->left; + result.p = node; + /* End point is past the rightmost node. */ + result.q = NULL; +#if defined GCC_LINT || defined lint + result.i = 0; + result.j = 0; + result.count = 0; +#endif + + return result; +} + +static gl_oset_iterator_t +gl_tree_iterator_atleast (gl_oset_t set, + gl_setelement_threshold_fn threshold_fn, + const void *threshold) +{ + gl_oset_iterator_t result; + gl_oset_node_t node; + + result.vtable = set->base.vtable; + result.set = set; + /* End point is past the rightmost node. */ + result.q = NULL; +#if defined GCC_LINT || defined lint + result.i = 0; + result.j = 0; + result.count = 0; +#endif + + for (node = set->root; node != NULL; ) + { + if (! threshold_fn (node->value, threshold)) + node = node->right; + else + { + /* We have an element >= THRESHOLD. But we need the leftmost such + element. */ + gl_oset_node_t found = node; + node = node->left; + for (; node != NULL; ) + { + if (! threshold_fn (node->value, threshold)) + node = node->right; + else + { + found = node; + node = node->left; + } + } + result.p = found; + return result; + } + } + result.p = NULL; + return result; +} + +static bool +gl_tree_iterator_next (gl_oset_iterator_t *iterator, const void **eltp) +{ + if (iterator->p != iterator->q) + { + gl_oset_node_t node = (gl_oset_node_t) iterator->p; + *eltp = node->value; + /* Advance to the next node. */ + node = gl_tree_next_node (node); + iterator->p = node; + return true; + } + else + return false; +} + +static void +gl_tree_iterator_free (gl_oset_iterator_t *iterator _GL_ATTRIBUTE_MAYBE_UNUSED) +{ +} diff --git a/contrib/tools/bison/lib/gl_anytreehash_list1.h b/contrib/tools/bison/lib/gl_anytreehash_list1.h new file mode 100644 index 0000000000..715f602042 --- /dev/null +++ b/contrib/tools/bison/lib/gl_anytreehash_list1.h @@ -0,0 +1,346 @@ +/* Sequential list data type implemented by a hash table with a binary tree. + Copyright (C) 2006-2007, 2009-2020 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Common code of gl_avltreehash_list.c and gl_rbtreehash_list.c. */ + +/* Hash table entry representing the same value at more than one position. */ +struct gl_multiple_nodes +{ + struct gl_hash_entry h; /* hash table entry fields; must be first */ + void *magic; /* used to distinguish from single node */ + gl_oset_t nodes; /* set of nodes, sorted by position */ +}; +/* A value that cannot occur at the corresponding field (->left) in + gl_list_node_impl. */ +#define MULTIPLE_NODES_MAGIC (void *) -1 + +/* Returns the position of the given node in the tree. */ +static size_t _GL_ATTRIBUTE_PURE +node_position (gl_list_node_t node) +{ + size_t position = 0; + + if (node->left != NULL) + position += node->left->branch_size; + for (;;) + { + gl_list_node_t parent = node->parent; + + if (parent == NULL) + return position; + /* position is now relative to the subtree of node. */ + if (parent->right == node) + { + position += 1; + if (parent->left != NULL) + position += parent->left->branch_size; + } + /* position is now relative to the subtree of parent. */ + node = parent; + } +} + +/* Compares two nodes by their position in the tree. */ +static int _GL_ATTRIBUTE_PURE +compare_by_position (const void *x1, const void *x2) +{ + gl_list_node_t node1 = (gl_list_node_t) x1; + gl_list_node_t node2 = (gl_list_node_t) x2; + size_t position1 = node_position (node1); + size_t position2 = node_position (node2); + + return (position1 > position2 ? 1 : + position1 < position2 ? -1 : 0); +} + +/* Compares a node's position in the tree with a given threshold. */ +static bool _GL_ATTRIBUTE_PURE +compare_position_threshold (const void *x, const void *threshold) +{ + gl_list_node_t node = (gl_list_node_t) x; + size_t position = node_position (node); + return (position >= (uintptr_t)threshold); +} + +/* Returns the first element of a non-empty ordered set of nodes. */ +static gl_list_node_t +gl_oset_first (gl_oset_t set) +{ + gl_oset_iterator_t iter = gl_oset_iterator (set); + const void *first; + + if (!gl_oset_iterator_next (&iter, &first)) + abort (); + gl_oset_iterator_free (&iter); + return (gl_list_node_t) first; +} + +/* Adds a node to the hash table structure. + If duplicates are allowed, this function performs in average time + O((log n)^2): gl_oset_nx_add may need to add an element to an ordered set + of size O(n), needing O(log n) comparison function calls. The comparison + function is compare_by_position, which is O(log n) worst-case. + If duplicates are forbidden, this function is O(1). + Return 0 upon success, -1 upon out-of-memory. */ +static int +add_to_bucket (gl_list_t list, gl_list_node_t new_node) +{ + size_t bucket = new_node->h.hashcode % list->table_size; + + /* If no duplicates are allowed, multiple nodes are not needed. */ + if (list->base.allow_duplicates) + { + size_t hashcode = new_node->h.hashcode; + const void *value = new_node->value; + gl_listelement_equals_fn equals = list->base.equals_fn; + gl_hash_entry_t *entryp; + + for (entryp = &list->table[bucket]; *entryp != NULL; entryp = &(*entryp)->hash_next) + { + gl_hash_entry_t entry = *entryp; + + if (entry->hashcode == hashcode) + { + if (((struct gl_multiple_nodes *) entry)->magic == MULTIPLE_NODES_MAGIC) + { + /* An entry representing multiple nodes. */ + gl_oset_t nodes = ((struct gl_multiple_nodes *) entry)->nodes; + /* Only the first node is interesting. */ + gl_list_node_t node = gl_oset_first (nodes); + if (equals != NULL ? equals (value, node->value) : value == node->value) + { + /* Found already multiple nodes with the same value. + Add the new_node to it. */ + return gl_oset_nx_add (nodes, new_node); + } + } + else + { + /* An entry representing a single node. */ + gl_list_node_t node = (struct gl_list_node_impl *) entry; + if (equals != NULL ? equals (value, node->value) : value == node->value) + { + /* Found already a node with the same value. Turn it + into an ordered set, and add new_node to it. */ + gl_oset_t nodes; + struct gl_multiple_nodes *multi_entry; + + nodes = + gl_oset_nx_create_empty (OSET_TREE_FLAVOR, + compare_by_position, NULL); + if (nodes == NULL) + return -1; + + if (gl_oset_nx_add (nodes, node) < 0) + goto fail; + if (gl_oset_nx_add (nodes, new_node) < 0) + goto fail; + + multi_entry = + (struct gl_multiple_nodes *) malloc (sizeof (struct gl_multiple_nodes)); + if (multi_entry == NULL) + goto fail; + multi_entry->h.hash_next = entry->hash_next; + multi_entry->h.hashcode = entry->hashcode; + multi_entry->magic = MULTIPLE_NODES_MAGIC; + multi_entry->nodes = nodes; + *entryp = &multi_entry->h; + return 0; + + fail: + gl_oset_free (nodes); + return -1; + } + } + } + } + } + /* If no duplicates are allowed, multiple nodes are not needed. */ + new_node->h.hash_next = list->table[bucket]; + list->table[bucket] = &new_node->h; + return 0; +} +/* Tell GCC that the likely return value is 0. */ +#define add_to_bucket(list,node) \ + __builtin_expect ((add_to_bucket) (list, node), 0) + +/* Removes a node from the hash table structure. + If duplicates are allowed, this function performs in average time + O((log n)^2): gl_oset_remove may need to remove an element from an ordered + set of size O(n), needing O(log n) comparison function calls. The + comparison function is compare_by_position, which is O(log n) worst-case. + If duplicates are forbidden, this function is O(1) on average. */ +static void +remove_from_bucket (gl_list_t list, gl_list_node_t old_node) +{ + size_t bucket = old_node->h.hashcode % list->table_size; + + if (list->base.allow_duplicates) + { + size_t hashcode = old_node->h.hashcode; + const void *value = old_node->value; + gl_listelement_equals_fn equals = list->base.equals_fn; + gl_hash_entry_t *entryp; + + for (entryp = &list->table[bucket]; ; entryp = &(*entryp)->hash_next) + { + gl_hash_entry_t entry = *entryp; + + if (entry == &old_node->h) + { + /* Found old_node as a single node in the bucket. Remove it. */ + *entryp = old_node->h.hash_next; + break; + } + if (entry == NULL) + /* node is not in the right bucket. Did the hash codes + change inadvertently? */ + abort (); + if (((struct gl_multiple_nodes *) entry)->magic == MULTIPLE_NODES_MAGIC + && entry->hashcode == hashcode) + { + /* An entry representing multiple nodes. */ + gl_oset_t nodes = ((struct gl_multiple_nodes *) entry)->nodes; + /* Only the first node is interesting. */ + gl_list_node_t node = gl_oset_first (nodes); + if (equals != NULL ? equals (value, node->value) : value == node->value) + { + /* Found multiple nodes with the same value. + old_node must be one of them. Remove it. */ + if (!gl_oset_remove (nodes, old_node)) + abort (); + if (gl_oset_size (nodes) == 1) + { + /* Replace a one-element set with a single node. */ + node = gl_oset_first (nodes); + node->h.hash_next = entry->hash_next; + *entryp = &node->h; + gl_oset_free (nodes); + free (entry); + } + break; + } + } + } + } + else + { + /* If no duplicates are allowed, multiple nodes are not needed. */ + gl_hash_entry_t *entryp; + + for (entryp = &list->table[bucket]; ; entryp = &(*entryp)->hash_next) + { + if (*entryp == &old_node->h) + { + *entryp = old_node->h.hash_next; + break; + } + if (*entryp == NULL) + /* node is not in the right bucket. Did the hash codes + change inadvertently? */ + abort (); + } + } +} + +/* Builds up the hash table during initialization: Stores all the nodes of + list->root in the hash table. + Returns 0 upon success, -1 upon out-of-memory. */ +static int +add_nodes_to_buckets (gl_list_t list) +{ + /* Iterate across all nodes. */ + gl_list_node_t node = list->root; + iterstack_t stack; + iterstack_item_t *stack_ptr = &stack[0]; + + for (;;) + { + /* Descend on left branch. */ + for (;;) + { + if (node == NULL) + break; + stack_ptr->node = node; + stack_ptr->rightp = false; + node = node->left; + stack_ptr++; + } + /* Climb up again. */ + for (;;) + { + if (stack_ptr == &stack[0]) + goto done; + stack_ptr--; + if (!stack_ptr->rightp) + break; + } + node = stack_ptr->node; + /* Add the current node to the hash table. */ + node->h.hashcode = + (list->base.hashcode_fn != NULL + ? list->base.hashcode_fn (node->value) + : (size_t)(uintptr_t) node->value); + if (add_to_bucket (list, node) < 0) + goto fail; + /* Descend on right branch. */ + stack_ptr->rightp = true; + node = node->right; + stack_ptr++; + } + done: + return 0; + + fail: + /* Undo everything. */ + for (;;) + { + /* Descend on left branch. */ + stack_ptr->rightp = false; + node = node->left; + stack_ptr++; + /* Descend on right branch. */ + for (;;) + { + if (node == NULL) + break; + stack_ptr->node = node; + stack_ptr->rightp = true; + node = node->right; + stack_ptr++; + } + /* Climb up again. */ + for (;;) + { + if (stack_ptr == &stack[0]) + goto fail_done; + stack_ptr--; + if (stack_ptr->rightp) + break; + } + node = stack_ptr->node; + /* Remove the current node from the hash table. */ + remove_from_bucket (list, node); + } + fail_done: + return -1; +} +/* Tell GCC that the likely return value is 0. */ +#if (__GNUC__ >= 3) || (__clang_major__ >= 4) +# define add_nodes_to_buckets(list) \ + __builtin_expect ((add_nodes_to_buckets) (list), 0) +#endif diff --git a/contrib/tools/bison/lib/gl_anytreehash_list2.h b/contrib/tools/bison/lib/gl_anytreehash_list2.h new file mode 100644 index 0000000000..26e52bf389 --- /dev/null +++ b/contrib/tools/bison/lib/gl_anytreehash_list2.h @@ -0,0 +1,213 @@ +/* Sequential list data type implemented by a hash table with a binary tree. + Copyright (C) 2006-2007, 2009-2020 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Common code of gl_avltreehash_list.c and gl_rbtreehash_list.c. */ + +static gl_list_node_t +gl_tree_search_from_to (gl_list_t list, size_t start_index, size_t end_index, + const void *elt) +{ + if (!(start_index <= end_index + && end_index <= (list->root != NULL ? list->root->branch_size : 0))) + /* Invalid arguments. */ + abort (); + { + size_t hashcode = + (list->base.hashcode_fn != NULL + ? list->base.hashcode_fn (elt) + : (size_t)(uintptr_t) elt); + size_t bucket = hashcode % list->table_size; + gl_listelement_equals_fn equals = list->base.equals_fn; + gl_hash_entry_t entry; + + if (list->base.allow_duplicates) + { + for (entry = list->table[bucket]; entry != NULL; entry = entry->hash_next) + if (entry->hashcode == hashcode) + { + if (((struct gl_multiple_nodes *) entry)->magic == MULTIPLE_NODES_MAGIC) + { + /* An entry representing multiple nodes. */ + gl_oset_t nodes = ((struct gl_multiple_nodes *) entry)->nodes; + /* The first node is interesting. */ + gl_list_node_t node = gl_oset_first (nodes); + if (equals != NULL ? equals (elt, node->value) : elt == node->value) + { + /* All nodes in the entry are equal to the given ELT. */ + if (start_index == 0) + { + /* We have to return only the one at the minimal + position, and this is the first one in the ordered + set. */ + if (end_index == list->root->branch_size + || node_position (node) < end_index) + return node; + } + else + { + /* We have to return only the one at the minimal + position >= start_index. */ + const void *nodes_elt; + if (gl_oset_search_atleast (nodes, + compare_position_threshold, + (void *)(uintptr_t)start_index, + &nodes_elt)) + { + node = (gl_list_node_t) nodes_elt; + if (end_index == list->root->branch_size + || node_position (node) < end_index) + return node; + } + } + break; + } + } + else + { + /* An entry representing a single node. */ + gl_list_node_t node = (struct gl_list_node_impl *) entry; + if (equals != NULL ? equals (elt, node->value) : elt == node->value) + { + bool position_in_bounds; + if (start_index == 0 && end_index == list->root->branch_size) + position_in_bounds = true; + else + { + size_t position = node_position (node); + position_in_bounds = + (position >= start_index && position < end_index); + } + if (position_in_bounds) + return node; + break; + } + } + } + } + else + { + /* If no duplicates are allowed, multiple nodes are not needed. */ + for (entry = list->table[bucket]; entry != NULL; entry = entry->hash_next) + if (entry->hashcode == hashcode) + { + gl_list_node_t node = (struct gl_list_node_impl *) entry; + if (equals != NULL ? equals (elt, node->value) : elt == node->value) + { + bool position_in_bounds; + if (start_index == 0 && end_index == list->root->branch_size) + position_in_bounds = true; + else + { + size_t position = node_position (node); + position_in_bounds = + (position >= start_index && position < end_index); + } + if (position_in_bounds) + return node; + break; + } + } + } + + return NULL; + } +} + +static size_t +gl_tree_indexof_from_to (gl_list_t list, size_t start_index, size_t end_index, + const void *elt) +{ + gl_list_node_t node = + gl_tree_search_from_to (list, start_index, end_index, elt); + + if (node != NULL) + return node_position (node); + else + return (size_t)(-1); +} + +static void +gl_tree_list_free (gl_list_t list) +{ + if (list->base.allow_duplicates) + { + /* Free the ordered sets in the hash buckets. */ + size_t i; + + for (i = list->table_size; i > 0; ) + { + gl_hash_entry_t entry = list->table[--i]; + + while (entry != NULL) + { + gl_hash_entry_t next = entry->hash_next; + + if (((struct gl_multiple_nodes *) entry)->magic == MULTIPLE_NODES_MAGIC) + { + gl_oset_t nodes = ((struct gl_multiple_nodes *) entry)->nodes; + + gl_oset_free (nodes); + free (entry); + } + + entry = next; + } + } + } + + /* Iterate across all elements in post-order. */ + { + gl_list_node_t node = list->root; + iterstack_t stack; + iterstack_item_t *stack_ptr = &stack[0]; + + for (;;) + { + /* Descend on left branch. */ + for (;;) + { + if (node == NULL) + break; + stack_ptr->node = node; + stack_ptr->rightp = false; + node = node->left; + stack_ptr++; + } + /* Climb up again. */ + for (;;) + { + if (stack_ptr == &stack[0]) + goto done_iterate; + stack_ptr--; + node = stack_ptr->node; + if (!stack_ptr->rightp) + break; + /* Free the current node. */ + if (list->base.dispose_fn != NULL) + list->base.dispose_fn (node->value); + free (node); + } + /* Descend on right branch. */ + stack_ptr->rightp = true; + node = node->right; + stack_ptr++; + } + } + done_iterate: + free (list->table); + free (list); +} diff --git a/contrib/tools/bison/lib/gl_array_list.c b/contrib/tools/bison/lib/gl_array_list.c index 49509620f7..3d9020e5d8 100644 --- a/contrib/tools/bison/lib/gl_array_list.c +++ b/contrib/tools/bison/lib/gl_array_list.c @@ -111,7 +111,7 @@ gl_array_nx_create (gl_list_implementation_t implementation, return NULL; } -static size_t +static size_t _GL_ATTRIBUTE_PURE gl_array_size (gl_list_t list) { return list->count; @@ -189,7 +189,7 @@ gl_array_nx_set_at (gl_list_t list, size_t position, const void *elt) return INDEX_TO_NODE (position); } -static size_t +static size_t _GL_ATTRIBUTE_PURE gl_array_indexof_from_to (gl_list_t list, size_t start_index, size_t end_index, const void *elt) { @@ -232,7 +232,7 @@ gl_array_indexof_from_to (gl_list_t list, size_t start_index, size_t end_index, return (size_t)(-1); } -static gl_list_node_t +static gl_list_node_t _GL_ATTRIBUTE_PURE gl_array_search_from_to (gl_list_t list, size_t start_index, size_t end_index, const void *elt) { @@ -441,7 +441,7 @@ gl_array_list_free (gl_list_t list) /* --------------------- gl_list_iterator_t Data Type --------------------- */ -static gl_list_iterator_t +static gl_list_iterator_t _GL_ATTRIBUTE_PURE gl_array_iterator (gl_list_t list) { gl_list_iterator_t result; @@ -459,7 +459,7 @@ gl_array_iterator (gl_list_t list) return result; } -static gl_list_iterator_t +static gl_list_iterator_t _GL_ATTRIBUTE_PURE gl_array_iterator_from_to (gl_list_t list, size_t start_index, size_t end_index) { gl_list_iterator_t result; @@ -509,13 +509,13 @@ gl_array_iterator_next (gl_list_iterator_t *iterator, } static void -gl_array_iterator_free (gl_list_iterator_t *iterator _GL_UNUSED) +gl_array_iterator_free (gl_list_iterator_t *iterator _GL_ATTRIBUTE_MAYBE_UNUSED) { } /* ---------------------- Sorted gl_list_t Data Type ---------------------- */ -static size_t +static size_t _GL_ATTRIBUTE_PURE gl_array_sortedlist_indexof_from_to (gl_list_t list, gl_listelement_compar_fn compar, size_t low, size_t high, @@ -574,7 +574,7 @@ gl_array_sortedlist_indexof_from_to (gl_list_t list, return (size_t)(-1); } -static size_t +static size_t _GL_ATTRIBUTE_PURE gl_array_sortedlist_indexof (gl_list_t list, gl_listelement_compar_fn compar, const void *elt) { @@ -582,7 +582,7 @@ gl_array_sortedlist_indexof (gl_list_t list, gl_listelement_compar_fn compar, elt); } -static gl_list_node_t +static gl_list_node_t _GL_ATTRIBUTE_PURE gl_array_sortedlist_search_from_to (gl_list_t list, gl_listelement_compar_fn compar, size_t low, size_t high, @@ -593,7 +593,7 @@ gl_array_sortedlist_search_from_to (gl_list_t list, return INDEX_TO_NODE (index); } -static gl_list_node_t +static gl_list_node_t _GL_ATTRIBUTE_PURE gl_array_sortedlist_search (gl_list_t list, gl_listelement_compar_fn compar, const void *elt) { diff --git a/contrib/tools/bison/lib/gl_linked_list.c b/contrib/tools/bison/lib/gl_linked_list.c new file mode 100644 index 0000000000..b1391cef9a --- /dev/null +++ b/contrib/tools/bison/lib/gl_linked_list.c @@ -0,0 +1,64 @@ +/* Sequential list data type implemented by a linked list. + Copyright (C) 2006, 2008-2020 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include "gl_linked_list.h" + +#include <stdlib.h> + +/* -------------------------- gl_list_t Data Type -------------------------- */ + +/* Generic linked list code. */ +#include "gl_anylinked_list1.h" +#include "gl_anylinked_list2.h" + + +const struct gl_list_implementation gl_linked_list_implementation = + { + gl_linked_nx_create_empty, + gl_linked_nx_create, + gl_linked_size, + gl_linked_node_value, + gl_linked_node_nx_set_value, + gl_linked_next_node, + gl_linked_previous_node, + gl_linked_get_at, + gl_linked_nx_set_at, + gl_linked_search_from_to, + gl_linked_indexof_from_to, + gl_linked_nx_add_first, + gl_linked_nx_add_last, + gl_linked_nx_add_before, + gl_linked_nx_add_after, + gl_linked_nx_add_at, + gl_linked_remove_node, + gl_linked_remove_at, + gl_linked_remove, + gl_linked_list_free, + gl_linked_iterator, + gl_linked_iterator_from_to, + gl_linked_iterator_next, + gl_linked_iterator_free, + gl_linked_sortedlist_search, + gl_linked_sortedlist_search_from_to, + gl_linked_sortedlist_indexof, + gl_linked_sortedlist_indexof_from_to, + gl_linked_sortedlist_nx_add, + gl_linked_sortedlist_remove + }; diff --git a/contrib/tools/bison/lib/gl_linked_list.h b/contrib/tools/bison/lib/gl_linked_list.h new file mode 100644 index 0000000000..163e92d4c9 --- /dev/null +++ b/contrib/tools/bison/lib/gl_linked_list.h @@ -0,0 +1,34 @@ +/* Sequential list data type implemented by a linked list. + Copyright (C) 2006, 2009-2020 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _GL_LINKED_LIST_H +#define _GL_LINKED_LIST_H + +#include "gl_list.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const struct gl_list_implementation gl_linked_list_implementation; +#define GL_LINKED_LIST &gl_linked_list_implementation + +#ifdef __cplusplus +} +#endif + +#endif /* _GL_LINKED_LIST_H */ diff --git a/contrib/tools/bison/lib/gl_oset.c b/contrib/tools/bison/lib/gl_oset.c new file mode 100644 index 0000000000..21f731a31a --- /dev/null +++ b/contrib/tools/bison/lib/gl_oset.c @@ -0,0 +1,3 @@ +#include <config.h> +#define GL_OSET_INLINE _GL_EXTERN_INLINE +#include "gl_oset.h" diff --git a/contrib/tools/bison/lib/gl_oset.h b/contrib/tools/bison/lib/gl_oset.h new file mode 100644 index 0000000000..9e44892d99 --- /dev/null +++ b/contrib/tools/bison/lib/gl_oset.h @@ -0,0 +1,336 @@ +/* Abstract ordered set data type. + Copyright (C) 2006-2007, 2009-2020 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _GL_OSET_H +#define _GL_OSET_H + +#include <stdbool.h> +#include <stddef.h> + +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef GL_OSET_INLINE +# define GL_OSET_INLINE _GL_INLINE +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +/* gl_oset is an abstract ordered set data type. It can contain any number + of objects ('void *' or 'const void *' pointers) in the order of a given + comparator function. Duplicates (in the sense of the comparator) are + forbidden. + + There are several implementations of this ordered set datatype, optimized + for different operations or for memory. You can start using the simplest + ordered set implementation, GL_ARRAY_OSET, and switch to a different + implementation later, when you realize which operations are performed + the most frequently. The API of the different implementations is exactly + the same; when switching to a different implementation, you only have to + change the gl_oset_create call. + + The implementations are: + GL_ARRAY_OSET a growable array + GL_AVLTREE_OSET a binary tree (AVL tree) + GL_RBTREE_OSET a binary tree (red-black tree) + + The memory consumption is asymptotically the same: O(1) for every object + in the set. When looking more closely at the average memory consumed + for an object, GL_ARRAY_OSET is the most compact representation, and + GL_AVLTREE_OSET, GL_RBTREE_OSET need more memory. + + The guaranteed average performance of the operations is, for a set of + n elements: + + Operation ARRAY TREE + + gl_oset_size O(1) O(1) + gl_oset_add O(n) O(log n) + gl_oset_remove O(n) O(log n) + gl_oset_update O(n) O(log n) + gl_oset_search O(log n) O(log n) + gl_oset_search_atleast O(log n) O(log n) + gl_oset_iterator O(1) O(log n) + gl_oset_iterator_atleast O(log n) O(log n) + gl_oset_iterator_next O(1) O(log n) + */ + +/* -------------------------- gl_oset_t Data Type -------------------------- */ + +/* Type of function used to compare two elements. Same as for qsort(). + NULL denotes pointer comparison. */ +typedef int (*gl_setelement_compar_fn) (const void *elt1, const void *elt2); + +#ifndef _GL_SETELEMENT_DISPOSE_FN_DEFINED +/* Type of function used to dispose an element once it's removed from a set. + NULL denotes a no-op. */ +typedef void (*gl_setelement_dispose_fn) (const void *elt); +# define _GL_SETELEMENT_DISPOSE_FN_DEFINED 1 +#endif + +/* Type of function used to compare an element with a threshold. + Returns true if the element is greater or equal than the threshold. */ +typedef bool (*gl_setelement_threshold_fn) (const void *elt, const void *threshold); + +struct gl_oset_impl; +/* Type representing an entire ordered set. */ +typedef struct gl_oset_impl * gl_oset_t; + +struct gl_oset_implementation; +/* Type representing a ordered set datatype implementation. */ +typedef const struct gl_oset_implementation * gl_oset_implementation_t; + +#if 0 /* Unless otherwise specified, these are defined inline below. */ + +/* Creates an empty set. + IMPLEMENTATION is one of GL_ARRAY_OSET, GL_AVLTREE_OSET, GL_RBTREE_OSET. + COMPAR_FN is an element comparison function or NULL. + DISPOSE_FN is an element disposal function or NULL. */ +/* declared in gl_xoset.h */ +extern gl_oset_t gl_oset_create_empty (gl_oset_implementation_t implementation, + gl_setelement_compar_fn compar_fn, + gl_setelement_dispose_fn dispose_fn); +/* Likewise. Returns NULL upon out-of-memory. */ +extern gl_oset_t gl_oset_nx_create_empty (gl_oset_implementation_t implementation, + gl_setelement_compar_fn compar_fn, + gl_setelement_dispose_fn dispose_fn); + +/* Returns the current number of elements in an ordered set. */ +extern size_t gl_oset_size (gl_oset_t set); + +/* Searches whether an element is already in the ordered set. + Returns true if found, or false if not present in the set. */ +extern bool gl_oset_search (gl_oset_t set, const void *elt); + +/* Searches the least element in the ordered set that compares greater or equal + to the given THRESHOLD. The representation of the THRESHOLD is defined + by the THRESHOLD_FN. + Returns true and stores the found element in *ELTP if found, otherwise returns + false. */ +extern bool gl_oset_search_atleast (gl_oset_t set, + gl_setelement_threshold_fn threshold_fn, + const void *threshold, + const void **eltp); + +/* Adds an element to an ordered set. + Returns true if it was not already in the set and added, false otherwise. */ +/* declared in gl_xoset.h */ +extern bool gl_oset_add (gl_oset_t set, const void *elt); +/* Likewise. Returns -1 upon out-of-memory. */ +extern int gl_oset_nx_add (gl_oset_t set, const void *elt) + _GL_ATTRIBUTE_NODISCARD; + +/* Removes an element from an ordered set. + Returns true if it was found and removed. */ +extern bool gl_oset_remove (gl_oset_t set, const void *elt); + +/* Invokes ACTION (ELT, ACTION_DATA) and updates the given ordered set if, + during this invocation, the attributes/properties of the element ELT change + in a way that influences the comparison function. + Warning: During the invocation of ACTION, the ordered set is inconsistent + and must not be accessed! + Returns 1 if the position of the element in the ordered set has changed as + a consequence, 0 if the element stayed at the same position, or -1 if it + collided with another element and was therefore removed. */ +extern int gl_oset_update (gl_oset_t set, const void *elt, + void (*action) (const void *elt, void *action_data), + void *action_data); + +/* Frees an entire ordered set. + (But this call does not free the elements of the set. It only invokes + the DISPOSE_FN on each of the elements of the set.) */ +extern void gl_oset_free (gl_oset_t set); + +#endif /* End of inline and gl_xoset.h-defined functions. */ + +/* --------------------- gl_oset_iterator_t Data Type --------------------- */ + +/* Functions for iterating through an ordered set. */ + +/* Type of an iterator that traverses an ordered set. + This is a fixed-size struct, so that creation of an iterator doesn't need + memory allocation on the heap. */ +typedef struct +{ + /* For fast dispatch of gl_oset_iterator_next. */ + const struct gl_oset_implementation *vtable; + /* For detecting whether the last returned element was removed. */ + gl_oset_t set; + size_t count; + /* Other, implementation-private fields. */ + void *p; void *q; + size_t i; size_t j; +} gl_oset_iterator_t; + +#if 0 /* These are defined inline below. */ + +/* Creates an iterator traversing an ordered set. + The set's contents must not be modified while the iterator is in use, + except for removing the last returned element. */ +extern gl_oset_iterator_t gl_oset_iterator (gl_oset_t set); + +/* Creates an iterator traversing the tail of an ordered set, that comprises + the elements that compare greater or equal to the given THRESHOLD. The + representation of the THRESHOLD is defined by the THRESHOLD_FN. */ +extern gl_oset_iterator_t gl_oset_iterator_atleast (gl_oset_t set, + gl_setelement_threshold_fn threshold_fn, + const void *threshold); + +/* If there is a next element, stores the next element in *ELTP, advances the + iterator and returns true. Otherwise, returns false. */ +extern bool gl_oset_iterator_next (gl_oset_iterator_t *iterator, + const void **eltp); + +/* Frees an iterator. */ +extern void gl_oset_iterator_free (gl_oset_iterator_t *iterator); + +#endif /* End of inline functions. */ + +/* ------------------------ Implementation Details ------------------------ */ + +struct gl_oset_implementation +{ + /* gl_oset_t functions. */ + gl_oset_t (*nx_create_empty) (gl_oset_implementation_t implementation, + gl_setelement_compar_fn compar_fn, + gl_setelement_dispose_fn dispose_fn); + size_t (*size) (gl_oset_t set); + bool (*search) (gl_oset_t set, const void *elt); + bool (*search_atleast) (gl_oset_t set, + gl_setelement_threshold_fn threshold_fn, + const void *threshold, const void **eltp); + int (*nx_add) (gl_oset_t set, const void *elt); + bool (*remove_elt) (gl_oset_t set, const void *elt); + int (*update) (gl_oset_t set, const void *elt, + void (*action) (const void * /*elt*/, void * /*action_data*/), + void *action_data); + void (*oset_free) (gl_oset_t set); + /* gl_oset_iterator_t functions. */ + gl_oset_iterator_t (*iterator) (gl_oset_t set); + gl_oset_iterator_t (*iterator_atleast) (gl_oset_t set, + gl_setelement_threshold_fn threshold_fn, + const void *threshold); + bool (*iterator_next) (gl_oset_iterator_t *iterator, const void **eltp); + void (*iterator_free) (gl_oset_iterator_t *iterator); +}; + +struct gl_oset_impl_base +{ + const struct gl_oset_implementation *vtable; + gl_setelement_compar_fn compar_fn; + gl_setelement_dispose_fn dispose_fn; +}; + +/* Define all functions of this file as accesses to the + struct gl_oset_implementation. */ + +GL_OSET_INLINE gl_oset_t +gl_oset_nx_create_empty (gl_oset_implementation_t implementation, + gl_setelement_compar_fn compar_fn, + gl_setelement_dispose_fn dispose_fn) +{ + return implementation->nx_create_empty (implementation, compar_fn, + dispose_fn); +} + +GL_OSET_INLINE size_t +gl_oset_size (gl_oset_t set) +{ + return ((const struct gl_oset_impl_base *) set)->vtable->size (set); +} + +GL_OSET_INLINE bool +gl_oset_search (gl_oset_t set, const void *elt) +{ + return ((const struct gl_oset_impl_base *) set)->vtable->search (set, elt); +} + +GL_OSET_INLINE bool +gl_oset_search_atleast (gl_oset_t set, + gl_setelement_threshold_fn threshold_fn, + const void *threshold, const void **eltp) +{ + return ((const struct gl_oset_impl_base *) set)->vtable + ->search_atleast (set, threshold_fn, threshold, eltp); +} + +GL_OSET_INLINE _GL_ATTRIBUTE_NODISCARD int +gl_oset_nx_add (gl_oset_t set, const void *elt) +{ + return ((const struct gl_oset_impl_base *) set)->vtable->nx_add (set, elt); +} + +GL_OSET_INLINE bool +gl_oset_remove (gl_oset_t set, const void *elt) +{ + return ((const struct gl_oset_impl_base *) set)->vtable + ->remove_elt (set, elt); +} + +GL_OSET_INLINE int +gl_oset_update (gl_oset_t set, const void *elt, + void (*action) (const void * /*elt*/, void * /*action_data*/), + void *action_data) +{ + return ((const struct gl_oset_impl_base *) set)->vtable + ->update (set, elt, action, action_data); +} + +GL_OSET_INLINE void +gl_oset_free (gl_oset_t set) +{ + ((const struct gl_oset_impl_base *) set)->vtable->oset_free (set); +} + +GL_OSET_INLINE gl_oset_iterator_t +gl_oset_iterator (gl_oset_t set) +{ + return ((const struct gl_oset_impl_base *) set)->vtable->iterator (set); +} + +GL_OSET_INLINE gl_oset_iterator_t +gl_oset_iterator_atleast (gl_oset_t set, + gl_setelement_threshold_fn threshold_fn, + const void *threshold) +{ + return ((const struct gl_oset_impl_base *) set)->vtable + ->iterator_atleast (set, threshold_fn, threshold); +} + +GL_OSET_INLINE bool +gl_oset_iterator_next (gl_oset_iterator_t *iterator, const void **eltp) +{ + return iterator->vtable->iterator_next (iterator, eltp); +} + +GL_OSET_INLINE void +gl_oset_iterator_free (gl_oset_iterator_t *iterator) +{ + iterator->vtable->iterator_free (iterator); +} + +#ifdef __cplusplus +} +#endif + +_GL_INLINE_HEADER_END + +#endif /* _GL_OSET_H */ diff --git a/contrib/tools/bison/lib/gl_rbtree_ordered.h b/contrib/tools/bison/lib/gl_rbtree_ordered.h new file mode 100644 index 0000000000..8625afef46 --- /dev/null +++ b/contrib/tools/bison/lib/gl_rbtree_ordered.h @@ -0,0 +1,800 @@ +/* Ordered {set,map} data type implemented by a binary tree. + Copyright (C) 2006-2007, 2009-2020 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* A red-black tree is a binary tree where every node is colored black or + red such that + 1. The root is black. + 2. No red node has a red parent. + Or equivalently: No red node has a red child. + 3. All paths from the root down to any NULL endpoint contain the same + number of black nodes. + Let's call this the "black-height" bh of the tree. It follows that every + such path contains exactly bh black and between 0 and bh red nodes. (The + extreme cases are a path containing only black nodes, and a path colored + alternately black-red-black-red-...-black-red.) The height of the tree + therefore is >= bh, <= 2*bh. + */ + +/* Color of a node. */ +typedef enum color { BLACK, RED } color_t; + +/* Tree node implementation, valid for this file only. */ +struct NODE_IMPL +{ + struct NODE_IMPL *left; /* left branch, or NULL */ + struct NODE_IMPL *right; /* right branch, or NULL */ + /* Parent pointer, or NULL. The parent pointer is not needed for most + operations. It is needed so that a NODE_T can be returned without + memory allocation, on which the functions <container>_remove_node, + <container>_add_before, <container>_add_after can be implemented. */ + struct NODE_IMPL *parent; + color_t color; /* node's color */ + NODE_PAYLOAD_FIELDS +}; +typedef struct NODE_IMPL * NODE_T; + +/* Concrete CONTAINER_IMPL type, valid for this file only. */ +struct CONTAINER_IMPL +{ + struct CONTAINER_IMPL_BASE base; + struct NODE_IMPL *root; /* root node or NULL */ + size_t count; /* number of nodes */ +}; + +/* A red-black tree of height h has a black-height bh >= ceil(h/2) and + therefore at least 2^ceil(h/2) - 1 elements. So, h <= 116 (because a tree + of height h >= 117 would have at least 2^59 - 1 elements, and because even + on 64-bit machines, + sizeof (NODE_IMPL) * (2^59 - 1) > 2^64 + this would exceed the address space of the machine. */ +#define MAXHEIGHT 116 + +/* Rotates left a subtree. + + B D + / \ / \ + A D --> B E + / \ / \ + C E A C + + Changes the tree structure, updates the branch sizes. + The caller must update the colors and register D as child of its parent. */ +static NODE_T +rotate_left (NODE_T b_node, NODE_T d_node) +{ + NODE_T c_node = d_node->left; + + b_node->right = c_node; + d_node->left = b_node; + + d_node->parent = b_node->parent; + b_node->parent = d_node; + if (c_node != NULL) + c_node->parent = b_node; + + return d_node; +} + +/* Rotates right a subtree. + + D B + / \ / \ + B E --> A D + / \ / \ + A C C E + + Changes the tree structure, updates the branch sizes. + The caller must update the colors and register B as child of its parent. */ +static NODE_T +rotate_right (NODE_T b_node, NODE_T d_node) +{ + NODE_T c_node = b_node->right; + + d_node->left = c_node; + b_node->right = d_node; + + b_node->parent = d_node->parent; + d_node->parent = b_node; + if (c_node != NULL) + c_node->parent = d_node; + + return b_node; +} + +/* Ensures the tree is balanced, after an insertion operation. + Also assigns node->color. + parent is the given node's parent, known to be non-NULL. */ +static void +rebalance_after_add (CONTAINER_T container, NODE_T node, NODE_T parent) +{ + for (;;) + { + /* At this point, parent = node->parent != NULL. + Think of node->color being RED (although node->color is not yet + assigned.) */ + NODE_T grandparent; + NODE_T uncle; + + if (parent->color == BLACK) + { + /* A RED color for node is acceptable. */ + node->color = RED; + return; + } + + grandparent = parent->parent; + /* Since parent is RED, we know that + grandparent is != NULL and colored BLACK. */ + + if (grandparent->left == parent) + uncle = grandparent->right; + else if (grandparent->right == parent) + uncle = grandparent->left; + else + abort (); + + if (uncle != NULL && uncle->color == RED) + { + /* Change grandparent from BLACK to RED, and + change parent and uncle from RED to BLACK. + This makes it acceptable for node to be RED. */ + node->color = RED; + parent->color = uncle->color = BLACK; + node = grandparent; + } + else + { + /* grandparent and uncle are BLACK. parent is RED. node wants + to be RED too. + In this case, recoloring is not sufficient. Need to perform + one or two rotations. */ + NODE_T *grandparentp; + + if (grandparent->parent == NULL) + grandparentp = &container->root; + else if (grandparent->parent->left == grandparent) + grandparentp = &grandparent->parent->left; + else if (grandparent->parent->right == grandparent) + grandparentp = &grandparent->parent->right; + else + abort (); + + if (grandparent->left == parent) + { + if (parent->right == node) + { + /* Rotation between node and parent. */ + grandparent->left = rotate_left (parent, node); + node = parent; + parent = grandparent->left; + } + /* grandparent and uncle are BLACK. parent and node want to be + RED. parent = grandparent->left. node = parent->left. + + grandparent parent + bh+1 bh+1 + / \ / \ + parent uncle --> node grandparent + bh bh bh bh + / \ / \ + node C C uncle + bh bh bh bh + */ + *grandparentp = rotate_right (parent, grandparent); + parent->color = BLACK; + node->color = grandparent->color = RED; + } + else /* grandparent->right == parent */ + { + if (parent->left == node) + { + /* Rotation between node and parent. */ + grandparent->right = rotate_right (node, parent); + node = parent; + parent = grandparent->right; + } + /* grandparent and uncle are BLACK. parent and node want to be + RED. parent = grandparent->right. node = parent->right. + + grandparent parent + bh+1 bh+1 + / \ / \ + uncle parent --> grandparent node + bh bh bh bh + / \ / \ + C node uncle C + bh bh bh bh + */ + *grandparentp = rotate_left (grandparent, parent); + parent->color = BLACK; + node->color = grandparent->color = RED; + } + return; + } + + /* Start again with a new (node, parent) pair. */ + parent = node->parent; + + if (parent == NULL) + { + /* Change node's color from RED to BLACK. This increases the + tree's black-height. */ + node->color = BLACK; + return; + } + } +} + +/* Ensures the tree is balanced, after a deletion operation. + CHILD was a grandchild of PARENT and is now its child. Between them, + a black node was removed. CHILD is also black, or NULL. + (CHILD can also be NULL. But PARENT is non-NULL.) */ +static void +rebalance_after_remove (CONTAINER_T container, NODE_T child, NODE_T parent) +{ + for (;;) + { + /* At this point, we reduced the black-height of the CHILD subtree by 1. + To make up, either look for a possibility to turn a RED to a BLACK + node, or try to reduce the black-height tree of CHILD's sibling + subtree as well. */ + NODE_T *parentp; + + if (parent->parent == NULL) + parentp = &container->root; + else if (parent->parent->left == parent) + parentp = &parent->parent->left; + else if (parent->parent->right == parent) + parentp = &parent->parent->right; + else + abort (); + + if (parent->left == child) + { + NODE_T sibling = parent->right; + /* sibling's black-height is >= 1. In particular, + sibling != NULL. + + parent + / \ + child sibling + bh bh+1 + */ + + if (sibling->color == RED) + { + /* sibling is RED, hence parent is BLACK and sibling's children + are non-NULL and BLACK. + + parent sibling + bh+2 bh+2 + / \ / \ + child sibling --> parent SR + bh bh+1 bh+1 bh+1 + / \ / \ + SL SR child SL + bh+1 bh+1 bh bh+1 + */ + *parentp = rotate_left (parent, sibling); + parent->color = RED; + sibling->color = BLACK; + + /* Concentrate on the subtree of parent. The new sibling is + one of the old sibling's children, and known to be BLACK. */ + parentp = &sibling->left; + sibling = parent->right; + } + /* Now we know that sibling is BLACK. + + parent + / \ + child sibling + bh bh+1 + */ + if (sibling->right != NULL && sibling->right->color == RED) + { + /* + parent sibling + bh+1|bh+2 bh+1|bh+2 + / \ / \ + child sibling --> parent SR + bh bh+1 bh+1 bh+1 + / \ / \ + SL SR child SL + bh bh bh bh + */ + *parentp = rotate_left (parent, sibling); + sibling->color = parent->color; + parent->color = BLACK; + sibling->right->color = BLACK; + return; + } + else if (sibling->left != NULL && sibling->left->color == RED) + { + /* + parent parent + bh+1|bh+2 bh+1|bh+2 + / \ / \ + child sibling --> child SL + bh bh+1 bh bh+1 + / \ / \ + SL SR SLL sibling + bh bh bh bh + / \ / \ + SLL SLR SLR SR + bh bh bh bh + + where SLL, SLR, SR are all black. + */ + parent->right = rotate_right (sibling->left, sibling); + /* Change sibling from BLACK to RED and SL from RED to BLACK. */ + sibling->color = RED; + sibling = parent->right; + sibling->color = BLACK; + + /* Now do as in the previous case. */ + *parentp = rotate_left (parent, sibling); + sibling->color = parent->color; + parent->color = BLACK; + sibling->right->color = BLACK; + return; + } + else + { + if (parent->color == BLACK) + { + /* Change sibling from BLACK to RED. Then the entire + subtree at parent has decreased its black-height. + parent parent + bh+2 bh+1 + / \ / \ + child sibling --> child sibling + bh bh+1 bh bh + */ + sibling->color = RED; + + child = parent; + } + else + { + /* Change parent from RED to BLACK, but compensate by + changing sibling from BLACK to RED. + parent parent + bh+1 bh+1 + / \ / \ + child sibling --> child sibling + bh bh+1 bh bh + */ + parent->color = BLACK; + sibling->color = RED; + return; + } + } + } + else if (parent->right == child) + { + NODE_T sibling = parent->left; + /* sibling's black-height is >= 1. In particular, + sibling != NULL. + + parent + / \ + sibling child + bh+1 bh + */ + + if (sibling->color == RED) + { + /* sibling is RED, hence parent is BLACK and sibling's children + are non-NULL and BLACK. + + parent sibling + bh+2 bh+2 + / \ / \ + sibling child --> SR parent + bh+1 ch bh+1 bh+1 + / \ / \ + SL SR SL child + bh+1 bh+1 bh+1 bh + */ + *parentp = rotate_right (sibling, parent); + parent->color = RED; + sibling->color = BLACK; + + /* Concentrate on the subtree of parent. The new sibling is + one of the old sibling's children, and known to be BLACK. */ + parentp = &sibling->right; + sibling = parent->left; + } + /* Now we know that sibling is BLACK. + + parent + / \ + sibling child + bh+1 bh + */ + if (sibling->left != NULL && sibling->left->color == RED) + { + /* + parent sibling + bh+1|bh+2 bh+1|bh+2 + / \ / \ + sibling child --> SL parent + bh+1 bh bh+1 bh+1 + / \ / \ + SL SR SR child + bh bh bh bh + */ + *parentp = rotate_right (sibling, parent); + sibling->color = parent->color; + parent->color = BLACK; + sibling->left->color = BLACK; + return; + } + else if (sibling->right != NULL && sibling->right->color == RED) + { + /* + parent parent + bh+1|bh+2 bh+1|bh+2 + / \ / \ + sibling child --> SR child + bh+1 bh bh+1 bh + / \ / \ + SL SR sibling SRR + bh bh bh bh + / \ / \ + SRL SRR SL SRL + bh bh bh bh + + where SL, SRL, SRR are all black. + */ + parent->left = rotate_left (sibling, sibling->right); + /* Change sibling from BLACK to RED and SL from RED to BLACK. */ + sibling->color = RED; + sibling = parent->left; + sibling->color = BLACK; + + /* Now do as in the previous case. */ + *parentp = rotate_right (sibling, parent); + sibling->color = parent->color; + parent->color = BLACK; + sibling->left->color = BLACK; + return; + } + else + { + if (parent->color == BLACK) + { + /* Change sibling from BLACK to RED. Then the entire + subtree at parent has decreased its black-height. + parent parent + bh+2 bh+1 + / \ / \ + sibling child --> sibling child + bh+1 bh bh bh + */ + sibling->color = RED; + + child = parent; + } + else + { + /* Change parent from RED to BLACK, but compensate by + changing sibling from BLACK to RED. + parent parent + bh+1 bh+1 + / \ / \ + sibling child --> sibling child + bh+1 bh bh bh + */ + parent->color = BLACK; + sibling->color = RED; + return; + } + } + } + else + abort (); + + /* Start again with a new (child, parent) pair. */ + parent = child->parent; + +#if 0 /* Already handled. */ + if (child != NULL && child->color == RED) + { + child->color = BLACK; + return; + } +#endif + + if (parent == NULL) + return; + } +} + +static NODE_T +gl_tree_nx_add_first (CONTAINER_T container, NODE_PAYLOAD_PARAMS) +{ + /* Create new node. */ + NODE_T new_node = + (struct NODE_IMPL *) malloc (sizeof (struct NODE_IMPL)); + + if (new_node == NULL) + return NULL; + + new_node->left = NULL; + new_node->right = NULL; + NODE_PAYLOAD_ASSIGN(new_node) + + /* Add it to the tree. */ + if (container->root == NULL) + { + new_node->color = BLACK; + container->root = new_node; + new_node->parent = NULL; + } + else + { + NODE_T node; + + for (node = container->root; node->left != NULL; ) + node = node->left; + + node->left = new_node; + new_node->parent = node; + + /* Color and rebalance. */ + rebalance_after_add (container, new_node, node); + } + + container->count++; + return new_node; +} + +/* Adds the already allocated NEW_NODE to the tree, right before NODE. */ +static void +gl_tree_add_node_before (CONTAINER_T container, NODE_T node, NODE_T new_node) +{ + new_node->left = NULL; + new_node->right = NULL; + + /* Add it to the tree. */ + if (node->left == NULL) + node->left = new_node; + else + { + for (node = node->left; node->right != NULL; ) + node = node->right; + node->right = new_node; + } + new_node->parent = node; + + /* Color and rebalance. */ + rebalance_after_add (container, new_node, node); + + container->count++; +} + +static NODE_T +gl_tree_nx_add_before (CONTAINER_T container, NODE_T node, NODE_PAYLOAD_PARAMS) +{ + /* Create new node. */ + NODE_T new_node = + (struct NODE_IMPL *) malloc (sizeof (struct NODE_IMPL)); + + if (new_node == NULL) + return NULL; + + NODE_PAYLOAD_ASSIGN(new_node) + + gl_tree_add_node_before (container, node, new_node); + return new_node; +} + +/* Adds the already allocated NEW_NODE to the tree, right after NODE. */ +static void +gl_tree_add_node_after (CONTAINER_T container, NODE_T node, NODE_T new_node) +{ + new_node->left = NULL; + new_node->right = NULL; + + /* Add it to the tree. */ + if (node->right == NULL) + node->right = new_node; + else + { + for (node = node->right; node->left != NULL; ) + node = node->left; + node->left = new_node; + } + new_node->parent = node; + + /* Color and rebalance. */ + rebalance_after_add (container, new_node, node); + + container->count++; +} + +static NODE_T +gl_tree_nx_add_after (CONTAINER_T container, NODE_T node, NODE_PAYLOAD_PARAMS) +{ + /* Create new node. */ + NODE_T new_node = + (struct NODE_IMPL *) malloc (sizeof (struct NODE_IMPL)); + + if (new_node == NULL) + return NULL; + + NODE_PAYLOAD_ASSIGN(new_node) + + gl_tree_add_node_after (container, node, new_node); + return new_node; +} + +static void +gl_tree_remove_node_no_free (CONTAINER_T container, NODE_T node) +{ + NODE_T parent = node->parent; + + if (node->left == NULL) + { + /* Replace node with node->right. */ + NODE_T child = node->right; + + if (child != NULL) + { + child->parent = parent; + /* Since node->left == NULL, child must be RED and of height 1, + hence node must have been BLACK. Recolor the child. */ + child->color = BLACK; + } + if (parent == NULL) + container->root = child; + else + { + if (parent->left == node) + parent->left = child; + else /* parent->right == node */ + parent->right = child; + + if (child == NULL && node->color == BLACK) + rebalance_after_remove (container, child, parent); + } + } + else if (node->right == NULL) + { + /* It is not absolutely necessary to treat this case. But the more + general case below is more complicated, hence slower. */ + /* Replace node with node->left. */ + NODE_T child = node->left; + + child->parent = parent; + /* Since node->right == NULL, child must be RED and of height 1, + hence node must have been BLACK. Recolor the child. */ + child->color = BLACK; + if (parent == NULL) + container->root = child; + else + { + if (parent->left == node) + parent->left = child; + else /* parent->right == node */ + parent->right = child; + } + } + else + { + /* Replace node with the rightmost element of the node->left subtree. */ + NODE_T subst; + NODE_T subst_parent; + NODE_T child; + color_t removed_color; + + for (subst = node->left; subst->right != NULL; ) + subst = subst->right; + + subst_parent = subst->parent; + + child = subst->left; + + removed_color = subst->color; + + /* The case subst_parent == node is special: If we do nothing special, + we get confusion about node->left, subst->left and child->parent. + subst_parent == node + <==> The 'for' loop above terminated immediately. + <==> subst == subst_parent->left + [otherwise subst == subst_parent->right] + In this case, we would need to first set + child->parent = node; node->left = child; + and later - when we copy subst into node's position - again + child->parent = subst; subst->left = child; + Altogether a no-op. */ + if (subst_parent != node) + { + if (child != NULL) + child->parent = subst_parent; + subst_parent->right = child; + } + + /* Copy subst into node's position. + (This is safer than to copy subst's value into node, keep node in + place, and free subst.) */ + if (subst_parent != node) + { + subst->left = node->left; + subst->left->parent = subst; + } + subst->right = node->right; + subst->right->parent = subst; + subst->color = node->color; + subst->parent = parent; + if (parent == NULL) + container->root = subst; + else if (parent->left == node) + parent->left = subst; + else /* parent->right == node */ + parent->right = subst; + + if (removed_color == BLACK) + { + if (child != NULL && child->color == RED) + /* Recolor the child. */ + child->color = BLACK; + else + /* Rebalancing starts at child's parent, that is subst_parent - + except when subst_parent == node. In this case, we need to use + its replacement, subst. */ + rebalance_after_remove (container, child, + subst_parent != node ? subst_parent : subst); + } + } + + container->count--; +} + +static bool +gl_tree_remove_node (CONTAINER_T container, NODE_T node) +{ + gl_tree_remove_node_no_free (container, node); + NODE_PAYLOAD_DISPOSE (container, node) + free (node); + return true; +} + +/* For debugging. */ +static unsigned int +check_invariants (NODE_T node, NODE_T parent, size_t *counterp) +{ + unsigned int left_blackheight = + (node->left != NULL ? check_invariants (node->left, node, counterp) : 0); + unsigned int right_blackheight = + (node->right != NULL ? check_invariants (node->right, node, counterp) : 0); + + if (!(node->parent == parent)) + abort (); + if (!(node->color == BLACK || node->color == RED)) + abort (); + if (parent == NULL && !(node->color == BLACK)) + abort (); + if (!(left_blackheight == right_blackheight)) + abort (); + + (*counterp)++; + + return left_blackheight + (node->color == BLACK ? 1 : 0); +} diff --git a/contrib/tools/bison/lib/gl_rbtree_oset.c b/contrib/tools/bison/lib/gl_rbtree_oset.c new file mode 100644 index 0000000000..bc55ace32f --- /dev/null +++ b/contrib/tools/bison/lib/gl_rbtree_oset.c @@ -0,0 +1,73 @@ +/* Ordered set data type implemented by a binary tree. + Copyright (C) 2006-2007, 2009-2020 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include "gl_rbtree_oset.h" + +#include <stdlib.h> + +/* -------------------------- gl_oset_t Data Type -------------------------- */ + +/* Parameterization of gl_rbtree_ordered.h. */ +#define CONTAINER_T gl_oset_t +#define CONTAINER_IMPL gl_oset_impl +#define CONTAINER_IMPL_BASE gl_oset_impl_base +#define NODE_IMPL gl_oset_node_impl +#define NODE_T gl_oset_node_t +#define NODE_PAYLOAD_FIELDS \ + const void *value; +#define NODE_PAYLOAD_PARAMS \ + const void *elt +#define NODE_PAYLOAD_ASSIGN(node) \ + node->value = elt; +#define NODE_PAYLOAD_DISPOSE(container, node) \ + if (container->base.dispose_fn != NULL) \ + container->base.dispose_fn (node->value); + +#include "gl_rbtree_ordered.h" + +/* Generic binary tree code. */ +#include "gl_anytree_oset.h" + +/* For debugging. */ +void +gl_rbtree_oset_check_invariants (gl_oset_t set) +{ + size_t counter = 0; + if (set->root != NULL) + check_invariants (set->root, NULL, &counter); + if (!(set->count == counter)) + abort (); +} + +const struct gl_oset_implementation gl_rbtree_oset_implementation = + { + gl_tree_nx_create_empty, + gl_tree_size, + gl_tree_search, + gl_tree_search_atleast, + gl_tree_nx_add, + gl_tree_remove, + gl_tree_update, + gl_tree_oset_free, + gl_tree_iterator, + gl_tree_iterator_atleast, + gl_tree_iterator_next, + gl_tree_iterator_free + }; diff --git a/contrib/tools/bison/lib/gl_rbtree_oset.h b/contrib/tools/bison/lib/gl_rbtree_oset.h new file mode 100644 index 0000000000..b03aee4d99 --- /dev/null +++ b/contrib/tools/bison/lib/gl_rbtree_oset.h @@ -0,0 +1,34 @@ +/* Ordered set data type implemented by a binary tree. + Copyright (C) 2006, 2009-2020 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _GL_RBTREE_OSET_H +#define _GL_RBTREE_OSET_H + +#include "gl_oset.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const struct gl_oset_implementation gl_rbtree_oset_implementation; +#define GL_RBTREE_OSET &gl_rbtree_oset_implementation + +#ifdef __cplusplus +} +#endif + +#endif /* _GL_RBTREE_OSET_H */ diff --git a/contrib/tools/bison/lib/gl_rbtreehash_list.c b/contrib/tools/bison/lib/gl_rbtreehash_list.c new file mode 100644 index 0000000000..be2ee6f4e9 --- /dev/null +++ b/contrib/tools/bison/lib/gl_rbtreehash_list.c @@ -0,0 +1,127 @@ +/* Sequential list data type implemented by a hash table with a binary tree. + Copyright (C) 2006, 2008-2020 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include "gl_rbtreehash_list.h" + +#include <stdint.h> /* for uintptr_t, SIZE_MAX */ +#include <stdlib.h> + +#include "gl_rbtree_oset.h" +#include "xsize.h" + +#define WITH_HASHTABLE 1 + +/* Which kind of binary trees to use for ordered sets. Quite arbitrary. */ +#define OSET_TREE_FLAVOR GL_RBTREE_OSET + +/* -------------------------- gl_list_t Data Type -------------------------- */ + +/* Generic hash-table code: Type definitions. */ +#include "gl_anyhash1.h" + +/* Generic red-black tree code: Type definitions. */ +#include "gl_anyrbtree_list1.h" + +/* Generic hash-table code: Low-level code. */ +#define CONTAINER_T gl_list_t +#define CONTAINER_COUNT(list) \ + ((list)->root != NULL ? (list)->root->branch_size : 0) +#include "gl_anyhash2.h" + +/* Generic binary tree code: Type definitions. */ +#include "gl_anytree_list1.h" + +/* Hash-table with binary tree code: Handling of hash buckets. */ +#include "gl_anytreehash_list1.h" + +/* Generic red-black tree code: Insertion/deletion algorithms. */ +#include "gl_anyrbtree_list2.h" + +/* Generic binary tree code: Functions taking advantage of the hash table. */ +#include "gl_anytreehash_list2.h" + +/* Generic binary tree code: All other functions. */ +#include "gl_anytree_list2.h" + +/* For debugging. */ +static unsigned int +check_invariants (gl_list_node_t node, gl_list_node_t parent) +{ + unsigned int left_blackheight = + (node->left != NULL ? check_invariants (node->left, node) : 0); + unsigned int right_blackheight = + (node->right != NULL ? check_invariants (node->right, node) : 0); + + if (!(node->parent == parent)) + abort (); + if (!(node->branch_size + == (node->left != NULL ? node->left->branch_size : 0) + + 1 + (node->right != NULL ? node->right->branch_size : 0))) + abort (); + if (!(node->color == BLACK || node->color == RED)) + abort (); + if (parent == NULL && !(node->color == BLACK)) + abort (); + if (!(left_blackheight == right_blackheight)) + abort (); + + return left_blackheight + (node->color == BLACK ? 1 : 0); +} +void +gl_rbtreehash_list_check_invariants (gl_list_t list) +{ + if (list->root != NULL) + check_invariants (list->root, NULL); +} + + +const struct gl_list_implementation gl_rbtreehash_list_implementation = + { + gl_tree_nx_create_empty, + gl_tree_nx_create, + gl_tree_size, + gl_tree_node_value, + gl_tree_node_nx_set_value, + gl_tree_next_node, + gl_tree_previous_node, + gl_tree_get_at, + gl_tree_nx_set_at, + gl_tree_search_from_to, + gl_tree_indexof_from_to, + gl_tree_nx_add_first, + gl_tree_nx_add_last, + gl_tree_nx_add_before, + gl_tree_nx_add_after, + gl_tree_nx_add_at, + gl_tree_remove_node, + gl_tree_remove_at, + gl_tree_remove, + gl_tree_list_free, + gl_tree_iterator, + gl_tree_iterator_from_to, + gl_tree_iterator_next, + gl_tree_iterator_free, + gl_tree_sortedlist_search, + gl_tree_sortedlist_search_from_to, + gl_tree_sortedlist_indexof, + gl_tree_sortedlist_indexof_from_to, + gl_tree_sortedlist_nx_add, + gl_tree_sortedlist_remove + }; diff --git a/contrib/tools/bison/lib/gl_rbtreehash_list.h b/contrib/tools/bison/lib/gl_rbtreehash_list.h new file mode 100644 index 0000000000..dba63795a9 --- /dev/null +++ b/contrib/tools/bison/lib/gl_rbtreehash_list.h @@ -0,0 +1,34 @@ +/* Sequential list data type implemented by a hash table with a binary tree. + Copyright (C) 2006, 2009-2020 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2006. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _GL_RBTREEHASH_LIST_H +#define _GL_RBTREEHASH_LIST_H + +#include "gl_list.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const struct gl_list_implementation gl_rbtreehash_list_implementation; +#define GL_RBTREEHASH_LIST &gl_rbtreehash_list_implementation + +#ifdef __cplusplus +} +#endif + +#endif /* _GL_RBTREEHASH_LIST_H */ diff --git a/contrib/tools/bison/lib/hash.c b/contrib/tools/bison/lib/hash.c index 7aaf106267..2d64c82e59 100644 --- a/contrib/tools/bison/lib/hash.c +++ b/contrib/tools/bison/lib/hash.c @@ -138,38 +138,24 @@ static const Hash_tuning default_tuning = /* Information and lookup. */ -/* The following few functions provide information about the overall hash - table organization: the number of entries, number of buckets and maximum - length of buckets. */ - -/* Return the number of buckets in the hash table. The table size, the total - number of buckets (used plus unused), or the maximum number of slots, are - the same quantity. */ - size_t hash_get_n_buckets (const Hash_table *table) { return table->n_buckets; } -/* Return the number of slots in use (non-empty buckets). */ - size_t hash_get_n_buckets_used (const Hash_table *table) { return table->n_buckets_used; } -/* Return the number of active entries. */ - size_t hash_get_n_entries (const Hash_table *table) { return table->n_entries; } -/* Return the length of the longest chain (bucket). */ - size_t hash_get_max_bucket_length (const Hash_table *table) { @@ -194,9 +180,6 @@ hash_get_max_bucket_length (const Hash_table *table) return max_bucket_length; } -/* Do a mild validation of a hash table, by traversing it and checking two - statistics. */ - bool hash_table_ok (const Hash_table *table) { @@ -254,9 +237,6 @@ safe_hasher (const Hash_table *table, const void *key) return table->bucket + n; } -/* If ENTRY matches an entry already in the hash table, return the - entry from the table. Otherwise, return NULL. */ - void * hash_lookup (const Hash_table *table, const void *entry) { @@ -275,15 +255,6 @@ hash_lookup (const Hash_table *table, const void *entry) /* Walking. */ -/* The functions in this page traverse the hash table and process the - contained entries. For the traversal to work properly, the hash table - should not be resized nor modified while any particular entry is being - processed. In particular, entries should not be added, and an entry - may be removed only if there is no shrink threshold and the entry being - removed has already been passed to hash_get_next. */ - -/* Return the first data in the table, or NULL if the table is empty. */ - void * hash_get_first (const Hash_table *table) { @@ -299,10 +270,6 @@ hash_get_first (const Hash_table *table) return bucket->data; } -/* Return the user data for the entry following ENTRY, where ENTRY has been - returned by a previous call to either 'hash_get_first' or 'hash_get_next'. - Return NULL if there are no more entries. */ - void * hash_get_next (const Hash_table *table, const void *entry) { @@ -328,10 +295,6 @@ hash_get_next (const Hash_table *table, const void *entry) return NULL; } -/* Fill BUFFER with pointers to active user entries in the hash table, then - return the number of pointers copied. Do not copy more than BUFFER_SIZE - pointers. */ - size_t hash_get_entries (const Hash_table *table, void **buffer, size_t buffer_size) @@ -356,14 +319,6 @@ hash_get_entries (const Hash_table *table, void **buffer, return counter; } -/* Call a PROCESSOR function for each entry of a hash table, and return the - number of entries for which the processor function returned success. A - pointer to some PROCESSOR_DATA which will be made available to each call to - the processor function. The PROCESSOR accepts two arguments: the first is - the user entry being walked into, the second is the value of PROCESSOR_DATA - as received. The walking continue for as long as the PROCESSOR function - returns nonzero. When it returns zero, the walking is interrupted. */ - size_t hash_do_for_each (const Hash_table *table, Hash_processor processor, void *processor_data) @@ -390,9 +345,6 @@ hash_do_for_each (const Hash_table *table, Hash_processor processor, /* Allocation and clean-up. */ -/* Return a hash index for a NUL-terminated STRING between 0 and N_BUCKETS-1. - This is a convenience routine for constructing other hashing functions. */ - #if USE_DIFF_HASH /* About hashings, Paul Eggert writes to me (FP), on 1994-01-01: "Please see @@ -556,40 +508,6 @@ compute_bucket_size (size_t candidate, const Hash_tuning *tuning) return candidate; } -/* Allocate and return a new hash table, or NULL upon failure. The initial - number of buckets is automatically selected so as to _guarantee_ that you - may insert at least CANDIDATE different user entries before any growth of - the hash table size occurs. So, if have a reasonably tight a-priori upper - bound on the number of entries you intend to insert in the hash table, you - may save some table memory and insertion time, by specifying it here. If - the IS_N_BUCKETS field of the TUNING structure is true, the CANDIDATE - argument has its meaning changed to the wanted number of buckets. - - TUNING points to a structure of user-supplied values, in case some fine - tuning is wanted over the default behavior of the hasher. If TUNING is - NULL, the default tuning parameters are used instead. If TUNING is - provided but the values requested are out of bounds or might cause - rounding errors, return NULL. - - The user-supplied HASHER function, when not NULL, accepts two - arguments ENTRY and TABLE_SIZE. It computes, by hashing ENTRY contents, a - slot number for that entry which should be in the range 0..TABLE_SIZE-1. - This slot number is then returned. - - The user-supplied COMPARATOR function, when not NULL, accepts two - arguments pointing to user data, it then returns true for a pair of entries - that compare equal, or false otherwise. This function is internally called - on entries which are already known to hash to the same bucket index, - but which are distinct pointers. - - The user-supplied DATA_FREER function, when not NULL, may be later called - with the user data as an argument, just before the entry containing the - data gets freed. This happens from within 'hash_free' or 'hash_clear'. - You should specify this function only if you want these functions to free - all of your 'data' data. This is typically the case when your data is - simply an auxiliary struct that you have malloc'd to aggregate several - values. */ - Hash_table * hash_initialize (size_t candidate, const Hash_tuning *tuning, Hash_hasher hasher, Hash_comparator comparator, @@ -645,10 +563,6 @@ hash_initialize (size_t candidate, const Hash_tuning *tuning, return NULL; } -/* Make all buckets empty, placing any chained entries on the free list. - Apply the user-specified function data_freer (if any) to the datas of any - affected entries. */ - void hash_clear (Hash_table *table) { @@ -687,11 +601,6 @@ hash_clear (Hash_table *table) table->n_entries = 0; } -/* Reclaim all storage associated with a hash table. If a data_freer - function has been supplied by the user when the hash table was created, - this function applies it to the data of each entry before freeing that - entry. */ - void hash_free (Hash_table *table) { @@ -931,14 +840,6 @@ transfer_entries (Hash_table *dst, Hash_table *src, bool safe) return true; } -/* For an already existing hash table, change the number of buckets through - specifying CANDIDATE. The contents of the hash table are preserved. The - new number of buckets is automatically selected so as to _guarantee_ that - the table may receive at least CANDIDATE different user entries, including - those already in the table, before any other growth of the hash table size - occurs. If TUNING->IS_N_BUCKETS is true, then CANDIDATE specifies the - exact number of buckets desired. Return true iff the rehash succeeded. */ - bool hash_rehash (Hash_table *table, size_t candidate) { @@ -1018,22 +919,6 @@ hash_rehash (Hash_table *table, size_t candidate) return false; } -/* Insert ENTRY into hash TABLE if there is not already a matching entry. - - Return -1 upon memory allocation failure. - Return 1 if insertion succeeded. - Return 0 if there is already a matching entry in the table, - and in that case, if MATCHED_ENT is non-NULL, set *MATCHED_ENT - to that entry. - - This interface is easier to use than hash_insert when you must - distinguish between the latter two cases. More importantly, - hash_insert is unusable for some types of ENTRY values. When using - hash_insert, the only way to distinguish those cases is to compare - the return value and ENTRY. That works only when you can have two - different ENTRY values that point to data that compares "equal". Thus, - when the ENTRY value is a simple scalar, you must use - hash_insert_if_absent. ENTRY must not be NULL. */ int hash_insert_if_absent (Hash_table *table, void const *entry, void const **matched_ent) @@ -1116,12 +1001,6 @@ hash_insert_if_absent (Hash_table *table, void const *entry, return 1; } -/* If ENTRY matches an entry already in the hash table, return the pointer - to the entry from the table. Otherwise, insert ENTRY and return ENTRY. - Return NULL if the storage required for insertion cannot be allocated. - This implementation does not support duplicate entries or insertion of - NULL. */ - void * hash_insert (Hash_table *table, void const *entry) { @@ -1132,12 +1011,8 @@ hash_insert (Hash_table *table, void const *entry) : (void *) (err == 0 ? matched_ent : entry)); } -/* If ENTRY is already in the table, remove it and return the just-deleted - data (the user may want to deallocate its storage). If ENTRY is not in the - table, don't modify the table and return NULL. */ - void * -hash_delete (Hash_table *table, const void *entry) +hash_remove (Hash_table *table, const void *entry) { void *data; struct hash_entry *bucket; @@ -1196,6 +1071,12 @@ hash_delete (Hash_table *table, const void *entry) return data; } +void * +hash_delete (Hash_table *table, const void *entry) +{ + return hash_remove (table, entry); +} + /* Testing. */ #if TESTING diff --git a/contrib/tools/bison/lib/hash.h b/contrib/tools/bison/lib/hash.h index ae08ce8678..e280adb13b 100644 --- a/contrib/tools/bison/lib/hash.h +++ b/contrib/tools/bison/lib/hash.h @@ -27,10 +27,9 @@ # include <stdio.h> # include <stdbool.h> -typedef size_t (*Hash_hasher) (const void *, size_t); -typedef bool (*Hash_comparator) (const void *, const void *); -typedef void (*Hash_data_freer) (void *); -typedef bool (*Hash_processor) (void *, void *); +# ifdef __cplusplus +extern "C" { +# endif struct hash_tuning { @@ -50,39 +49,213 @@ struct hash_table; typedef struct hash_table Hash_table; -/* Information and lookup. */ -size_t hash_get_n_buckets (const Hash_table *) _GL_ATTRIBUTE_PURE; -size_t hash_get_n_buckets_used (const Hash_table *) _GL_ATTRIBUTE_PURE; -size_t hash_get_n_entries (const Hash_table *) _GL_ATTRIBUTE_PURE; -size_t hash_get_max_bucket_length (const Hash_table *) _GL_ATTRIBUTE_PURE; -bool hash_table_ok (const Hash_table *) _GL_ATTRIBUTE_PURE; -void hash_print_statistics (const Hash_table *, FILE *); -void *hash_lookup (const Hash_table *, const void *); - -/* Walking. */ -void *hash_get_first (const Hash_table *) _GL_ATTRIBUTE_PURE; -void *hash_get_next (const Hash_table *, const void *); -size_t hash_get_entries (const Hash_table *, void **, size_t); -size_t hash_do_for_each (const Hash_table *, Hash_processor, void *); - -/* Allocation and clean-up. */ -size_t hash_string (const char *, size_t) _GL_ATTRIBUTE_PURE; -void hash_reset_tuning (Hash_tuning *); -Hash_table *hash_initialize (size_t, const Hash_tuning *, - Hash_hasher, Hash_comparator, - Hash_data_freer) _GL_ATTRIBUTE_NODISCARD; -Hash_table *hash_xinitialize (size_t, const Hash_tuning *, - Hash_hasher, Hash_comparator, - Hash_data_freer) _GL_ATTRIBUTE_NODISCARD; -void hash_clear (Hash_table *); -void hash_free (Hash_table *); - -/* Insertion and deletion. */ -bool hash_rehash (Hash_table *, size_t) _GL_ATTRIBUTE_NODISCARD; -void *hash_insert (Hash_table *, const void *) _GL_ATTRIBUTE_NODISCARD; - -int hash_insert_if_absent (Hash_table *table, const void *entry, - const void **matched_ent); -void *hash_delete (Hash_table *, const void *); +/* + * Information and lookup. + */ + +/* The following few functions provide information about the overall hash + table organization: the number of entries, number of buckets and maximum + length of buckets. */ + +/* Return the number of buckets in the hash table. The table size, the total + number of buckets (used plus unused), or the maximum number of slots, are + the same quantity. */ +extern size_t hash_get_n_buckets (const Hash_table *table) + _GL_ATTRIBUTE_PURE; + +/* Return the number of slots in use (non-empty buckets). */ +extern size_t hash_get_n_buckets_used (const Hash_table *table) + _GL_ATTRIBUTE_PURE; + +/* Return the number of active entries. */ +extern size_t hash_get_n_entries (const Hash_table *table) + _GL_ATTRIBUTE_PURE; + +/* Return the length of the longest chain (bucket). */ +extern size_t hash_get_max_bucket_length (const Hash_table *table) + _GL_ATTRIBUTE_PURE; + +/* Do a mild validation of a hash table, by traversing it and checking two + statistics. */ +extern bool hash_table_ok (const Hash_table *table) + _GL_ATTRIBUTE_PURE; + +extern void hash_print_statistics (const Hash_table *table, FILE *stream); + +/* If ENTRY matches an entry already in the hash table, return the + entry from the table. Otherwise, return NULL. */ +extern void *hash_lookup (const Hash_table *table, const void *entry); + +/* + * Walking. + */ + +/* The functions in this page traverse the hash table and process the + contained entries. For the traversal to work properly, the hash table + should not be resized nor modified while any particular entry is being + processed. In particular, entries should not be added, and an entry + may be removed only if there is no shrink threshold and the entry being + removed has already been passed to hash_get_next. */ + +/* Return the first data in the table, or NULL if the table is empty. */ +extern void *hash_get_first (const Hash_table *table) + _GL_ATTRIBUTE_PURE; + +/* Return the user data for the entry following ENTRY, where ENTRY has been + returned by a previous call to either 'hash_get_first' or 'hash_get_next'. + Return NULL if there are no more entries. */ +extern void *hash_get_next (const Hash_table *table, const void *entry); + +/* Fill BUFFER with pointers to active user entries in the hash table, then + return the number of pointers copied. Do not copy more than BUFFER_SIZE + pointers. */ +extern size_t hash_get_entries (const Hash_table *table, void **buffer, + size_t buffer_size); + +typedef bool (*Hash_processor) (void *entry, void *processor_data); + +/* Call a PROCESSOR function for each entry of a hash table, and return the + number of entries for which the processor function returned success. A + pointer to some PROCESSOR_DATA which will be made available to each call to + the processor function. The PROCESSOR accepts two arguments: the first is + the user entry being walked into, the second is the value of PROCESSOR_DATA + as received. The walking continue for as long as the PROCESSOR function + returns nonzero. When it returns zero, the walking is interrupted. */ +extern size_t hash_do_for_each (const Hash_table *table, + Hash_processor processor, void *processor_data); + +/* + * Allocation and clean-up. + */ + +/* Return a hash index for a NUL-terminated STRING between 0 and N_BUCKETS-1. + This is a convenience routine for constructing other hashing functions. */ +extern size_t hash_string (const char *string, size_t n_buckets) + _GL_ATTRIBUTE_PURE; + +extern void hash_reset_tuning (Hash_tuning *tuning); + +typedef size_t (*Hash_hasher) (const void *entry, size_t table_size); +typedef bool (*Hash_comparator) (const void *entry1, const void *entry2); +typedef void (*Hash_data_freer) (void *entry); + +/* Allocate and return a new hash table, or NULL upon failure. The initial + number of buckets is automatically selected so as to _guarantee_ that you + may insert at least CANDIDATE different user entries before any growth of + the hash table size occurs. So, if have a reasonably tight a-priori upper + bound on the number of entries you intend to insert in the hash table, you + may save some table memory and insertion time, by specifying it here. If + the IS_N_BUCKETS field of the TUNING structure is true, the CANDIDATE + argument has its meaning changed to the wanted number of buckets. + + TUNING points to a structure of user-supplied values, in case some fine + tuning is wanted over the default behavior of the hasher. If TUNING is + NULL, the default tuning parameters are used instead. If TUNING is + provided but the values requested are out of bounds or might cause + rounding errors, return NULL. + + The user-supplied HASHER function, when not NULL, accepts two + arguments ENTRY and TABLE_SIZE. It computes, by hashing ENTRY contents, a + slot number for that entry which should be in the range 0..TABLE_SIZE-1. + This slot number is then returned. + + The user-supplied COMPARATOR function, when not NULL, accepts two + arguments pointing to user data, it then returns true for a pair of entries + that compare equal, or false otherwise. This function is internally called + on entries which are already known to hash to the same bucket index, + but which are distinct pointers. + + The user-supplied DATA_FREER function, when not NULL, may be later called + with the user data as an argument, just before the entry containing the + data gets freed. This happens from within 'hash_free' or 'hash_clear'. + You should specify this function only if you want these functions to free + all of your 'data' data. This is typically the case when your data is + simply an auxiliary struct that you have malloc'd to aggregate several + values. */ +extern Hash_table *hash_initialize (size_t candidate, + const Hash_tuning *tuning, + Hash_hasher hasher, + Hash_comparator comparator, + Hash_data_freer data_freer) + _GL_ATTRIBUTE_NODISCARD; + +/* Same as hash_initialize, but invokes xalloc_die on memory exhaustion. */ +/* This function is defined by module 'xhash'. */ +extern Hash_table *hash_xinitialize (size_t candidate, + const Hash_tuning *tuning, + Hash_hasher hasher, + Hash_comparator comparator, + Hash_data_freer data_freer) + _GL_ATTRIBUTE_NODISCARD; + +/* Make all buckets empty, placing any chained entries on the free list. + Apply the user-specified function data_freer (if any) to the datas of any + affected entries. */ +extern void hash_clear (Hash_table *table); + +/* Reclaim all storage associated with a hash table. If a data_freer + function has been supplied by the user when the hash table was created, + this function applies it to the data of each entry before freeing that + entry. */ +extern void hash_free (Hash_table *table); + +/* + * Insertion and deletion. + */ + +/* For an already existing hash table, change the number of buckets through + specifying CANDIDATE. The contents of the hash table are preserved. The + new number of buckets is automatically selected so as to _guarantee_ that + the table may receive at least CANDIDATE different user entries, including + those already in the table, before any other growth of the hash table size + occurs. If TUNING->IS_N_BUCKETS is true, then CANDIDATE specifies the + exact number of buckets desired. Return true iff the rehash succeeded. */ +extern bool hash_rehash (Hash_table *table, size_t candidate) + _GL_ATTRIBUTE_NODISCARD; + +/* If ENTRY matches an entry already in the hash table, return the pointer + to the entry from the table. Otherwise, insert ENTRY and return ENTRY. + Return NULL if the storage required for insertion cannot be allocated. + This implementation does not support duplicate entries or insertion of + NULL. */ +extern void *hash_insert (Hash_table *table, const void *entry) + _GL_ATTRIBUTE_NODISCARD; + +/* Same as hash_insert, but invokes xalloc_die on memory exhaustion. */ +/* This function is defined by module 'xhash'. */ +extern void *hash_xinsert (Hash_table *table, const void *entry); + +/* Insert ENTRY into hash TABLE if there is not already a matching entry. + + Return -1 upon memory allocation failure. + Return 1 if insertion succeeded. + Return 0 if there is already a matching entry in the table, + and in that case, if MATCHED_ENT is non-NULL, set *MATCHED_ENT + to that entry. + + This interface is easier to use than hash_insert when you must + distinguish between the latter two cases. More importantly, + hash_insert is unusable for some types of ENTRY values. When using + hash_insert, the only way to distinguish those cases is to compare + the return value and ENTRY. That works only when you can have two + different ENTRY values that point to data that compares "equal". Thus, + when the ENTRY value is a simple scalar, you must use + hash_insert_if_absent. ENTRY must not be NULL. */ +extern int hash_insert_if_absent (Hash_table *table, const void *entry, + const void **matched_ent); + +/* If ENTRY is already in the table, remove it and return the just-deleted + data (the user may want to deallocate its storage). If ENTRY is not in the + table, don't modify the table and return NULL. */ +extern void *hash_remove (Hash_table *table, const void *entry); + +/* Same as hash_remove. This interface is deprecated. + FIXME: Remove in 2022. */ +extern void *hash_delete (Hash_table *table, const void *entry) + _GL_ATTRIBUTE_DEPRECATED; + +# ifdef __cplusplus +} +# endif #endif diff --git a/contrib/tools/bison/lib/intprops.h b/contrib/tools/bison/lib/intprops.h index dfbcaae73e..b659de7185 100644 --- a/contrib/tools/bison/lib/intprops.h +++ b/contrib/tools/bison/lib/intprops.h @@ -48,7 +48,7 @@ /* Minimum and maximum values for integer types and expressions. */ /* The width in bits of the integer type or expression T. - Do not evaluate T. + Do not evaluate T. T must not be a bit-field expression. Padding bits are not supported; this is checked at compile-time below. */ #define TYPE_WIDTH(t) (sizeof (t) * CHAR_BIT) @@ -70,7 +70,7 @@ ? _GL_SIGNED_INT_MAXIMUM (e) \ : _GL_INT_NEGATE_CONVERT (e, 1)) #define _GL_SIGNED_INT_MAXIMUM(e) \ - (((_GL_INT_CONVERT (e, 1) << (TYPE_WIDTH ((e) + 0) - 2)) - 1) * 2 + 1) + (((_GL_INT_CONVERT (e, 1) << (TYPE_WIDTH (+ (e)) - 2)) - 1) * 2 + 1) /* Work around OpenVMS incompatibility with C99. */ #if !defined LLONG_MAX && defined __INT64_MAX @@ -86,6 +86,7 @@ /* Does the __typeof__ keyword work? This could be done by 'configure', but for now it's easier to do it by hand. */ #if (2 <= __GNUC__ \ + || (4 <= __clang_major__) \ || (1210 <= __IBMC__ && defined __IBM__TYPEOF__) \ || (0x5110 <= __SUNPRO_C && !__STDC__)) # define _GL_HAVE___TYPEOF__ 1 @@ -94,8 +95,9 @@ #endif /* Return 1 if the integer type or expression T might be signed. Return 0 - if it is definitely unsigned. This macro does not evaluate its argument, - and expands to an integer constant expression. */ + if it is definitely unsigned. T must not be a bit-field expression. + This macro does not evaluate its argument, and expands to an + integer constant expression. */ #if _GL_HAVE___TYPEOF__ # define _GL_SIGNED_TYPE_OR_EXPR(t) TYPE_SIGNED (__typeof__ (t)) #else @@ -108,6 +110,8 @@ #define INT_BITS_STRLEN_BOUND(b) (((b) * 146 + 484) / 485) /* Bound on length of the string representing an integer type or expression T. + T must not be a bit-field expression. + Subtract 1 for the sign bit if T is signed, and then add 1 more for a minus sign if needed. @@ -119,7 +123,7 @@ + _GL_SIGNED_TYPE_OR_EXPR (t)) /* Bound on buffer size needed to represent an integer type or expression T, - including the terminating null. */ + including the terminating null. T must not be a bit-field expression. */ #define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1) @@ -239,8 +243,14 @@ #endif /* True if __builtin_add_overflow_p (A, B, C) works, and similarly for - __builtin_mul_overflow_p and __builtin_mul_overflow_p. */ -#define _GL_HAS_BUILTIN_OVERFLOW_P (7 <= __GNUC__) + __builtin_sub_overflow_p and __builtin_mul_overflow_p. */ +#ifdef __clang__ +/* Clang 9 lacks __builtin_mul_overflow_p, and even if it did it would + presumably run afoul of Clang bug 16404. */ +# define _GL_HAS_BUILTIN_OVERFLOW_P 0 +#else +# define _GL_HAS_BUILTIN_OVERFLOW_P (7 <= __GNUC__) +#endif /* The _GL*_OVERFLOW macros have the same restrictions as the *_RANGE_OVERFLOW macros, except that they do not assume that operands @@ -395,7 +405,7 @@ For now, assume all versions of GCC-like compilers generate bogus warnings for _Generic. This matters only for compilers that lack relevant builtins. */ -#if __GNUC__ +#if __GNUC__ || defined __clang__ # define _GL__GENERIC_BOGUS 1 #else # define _GL__GENERIC_BOGUS 0 @@ -565,7 +575,7 @@ ? (EXPR_SIGNED (_GL_INT_CONVERT (tmax, b)) \ ? (a) < (tmax) / (b) \ : ((INT_NEGATE_OVERFLOW (b) \ - ? _GL_INT_CONVERT (b, tmax) >> (TYPE_WIDTH (b) - 1) \ + ? _GL_INT_CONVERT (b, tmax) >> (TYPE_WIDTH (+ (b)) - 1) \ : (tmax) / -(b)) \ <= -1 - (a))) \ : INT_NEGATE_OVERFLOW (_GL_INT_CONVERT (b, tmin)) && (b) == -1 \ diff --git a/contrib/tools/bison/lib/isnand-nolibm.h b/contrib/tools/bison/lib/isnand-nolibm.h index cbabed4c10..b3003c6ea3 100644 --- a/contrib/tools/bison/lib/isnand-nolibm.h +++ b/contrib/tools/bison/lib/isnand-nolibm.h @@ -17,8 +17,8 @@ #if HAVE_ISNAND_IN_LIBC /* Get declaration of isnan macro. */ # include <math.h> -# if __GNUC__ >= 4 - /* GCC 4.0 and newer provides three built-ins for isnan. */ +# if (__GNUC__ >= 4) || (__clang_major__ >= 4) + /* GCC >= 4.0 and clang provide a type-generic built-in for isnan. */ # undef isnand # define isnand(x) __builtin_isnan ((double)(x)) # else diff --git a/contrib/tools/bison/lib/isnanl-nolibm.h b/contrib/tools/bison/lib/isnanl-nolibm.h index c45e3ab2c7..927918ca66 100644 --- a/contrib/tools/bison/lib/isnanl-nolibm.h +++ b/contrib/tools/bison/lib/isnanl-nolibm.h @@ -17,10 +17,11 @@ #if HAVE_ISNANL_IN_LIBC /* Get declaration of isnan macro or (older) isnanl function. */ # include <math.h> -# if __GNUC__ >= 4 - /* GCC 4.0 and newer provides three built-ins for isnan. */ +# if (__GNUC__ >= 4) || (__clang_major__ >= 4) + /* GCC >= 4.0 and clang provide a type-generic built-in for isnan. + GCC >= 4.0 also provides __builtin_isnanl, but clang doesn't. */ # undef isnanl -# define isnanl(x) __builtin_isnanl ((long double)(x)) +# define isnanl(x) __builtin_isnan ((long double)(x)) # elif defined isnan # undef isnanl # define isnanl(x) isnan ((long double)(x)) diff --git a/contrib/tools/bison/lib/obstack.c b/contrib/tools/bison/lib/obstack.c index 780cda7b52..7a9d588478 100644 --- a/contrib/tools/bison/lib/obstack.c +++ b/contrib/tools/bison/lib/obstack.c @@ -322,7 +322,7 @@ int obstack_exit_failure = EXIT_FAILURE; # include <libio/iolibio.h> # endif -static _Noreturn void +static __attribute_noreturn__ void print_and_abort (void) { /* Don't change any of these strings. Yes, it would be possible to add diff --git a/contrib/tools/bison/lib/obstack.h b/contrib/tools/bison/lib/obstack.h index 3a7beb0ca3..980d1fe852 100644 --- a/contrib/tools/bison/lib/obstack.h +++ b/contrib/tools/bison/lib/obstack.h @@ -153,7 +153,7 @@ /* Not the same as _Noreturn, since it also works with function pointers. */ #ifndef __attribute_noreturn__ -# if 2 < __GNUC__ + (8 <= __GNUC_MINOR__) || 0x5110 <= __SUNPRO_C +# if 2 < __GNUC__ + (8 <= __GNUC_MINOR__) || defined __clang__ || 0x5110 <= __SUNPRO_C # define __attribute_noreturn__ __attribute__ ((__noreturn__)) # else # define __attribute_noreturn__ @@ -283,8 +283,9 @@ extern int obstack_exit_failure; #define obstack_memory_used(h) _obstack_memory_used (h) -#if defined __GNUC__ -# if !defined __GNUC_MINOR__ || __GNUC__ * 1000 + __GNUC_MINOR__ < 2008 +#if defined __GNUC__ || defined __clang__ +# if !(defined __GNUC_MINOR__ && __GNUC__ * 1000 + __GNUC_MINOR__ >= 2008 \ + || defined __clang__) # define __extension__ # endif diff --git a/contrib/tools/bison/lib/open.c b/contrib/tools/bison/lib/open.c index bb180fde29..0f7c6e9b9d 100644 --- a/contrib/tools/bison/lib/open.c +++ b/contrib/tools/bison/lib/open.c @@ -30,7 +30,11 @@ static int orig_open (const char *filename, int flags, mode_t mode) { +#if defined _WIN32 && !defined __CYGWIN__ + return _open (filename, flags, mode); +#else return open (filename, flags, mode); +#endif } /* Specification. */ @@ -124,7 +128,7 @@ open (const char *filename, int flags, ...) #endif fd = orig_open (filename, - flags & ~(have_cloexec <= 0 ? O_CLOEXEC : 0), mode); + flags & ~(have_cloexec < 0 ? O_CLOEXEC : 0), mode); if (flags & O_CLOEXEC) { diff --git a/contrib/tools/bison/lib/path-join.c b/contrib/tools/bison/lib/path-join.c index 411f331603..32e7f002ae 100644 --- a/contrib/tools/bison/lib/path-join.c +++ b/contrib/tools/bison/lib/path-join.c @@ -1,5 +1,5 @@ /* Concatenate path components. - Copyright (C) 2018-2020 Free Software Foundation, Inc. + Copyright (C) 2018-2021 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the diff --git a/contrib/tools/bison/lib/path-join.h b/contrib/tools/bison/lib/path-join.h index c4444a472c..18b6190fe3 100644 --- a/contrib/tools/bison/lib/path-join.h +++ b/contrib/tools/bison/lib/path-join.h @@ -1,5 +1,5 @@ /* Concatenate path components. - Copyright (C) 2018-2020 Free Software Foundation, Inc. + Copyright (C) 2018-2021 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the diff --git a/contrib/tools/bison/lib/platform/win64/sys/stat.h b/contrib/tools/bison/lib/platform/win64/sys/stat.h index 7a9004a80d..7f3df79756 100644 --- a/contrib/tools/bison/lib/platform/win64/sys/stat.h +++ b/contrib/tools/bison/lib/platform/win64/sys/stat.h @@ -943,7 +943,7 @@ _GL_WARN_ON_USE (mknodat, "mknodat is not portable - " #endif -#if 1 +#if 0 # if 1 /* We can't use the object-like #define stat rpl_stat, because of struct stat. This means that rpl_stat will not be used if the user diff --git a/contrib/tools/bison/lib/spawn-pipe.c b/contrib/tools/bison/lib/spawn-pipe.c index 3e5afbef94..d56a57cf8d 100644 --- a/contrib/tools/bison/lib/spawn-pipe.c +++ b/contrib/tools/bison/lib/spawn-pipe.c @@ -121,7 +121,7 @@ create_pipe (const char *progname, #if (defined _WIN32 && ! defined __CYGWIN__) || defined __KLIBC__ /* Native Windows API. - This uses _pipe(), dup2(), and spawnv(). It could also be implemented + This uses _pipe(), dup2(), and _spawnv(). It could also be implemented using the low-level functions CreatePipe(), DuplicateHandle(), CreateProcess() and _open_osfhandle(); see the GNU make and GNU clisp and cvs source code. */ @@ -189,25 +189,25 @@ create_pipe (const char *progname, /* The child process doesn't inherit ifd[0], ifd[1], ofd[0], ofd[1], but it inherits all open()ed or dup2()ed file handles (which is what we want in the case of STD*_FILENO). */ - /* Use spawnvpe and pass the environment explicitly. This is needed if + /* Use _spawnvpe and pass the environment explicitly. This is needed if the program has modified the environment using putenv() or [un]setenv(). On Windows, programs have two environments, one in the "environment block" of the process and managed through SetEnvironmentVariable(), and one inside the process, in the location retrieved by the 'environ' - macro. When using spawnvp() without 'e', the child process inherits a + macro. When using _spawnvp() without 'e', the child process inherits a copy of the environment block - ignoring the effects of putenv() and [un]setenv(). */ { - child = spawnvpe (P_NOWAIT, prog_path, (const char **) prog_argv, - (const char **) environ); + child = _spawnvpe (P_NOWAIT, prog_path, (const char **) prog_argv, + (const char **) environ); if (child < 0 && errno == ENOEXEC) { /* prog is not a native executable. Try to execute it as a shell script. Note that prepare_spawn() has already prepended a hidden element "sh.exe" to prog_argv. */ --prog_argv; - child = spawnvpe (P_NOWAIT, prog_argv[0], (const char **) prog_argv, - (const char **) environ); + child = _spawnvpe (P_NOWAIT, prog_argv[0], (const char **) prog_argv, + (const char **) environ); } } if (child == -1) diff --git a/contrib/tools/bison/lib/stdio-impl.h b/contrib/tools/bison/lib/stdio-impl.h index 067b95ebd6..15066aa59f 100644 --- a/contrib/tools/bison/lib/stdio-impl.h +++ b/contrib/tools/bison/lib/stdio-impl.h @@ -175,7 +175,7 @@ # define fp_ fp # endif -# if defined _SCO_DS /* OpenServer */ +# if defined _SCO_DS || (defined __SCO_VERSION__ || defined __sysv5__) /* OpenServer 5, OpenServer 6, UnixWare 7 */ # define _cnt __cnt # define _ptr __ptr # define _base __base diff --git a/contrib/tools/bison/lib/stpncpy.c b/contrib/tools/bison/lib/stpncpy.c new file mode 100644 index 0000000000..aca7838aa4 --- /dev/null +++ b/contrib/tools/bison/lib/stpncpy.c @@ -0,0 +1,92 @@ +/* Copyright (C) 1993, 1995-1997, 2002-2003, 2005-2007, 2009-2020 Free Software + * Foundation, Inc. + + NOTE: The canonical source of this file is maintained with the GNU C Library. + Bugs can be reported to bug-glibc@gnu.org. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 3 of the License, or any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* This is almost copied from strncpy.c, written by Torbjorn Granlund. */ + +#include <config.h> + +/* Specification. */ +#include <string.h> + +#ifndef weak_alias +# define __stpncpy stpncpy +#endif + +/* Copy no more than N bytes of SRC to DST, returning a pointer past the + last non-NUL byte written into DST. */ +char * +(__stpncpy) (char *dest, const char *src, size_t n) +{ + char c; + char *s = dest; + + if (n >= 4) + { + size_t n4 = n >> 2; + + for (;;) + { + c = *src++; + *dest++ = c; + if (c == '\0') + break; + c = *src++; + *dest++ = c; + if (c == '\0') + break; + c = *src++; + *dest++ = c; + if (c == '\0') + break; + c = *src++; + *dest++ = c; + if (c == '\0') + break; + if (--n4 == 0) + goto last_chars; + } + n -= dest - s; + goto zero_fill; + } + + last_chars: + n &= 3; + if (n == 0) + return dest; + + for (;;) + { + c = *src++; + --n; + *dest++ = c; + if (c == '\0') + break; + if (n == 0) + return dest; + } + + zero_fill: + while (n-- > 0) + dest[n] = '\0'; + + return dest - 1; +} +#ifdef weak_alias +weak_alias (__stpncpy, stpncpy) +#endif diff --git a/contrib/tools/bison/lib/streq.h b/contrib/tools/bison/lib/streq.h index d06c27200c..586f051262 100644 --- a/contrib/tools/bison/lib/streq.h +++ b/contrib/tools/bison/lib/streq.h @@ -29,7 +29,7 @@ /* Help GCC to generate good code for string comparisons with immediate strings. */ -#if defined (__GNUC__) && defined (__OPTIMIZE__) +#if (defined __GNUC__ || defined __clang__) && defined __OPTIMIZE__ static inline int streq9 (const char *s1, const char *s2) diff --git a/contrib/tools/bison/lib/textstyle.h b/contrib/tools/bison/lib/textstyle.h index 8cf63c7979..bdaafa4f5b 100644 --- a/contrib/tools/bison/lib/textstyle.h +++ b/contrib/tools/bison/lib/textstyle.h @@ -116,7 +116,7 @@ ostream_write_str (ostream_t stream, const char *string) static inline ptrdiff_t ostream_printf (ostream_t stream, const char *format, ...) -#if (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) || __GNUC__ > 3 +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) || defined __clang__ __attribute__ ((__format__ (__printf__, 2, 3))) #endif ; @@ -141,7 +141,7 @@ ostream_printf (ostream_t stream, const char *format, ...) static inline ptrdiff_t ostream_vprintf (ostream_t stream, const char *format, va_list args) -#if (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) || __GNUC__ > 3 +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) || defined __clang__ __attribute__ ((__format__ (__printf__, 2, 0))) #endif ; diff --git a/contrib/tools/bison/lib/thread-optim.h b/contrib/tools/bison/lib/thread-optim.h new file mode 100644 index 0000000000..b5166cfc6b --- /dev/null +++ b/contrib/tools/bison/lib/thread-optim.h @@ -0,0 +1,60 @@ +/* Optimization of multithreaded code. + + Copyright (C) 2020 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <bruno@clisp.org>, 2020. */ + +#ifndef _THREAD_OPTIM_H +#define _THREAD_OPTIM_H + +/* This file defines a way to optimize multithreaded code for the single-thread + case, based on the variable '__libc_single_threaded', defined in + glibc >= 2.32. */ + +/* Typical use: In a block or function, use + + bool mt = gl_multithreaded (); + ... + if (mt) + if (pthread_mutex_lock (&lock)) abort (); + ... + if (mt) + if (pthread_mutex_unlock (&lock)) abort (); + + The gl_multithreaded () invocation determines whether the program currently + is multithreaded. + + if (mt) STATEMENT executes STATEMENT in the multithreaded case, and skips + it in the single-threaded case. + + The code between the gl_multithreaded () invocation and any use of the + variable 'mt' must not create threads or invoke functions that may + indirectly create threads (e.g. 'dlopen' may, indirectly through C++ + initializers of global variables in the shared library being opened, + create threads). + + The lock here is meant to synchronize threads in the same process. The + same optimization cannot be applied to locks that synchronize different + processes (e.g. through shared memory mappings). */ + +#if HAVE_SYS_SINGLE_THREADED_H /* glibc >= 2.32 */ +# error #include <sys/single_threaded.h> +# define gl_multithreaded() !__libc_single_threaded +#else +# define gl_multithreaded() 1 +#endif + +#endif /* _THREAD_OPTIM_H */ diff --git a/contrib/tools/bison/lib/timespec.h b/contrib/tools/bison/lib/timespec.h index 02684ce6ea..dc999f944b 100644 --- a/contrib/tools/bison/lib/timespec.h +++ b/contrib/tools/bison/lib/timespec.h @@ -34,7 +34,6 @@ extern "C" { #endif #include "arg-nonnull.h" -#include "verify.h" /* Inverse resolution of timespec timestamps (in units per second), and log base 10 of the inverse resolution. */ @@ -59,46 +58,12 @@ make_timespec (time_t s, long int ns) return r; } -/* Return negative, zero, positive if A < B, A == B, A > B, respectively. - - For each timestamp T, this code assumes that either: - - * T.tv_nsec is in the range 0..999999999; or - * T.tv_sec corresponds to a valid leap second on a host that supports - leap seconds, and T.tv_nsec is in the range 1000000000..1999999999; or - * T.tv_sec is the minimum time_t value and T.tv_nsec is -1; or - T.tv_sec is the maximum time_t value and T.tv_nsec is 2000000000. - This allows for special struct timespec values that are less or - greater than all possible valid timestamps. - - In all these cases, it is safe to subtract two tv_nsec values and - convert the result to integer without worrying about overflow on - any platform of interest to the GNU project, since all such - platforms have 32-bit int or wider. - - Replacing "a.tv_nsec - b.tv_nsec" with something like - "a.tv_nsec < b.tv_nsec ? -1 : a.tv_nsec > b.tv_nsec" would cause - this function to work in some cases where the above assumption is - violated, but not in all cases (e.g., a.tv_sec==1, a.tv_nsec==-2, - b.tv_sec==0, b.tv_nsec==999999999) and is arguably not worth the - extra instructions. Using a subtraction has the advantage of - detecting some invalid cases on platforms that detect integer - overflow. */ +/* Return negative, zero, positive if A < B, A == B, A > B, respectively. */ _GL_TIMESPEC_INLINE int _GL_ATTRIBUTE_PURE timespec_cmp (struct timespec a, struct timespec b) { - if (a.tv_sec < b.tv_sec) - return -1; - if (a.tv_sec > b.tv_sec) - return 1; - - /* Pacify gcc -Wstrict-overflow (bleeding-edge circa 2017-10-02). See: - https://lists.gnu.org/r/bug-gnulib/2017-10/msg00006.html */ - assume (-1 <= a.tv_nsec && a.tv_nsec <= 2 * TIMESPEC_HZ); - assume (-1 <= b.tv_nsec && b.tv_nsec <= 2 * TIMESPEC_HZ); - - return a.tv_nsec - b.tv_nsec; + return 2 * _GL_CMP (a.tv_sec, b.tv_sec) + _GL_CMP (a.tv_nsec, b.tv_nsec); } /* Return -1, 0, 1, depending on the sign of A. A.tv_nsec must be @@ -106,7 +71,7 @@ timespec_cmp (struct timespec a, struct timespec b) _GL_TIMESPEC_INLINE int _GL_ATTRIBUTE_PURE timespec_sign (struct timespec a) { - return a.tv_sec < 0 ? -1 : a.tv_sec || a.tv_nsec; + return _GL_CMP (a.tv_sec, 0) + (!a.tv_sec & !!a.tv_nsec); } struct timespec timespec_add (struct timespec, struct timespec) diff --git a/contrib/tools/bison/lib/timevar.def b/contrib/tools/bison/lib/timevar.def index 6e0d6ff054..011835278f 100644 --- a/contrib/tools/bison/lib/timevar.def +++ b/contrib/tools/bison/lib/timevar.def @@ -1,7 +1,7 @@ /* This file contains the definitions for timing variables used to -*- C -*- measure run-time performance of the compiler. - Copyright (C) 2002, 2007, 2009-2015, 2018-2020 Free Software + Copyright (C) 2002, 2007, 2009-2015, 2018-2021 Free Software Foundation, Inc. Contributed by Akim Demaille <akim@freefriends.org>. @@ -19,7 +19,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ /* This file contains timing variable definitions, used by timevar.h and timevar.c. diff --git a/contrib/tools/bison/lib/unicodeio.c b/contrib/tools/bison/lib/unicodeio.c new file mode 100644 index 0000000000..d587a278d6 --- /dev/null +++ b/contrib/tools/bison/lib/unicodeio.c @@ -0,0 +1,232 @@ +/* Unicode character output to streams with locale dependent encoding. + + Copyright (C) 2000-2003, 2006, 2008-2020 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <haible@clisp.cons.org>. */ + +#include <config.h> + +/* Specification. */ +#include "unicodeio.h" + +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#if HAVE_ICONV +# include <iconv.h> +#endif + +#include <error.h> + +#include "gettext.h" +#define _(msgid) gettext (msgid) +#define N_(msgid) msgid + +#include "localcharset.h" +#include "unistr.h" + +/* When we pass a Unicode character to iconv(), we must pass it in a + suitable encoding. The standardized Unicode encodings are + UTF-8, UCS-2, UCS-4, UTF-16, UTF-16BE, UTF-16LE, UTF-7. + UCS-2 supports only characters up to \U0000FFFF. + UTF-16 and variants support only characters up to \U0010FFFF. + UTF-7 is way too complex and not supported by glibc-2.1. + UCS-4 specification leaves doubts about endianness and byte order + mark. glibc currently interprets it as big endian without byte order + mark, but this is not backed by an RFC. + So we use UTF-8. It supports characters up to \U7FFFFFFF and is + unambiguously defined. */ + +/* Luckily, the encoding's name is platform independent. */ +#define UTF8_NAME "UTF-8" + +/* Converts the Unicode character CODE to its multibyte representation + in the current locale and calls the SUCCESS callback on the resulting + byte sequence. If an error occurs, invokes the FAILURE callback instead, + passing it CODE and an English error string. + Returns whatever the callback returned. + Assumes that the locale doesn't change between two calls. */ +long +unicode_to_mb (unsigned int code, + long (*success) (const char *buf, size_t buflen, + void *callback_arg), + long (*failure) (unsigned int code, const char *msg, + void *callback_arg), + void *callback_arg) +{ + static int initialized; + static int is_utf8; +#if HAVE_ICONV + static iconv_t utf8_to_local; +#endif + + char inbuf[6]; + int count; + + if (!initialized) + { + const char *charset = locale_charset (); + + is_utf8 = !strcmp (charset, UTF8_NAME); +#if HAVE_ICONV + if (!is_utf8) + { + utf8_to_local = iconv_open (charset, UTF8_NAME); + if (utf8_to_local == (iconv_t)(-1)) + /* For an unknown encoding, assume ASCII. */ + utf8_to_local = iconv_open ("ASCII", UTF8_NAME); + } +#endif + initialized = 1; + } + + /* Test whether the utf8_to_local converter is available at all. */ + if (!is_utf8) + { +#if HAVE_ICONV + if (utf8_to_local == (iconv_t)(-1)) + return failure (code, N_("iconv function not usable"), callback_arg); +#else + return failure (code, N_("iconv function not available"), callback_arg); +#endif + } + + /* Convert the character to UTF-8. */ + count = u8_uctomb ((unsigned char *) inbuf, code, sizeof (inbuf)); + if (count < 0) + return failure (code, N_("character out of range"), callback_arg); + +#if HAVE_ICONV + if (!is_utf8) + { + char outbuf[25]; + const char *inptr; + size_t inbytesleft; + char *outptr; + size_t outbytesleft; + size_t res; + + inptr = inbuf; + inbytesleft = count; + outptr = outbuf; + outbytesleft = sizeof (outbuf); + + /* Convert the character from UTF-8 to the locale's charset. */ + res = iconv (utf8_to_local, + (ICONV_CONST char **)&inptr, &inbytesleft, + &outptr, &outbytesleft); + /* Analyze what iconv() actually did and distinguish replacements + that are OK (no need to invoke the FAILURE callback), such as + - replacing GREEK SMALL LETTER MU with MICRO SIGN, or + - replacing FULLWIDTH COLON with ':', or + - replacing a Unicode TAG character (U+E00xx) with an empty string, + from replacements that are worse than the FAILURE callback, such as + - replacing 'ç' with '?' (NetBSD, Solaris 11) or '*' (musl) or + NUL (IRIX). */ + if (inbytesleft > 0 || res == (size_t)(-1) + /* Irix iconv() inserts a NUL byte if it cannot convert. */ +# if !defined _LIBICONV_VERSION && (defined sgi || defined __sgi) + || (res > 0 && code != 0 && outptr - outbuf == 1 && *outbuf == '\0') +# endif + /* NetBSD iconv() and Solaris 11 iconv() insert a '?' if they cannot + convert. */ +# if !defined _LIBICONV_VERSION && (defined __NetBSD__ || defined __sun) + || (res > 0 && outptr - outbuf == 1 && *outbuf == '?') +# endif + /* musl libc iconv() inserts a '*' if it cannot convert. */ +# if !defined _LIBICONV_VERSION && MUSL_LIBC + || (res > 0 && outptr - outbuf == 1 && *outbuf == '*') +# endif + ) + return failure (code, NULL, callback_arg); + + /* Avoid glibc-2.1 bug and Solaris 7 bug. */ +# if defined _LIBICONV_VERSION \ + || !(((__GLIBC__ - 0 == 2 && __GLIBC_MINOR__ - 0 <= 1) \ + && !defined __UCLIBC__) \ + || defined __sun) + + /* Get back to the initial shift state. */ + res = iconv (utf8_to_local, NULL, NULL, &outptr, &outbytesleft); + if (res == (size_t)(-1)) + return failure (code, NULL, callback_arg); +# endif + + return success (outbuf, outptr - outbuf, callback_arg); + } +#endif + + /* At this point, is_utf8 is true, so no conversion is needed. */ + return success (inbuf, count, callback_arg); +} + +/* Simple success callback that outputs the converted string. + The STREAM is passed as callback_arg. */ +long +fwrite_success_callback (const char *buf, size_t buflen, void *callback_arg) +{ + FILE *stream = (FILE *) callback_arg; + + /* The return value of fwrite can be ignored here, because under normal + conditions (STREAM is an open stream and not wide-character oriented) + when fwrite() returns a value != buflen it also sets STREAM's error + indicator. */ + fwrite (buf, 1, buflen, stream); + return 0; +} + +/* Simple failure callback that displays an error and exits. */ +static long +exit_failure_callback (unsigned int code, const char *msg, + void *callback_arg _GL_UNUSED) +{ + if (msg == NULL) + error (1, 0, _("cannot convert U+%04X to local character set"), code); + else + error (1, 0, _("cannot convert U+%04X to local character set: %s"), code, + gettext (msg)); + return -1; +} + +/* Simple failure callback that displays a fallback representation in plain + ASCII, using the same notation as ISO C99 strings. */ +static long +fallback_failure_callback (unsigned int code, + const char *msg _GL_UNUSED, + void *callback_arg) +{ + FILE *stream = (FILE *) callback_arg; + + if (code < 0x10000) + fprintf (stream, "\\u%04X", code); + else + fprintf (stream, "\\U%08X", code); + return -1; +} + +/* Outputs the Unicode character CODE to the output stream STREAM. + Upon failure, exit if exit_on_error is true, otherwise output a fallback + notation. */ +void +print_unicode_char (FILE *stream, unsigned int code, int exit_on_error) +{ + unicode_to_mb (code, fwrite_success_callback, + exit_on_error + ? exit_failure_callback + : fallback_failure_callback, + stream); +} diff --git a/contrib/tools/bison/lib/unicodeio.h b/contrib/tools/bison/lib/unicodeio.h new file mode 100644 index 0000000000..bd897acedf --- /dev/null +++ b/contrib/tools/bison/lib/unicodeio.h @@ -0,0 +1,48 @@ +/* Unicode character output to streams with locale dependent encoding. + + Copyright (C) 2000-2003, 2005, 2008-2020 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef UNICODEIO_H +# define UNICODEIO_H + +# include <stddef.h> +# include <stdio.h> + +/* Converts the Unicode character CODE to its multibyte representation + in the current locale and calls the SUCCESS callback on the resulting + byte sequence. If an error occurs, invokes the FAILURE callback instead, + passing it CODE and an English error string. + Returns whatever the callback returned. + Assumes that the locale doesn't change between two calls. */ +extern long unicode_to_mb (unsigned int code, + long (*success) (const char *buf, size_t buflen, + void *callback_arg), + long (*failure) (unsigned int code, const char *msg, + void *callback_arg), + void *callback_arg); + +/* Outputs the Unicode character CODE to the output stream STREAM. + Upon failure, exit if exit_on_error is true, otherwise output a fallback + notation. */ +extern void print_unicode_char (FILE *stream, unsigned int code, + int exit_on_error); + +/* Simple success callback that outputs the converted string. + The STREAM is passed as callback_arg. */ +extern long fwrite_success_callback (const char *buf, size_t buflen, + void *callback_arg); + +#endif diff --git a/contrib/tools/bison/lib/unistr.h b/contrib/tools/bison/lib/unistr.h new file mode 100644 index 0000000000..8d8fd0f010 --- /dev/null +++ b/contrib/tools/bison/lib/unistr.h @@ -0,0 +1,750 @@ +/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ +/* Elementary Unicode string functions. + Copyright (C) 2001-2002, 2005-2020 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _UNISTR_H +#define _UNISTR_H + +#include "unitypes.h" + +/* Get common macros for C. */ +#include "unused-parameter.h" + +/* Get bool. */ +#include <stdbool.h> + +/* Get size_t, ptrdiff_t. */ +#include <stddef.h> + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Conventions: + + All functions prefixed with u8_ operate on UTF-8 encoded strings. + Their unit is an uint8_t (1 byte). + + All functions prefixed with u16_ operate on UTF-16 encoded strings. + Their unit is an uint16_t (a 2-byte word). + + All functions prefixed with u32_ operate on UCS-4 encoded strings. + Their unit is an uint32_t (a 4-byte word). + + All argument pairs (s, n) denote a Unicode string s[0..n-1] with exactly + n units. + + All arguments starting with "str" and the arguments of functions starting + with u8_str/u16_str/u32_str denote a NUL terminated string, i.e. a string + which terminates at the first NUL unit. This termination unit is + considered part of the string for all memory allocation purposes, but + is not considered part of the string for all other logical purposes. + + Functions returning a string result take a (resultbuf, lengthp) argument + pair. If resultbuf is not NULL and the result fits into *lengthp units, + it is put in resultbuf, and resultbuf is returned. Otherwise, a freshly + allocated string is returned. In both cases, *lengthp is set to the + length (number of units) of the returned string. In case of error, + NULL is returned and errno is set. */ + + +/* Elementary string checks. */ + +/* Check whether an UTF-8 string is well-formed. + Return NULL if valid, or a pointer to the first invalid unit otherwise. */ +extern const uint8_t * + u8_check (const uint8_t *s, size_t n) + _UC_ATTRIBUTE_PURE; + +/* Check whether an UTF-16 string is well-formed. + Return NULL if valid, or a pointer to the first invalid unit otherwise. */ +extern const uint16_t * + u16_check (const uint16_t *s, size_t n) + _UC_ATTRIBUTE_PURE; + +/* Check whether an UCS-4 string is well-formed. + Return NULL if valid, or a pointer to the first invalid unit otherwise. */ +extern const uint32_t * + u32_check (const uint32_t *s, size_t n) + _UC_ATTRIBUTE_PURE; + + +/* Elementary string conversions. */ + +/* Convert an UTF-8 string to an UTF-16 string. */ +extern uint16_t * + u8_to_u16 (const uint8_t *s, size_t n, uint16_t *resultbuf, + size_t *lengthp); + +/* Convert an UTF-8 string to an UCS-4 string. */ +extern uint32_t * + u8_to_u32 (const uint8_t *s, size_t n, uint32_t *resultbuf, + size_t *lengthp); + +/* Convert an UTF-16 string to an UTF-8 string. */ +extern uint8_t * + u16_to_u8 (const uint16_t *s, size_t n, uint8_t *resultbuf, + size_t *lengthp); + +/* Convert an UTF-16 string to an UCS-4 string. */ +extern uint32_t * + u16_to_u32 (const uint16_t *s, size_t n, uint32_t *resultbuf, + size_t *lengthp); + +/* Convert an UCS-4 string to an UTF-8 string. */ +extern uint8_t * + u32_to_u8 (const uint32_t *s, size_t n, uint8_t *resultbuf, + size_t *lengthp); + +/* Convert an UCS-4 string to an UTF-16 string. */ +extern uint16_t * + u32_to_u16 (const uint32_t *s, size_t n, uint16_t *resultbuf, + size_t *lengthp); + + +/* Elementary string functions. */ + +/* Return the length (number of units) of the first character in S, which is + no longer than N. Return 0 if it is the NUL character. Return -1 upon + failure. */ +/* Similar to mblen(), except that s must not be NULL. */ +extern int + u8_mblen (const uint8_t *s, size_t n) + _UC_ATTRIBUTE_PURE; +extern int + u16_mblen (const uint16_t *s, size_t n) + _UC_ATTRIBUTE_PURE; +extern int + u32_mblen (const uint32_t *s, size_t n) + _UC_ATTRIBUTE_PURE; + +/* Return the length (number of units) of the first character in S, putting + its 'ucs4_t' representation in *PUC. Upon failure, *PUC is set to 0xfffd, + and an appropriate number of units is returned. + The number of available units, N, must be > 0. */ +/* Similar to mbtowc(), except that puc and s must not be NULL, n must be > 0, + and the NUL character is not treated specially. */ +/* The variants with _unsafe suffix are for backward compatibility with + libunistring versions < 0.9.7. */ + +#if GNULIB_UNISTR_U8_MBTOUC_UNSAFE || HAVE_LIBUNISTRING +# if !HAVE_INLINE +extern int + u8_mbtouc_unsafe (ucs4_t *puc, const uint8_t *s, size_t n); +# else +extern int + u8_mbtouc_unsafe_aux (ucs4_t *puc, const uint8_t *s, size_t n); +static inline int +u8_mbtouc_unsafe (ucs4_t *puc, const uint8_t *s, size_t n) +{ + uint8_t c = *s; + + if (c < 0x80) + { + *puc = c; + return 1; + } + else + return u8_mbtouc_unsafe_aux (puc, s, n); +} +# endif +#endif + +#if GNULIB_UNISTR_U16_MBTOUC_UNSAFE || HAVE_LIBUNISTRING +# if !HAVE_INLINE +extern int + u16_mbtouc_unsafe (ucs4_t *puc, const uint16_t *s, size_t n); +# else +extern int + u16_mbtouc_unsafe_aux (ucs4_t *puc, const uint16_t *s, size_t n); +static inline int +u16_mbtouc_unsafe (ucs4_t *puc, const uint16_t *s, size_t n) +{ + uint16_t c = *s; + + if (c < 0xd800 || c >= 0xe000) + { + *puc = c; + return 1; + } + else + return u16_mbtouc_unsafe_aux (puc, s, n); +} +# endif +#endif + +#if GNULIB_UNISTR_U32_MBTOUC_UNSAFE || HAVE_LIBUNISTRING +# if !HAVE_INLINE +extern int + u32_mbtouc_unsafe (ucs4_t *puc, const uint32_t *s, size_t n); +# else +static inline int +u32_mbtouc_unsafe (ucs4_t *puc, + const uint32_t *s, size_t n _GL_UNUSED_PARAMETER) +{ + uint32_t c = *s; + + if (c < 0xd800 || (c >= 0xe000 && c < 0x110000)) + *puc = c; + else + /* invalid multibyte character */ + *puc = 0xfffd; + return 1; +} +# endif +#endif + +#if GNULIB_UNISTR_U8_MBTOUC || HAVE_LIBUNISTRING +# if !HAVE_INLINE +extern int + u8_mbtouc (ucs4_t *puc, const uint8_t *s, size_t n); +# else +extern int + u8_mbtouc_aux (ucs4_t *puc, const uint8_t *s, size_t n); +static inline int +u8_mbtouc (ucs4_t *puc, const uint8_t *s, size_t n) +{ + uint8_t c = *s; + + if (c < 0x80) + { + *puc = c; + return 1; + } + else + return u8_mbtouc_aux (puc, s, n); +} +# endif +#endif + +#if GNULIB_UNISTR_U16_MBTOUC || HAVE_LIBUNISTRING +# if !HAVE_INLINE +extern int + u16_mbtouc (ucs4_t *puc, const uint16_t *s, size_t n); +# else +extern int + u16_mbtouc_aux (ucs4_t *puc, const uint16_t *s, size_t n); +static inline int +u16_mbtouc (ucs4_t *puc, const uint16_t *s, size_t n) +{ + uint16_t c = *s; + + if (c < 0xd800 || c >= 0xe000) + { + *puc = c; + return 1; + } + else + return u16_mbtouc_aux (puc, s, n); +} +# endif +#endif + +#if GNULIB_UNISTR_U32_MBTOUC || HAVE_LIBUNISTRING +# if !HAVE_INLINE +extern int + u32_mbtouc (ucs4_t *puc, const uint32_t *s, size_t n); +# else +static inline int +u32_mbtouc (ucs4_t *puc, const uint32_t *s, size_t n _GL_UNUSED_PARAMETER) +{ + uint32_t c = *s; + + if (c < 0xd800 || (c >= 0xe000 && c < 0x110000)) + *puc = c; + else + /* invalid multibyte character */ + *puc = 0xfffd; + return 1; +} +# endif +#endif + +/* Return the length (number of units) of the first character in S, putting + its 'ucs4_t' representation in *PUC. Upon failure, *PUC is set to 0xfffd, + and -1 is returned for an invalid sequence of units, -2 is returned for an + incomplete sequence of units. + The number of available units, N, must be > 0. */ +/* Similar to u*_mbtouc(), except that the return value gives more details + about the failure, similar to mbrtowc(). */ + +#if GNULIB_UNISTR_U8_MBTOUCR || HAVE_LIBUNISTRING +extern int + u8_mbtoucr (ucs4_t *puc, const uint8_t *s, size_t n); +#endif + +#if GNULIB_UNISTR_U16_MBTOUCR || HAVE_LIBUNISTRING +extern int + u16_mbtoucr (ucs4_t *puc, const uint16_t *s, size_t n); +#endif + +#if GNULIB_UNISTR_U32_MBTOUCR || HAVE_LIBUNISTRING +extern int + u32_mbtoucr (ucs4_t *puc, const uint32_t *s, size_t n); +#endif + +/* Put the multibyte character represented by UC in S, returning its + length. Return -1 upon failure, -2 if the number of available units, N, + is too small. The latter case cannot occur if N >= 6/2/1, respectively. */ +/* Similar to wctomb(), except that s must not be NULL, and the argument n + must be specified. */ + +#if GNULIB_UNISTR_U8_UCTOMB || HAVE_LIBUNISTRING +/* Auxiliary function, also used by u8_chr, u8_strchr, u8_strrchr. */ +extern int + u8_uctomb_aux (uint8_t *s, ucs4_t uc, ptrdiff_t n); +# if !HAVE_INLINE +extern int + u8_uctomb (uint8_t *s, ucs4_t uc, ptrdiff_t n); +# else +static inline int +u8_uctomb (uint8_t *s, ucs4_t uc, ptrdiff_t n) +{ + if (uc < 0x80 && n > 0) + { + s[0] = uc; + return 1; + } + else + return u8_uctomb_aux (s, uc, n); +} +# endif +#endif + +#if GNULIB_UNISTR_U16_UCTOMB || HAVE_LIBUNISTRING +/* Auxiliary function, also used by u16_chr, u16_strchr, u16_strrchr. */ +extern int + u16_uctomb_aux (uint16_t *s, ucs4_t uc, ptrdiff_t n); +# if !HAVE_INLINE +extern int + u16_uctomb (uint16_t *s, ucs4_t uc, ptrdiff_t n); +# else +static inline int +u16_uctomb (uint16_t *s, ucs4_t uc, ptrdiff_t n) +{ + if (uc < 0xd800 && n > 0) + { + s[0] = uc; + return 1; + } + else + return u16_uctomb_aux (s, uc, n); +} +# endif +#endif + +#if GNULIB_UNISTR_U32_UCTOMB || HAVE_LIBUNISTRING +# if !HAVE_INLINE +extern int + u32_uctomb (uint32_t *s, ucs4_t uc, ptrdiff_t n); +# else +static inline int +u32_uctomb (uint32_t *s, ucs4_t uc, ptrdiff_t n) +{ + if (uc < 0xd800 || (uc >= 0xe000 && uc < 0x110000)) + { + if (n > 0) + { + *s = uc; + return 1; + } + else + return -2; + } + else + return -1; +} +# endif +#endif + +/* Copy N units from SRC to DEST. */ +/* Similar to memcpy(). */ +extern uint8_t * + u8_cpy (uint8_t *_UC_RESTRICT dest, const uint8_t *src, size_t n); +extern uint16_t * + u16_cpy (uint16_t *_UC_RESTRICT dest, const uint16_t *src, size_t n); +extern uint32_t * + u32_cpy (uint32_t *_UC_RESTRICT dest, const uint32_t *src, size_t n); + +/* Copy N units from SRC to DEST, guaranteeing correct behavior for + overlapping memory areas. */ +/* Similar to memmove(). */ +extern uint8_t * + u8_move (uint8_t *dest, const uint8_t *src, size_t n); +extern uint16_t * + u16_move (uint16_t *dest, const uint16_t *src, size_t n); +extern uint32_t * + u32_move (uint32_t *dest, const uint32_t *src, size_t n); + +/* Set the first N characters of S to UC. UC should be a character that + occupies only 1 unit. */ +/* Similar to memset(). */ +extern uint8_t * + u8_set (uint8_t *s, ucs4_t uc, size_t n); +extern uint16_t * + u16_set (uint16_t *s, ucs4_t uc, size_t n); +extern uint32_t * + u32_set (uint32_t *s, ucs4_t uc, size_t n); + +/* Compare S1 and S2, each of length N. */ +/* Similar to memcmp(). */ +extern int + u8_cmp (const uint8_t *s1, const uint8_t *s2, size_t n) + _UC_ATTRIBUTE_PURE; +extern int + u16_cmp (const uint16_t *s1, const uint16_t *s2, size_t n) + _UC_ATTRIBUTE_PURE; +extern int + u32_cmp (const uint32_t *s1, const uint32_t *s2, size_t n) + _UC_ATTRIBUTE_PURE; + +/* Compare S1 and S2. */ +/* Similar to the gnulib function memcmp2(). */ +extern int + u8_cmp2 (const uint8_t *s1, size_t n1, const uint8_t *s2, size_t n2) + _UC_ATTRIBUTE_PURE; +extern int + u16_cmp2 (const uint16_t *s1, size_t n1, const uint16_t *s2, size_t n2) + _UC_ATTRIBUTE_PURE; +extern int + u32_cmp2 (const uint32_t *s1, size_t n1, const uint32_t *s2, size_t n2) + _UC_ATTRIBUTE_PURE; + +/* Search the string at S for UC. */ +/* Similar to memchr(). */ +extern uint8_t * + u8_chr (const uint8_t *s, size_t n, ucs4_t uc) + _UC_ATTRIBUTE_PURE; +extern uint16_t * + u16_chr (const uint16_t *s, size_t n, ucs4_t uc) + _UC_ATTRIBUTE_PURE; +extern uint32_t * + u32_chr (const uint32_t *s, size_t n, ucs4_t uc) + _UC_ATTRIBUTE_PURE; + +/* Count the number of Unicode characters in the N units from S. */ +/* Similar to mbsnlen(). */ +extern size_t + u8_mbsnlen (const uint8_t *s, size_t n) + _UC_ATTRIBUTE_PURE; +extern size_t + u16_mbsnlen (const uint16_t *s, size_t n) + _UC_ATTRIBUTE_PURE; +extern size_t + u32_mbsnlen (const uint32_t *s, size_t n) + _UC_ATTRIBUTE_PURE; + +/* Elementary string functions with memory allocation. */ + +/* Make a freshly allocated copy of S, of length N. */ +extern uint8_t * + u8_cpy_alloc (const uint8_t *s, size_t n); +extern uint16_t * + u16_cpy_alloc (const uint16_t *s, size_t n); +extern uint32_t * + u32_cpy_alloc (const uint32_t *s, size_t n); + +/* Elementary string functions on NUL terminated strings. */ + +/* Return the length (number of units) of the first character in S. + Return 0 if it is the NUL character. Return -1 upon failure. */ +extern int + u8_strmblen (const uint8_t *s) + _UC_ATTRIBUTE_PURE; +extern int + u16_strmblen (const uint16_t *s) + _UC_ATTRIBUTE_PURE; +extern int + u32_strmblen (const uint32_t *s) + _UC_ATTRIBUTE_PURE; + +/* Return the length (number of units) of the first character in S, putting + its 'ucs4_t' representation in *PUC. Return 0 if it is the NUL + character. Return -1 upon failure. */ +extern int + u8_strmbtouc (ucs4_t *puc, const uint8_t *s); +extern int + u16_strmbtouc (ucs4_t *puc, const uint16_t *s); +extern int + u32_strmbtouc (ucs4_t *puc, const uint32_t *s); + +/* Forward iteration step. Advances the pointer past the next character, + or returns NULL if the end of the string has been reached. Puts the + character's 'ucs4_t' representation in *PUC. */ +extern const uint8_t * + u8_next (ucs4_t *puc, const uint8_t *s); +extern const uint16_t * + u16_next (ucs4_t *puc, const uint16_t *s); +extern const uint32_t * + u32_next (ucs4_t *puc, const uint32_t *s); + +/* Backward iteration step. Advances the pointer to point to the previous + character, or returns NULL if the beginning of the string had been reached. + Puts the character's 'ucs4_t' representation in *PUC. */ +extern const uint8_t * + u8_prev (ucs4_t *puc, const uint8_t *s, const uint8_t *start); +extern const uint16_t * + u16_prev (ucs4_t *puc, const uint16_t *s, const uint16_t *start); +extern const uint32_t * + u32_prev (ucs4_t *puc, const uint32_t *s, const uint32_t *start); + +/* Return the number of units in S. */ +/* Similar to strlen(), wcslen(). */ +extern size_t + u8_strlen (const uint8_t *s) + _UC_ATTRIBUTE_PURE; +extern size_t + u16_strlen (const uint16_t *s) + _UC_ATTRIBUTE_PURE; +extern size_t + u32_strlen (const uint32_t *s) + _UC_ATTRIBUTE_PURE; + +/* Return the number of units in S, but at most MAXLEN. */ +/* Similar to strnlen(), wcsnlen(). */ +extern size_t + u8_strnlen (const uint8_t *s, size_t maxlen) + _UC_ATTRIBUTE_PURE; +extern size_t + u16_strnlen (const uint16_t *s, size_t maxlen) + _UC_ATTRIBUTE_PURE; +extern size_t + u32_strnlen (const uint32_t *s, size_t maxlen) + _UC_ATTRIBUTE_PURE; + +/* Copy SRC to DEST. */ +/* Similar to strcpy(), wcscpy(). */ +extern uint8_t * + u8_strcpy (uint8_t *_UC_RESTRICT dest, const uint8_t *src); +extern uint16_t * + u16_strcpy (uint16_t *_UC_RESTRICT dest, const uint16_t *src); +extern uint32_t * + u32_strcpy (uint32_t *_UC_RESTRICT dest, const uint32_t *src); + +/* Copy SRC to DEST, returning the address of the terminating NUL in DEST. */ +/* Similar to stpcpy(). */ +extern uint8_t * + u8_stpcpy (uint8_t *_UC_RESTRICT dest, const uint8_t *src); +extern uint16_t * + u16_stpcpy (uint16_t *_UC_RESTRICT dest, const uint16_t *src); +extern uint32_t * + u32_stpcpy (uint32_t *_UC_RESTRICT dest, const uint32_t *src); + +/* Copy no more than N units of SRC to DEST. */ +/* Similar to strncpy(), wcsncpy(). */ +extern uint8_t * + u8_strncpy (uint8_t *_UC_RESTRICT dest, const uint8_t *src, size_t n); +extern uint16_t * + u16_strncpy (uint16_t *_UC_RESTRICT dest, const uint16_t *src, size_t n); +extern uint32_t * + u32_strncpy (uint32_t *_UC_RESTRICT dest, const uint32_t *src, size_t n); + +/* Copy no more than N units of SRC to DEST. Return a pointer past the last + non-NUL unit written into DEST. */ +/* Similar to stpncpy(). */ +extern uint8_t * + u8_stpncpy (uint8_t *_UC_RESTRICT dest, const uint8_t *src, size_t n); +extern uint16_t * + u16_stpncpy (uint16_t *_UC_RESTRICT dest, const uint16_t *src, size_t n); +extern uint32_t * + u32_stpncpy (uint32_t *_UC_RESTRICT dest, const uint32_t *src, size_t n); + +/* Append SRC onto DEST. */ +/* Similar to strcat(), wcscat(). */ +extern uint8_t * + u8_strcat (uint8_t *_UC_RESTRICT dest, const uint8_t *src); +extern uint16_t * + u16_strcat (uint16_t *_UC_RESTRICT dest, const uint16_t *src); +extern uint32_t * + u32_strcat (uint32_t *_UC_RESTRICT dest, const uint32_t *src); + +/* Append no more than N units of SRC onto DEST. */ +/* Similar to strncat(), wcsncat(). */ +extern uint8_t * + u8_strncat (uint8_t *_UC_RESTRICT dest, const uint8_t *src, size_t n); +extern uint16_t * + u16_strncat (uint16_t *_UC_RESTRICT dest, const uint16_t *src, size_t n); +extern uint32_t * + u32_strncat (uint32_t *_UC_RESTRICT dest, const uint32_t *src, size_t n); + +/* Compare S1 and S2. */ +/* Similar to strcmp(), wcscmp(). */ +#ifdef __sun +/* Avoid a collision with the u8_strcmp() function in Solaris 11 libc. */ +extern int + u8_strcmp_gnu (const uint8_t *s1, const uint8_t *s2) + _UC_ATTRIBUTE_PURE; +# define u8_strcmp u8_strcmp_gnu +#else +extern int + u8_strcmp (const uint8_t *s1, const uint8_t *s2) + _UC_ATTRIBUTE_PURE; +#endif +extern int + u16_strcmp (const uint16_t *s1, const uint16_t *s2) + _UC_ATTRIBUTE_PURE; +extern int + u32_strcmp (const uint32_t *s1, const uint32_t *s2) + _UC_ATTRIBUTE_PURE; + +/* Compare S1 and S2 using the collation rules of the current locale. + Return -1 if S1 < S2, 0 if S1 = S2, 1 if S1 > S2. + Upon failure, set errno and return any value. */ +/* Similar to strcoll(), wcscoll(). */ +extern int + u8_strcoll (const uint8_t *s1, const uint8_t *s2); +extern int + u16_strcoll (const uint16_t *s1, const uint16_t *s2); +extern int + u32_strcoll (const uint32_t *s1, const uint32_t *s2); + +/* Compare no more than N units of S1 and S2. */ +/* Similar to strncmp(), wcsncmp(). */ +extern int + u8_strncmp (const uint8_t *s1, const uint8_t *s2, size_t n) + _UC_ATTRIBUTE_PURE; +extern int + u16_strncmp (const uint16_t *s1, const uint16_t *s2, size_t n) + _UC_ATTRIBUTE_PURE; +extern int + u32_strncmp (const uint32_t *s1, const uint32_t *s2, size_t n) + _UC_ATTRIBUTE_PURE; + +/* Duplicate S, returning an identical malloc'd string. */ +/* Similar to strdup(), wcsdup(). */ +extern uint8_t * + u8_strdup (const uint8_t *s); +extern uint16_t * + u16_strdup (const uint16_t *s); +extern uint32_t * + u32_strdup (const uint32_t *s); + +/* Find the first occurrence of UC in STR. */ +/* Similar to strchr(), wcschr(). */ +extern uint8_t * + u8_strchr (const uint8_t *str, ucs4_t uc) + _UC_ATTRIBUTE_PURE; +extern uint16_t * + u16_strchr (const uint16_t *str, ucs4_t uc) + _UC_ATTRIBUTE_PURE; +extern uint32_t * + u32_strchr (const uint32_t *str, ucs4_t uc) + _UC_ATTRIBUTE_PURE; + +/* Find the last occurrence of UC in STR. */ +/* Similar to strrchr(), wcsrchr(). */ +extern uint8_t * + u8_strrchr (const uint8_t *str, ucs4_t uc) + _UC_ATTRIBUTE_PURE; +extern uint16_t * + u16_strrchr (const uint16_t *str, ucs4_t uc) + _UC_ATTRIBUTE_PURE; +extern uint32_t * + u32_strrchr (const uint32_t *str, ucs4_t uc) + _UC_ATTRIBUTE_PURE; + +/* Return the length of the initial segment of STR which consists entirely + of Unicode characters not in REJECT. */ +/* Similar to strcspn(), wcscspn(). */ +extern size_t + u8_strcspn (const uint8_t *str, const uint8_t *reject) + _UC_ATTRIBUTE_PURE; +extern size_t + u16_strcspn (const uint16_t *str, const uint16_t *reject) + _UC_ATTRIBUTE_PURE; +extern size_t + u32_strcspn (const uint32_t *str, const uint32_t *reject) + _UC_ATTRIBUTE_PURE; + +/* Return the length of the initial segment of STR which consists entirely + of Unicode characters in ACCEPT. */ +/* Similar to strspn(), wcsspn(). */ +extern size_t + u8_strspn (const uint8_t *str, const uint8_t *accept) + _UC_ATTRIBUTE_PURE; +extern size_t + u16_strspn (const uint16_t *str, const uint16_t *accept) + _UC_ATTRIBUTE_PURE; +extern size_t + u32_strspn (const uint32_t *str, const uint32_t *accept) + _UC_ATTRIBUTE_PURE; + +/* Find the first occurrence in STR of any character in ACCEPT. */ +/* Similar to strpbrk(), wcspbrk(). */ +extern uint8_t * + u8_strpbrk (const uint8_t *str, const uint8_t *accept) + _UC_ATTRIBUTE_PURE; +extern uint16_t * + u16_strpbrk (const uint16_t *str, const uint16_t *accept) + _UC_ATTRIBUTE_PURE; +extern uint32_t * + u32_strpbrk (const uint32_t *str, const uint32_t *accept) + _UC_ATTRIBUTE_PURE; + +/* Find the first occurrence of NEEDLE in HAYSTACK. */ +/* Similar to strstr(), wcsstr(). */ +extern uint8_t * + u8_strstr (const uint8_t *haystack, const uint8_t *needle) + _UC_ATTRIBUTE_PURE; +extern uint16_t * + u16_strstr (const uint16_t *haystack, const uint16_t *needle) + _UC_ATTRIBUTE_PURE; +extern uint32_t * + u32_strstr (const uint32_t *haystack, const uint32_t *needle) + _UC_ATTRIBUTE_PURE; + +/* Test whether STR starts with PREFIX. */ +extern bool + u8_startswith (const uint8_t *str, const uint8_t *prefix) + _UC_ATTRIBUTE_PURE; +extern bool + u16_startswith (const uint16_t *str, const uint16_t *prefix) + _UC_ATTRIBUTE_PURE; +extern bool + u32_startswith (const uint32_t *str, const uint32_t *prefix) + _UC_ATTRIBUTE_PURE; + +/* Test whether STR ends with SUFFIX. */ +extern bool + u8_endswith (const uint8_t *str, const uint8_t *suffix) + _UC_ATTRIBUTE_PURE; +extern bool + u16_endswith (const uint16_t *str, const uint16_t *suffix) + _UC_ATTRIBUTE_PURE; +extern bool + u32_endswith (const uint32_t *str, const uint32_t *suffix) + _UC_ATTRIBUTE_PURE; + +/* Divide STR into tokens separated by characters in DELIM. + This interface is actually more similar to wcstok than to strtok. */ +/* Similar to strtok_r(), wcstok(). */ +extern uint8_t * + u8_strtok (uint8_t *_UC_RESTRICT str, const uint8_t *delim, + uint8_t **ptr); +extern uint16_t * + u16_strtok (uint16_t *_UC_RESTRICT str, const uint16_t *delim, + uint16_t **ptr); +extern uint32_t * + u32_strtok (uint32_t *_UC_RESTRICT str, const uint32_t *delim, + uint32_t **ptr); + + +#ifdef __cplusplus +} +#endif + +#endif /* _UNISTR_H */ diff --git a/contrib/tools/bison/lib/unistr/u8-mbtoucr.c b/contrib/tools/bison/lib/unistr/u8-mbtoucr.c new file mode 100644 index 0000000000..afc43b6a49 --- /dev/null +++ b/contrib/tools/bison/lib/unistr/u8-mbtoucr.c @@ -0,0 +1,142 @@ +/* Look at first character in UTF-8 string, returning an error code. + Copyright (C) 1999-2002, 2006-2007, 2009-2020 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2001. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include "unistr.h" + +int +u8_mbtoucr (ucs4_t *puc, const uint8_t *s, size_t n) +{ + uint8_t c = *s; + + if (c < 0x80) + { + *puc = c; + return 1; + } + else if (c >= 0xc2) + { + if (c < 0xe0) + { + if (n >= 2) + { + if ((s[1] ^ 0x80) < 0x40) + { + *puc = ((unsigned int) (c & 0x1f) << 6) + | (unsigned int) (s[1] ^ 0x80); + return 2; + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return -2; + } + } + else if (c < 0xf0) + { + if (n >= 2) + { + if ((s[1] ^ 0x80) < 0x40 + && (c >= 0xe1 || s[1] >= 0xa0) + && (c != 0xed || s[1] < 0xa0)) + { + if (n >= 3) + { + if ((s[2] ^ 0x80) < 0x40) + { + *puc = ((unsigned int) (c & 0x0f) << 12) + | ((unsigned int) (s[1] ^ 0x80) << 6) + | (unsigned int) (s[2] ^ 0x80); + return 3; + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return -2; + } + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return -2; + } + } + else if (c < 0xf8) + { + if (n >= 2) + { + if ((s[1] ^ 0x80) < 0x40 + && (c >= 0xf1 || s[1] >= 0x90) + && (c < 0xf4 || (c == 0xf4 && s[1] < 0x90))) + { + if (n >= 3) + { + if ((s[2] ^ 0x80) < 0x40) + { + if (n >= 4) + { + if ((s[3] ^ 0x80) < 0x40) + { + *puc = ((unsigned int) (c & 0x07) << 18) + | ((unsigned int) (s[1] ^ 0x80) << 12) + | ((unsigned int) (s[2] ^ 0x80) << 6) + | (unsigned int) (s[3] ^ 0x80); + return 4; + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return -2; + } + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return -2; + } + } + /* invalid multibyte character */ + } + else + { + /* incomplete multibyte character */ + *puc = 0xfffd; + return -2; + } + } + } + /* invalid multibyte character */ + *puc = 0xfffd; + return -1; +} diff --git a/contrib/tools/bison/lib/unistr/u8-uctomb-aux.c b/contrib/tools/bison/lib/unistr/u8-uctomb-aux.c new file mode 100644 index 0000000000..15e9c90f45 --- /dev/null +++ b/contrib/tools/bison/lib/unistr/u8-uctomb-aux.c @@ -0,0 +1,60 @@ +/* Conversion UCS-4 to UTF-8. + Copyright (C) 2002, 2006-2007, 2009-2020 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2002. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification. */ +#include "unistr.h" + +#include "attribute.h" + +int +u8_uctomb_aux (uint8_t *s, ucs4_t uc, ptrdiff_t n) +{ + int count; + + if (uc < 0x80) + /* The case n >= 1 is already handled by the caller. */ + return -2; + else if (uc < 0x800) + count = 2; + else if (uc < 0x10000) + { + if (uc < 0xd800 || uc >= 0xe000) + count = 3; + else + return -1; + } + else if (uc < 0x110000) + count = 4; + else + return -1; + + if (n < count) + return -2; + + switch (count) /* note: code falls through cases! */ + { + case 4: s[3] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0x10000; + FALLTHROUGH; + case 3: s[2] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0x800; + FALLTHROUGH; + case 2: s[1] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0xc0; + /*case 1:*/ s[0] = uc; + } + return count; +} diff --git a/contrib/tools/bison/lib/unistr/u8-uctomb.c b/contrib/tools/bison/lib/unistr/u8-uctomb.c new file mode 100644 index 0000000000..79efdc14d2 --- /dev/null +++ b/contrib/tools/bison/lib/unistr/u8-uctomb.c @@ -0,0 +1,79 @@ +/* Store a character in UTF-8 string. + Copyright (C) 2002, 2005-2006, 2009-2020 Free Software Foundation, Inc. + Written by Bruno Haible <bruno@clisp.org>, 2002. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +#if defined IN_LIBUNISTRING +/* Tell unistr.h to declare u8_uctomb as 'extern', not 'static inline'. */ +# error #include "unistring-notinline.h" +#endif + +/* Specification. */ +#include "unistr.h" + +#include "attribute.h" + +#if !HAVE_INLINE + +int +u8_uctomb (uint8_t *s, ucs4_t uc, ptrdiff_t n) +{ + if (uc < 0x80) + { + if (n > 0) + { + s[0] = uc; + return 1; + } + /* else return -2, below. */ + } + else + { + int count; + + if (uc < 0x800) + count = 2; + else if (uc < 0x10000) + { + if (uc < 0xd800 || uc >= 0xe000) + count = 3; + else + return -1; + } + else if (uc < 0x110000) + count = 4; + else + return -1; + + if (n >= count) + { + switch (count) /* note: code falls through cases! */ + { + case 4: s[3] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0x10000; + FALLTHROUGH; + case 3: s[2] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0x800; + FALLTHROUGH; + case 2: s[1] = 0x80 | (uc & 0x3f); uc = uc >> 6; uc |= 0xc0; + /*case 1:*/ s[0] = uc; + } + return count; + } + } + return -2; +} + +#endif diff --git a/contrib/tools/bison/lib/unitypes.h b/contrib/tools/bison/lib/unitypes.h index b277a0858a..ad8a6dd94d 100644 --- a/contrib/tools/bison/lib/unitypes.h +++ b/contrib/tools/bison/lib/unitypes.h @@ -27,7 +27,7 @@ typedef uint32_t ucs4_t; /* Attribute of a function whose result depends only on the arguments (not pointers!) and which has no side effects. */ #ifndef _UC_ATTRIBUTE_CONST -# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95) +# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95) || defined __clang__ # define _UC_ATTRIBUTE_CONST __attribute__ ((__const__)) # else # define _UC_ATTRIBUTE_CONST @@ -37,7 +37,7 @@ typedef uint32_t ucs4_t; /* Attribute of a function whose result depends only on the arguments (possibly pointers) and global memory, and which has no side effects. */ #ifndef _UC_ATTRIBUTE_PURE -# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) +# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) || defined __clang__ # define _UC_ATTRIBUTE_PURE __attribute__ ((__pure__)) # else # define _UC_ATTRIBUTE_PURE @@ -48,7 +48,9 @@ typedef uint32_t ucs4_t; pass a pointer to a different object in the specified pointer argument than in the other pointer arguments. */ #ifndef _UC_RESTRICT -# if defined __restrict || 2 < __GNUC__ + (95 <= __GNUC_MINOR__) +# if defined __restrict \ + || 2 < __GNUC__ + (95 <= __GNUC_MINOR__) \ + || __clang_major__ >= 3 # define _UC_RESTRICT __restrict # elif 199901L <= __STDC_VERSION__ || defined restrict # define _UC_RESTRICT restrict diff --git a/contrib/tools/bison/lib/unused-parameter.h b/contrib/tools/bison/lib/unused-parameter.h new file mode 100644 index 0000000000..662ff1b233 --- /dev/null +++ b/contrib/tools/bison/lib/unused-parameter.h @@ -0,0 +1,32 @@ +/* A C macro for declaring that specific function parameters are not used. + Copyright (C) 2008-2020 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* _GL_UNUSED_PARAMETER is a marker that can be appended to function parameter + declarations for parameters that are not used. This helps to reduce + warnings, such as from GCC -Wunused-parameter. The syntax is as follows: + type param _GL_UNUSED_PARAMETER + or more generally + param_decl _GL_UNUSED_PARAMETER + For example: + int param _GL_UNUSED_PARAMETER + int *(*param)(void) _GL_UNUSED_PARAMETER + Other possible, but obscure and discouraged syntaxes: + int _GL_UNUSED_PARAMETER *(*param)(void) + _GL_UNUSED_PARAMETER int *(*param)(void) + */ +#ifndef _GL_UNUSED_PARAMETER +# define _GL_UNUSED_PARAMETER _GL_ATTRIBUTE_MAYBE_UNUSED +#endif diff --git a/contrib/tools/bison/lib/vasnprintf.c b/contrib/tools/bison/lib/vasnprintf.c index 62f8fbf4db..dfa344e535 100644 --- a/contrib/tools/bison/lib/vasnprintf.c +++ b/contrib/tools/bison/lib/vasnprintf.c @@ -633,7 +633,8 @@ divide (mpn_t a, mpn_t b, mpn_t *q) mp_limb_t msd = b_ptr[b_len - 1]; /* = b[n-1], > 0 */ /* Determine s = GMP_LIMB_BITS - integer_length (msd). Code copied from gnulib's integer_length.c. */ -# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) \ + || (__clang_major__ >= 4) s = __builtin_clz (msd); # else # if defined DBL_EXPBIT0_WORD && defined DBL_EXPBIT0_BIT @@ -5116,39 +5117,32 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, #endif *fbp = dp->conversion; #if USE_SNPRINTF -# if ! (((__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) \ - && !defined __UCLIBC__) \ - || (defined __APPLE__ && defined __MACH__) \ - || defined __ANDROID__ \ - || (defined _WIN32 && ! defined __CYGWIN__)) - fbp[1] = '%'; - fbp[2] = 'n'; - fbp[3] = '\0'; -# else - /* On glibc2 systems from glibc >= 2.3 - probably also older - ones - we know that snprintf's return value conforms to - ISO C 99: the tests gl_SNPRINTF_RETVAL_C99 and - gl_SNPRINTF_TRUNCATION_C99 pass. - Therefore we can avoid using %n in this situation. - On glibc2 systems from 2004-10-18 or newer, the use of %n - in format strings in writable memory may crash the program - (if compiled with _FORTIFY_SOURCE=2), so we should avoid it - in this situation. */ - /* On Mac OS X 10.3 or newer, we know that snprintf's return - value conforms to ISO C 99: the tests gl_SNPRINTF_RETVAL_C99 - and gl_SNPRINTF_TRUNCATION_C99 pass. - Therefore we can avoid using %n in this situation. - On Mac OS X 10.13 or newer, the use of %n in format strings - in writable memory by default crashes the program, so we - should avoid it in this situation. */ - /* On Android, we know that snprintf's return value conforms to - ISO C 99: the tests gl_SNPRINTF_RETVAL_C99 and - gl_SNPRINTF_TRUNCATION_C99 pass. - Therefore we can avoid using %n in this situation. - Starting on 2018-03-07, the use of %n in format strings - produces a fatal error (see - <https://android.googlesource.com/platform/bionic/+/41398d03b7e8e0dfb951660ae713e682e9fc0336>), - so we should avoid it. */ +# if ((HAVE_SNPRINTF_RETVAL_C99 && HAVE_SNPRINTF_TRUNCATION_C99) \ + || ((__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) \ + && !defined __UCLIBC__) \ + || (defined __APPLE__ && defined __MACH__) \ + || defined __ANDROID__ \ + || (defined _WIN32 && ! defined __CYGWIN__)) + /* On systems where we know that snprintf's return value + conforms to ISO C 99 (HAVE_SNPRINTF_RETVAL_C99) and that + snprintf always produces NUL-terminated strings + (HAVE_SNPRINTF_TRUNCATION_C99), it is possible to avoid + using %n. And it is desirable to do so, because more and + more platforms no longer support %n, for "security reasons". + In particular, the following platforms: + - On glibc2 systems from 2004-10-18 or newer, the use of + %n in format strings in writable memory may crash the + program (if compiled with _FORTIFY_SOURCE=2). + - On Mac OS X 10.13 or newer, the use of %n in format + strings in writable memory by default crashes the + program. + - On Android, starting on 2018-03-07, the use of %n in + format strings produces a fatal error (see + <https://android.googlesource.com/platform/bionic/+/41398d03b7e8e0dfb951660ae713e682e9fc0336>). + On these platforms, HAVE_SNPRINTF_RETVAL_C99 and + HAVE_SNPRINTF_TRUNCATION_C99 are 1. We have listed them + explicitly in the condition above, in case of cross- + compilation (just to be sure). */ /* On native Windows systems (such as mingw), we can avoid using %n because: - Although the gl_SNPRINTF_TRUNCATION_C99 test fails, @@ -5165,6 +5159,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, <https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/set-printf-count-output> So we should avoid %n in this situation. */ fbp[1] = '\0'; +# else /* AIX <= 5.1, HP-UX, IRIX, OSF/1, Solaris <= 9, BeOS */ + fbp[1] = '%'; + fbp[2] = 'n'; + fbp[3] = '\0'; # endif #else fbp[1] = '\0'; diff --git a/contrib/tools/bison/lib/verify.h b/contrib/tools/bison/lib/verify.h index d9ab89a570..fa1ed717d0 100644 --- a/contrib/tools/bison/lib/verify.h +++ b/contrib/tools/bison/lib/verify.h @@ -23,11 +23,15 @@ /* Define _GL_HAVE__STATIC_ASSERT to 1 if _Static_assert (R, DIAGNOSTIC) works as per C11. This is supported by GCC 4.6.0 and later, in C - mode. + mode, and by clang (also in C++ mode). Define _GL_HAVE__STATIC_ASSERT1 to 1 if _Static_assert (R) works as - per C2X, and define _GL_HAVE_STATIC_ASSERT1 if static_assert (R) - works as per C++17. This is supported by GCC 9.1 and later. + per C2X. This is supported by GCC 9.1 and later, and by clang in + C++1z mode. + + Define _GL_HAVE_STATIC_ASSERT1 if static_assert (R) works as per + C++17. This is supported by GCC 9.1 and later, and by clang in + C++1z mode. Support compilers claiming conformance to the relevant standard, and also support GCC when not pedantic. If we were willing to slow @@ -35,7 +39,8 @@ since this affects only the quality of diagnostics, why bother? */ #ifndef __cplusplus # if (201112L <= __STDC_VERSION__ \ - || (!defined __STRICT_ANSI__ && 4 < __GNUC__ + (6 <= __GNUC_MINOR__))) + || (!defined __STRICT_ANSI__ \ + && (4 < __GNUC__ + (6 <= __GNUC_MINOR__) || 4 <= __clang_major__))) # define _GL_HAVE__STATIC_ASSERT 1 # endif # if (202000L <= __STDC_VERSION__ \ @@ -43,7 +48,15 @@ # define _GL_HAVE__STATIC_ASSERT1 1 # endif #else -# if 201703L <= __cplusplus || 9 <= __GNUC__ +# if 4 <= __clang_major__ +# define _GL_HAVE__STATIC_ASSERT 1 +# endif +# if 4 <= __clang_major__ && 201411 <= __cpp_static_assert +# define _GL_HAVE__STATIC_ASSERT1 1 +# endif +# if 201703L <= __cplusplus \ + || 9 <= __GNUC__ \ + || (4 <= __clang_major__ && 201411 <= __cpp_static_assert) # define _GL_HAVE_STATIC_ASSERT1 1 # endif #endif @@ -277,10 +290,27 @@ template <int w> #endif /* Assume that R always holds. Behavior is undefined if R is false, - fails to evaluate, or has side effects. Although assuming R can - help a compiler generate better code or diagnostics, performance - can suffer if R uses hard-to-optimize features such as function - calls not inlined by the compiler. */ + fails to evaluate, or has side effects. + + 'assume (R)' is a directive from the programmer telling the + compiler that R is true so the compiler needn't generate code to + test R. This is why 'assume' is in verify.h: it's related to + static checking (in this case, static checking done by the + programmer), not dynamic checking. + + 'assume (R)' can affect compilation of all the code, not just code + that happens to be executed after the assume (R) is "executed". + For example, if the code mistakenly does 'assert (R); assume (R);' + the compiler is entitled to optimize away the 'assert (R)'. + + Although assuming R can help a compiler generate better code or + diagnostics, performance can suffer if R uses hard-to-optimize + features such as function calls not inlined by the compiler. + + Avoid Clang's __builtin_assume, as it breaks GNU Emacs master + as of 2020-08-23T21:09:49Z!eggert@cs.ucla.edu; see + <https://bugs.gnu.org/43152#71>. It's not known whether this breakage + is a Clang bug or an Emacs bug; play it safe for now. */ #if _GL_HAS_BUILTIN_UNREACHABLE # define assume(R) ((R) ? (void) 0 : __builtin_unreachable ()) diff --git a/contrib/tools/bison/lib/wait-process.c b/contrib/tools/bison/lib/wait-process.c index 58a1e1121d..dd9ea1e1c3 100644 --- a/contrib/tools/bison/lib/wait-process.c +++ b/contrib/tools/bison/lib/wait-process.c @@ -44,7 +44,7 @@ # define WIN32_LEAN_AND_MEAN # include <windows.h> -/* The return value of spawnvp() is really a process handle as returned +/* The return value of _spawnvp() is really a process handle as returned by CreateProcess(). Therefore we can kill it using TerminateProcess. */ # define kill(pid,sig) TerminateProcess ((HANDLE) (pid), sig) diff --git a/contrib/tools/bison/lib/windows-rwlock.c b/contrib/tools/bison/lib/windows-rwlock.c index aafc5ddda3..64e761cd4f 100644 --- a/contrib/tools/bison/lib/windows-rwlock.c +++ b/contrib/tools/bison/lib/windows-rwlock.c @@ -25,6 +25,10 @@ #include <errno.h> #include <stdlib.h> +/* Don't assume that UNICODE is not defined. */ +#undef CreateEvent +#define CreateEvent CreateEventA + /* In this file, the waitqueues are implemented as circular arrays. */ #define glwthread_waitqueue_t glwthread_carray_waitqueue_t diff --git a/contrib/tools/bison/lib/xalloc-oversized.h b/contrib/tools/bison/lib/xalloc-oversized.h index 13ee23031a..7cd4a74f04 100644 --- a/contrib/tools/bison/lib/xalloc-oversized.h +++ b/contrib/tools/bison/lib/xalloc-oversized.h @@ -41,7 +41,7 @@ typedef size_t __xalloc_count_type; positive and N must be nonnegative. This is a macro, not a function, so that it works correctly even when SIZE_MAX < N. */ -#if 7 <= __GNUC__ +#if 7 <= __GNUC__ && !defined __clang__ # define xalloc_oversized(n, s) \ __builtin_mul_overflow_p (n, s, (__xalloc_count_type) 1) #elif 5 <= __GNUC__ && !defined __ICC && !__STRICT_ANSI__ diff --git a/contrib/tools/bison/lib/xalloc.h b/contrib/tools/bison/lib/xalloc.h index 24273ffbe3..d4f96bfe0f 100644 --- a/contrib/tools/bison/lib/xalloc.h +++ b/contrib/tools/bison/lib/xalloc.h @@ -31,11 +31,14 @@ _GL_INLINE_HEADER_BEGIN # define XALLOC_INLINE _GL_INLINE #endif + #ifdef __cplusplus extern "C" { #endif +#if GNULIB_XALLOC_DIE + /* This function is always triggered when memory is exhausted. It must be defined by the application, either explicitly or by using gnulib's xalloc-die module. This is the @@ -43,6 +46,10 @@ extern "C" { memory allocation failure. */ /*extern*/ _Noreturn void xalloc_die (void); +#endif /* GNULIB_XALLOC_DIE */ + +#if GNULIB_XALLOC + void *xmalloc (size_t s) _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1)); void *xzalloc (size_t s) @@ -64,23 +71,23 @@ char *xstrdup (char const *str) /* Allocate an object of type T dynamically, with error checking. */ /* extern t *XMALLOC (typename t); */ -#define XMALLOC(t) ((t *) xmalloc (sizeof (t))) +# define XMALLOC(t) ((t *) xmalloc (sizeof (t))) /* Allocate memory for N elements of type T, with error checking. */ /* extern t *XNMALLOC (size_t n, typename t); */ -#define XNMALLOC(n, t) \ - ((t *) (sizeof (t) == 1 ? xmalloc (n) : xnmalloc (n, sizeof (t)))) +# define XNMALLOC(n, t) \ + ((t *) (sizeof (t) == 1 ? xmalloc (n) : xnmalloc (n, sizeof (t)))) /* Allocate an object of type T dynamically, with error checking, and zero it. */ /* extern t *XZALLOC (typename t); */ -#define XZALLOC(t) ((t *) xzalloc (sizeof (t))) +# define XZALLOC(t) ((t *) xzalloc (sizeof (t))) /* Allocate memory for N elements of type T, with error checking, and zero it. */ /* extern t *XCALLOC (size_t n, typename t); */ -#define XCALLOC(n, t) \ - ((t *) (sizeof (t) == 1 ? xzalloc (n) : xcalloc (n, sizeof (t)))) +# define XCALLOC(n, t) \ + ((t *) (sizeof (t) == 1 ? xzalloc (n) : xcalloc (n, sizeof (t)))) /* Allocate an array of N objects, each with S bytes of memory, @@ -211,8 +218,15 @@ xcharalloc (size_t n) return XNMALLOC (n, char); } +#endif /* GNULIB_XALLOC */ + + #ifdef __cplusplus } +#endif + + +#if GNULIB_XALLOC && defined __cplusplus /* C++ does not allow conversions from void * to other pointer types without a cast. Use templates to work around the problem when @@ -248,7 +262,8 @@ xmemdup (T const *p, size_t s) return (T *) xmemdup ((void const *) p, s); } -#endif +#endif /* GNULIB_XALLOC && C++ */ + _GL_INLINE_HEADER_END diff --git a/contrib/tools/bison/lib/xhash.c b/contrib/tools/bison/lib/xhash.c index 1e998d2d15..d358f4e52d 100644 --- a/contrib/tools/bison/lib/xhash.c +++ b/contrib/tools/bison/lib/xhash.c @@ -22,9 +22,6 @@ #include "xalloc.h" -/* Same as hash_initialize, but invokes xalloc_die on memory - exhaustion. */ - Hash_table * hash_xinitialize (size_t candidate, const Hash_tuning *tuning, Hash_hasher hasher, Hash_comparator comparator, @@ -36,3 +33,12 @@ hash_xinitialize (size_t candidate, const Hash_tuning *tuning, xalloc_die (); return res; } + +void * +hash_xinsert (Hash_table *table, void const *entry) +{ + void *res = hash_insert (table, entry); + if (!res) + xalloc_die (); + return res; +} diff --git a/contrib/tools/bison/lib/ya.make b/contrib/tools/bison/lib/ya.make index 85c4aade38..8ef263c2f8 100644 --- a/contrib/tools/bison/lib/ya.make +++ b/contrib/tools/bison/lib/ya.make @@ -6,6 +6,10 @@ LICENSE(GPL-3.0-or-later) LICENSE_TEXTS(.yandex_meta/licenses.list.txt) +PEERDIR( + contrib/libs/libiconv +) + ADDINCL( contrib/tools/bison contrib/tools/bison/lib @@ -60,7 +64,11 @@ SRCS( gethrxtime.c getprogname.c gl_array_list.c + gl_linked_list.c gl_list.c + gl_oset.c + gl_rbtree_oset.c + gl_rbtreehash_list.c gl_xlist.c glthread/lock.c glthread/threadlib.c @@ -90,7 +98,11 @@ SRCS( stripslash.c timespec.c timevar.c + unicodeio.c unistd.c + unistr/u8-mbtoucr.c + unistr/u8-uctomb-aux.c + unistr/u8-uctomb.c uniwidth/width.c vasnprintf.c vasprintf.c @@ -138,6 +150,7 @@ ELSEIF (OS_WINDOWS) sigaction.c sigprocmask.c stpcpy.c + stpncpy.c strndup.c strverscmp.c waitpid.c diff --git a/contrib/tools/bison/src/AnnotationList.c b/contrib/tools/bison/src/AnnotationList.c index f7ef092971..26184f95e6 100644 --- a/contrib/tools/bison/src/AnnotationList.c +++ b/contrib/tools/bison/src/AnnotationList.c @@ -1,6 +1,6 @@ /* IELR's inadequacy annotation list. - Copyright (C) 2009-2015, 2018-2020 Free Software Foundation, Inc. + Copyright (C) 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -15,14 +15,16 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> -#include "system.h" #include "AnnotationList.h" -#include "lalr.h" + +#include "system.h" + #include "ielr.h" +#include "lalr.h" /** * \pre @@ -38,15 +40,14 @@ static AnnotationList* AnnotationList__alloc_on_obstack (ContributionIndex contribution_count, struct obstack *annotations_obstackp) { - AnnotationList *result; - size_t contributions_size = - contribution_count * sizeof result->contributions[0]; - result = obstack_alloc (annotations_obstackp, - offsetof (AnnotationList, contributions) - + contributions_size); - result->next = NULL; - result->inadequacyNode = NULL; - return result; + AnnotationList *res; + size_t contributions_size = contribution_count * sizeof res->contributions[0]; + res = obstack_alloc (annotations_obstackp, + offsetof (AnnotationList, contributions) + + contributions_size); + res->next = NULL; + res->inadequacyNode = NULL; + return res; } /** @@ -102,13 +103,12 @@ AnnotationList__insertInto (AnnotationList *self, AnnotationList **list, for (node = list; *node; node = &(*node)->next) { int cmp = 0; - ContributionIndex ci; if (self->inadequacyNode->id < (*node)->inadequacyNode->id) cmp = 1; else if ((*node)->inadequacyNode->id < self->inadequacyNode->id) cmp = -1; else - for (ci = 0; + for (ContributionIndex ci = 0; cmp == 0 && ci < self->inadequacyNode->contributionCount; ++ci) { @@ -120,19 +120,16 @@ AnnotationList__insertInto (AnnotationList *self, AnnotationList **list, else if (AnnotationList__isContributionAlways (*node, ci)) cmp = 1; else - { - size_t item; - for (item = 0; cmp == 0 && item < nitems; ++item) - { - if (!Sbitset__test (self->contributions[ci], item)) - { - if (Sbitset__test ((*node)->contributions[ci], item)) - cmp = -1; - } - else if (!Sbitset__test ((*node)->contributions[ci], item)) - cmp = 1; - } - } + for (size_t item = 0; cmp == 0 && item < nitems; ++item) + { + if (!Sbitset__test (self->contributions[ci], item)) + { + if (Sbitset__test ((*node)->contributions[ci], item)) + cmp = -1; + } + else if (!Sbitset__test ((*node)->contributions[ci], item)) + cmp = 1; + } } if (cmp < 0) { @@ -172,10 +169,10 @@ AnnotationList__compute_conflicted_tokens (bitset shift_tokens, bitset_copy (tokens, shift_tokens); for (int i = 0; i < reds->num; ++i) { - bitset_and (conflicted_tokens_rule, tokens, reds->lookahead_tokens[i]); + bitset_and (conflicted_tokens_rule, tokens, reds->lookaheads[i]); bitset_or (conflicted_tokens, conflicted_tokens, conflicted_tokens_rule); - bitset_or (tokens, tokens, reds->lookahead_tokens[i]); + bitset_or (tokens, tokens, reds->lookaheads[i]); /* Check that rules are sorted on rule number or the next step in AnnotationList__compute_from_inadequacies will misbehave. */ aver (i == 0 || reds->rules[i-1] < reds->rules[i]); @@ -188,7 +185,7 @@ AnnotationList__compute_conflicted_tokens (bitset shift_tokens, } static bool -AnnotationList__compute_lhs_contributions (state *s, rule *the_rule, +AnnotationList__compute_lhs_contributions (state *s, const rule *the_rule, symbol_number conflicted_token, bitsetv follow_kernel_items, bitsetv always_follows, @@ -232,115 +229,110 @@ AnnotationList__computePredecessorAnnotations ( annotation_node->inadequacyNode = self->inadequacyNode; bool potential_contribution = false; bitset *lookaheads = NULL; - { - for (ContributionIndex ci = 0; ci < self->inadequacyNode->contributionCount; ++ci) - { - symbol_number contribution_token = - InadequacyList__getContributionToken (self->inadequacyNode, ci) - ->content->number; - if (AnnotationList__isContributionAlways (self, ci)) - { - annotation_node->contributions[ci] = NULL; - continue; - } - annotation_node->contributions[ci] = - Sbitset__new_on_obstack ((*predecessor)->nitems, - annotations_obstackp); + + for (ContributionIndex ci = 0; ci < self->inadequacyNode->contributionCount; ++ci) + { + symbol_number contribution_token = + InadequacyList__getContributionToken (self->inadequacyNode, ci) + ->content->number; + if (AnnotationList__isContributionAlways (self, ci)) { - size_t predecessor_item = 0; - Sbitset sbiter_item; - Sbitset__Index self_item; - SBITSET__FOR_EACH (self->contributions[ci], s->nitems, - sbiter_item, self_item) - { - /* If this kernel item is the beginning of a RHS, it must be - the kernel item in the start state, and so it has an empty - lookahead set. Thus, it can't contribute to inadequacies, - and so it should never have been identified as a - contribution. If, instead, this kernel item is the - successor of the start state's kernel item, the lookahead - set is still empty, and so it also should never have been - identified as a contribution. This situation is fortunate - because we want to avoid the - 2 below in both cases. */ - aver (s->items[self_item] > 1); - /* If this kernel item is next to the beginning of the RHS, - then check all of the predecessor's goto follows for the - LHS. */ - if (item_number_is_rule_number (ritem[s->items[self_item] - - 2])) - { - int rulei; - for (rulei = s->items[self_item]; - !item_number_is_rule_number (ritem[rulei]); - ++rulei) - continue; - Sbitset items; - if (AnnotationList__compute_lhs_contributions ( - *predecessor, - &rules[item_number_as_rule_number (ritem[rulei])], - contribution_token, - follow_kernel_items, always_follows, predecessors, - item_lookahead_sets, &items, annotations_obstackp)) - { - obstack_free (annotations_obstackp, - annotation_node->contributions[ci]); - annotation_node->contributions[ci] = NULL; - break; - } - else - { - Sbitset__or (annotation_node->contributions[ci], - annotation_node->contributions[ci], - items, (*predecessor)->nitems); - obstack_free (annotations_obstackp, items); - } - } - /* If this kernel item is later in the RHS, then check the - predecessor item's lookahead set. */ - else - { - /* We don't have to start the predecessor item search at - the beginning every time because items from both - states are sorted by their indices in ritem. */ - for (; - predecessor_item < (*predecessor)->nitems; - ++predecessor_item) - if ((*predecessor)->items[predecessor_item] - == s->items[self_item] - 1) - break; - aver (predecessor_item != (*predecessor)->nitems); - if (ielr_item_has_lookahead (*predecessor, 0, - predecessor_item, - contribution_token, - predecessors, - item_lookahead_sets)) - Sbitset__set (annotation_node->contributions[ci], - predecessor_item); - } - } + annotation_node->contributions[ci] = NULL; + continue; } - if (annotation_node->contributions[ci]) + annotation_node->contributions[ci] = + Sbitset__new_on_obstack ((*predecessor)->nitems, + annotations_obstackp); + { + size_t predecessor_item = 0; + Sbitset sbiter_item; + Sbitset__Index self_item; + SBITSET__FOR_EACH (self->contributions[ci], s->nitems, + sbiter_item, self_item) { - Sbitset biter; - Sbitset__Index i; - SBITSET__FOR_EACH (annotation_node->contributions[ci], - (*predecessor)->nitems, biter, i) + /* If this kernel item is the beginning of a RHS, it must be + the kernel item in the start state, and so it has an empty + lookahead set. Thus, it can't contribute to inadequacies, + and so it should never have been identified as a + contribution. If, instead, this kernel item is the + successor of the start state's kernel item, the lookahead + set is still empty, and so it also should never have been + identified as a contribution. This situation is fortunate + because we want to avoid the - 2 below in both cases. */ + aver (s->items[self_item] > 1); + /* If this kernel item is next to the beginning of the RHS, + then check all of the predecessor's goto follows for the + LHS. */ + if (item_number_is_rule_number (ritem[s->items[self_item] - 2])) { - potential_contribution = true; - if (!lookaheads) + Sbitset items; + if (AnnotationList__compute_lhs_contributions ( + *predecessor, + item_rule (&ritem[s->items[self_item]]), + contribution_token, + follow_kernel_items, always_follows, predecessors, + item_lookahead_sets, &items, annotations_obstackp)) { - lookaheads = xnmalloc ((*predecessor)->nitems, - sizeof *lookaheads); - for (size_t j = 0; j < (*predecessor)->nitems; ++j) - lookaheads[j] = NULL; + obstack_free (annotations_obstackp, + annotation_node->contributions[ci]); + annotation_node->contributions[ci] = NULL; + // "Break" out of SBITSET__FOR_EACH. + goto after_sbitset__for_each; } - if (!lookaheads[i]) - lookaheads[i] = bitset_create (ntokens, BITSET_FIXED); - bitset_set (lookaheads[i], contribution_token); + else + { + Sbitset__or (annotation_node->contributions[ci], + annotation_node->contributions[ci], + items, (*predecessor)->nitems); + obstack_free (annotations_obstackp, items); + } + } + /* If this kernel item is later in the RHS, then check the + predecessor item's lookahead set. */ + else + { + /* We don't have to start the predecessor item search at + the beginning every time because items from both + states are sorted by their indices in ritem. */ + for (; + predecessor_item < (*predecessor)->nitems; + ++predecessor_item) + if ((*predecessor)->items[predecessor_item] + == s->items[self_item] - 1) + break; + aver (predecessor_item != (*predecessor)->nitems); + if (ielr_item_has_lookahead (*predecessor, 0, + predecessor_item, + contribution_token, + predecessors, + item_lookahead_sets)) + Sbitset__set (annotation_node->contributions[ci], + predecessor_item); } } + after_sbitset__for_each:; } - } + if (annotation_node->contributions[ci]) + { + Sbitset biter; + Sbitset__Index i; + SBITSET__FOR_EACH (annotation_node->contributions[ci], + (*predecessor)->nitems, biter, i) + { + potential_contribution = true; + if (!lookaheads) + { + lookaheads = xnmalloc ((*predecessor)->nitems, + sizeof *lookaheads); + for (size_t j = 0; j < (*predecessor)->nitems; ++j) + lookaheads[j] = NULL; + } + if (!lookaheads[i]) + lookaheads[i] = bitset_create (ntokens, BITSET_FIXED); + bitset_set (lookaheads[i], contribution_token); + } + } + } /* If the predecessor has any contributions besides just "always" and "never" contributions: @@ -409,7 +401,7 @@ AnnotationList__compute_from_inadequacies ( struct obstack *annotations_obstackp, InadequacyListNodeCount *inadequacy_list_node_count) { - /* Return an empty list if s->lookahead_tokens = NULL. */ + /* Return an empty list if s->lookaheads = NULL. */ if (s->consistent) return; @@ -425,16 +417,12 @@ AnnotationList__compute_from_inadequacies ( BITSET_FOR_EACH (biter_conflict, conflicted_tokens, conflicted_token, 0) { AnnotationList *annotation_node; - /* FIXME: Would a BITSET_FRUGAL or BITEST_SPARSE be more efficient? Now - or convert it inside InadequacyList__new_conflict? */ - bitset actions = bitset_create (s->reductions->num + 1, BITSET_FIXED); ContributionIndex contribution_count = 0; - bool potential_contribution = false; /* Allocate the annotation node. */ { for (int rule_i = 0; rule_i < s->reductions->num; ++rule_i) - if (bitset_test (s->reductions->lookahead_tokens[rule_i], + if (bitset_test (s->reductions->lookaheads[rule_i], conflicted_token)) ++contribution_count; if (bitset_test (shift_tokens, conflicted_token)) @@ -444,6 +432,11 @@ AnnotationList__compute_from_inadequacies ( annotations_obstackp); } + /* FIXME: Would a BITSET_FRUGAL or BITEST_SPARSE be more efficient? Now + or convert it inside InadequacyList__new_conflict? */ + bitset actions = bitset_create (s->reductions->num + 1, BITSET_FIXED); + bool potential_contribution = false; + /* Add a contribution for each reduction that has conflicted_token as a lookahead. */ { @@ -452,7 +445,7 @@ AnnotationList__compute_from_inadequacies ( for (int rule_i = 0; rule_i < s->reductions->num; ++rule_i) { rule *the_rule = s->reductions->rules[rule_i]; - if (bitset_test (s->reductions->lookahead_tokens[rule_i], + if (bitset_test (s->reductions->lookaheads[rule_i], conflicted_token)) { bitset_set (actions, rule_i); @@ -464,11 +457,8 @@ AnnotationList__compute_from_inadequacies ( annotations_obstackp); /* Catch item_i up to rule_i. This works because both are sorted on rule number. */ - while (!item_number_is_rule_number ( - ritem[s->items[item_i]]) - || item_number_as_rule_number ( - ritem[s->items[item_i]]) - != the_rule->number) + while (!item_number_is_rule_number (ritem[s->items[item_i]]) + || item_number_as_rule_number (ritem[s->items[item_i]]) != the_rule->number) { ++item_i; aver (item_i < s->nitems); @@ -571,44 +561,40 @@ AnnotationList__debug (AnnotationList const *self, size_t nitems, int spaces) AnnotationIndex ai; for (a = self, ai = 0; a; a = a->next, ++ai) { - for (int j = 0; j < spaces; ++j) - putc (' ', stderr); - fprintf (stderr, "Annotation %d (manifesting state %d):\n", + fprintf (stderr, "%*sAnnotation %d (manifesting state %d):\n", + spaces, "", ai, a->inadequacyNode->manifestingState->number); - { - bitset_bindex rulei - = bitset_first (a->inadequacyNode->inadequacy.conflict.actions); - for (ContributionIndex ci = 0; ci < a->inadequacyNode->contributionCount; ++ci) - { - symbol_number token = - InadequacyList__getContributionToken (a->inadequacyNode, ci) - ->content->number; - for (int j = 0; j < spaces+2; ++j) - putc (' ', stderr); - if (ci == InadequacyList__getShiftContributionIndex ( - a->inadequacyNode)) - fprintf (stderr, "Contributes shift of token %d.\n", token); - else - { - fprintf (stderr, "Contributes token %d", token); - aver (rulei != BITSET_BINDEX_MAX); - fprintf (stderr, " as lookahead, rule number %d", - a->inadequacyNode->manifestingState - ->reductions->rules[rulei]->number); - rulei = - bitset_next (a->inadequacyNode->inadequacy.conflict.actions, - rulei+1); - if (AnnotationList__isContributionAlways (a, ci)) - fprintf (stderr, " always."); - else - { - fprintf (stderr, ", items: "); - Sbitset__fprint (a->contributions[ci], nitems, stderr); - } - fprintf (stderr, "\n"); - } - } - } + bitset_bindex rulei + = bitset_first (a->inadequacyNode->inadequacy.conflict.actions); + for (ContributionIndex ci = 0; ci < a->inadequacyNode->contributionCount; ++ci) + { + symbol_number token = + InadequacyList__getContributionToken (a->inadequacyNode, ci) + ->content->number; + fprintf (stderr, "%*s", spaces+2, ""); + if (ci == InadequacyList__getShiftContributionIndex ( + a->inadequacyNode)) + fprintf (stderr, "Contributes shift of token %d.\n", token); + else + { + fprintf (stderr, "Contributes token %d", token); + aver (rulei != BITSET_BINDEX_MAX); + fprintf (stderr, " as lookahead, rule number %d", + a->inadequacyNode->manifestingState + ->reductions->rules[rulei]->number); + rulei = + bitset_next (a->inadequacyNode->inadequacy.conflict.actions, + rulei+1); + if (AnnotationList__isContributionAlways (a, ci)) + fprintf (stderr, " always."); + else + { + fprintf (stderr, ", items: "); + Sbitset__fprint (a->contributions[ci], nitems, stderr); + } + fprintf (stderr, "\n"); + } + } } } @@ -775,8 +761,7 @@ AnnotationList__computeDominantContribution (AnnotationList const *self, /* R/R conflict, so the reduction with the lowest rule number dominates. Fortunately, contributions are sorted by rule number. */ for (ContributionIndex ci = 0; ci < self->inadequacyNode->contributionCount; ++ci) - if (AnnotationList__stateMakesContribution (self, nitems, ci, - lookaheads)) + if (AnnotationList__stateMakesContribution (self, nitems, ci, lookaheads)) { if (require_split_stable && !AnnotationList__isContributionAlways (self, ci)) diff --git a/contrib/tools/bison/src/AnnotationList.h b/contrib/tools/bison/src/AnnotationList.h index d5258a57d3..3c43ca9073 100644 --- a/contrib/tools/bison/src/AnnotationList.h +++ b/contrib/tools/bison/src/AnnotationList.h @@ -1,6 +1,6 @@ /* IELR's inadequacy annotation list. - Copyright (C) 2009-2015, 2018-2020 Free Software Foundation, Inc. + Copyright (C) 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -15,12 +15,13 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef ANNOTATION_LIST_H_ # define ANNOTATION_LIST_H_ # include <bitsetv.h> + # include "Sbitset.h" # include "InadequacyList.h" # include "state.h" diff --git a/contrib/tools/bison/src/InadequacyList.c b/contrib/tools/bison/src/InadequacyList.c index 6d7f19224e..c958f8226d 100644 --- a/contrib/tools/bison/src/InadequacyList.c +++ b/contrib/tools/bison/src/InadequacyList.c @@ -1,6 +1,6 @@ /* IELR's inadequacy list. - Copyright (C) 2009-2015, 2018-2020 Free Software Foundation, Inc. + Copyright (C) 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -15,7 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> #include "system.h" diff --git a/contrib/tools/bison/src/InadequacyList.h b/contrib/tools/bison/src/InadequacyList.h index 317d9d5a52..98142d053a 100644 --- a/contrib/tools/bison/src/InadequacyList.h +++ b/contrib/tools/bison/src/InadequacyList.h @@ -1,6 +1,6 @@ /* IELR's inadequacy list. - Copyright (C) 2009-2015, 2018-2020 Free Software Foundation, Inc. + Copyright (C) 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -15,7 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef INADEQUACY_LIST_H_ # define INADEQUACY_LIST_H_ diff --git a/contrib/tools/bison/src/Sbitset.c b/contrib/tools/bison/src/Sbitset.c index 3b16510322..aa31885850 100644 --- a/contrib/tools/bison/src/Sbitset.c +++ b/contrib/tools/bison/src/Sbitset.c @@ -1,6 +1,6 @@ /* A simple, memory-efficient bitset implementation. - Copyright (C) 2009-2015, 2018-2020 Free Software Foundation, Inc. + Copyright (C) 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -15,7 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> #include "system.h" diff --git a/contrib/tools/bison/src/Sbitset.h b/contrib/tools/bison/src/Sbitset.h index 997dab2fea..f6bd956e64 100644 --- a/contrib/tools/bison/src/Sbitset.h +++ b/contrib/tools/bison/src/Sbitset.h @@ -1,6 +1,6 @@ /* A simple, memory-efficient bitset implementation. - Copyright (C) 2009-2015, 2018-2020 Free Software Foundation, Inc. + Copyright (C) 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -15,7 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef SBITSET_H_ # define SBITSET_H_ @@ -81,6 +81,8 @@ void Sbitset__fprint (Sbitset self, Sbitset__Index nbits, FILE *file); *ptr_self = *ptr_other1 | *ptr_other2; \ } while (0) +/* ATTENTION: there are *two* loops here, "break" and "continue" will + not apply to the whole loop, just the inner one. */ # define SBITSET__FOR_EACH(SELF, NBITS, ITER, INDEX) \ for ((ITER) = (SELF); (ITER) < (SELF) + Sbitset__nbytes (NBITS); ++(ITER)) \ if (*(ITER) != 0) \ diff --git a/contrib/tools/bison/src/assoc.c b/contrib/tools/bison/src/assoc.c index 0c3de26fd5..8b883e2348 100644 --- a/contrib/tools/bison/src/assoc.c +++ b/contrib/tools/bison/src/assoc.c @@ -1,6 +1,6 @@ /* Associativity information. - Copyright (C) 2002, 2005-2006, 2008-2015, 2018-2020 Free Software + Copyright (C) 2002, 2005-2006, 2008-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> #include "system.h" diff --git a/contrib/tools/bison/src/assoc.h b/contrib/tools/bison/src/assoc.h index 9fdbb466f3..1ae9d32cbf 100644 --- a/contrib/tools/bison/src/assoc.h +++ b/contrib/tools/bison/src/assoc.h @@ -1,6 +1,6 @@ /* Associativity information. - Copyright (C) 2002, 2006, 2008-2015, 2018-2020 Free Software + Copyright (C) 2002, 2006, 2008-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef ASSOC_H_ # define ASSOC_H_ diff --git a/contrib/tools/bison/src/closure.c b/contrib/tools/bison/src/closure.c index 5a93ded729..025f9666a6 100644 --- a/contrib/tools/bison/src/closure.c +++ b/contrib/tools/bison/src/closure.c @@ -1,7 +1,7 @@ /* Closures for Bison Copyright (C) 1984, 1989, 2000-2002, 2004-2005, 2007, 2009-2015, - 2018-2020 Free Software Foundation, Inc. + 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> #include "system.h" @@ -32,7 +32,7 @@ #include "symtab.h" /* NITEMSET is the size of the array ITEMSET. */ -item_number *itemset; +item_index *itemset; size_t nitemset; /* RULESET contains a bit for each rule. CLOSURE sets the bits for @@ -54,16 +54,16 @@ static bitsetv firsts = NULL; `-----------------*/ static void -closure_print (char const *title, item_number const *array, size_t size) +closure_print (char const *title, item_index const *array, size_t size) { fprintf (stderr, "Closure: %s\n", title); for (size_t i = 0; i < size; ++i) { fprintf (stderr, " %2d: .", array[i]); item_number *rp; - for (rp = &ritem[array[i]]; *rp >= 0; ++rp) + for (rp = &ritem[array[i]]; 0 <= *rp; ++rp) fprintf (stderr, " %s", symbols[*rp]->tag); - fprintf (stderr, " (rule %d)\n", -*rp - 1); + fprintf (stderr, " (rule %d)\n", item_number_as_rule_number (*rp)); } fputs ("\n\n", stderr); } @@ -104,21 +104,21 @@ print_fderives (void) fprintf (stderr, "\n\n"); } -/*------------------------------------------------------------------. -| Set FIRSTS to be an NVARS array of NVARS bitsets indicating which | -| items can represent the beginning of the input corresponding to | -| which other items. | -| | -| For example, if some rule expands symbol 5 into the sequence of | -| symbols 8 3 20, the symbol 8 can be the beginning of the data for | -| symbol 5, so the bit [8 - ntokens] in first[5 - ntokens] (= FIRST | -| (5)) is set. | -`------------------------------------------------------------------*/ +/*-------------------------------------------------------------------. +| Set FIRSTS to be an NNTERMS array of NNTERMS bitsets indicating | +| which items can represent the beginning of the input corresponding | +| to which other items. | +| | +| For example, if some rule expands symbol 5 into the sequence of | +| symbols 8 3 20, the symbol 8 can be the beginning of the data for | +| symbol 5, so the bit [8 - ntokens] in first[5 - ntokens] (= FIRST | +| (5)) is set. | +`-------------------------------------------------------------------*/ static void set_firsts (void) { - firsts = bitsetv_create (nvars, nvars, BITSET_FIXED); + firsts = bitsetv_create (nnterms, nnterms, BITSET_FIXED); for (symbol_number i = ntokens; i < nsyms; ++i) for (symbol_number j = 0; derives[i - ntokens][j]; ++j) @@ -139,8 +139,8 @@ set_firsts (void) } /*-------------------------------------------------------------------. -| Set FDERIVES to an NVARS by NRULES matrix of bits indicating which | -| rules can help derive the beginning of the data for each | +| Set FDERIVES to an NNTERMS by NRULES matrix of bits indicating | +| which rules can help derive the beginning of the data for each | | nonterminal. | | | | For example, if symbol 5 can be derived as the sequence of symbols | @@ -151,7 +151,7 @@ set_firsts (void) static void set_fderives (void) { - fderives = bitsetv_create (nvars, nrules, BITSET_FIXED); + fderives = bitsetv_create (nnterms, nrules, BITSET_FIXED); set_firsts (); @@ -182,7 +182,7 @@ closure_new (int n) void -closure (item_number const *core, size_t n) +closure (item_index const *core, size_t n) { if (trace_flag & trace_closure) closure_print ("input", core, n); @@ -203,7 +203,7 @@ closure (item_number const *core, size_t n) bitset_iterator iter; BITSET_FOR_EACH (iter, ruleset, ruleno, 0) { - item_number itemno = rules[ruleno].rhs - ritem; + item_index itemno = rules[ruleno].rhs - ritem; while (c < n && core[c] < itemno) { itemset[nitemset] = core[c]; diff --git a/contrib/tools/bison/src/closure.h b/contrib/tools/bison/src/closure.h index 21d6ba196e..a928144672 100644 --- a/contrib/tools/bison/src/closure.h +++ b/contrib/tools/bison/src/closure.h @@ -1,6 +1,6 @@ /* Subroutines for bison - Copyright (C) 1984, 1989, 2000-2002, 2007, 2009-2015, 2018-2020 Free + Copyright (C) 1984, 1989, 2000-2002, 2007, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef CLOSURE_H_ # define CLOSURE_H_ @@ -30,12 +30,12 @@ void closure_new (int n); -/* Given the kernel (aka core) of a state (a sorted vector of item numbers +/* Given the kernel (aka core) of a state (a sorted vector of item indices ITEMS, of length N), set up RULESET and ITEMSET to indicate what rules could be run and which items could be accepted when those items are the active ones. */ -void closure (item_number const *items, size_t n); +void closure (item_index const *items, size_t n); /* Free ITEMSET, RULESET and internal data. */ @@ -43,12 +43,12 @@ void closure (item_number const *items, size_t n); void closure_free (void); -/* ITEMSET is a sorted vector of item numbers; NITEMSET is its size +/* ITEMSET is a sorted vector of item indices; NITEMSET is its size (actually, points to just beyond the end of the part of it that is significant). CLOSURE places there the indices of all items which represent units of input that could arrive next. */ -extern item_number *itemset; +extern item_index *itemset; extern size_t nitemset; #endif /* !CLOSURE_H_ */ diff --git a/contrib/tools/bison/src/complain.c b/contrib/tools/bison/src/complain.c index 6a78d40e7f..357233e310 100644 --- a/contrib/tools/bison/src/complain.c +++ b/contrib/tools/bison/src/complain.c @@ -1,6 +1,6 @@ /* Declaration for error-reporting function for Bison. - Copyright (C) 2000-2002, 2004-2006, 2009-2015, 2018-2020 Free + Copyright (C) 2000-2002, 2004-2006, 2009-2015, 2018-2021 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -14,7 +14,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ /* Based on error.c and error.h, written by David MacKenzie <djm@gnu.ai.mit.edu>. */ @@ -35,6 +35,13 @@ #include "getargs.h" #include "quote.h" +// The URL of the manual page about diagnostics. Use the per-node +// manual, to avoid downloading repeatedly the whole manual over the +// Internet. +static const char *diagnostics_url + = "https://www.gnu.org/software/bison/manual/html_node/Diagnostics.html"; + + err_status complaint_status = status_none; bool warnings_are_errors = false; @@ -96,6 +103,20 @@ end_use_class (const char *s, FILE *out) } } +static void +begin_hyperlink (FILE *out, const char *ref) +{ + if (out == stderr) + styled_ostream_set_hyperlink (errstream, ref, NULL); +} + +static void +end_hyperlink (FILE *out) +{ + if (out == stderr) + styled_ostream_set_hyperlink (errstream, NULL, NULL); +} + void flush (FILE *out) { @@ -104,6 +125,23 @@ flush (FILE *out) fflush (out); } +bool +is_styled (FILE *out) +{ + if (out != stderr) + return false; + if (color_debug) + return true; +#if HAVE_LIBTEXTSTYLE + return (color_mode == color_yes + || color_mode == color_html + || (color_mode == color_tty && isatty (STDERR_FILENO))); +#else + return false; +#endif +} + + /*------------------------. | --warnings's handling. | `------------------------*/ @@ -114,6 +152,7 @@ static const argmatch_warning_doc argmatch_warning_docs[] = { { "conflicts-sr", N_("S/R conflicts (enabled by default)") }, { "conflicts-rr", N_("R/R conflicts (enabled by default)") }, + { "counterexamples", N_("generate conflict counterexamples") }, { "dangling-alias", N_("string aliases not attached to a symbol") }, { "deprecated", N_("obsolete constructs") }, { "empty-rule", N_("empty rules without %empty") }, @@ -121,7 +160,7 @@ static const argmatch_warning_doc argmatch_warning_docs[] = { "precedence", N_("useless precedence and associativity") }, { "yacc", N_("incompatibilities with POSIX Yacc") }, { "other", N_("all other warnings (enabled by default)") }, - { "all", N_("all the warnings except 'dangling-alias' and 'yacc'") }, + { "all", N_("all the warnings except 'counterexamples', 'dangling-alias' and 'yacc'") }, { "no-CATEGORY", N_("turn off warnings in CATEGORY") }, { "none", N_("turn off all the warnings") }, { "error[=CATEGORY]", N_("treat warnings as errors") }, @@ -130,18 +169,19 @@ static const argmatch_warning_doc argmatch_warning_docs[] = static const argmatch_warning_arg argmatch_warning_args[] = { - { "all", Wall }, - { "conflicts-rr", Wconflicts_rr }, - { "conflicts-sr", Wconflicts_sr }, - { "dangling-alias", Wdangling_alias }, - { "deprecated", Wdeprecated }, - { "empty-rule", Wempty_rule }, - { "everything", Weverything }, - { "midrule-values", Wmidrule_values }, - { "none", Wnone }, - { "other", Wother }, - { "precedence", Wprecedence }, - { "yacc", Wyacc }, + { "all", Wall }, + { "conflicts-rr", Wconflicts_rr }, + { "conflicts-sr", Wconflicts_sr }, + { "counterexamples", Wcounterexamples }, { "cex", Wcounterexamples }, // Show cex second. + { "dangling-alias", Wdangling_alias }, + { "deprecated", Wdeprecated }, + { "empty-rule", Wempty_rule }, + { "everything", Weverything }, + { "midrule-values", Wmidrule_values }, + { "none", Wnone }, + { "other", Wother }, + { "precedence", Wprecedence }, + { "yacc", Wyacc }, { NULL, Wnone } }; @@ -286,9 +326,7 @@ void complain_init_color (void) { #if HAVE_LIBTEXTSTYLE - if (color_mode == color_yes - || color_mode == color_html - || (color_mode == color_tty && isatty (STDERR_FILENO))) + if (is_styled (stderr)) { style_file_prepare ("BISON_STYLE", "BISON_STYLEDIR", pkgdatadir (), "bison-default.css"); @@ -410,9 +448,20 @@ warnings_print_categories (warnings warn_flags, FILE *out) const char* style = severity_style (s); fputs (" [", out); begin_use_class (style, out); - fprintf (out, "-W%s%s", - s == severity_error ? "error=" : "", - argmatch_warning_argument (&w)); + // E.g., "counterexamples". + const char *warning = argmatch_warning_argument (&w); + char ref[200]; + snprintf (ref, sizeof ref, + "%s#W%s", diagnostics_url, warning); + begin_hyperlink (out, ref); + ostream_printf (errstream, + "-W%s%s", + s == severity_error ? "error=" : "", + warning); + end_hyperlink (out); + // Because we mix stdio with ostream I/O, we need to flush + // here for sake of color == debug. + flush (out); end_use_class (style, out); fputc (']', out); /* Display only the first match, the second is "-Wall". */ diff --git a/contrib/tools/bison/src/complain.h b/contrib/tools/bison/src/complain.h index 65204ce038..fe92e7a426 100644 --- a/contrib/tools/bison/src/complain.h +++ b/contrib/tools/bison/src/complain.h @@ -1,6 +1,6 @@ /* Declaration for error-reporting function for Bison. - Copyright (C) 2000-2002, 2006, 2009-2015, 2018-2020 Free Software + Copyright (C) 2000-2002, 2006, 2009-2015, 2018-2021 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -14,11 +14,13 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef COMPLAIN_H_ # define COMPLAIN_H_ 1 +# include <attribute.h> + # include "location.h" /*---------------. @@ -34,6 +36,8 @@ void end_use_class (const char *style, FILE *out); /** Flush \a out. */ void flush (FILE *out); +/** Whether there's styling on OUT. */ +bool is_styled (FILE *out); /*-------------. | --warnings. | @@ -44,6 +48,7 @@ typedef enum { warning_conflicts_rr, warning_conflicts_sr, + warning_counterexamples, warning_dangling_alias, warning_deprecated, warning_empty_rule, @@ -104,6 +109,7 @@ typedef enum Wconflicts_rr = 1 << warning_conflicts_rr, Wconflicts_sr = 1 << warning_conflicts_sr, + Wcounterexamples = 1 << warning_counterexamples, Wdangling_alias = 1 << warning_dangling_alias, Wdeprecated = 1 << warning_deprecated, Wempty_rule = 1 << warning_empty_rule, @@ -120,7 +126,7 @@ typedef enum /**< All above warnings. */ Weverything = ~complaint & ~fatal & ~silent, - Wall = Weverything & ~Wdangling_alias & ~Wyacc + Wall = Weverything & ~Wcounterexamples & ~Wdangling_alias & ~Wyacc } warnings; /** Whether the warnings of \a flags are all unset. @@ -132,7 +138,7 @@ bool warning_is_enabled (warnings flags); /** Make a complaint, with maybe a location. */ void complain (location const *loc, warnings flags, char const *message, ...) - __attribute__ ((__format__ (__printf__, 3, 4))); + ATTRIBUTE_FORMAT ((__printf__, 3, 4)); /** Likewise, but with an \a argc/argv interface. */ void complain_args (location const *loc, warnings w, @@ -141,7 +147,7 @@ void complain_args (location const *loc, warnings w, /** Make a subcomplain with location and note. */ void subcomplain (location const *loc, warnings flags, char const *message, ...) - __attribute__ ((__format__ (__printf__, 3, 4))); + ATTRIBUTE_FORMAT ((__printf__, 3, 4)); /** GNU Bison extension not valid with POSIX Yacc. */ diff --git a/contrib/tools/bison/src/conflicts.c b/contrib/tools/bison/src/conflicts.c index 5ecd7d1747..999dc9fcb4 100644 --- a/contrib/tools/bison/src/conflicts.c +++ b/contrib/tools/bison/src/conflicts.c @@ -1,6 +1,6 @@ /* Find and resolve or report lookahead conflicts for bison, - Copyright (C) 1984, 1989, 1992, 2000-2015, 2018-2020 Free Software + Copyright (C) 1984, 1989, 1992, 2000-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> #include "system.h" @@ -25,6 +25,7 @@ #include "complain.h" #include "conflicts.h" +#include "counterexample.h" #include "files.h" #include "getargs.h" #include "gram.h" @@ -48,6 +49,12 @@ static struct obstack solved_conflicts_xml_obstack; static bitset shift_set; static bitset lookahead_set; +bool +has_conflicts (const state *s) +{ + return conflicts[s->number]; +} + enum conflict_resolution @@ -219,7 +226,7 @@ log_resolution (rule *r, symbol_number token, /*------------------------------------------------------------------. | Turn off the shift recorded for the specified token in the | -| specified state. Used when we resolve a shift-reduce conflict in | +| specified state. Used when we resolve a shift/reduce conflict in | | favor of the reduction or as an error (%nonassoc). | `------------------------------------------------------------------*/ @@ -238,19 +245,19 @@ flush_shift (state *s, int token) /*--------------------------------------------------------------------. | Turn off the reduce recorded for the specified token in the | -| specified lookahead set. Used when we resolve a shift-reduce | +| specified lookahead set. Used when we resolve a shift/reduce | | conflict in favor of the shift or as an error (%nonassoc). | `--------------------------------------------------------------------*/ static void -flush_reduce (bitset lookahead_tokens, int token) +flush_reduce (bitset lookaheads, int token) { - bitset_reset (lookahead_tokens, token); + bitset_reset (lookaheads, token); } /*------------------------------------------------------------------. -| Attempt to resolve shift-reduce conflict for one rule by means of | +| Attempt to resolve shift/reduce conflict for one rule by means of | | precedence declarations. It has already been checked that the | | rule has a precedence. A conflict is resolved by modifying the | | shift or reduce tables so that there is no longer a conflict. | @@ -268,14 +275,14 @@ resolve_sr_conflict (state *s, int ruleno, symbol **errors, int *nerrs) /* Find the rule to reduce by to get precedence of reduction. */ rule *redrule = reds->rules[ruleno]; int redprec = redrule->prec->prec; - bitset lookahead_tokens = reds->lookahead_tokens[ruleno]; + bitset lookaheads = reds->lookaheads[ruleno]; for (symbol_number i = 0; i < ntokens; ++i) - if (bitset_test (lookahead_tokens, i) + if (bitset_test (lookaheads, i) && bitset_test (lookahead_set, i) && symbols[i]->content->prec) { - /* Shift-reduce conflict occurs for token number i + /* Shift/reduce conflict occurs for token number i and it has a precedence. The precedence of shifting is that of token i. */ if (symbols[i]->content->prec < redprec) @@ -288,7 +295,7 @@ resolve_sr_conflict (state *s, int ruleno, symbol **errors, int *nerrs) { register_precedence (i, redrule->prec->number); log_resolution (redrule, i, shift_resolution); - flush_reduce (lookahead_tokens, i); + flush_reduce (lookaheads, i); } else /* Matching precedence levels. @@ -309,7 +316,7 @@ resolve_sr_conflict (state *s, int ruleno, symbol **errors, int *nerrs) case right_assoc: register_assoc (i, redrule->prec->number); log_resolution (redrule, i, right_resolution); - flush_reduce (lookahead_tokens, i); + flush_reduce (lookaheads, i); break; case left_assoc: @@ -322,7 +329,7 @@ resolve_sr_conflict (state *s, int ruleno, symbol **errors, int *nerrs) register_assoc (i, redrule->prec->number); log_resolution (redrule, i, nonassoc_resolution); flush_shift (s, i); - flush_reduce (lookahead_tokens, i); + flush_reduce (lookaheads, i); /* Record an explicit error for this token. */ errors[(*nerrs)++] = symbols[i]; break; @@ -357,11 +364,12 @@ set_conflicts (state *s, symbol **errors) } /* Loop over all rules which require lookahead in this state. First - check for shift-reduce conflict, and try to resolve using + check for shift/reduce conflict, and try to resolve using precedence. */ for (int i = 0; i < reds->num; ++i) - if (reds->rules[i]->prec && reds->rules[i]->prec->prec - && !bitset_disjoint_p (reds->lookahead_tokens[i], lookahead_set)) + if (reds->rules[i]->prec + && reds->rules[i]->prec->prec + && !bitset_disjoint_p (reds->lookaheads[i], lookahead_set)) resolve_sr_conflict (s, i, errors, &nerrs); if (nerrs) @@ -377,13 +385,13 @@ set_conflicts (state *s, symbol **errors) /* Loop over all rules which require lookahead in this state. Check for conflicts not resolved above. - reds->lookahead_tokens can be NULL if the LR type is LR(0). */ - if (reds->lookahead_tokens) + reds->lookaheads can be NULL if the LR type is LR(0). */ + if (reds->lookaheads) for (int i = 0; i < reds->num; ++i) { - if (!bitset_disjoint_p (reds->lookahead_tokens[i], lookahead_set)) + if (!bitset_disjoint_p (reds->lookaheads[i], lookahead_set)) conflicts[s->number] = true; - bitset_or (lookahead_set, lookahead_set, reds->lookahead_tokens[i]); + bitset_or (lookahead_set, lookahead_set, reds->lookaheads[i]); } } @@ -452,7 +460,7 @@ count_state_sr_conflicts (const state *s) } for (int i = 0; i < reds->num; ++i) - bitset_or (lookahead_set, lookahead_set, reds->lookahead_tokens[i]); + bitset_or (lookahead_set, lookahead_set, reds->lookaheads[i]); bitset_and (lookahead_set, lookahead_set, shift_set); @@ -491,7 +499,7 @@ count_state_rr_conflicts (const state *s) { int count = 0; for (int j = 0; j < reds->num; ++j) - count += bitset_test (reds->lookahead_tokens[j], i); + count += bitset_test (reds->lookaheads[j], i); if (2 <= count) res += count-1; } @@ -526,7 +534,7 @@ count_rule_state_sr_conflicts (rule *r, state *s) for (int i = 0; i < reds->num; ++i) if (reds->rules[i] == r) { - bitset lookaheads = reds->lookahead_tokens[i]; + bitset lookaheads = reds->lookaheads[i]; int j; FOR_EACH_SHIFT (trans, j) res += bitset_test (lookaheads, TRANSITION_SYMBOL (trans, j)); @@ -568,8 +576,8 @@ count_rule_state_rr_conflicts (rule *r, state *s) if (reds->rules[j] != r) { bitset_and (lookaheads, - reds->lookahead_tokens[i], - reds->lookahead_tokens[j]); + reds->lookaheads[i], + reds->lookaheads[j]); res += bitset_count (lookaheads); } bitset_free (lookaheads); @@ -624,12 +632,20 @@ conflicts_total_count (void) return count_sr_conflicts () + count_rr_conflicts (); } -/*------------------------------. -| Reporting per-rule conflicts. | -`------------------------------*/ +static void +report_counterexamples (void) +{ + for (state_number sn = 0; sn < nstates; ++sn) + if (conflicts[sn]) + counterexample_report_state (states[sn], stderr, ""); +} + +/*------------------------------------------------. +| Report per-rule %expect/%expect-rr mismatches. | +`------------------------------------------------*/ static void -rule_conflicts_print (void) +report_rule_expectation_mismatches (void) { for (rule_number i = 0; i < nrules; i += 1) { @@ -644,13 +660,13 @@ rule_conflicts_print (void) complain (&r->location, complaint, _("shift/reduce conflicts for rule %d:" " %d found, %d expected"), - r->user_number, sr, expected_sr); + r->code, sr, expected_sr); int rr = count_rule_rr_conflicts (r); if (rr != expected_rr && (rr != 0 || expected_rr != -1)) complain (&r->location, complaint, _("reduce/reduce conflicts for rule %d:" " %d found, %d expected"), - r->user_number, rr, expected_rr); + r->code, rr, expected_rr); } } } @@ -662,7 +678,7 @@ rule_conflicts_print (void) void conflicts_print (void) { - rule_conflicts_print (); + report_rule_expectation_mismatches (); if (! glr_parser && expected_rr_conflicts != -1) { @@ -670,8 +686,10 @@ conflicts_print (void) expected_rr_conflicts = -1; } - /* Screams for factoring, but almost useless because of the - different strings to translate. */ + // The warning flags used to emit a diagnostic, if we did. + warnings unexpected_conflicts_warning = Wnone; + /* The following two blocks scream for factoring, but i18n support + would make it ugly. */ { int total = count_sr_conflicts (); /* If %expect is not used, but %expect-rr is, then expect 0 sr. */ @@ -682,16 +700,23 @@ conflicts_print (void) if (expected != -1) { if (expected != total) - complain (NULL, complaint, - _("shift/reduce conflicts: %d found, %d expected"), - total, expected); + { + complain (NULL, complaint, + _("shift/reduce conflicts: %d found, %d expected"), + total, expected); + if (total) + unexpected_conflicts_warning = complaint; + } } else if (total) - complain (NULL, Wconflicts_sr, - ngettext ("%d shift/reduce conflict", - "%d shift/reduce conflicts", - total), - total); + { + complain (NULL, Wconflicts_sr, + ngettext ("%d shift/reduce conflict", + "%d shift/reduce conflicts", + total), + total); + unexpected_conflicts_warning = Wconflicts_sr; + } } { @@ -704,17 +729,31 @@ conflicts_print (void) if (expected != -1) { if (expected != total) - complain (NULL, complaint, - _("reduce/reduce conflicts: %d found, %d expected"), - total, expected); + { + complain (NULL, complaint, + _("reduce/reduce conflicts: %d found, %d expected"), + total, expected); + if (total) + unexpected_conflicts_warning = complaint; + } } else if (total) - complain (NULL, Wconflicts_rr, - ngettext ("%d reduce/reduce conflict", - "%d reduce/reduce conflicts", - total), - total); + { + complain (NULL, Wconflicts_rr, + ngettext ("%d reduce/reduce conflict", + "%d reduce/reduce conflicts", + total), + total); + unexpected_conflicts_warning = Wconflicts_rr; + } } + + if (warning_is_enabled (Wcounterexamples)) + report_counterexamples (); + else if (unexpected_conflicts_warning != Wnone) + subcomplain (NULL, unexpected_conflicts_warning, + _("rerun with option '-Wcounterexamples'" + " to generate conflict counterexamples")); } void diff --git a/contrib/tools/bison/src/conflicts.h b/contrib/tools/bison/src/conflicts.h index 5b26efdefe..1dff0ba27c 100644 --- a/contrib/tools/bison/src/conflicts.h +++ b/contrib/tools/bison/src/conflicts.h @@ -1,6 +1,6 @@ /* Find and resolve or report lookahead conflicts for bison, - Copyright (C) 2000-2002, 2004, 2007, 2009-2015, 2018-2020 Free + Copyright (C) 2000-2002, 2004, 2007, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef CONFLICTS_H_ # define CONFLICTS_H_ @@ -41,6 +41,8 @@ int conflicts_total_count (void); void conflicts_output (FILE *out); void conflicts_free (void); +bool has_conflicts (const state *s); + /* Were there conflicts? */ extern int expected_sr_conflicts; extern int expected_rr_conflicts; diff --git a/contrib/tools/bison/src/counterexample.c b/contrib/tools/bison/src/counterexample.c new file mode 100644 index 0000000000..733ee79553 --- /dev/null +++ b/contrib/tools/bison/src/counterexample.c @@ -0,0 +1,1399 @@ +/* Conflict counterexample generation + + Copyright (C) 2020-2021 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +#include "counterexample.h" + +#include "system.h" + +#include <errno.h> +#include <gl_linked_list.h> +#include <gl_rbtreehash_list.h> +#include <hash.h> +#include <mbswidth.h> +#include <stdlib.h> +#include <textstyle.h> +#include <time.h> + +#include "closure.h" +#include "complain.h" +#include "derivation.h" +#include "getargs.h" +#include "gram.h" +#include "lalr.h" +#include "lssi.h" +#include "nullable.h" +#include "parse-simulation.h" + + +#define TIME_LIMIT_ENFORCED true +/** If set to false, only consider the states on the shortest + * lookahead-sensitive path when constructing a unifying counterexample. */ +#define EXTENDED_SEARCH false + +/* costs for making various steps in a search */ +#define PRODUCTION_COST 50 +#define REDUCE_COST 1 +#define SHIFT_COST 1 +#define UNSHIFT_COST 1 +#define EXTENDED_COST 10000 + +/** The time limit before printing an assurance message to the user to + * indicate that the search is still running. */ +#define ASSURANCE_LIMIT 2.0f + +/* The time limit before giving up looking for unifying counterexample. */ +static float time_limit = 5.0f; + +#define CUMULATIVE_TIME_LIMIT 120.0f + +// This is the fastest way to get the tail node from the gl_list API. +static gl_list_node_t +list_get_end (gl_list_t list) +{ + gl_list_node_t sentinel = gl_list_add_last (list, NULL); + gl_list_node_t res = gl_list_previous_node (list, sentinel); + gl_list_remove_node (list, sentinel); + return res; +} + +typedef struct +{ + derivation *d1; + derivation *d2; + bool shift_reduce; + bool unifying; + bool timeout; +} counterexample; + +static counterexample * +new_counterexample (derivation *d1, derivation *d2, + bool shift_reduce, + bool u, bool t) +{ + counterexample *res = xmalloc (sizeof *res); + res->shift_reduce = shift_reduce; + if (shift_reduce) + { + // Display the shift first. + res->d1 = d2; + res->d2 = d1; + } + else + { + res->d1 = d1; + res->d2 = d2; + } + res->unifying = u; + res->timeout = t; + return res; +} + +static void +free_counterexample (counterexample *cex) +{ + derivation_free (cex->d1); + derivation_free (cex->d2); + free (cex); +} + +static void +counterexample_print (const counterexample *cex, FILE *out, const char *prefix) +{ + const bool flat = getenv ("YYFLAT"); + const char *example1_label + = cex->unifying ? _("Example") : _("First example"); + const char *example2_label + = cex->unifying ? _("Example") : _("Second example"); + const char *deriv1_label + = cex->shift_reduce ? _("Shift derivation") : _("First reduce derivation"); + const char *deriv2_label + = cex->shift_reduce ? _("Reduce derivation") : _("Second reduce derivation"); + const int width = + max_int (max_int (mbswidth (example1_label, 0), mbswidth (example2_label, 0)), + max_int (mbswidth (deriv1_label, 0), mbswidth (deriv2_label, 0))); + if (flat) + fprintf (out, " %s%s%*s ", prefix, + example1_label, width - mbswidth (example1_label, 0), ""); + else + fprintf (out, " %s%s: ", prefix, example1_label); + derivation_print_leaves (cex->d1, out); + if (flat) + fprintf (out, " %s%s%*s ", prefix, + deriv1_label, width - mbswidth (deriv1_label, 0), ""); + else + fprintf (out, " %s%s", prefix, deriv1_label); + derivation_print (cex->d1, out, prefix); + + // If we output to the terminal (via stderr) and we have color + // support, display unifying examples a second time, as color allows + // to see the differences. + if (!cex->unifying || is_styled (stderr)) + { + if (flat) + fprintf (out, " %s%s%*s ", prefix, + example2_label, width - mbswidth (example2_label, 0), ""); + else + fprintf (out, " %s%s: ", prefix, example2_label); + derivation_print_leaves (cex->d2, out); + } + if (flat) + fprintf (out, " %s%s%*s ", prefix, + deriv2_label, width - mbswidth (deriv2_label, 0), ""); + else + fprintf (out, " %s%s", prefix, deriv2_label); + derivation_print (cex->d2, out, prefix); + + if (out != stderr) + putc ('\n', out); +} + +/* + * + * NON UNIFYING COUNTER EXAMPLES + * + */ + +// Search node for BFS on state items +struct si_bfs_node; +typedef struct si_bfs_node +{ + state_item_number si; + struct si_bfs_node *parent; + int reference_count; +} si_bfs_node; + +static si_bfs_node * +si_bfs_new (state_item_number si, si_bfs_node *parent) +{ + si_bfs_node *res = xcalloc (1, sizeof *res); + res->si = si; + res->parent = parent; + res->reference_count = 1; + if (parent) + ++parent->reference_count; + return res; +} + +static bool +si_bfs_contains (const si_bfs_node *n, state_item_number sin) +{ + for (const si_bfs_node *search = n; search != NULL; search = search->parent) + if (search->si == sin) + return true; + return false; +} + +static void +si_bfs_free (si_bfs_node *n) +{ + if (n == NULL) + return; + --n->reference_count; + if (n->reference_count == 0) + { + si_bfs_free (n->parent); + free (n); + } +} + +typedef gl_list_t si_bfs_node_list; + +/** + * start is a state_item such that conflict_sym is an element of FIRSTS of the + * nonterminal after the dot in start. Because of this, we should be able to + * find a production item starting with conflict_sym by only searching productions + * of the nonterminal and shifting over nullable nonterminals + * + * this returns the derivation of the productions that lead to conflict_sym + */ +static inline derivation_list +expand_to_conflict (state_item_number start, symbol_number conflict_sym) +{ + si_bfs_node *init = si_bfs_new (start, NULL); + + si_bfs_node_list queue + = gl_list_create (GL_LINKED_LIST, NULL, NULL, + (gl_listelement_dispose_fn) si_bfs_free, + true, 1, (const void **) &init); + si_bfs_node *node = NULL; + // breadth-first search for a path of productions to the conflict symbol + while (gl_list_size (queue) > 0) + { + node = (si_bfs_node *) gl_list_get_at (queue, 0); + state_item *silast = &state_items[node->si]; + symbol_number sym = item_number_as_symbol_number (*silast->item); + if (sym == conflict_sym) + break; + if (ISVAR (sym)) + { + // add each production to the search + bitset_iterator biter; + state_item_number sin; + bitset sib = silast->prods; + BITSET_FOR_EACH (biter, sib, sin, 0) + { + // ignore productions already in the path + if (si_bfs_contains (node, sin)) + continue; + si_bfs_node *next = si_bfs_new (sin, node); + gl_list_add_last (queue, next); + } + // for nullable nonterminals, add its goto to the search + if (nullable[sym - ntokens]) + { + si_bfs_node *next = si_bfs_new (silast->trans, node); + gl_list_add_last (queue, next); + } + } + gl_list_remove_at (queue, 0); + } + if (gl_list_size (queue) == 0) + { + gl_list_free (queue); + fputs ("Error expanding derivation\n", stderr); + abort (); + } + + derivation *dinit = derivation_new_leaf (conflict_sym); + derivation_list result = derivation_list_new (); + derivation_list_append (result, dinit); + // iterate backwards through the generated path to create a derivation + // of the conflict symbol containing derivations of each production step. + + for (si_bfs_node *n = node; n != NULL; n = n->parent) + { + state_item *si = &state_items[n->si]; + item_number *pos = si->item; + if (SI_PRODUCTION (si)) + { + item_number *i = NULL; + for (i = pos + 1; !item_number_is_rule_number (*i); ++i) + derivation_list_append (result, derivation_new_leaf (*i)); + symbol_number lhs = + rules[item_number_as_rule_number (*i)].lhs->number; + derivation *deriv = derivation_new (lhs, result); + result = derivation_list_new (); + derivation_list_append (result, deriv); + } + else + { + symbol_number sym = item_number_as_symbol_number (*(pos - 1)); + derivation *deriv = derivation_new_leaf (sym); + derivation_list_prepend (result, deriv); + } + } + gl_list_free (queue); + derivation_free ((derivation*)gl_list_get_at (result, 0)); + gl_list_remove_at (result, 0); + return result; +} + +/** + * Complete derivations for any pending productions in the given + * sequence of state-items. For example, the input could be a path + * of states that would give us the following input: + * Stmt ::= [lval ::= [VAR] '=' e ::=[ e::=['0'] '+' • + * So to complete the derivation of Stmt, we need an output like: + * Stmt ::= [lval ::= [VAR] '=' e ::=[ e::=['0'] '+' • e ] ';' ] + */ +static derivation * +complete_diverging_example (symbol_number conflict_sym, + state_item_list path, derivation_list derivs) +{ + // The idea is to transfer each pending symbol on the productions + // associated with the given StateItems to the resulting derivation. + derivation_list result = derivation_list_new (); + bool lookahead_required = false; + if (!derivs) + { + derivs = derivation_list_new (); + gl_list_add_last (result, derivation_dot ()); + lookahead_required = true; + } + + gl_list_node_t deriv = list_get_end (derivs); + + // We go backwards through the path to create the derivation tree bottom-up. + // Effectively this loops through each production once, and generates a + // derivation of the left hand side by appending all of the rhs symbols. + // this becomes the derivation of the nonterminal after the dot in the + // next production, and all of the other symbols of the rule are added as normal. + for (gl_list_node_t state_node = list_get_end (path); + state_node != NULL; + state_node = gl_list_previous_node (path, state_node)) + { + state_item *si = (state_item *) gl_list_node_value (path, state_node); + item_number *item = si->item; + item_number pos = *item; + // symbols after dot + if (gl_list_size (result) == 1 && !item_number_is_rule_number (pos) + && gl_list_get_at (result, 0) == derivation_dot ()) + { + derivation_list_append (result, + derivation_new_leaf (item_number_as_symbol_number (pos))); + lookahead_required = false; + } + item_number *i = item; + // go through each symbol after the dot in the current rule, and + // add each symbol to its derivation. + for (state_item_number nsi = si - state_items; + !item_number_is_rule_number (*i); + ++i, nsi = state_items[nsi].trans) + { + // if the item is a reduction, we could skip to the wrong rule + // by starting at i + 1, so this continue is necessary + if (i == item) + continue; + symbol_number sym = item_number_as_symbol_number (*i); + if (!lookahead_required || sym == conflict_sym) + { + derivation_list_append (result, derivation_new_leaf (sym)); + lookahead_required = false; + continue; + } + // Since PATH is a path to the conflict state-item, + // for a reduce conflict item, we will want to have a derivation + // that shows the conflict symbol from its lookahead set being used. + // + // Since reductions have the dot at the end of the item, + // this loop will be first executed on the last item in the path + // that's not a reduction. When that happens, + // the symbol after the dot should be a nonterminal, + // and we can look through successive nullable nonterminals + // for one with the conflict symbol in its first set. + if (bitset_test (FIRSTS (sym), conflict_sym)) + { + lookahead_required = false; + derivation_list next_derivs = + expand_to_conflict (nsi, conflict_sym); + derivation *d = NULL; + for (gl_list_iterator_t it = gl_list_iterator (next_derivs); + derivation_list_next (&it, &d);) + derivation_list_append (result, d); + i += gl_list_size (next_derivs) - 1; + derivation_list_free (next_derivs); + } + else if (nullable[sym - ntokens]) + { + derivation *d = derivation_new_leaf (sym); + derivation_list_append (result, d); + } + else + { + // We found a path to the conflict item, and despite it + // having the conflict symbol in its lookahead, no example + // containing the symbol after the conflict item + // can be found. + derivation_list_append (result, derivation_new_leaf (1)); + lookahead_required = false; + } + } + const rule *r = &rules[item_number_as_rule_number (*i)]; + // add derivations for symbols before dot + for (i = item - 1; !item_number_is_rule_number (*i) && i >= ritem; i--) + { + gl_list_node_t p = gl_list_previous_node (path, state_node); + if (p) + state_node = p; + if (deriv) + { + const void *tmp_deriv = gl_list_node_value (derivs, deriv); + deriv = gl_list_previous_node (derivs, deriv); + derivation_list_prepend (result, (derivation*)tmp_deriv); + } + else + derivation_list_prepend (result, derivation_new_leaf (*i)); + } + // completing the derivation + derivation *new_deriv = derivation_new (r->lhs->number, result); + result = derivation_list_new (); + derivation_list_append (result, new_deriv); + } + derivation *res = (derivation *) gl_list_get_at (result, 0); + derivation_retain (res); + derivation_list_free (result); + derivation_list_free (derivs); + return res; +} + +/* Iterate backwards through the shifts of the path in the reduce + conflict, and find a path of shifts from the shift conflict that + goes through the same states. */ +static state_item_list +nonunifying_shift_path (state_item_list reduce_path, state_item *shift_conflict) +{ + gl_list_node_t tmp = gl_list_add_last (reduce_path, NULL); + gl_list_node_t next_node = gl_list_previous_node (reduce_path, tmp); + gl_list_node_t node = gl_list_previous_node (reduce_path, next_node); + gl_list_remove_node (reduce_path, tmp); + state_item *si = shift_conflict; + state_item_list result = + gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true); + // FIXME: bool paths_merged; + for (; node != NULL; next_node = node, + node = gl_list_previous_node (reduce_path, node)) + { + state_item *refsi = + (state_item *) gl_list_node_value (reduce_path, node); + state_item *nextrefsi = + (state_item *) gl_list_node_value (reduce_path, next_node); + if (nextrefsi == si) + { + gl_list_add_first (result, refsi); + si = refsi; + continue; + } + // skip reduction items + if (nextrefsi->item != refsi->item + 1 && refsi->item != ritem) + continue; + + // bfs to find a shift to the right state + si_bfs_node *init = si_bfs_new (si - state_items, NULL); + si_bfs_node_list queue + = gl_list_create (GL_LINKED_LIST, NULL, NULL, + (gl_listelement_dispose_fn) si_bfs_free, + true, 1, (const void **) &init); + si_bfs_node *sis = NULL; + state_item *prevsi = NULL; + while (gl_list_size (queue) > 0) + { + sis = (si_bfs_node *) gl_list_get_at (queue, 0); + // if we end up in the start state, the shift couldn't be found. + if (sis->si == 0) + break; + + state_item *search_si = &state_items[sis->si]; + // if the current state-item is a production item, + // its reverse production items get added to the queue. + // Otherwise, look for a reverse transition to the target state. + bitset rsi = search_si->revs; + bitset_iterator biter; + state_item_number sin; + BITSET_FOR_EACH (biter, rsi, sin, 0) + { + prevsi = &state_items[sin]; + if (SI_TRANSITION (search_si)) + { + if (prevsi->state == refsi->state) + goto search_end; + } + else if (!si_bfs_contains (sis, sin)) + { + si_bfs_node *prevsis = si_bfs_new (sin, sis); + gl_list_add_last (queue, prevsis); + } + } + gl_list_remove_at (queue, 0); + } + search_end: + // prepend path to shift we found + if (sis) + { + gl_list_node_t ln = gl_list_add_first (result, &state_items[sis->si]); + for (si_bfs_node *n = sis->parent; n; n = n->parent) + ln = gl_list_add_after (result, ln, &state_items[n->si]); + + } + si = prevsi; + gl_list_free (queue); + } + if (trace_flag & trace_cex) + { + fputs ("SHIFT ITEM PATH:\n", stderr); + state_item *sip = NULL; + for (gl_list_iterator_t it = gl_list_iterator (result); + state_item_list_next (&it, &sip); + ) + state_item_print (sip, stderr, ""); + } + return result; +} + + +/** + * Construct a nonunifying counterexample from the shortest + * lookahead-sensitive path. + */ +static counterexample * +example_from_path (bool shift_reduce, + state_item_number itm2, + state_item_list shortest_path, symbol_number next_sym) +{ + derivation *deriv1 = + complete_diverging_example (next_sym, shortest_path, NULL); + state_item_list path_2 + = shift_reduce + ? nonunifying_shift_path (shortest_path, &state_items [itm2]) + : shortest_path_from_start (itm2, next_sym); + derivation *deriv2 = complete_diverging_example (next_sym, path_2, NULL); + gl_list_free (path_2); + return new_counterexample (deriv1, deriv2, shift_reduce, false, true); +} + +/* + * + * UNIFYING COUNTER EXAMPLES + * + */ + +/* A search state keeps track of two parser simulations, + * one starting at each conflict. Complexity is a metric + * which sums different parser actions with varying weights. + */ +typedef struct +{ + parse_state *states[2]; + int complexity; +} search_state; + +static search_state * +initial_search_state (state_item *conflict1, state_item *conflict2) +{ + search_state *res = xmalloc (sizeof *res); + res->states[0] = new_parse_state (conflict1); + res->states[1] = new_parse_state (conflict2); + parse_state_retain (res->states[0]); + parse_state_retain (res->states[1]); + res->complexity = 0; + return res; +} + +static search_state * +new_search_state (parse_state *ps1, parse_state *ps2, int complexity) +{ + search_state *res = xmalloc (sizeof *res); + res->states[0] = ps1; + res->states[1] = ps2; + parse_state_retain (res->states[0]); + parse_state_retain (res->states[1]); + res->complexity = complexity; + return res; +} + +static search_state * +copy_search_state (search_state *parent) +{ + search_state *res = xmalloc (sizeof *res); + *res = *parent; + parse_state_retain (res->states[0]); + parse_state_retain (res->states[1]); + return res; +} + +static void +search_state_free_children (search_state *ss) +{ + free_parse_state (ss->states[0]); + free_parse_state (ss->states[1]); +} + +static void +search_state_free (search_state *ss) +{ + if (ss == NULL) + return; + search_state_free_children (ss); + free (ss); +} + +/* For debugging traces. */ +static void +search_state_print (search_state *ss) +{ + fputs ("CONFLICT 1 ", stderr); + print_parse_state (ss->states[0]); + fputs ("CONFLICT 2 ", stderr); + print_parse_state (ss->states[1]); + putc ('\n', stderr); +} + +typedef gl_list_t search_state_list; + +static inline bool +search_state_list_next (gl_list_iterator_t *it, search_state **ss) +{ + const void *p = NULL; + bool res = gl_list_iterator_next (it, &p, NULL); + if (res) + *ss = (search_state*) p; + else + gl_list_iterator_free (it); + return res; +} + +/* + * When a search state is copied, this is used to + * directly set one of the parse states + */ +static inline void +ss_set_parse_state (search_state *ss, int idx, parse_state *ps) +{ + free_parse_state (ss->states[idx]); + ss->states[idx] = ps; + parse_state_retain (ps); +} + +/* + * Construct a nonunifying example from a search state + * which has its parse states unified at the beginning + * but not the end of the example. + */ +static counterexample * +complete_diverging_examples (search_state *ss, + symbol_number next_sym, + bool shift_reduce) +{ + derivation *new_derivs[2]; + for (int i = 0; i < 2; ++i) + { + state_item_list sitems; + derivation_list derivs; + parse_state_lists (ss->states[i], &sitems, &derivs); + new_derivs[i] = complete_diverging_example (next_sym, sitems, derivs); + gl_list_free (sitems); + } + return new_counterexample (new_derivs[0], new_derivs[1], + shift_reduce, false, true); +} + +/* + * Search states are stored in bundles with those that + * share the same complexity. This is so the priority + * queue takes less overhead. + */ +typedef struct +{ + search_state_list states; + int complexity; +} search_state_bundle; + +static void +ssb_free (search_state_bundle *ssb) +{ + gl_list_free (ssb->states); + free (ssb); +} + +static size_t +ssb_hasher (search_state_bundle *ssb) +{ + return ssb->complexity; +} + +static int +ssb_comp (const search_state_bundle *s1, const search_state_bundle *s2) +{ + return s1->complexity - s2->complexity; +} + +static bool +ssb_equals (const search_state_bundle *s1, const search_state_bundle *s2) +{ + return s1->complexity == s2->complexity; +} + +typedef gl_list_t ssb_list; + +static size_t +visited_hasher (const search_state *ss, size_t max) +{ + return (parse_state_hasher (ss->states[0], max) + + parse_state_hasher (ss->states[1], max)) % max; +} + +static bool +visited_comparator (const search_state *ss1, const search_state *ss2) +{ + return parse_state_comparator (ss1->states[0], ss2->states[0]) + && parse_state_comparator (ss1->states[1], ss2->states[1]); +} + +/* Priority queue for search states with minimal complexity. */ +static ssb_list ssb_queue; +static Hash_table *visited; +/* The set of parser states on the shortest lookahead-sensitive path. */ +static bitset scp_set = NULL; +/* The set of parser states used for the conflict reduction rule. */ +static bitset rpp_set = NULL; + +static void +ssb_append (search_state *ss) +{ + if (hash_lookup (visited, ss)) + { + search_state_free (ss); + return; + } + hash_xinsert (visited, ss); + // if states are only referenced by the visited set, + // their contents should be freed as we only need + // the metadata necessary to compute a hash. + parse_state_free_contents_early (ss->states[0]); + parse_state_free_contents_early (ss->states[1]); + parse_state_retain (ss->states[0]); + parse_state_retain (ss->states[1]); + search_state_bundle *ssb = xmalloc (sizeof *ssb); + ssb->complexity = ss->complexity; + gl_list_node_t n = gl_list_search (ssb_queue, ssb); + if (!n) + { + ssb->states = + gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, + (gl_listelement_dispose_fn)search_state_free_children, + true); + gl_sortedlist_add (ssb_queue, (gl_listelement_compar_fn) ssb_comp, ssb); + } + else + { + free (ssb); + ssb = (search_state_bundle *) gl_list_node_value (ssb_queue, n); + } + gl_list_add_last (ssb->states, ss); +} + +/* + * The following functions perform various actions on parse states + * and assign complexities to the newly generated search states. + */ +static void +production_step (search_state *ss, int parser_state) +{ + const state_item *other_si = parse_state_tail (ss->states[1 - parser_state]); + symbol_number other_sym = item_number_as_symbol_number (*other_si->item); + parse_state_list prods = + simulate_production (ss->states[parser_state], other_sym); + int complexity = ss->complexity + PRODUCTION_COST; + + parse_state *ps = NULL; + for (gl_list_iterator_t it = gl_list_iterator (prods); + parse_state_list_next (&it, &ps); + ) + { + search_state *copy = copy_search_state (ss); + ss_set_parse_state (copy, parser_state, ps); + copy->complexity = complexity; + ssb_append (copy); + } + gl_list_free (prods); +} + +static inline int +reduction_cost (const parse_state *ps) +{ + int shifts; + int productions; + parse_state_completed_steps (ps, &shifts, &productions); + return SHIFT_COST * shifts + PRODUCTION_COST * productions; +} + +static search_state_list +reduction_step (search_state *ss, const item_number *conflict_item, + int parser_state, int rule_len) +{ + (void) conflict_item; // FIXME: Unused + search_state_list result = + gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, 1); + + parse_state *ps = ss->states[parser_state]; + const state_item *si = parse_state_tail (ps); + bitset symbol_set = si->lookahead; + parse_state *other = ss->states[1 - parser_state]; + const state_item *other_si = parse_state_tail (other); + // if the other state can transition on a symbol, + // the reduction needs to have that symbol in its lookahead + if (item_number_is_symbol_number (*other_si->item)) + { + symbol_number other_sym = + item_number_as_symbol_number (*other_si->item); + if (!intersect_symbol (other_sym, symbol_set)) + return result; + symbol_set = bitset_create (nsyms, BITSET_FIXED); + bitset_set (symbol_set, other_sym); + } + + // FIXME: search_state *new_root = copy_search_state (ss); + parse_state_list reduced = + simulate_reduction (ps, rule_len, symbol_set); + parse_state *reduced_ps = NULL; + for (gl_list_iterator_t it = gl_list_iterator (reduced); + parse_state_list_next (&it, &reduced_ps); + ) + { + search_state *copy = copy_search_state (ss); + ss_set_parse_state (copy, parser_state, reduced_ps); + int r_cost = reduction_cost (reduced_ps); + copy->complexity += r_cost + PRODUCTION_COST + 2 * SHIFT_COST; + gl_list_add_last (result, copy); + } + gl_list_free (reduced); + if (symbol_set != si->lookahead) + bitset_free (symbol_set); + return result; +} + +/** + * Attempt to prepend the given symbol to this search state, respecting + * the given subsequent next symbol on each path. If a reverse transition + * cannot be made on both states, possible reverse productions are prepended + */ +static void +search_state_prepend (search_state *ss, symbol_number sym, bitset guide) +{ + (void) sym; // FIXME: Unused. + const state_item *si1src = parse_state_head (ss->states[0]); + const state_item *si2src = parse_state_head (ss->states[1]); + + bool prod1 = SI_PRODUCTION (si1src); + // If one can make a reverse transition and the other can't, only apply + // the reverse productions that the other state can make in an attempt to + // make progress. + if (prod1 != SI_PRODUCTION (si2src)) + { + int prod_state = prod1 ? 0 : 1; + parse_state_list prev = parser_prepend (ss->states[prod_state]); + parse_state *ps = NULL; + for (gl_list_iterator_t iter = gl_list_iterator (prev); + parse_state_list_next (&iter, &ps); + ) + { + const state_item *psi = parse_state_head (ps); + bool guided = bitset_test (guide, psi->state->number); + if (!guided && !EXTENDED_SEARCH) + continue; + + search_state *copy = copy_search_state (ss); + ss_set_parse_state (copy, prod_state, ps); + copy->complexity += PRODUCTION_COST; + if (!guided) + copy->complexity += EXTENDED_COST; + ssb_append (copy); + } + gl_list_free (prev); + return; + } + // The parse state heads are either both production items or both + // transition items. So all prepend options will either be + // reverse transitions or reverse productions + int complexity_cost = prod1 ? PRODUCTION_COST : UNSHIFT_COST; + complexity_cost *= 2; + + parse_state_list prev1 = parser_prepend (ss->states[0]); + parse_state_list prev2 = parser_prepend (ss->states[1]); + + // loop through each pair of possible prepend states and append search + // states for each pair where the parser states correspond to the same + // parsed input. + parse_state *ps1 = NULL; + for (gl_list_iterator_t iter1 = gl_list_iterator (prev1); + parse_state_list_next (&iter1, &ps1); + ) + { + const state_item *psi1 = parse_state_head (ps1); + bool guided1 = bitset_test (guide, psi1->state->number); + if (!guided1 && !EXTENDED_SEARCH) + continue; + + parse_state *ps2 = NULL; + for (gl_list_iterator_t iter2 = gl_list_iterator (prev2); + parse_state_list_next (&iter2, &ps2); + ) + { + const state_item *psi2 = parse_state_head (ps2); + + bool guided2 = bitset_test (guide, psi2->state->number); + if (!guided2 && !EXTENDED_SEARCH) + continue; + // Only consider prepend state items that share the same state. + if (psi1->state != psi2->state) + continue; + + int complexity = ss->complexity; + if (prod1) + complexity += PRODUCTION_COST * 2; + else + complexity += UNSHIFT_COST * 2; + // penalty for not being along the guide path + if (!guided1 || !guided2) + complexity += EXTENDED_COST; + ssb_append (new_search_state (ps1, ps2, complexity)); + } + } + gl_list_free (prev1); + gl_list_free (prev2); +} + +/** + * Determine if the productions associated with the given parser items have + * the same prefix up to the dot. + */ +static bool +have_common_prefix (const item_number *itm1, const item_number *itm2) +{ + int i = 0; + for (; !item_number_is_rule_number (itm1[i]); ++i) + if (itm1[i] != itm2[i]) + return false; + return item_number_is_rule_number (itm2[i]); +} + +/* + * The start and end locations of an item in ritem. + */ +static const item_number * +item_rule_start (const item_number *item) +{ + const item_number *res = NULL; + for (res = item; + ritem < res && item_number_is_symbol_number (*(res - 1)); + --res) + continue; + return res; +} + +static const item_number * +item_rule_end (const item_number *item) +{ + const item_number *res = NULL; + for (res = item; item_number_is_symbol_number (*res); ++res) + continue; + return res; +} + +/* + * Perform the appropriate possible parser actions + * on a search state and add the results to the + * search state priority queue. + */ +static inline void +generate_next_states (search_state *ss, state_item *conflict1, + state_item *conflict2) +{ + // Compute the successor configurations. + parse_state *ps1 = ss->states[0]; + parse_state *ps2 = ss->states[1]; + const state_item *si1 = parse_state_tail (ps1); + const state_item *si2 = parse_state_tail (ps2); + bool si1reduce = item_number_is_rule_number (*si1->item); + bool si2reduce = item_number_is_rule_number (*si2->item); + if (!si1reduce && !si2reduce) + { + // Transition if both paths end at the same symbol + if (*si1->item == *si2->item) + { + int complexity = ss->complexity + 2 * SHIFT_COST; + parse_state_list trans1 = simulate_transition (ps1); + parse_state_list trans2 = simulate_transition (ps2); + parse_state *tps1 = NULL; + parse_state *tps2 = NULL; + for (gl_list_iterator_t it1 = gl_list_iterator (trans1); + parse_state_list_next (&it1, &tps1); + ) + for (gl_list_iterator_t it2 = gl_list_iterator (trans2); + parse_state_list_next (&it2, &tps2); + ) + ssb_append (new_search_state (tps1, tps2, complexity)); + gl_list_free (trans1); + gl_list_free (trans2); + } + + // Take production steps if possible. + production_step (ss, 0); + production_step (ss, 1); + } + // One of the states requires a reduction + else + { + const item_number *rhs1 = item_rule_start (si1->item); + const item_number *rhe1 = item_rule_end (si1->item); + int len1 = rhe1 - rhs1; + int size1 = parse_state_length (ps1); + bool ready1 = si1reduce && len1 < size1; + + const item_number *rhs2 = item_rule_start (si2->item); + const item_number *rhe2 = item_rule_end (si2->item); + int len2 = rhe2 - rhs2; + int size2 = parse_state_length (ps2); + bool ready2 = si2reduce && len2 < size2; + // If there is a path ready for reduction without being + // prepended further, reduce. + if (ready1 && ready2) + { + search_state_list reduced1 = reduction_step (ss, conflict1->item, 0, len1); + gl_list_add_last (reduced1, ss); + search_state *red1 = NULL; + for (gl_list_iterator_t iter = gl_list_iterator (reduced1); + search_state_list_next (&iter, &red1); + ) + { + search_state_list reduced2 = + reduction_step (red1, conflict2->item, 1, len2); + search_state *red2 = NULL; + for (gl_list_iterator_t iter2 = gl_list_iterator (reduced2); + search_state_list_next (&iter2, &red2); + ) + ssb_append (red2); + // Avoid duplicates. + if (red1 != ss) + ssb_append (red1); + gl_list_free (reduced2); + } + gl_list_free (reduced1); + } + else if (ready1) + { + search_state_list reduced1 = reduction_step (ss, conflict1->item, 0, len1); + search_state *red1 = NULL; + for (gl_list_iterator_t iter = gl_list_iterator (reduced1); + search_state_list_next (&iter, &red1); + ) + ssb_append (red1); + gl_list_free (reduced1); + } + else if (ready2) + { + search_state_list reduced2 = reduction_step (ss, conflict2->item, 1, len2); + search_state *red2 = NULL; + for (gl_list_iterator_t iter2 = gl_list_iterator (reduced2); + search_state_list_next (&iter2, &red2); + ) + ssb_append (red2); + gl_list_free (reduced2); + } + /* Both states end with a reduction, yet they don't have enough symbols + * to reduce. This means symbols are missing from the beginning of the + * rule, so we must prepend */ + else + { + const symbol_number sym + = si1reduce && !ready1 + ? *(rhe1 - size1) + : *(rhe2 - size2); + search_state_prepend (ss, sym, + parse_state_depth (ss->states[0]) >= 0 + ? rpp_set : scp_set); + } + } +} + +/* + * Perform the actual counterexample search, + * keeps track of what stage of the search algorithm + * we are at and gives the appropriate counterexample + * type based off of time constraints. + */ +static counterexample * +unifying_example (state_item_number itm1, + state_item_number itm2, + bool shift_reduce, + state_item_list reduce_path, symbol_number next_sym) +{ + state_item *conflict1 = &state_items[itm1]; + state_item *conflict2 = &state_items[itm2]; + search_state *initial = initial_search_state (conflict1, conflict2); + ssb_queue = gl_list_create_empty (GL_RBTREEHASH_LIST, + (gl_listelement_equals_fn) ssb_equals, + (gl_listelement_hashcode_fn) ssb_hasher, + (gl_listelement_dispose_fn) ssb_free, + false); + visited = + hash_initialize (32, NULL, (Hash_hasher) visited_hasher, + (Hash_comparator) visited_comparator, + (Hash_data_freer) search_state_free); + ssb_append (initial); + time_t start = time (NULL); + bool assurance_printed = false; + search_state *stage3result = NULL; + counterexample *cex = NULL; + while (gl_list_size (ssb_queue) > 0) + { + const search_state_bundle *ssb = gl_list_get_at (ssb_queue, 0); + + search_state *ss = NULL; + for (gl_list_iterator_t it = gl_list_iterator (ssb->states); + search_state_list_next (&it, &ss); + ) + { + if (trace_flag & trace_cex) + search_state_print (ss); + // Stage 1/2 completing the rules containing the conflicts + parse_state *ps1 = ss->states[0]; + parse_state *ps2 = ss->states[1]; + if (parse_state_depth (ps1) < 0 && parse_state_depth (ps2) < 0) + { + // Stage 3: reduce and shift conflict items completed. + const state_item *si1src = parse_state_head (ps1); + const state_item *si2src = parse_state_head (ps2); + if (item_rule (si1src->item)->lhs == item_rule (si2src->item)->lhs + && have_common_prefix (si1src->item, si2src->item)) + { + // Stage 4: both paths share a prefix + derivation *d1 = parse_state_derivation (ps1); + derivation *d2 = parse_state_derivation (ps2); + if (parse_state_derivation_completed (ps1) + && parse_state_derivation_completed (ps2)) + { + // Once we have two derivations for the same symbol, + // we've found a unifying counterexample. + cex = new_counterexample (d1, d2, shift_reduce, true, false); + derivation_retain (d1); + derivation_retain (d2); + goto cex_search_end; + } + if (!stage3result) + stage3result = copy_search_state (ss); + } + } + if (TIME_LIMIT_ENFORCED) + { + float time_passed = difftime (time (NULL), start); + if (!assurance_printed && time_passed > ASSURANCE_LIMIT + && stage3result) + { + fputs ("Productions leading up to the conflict state found. " + "Still finding a possible unifying counterexample...", + stderr); + assurance_printed = true; + } + if (time_passed > time_limit) + { + fprintf (stderr, "time limit exceeded: %f\n", time_passed); + goto cex_search_end; + } + } + generate_next_states (ss, conflict1, conflict2); + } + gl_sortedlist_remove (ssb_queue, + (gl_listelement_compar_fn) ssb_comp, ssb); + } +cex_search_end:; + if (!cex) + { + // No unifying counterexamples + // If a search state from Stage 3 is available, use it + // to construct a more compact nonunifying counterexample. + if (stage3result) + cex = complete_diverging_examples (stage3result, next_sym, shift_reduce); + // Otherwise, construct a nonunifying counterexample that + // begins from the start state using the shortest + // lookahead-sensitive path to the reduce item. + else + cex = example_from_path (shift_reduce, itm2, reduce_path, next_sym); + } + gl_list_free (ssb_queue); + hash_free (visited); + if (stage3result) + search_state_free (stage3result); + return cex; +} + +static time_t cumulative_time; + +void +counterexample_init (void) +{ + /* Recognize $TIME_LIMIT. Not a public feature, just to help + debugging. If we need something public, a %define/-D/-F variable + would be more appropriate. */ + { + const char *cp = getenv ("TIME_LIMIT"); + if (cp) + { + char *end = NULL; + float v = strtof (cp, &end); + if (*end == '\0' && errno == 0) + time_limit = v; + } + } + time (&cumulative_time); + scp_set = bitset_create (nstates, BITSET_FIXED); + rpp_set = bitset_create (nstates, BITSET_FIXED); + state_items_init (); +} + + +void +counterexample_free (void) +{ + if (scp_set) + { + bitset_free (scp_set); + bitset_free (rpp_set); + state_items_free (); + } +} + +/** + * Report a counterexample for conflict on symbol next_sym + * between the given state-items + */ +static void +counterexample_report (state_item_number itm1, state_item_number itm2, + symbol_number next_sym, bool shift_reduce, + FILE *out, const char *prefix) +{ + // Compute the shortest lookahead-sensitive path and associated sets of + // parser states. + state_item_list shortest_path = shortest_path_from_start (itm1, next_sym); + bool reduce_prod_reached = false; + const rule *reduce_rule = item_rule (state_items[itm1].item); + + bitset_zero (scp_set); + bitset_zero (rpp_set); + + state_item *si = NULL; + for (gl_list_iterator_t it = gl_list_iterator (shortest_path); + state_item_list_next (&it, &si); + ) + { + bitset_set (scp_set, si->state->number); + reduce_prod_reached = reduce_prod_reached + || item_rule (si->item) == reduce_rule; + if (reduce_prod_reached) + bitset_set (rpp_set, si->state->number); + } + time_t t = time (NULL); + counterexample *cex + = difftime (t, cumulative_time) < CUMULATIVE_TIME_LIMIT + ? unifying_example (itm1, itm2, shift_reduce, shortest_path, next_sym) + : example_from_path (shift_reduce, itm2, shortest_path, next_sym); + + gl_list_free (shortest_path); + counterexample_print (cex, out, prefix); + free_counterexample (cex); +} + + +// ITM1 denotes a shift, ITM2 a reduce. +static void +counterexample_report_shift_reduce (state_item_number itm1, state_item_number itm2, + symbol_number next_sym, + FILE *out, const char *prefix) +{ + if (out == stderr) + complain (NULL, Wcounterexamples, + _("shift/reduce conflict on token %s"), symbols[next_sym]->tag); + else + { + fputs (prefix, out); + fprintf (out, _("shift/reduce conflict on token %s"), symbols[next_sym]->tag); + fprintf (out, "%s\n", _(":")); + } + // In the report, print the items. + if (out != stderr || trace_flag & trace_cex) + { + state_item_print (&state_items[itm1], out, prefix); + state_item_print (&state_items[itm2], out, prefix); + } + counterexample_report (itm1, itm2, next_sym, true, out, prefix); +} + +static void +counterexample_report_reduce_reduce (state_item_number itm1, state_item_number itm2, + bitset conflict_syms, + FILE *out, const char *prefix) +{ + { + struct obstack obstack; + obstack_init (&obstack); + bitset_iterator biter; + state_item_number sym; + const char *sep = ""; + BITSET_FOR_EACH (biter, conflict_syms, sym, 0) + { + obstack_printf (&obstack, "%s%s", sep, symbols[sym]->tag); + sep = ", "; + } + char *tokens = obstack_finish0 (&obstack); + if (out == stderr) + complain (NULL, Wcounterexamples, + ngettext ("reduce/reduce conflict on token %s", + "reduce/reduce conflict on tokens %s", + bitset_count (conflict_syms)), + tokens); + else + { + fputs (prefix, out); + fprintf (out, + ngettext ("reduce/reduce conflict on token %s", + "reduce/reduce conflict on tokens %s", + bitset_count (conflict_syms)), + tokens); + fprintf (out, "%s\n", _(":")); + } + obstack_free (&obstack, NULL); + } + // In the report, print the items. + if (out != stderr || trace_flag & trace_cex) + { + state_item_print (&state_items[itm1], out, prefix); + state_item_print (&state_items[itm2], out, prefix); + } + counterexample_report (itm1, itm2, bitset_first (conflict_syms), + false, out, prefix); +} + +static state_item_number +find_state_item_number (const rule *r, state_number sn) +{ + for (state_item_number i = state_item_map[sn]; i < state_item_map[sn + 1]; ++i) + if (!SI_DISABLED (i) + && item_number_as_rule_number (*state_items[i].item) == r->number) + return i; + abort (); +} + +void +counterexample_report_state (const state *s, FILE *out, const char *prefix) +{ + const state_number sn = s->number; + const reductions *reds = s->reductions; + bitset lookaheads = bitset_create (ntokens, BITSET_FIXED); + for (int i = 0; i < reds->num; ++i) + { + const rule *r1 = reds->rules[i]; + const state_item_number c1 = find_state_item_number (r1, sn); + for (state_item_number c2 = state_item_map[sn]; c2 < state_item_map[sn + 1]; ++c2) + if (!SI_DISABLED (c2)) + { + item_number conf = *state_items[c2].item; + if (item_number_is_symbol_number (conf) + && bitset_test (reds->lookaheads[i], conf)) + counterexample_report_shift_reduce (c1, c2, conf, out, prefix); + } + for (int j = i+1; j < reds->num; ++j) + { + const rule *r2 = reds->rules[j]; + // Conflicts: common lookaheads. + bitset_intersection (lookaheads, + reds->lookaheads[i], + reds->lookaheads[j]); + if (!bitset_empty_p (lookaheads)) + for (state_item_number c2 = state_item_map[sn]; c2 < state_item_map[sn + 1]; ++c2) + if (!SI_DISABLED (c2) + && item_rule (state_items[c2].item) == r2) + { + counterexample_report_reduce_reduce (c1, c2, lookaheads, out, prefix); + break; + } + } + } + bitset_free (lookaheads); +} diff --git a/contrib/tools/bison/src/counterexample.h b/contrib/tools/bison/src/counterexample.h new file mode 100644 index 0000000000..8f833f3d91 --- /dev/null +++ b/contrib/tools/bison/src/counterexample.h @@ -0,0 +1,36 @@ +/* Conflict counterexample generation + + Copyright (C) 2020-2021 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef COUNTEREXAMPLE_H +# define COUNTEREXAMPLE_H + +# include "state.h" + +// Init/deinit this module. +void counterexample_init (void); +void counterexample_free (void); + +// Print the counterexamples for the conflicts of state S. +// +// Used both for the warnings on the terminal (OUT = stderr, PREFIX = +// ""), and for the reports (OUT != stderr, PREFIX != ""). +void +counterexample_report_state (const state *s, FILE *out, const char *prefix); + +#endif /* COUNTEREXAMPLE_H */ diff --git a/contrib/tools/bison/src/derivation.c b/contrib/tools/bison/src/derivation.c new file mode 100644 index 0000000000..4890db65dc --- /dev/null +++ b/contrib/tools/bison/src/derivation.c @@ -0,0 +1,438 @@ +/* Counterexample derivation trees + + Copyright (C) 2020-2021 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +#include "derivation.h" +#include "glyphs.h" + +#include <c-ctype.h> +#include <gl_linked_list.h> +#include <mbswidth.h> + +#include "system.h" +#include "complain.h" + +struct derivation +{ + symbol_number sym; + derivation_list children; + int reference_count; + // Color assigned for styling. Guarantees that the derivation is + // always displayed with the same color, independently of the order + // in which the derivations are traversed. + int color; +}; + +static derivation d_dot = { -1, NULL, -1, -1 }; + +derivation * +derivation_dot (void) +{ + return &d_dot; +} + +void +derivation_list_append (derivation_list dl, derivation *d) +{ + derivation_retain (d); + gl_list_add_last (dl, d); +} + +void +derivation_list_prepend (derivation_list dl, derivation *d) +{ + derivation_retain (d); + gl_list_add_first (dl, d); +} + +void derivation_list_free (derivation_list dl) +{ + derivation *d = NULL; + for (gl_list_iterator_t it = gl_list_iterator (dl); + derivation_list_next (&it, &d); + ) + if (d != &d_dot) + derivation_free (d); + gl_list_free (dl); +} + +derivation * +derivation_new (symbol_number sym, derivation_list children) +{ + derivation *res = xmalloc (sizeof *res); + res->sym = sym; + res->children = children; + res->reference_count = 0; + res->color = -1; + return res; +} + +void +derivation_retain (derivation *d) +{ + ++d->reference_count; +} + +void +derivation_free (derivation *d) +{ + if (!d) + return; + derivation_list free_queue = + gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, + 1, (const void **)&d); + while (gl_list_size (free_queue) > 0) + { + derivation *deriv = (derivation *) gl_list_get_at (free_queue, 0); + if (--deriv->reference_count == 0) + { + if (deriv->children) + { + derivation *child = NULL; + for (gl_list_iterator_t it = gl_list_iterator (deriv->children); + derivation_list_next (&it, &child); + ) + if (child != &d_dot) + gl_list_add_last (free_queue, child); + gl_list_free (deriv->children); + } + free (deriv); + } + gl_list_remove_at (free_queue, 0); + } + gl_list_free (free_queue); +} + +size_t +derivation_size (const derivation *deriv) +{ + if (!deriv->children) + return 1; + int size = 1; + derivation *child = NULL; + for (gl_list_iterator_t it = gl_list_iterator (deriv->children); + derivation_list_next (&it, &child); + ) + size += derivation_size (child); + return size; +} + + +// Longest distance from root to leaf. +static int +derivation_depth (const derivation *deriv) +{ + if (deriv->children) + { + // Children's depth cannot be 0, even if there are no children + // (the case of a derivation with an empty RHS). + int res = 1; + derivation *child; + for (gl_list_iterator_t it = gl_list_iterator (deriv->children); + derivation_list_next (&it, &child); + ) + res = max_int (res, derivation_depth (child)); + return res + 1; + } + else + return 1; +} + +static bool +all_spaces (const char *s) +{ + while (c_isspace (*s)) + s++; + return *s == '\0'; +} + +// Printing the derivation as trees without trailing spaces is +// painful: we cannot simply pad one "column" before moving to the +// next: +// +// exp +// ↳ x1 e1 foo1 x1 +// ↳ x2 ↳ ε ↳ foo2 ↳ x2 +// ↳ x3 ↳ foo3 ↳ x3 +// ↳ "X" • ↳ x1 foo4 ↳ "X" +// ↳ x2 ↳ "quuux" +// ↳ x3 +// ↳ "X" +// +// It's hard for a column to know that it's "last" to decide whether +// to output the right-padding or not. So when we need to pad on the +// right to complete a column, we don't output the spaces, we +// accumulate the width of padding in *PADDING. +// +// Each time we actually print something (non space), we flush that +// padding. When we _don't_ print something, its width is added to +// the current padding. +// +// This function implements this. +// +// When COND is true, put S on OUT, preceded by *PADDING white spaces. +// Otherwise add the width to *PADDING. Return the width of S. +static int +fputs_if (bool cond, FILE *out, int *padding, const char *s) +{ + int res = mbswidth (s, 0); + if (cond && !all_spaces (s)) + { + fprintf (out, "%*s%s", *padding, "", s); + *padding = 0; + } + else + { + *padding += res; + } + return res; +} + +// The width taken to report this derivation recursively down to its +// leaves. +static int +derivation_width (const derivation *deriv) +{ + if (deriv->children) + { + const symbol *sym = symbols[deriv->sym]; + int self_width = mbswidth (sym->tag, 0); + + // Arrow and space. + int children_width = down_arrow_width; + if (gl_list_size (deriv->children) == 0) + // Empty rhs. + children_width += empty_width; + else + { + derivation *child; + for (gl_list_iterator_t it = gl_list_iterator (deriv->children); + derivation_list_next (&it, &child); + ) + children_width + += derivation_separator_width + derivation_width (child); + // No separator at the beginning. + children_width -= derivation_separator_width; + } + return max_int (self_width, children_width); + } + else if (deriv == &d_dot) + { + return dot_width; + } + else // leaf. + { + const symbol *sym = symbols[deriv->sym]; + return mbswidth (sym->tag, 0); + } +} + + +// Print DERIV for DEPTH. +// +// The tree is printed from top to bottom with DEPTH ranging from 0 to +// the total depth of the tree. DERIV should only printed when we +// reach its depth, i.e., then DEPTH is 0. +// +// When DEPTH is 1 and we're on a subderivation, then we print the RHS +// of the derivation (in DEPTH 0 we printed its LHS). +// +// Return the "logical printed" width. We might have not have reached +// that width, in which case the missing spaces are in *PADDING. +static int +derivation_print_tree_impl (const derivation *deriv, FILE *out, + int depth, int *padding) +{ + const int width = derivation_width (deriv); + + int res = 0; + if (deriv->children) + { + const symbol *sym = symbols[deriv->sym]; + char style[20]; + snprintf (style, 20, "cex-%d", deriv->color); + + if (depth == 0 || depth == 1) + { + begin_use_class (style, out); + begin_use_class ("cex-step", out); + } + if (depth == 0) + { + res += fputs_if (true, out, padding, sym->tag); + } + else + { + res += fputs_if (depth == 1, out, padding, down_arrow); + if (gl_list_size (deriv->children) == 0) + // Empty rhs. + res += fputs_if (depth == 1, out, padding, empty); + else + { + bool first = true; + derivation *child; + for (gl_list_iterator_t it = gl_list_iterator (deriv->children); + derivation_list_next (&it, &child); + ) + { + if (!first) + res += fputs_if (depth == 1, out, padding, derivation_separator); + res += derivation_print_tree_impl (child, out, depth - 1, padding); + first = false; + } + } + } + if (depth == 0 || depth == 1) + { + end_use_class ("cex-step", out); + end_use_class (style, out); + } + *padding += width - res; + res = width; + } + else if (deriv == &d_dot) + { + if (depth == 0) + begin_use_class ("cex-dot", out); + res += fputs_if (depth == 0, out, padding, dot); + if (depth == 0) + end_use_class ("cex-dot", out); + } + else // leaf. + { + const symbol *sym = symbols[deriv->sym]; + if (depth == 0) + begin_use_class ("cex-leaf", out); + res += fputs_if (depth == 0, out, padding, sym->tag); + if (depth == 0) + end_use_class ("cex-leaf", out); + } + return res; +} + +static void +derivation_print_tree (const derivation *deriv, FILE *out, const char *prefix) +{ + fputc ('\n', out); + for (int depth = 0, max_depth = derivation_depth (deriv); + depth < max_depth; ++depth) + { + int padding = 0; + fprintf (out, " %s", prefix); + derivation_print_tree_impl (deriv, out, depth, &padding); + fputc ('\n', out); + } +} + + +/* Print DERIV, colored according to COUNTER. + Return false if nothing is printed. */ +static bool +derivation_print_flat_impl (derivation *deriv, FILE *out, + bool leaves_only, + int *counter, const char *prefix) +{ + if (deriv->children) + { + const symbol *sym = symbols[deriv->sym]; + deriv->color = *counter; + ++*counter; + char style[20]; + snprintf (style, 20, "cex-%d", deriv->color); + begin_use_class (style, out); + + if (!leaves_only) + { + fputs (prefix, out); + begin_use_class ("cex-step", out); + fprintf (out, "%s %s [ ", sym->tag, arrow); + end_use_class ("cex-step", out); + prefix = ""; + } + bool res = false; + derivation *child; + for (gl_list_iterator_t it = gl_list_iterator (deriv->children); + derivation_list_next (&it, &child); + ) + { + if (derivation_print_flat_impl (child, out, + leaves_only, counter, prefix)) + { + prefix = " "; + res = true; + } + else if (!leaves_only) + prefix = " "; + } + if (!leaves_only) + { + begin_use_class ("cex-step", out); + if (res) + fputs (" ]", out); + else + fputs ("]", out); + end_use_class ("cex-step", out); + } + end_use_class (style, out); + return res; + } + else if (deriv == &d_dot) + { + fputs (prefix, out); + begin_use_class ("cex-dot", out); + fputs (dot, out); + end_use_class ("cex-dot", out); + } + else // leaf. + { + fputs (prefix, out); + const symbol *sym = symbols[deriv->sym]; + begin_use_class ("cex-leaf", out); + fprintf (out, "%s", sym->tag); + end_use_class ("cex-leaf", out); + } + return true; +} + +static void +derivation_print_flat (const derivation *deriv, FILE *out, const char *prefix) +{ + int counter = 0; + fputs (prefix, out); + derivation_print_flat_impl ((derivation *)deriv, out, false, &counter, ""); + fputc ('\n', out); +} + +void +derivation_print_leaves (const derivation *deriv, FILE *out) +{ + int counter = 0; + derivation_print_flat_impl ((derivation *)deriv, out, true, &counter, ""); + fputc ('\n', out); +} + +void +derivation_print (const derivation *deriv, FILE *out, const char *prefix) +{ + if (getenv ("YYFLAT")) + derivation_print_flat (deriv, out, prefix); + else + derivation_print_tree (deriv, out, prefix); +} diff --git a/contrib/tools/bison/src/derivation.h b/contrib/tools/bison/src/derivation.h new file mode 100644 index 0000000000..6fa1b08ccf --- /dev/null +++ b/contrib/tools/bison/src/derivation.h @@ -0,0 +1,74 @@ +/* Counterexample derivation trees + + Copyright (C) 2020-2021 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef DERIVATION_H +# define DERIVATION_H + +# include <gl_linked_list.h> +# include <gl_xlist.h> + +# include "gram.h" + +/* Derivations are trees of symbols such that each nonterminal's + children are symbols that produce that nonterminal if they are + relevant to the counterexample. The leaves of a derivation form a + counterexample when printed. */ + +typedef gl_list_t derivation_list; +typedef struct derivation derivation; + +static inline derivation_list derivation_list_new (void) +{ + return gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true); +} + +static inline bool +derivation_list_next (gl_list_iterator_t *it, derivation **d) +{ + const void *p = NULL; + bool res = gl_list_iterator_next (it, &p, NULL); + if (res) + *d = (derivation *) p; + else + gl_list_iterator_free (it); + return res; +} + +void derivation_list_append (derivation_list dl, derivation *d); +void derivation_list_prepend (derivation_list dl, derivation *d); +void derivation_list_free (derivation_list dl); + +derivation *derivation_new (symbol_number sym, derivation_list children); + +static inline derivation *derivation_new_leaf (symbol_number sym) +{ + return derivation_new (sym, NULL); +} + +// Number of symbols. +size_t derivation_size (const derivation *deriv); +void derivation_print (const derivation *deriv, FILE *out, const char *prefix); +void derivation_print_leaves (const derivation *deriv, FILE *out); +void derivation_free (derivation *deriv); +void derivation_retain (derivation *deriv); + +// A derivation denoting the position of the dot. +derivation *derivation_dot (void); + +#endif /* DERIVATION_H */ diff --git a/contrib/tools/bison/src/derives.c b/contrib/tools/bison/src/derives.c index c859a5e23d..4ea5f78bb4 100644 --- a/contrib/tools/bison/src/derives.c +++ b/contrib/tools/bison/src/derives.c @@ -1,6 +1,6 @@ /* Match rules with nonterminals for bison, - Copyright (C) 1984, 1989, 2000-2003, 2005, 2009-2015, 2018-2020 Free + Copyright (C) 1984, 1989, 2000-2003, 2005, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> #include "system.h" @@ -47,7 +47,7 @@ print_derives (void) fprintf (stderr, " %s derives\n", symbols[i]->tag); for (rule **rp = derives[i - ntokens]; *rp; ++rp) { - fprintf (stderr, " %3d ", (*rp)->user_number); + fprintf (stderr, " %3d ", (*rp)->code); rule_rhs_print (*rp, stderr); fprintf (stderr, "\n"); } @@ -62,7 +62,7 @@ derives_compute (void) { /* DSET[NTERM - NTOKENS] -- A linked list of the numbers of the rules whose LHS is NTERM. */ - rule_list **dset = xcalloc (nvars, sizeof *dset); + rule_list **dset = xcalloc (nnterms, sizeof *dset); /* DELTS[RULE] -- There are NRULES rule number to attach to nterms. Instead of performing NRULES allocations for each, have an array @@ -82,9 +82,9 @@ derives_compute (void) /* DSET contains what we need under the form of a linked list. Make it a single array. */ - derives = xnmalloc (nvars, sizeof *derives); + derives = xnmalloc (nnterms, sizeof *derives); /* Q is the storage for DERIVES[...] (DERIVES[0] = q). */ - rule **q = xnmalloc (nvars + nrules, sizeof *q); + rule **q = xnmalloc (nnterms + nrules, sizeof *q); for (symbol_number i = ntokens; i < nsyms; ++i) { diff --git a/contrib/tools/bison/src/derives.h b/contrib/tools/bison/src/derives.h index 33430e6ff5..0c28a41bb8 100644 --- a/contrib/tools/bison/src/derives.h +++ b/contrib/tools/bison/src/derives.h @@ -1,6 +1,6 @@ /* Match rules with nonterminals for bison, - Copyright (C) 1984, 1989, 2000-2002, 2009-2015, 2018-2020 Free + Copyright (C) 1984, 1989, 2000-2002, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef DERIVES_H_ # define DERIVES_H_ diff --git a/contrib/tools/bison/src/files.c b/contrib/tools/bison/src/files.c index d383a0ede0..b4f57e656e 100644 --- a/contrib/tools/bison/src/files.c +++ b/contrib/tools/bison/src/files.c @@ -1,6 +1,6 @@ /* Open and close files for Bison. - Copyright (C) 1984, 1986, 1989, 1992, 2000-2015, 2018-2020 Free + Copyright (C) 1984, 1986, 1989, 1992, 2000-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,19 +16,24 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> #include "system.h" #include <configmake.h> /* PKGDATADIR */ -#include <error.h> #include <dirname.h> +#include <error.h> #include <get-errno.h> +#include <gl_array_list.h> +#include <gl_xlist.h> #include <quote.h> #include <quotearg.h> #include <relocatable.h> /* relocate2 */ #include <stdio-safer.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> #include <xstrndup.h> #include "complain.h" @@ -52,6 +57,7 @@ char *spec_verbose_file = NULL; /* for --verbose. */ char *spec_graph_file = NULL; /* for -g. */ char *spec_xml_file = NULL; /* for -x. */ char *spec_header_file = NULL; /* for --defines. */ +char *spec_mapped_header_file = NULL; char *parser_file_name; /* All computed output file names. */ @@ -70,7 +76,7 @@ static int generated_files_size = 0; uniqstr grammar_file = NULL; /* If --output=dir/foo.c was specified, - DIR_PREFIX is 'dir/' and ALL_BUT_EXT and ALL_BUT_TAB_EXT are 'dir/foo'. + DIR_PREFIX gis 'dir/' and ALL_BUT_EXT and ALL_BUT_TAB_EXT are 'dir/foo'. If --output=dir/foo.tab.c was specified, DIR_PREFIX is 'dir/', ALL_BUT_EXT is 'dir/foo.tab', and ALL_BUT_TAB_EXT is 'dir/foo'. @@ -88,11 +94,20 @@ uniqstr grammar_file = NULL; char *all_but_ext; static char *all_but_tab_ext; char *dir_prefix; +char *mapped_dir_prefix; /* C source file extension (the parser source). */ static char *src_extension = NULL; /* Header file extension (if option '`-d'' is specified). */ static char *header_extension = NULL; + +struct prefix_map +{ + char *oldprefix; + char *newprefix; +}; + +static gl_list_t prefix_maps = NULL; /*-----------------------------------------------------------------. | Return a newly allocated string composed of the concatenation of | @@ -160,6 +175,70 @@ xfdopen (int fd, char const *mode) return res; } +/* Given an input file path, returns a dynamically allocated string that + contains the path with the file prefix mapping rules applied, or NULL if + the input was NULL. */ +char * +map_file_name (char const *filename) +{ + if (!filename) + return NULL; + + struct prefix_map const *p = NULL; + if (prefix_maps) + { + void const *ptr; + gl_list_iterator_t iter = gl_list_iterator (prefix_maps); + while (gl_list_iterator_next (&iter, &ptr, NULL)) + { + p = ptr; + if (strncmp (p->oldprefix, filename, strlen (p->oldprefix)) == 0) + break; + p = NULL; + } + gl_list_iterator_free (&iter); + } + + if (!p) + return xstrdup (filename); + + size_t oldprefix_len = strlen (p->oldprefix); + size_t newprefix_len = strlen (p->newprefix); + char *s = xmalloc (newprefix_len + strlen (filename) - oldprefix_len + 1); + + char *end = stpcpy (s, p->newprefix); + stpcpy (end, filename + oldprefix_len); + + return s; +} + +static void +prefix_map_free (struct prefix_map *p) +{ + free (p->oldprefix); + free (p->newprefix); + free (p); +} + +/* Adds a new file prefix mapping. If a file path starts with oldprefix, it + will be replaced with newprefix */ +void +add_prefix_map (char const *oldprefix, char const *newprefix) +{ + if (!prefix_maps) + prefix_maps = gl_list_create_empty (GL_ARRAY_LIST, + /* equals */ NULL, + /* hashcode */ NULL, + (gl_listelement_dispose_fn) prefix_map_free, + true); + + struct prefix_map *p = xmalloc (sizeof (*p)); + p->oldprefix = xstrdup (oldprefix); + p->newprefix = xstrdup (newprefix); + + gl_list_add_last (prefix_maps, p); +} + /*------------------------------------------------------------------. | Compute ALL_BUT_EXT, ALL_BUT_TAB_EXT and output files extensions. | `------------------------------------------------------------------*/ @@ -370,6 +449,9 @@ compute_output_file_names (void) output_file_name_check (&spec_verbose_file, false); } + spec_mapped_header_file = map_file_name (spec_header_file); + mapped_dir_prefix = map_file_name (dir_prefix); + free (all_but_tab_ext); free (src_extension); free (header_extension); @@ -431,6 +513,23 @@ pkgdatadir (void) } } +char const * +m4path (void) +{ + char const *m4 = getenv ("M4"); + if (m4) + return m4; + + /* We don't use relocate2() to store the temporary buffer and re-use + it, because m4path() is only called once. */ + char const *m4_relocated = relocate (M4); + struct stat buf; + if (stat (m4_relocated, &buf) == 0) + return m4_relocated; + + return M4; +} + void output_file_names_free (void) { @@ -439,10 +538,15 @@ output_file_names_free (void) free (spec_graph_file); free (spec_xml_file); free (spec_header_file); + free (spec_mapped_header_file); free (parser_file_name); free (dir_prefix); + free (mapped_dir_prefix); for (int i = 0; i < generated_files_size; i++) free (generated_files[i].name); free (generated_files); free (relocate_buffer); + + if (prefix_maps) + gl_list_free (prefix_maps); } diff --git a/contrib/tools/bison/src/files.h b/contrib/tools/bison/src/files.h index 00814ad051..5b2a118d4c 100644 --- a/contrib/tools/bison/src/files.h +++ b/contrib/tools/bison/src/files.h @@ -1,6 +1,6 @@ /* File names and variables for bison, - Copyright (C) 1984, 1989, 2000-2002, 2006-2007, 2009-2015, 2018-2020 + Copyright (C) 1984, 1989, 2000-2002, 2006-2007, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef FILES_H_ # define FILES_H_ @@ -50,9 +50,15 @@ extern char *spec_xml_file; /* File name specified with --defines. */ extern char *spec_header_file; +/* File name specified with --defines, adjusted for mapped prefixes. */ +extern char *spec_mapped_header_file; + /* Directory prefix of output file names. */ extern char *dir_prefix; +/* Directory prefix of output file name, adjusted for mapped prefixes. */ +extern char *mapped_dir_prefix; + /* The file name as given on the command line. Not named "input_file" because Flex uses this name for an argument, and therefore GCC warns about a name clash. */ @@ -64,6 +70,9 @@ extern char *all_but_ext; /* Where our data files are installed. */ char const *pkgdatadir (void); +/* Where the m4 program is installed. */ +char const *m4path (void); + void compute_output_file_names (void); void output_file_names_free (void); @@ -82,4 +91,7 @@ FILE *xfopen (const char *name, char const *mode); void xfclose (FILE *ptr); FILE *xfdopen (int fd, char const *mode); +char *map_file_name (char const *filename); +void add_prefix_map (char const *oldprefix, char const *newprefix); + #endif /* !FILES_H_ */ diff --git a/contrib/tools/bison/src/fixits.c b/contrib/tools/bison/src/fixits.c index 2c900254d3..3467cdaed7 100644 --- a/contrib/tools/bison/src/fixits.c +++ b/contrib/tools/bison/src/fixits.c @@ -1,6 +1,6 @@ /* Support for fixing grammar files. - Copyright (C) 2019-2020 Free Software Foundation, Inc. + Copyright (C) 2019-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -15,25 +15,25 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> #include "fixits.h" -#include "system.h" +#include <error.h> +#include <get-errno.h> +#include <gl_array_list.h> +#include <gl_xlist.h> +#include <progname.h> +#include <quote.h> +#include <quotearg.h> +#include <vasnprintf.h> -#include "error.h" -#include "get-errno.h" -#include "getargs.h" -#include "gl_array_list.h" -#include "gl_xlist.h" -#include "progname.h" -#include "quote.h" -#include "quotearg.h" -#include "vasnprintf.h" +#include "system.h" #include "files.h" +#include "getargs.h" typedef struct { @@ -68,7 +68,7 @@ fixit_free (fixit *f) /* GCC and Clang follow the same pattern. https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Message-Formatting-Options.html - http://clang.llvm.org/docs/UsersManual.html#cmdoption-fdiagnostics-parseable-fixits */ + https://clang.llvm.org/docs/UsersManual.html#cmdoption-fdiagnostics-parseable-fixits */ static void fixit_print (fixit const *f, FILE *out) { diff --git a/contrib/tools/bison/src/fixits.h b/contrib/tools/bison/src/fixits.h index f79217a3d3..46440a3499 100644 --- a/contrib/tools/bison/src/fixits.h +++ b/contrib/tools/bison/src/fixits.h @@ -1,6 +1,6 @@ /* Support for fixing grammar files. - Copyright (C) 2019-2020 Free Software Foundation, Inc. + Copyright (C) 2019-2021 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -13,7 +13,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef FIXITS_H_ # define FIXITS_H_ 1 diff --git a/contrib/tools/bison/src/flex-scanner.h b/contrib/tools/bison/src/flex-scanner.h index 6f6861741a..238ca88117 100644 --- a/contrib/tools/bison/src/flex-scanner.h +++ b/contrib/tools/bison/src/flex-scanner.h @@ -1,6 +1,6 @@ /* Common parts between scan-code.l, scan-gram.l, and scan-skel.l. - Copyright (C) 2006, 2009-2015, 2018-2020 Free Software Foundation, + Copyright (C) 2006, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef FLEX_PREFIX # error "FLEX_PREFIX not defined" @@ -94,22 +94,33 @@ int FLEX_PREFIX (lex_destroy) (void); keep (to construct ID, STRINGS etc.). Use the following macros to use it. - Use STRING_GROW to append what has just been matched, and - STRING_FINISH to end the string (it puts the ending 0). - STRING_FINISH also stores this string in LAST_STRING, which can be - used, and which is used by STRING_FREE to free the last string. */ + Use STRING_GROW () to append what has just been matched, and + STRING_FINISH () to end the string (it puts the ending 0). + STRING_FINISH () also stores this string in LAST_STRING, which can be + used, and which is used by STRING_FREE () to free the last string. */ #ifndef FLEX_NO_OBSTACK static struct obstack obstack_for_string; -# define STRING_GROW \ +# define STRING_GROW() \ obstack_grow (&obstack_for_string, yytext, yyleng) -# define STRING_FINISH \ +# define STRING_FINISH() \ (last_string = obstack_finish0 (&obstack_for_string)) -# define STRING_FREE \ +# define STRING_1GROW(Char) \ + obstack_1grow (&obstack_for_string, Char) + +# ifdef NDEBUG +# define STRING_FREE() \ obstack_free (&obstack_for_string, last_string) +# else +# define STRING_FREE() \ + do { \ + obstack_free (&obstack_for_string, last_string); \ + last_string = NULL; \ + } while (0) +# endif #endif diff --git a/contrib/tools/bison/src/getargs.c b/contrib/tools/bison/src/getargs.c index 55884d345b..c0864255d5 100644 --- a/contrib/tools/bison/src/getargs.c +++ b/contrib/tools/bison/src/getargs.c @@ -1,6 +1,6 @@ /* Parse command line arguments for Bison. - Copyright (C) 1984, 1986, 1989, 1992, 2000-2015, 2018-2020 Free + Copyright (C) 1984, 1986, 1989, 1992, 2000-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> #include "getargs.h" @@ -151,8 +151,8 @@ flags_argmatch (const char *opt, */ #define FLAGS_ARGMATCH(FlagName, Args, All) \ flags_argmatch ("--" #FlagName, \ - (xargmatch_fn*) argmatch_## FlagName ## _value, \ - argmatch_## FlagName ## _usage, \ + (xargmatch_fn*) argmatch_## FlagName ## _value, \ + argmatch_ ## FlagName ## _usage, \ All, &FlagName ## _flag, Args) /*---------------------. @@ -206,23 +206,26 @@ ARGMATCH_DEFINE_GROUP (report, enum report) static const argmatch_report_doc argmatch_report_docs[] = { - { "states", N_("describe the states") }, - { "itemsets", N_("complete the core item sets with their closure") }, - { "lookaheads", N_("explicitly associate lookahead tokens to items") }, - { "solved", N_("describe shift/reduce conflicts solving") }, - { "all", N_("include all the above information") }, - { "none", N_("disable the report") }, + { "states", N_("describe the states") }, + { "itemsets", N_("complete the core item sets with their closure") }, + { "lookaheads", N_("explicitly associate lookahead tokens to items") }, + { "solved", N_("describe shift/reduce conflicts solving") }, + { "counterexamples", N_("generate conflict counterexamples") }, + { "all", N_("include all the above information") }, + { "none", N_("disable the report") }, { NULL, NULL }, }; static const argmatch_report_arg argmatch_report_args[] = { - { "none", report_none }, - { "states", report_states }, - { "itemsets", report_states | report_itemsets }, - { "lookaheads", report_states | report_lookahead_tokens }, - { "solved", report_states | report_solved_conflicts }, - { "all", report_all }, + { "none", report_none }, + { "states", report_states }, + { "itemsets", report_states | report_itemsets }, + { "lookaheads", report_states | report_lookaheads }, + { "solved", report_states | report_solved_conflicts }, + { "counterexamples", report_cex }, + { "cex", report_cex }, + { "all", report_all }, { NULL, report_none }, }; @@ -262,6 +265,7 @@ static const argmatch_trace_doc argmatch_trace_docs[] = { "skeleton", "skeleton postprocessing" }, { "time", "time consumption" }, { "ielr", "IELR conversion" }, + { "cex", "counterexample generation"}, { "all", "all of the above" }, { NULL, NULL}, }; @@ -285,6 +289,7 @@ static const argmatch_trace_arg argmatch_trace_args[] = { "skeleton", trace_skeleton }, { "time", trace_time }, { "ielr", trace_ielr }, + { "cex", trace_cex }, { "all", trace_all }, { NULL, trace_none}, }; @@ -339,7 +344,8 @@ const argmatch_feature_group_type argmatch_feature_group = | Display the help message and exit STATUS. | `-------------------------------------------*/ -static void usage (int) ATTRIBUTE_NORETURN; + _Noreturn +static void usage (int); static void usage (int status) @@ -420,15 +426,17 @@ Tuning the Parser:\n\ * won't assume that -d also takes an argument. */ fputs (_("\ Output Files:\n\ - --defines[=FILE] also produce a header file\n\ - -d likewise but cannot specify FILE (for POSIX Yacc)\n\ - -r, --report=THINGS also produce details on the automaton\n\ - --report-file=FILE write report to FILE\n\ - -v, --verbose same as '--report=state'\n\ - -b, --file-prefix=PREFIX specify a PREFIX for output files\n\ - -o, --output=FILE leave output to FILE\n\ - -g, --graph[=FILE] also output a graph of the automaton\n\ - -x, --xml[=FILE] also output an XML report of the automaton\n\ + --defines[=FILE] also produce a header file\n\ + -d likewise but cannot specify FILE (for POSIX Yacc)\n\ + -r, --report=THINGS also produce details on the automaton\n\ + --report-file=FILE write report to FILE\n\ + -v, --verbose same as '--report=state'\n\ + -b, --file-prefix=PREFIX specify a PREFIX for output files\n\ + -o, --output=FILE leave output to FILE\n\ + -g, --graph[=FILE] also output a graph of the automaton\n\ + -x, --xml[=FILE] also output an XML report of the automaton\n\ + -M, --file-prefix-map=OLD=NEW replace prefix OLD with NEW when writing file paths\n\ + in output files\n\ "), stdout); putc ('\n', stdout); @@ -438,7 +446,7 @@ Output Files:\n\ printf (_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT); printf (_("%s home page: <%s>.\n"), PACKAGE_NAME, PACKAGE_URL); fputs (_("General help using GNU software: " - "<http://www.gnu.org/gethelp/>.\n"), + "<https://www.gnu.org/gethelp/>.\n"), stdout); #if (defined __GLIBC__ && __GLIBC__ >= 2) && !defined __UCLIBC__ @@ -447,13 +455,12 @@ Output Files:\n\ man page. */ const char *lc_messages = setlocale (LC_MESSAGES, NULL); if (lc_messages && !STREQ (lc_messages, "en_")) - /* TRANSLATORS: Replace LANG_CODE in this URL with your language - code <http://translationproject.org/team/LANG_CODE.html> to - form one of the URLs at http://translationproject.org/team/. + /* TRANSLATORS: Replace LANG_CODE in this URL with your language code to + form one of the URLs at https://translationproject.org/team/. Otherwise, replace the entire URL with your translation team's email address. */ fputs (_("Report translation bugs to " - "<http://translationproject.org/team/>.\n"), stdout); + "<https://translationproject.org/team/>.\n"), stdout); #endif fputs (_("For complete documentation, run: info bison.\n"), stdout); } @@ -549,6 +556,7 @@ static char const short_options[] = "h" "k" "l" + "M:" "o:" "p:" "r:" @@ -600,14 +608,15 @@ static struct option const long_options[] = { "yacc", no_argument, 0, 'y' }, /* Output Files. */ - { "defines", optional_argument, 0, 'd' }, - { "report", required_argument, 0, 'r' }, - { "report-file", required_argument, 0, REPORT_FILE_OPTION }, - { "verbose", no_argument, 0, 'v' }, - { "file-prefix", required_argument, 0, 'b' }, - { "output", required_argument, 0, 'o' }, - { "graph", optional_argument, 0, 'g' }, - { "xml", optional_argument, 0, 'x' }, + { "defines", optional_argument, 0, 'd' }, + { "report", required_argument, 0, 'r' }, + { "report-file", required_argument, 0, REPORT_FILE_OPTION }, + { "verbose", no_argument, 0, 'v' }, + { "file-prefix", required_argument, 0, 'b' }, + { "output", required_argument, 0, 'o' }, + { "graph", optional_argument, 0, 'g' }, + { "xml", optional_argument, 0, 'x' }, + { "file-prefix-map", required_argument, 0, 'M' }, /* Hidden. */ { "fixed-output-files", no_argument, 0, FIXED_OUTPUT_FILES_OPTION }, @@ -713,6 +722,22 @@ getargs (int argc, char *argv[]) language_argmatch (optarg, command_line_prio, loc); break; + case 'M': // -MOLDPREFIX=NEWPREFIX + { + char *newprefix = strchr (optarg, '='); + if (newprefix) + { + *newprefix = '\0'; + add_prefix_map (optarg, newprefix + 1); + } + else + { + complain (&loc, complaint, _("invalid argument for %s: %s"), + quote ("--file-prefix-map"), quotearg_n (1, optarg)); + } + } + break; + case 'S': skeleton_arg (optarg, command_line_prio, loc); break; @@ -862,7 +887,7 @@ getargs (int argc, char *argv[]) void tr (char *s, char from, char to) { - for (; *s; s++) + for (; *s; ++s) if (*s == from) *s = to; } diff --git a/contrib/tools/bison/src/getargs.h b/contrib/tools/bison/src/getargs.h index c1629ab558..a02e7080d4 100644 --- a/contrib/tools/bison/src/getargs.h +++ b/contrib/tools/bison/src/getargs.h @@ -1,6 +1,6 @@ /* Parse command line arguments for bison. - Copyright (C) 1984, 1986, 1989, 1992, 2000-2015, 2018-2020 Free + Copyright (C) 1984, 1986, 1989, 1992, 2000-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef GETARGS_H_ # define GETARGS_H_ @@ -77,8 +77,9 @@ enum report report_none = 0, report_states = 1 << 0, report_itemsets = 1 << 1, - report_lookahead_tokens = 1 << 2, + report_lookaheads = 1 << 2, report_solved_conflicts = 1 << 3, + report_cex = 1 << 4, report_all = ~0 }; /** What appears in the *.output file. */ @@ -106,6 +107,7 @@ enum trace trace_ielr = 1 << 13, /**< IELR conversion. */ trace_closure = 1 << 14, /**< Input/output of closure(). */ trace_locations = 1 << 15, /**< Full display of locations. */ + trace_cex = 1 << 16, /**< Counterexample generation */ trace_all = ~0 /**< All of the above. */ }; /** What debug items bison displays during its run. */ diff --git a/contrib/tools/bison/src/glyphs.c b/contrib/tools/bison/src/glyphs.c new file mode 100644 index 0000000000..d93fd8e951 --- /dev/null +++ b/contrib/tools/bison/src/glyphs.c @@ -0,0 +1,93 @@ +/* Graphical symbols. + + Copyright (C) 2020-2021 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +#include "glyphs.h" + +#include <assert.h> +#include <attribute.h> +#include <stdbool.h> +#include <string.h> +#include <mbswidth.h> +#include <unicodeio.h> + + +glyph_buffer_t arrow; +int arrow_width; + +glyph_buffer_t down_arrow; +int down_arrow_width; + +glyph_buffer_t dot; +int dot_width; + +glyph_buffer_t empty; +int empty_width; + +const char *derivation_separator = " "; +int derivation_separator_width = 1; + +typedef struct +{ + glyph_buffer_t *pbuf; + const char *fallback; +} callback_arg_t; + + +static long +on_success (const char *buf, size_t buflen, void *callback_arg) +{ + callback_arg_t *arg = (callback_arg_t *) callback_arg; + assert (buflen + 1 < sizeof *arg->pbuf); + *stpncpy (*arg->pbuf, buf, buflen) = '\0'; + return 1; +} + +static long +on_failure (unsigned code MAYBE_UNUSED, const char *msg MAYBE_UNUSED, + void *callback_arg) +{ + callback_arg_t *arg = (callback_arg_t *) callback_arg; + assert (strlen (arg->fallback) + 1 < sizeof *arg->pbuf); + strcpy (*arg->pbuf, arg->fallback); + return 0; +} + +static bool +glyph_set (glyph_buffer_t *glyph, int *width, + unsigned code, const char *fallback) +{ + callback_arg_t arg = { glyph, fallback }; + int res = unicode_to_mb (code, on_success, on_failure, &arg); + *width = mbswidth (*glyph, 0); + return res; +} + +void +glyphs_init (void) +{ + glyph_set (&arrow, &arrow_width, 0x2192, "->"); + glyph_set (&dot, &dot_width, 0x2022, "."); + glyph_set (&down_arrow, &down_arrow_width, 0x21b3, "`->"); + glyph_set (&empty, &empty_width, 0x03b5, "%empty"); + + strncat (down_arrow, " ", sizeof down_arrow - strlen (down_arrow) - 1); + down_arrow_width += 1; +} diff --git a/contrib/tools/bison/src/glyphs.h b/contrib/tools/bison/src/glyphs.h new file mode 100644 index 0000000000..dbbd32c421 --- /dev/null +++ b/contrib/tools/bison/src/glyphs.h @@ -0,0 +1,50 @@ +/* Graphical symbols. + + Copyright (C) 2020-2021 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef GLYPHS_H +# define GLYPHS_H + +/* Initialize the following variables. */ +void glyphs_init (void); + +/* In gnulib/lib/unicodeio.h unicode_to_mb uses a buffer of 25 bytes. + In down_arrow, we append one space. */ +typedef char glyph_buffer_t[26]; + +/* "→", separates the lhs of a rule from its rhs. */ +extern glyph_buffer_t arrow; +extern int arrow_width; + +/* "•", a point in an item (aka, a dotted rule). */ +extern glyph_buffer_t dot; +extern int dot_width; + +/* "↳ ", below an lhs to announce the rhs. */ +extern glyph_buffer_t down_arrow; +extern int down_arrow_width; + +/* "ε", an empty rhs. */ +extern glyph_buffer_t empty; +extern int empty_width; + +/* " ", separate symbols in the rhs of a derivation. */ +extern const char *derivation_separator; +extern int derivation_separator_width; + +#endif /* GLYPHS_H */ diff --git a/contrib/tools/bison/src/gram.c b/contrib/tools/bison/src/gram.c index 6202b82a73..71e65eda3b 100644 --- a/contrib/tools/bison/src/gram.c +++ b/contrib/tools/bison/src/gram.c @@ -1,6 +1,6 @@ /* Allocate input grammar variables for Bison. - Copyright (C) 1984, 1986, 1989, 2001-2003, 2005-2015, 2018-2020 Free + Copyright (C) 1984, 1986, 1989, 2001-2003, 2005-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,13 +16,14 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> #include "system.h" #include "complain.h" #include "getargs.h" +#include "glyphs.h" #include "gram.h" #include "print-xml.h" #include "reader.h" @@ -40,25 +41,14 @@ rule_number nrules = 0; symbol **symbols = NULL; int nsyms = 0; int ntokens = 1; -int nvars = 0; +int nnterms = 0; symbol_number *token_translations = NULL; -int max_user_token_number = 256; +int max_code = 256; int required_version = 0; -rule const * -item_rule (item_number const *item) -{ - item_number const *sp = item; - while (0 <= *sp) - ++sp; - rule_number r = item_number_as_rule_number (*sp); - return &rules[r]; -} - - void item_print (item_number *item, rule const *previous_rule, FILE *out) { @@ -67,7 +57,7 @@ item_print (item_number *item, rule const *previous_rule, FILE *out) for (item_number *sp = r->rhs; sp < item; sp++) fprintf (out, " %s", symbols[*sp]->tag); - fputs (" .", out); + fprintf (out, " %s", dot); if (0 <= *r->rhs) for (item_number *sp = item; 0 <= *sp; ++sp) fprintf (out, " %s", symbols[*sp]->tag); @@ -202,10 +192,10 @@ grammar_rules_partial_print (FILE *out, const char *title, if (first) fprintf (out, "%s\n\n", title); else if (previous_rule && previous_rule->lhs != rules[r].lhs) - fputc ('\n', out); + putc ('\n', out); first = false; rule_print (&rules[r], previous_rule, out); - fputc ('\n', out); + putc ('\n', out); previous_rule = &rules[r]; } if (!first) @@ -251,15 +241,25 @@ grammar_rules_print_xml (FILE *out, int level) xml_puts (out, level + 1, "<rules/>"); } +static void +section (FILE *out, const char *s) +{ + fprintf (out, "%s\n", s); + for (int i = strlen (s); 0 < i; --i) + putc ('-', out); + putc ('\n', out); + putc ('\n', out); +} + void grammar_dump (FILE *out, const char *title) { fprintf (out, "%s\n\n", title); fprintf (out, - "ntokens = %d, nvars = %d, nsyms = %d, nrules = %d, nritems = %d\n\n", - ntokens, nvars, nsyms, nrules, nritems); + "ntokens = %d, nnterms = %d, nsyms = %d, nrules = %d, nritems = %d\n\n", + ntokens, nnterms, nsyms, nrules, nritems); - fprintf (out, "Tokens\n------\n\n"); + section (out, "Tokens"); { fprintf (out, "Value Sprec Sassoc Tag\n"); @@ -271,7 +271,7 @@ grammar_dump (FILE *out, const char *title) fprintf (out, "\n\n"); } - fprintf (out, "Non terminals\n-------------\n\n"); + section (out, "Nonterminals"); { fprintf (out, "Value Tag\n"); @@ -281,7 +281,7 @@ grammar_dump (FILE *out, const char *title) fprintf (out, "\n\n"); } - fprintf (out, "Rules\n-----\n\n"); + section (out, "Rules"); { fprintf (out, "Num (Prec, Assoc, Useful, UselessChain) Lhs" @@ -303,17 +303,17 @@ grammar_dump (FILE *out, const char *title) /* Dumped the RHS. */ for (item_number *rhsp = rule_i->rhs; 0 <= *rhsp; ++rhsp) fprintf (out, " %3d", *rhsp); - fputc ('\n', out); + putc ('\n', out); } } fprintf (out, "\n\n"); - fprintf (out, "Rules interpreted\n-----------------\n\n"); + section (out, "Rules interpreted"); for (rule_number r = 0; r < nrules + nuseless_productions; ++r) { fprintf (out, "%-5d %s:", r, rules[r].lhs->symbol->tag); rule_rhs_print (&rules[r], out); - fputc ('\n', out); + putc ('\n', out); } fprintf (out, "\n\n"); } diff --git a/contrib/tools/bison/src/gram.h b/contrib/tools/bison/src/gram.h index afae95a78b..dd649f5d68 100644 --- a/contrib/tools/bison/src/gram.h +++ b/contrib/tools/bison/src/gram.h @@ -1,6 +1,6 @@ /* Data definitions for internal representation of Bison's input. - Copyright (C) 1984, 1986, 1989, 1992, 2001-2007, 2009-2015, 2018-2020 + Copyright (C) 1984, 1986, 1989, 1992, 2001-2007, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,16 +16,16 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef GRAM_H_ # define GRAM_H_ /* Representation of the grammar rules: - NTOKENS is the number of tokens, and NVARS is the number of + NTOKENS is the number of tokens, and NNTERMS is the number of variables (nonterminals). NSYMS is the total number, ntokens + - nvars. + nnterms. Each symbol (either token or variable) receives a symbol number. Numbers 0 to NTOKENS - 1 are for tokens, and NTOKENS to NSYMS - 1 @@ -101,6 +101,8 @@ Associativities are recorded similarly in SYMBOLS[I]->assoc. */ +# include "system.h" + # include "location.h" # include "symtab.h" @@ -109,13 +111,17 @@ extern int nsyms; extern int ntokens; -extern int nvars; +extern int nnterms; +/* Elements of ritem. */ typedef int item_number; # define ITEM_NUMBER_MAX INT_MAX extern item_number *ritem; extern int nritems; +/* Indices into ritem. */ +typedef unsigned int item_index; + /* There is weird relationship between OT1H item_number and OTOH symbol_number and rule_number: we store the latter in item_number. symbol_number values are stored as-is, while @@ -173,7 +179,7 @@ typedef struct { /* The number of the rule in the source. It is usually the index in RULES too, except if there are useless rules. */ - rule_number user_number; + rule_number code; /* The index in RULES. Usually the rule number in the source, except if some rules are useless. */ @@ -210,7 +216,15 @@ extern rule *rules; extern rule_number nrules; /* Get the rule associated to this item. ITEM points inside RITEM. */ -rule const *item_rule (item_number const *item); +static inline rule const * +item_rule (item_number const *item) +{ + item_number const *sp = item; + while (!item_number_is_rule_number (*sp)) + ++sp; + rule_number r = item_number_as_rule_number (*sp); + return &rules[r]; +} /* Pretty-print this ITEM (as in the report). ITEM points inside RITEM. PREVIOUS_RULE is used to see if the lhs is common, in which @@ -262,7 +276,7 @@ extern symbol **symbols; by the user's yylex routine, it yields the internal token number used by the parser and throughout bison. */ extern symbol_number *token_translations; -extern int max_user_token_number; +extern int max_code; diff --git a/contrib/tools/bison/src/graphviz.c b/contrib/tools/bison/src/graphviz.c index 80a2ff99dd..b1a3bdb399 100644 --- a/contrib/tools/bison/src/graphviz.c +++ b/contrib/tools/bison/src/graphviz.c @@ -1,6 +1,6 @@ /* Output Graphviz specification of a state machine generated by Bison. - Copyright (C) 2006-2007, 2009-2015, 2018-2020 Free Software + Copyright (C) 2006-2007, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ /* Written by Paul Eggert and Satya Kiran Popuri. */ @@ -72,18 +72,20 @@ output_edge (int source, int destination, char const *label, { fprintf (fout, " %d -> %d [style=%s", source, destination, style); if (label) - fprintf (fout, " label=%s", quote (label)); + { + fputs (" label=\"", fout); + for (const char *cp = label; *cp; ++cp) + switch (*cp) + { + case '"': fputs ("\\\"", fout); break; + case '\\': fputs ("\\\\", fout); break; + default: fputc (*cp, fout); break; + } + fputc ('"', fout); + } fputs ("]\n", fout); } -char const * -escape (char const *name) -{ - char *q = quote (name); - q[strlen (q) - 1] = '\0'; - return q + 1; -} - static void no_reduce_bitset_init (state const *s, bitset *no_reduce_set) { @@ -149,7 +151,7 @@ print_token (struct obstack *out, bool first, char const *tok) { if (! first) obstack_sgrow (out, ", "); - obstack_sgrow (out, escape (tok)); + obstack_backslash (out, tok); return false; } @@ -182,9 +184,9 @@ output_red (state const *s, reductions const *reds, FILE *fout) bool firste = true; rule_number ruleno = reds->rules[j]->number; - if (reds->lookahead_tokens) + if (reds->lookaheads) for (int i = 0; i < ntokens; i++) - if (bitset_test (reds->lookahead_tokens[j], i)) + if (bitset_test (reds->lookaheads[j], i)) { if (bitset_test (no_reduce_set, i)) firstd = print_token (&dout, firstd, symbols[i]->tag); diff --git a/contrib/tools/bison/src/graphviz.h b/contrib/tools/bison/src/graphviz.h index 06b4235866..51fd65dc0c 100644 --- a/contrib/tools/bison/src/graphviz.h +++ b/contrib/tools/bison/src/graphviz.h @@ -1,6 +1,6 @@ /* Output Graphviz specification of a state machine generated by Bison. - Copyright (C) 2006, 2010-2015, 2018-2020 Free Software Foundation, + Copyright (C) 2006, 2010-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ /* Written by Paul Eggert and Satya Kiran Popuri. */ @@ -63,10 +63,4 @@ void output_red (state const *s, reductions const *reds, FILE *fout); */ void finish_graph (FILE *fout); -/** Escape a lookahead token. - * - * \param name the token. - */ -char const *escape (char const *name); - #endif /* ! GRAPHVIZ_H_ */ diff --git a/contrib/tools/bison/src/ielr.c b/contrib/tools/bison/src/ielr.c index 8e34b2cc32..8814e657ce 100644 --- a/contrib/tools/bison/src/ielr.c +++ b/contrib/tools/bison/src/ielr.c @@ -1,6 +1,6 @@ /* IELR main implementation. - Copyright (C) 2009-2015, 2018-2020 Free Software Foundation, Inc. + Copyright (C) 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -15,13 +15,14 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> -#include "system.h" #include "ielr.h" +#include "system.h" + #include <bitset.h> #include <timevar.h> @@ -230,7 +231,7 @@ ielr_compute_follow_kernel_items (bitset ritem_sees_lookahead_set, for (goto_number i = 0; i < ngotos; ++i) { size_t nitems = states[from_state[i]]->nitems; - item_number *items = states[from_state[i]]->items; + item_index *items = states[from_state[i]]->items; for (size_t j = 0; j < nitems; ++j) /* If this item has this goto and if all subsequent symbols in this RHS (if any) are nullable nonterminals, then record this item as @@ -318,7 +319,7 @@ static state *** ielr_compute_predecessors (void) { int *predecessor_counts = xnmalloc (nstates, sizeof *predecessor_counts); - state ***result = xnmalloc (nstates, sizeof *result); + state ***res = xnmalloc (nstates, sizeof *res); for (state_number i = 0; i < nstates; ++i) predecessor_counts[i] = 0; for (state_number i = 0; i < nstates; ++i) @@ -326,18 +327,18 @@ ielr_compute_predecessors (void) ++predecessor_counts[states[i]->transitions->states[j]->number]; for (state_number i = 0; i < nstates; ++i) { - result[i] = xnmalloc (predecessor_counts[i]+1, sizeof *result[i]); - result[i][predecessor_counts[i]] = NULL; + res[i] = xnmalloc (predecessor_counts[i]+1, sizeof *res[i]); + res[i][predecessor_counts[i]] = NULL; predecessor_counts[i] = 0; } for (state_number i = 0; i < nstates; ++i) for (int j = 0; j < states[i]->transitions->num; ++j) { state_number k = states[i]->transitions->states[j]->number; - result[k][predecessor_counts[k]++] = states[i]; + res[k][predecessor_counts[k]++] = states[i]; } free (predecessor_counts); - return result; + return res; } /** @@ -417,19 +418,12 @@ ielr_item_has_lookahead (state *s, symbol_number lhs, size_t item, /* If the LHS symbol of this item isn't known (because this is a top-level invocation), go get it. */ if (!lhs) - { - int i; - for (i = s->items[item]; - !item_number_is_rule_number (ritem[i]); - ++i) - continue; - lhs = rules[item_number_as_rule_number (ritem[i])].lhs->number; - } + lhs = item_rule (&ritem[s->items[item]])->lhs->number; /* If this kernel item is next to the beginning of the RHS, then check all predecessors' goto follows for the LHS. */ if (item_number_is_rule_number (ritem[s->items[item] - 2])) { - aver (lhs != accept->content->number); + aver (lhs != acceptsymbol->content->number); for (state **predecessor = predecessors[s->number]; *predecessor; ++predecessor) @@ -632,17 +626,10 @@ ielr_compute_lookaheads (bitsetv follow_kernel_items, bitsetv always_follows, && !bitset_empty_p (lookahead_filter[t_item])) { if (item_number_is_rule_number (ritem[t->items[t_item] - 2])) - { - int rule_item; - for (rule_item = t->items[t_item]; - !item_number_is_rule_number (ritem[rule_item]); - ++rule_item) - ; - ielr_compute_goto_follow_set ( - follow_kernel_items, always_follows, s, - rules[item_number_as_rule_number (ritem[rule_item])].lhs, - lookaheads[t_item]); - } + ielr_compute_goto_follow_set ( + follow_kernel_items, always_follows, s, + item_rule (&ritem[t->items[t_item]])->lhs, + lookaheads[t_item]); else if (s->lookaheads) { /* We don't have to start the s item search at the beginning @@ -709,15 +696,17 @@ ielr_compute_state (bitsetv follow_kernel_items, bitsetv always_follows, /* Determine whether there's an isocore of t with which these lookaheads can be merged. */ { - AnnotationIndex ai; - AnnotationList *a; if (annotation_lists) - for (ai = 0, a = annotation_lists[lr0_isocore->state->number]; + { + AnnotationIndex ai; + AnnotationList *a; + for (ai = 0, a = annotation_lists[lr0_isocore->state->number]; a; ++ai, a = a->next) work1[ai] = AnnotationList__computeDominantContribution ( a, lr0_isocore->state->nitems, lookaheads, false); + } for (this_isocorep = &t->state_list; this_isocorep == &t->state_list || *this_isocorep != t->state_list; this_isocorep = &(*this_isocorep)->nextIsocore) @@ -726,6 +715,8 @@ ielr_compute_state (bitsetv follow_kernel_items, bitsetv always_follows, break; if (annotation_lists) { + AnnotationIndex ai; + AnnotationList *a; for (ai = 0, a = annotation_lists[lr0_isocore->state->number]; a; ++ai, a = a->next) @@ -789,15 +780,14 @@ ielr_compute_state (bitsetv follow_kernel_items, bitsetv always_follows, actually new. */ if (has_lookaheads) { - size_t i; if (!(*this_isocorep)->lookaheads) { (*this_isocorep)->lookaheads = xnmalloc (t->nitems, sizeof (*this_isocorep)->lookaheads); - for (i = 0; i < t->nitems; ++i) + for (size_t i = 0; i < t->nitems; ++i) (*this_isocorep)->lookaheads[i] = NULL; } - for (i = 0; i < t->nitems; ++i) + for (size_t i = 0; i < t->nitems; ++i) if (!bitset_empty_p (lookaheads[i])) { if (!(*this_isocorep)->lookaheads[i]) @@ -1030,12 +1020,12 @@ ielr_split_states (bitsetv follow_kernel_items, bitsetv always_follows, if (!node->state->consistent) { size_t i = 0; - item_number *itemset = node->state->items; + item_index *itemset = node->state->items; for (size_t r = 0; r < node->state->reductions->num; ++r) { rule *this_rule = node->state->reductions->rules[r]; bitset lookahead_set = - node->state->reductions->lookahead_tokens[r]; + node->state->reductions->lookaheads[r]; if (item_number_is_rule_number (*this_rule->rhs)) ielr_compute_goto_follow_set (follow_kernel_items, always_follows, node, diff --git a/contrib/tools/bison/src/ielr.h b/contrib/tools/bison/src/ielr.h index bb62625a06..e0dcf64132 100644 --- a/contrib/tools/bison/src/ielr.h +++ b/contrib/tools/bison/src/ielr.h @@ -1,6 +1,6 @@ /* IELR main implementation. - Copyright (C) 2009-2015, 2018-2020 Free Software Foundation, Inc. + Copyright (C) 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -15,7 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef IELR_H_ # define IELR_H_ diff --git a/contrib/tools/bison/src/lalr.c b/contrib/tools/bison/src/lalr.c index ee6c7cf6c2..f91bcbf20d 100644 --- a/contrib/tools/bison/src/lalr.c +++ b/contrib/tools/bison/src/lalr.c @@ -1,6 +1,6 @@ /* Compute lookahead criteria for Bison. - Copyright (C) 1984, 1986, 1989, 2000-2015, 2018-2020 Free Software + Copyright (C) 1984, 1986, 1989, 2000-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ /* Find which rules need lookahead in each state, and which lookahead @@ -99,7 +99,7 @@ void set_goto_map (void) { /* Count the number of gotos (ngotos) per nterm (goto_map). */ - goto_map = xcalloc (nvars + 1, sizeof *goto_map); + goto_map = xcalloc (nnterms + 1, sizeof *goto_map); ngotos = 0; for (state_number s = 0; s < nstates; ++s) { @@ -113,7 +113,7 @@ set_goto_map (void) } } - goto_number *temp_map = xnmalloc (nvars + 1, sizeof *temp_map); + goto_number *temp_map = xnmalloc (nnterms + 1, sizeof *temp_map); { goto_number k = 0; for (symbol_number i = ntokens; i < nsyms; ++i) @@ -256,9 +256,9 @@ lookback_find_state (int lookback_index) state *res = NULL; for (int j = 0; j < nstates; ++j) if (states[j]->reductions - && states[j]->reductions->lookahead_tokens) + && states[j]->reductions->lookaheads) { - if (states[j]->reductions->lookahead_tokens - LA > lookback_index) + if (states[j]->reductions->lookaheads - LA > lookback_index) /* Went too far. */ break; else @@ -280,7 +280,7 @@ lookback_print (FILE *out) { fprintf (out, " %3d = ", i); const state *s = lookback_find_state (i); - int rnum = i - (s->reductions->lookahead_tokens - LA); + int rnum = i - (s->reductions->lookaheads - LA); const rule *r = s->reductions->rules[rnum]; fprintf (out, "(%3d, ", s->number); rule_print (r, NULL, out); @@ -305,7 +305,7 @@ static void add_lookback_edge (state *s, rule const *r, goto_number gotono) { int ri = state_reduction_find (s, r); - int idx = (s->reductions->lookahead_tokens - LA) + ri; + int idx = (s->reductions->lookaheads - LA) + ri; lookback[idx] = goto_list_new (gotono, lookback[idx]); } @@ -421,7 +421,7 @@ compute_follows (void) static void -compute_lookahead_tokens (void) +compute_lookaheads (void) { if (trace_flag & trace_automaton) lookback_print (stderr); @@ -437,13 +437,12 @@ compute_lookahead_tokens (void) } -/*----------------------------------------------------. -| Count the number of lookahead tokens required for S | -| (N_LOOKAHEAD_TOKENS member). | -`----------------------------------------------------*/ +/*------------------------------------------------------. +| Count the number of lookahead tokens required for S. | +`------------------------------------------------------*/ static int -state_lookahead_tokens_count (state *s, bool default_reduction_only_for_accept) +state_lookaheads_count (state *s, bool default_reduction_only_for_accept) { const reductions *reds = s->reductions; const transitions *trans = s->transitions; @@ -473,9 +472,9 @@ state_lookahead_tokens_count (state *s, bool default_reduction_only_for_accept) } -/*----------------------------------------------------. -| Compute LA, NLA, and the lookahead_tokens members. | -`----------------------------------------------------*/ +/*----------------------------------------------. +| Compute LA, NLA, and the lookaheads members. | +`----------------------------------------------*/ void initialize_LA (void) @@ -491,25 +490,23 @@ initialize_LA (void) /* Compute the total number of reductions requiring a lookahead. */ nLA = 0; for (state_number i = 0; i < nstates; ++i) - nLA += - state_lookahead_tokens_count (states[i], - default_reduction_only_for_accept); + nLA += state_lookaheads_count (states[i], + default_reduction_only_for_accept); /* Avoid having to special case 0. */ if (!nLA) nLA = 1; bitsetv pLA = LA = bitsetv_create (nLA, ntokens, BITSET_FIXED); - /* Initialize the members LOOKAHEAD_TOKENS for each state whose reductions + /* Initialize the members LOOKAHEADS for each state whose reductions require lookahead tokens. */ for (state_number i = 0; i < nstates; ++i) { - int count = - state_lookahead_tokens_count (states[i], - default_reduction_only_for_accept); + int count = state_lookaheads_count (states[i], + default_reduction_only_for_accept); if (count) { - states[i]->reductions->lookahead_tokens = pLA; + states[i]->reductions->lookaheads = pLA; pLA += count; } } @@ -521,7 +518,7 @@ initialize_LA (void) `---------------------------------------------*/ static void -lookahead_tokens_print (FILE *out) +lookaheads_print (FILE *out) { fputs ("Lookaheads:\n", out); for (state_number i = 0; i < nstates; ++i) @@ -533,11 +530,11 @@ lookahead_tokens_print (FILE *out) for (int j = 0; j < reds->num; ++j) { fprintf (out, " rule %d:", reds->rules[j]->number); - if (reds->lookahead_tokens) + if (reds->lookaheads) { bitset_iterator iter; int k; - BITSET_FOR_EACH (iter, reds->lookahead_tokens[j], k, 0) + BITSET_FOR_EACH (iter, reds->lookaheads[j], k, 0) fprintf (out, " %s", symbols[k]->tag); } fputc ('\n', out); @@ -564,10 +561,10 @@ lalr (void) lookback = xcalloc (nLA, sizeof *lookback); build_relations (); compute_follows (); - compute_lookahead_tokens (); + compute_lookaheads (); if (trace_flag & trace_sets) - lookahead_tokens_print (stderr); + lookaheads_print (stderr); if (trace_flag & trace_automaton) { begin_use_class ("trace0", stderr); @@ -583,7 +580,7 @@ lalr_update_state_numbers (state_number old_to_new[], state_number nstates_old) { goto_number ngotos_reachable = 0; symbol_number nonterminal = 0; - aver (nsyms == nvars + ntokens); + aver (nsyms == nnterms + ntokens); for (goto_number i = 0; i < ngotos; ++i) { @@ -601,7 +598,7 @@ lalr_update_state_numbers (state_number old_to_new[], state_number nstates_old) ++ngotos_reachable; } } - while (nonterminal <= nvars) + while (nonterminal <= nnterms) { aver (ngotos == goto_map[nonterminal]); goto_map[nonterminal++] = ngotos_reachable; @@ -614,6 +611,6 @@ void lalr_free (void) { for (state_number s = 0; s < nstates; ++s) - states[s]->reductions->lookahead_tokens = NULL; + states[s]->reductions->lookaheads = NULL; bitsetv_free (LA); } diff --git a/contrib/tools/bison/src/lalr.h b/contrib/tools/bison/src/lalr.h index f94123a4bc..548c382ba8 100644 --- a/contrib/tools/bison/src/lalr.h +++ b/contrib/tools/bison/src/lalr.h @@ -1,7 +1,7 @@ /* Compute lookahead criteria for bison, Copyright (C) 1984, 1986, 1989, 2000, 2002, 2004, 2006-2007, - 2009-2015, 2018-2020 Free Software Foundation, Inc. + 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef LALR_H_ # define LALR_H_ diff --git a/contrib/tools/bison/src/location.c b/contrib/tools/bison/src/location.c index 3a31e0e710..a0c60e3872 100644 --- a/contrib/tools/bison/src/location.c +++ b/contrib/tools/bison/src/location.c @@ -1,6 +1,6 @@ /* Locations for Bison - Copyright (C) 2002, 2005-2015, 2018-2020 Free Software Foundation, + Copyright (C) 2002, 2005-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> #include "system.h" @@ -40,18 +40,6 @@ location const empty_loc = EMPTY_LOCATION_INIT; -static int -min_int (int a, int b) -{ - return a < b ? a : b; -} - -static int -max_int (int a, int b) -{ - return a >= b ? a : b; -} - /* The terminal width. Not less than 40. */ static int columns (void) @@ -167,7 +155,9 @@ int location_print (location loc, FILE *out) { int res = 0; - if (trace_flag & trace_locations) + if (location_empty (loc)) + res += fprintf (out, "(empty location)"); + else if (trace_flag & trace_locations) { res += boundary_print (&loc.start, out); res += fprintf (out, "-"); diff --git a/contrib/tools/bison/src/location.h b/contrib/tools/bison/src/location.h index d351cb0e3f..af21c70f5f 100644 --- a/contrib/tools/bison/src/location.h +++ b/contrib/tools/bison/src/location.h @@ -1,6 +1,6 @@ /* Locations for Bison - Copyright (C) 2002, 2004-2015, 2018-2020 Free Software Foundation, + Copyright (C) 2002, 2004-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef LOCATION_H_ # define LOCATION_H_ diff --git a/contrib/tools/bison/src/lr0.c b/contrib/tools/bison/src/lr0.c index 2ebdcf8a4d..b6dd79c019 100644 --- a/contrib/tools/bison/src/lr0.c +++ b/contrib/tools/bison/src/lr0.c @@ -1,6 +1,6 @@ /* Generate the LR(0) parser states for Bison. - Copyright (C) 1984, 1986, 1989, 2000-2002, 2004-2015, 2018-2020 Free + Copyright (C) 1984, 1986, 1989, 2000-2002, 2004-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ /* See comments in state.h for the data structures that represent it. @@ -49,7 +49,7 @@ static state_list *last_state = NULL; /* Print CORE for debugging. */ static void -core_print (size_t core_size, item_number *core, FILE *out) +core_print (size_t core_size, item_index *core, FILE *out) { for (int i = 0; i < core_size; ++i) { @@ -65,7 +65,7 @@ core_print (size_t core_size, item_number *core, FILE *out) `-----------------------------------------------------------------*/ static state * -state_list_append (symbol_number sym, size_t core_size, item_number *core) +state_list_append (symbol_number sym, size_t core_size, item_index *core) { state_list *node = xmalloc (sizeof *node); state *res = state_new (sym, core_size, core); @@ -86,7 +86,7 @@ state_list_append (symbol_number sym, size_t core_size, item_number *core) return res; } -/* Symbols that can be "shifted" (including non terminals) from the +/* Symbols that can be "shifted" (including nonterminals) from the current state. */ bitset shift_symbol; @@ -98,14 +98,14 @@ static rule **redset; static state **shiftset; -/* KERNEL_BASE[symbol-number] -> list of item numbers (offsets inside +/* KERNEL_BASE[symbol-number] -> list of item indices (offsets inside RITEM) of length KERNEL_SIZE[symbol-number]. */ -static item_number **kernel_base; +static item_index **kernel_base; static int *kernel_size; /* A single dimension array that serves as storage for KERNEL_BASE. */ -static item_number *kernel_items; +static item_index *kernel_items; static void @@ -257,7 +257,7 @@ new_itemsets (state *s) `--------------------------------------------------------------*/ static state * -get_state (symbol_number sym, size_t core_size, item_number *core) +get_state (symbol_number sym, size_t core_size, item_index *core) { if (trace_flag & trace_automaton) { @@ -394,7 +394,7 @@ generate_states (void) /* Create the initial state. The 0 at the lhs is the index of the item of this initial rule. */ - item_number initial_core = 0; + item_index initial_core = 0; state_list_append (0, 1, &initial_core); /* States are queued when they are created; process them all. */ diff --git a/contrib/tools/bison/src/lr0.h b/contrib/tools/bison/src/lr0.h index 31366dbdea..d105d6c96d 100644 --- a/contrib/tools/bison/src/lr0.h +++ b/contrib/tools/bison/src/lr0.h @@ -1,6 +1,6 @@ /* Generate the LR(0) parser states for Bison. - Copyright (C) 1984, 1986, 1989, 2000-2002, 2009-2015, 2018-2020 Free + Copyright (C) 1984, 1986, 1989, 2000-2002, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef LR0_H_ # define LR0_H_ diff --git a/contrib/tools/bison/src/lssi.c b/contrib/tools/bison/src/lssi.c new file mode 100644 index 0000000000..9b607a2f0d --- /dev/null +++ b/contrib/tools/bison/src/lssi.c @@ -0,0 +1,373 @@ +/* Lookahead sensitive state item searches for counterexample generation + + Copyright (C) 2020-2021 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +#include "lssi.h" + +#include <gl_linked_list.h> +#include <gl_xlist.h> +#include <stdlib.h> + +#include "getargs.h" +#include "nullable.h" + +// Lookahead sensitive state item. +typedef struct lssi +{ + state_item_number si; + struct lssi *parent; + // this is the precise lookahead set (follow_L from the CupEx paper) + bitset lookahead; + bool free_lookahead; +} lssi; + +static lssi * +new_lssi (state_item_number si, lssi *p, bitset l, bool free_l) +{ + lssi *res = xmalloc (sizeof *res); + res->si = si; + res->parent = p; + res->lookahead = l; + res->free_lookahead = free_l; + return res; +} + +static void +lssi_free (lssi *sn) +{ + if (sn == NULL) + return; + if (sn->free_lookahead) + bitset_free (sn->lookahead); + free (sn); +} + +static size_t +lssi_hasher (lssi *sn, size_t max) +{ + size_t hash = sn->si; + bitset_iterator biter; + symbol_number syn; + BITSET_FOR_EACH (biter, sn->lookahead, syn, 0) + hash += syn; + return hash % max; +} + +static bool +lssi_comparator (lssi *s1, lssi *s2) +{ + if (s1->si == s2->si) + { + if (s1->lookahead == s2->lookahead) + return true; + return bitset_equal_p (s1->lookahead, s2->lookahead); + } + return false; +} + +typedef gl_list_t lssi_list; + +static inline bool +append_lssi (lssi *sn, Hash_table *visited, lssi_list queue) +{ + if (hash_lookup (visited, sn)) + { + sn->free_lookahead = false; + lssi_free (sn); + return false; + } + hash_xinsert (visited, sn); + gl_list_add_last (queue, sn); + return true; +} + +#if 0 +static void +lssi_print (lssi *l) +{ + FILE *out = stderr; + print_state_item (&state_items[l->si], out); + if (l->lookahead) + { + fprintf (out, "FOLLOWL = { "); + bitset_iterator biter; + symbol_number sin; + BITSET_FOR_EACH (biter, l->lookahead, sin, 0) + fprintf (out, "%s, \n", symbols[sin]->tag); + fprintf (out, "}\n"); + } +} +#endif + +/** + * Compute the set of state-items that can reach the given conflict item via + * a combination of transitions or production steps. + */ +static bitset +eligible_state_items (state_item *target) +{ + bitset result = bitset_create (nstate_items, BITSET_FIXED); + state_item_list queue = + gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1, + (const void **) &target); + while (gl_list_size (queue) > 0) + { + state_item *si = (state_item *) gl_list_get_at (queue, 0); + gl_list_remove_at (queue, 0); + if (bitset_test (result, si - state_items)) + continue; + bitset_set (result, si - state_items); + // search all reverse edges. + bitset rsi = si->revs; + bitset_iterator biter; + state_item_number sin; + BITSET_FOR_EACH (biter, rsi, sin, 0) + gl_list_add_last (queue, &state_items[sin]); + } + gl_list_free (queue); + return result; +} + +/** + * Compute the shortest lookahead-sensitive path from the start state to + * this conflict. If optimized is true, only consider parser states + * that can reach the conflict state. + */ +state_item_list +shortest_path_from_start (state_item_number target, symbol_number next_sym) +{ + bitset eligible = eligible_state_items (&state_items[target]); + Hash_table *visited = hash_initialize (32, + NULL, + (Hash_hasher) lssi_hasher, + (Hash_comparator) lssi_comparator, + (Hash_data_freer) lssi_free); + bitset il = bitset_create (nsyms, BITSET_FIXED); + bitset_set (il, 0); + lssi *init = new_lssi (0, NULL, il, true); + lssi_list queue = gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, + NULL, true); + append_lssi (init, visited, queue); + // breadth-first search + bool finished = false; + lssi *n; + while (gl_list_size (queue) > 0) + { + n = (lssi *) gl_list_get_at (queue, 0); + gl_list_remove_at (queue, 0); + state_item_number last = n->si; + if (target == last && bitset_test (n->lookahead, next_sym)) + { + finished = true; + break; + } + state_item *si = &state_items[last]; + // Transitions don't change follow_L + if (si->trans >= 0) + { + if (bitset_test (eligible, si->trans)) + { + lssi *next = new_lssi (si->trans, n, n->lookahead, false); + append_lssi (next, visited, queue); + } + } + // For production steps, follow_L is based on the symbol after the + // nonterminal being produced. + // if no such symbol exists, follow_L is unchanged + // if the symbol is a terminal, follow_L only contains that terminal + // if the symbol is not nullable, follow_L is its FIRSTS set + // if the symbol is nullable, follow_L is its FIRSTS set unioned with + // this logic applied to the next symbol in the rule + if (si->prods) + { + // Compute follow_L as above + bitset lookahead = bitset_create (nsyms, BITSET_FIXED); + item_number *pos = si->item + 1; + for (; !item_number_is_rule_number (*pos); ++pos) + { + item_number it = *pos; + if (ISTOKEN (it)) + { + bitset_set (lookahead, it); + break; + } + else + { + bitset_union (lookahead, lookahead, FIRSTS (it)); + if (!nullable[it - ntokens]) + break; + } + } + if (item_number_is_rule_number (*pos)) + bitset_union (lookahead, n->lookahead, lookahead); + + bool lookahead_used = false; + // Try all possible production steps within this parser state. + bitset_iterator biter; + state_item_number nextSI; + BITSET_FOR_EACH (biter, si->prods, nextSI, 0) + { + if (!bitset_test (eligible, nextSI)) + continue; + lssi *next = new_lssi (nextSI, n, lookahead, + !lookahead_used); + lookahead_used = append_lssi (next, visited, queue) + || lookahead_used; + } + if (!lookahead_used) + bitset_free (lookahead); + } + } + + bitset_free (eligible); + if (!finished) + { + gl_list_free (queue); + fputs ("Cannot find shortest path to conflict state.", stderr); + abort (); + } + state_item_list res = + gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true); + for (lssi *sn = n; sn != NULL; sn = sn->parent) + gl_list_add_first (res, &state_items[sn->si]); + + hash_free (visited); + gl_list_free (queue); + + if (trace_flag & trace_cex) + { + fputs ("REDUCE ITEM PATH:\n", stderr); + gl_list_iterator_t it = gl_list_iterator (res); + const void *sip; + while (gl_list_iterator_next (&it, &sip, NULL)) + state_item_print ((state_item *) sip, stderr, ""); + } + return res; +} + +/** + * Determine if the given terminal is in the given symbol set or can begin + * a nonterminal in the given symbol set. + */ +bool +intersect_symbol (symbol_number sym, bitset syms) +{ + if (!syms) + return true; + bitset_iterator biter; + symbol_number sn; + BITSET_FOR_EACH (biter, syms, sn, 0) + { + if (sym == sn) + return true; + if (ISVAR (sn) && bitset_test (FIRSTS (sn), sym)) + return true; + } + return false; +} + +/** + * Determine if any symbol in ts is in syms + * or can begin a nonterminal syms. + */ +bool +intersect (bitset ts, bitset syms) +{ + if (!syms || !ts) + return true; + bitset_iterator biter; + symbol_number sn; + BITSET_FOR_EACH (biter, syms, sn, 0) + { + if (bitset_test (ts, sn)) + return true; + if (ISVAR (sn) && !bitset_disjoint_p (ts, FIRSTS (sn))) + return true; + } + return false; +} + + +/** + * Compute a list of state_items that have a production to n with respect + * to its lookahead + */ +state_item_list +lssi_reverse_production (const state_item *si, bitset lookahead) +{ + state_item_list result = + gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true); + if (SI_TRANSITION (si)) + return result; + // A production step was made to the current lalr_item. + // Check that the next symbol in the parent lalr_item is + // compatible with the lookahead. + bitset_iterator biter; + state_item_number sin; + BITSET_FOR_EACH (biter, si->revs, sin, 0) + { + state_item *prevsi = &state_items[sin]; + if (!production_allowed (prevsi, si)) + continue; + bitset prev_lookahead = prevsi->lookahead; + if (item_number_is_rule_number (*(prevsi->item))) + { + // reduce item + // Check that some lookaheads can be preserved. + if (!intersect (prev_lookahead, lookahead)) + continue; + } + else + { + // shift item + if (lookahead) + { + // Check that lookahead is compatible with the first + // possible symbols in the rest of the production. + // Alternatively, if the rest of the production is + // nullable, the lookahead must be compatible with + // the lookahead of the corresponding item. + bool applicable = false; + bool nlable = true; + for (item_number *pos = prevsi->item + 1; + !applicable && nlable && item_number_is_symbol_number (*pos); + ++pos) + { + symbol_number next_sym = item_number_as_symbol_number (*pos); + if (ISTOKEN (next_sym)) + { + applicable = intersect_symbol (next_sym, lookahead); + nlable = false; + } + else + { + applicable = intersect (FIRSTS (next_sym), lookahead); + if (!applicable) + nlable = nullable[next_sym - ntokens]; + } + } + if (!applicable && !nlable) + continue; + } + } + gl_list_add_last (result, prevsi); + } + return result; +} diff --git a/contrib/tools/bison/src/lssi.h b/contrib/tools/bison/src/lssi.h new file mode 100644 index 0000000000..e7feba3cee --- /dev/null +++ b/contrib/tools/bison/src/lssi.h @@ -0,0 +1,57 @@ +/* Lookahead sensitive state item searches for counterexample generation + + Copyright (C) 2020-2021 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef LSSI_H +# define LSSI_H + +# include "state-item.h" + +/* + All state-item graph nodes should also include a precise follow set (follow_L). + However, ignoring follow_L saves a lot of memory and is a pretty good approximation. + These functions exist to enforce restrictions caused by follow_L sets. + */ + +/* + * find shortest lookahead-sensitive path of state-items to target such that + * next_sym is in the follow_L set of target in that position. +*/ +state_item_list shortest_path_from_start (state_item_number target, + symbol_number next_sym); + +/** + * Determine if the given terminal is in the given symbol set or can begin + * a nonterminal in the given symbol set. + */ +bool intersect_symbol (symbol_number sym, bitset syms); + +/** + * Determine if any symbol in ts is in syms + * or can begin with a nonterminal in syms. + */ +bool intersect (bitset ts, bitset syms); + +/** + * Compute a set of sequences of state-items that can make production steps + * to this state-item such that the resulting possible lookahead symbols are + * as given. + */ +state_item_list lssi_reverse_production (const state_item *si, bitset lookahead); + +#endif /* LSSI_H */ diff --git a/contrib/tools/bison/src/main.c b/contrib/tools/bison/src/main.c index 9b93742787..63856fed1c 100644 --- a/contrib/tools/bison/src/main.c +++ b/contrib/tools/bison/src/main.c @@ -1,7 +1,7 @@ /* Top level entry point of Bison. Copyright (C) 1984, 1986, 1989, 1992, 1995, 2000-2002, 2004-2015, - 2018-2020 Free Software Foundation, Inc. + 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> #include "system.h" @@ -33,10 +33,12 @@ #include "complain.h" #include "conflicts.h" +#include "counterexample.h" #include "derives.h" #include "files.h" #include "fixits.h" #include "getargs.h" +#include "glyphs.h" #include "gram.h" #include "ielr.h" #include "lalr.h" @@ -44,6 +46,7 @@ #include "muscle-tab.h" #include "nullable.h" #include "output.h" +#include "parse-gram.h" #include "print-graph.h" #include "print-xml.h" #include "print.h" @@ -74,6 +77,7 @@ main (int argc, char *argv[]) atexit (close_stdout); + glyphs_init (); uniqstrs_new (); muscle_init (); complain_init (); @@ -135,6 +139,9 @@ main (int argc, char *argv[]) conflicts_update_state_numbers (old_to_new, nstates_old); free (old_to_new); } + if (report_flag & report_cex + || warning_is_enabled (Wcounterexamples)) + counterexample_init (); conflicts_print (); timevar_pop (tv_conflicts); @@ -208,11 +215,15 @@ main (int argc, char *argv[]) reduce_free (); conflicts_free (); grammar_free (); + counterexample_free (); output_file_names_free (); - /* The scanner memory cannot be released right after parsing, as it - contains things such as user actions, prologue, epilogue etc. */ + /* The scanner and parser memory cannot be released right after + parsing, as it contains things such as user actions, prologue, + epilogue etc. */ gram_scanner_free (); + parser_free (); + muscle_free (); code_scanner_free (); skel_scanner_free (); diff --git a/contrib/tools/bison/src/muscle-tab.c b/contrib/tools/bison/src/muscle-tab.c index 21443f4fe7..b610d0b8ae 100644 --- a/contrib/tools/bison/src/muscle-tab.c +++ b/contrib/tools/bison/src/muscle-tab.c @@ -1,6 +1,6 @@ /* Muscle table manager for Bison. - Copyright (C) 2001-2015, 2018-2020 Free Software Foundation, Inc. + Copyright (C) 2001-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -15,7 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> #include "system.h" @@ -107,8 +107,7 @@ muscle_entry_new (char const *key) res->key = key; res->value = NULL; res->storage = NULL; - if (!hash_insert (muscle_table, res)) - xalloc_die (); + hash_xinsert (muscle_table, res); return res; } @@ -128,9 +127,6 @@ muscle_init (void) muscle_table = hash_xinitialize (HT_INITIAL_CAPACITY, NULL, hash_muscle, hash_compare_muscles, muscle_entry_free); - - /* Version and input file. */ - MUSCLE_INSERT_STRING ("version", VERSION); } @@ -142,8 +138,7 @@ muscle_free (void) } /* Look for the muscle named KEY. Return NULL if does not exist. */ -static -muscle_entry * +static muscle_entry * muscle_lookup (char const *key) { muscle_entry probe; @@ -449,6 +444,7 @@ muscle_percent_variable_update (char const *variable, { "api.push_pull", "api.push-pull", muscle_keyword }, { "api.tokens.prefix", "api.token.prefix", muscle_code }, { "extends", "api.parser.extends", muscle_keyword }, + { "filename_type", "api.filename.type", muscle_code }, { "final", "api.parser.final", muscle_keyword }, { "implements", "api.parser.implements", muscle_keyword }, { "lex_symbol", "api.token.constructor", -1 }, @@ -457,6 +453,7 @@ muscle_percent_variable_update (char const *variable, { "lr.keep-unreachable-states", "lr.keep-unreachable-state", muscle_keyword }, { "lr.keep_unreachable_states", "lr.keep-unreachable-state", muscle_keyword }, { "namespace", "api.namespace", muscle_code }, + { "package", "api.package", muscle_code }, { "parser_class_name", "api.parser.class", muscle_code }, { "public", "api.parser.public", muscle_keyword }, { "strictfp", "api.parser.strictfp", muscle_keyword }, diff --git a/contrib/tools/bison/src/muscle-tab.h b/contrib/tools/bison/src/muscle-tab.h index a0dd2020a5..881782e7ba 100644 --- a/contrib/tools/bison/src/muscle-tab.h +++ b/contrib/tools/bison/src/muscle-tab.h @@ -1,6 +1,6 @@ /* Muscle table manager for Bison, - Copyright (C) 2001-2003, 2006-2015, 2018-2020 Free Software + Copyright (C) 2001-2003, 2006-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef MUSCLE_TAB_H_ # define MUSCLE_TAB_H_ diff --git a/contrib/tools/bison/src/named-ref.c b/contrib/tools/bison/src/named-ref.c index 6e639ac221..7524519d65 100644 --- a/contrib/tools/bison/src/named-ref.c +++ b/contrib/tools/bison/src/named-ref.c @@ -1,6 +1,6 @@ /* Named symbol references for Bison - Copyright (C) 2009-2015, 2018-2020 Free Software Foundation, Inc. + Copyright (C) 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -15,7 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> #include "system.h" diff --git a/contrib/tools/bison/src/named-ref.h b/contrib/tools/bison/src/named-ref.h index 250c713fa8..73429baad7 100644 --- a/contrib/tools/bison/src/named-ref.h +++ b/contrib/tools/bison/src/named-ref.h @@ -1,6 +1,6 @@ /* Named symbol references for Bison - Copyright (C) 2009-2015, 2018-2020 Free Software Foundation, Inc. + Copyright (C) 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -15,7 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef NAMED_REF_H_ # define NAMED_REF_H_ diff --git a/contrib/tools/bison/src/nullable.c b/contrib/tools/bison/src/nullable.c index 453b4e596b..7f0405d7a0 100644 --- a/contrib/tools/bison/src/nullable.c +++ b/contrib/tools/bison/src/nullable.c @@ -1,6 +1,6 @@ /* Calculate which nonterminals can expand into the null string for Bison. - Copyright (C) 1984, 1989, 2000-2006, 2009-2015, 2018-2020 Free + Copyright (C) 1984, 1989, 2000-2006, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ /* Set up NULLABLE, a vector saying which nonterminals can expand into @@ -36,7 +36,7 @@ typedef struct rule_list { struct rule_list *next; - rule *value; + const rule *value; } rule_list; bool *nullable = NULL; @@ -44,9 +44,8 @@ bool *nullable = NULL; static void nullable_print (FILE *out) { - int i; fputs ("NULLABLE\n", out); - for (i = ntokens; i < nsyms; i++) + for (int i = ntokens; i < nsyms; i++) fprintf (out, " %s: %s\n", symbols[i]->tag, nullable[i - ntokens] ? "yes" : "no"); fputs ("\n\n", out); @@ -55,68 +54,62 @@ nullable_print (FILE *out) void nullable_compute (void) { - rule_number ruleno; - symbol_number *s1; - symbol_number *s2; - rule_list *p; + nullable = xcalloc (nnterms, sizeof *nullable); - symbol_number *squeue = xnmalloc (nvars, sizeof *squeue); size_t *rcount = xcalloc (nrules, sizeof *rcount); /* RITEM contains all the rules, including useless productions. Hence we must allocate room for useless nonterminals too. */ - rule_list **rsets = xcalloc (nvars, sizeof *rsets); + rule_list **rsets = xcalloc (nnterms, sizeof *rsets); /* This is said to be more elements than we actually use. Supposedly NRITEMS - NRULES is enough. But why take the risk? */ - rule_list *relts = xnmalloc (nritems + nvars + 1, sizeof *relts); - - nullable = xcalloc (nvars, sizeof *nullable); - - s1 = s2 = squeue; - p = relts; - - for (ruleno = 0; ruleno < nrules; ++ruleno) - if (rules[ruleno].useful) - { - rule *rules_ruleno = &rules[ruleno]; - if (rules_ruleno->rhs[0] >= 0) - { - /* This rule has a non empty RHS. */ - item_number *rp = NULL; - bool any_tokens = false; - for (rp = rules_ruleno->rhs; *rp >= 0; ++rp) - if (ISTOKEN (*rp)) - any_tokens = true; - - /* This rule has only nonterminals: schedule it for the second - pass. */ - if (!any_tokens) - for (rp = rules_ruleno->rhs; *rp >= 0; ++rp) + rule_list *relts = xnmalloc (nritems + nnterms + 1, sizeof *relts); + + symbol_number *squeue = xnmalloc (nnterms, sizeof *squeue); + symbol_number *s2 = squeue; + { + rule_list *p = relts; + for (rule_number ruleno = 0; ruleno < nrules; ++ruleno) + if (rules[ruleno].useful) + { + const rule *r = &rules[ruleno]; + if (r->rhs[0] >= 0) + { + /* This rule has a non empty RHS. */ + bool any_tokens = false; + for (item_number *rp = r->rhs; *rp >= 0; ++rp) + if (ISTOKEN (*rp)) + any_tokens = true; + + /* This rule has only nonterminals: schedule it for the second + pass. */ + if (!any_tokens) + for (item_number *rp = r->rhs; *rp >= 0; ++rp) + { + rcount[ruleno]++; + p->next = rsets[*rp - ntokens]; + p->value = r; + rsets[*rp - ntokens] = p; + p++; + } + } + else + { + /* This rule has an empty RHS. */ + if (r->useful + && ! nullable[r->lhs->number - ntokens]) { - rcount[ruleno]++; - p->next = rsets[*rp - ntokens]; - p->value = rules_ruleno; - rsets[*rp - ntokens] = p; - p++; + nullable[r->lhs->number - ntokens] = true; + *s2++ = r->lhs->number; } - } - else - { - /* This rule has an empty RHS. */ - aver (item_number_as_rule_number (rules_ruleno->rhs[0]) - == ruleno); - if (rules_ruleno->useful - && ! nullable[rules_ruleno->lhs->number - ntokens]) - { - nullable[rules_ruleno->lhs->number - ntokens] = true; - *s2++ = rules_ruleno->lhs->number; - } - } - } + } + } + } + symbol_number *s1 = squeue; while (s1 < s2) - for (p = rsets[*s1++ - ntokens]; p; p = p->next) + for (rule_list *p = rsets[*s1++ - ntokens]; p; p = p->next) { - rule *r = p->value; + const rule *r = p->value; if (--rcount[r->number] == 0) if (r->useful && ! nullable[r->lhs->number - ntokens]) { diff --git a/contrib/tools/bison/src/nullable.h b/contrib/tools/bison/src/nullable.h index 236c50541d..38271730fe 100644 --- a/contrib/tools/bison/src/nullable.h +++ b/contrib/tools/bison/src/nullable.h @@ -1,6 +1,6 @@ /* Part of the bison parser generator, - Copyright (C) 2000, 2002, 2009-2015, 2018-2020 Free Software + Copyright (C) 2000, 2002, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef NULLABLE_H_ # define NULLABLE_H_ diff --git a/contrib/tools/bison/src/output.c b/contrib/tools/bison/src/output.c index e63c325492..de8e6a95fb 100644 --- a/contrib/tools/bison/src/output.c +++ b/contrib/tools/bison/src/output.c @@ -1,6 +1,6 @@ /* Output the generated parsing program for Bison. - Copyright (C) 1984, 1986, 1989, 1992, 2000-2015, 2018-2020 Free + Copyright (C) 1984, 1986, 1989, 1992, 2000-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,13 +16,14 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> #include "system.h" #include <filename.h> /* IS_PATH_WITH_DIR */ #include <get-errno.h> +#include <mbswidth.h> #include <path-join.h> #include <quotearg.h> #include <spawn-pipe.h> @@ -41,6 +42,7 @@ #include "scan-skel.h" #include "symtab.h" #include "tables.h" +#include "strversion.h" static struct obstack format_obstack; @@ -107,10 +109,8 @@ GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_state_number_table, state_number) `----------------------------------------------------------------*/ static void -quoted_output (FILE *out, char const *cp) +output_escaped (FILE *out, const char *cp) { - fprintf (out, "[["); - for (; *cp; cp++) switch (*cp) { @@ -120,7 +120,13 @@ quoted_output (FILE *out, char const *cp) case ']': fputs ("@}", out); break; default: fputc (*cp, out); break; } +} +static void +output_quoted (FILE *out, char const *cp) +{ + fprintf (out, "[["); + output_escaped (out, cp); fprintf (out, "]]"); } @@ -132,7 +138,7 @@ quoted_output (FILE *out, char const *cp) static void string_output (FILE *out, char const *string) { - quoted_output (out, quotearg_style (c_quoting_style, string)); + output_quoted (out, quotearg_style (c_quoting_style, string)); } @@ -193,9 +199,9 @@ static const char * symbol_tag (const symbol *sym) { const bool eof_is_user_defined - = !endtoken->alias || STRNEQ (endtoken->alias->tag, "$end"); + = !eoftoken->alias || STRNEQ (eoftoken->alias->tag, "$end"); - if (!eof_is_user_defined && sym->content == endtoken->content) + if (!eof_is_user_defined && sym->content == eoftoken->content) return "\"end of file\""; else if (sym->content == undeftoken->content) return "\"invalid token\""; @@ -232,7 +238,7 @@ prepare_symbol_names (char const *muscle_name) /* Width of the next token, including the two quotes, the comma and the space. */ int width - = strlen (cp) + 2 + = mbswidth (cp, 0) + 2 + (translatable ? strlen ("N_()") : 0); if (col + width > 75) @@ -244,7 +250,7 @@ prepare_symbol_names (char const *muscle_name) if (i) obstack_1grow (&format_obstack, ' '); if (translatable) - obstack_sgrow (&format_obstack, "]b4_symbol_translate(["); + obstack_sgrow (&format_obstack, "]b4_symbol_translate""(["); obstack_escape (&format_obstack, cp); if (translatable) obstack_sgrow (&format_obstack, "])["); @@ -272,14 +278,14 @@ static void prepare_symbols (void) { MUSCLE_INSERT_INT ("tokens_number", ntokens); - MUSCLE_INSERT_INT ("nterms_number", nvars); + MUSCLE_INSERT_INT ("nterms_number", nnterms); MUSCLE_INSERT_INT ("symbols_number", nsyms); - MUSCLE_INSERT_INT ("user_token_number_max", max_user_token_number); + MUSCLE_INSERT_INT ("code_max", max_code); muscle_insert_symbol_number_table ("translate", token_translations, token_translations[0], - 1, max_user_token_number + 1); + 1, max_code + 1); /* tname -- token names. */ prepare_symbol_names ("tname"); @@ -309,7 +315,7 @@ prepare_symbols (void) { int *values = xnmalloc (ntokens, sizeof *values); for (int i = 0; i < ntokens; ++i) - values[i] = symbols[i]->content->user_token_number; + values[i] = symbols[i]->content->code; muscle_insert_int_table ("toknum", values, values[0], 1, ntokens); free (values); @@ -475,6 +481,21 @@ symbol_numbers_output (FILE *out) `-------------------------------------------*/ static void +rule_output (const rule *r, FILE *out) +{ + output_escaped (out, r->lhs->symbol->tag); + fputc (':', out); + if (0 <= *r->rhs) + for (item_number *rhsp = r->rhs; 0 <= *rhsp; ++rhsp) + { + fputc (' ', out); + output_escaped (out, symbols[*rhsp]->tag); + } + else + fputs (" %empty", out); +} + +static void user_actions_output (FILE *out) { fputs ("m4_define([b4_actions], \n[", out); @@ -492,9 +513,11 @@ user_actions_output (FILE *out) string_output (out, rules[r].action_loc.start.file); fprintf (out, ")dnl\n"); } - fprintf (out, "[%*s%s]])\n\n", + fprintf (out, "[%*s%s]],\n[[", rules[r].action_loc.start.column - 1, "", rules[r].action); + rule_output (&rules[r], out); + fprintf (out, "]])\n\n"); } fputs ("])\n\n", out); } @@ -510,14 +533,8 @@ merger_output (FILE *out) int n; merger_list* p; for (n = 1, p = merge_functions; p != NULL; n += 1, p = p->next) - { - if (p->type[0] == '\0') - fprintf (out, " case %d: *yy0 = %s (*yy0, *yy1); break;\n", - n, p->name); - else - fprintf (out, " case %d: yy0->%s = %s (*yy0, *yy1); break;\n", - n, p->type, p->name); - } + fprintf (out, "]b4_call_merger""([%d], [%s], [%d])[\n", + n, p->name, p->sym->content->number); fputs ("]])\n\n", out); } @@ -532,7 +549,7 @@ prepare_symbol_definitions (void) /* Map "orig NUM" to new numbers. See data/README. */ for (symbol_number i = ntokens; i < nsyms + nuseless_nonterminals; ++i) { - obstack_printf (&format_obstack, "symbol(orig %d, number)", i); + obstack_printf (&format_obstack, "symbol""(orig %d, number)", i); const char *key = obstack_finish0 (&format_obstack); MUSCLE_INSERT_INT (key, nterm_map ? nterm_map[i - ntokens] : i); } @@ -543,12 +560,12 @@ prepare_symbol_definitions (void) const char *key; #define SET_KEY(Entry) \ - obstack_printf (&format_obstack, "symbol(%d, %s)", \ + obstack_printf (&format_obstack, "symbol""(%d, %s)", \ i, Entry); \ key = obstack_finish0 (&format_obstack); #define SET_KEY2(Entry, Suffix) \ - obstack_printf (&format_obstack, "symbol(%d, %s_%s)", \ + obstack_printf (&format_obstack, "symbol""(%d, %s_%s)", \ i, Entry, Suffix); \ key = obstack_finish0 (&format_obstack); @@ -565,8 +582,8 @@ prepare_symbol_definitions (void) SET_KEY ("tag"); MUSCLE_INSERT_STRING (key, symbol_tag (sym)); - SET_KEY ("user_number"); - MUSCLE_INSERT_INT (key, sym->content->user_token_number); + SET_KEY ("code"); + MUSCLE_INSERT_INT (key, sym->content->code); SET_KEY ("is_token"); MUSCLE_INSERT_INT (key, i < ntokens); @@ -682,7 +699,7 @@ static void output_skeleton (void) { /* Compute the names of the package data dir and skeleton files. */ - char const *m4 = (m4 = getenv ("M4")) ? m4 : M4; + char const *m4 = m4path (); char const *datadir = pkgdatadir (); char *skeldir = xpath_join (datadir, "skeletons"); char *m4sugar = xpath_join (datadir, "m4sugar/m4sugar.m4"); @@ -713,7 +730,7 @@ output_skeleton (void) extensions even when POSIXLY_CORRECT is set. See the thread starting at - <http://lists.gnu.org/archive/html/bug-bison/2008-07/msg00000.html> + <https://lists.gnu.org/r/bug-bison/2008-07/msg00000.html> for details. */ if (*M4_GNU_OPTION) argv[i++] = M4_GNU_OPTION; @@ -722,7 +739,7 @@ output_skeleton (void) argv[i++] = datadir; /* Some future version of GNU M4 (most likely 1.6) may treat the -dV in a position-dependent manner. See the thread starting at - <http://lists.gnu.org/archive/html/bug-bison/2008-07/msg00000.html> + <https://lists.gnu.org/r/bug-bison/2008-07/msg00000.html> for details. */ if (trace_flag & trace_m4_early) argv[i++] = "-dV"; @@ -785,6 +802,9 @@ prepare (void) char const *cp = getenv ("BISON_USE_PUSH_FOR_PULL"); bool use_push_for_pull_flag = cp && *cp && strtol (cp, 0, 10); + /* Versions. */ + MUSCLE_INSERT_STRING ("version_string", VERSION); + MUSCLE_INSERT_INT ("version", strversion_to_int (VERSION)); MUSCLE_INSERT_INT ("required_version", required_version); /* Flags. */ @@ -805,8 +825,10 @@ prepare (void) #define DEFINE(Name) MUSCLE_INSERT_STRING (#Name, Name ? Name : "") DEFINE (dir_prefix); + DEFINE (mapped_dir_prefix); DEFINE (parser_file_name); DEFINE (spec_header_file); + DEFINE (spec_mapped_header_file); DEFINE (spec_file_prefix); DEFINE (spec_graph_file); DEFINE (spec_name_prefix); diff --git a/contrib/tools/bison/src/output.h b/contrib/tools/bison/src/output.h index 641013063f..ed32fdc713 100644 --- a/contrib/tools/bison/src/output.h +++ b/contrib/tools/bison/src/output.h @@ -1,6 +1,6 @@ /* Output the generated parsing program for bison, - Copyright (C) 2000-2003, 2006-2007, 2009-2015, 2018-2020 Free + Copyright (C) 2000-2003, 2006-2007, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef OUTPUT_H_ # define OUTPUT_H_ diff --git a/contrib/tools/bison/src/parse-gram.c b/contrib/tools/bison/src/parse-gram.c index 9b1543cc67..c4dabc024b 100644 --- a/contrib/tools/bison/src/parse-gram.c +++ b/contrib/tools/bison/src/parse-gram.c @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 3.6.4. */ +/* A Bison parser, made by GNU Bison 3.7.6. */ /* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation, + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -45,11 +45,11 @@ define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ -/* Identify Bison output. */ -#define YYBISON 1 +/* Identify Bison output, and Bison version. */ +#define YYBISON 30706 -/* Bison version. */ -#define YYBISON_VERSION "3.6.4" +/* Bison version string. */ +#define YYBISON_VERSION "3.7.6" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -64,7 +64,7 @@ #define YYPULL 1 /* "%code top" blocks. */ -#line 27 "src/parse-gram.y" +#line 35 "src/parse-gram.y" /* On column 0 to please syntax-check. */ #include <config.h> @@ -151,7 +151,7 @@ enum yysymbol_kind_t YYSYMBOL_BRACED_CODE = 41, /* "{...}" */ YYSYMBOL_BRACED_PREDICATE = 42, /* "%?{...}" */ YYSYMBOL_BRACKETED_ID = 43, /* "[identifier]" */ - YYSYMBOL_CHAR = 44, /* "character literal" */ + YYSYMBOL_CHAR_LITERAL = 44, /* "character literal" */ YYSYMBOL_COLON = 45, /* ":" */ YYSYMBOL_EPILOGUE = 46, /* "epilogue" */ YYSYMBOL_EQUAL = 47, /* "=" */ @@ -164,7 +164,7 @@ enum yysymbol_kind_t YYSYMBOL_TAG = 54, /* "<tag>" */ YYSYMBOL_TAG_ANY = 55, /* "<*>" */ YYSYMBOL_TAG_NONE = 56, /* "<>" */ - YYSYMBOL_INT = 57, /* "integer literal" */ + YYSYMBOL_INT_LITERAL = 57, /* "integer literal" */ YYSYMBOL_PERCENT_PARAM = 58, /* "%param" */ YYSYMBOL_PERCENT_UNION = 59, /* "%union" */ YYSYMBOL_PERCENT_EMPTY = 60, /* "%empty" */ @@ -216,13 +216,11 @@ typedef enum yysymbol_kind_t yysymbol_kind_t; /* Unqualified %code blocks. */ -#line 33 "src/parse-gram.y" +#line 41 "src/parse-gram.y" #include "system.h" #include <c-ctype.h> - #include <errno.h> - #include <intprops.h> #include <quotearg.h> #include <vasnprintf.h> #include <xmemdup0.h> @@ -236,6 +234,11 @@ typedef enum yysymbol_kind_t yysymbol_kind_t; #include "reader.h" #include "scan-code.h" #include "scan-gram.h" + #include "strversion.h" + + /* Pretend to be at least that version, to check features published + in that version while developping it. */ + static const char* api_version = "3.7"; static int current_prec = 0; static location current_lhs_loc; @@ -260,17 +263,20 @@ typedef enum yysymbol_kind_t yysymbol_kind_t; static char *strip_braces (char *code); /* Convert CODE by calling code_props_plain_init if PLAIN, otherwise - code_props_symbol_action_init. Call + code_props_symbol_action_init. Calls gram_scanner_last_string_free to release the latest string from the scanner (should be CODE). */ static char const *translate_code (char *code, location loc, bool plain); /* Convert CODE by calling code_props_plain_init after having stripped the first and last characters (expected to be '{', and - '}'). Call gram_scanner_last_string_free to release the latest + '}'). Calls gram_scanner_last_string_free to release the latest string from the scanner (should be CODE). */ static char const *translate_code_braceless (char *code, location loc); + /* Handle a %defines directive. */ + static void handle_defines (char const *value); + /* Handle a %error-verbose directive. */ static void handle_error_verbose (location const *loc, char const *directive); @@ -279,6 +285,9 @@ typedef enum yysymbol_kind_t yysymbol_kind_t; location const *dir_loc, char const *directive, char const *value); + /* Handle a %language directive. */ + static void handle_language (location const *loc, char const *lang); + /* Handle a %name-prefix directive. */ static void handle_name_prefix (location const *loc, char const *directive, char const *value); @@ -304,7 +313,14 @@ typedef enum yysymbol_kind_t yysymbol_kind_t; /* Add style to semantic values in traces. */ static void tron (FILE *yyo); static void troff (FILE *yyo); -#line 255 "src/parse-gram.y" + + /* Interpret a quoted string (such as `"Hello, \"World\"\n\""`). + Manages the memory of the result. */ + static char *unquote (const char *str); + + /* Discard the latest unquoted string. */ + static void unquote_free (char *last_string); +#line 279 "src/parse-gram.y" /** Add a lex-param and/or a parse-param. * @@ -315,7 +331,7 @@ typedef enum yysymbol_kind_t yysymbol_kind_t; static void add_param (param_type type, char *decl, location loc); static param_type current_param = param_none; -#line 319 "src/parse-gram.c" +#line 335 "src/parse-gram.c" #ifdef short # undef short @@ -354,6 +370,18 @@ typedef int_least16_t yytype_int16; typedef short yytype_int16; #endif +/* Work around bug in HP-UX 11.23, which defines these macros + incorrectly for preprocessor constants. This workaround can likely + be removed in 2023, as HPE has promised support for HP-UX 11.23 + (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of + <https://h20195.www2.hpe.com/V2/getpdf.aspx/4AA4-7673ENW.pdf>. */ +#ifdef __hpux +# undef UINT_LEAST8_MAX +# undef UINT_LEAST16_MAX +# define UINT_LEAST8_MAX 255 +# define UINT_LEAST16_MAX 65535 +#endif + #if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ typedef __UINT_LEAST8_TYPE__ yytype_uint8; #elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \ @@ -455,9 +483,9 @@ typedef int yy_state_fast_t; /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ -# define YYUSE(E) ((void) (E)) +# define YY_USE(E) ((void) (E)) #else -# define YYUSE(E) /* empty */ +# define YY_USE(E) /* empty */ #endif #if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ @@ -615,6 +643,7 @@ union yyalloc /* YYNSTATES -- Number of states. */ #define YYNSTATES 167 +/* YYMAXUTOK -- Last valid token kind. */ #define YYMAXUTOK 315 @@ -626,19 +655,19 @@ union yyalloc /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_int16 yyrline[] = { - 0, 287, 287, 296, 297, 301, 302, 308, 312, 317, - 318, 323, 324, 325, 326, 327, 332, 337, 338, 339, - 340, 341, 342, 342, 343, 344, 345, 346, 347, 348, - 349, 350, 354, 355, 364, 365, 369, 380, 384, 388, - 396, 406, 407, 417, 418, 424, 437, 437, 442, 442, - 447, 451, 461, 462, 463, 464, 468, 469, 474, 475, - 479, 480, 484, 485, 486, 499, 508, 512, 516, 524, - 525, 529, 542, 543, 548, 549, 550, 568, 572, 576, - 584, 586, 591, 598, 608, 612, 616, 624, 629, 641, - 642, 648, 649, 650, 657, 657, 665, 666, 667, 672, - 675, 677, 679, 681, 683, 685, 687, 689, 691, 696, - 697, 706, 730, 731, 732, 733, 745, 747, 771, 776, - 777, 782, 790, 791 + 0, 311, 311, 320, 321, 325, 326, 332, 336, 341, + 342, 343, 344, 345, 346, 347, 352, 357, 358, 359, + 360, 361, 362, 362, 363, 364, 365, 366, 367, 368, + 369, 370, 374, 375, 384, 385, 389, 400, 404, 408, + 416, 426, 427, 437, 438, 444, 457, 457, 462, 462, + 467, 471, 481, 482, 483, 484, 488, 489, 494, 495, + 499, 500, 504, 505, 506, 519, 528, 532, 536, 544, + 545, 549, 562, 563, 568, 569, 570, 588, 592, 596, + 604, 606, 611, 618, 628, 632, 636, 644, 649, 661, + 662, 668, 669, 670, 677, 677, 685, 686, 687, 692, + 695, 697, 699, 701, 703, 705, 707, 709, 711, 716, + 717, 726, 750, 751, 752, 753, 765, 767, 791, 796, + 797, 802, 810, 811 }; #endif @@ -779,9 +808,9 @@ static const yytype_int16 yypgoto[] = }; /* YYDEFGOTO[NTERM-NUM]. */ -static const yytype_int16 yydefgoto[] = +static const yytype_uint8 yydefgoto[] = { - -1, 1, 2, 43, 82, 115, 77, 45, 84, 46, + 0, 1, 2, 43, 82, 115, 77, 45, 84, 46, 50, 49, 47, 156, 120, 121, 122, 97, 93, 94, 95, 128, 141, 87, 88, 89, 55, 56, 78, 79, 80, 135, 144, 145, 113, 63, 106, 57, 81, 58, @@ -1048,8 +1077,8 @@ yy_symbol_value_print (FILE *yyo, yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp) { FILE *yyoutput = yyo; - YYUSE (yyoutput); - YYUSE (yylocationp); + YY_USE (yyoutput); + YY_USE (yylocationp); if (!yyvaluep) return; # ifdef YYPRINT @@ -1057,117 +1086,117 @@ yy_symbol_value_print (FILE *yyo, YYPRINT (yyo, yytoknum[yykind], *yyvaluep); # endif /* "%code pre-printer" blocks. */ -#line 207 "src/parse-gram.y" +#line 231 "src/parse-gram.y" tron (yyo); -#line 1064 "src/parse-gram.c" +#line 1093 "src/parse-gram.c" YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN switch (yykind) { - case 3: /* "string" */ -#line 214 "src/parse-gram.y" + case YYSYMBOL_STRING: /* "string" */ +#line 238 "src/parse-gram.y" { fputs (((*yyvaluep).STRING), yyo); } -#line 1071 "src/parse-gram.c" +#line 1100 "src/parse-gram.c" break; - case 4: /* "translatable string" */ -#line 214 "src/parse-gram.y" + case YYSYMBOL_TSTRING: /* "translatable string" */ +#line 238 "src/parse-gram.y" { fputs (((*yyvaluep).TSTRING), yyo); } -#line 1077 "src/parse-gram.c" +#line 1106 "src/parse-gram.c" break; - case 21: /* "%error-verbose" */ -#line 221 "src/parse-gram.y" + case YYSYMBOL_PERCENT_ERROR_VERBOSE: /* "%error-verbose" */ +#line 245 "src/parse-gram.y" { fputs (((*yyvaluep).PERCENT_ERROR_VERBOSE), yyo); } -#line 1083 "src/parse-gram.c" +#line 1112 "src/parse-gram.c" break; - case 24: /* "%<flag>" */ -#line 224 "src/parse-gram.y" + case YYSYMBOL_PERCENT_FLAG: /* "%<flag>" */ +#line 248 "src/parse-gram.y" { fprintf (yyo, "%%%s", ((*yyvaluep).PERCENT_FLAG)); } -#line 1089 "src/parse-gram.c" +#line 1118 "src/parse-gram.c" break; - case 25: /* "%file-prefix" */ -#line 221 "src/parse-gram.y" + case YYSYMBOL_PERCENT_FILE_PREFIX: /* "%file-prefix" */ +#line 245 "src/parse-gram.y" { fputs (((*yyvaluep).PERCENT_FILE_PREFIX), yyo); } -#line 1095 "src/parse-gram.c" +#line 1124 "src/parse-gram.c" break; - case 29: /* "%name-prefix" */ -#line 221 "src/parse-gram.y" + case YYSYMBOL_PERCENT_NAME_PREFIX: /* "%name-prefix" */ +#line 245 "src/parse-gram.y" { fputs (((*yyvaluep).PERCENT_NAME_PREFIX), yyo); } -#line 1101 "src/parse-gram.c" +#line 1130 "src/parse-gram.c" break; - case 34: /* "%pure-parser" */ -#line 221 "src/parse-gram.y" + case YYSYMBOL_PERCENT_PURE_PARSER: /* "%pure-parser" */ +#line 245 "src/parse-gram.y" { fputs (((*yyvaluep).PERCENT_PURE_PARSER), yyo); } -#line 1107 "src/parse-gram.c" +#line 1136 "src/parse-gram.c" break; - case 41: /* "{...}" */ -#line 214 "src/parse-gram.y" + case YYSYMBOL_BRACED_CODE: /* "{...}" */ +#line 238 "src/parse-gram.y" { fputs (((*yyvaluep).BRACED_CODE), yyo); } -#line 1113 "src/parse-gram.c" +#line 1142 "src/parse-gram.c" break; - case 42: /* "%?{...}" */ -#line 214 "src/parse-gram.y" + case YYSYMBOL_BRACED_PREDICATE: /* "%?{...}" */ +#line 238 "src/parse-gram.y" { fputs (((*yyvaluep).BRACED_PREDICATE), yyo); } -#line 1119 "src/parse-gram.c" +#line 1148 "src/parse-gram.c" break; - case 43: /* "[identifier]" */ -#line 222 "src/parse-gram.y" + case YYSYMBOL_BRACKETED_ID: /* "[identifier]" */ +#line 246 "src/parse-gram.y" { fprintf (yyo, "[%s]", ((*yyvaluep).BRACKETED_ID)); } -#line 1125 "src/parse-gram.c" +#line 1154 "src/parse-gram.c" break; - case 44: /* "character literal" */ -#line 211 "src/parse-gram.y" - { fputs (char_name (((*yyvaluep).CHAR)), yyo); } -#line 1131 "src/parse-gram.c" + case YYSYMBOL_CHAR_LITERAL: /* "character literal" */ +#line 235 "src/parse-gram.y" + { fputs (char_name (((*yyvaluep).CHAR_LITERAL)), yyo); } +#line 1160 "src/parse-gram.c" break; - case 46: /* "epilogue" */ -#line 214 "src/parse-gram.y" + case YYSYMBOL_EPILOGUE: /* "epilogue" */ +#line 238 "src/parse-gram.y" { fputs (((*yyvaluep).EPILOGUE), yyo); } -#line 1137 "src/parse-gram.c" +#line 1166 "src/parse-gram.c" break; - case 48: /* "identifier" */ -#line 221 "src/parse-gram.y" + case YYSYMBOL_ID: /* "identifier" */ +#line 245 "src/parse-gram.y" { fputs (((*yyvaluep).ID), yyo); } -#line 1143 "src/parse-gram.c" +#line 1172 "src/parse-gram.c" break; - case 49: /* "identifier:" */ -#line 223 "src/parse-gram.y" + case YYSYMBOL_ID_COLON: /* "identifier:" */ +#line 247 "src/parse-gram.y" { fprintf (yyo, "%s:", ((*yyvaluep).ID_COLON)); } -#line 1149 "src/parse-gram.c" +#line 1178 "src/parse-gram.c" break; - case 52: /* "%{...%}" */ -#line 214 "src/parse-gram.y" + case YYSYMBOL_PROLOGUE: /* "%{...%}" */ +#line 238 "src/parse-gram.y" { fputs (((*yyvaluep).PROLOGUE), yyo); } -#line 1155 "src/parse-gram.c" +#line 1184 "src/parse-gram.c" break; - case 54: /* "<tag>" */ -#line 225 "src/parse-gram.y" + case YYSYMBOL_TAG: /* "<tag>" */ +#line 249 "src/parse-gram.y" { fprintf (yyo, "<%s>", ((*yyvaluep).TAG)); } -#line 1161 "src/parse-gram.c" +#line 1190 "src/parse-gram.c" break; - case 57: /* "integer literal" */ -#line 228 "src/parse-gram.y" - { fprintf (yyo, "%d", ((*yyvaluep).INT)); } -#line 1167 "src/parse-gram.c" + case YYSYMBOL_INT_LITERAL: /* "integer literal" */ +#line 252 "src/parse-gram.y" + { fprintf (yyo, "%d", ((*yyvaluep).INT_LITERAL)); } +#line 1196 "src/parse-gram.c" break; - case 58: /* "%param" */ -#line 267 "src/parse-gram.y" + case YYSYMBOL_PERCENT_PARAM: /* "%param" */ +#line 291 "src/parse-gram.y" { switch (((*yyvaluep).PERCENT_PARAM)) { @@ -1180,113 +1209,113 @@ tron (yyo); case param_none: aver (false); break; } } -#line 1184 "src/parse-gram.c" +#line 1213 "src/parse-gram.c" break; - case 68: /* code_props_type */ -#line 404 "src/parse-gram.y" + case YYSYMBOL_code_props_type: /* code_props_type */ +#line 424 "src/parse-gram.y" { fprintf (yyo, "%s", code_props_type_string (((*yyvaluep).code_props_type))); } -#line 1190 "src/parse-gram.c" +#line 1219 "src/parse-gram.c" break; - case 74: /* tag.opt */ -#line 221 "src/parse-gram.y" + case YYSYMBOL_74_tag_opt: /* tag.opt */ +#line 245 "src/parse-gram.y" { fputs (((*yyvaluep).yykind_74), yyo); } -#line 1196 "src/parse-gram.c" +#line 1225 "src/parse-gram.c" break; - case 75: /* generic_symlist */ -#line 237 "src/parse-gram.y" + case YYSYMBOL_generic_symlist: /* generic_symlist */ +#line 261 "src/parse-gram.y" { symbol_list_syms_print (((*yyvaluep).generic_symlist), yyo); } -#line 1202 "src/parse-gram.c" +#line 1231 "src/parse-gram.c" break; - case 76: /* generic_symlist_item */ -#line 237 "src/parse-gram.y" + case YYSYMBOL_generic_symlist_item: /* generic_symlist_item */ +#line 261 "src/parse-gram.y" { symbol_list_syms_print (((*yyvaluep).generic_symlist_item), yyo); } -#line 1208 "src/parse-gram.c" +#line 1237 "src/parse-gram.c" break; - case 77: /* tag */ -#line 225 "src/parse-gram.y" + case YYSYMBOL_tag: /* tag */ +#line 249 "src/parse-gram.y" { fprintf (yyo, "<%s>", ((*yyvaluep).tag)); } -#line 1214 "src/parse-gram.c" +#line 1243 "src/parse-gram.c" break; - case 78: /* nterm_decls */ -#line 237 "src/parse-gram.y" + case YYSYMBOL_nterm_decls: /* nterm_decls */ +#line 261 "src/parse-gram.y" { symbol_list_syms_print (((*yyvaluep).nterm_decls), yyo); } -#line 1220 "src/parse-gram.c" +#line 1249 "src/parse-gram.c" break; - case 79: /* token_decls */ -#line 237 "src/parse-gram.y" + case YYSYMBOL_token_decls: /* token_decls */ +#line 261 "src/parse-gram.y" { symbol_list_syms_print (((*yyvaluep).token_decls), yyo); } -#line 1226 "src/parse-gram.c" +#line 1255 "src/parse-gram.c" break; - case 80: /* token_decl.1 */ -#line 237 "src/parse-gram.y" + case YYSYMBOL_80_token_decl_1: /* token_decl.1 */ +#line 261 "src/parse-gram.y" { symbol_list_syms_print (((*yyvaluep).yykind_80), yyo); } -#line 1232 "src/parse-gram.c" +#line 1261 "src/parse-gram.c" break; - case 81: /* token_decl */ -#line 231 "src/parse-gram.y" + case YYSYMBOL_token_decl: /* token_decl */ +#line 255 "src/parse-gram.y" { fprintf (yyo, "%s", ((*yyvaluep).token_decl) ? ((*yyvaluep).token_decl)->tag : "<NULL>"); } -#line 1238 "src/parse-gram.c" +#line 1267 "src/parse-gram.c" break; - case 82: /* int.opt */ -#line 228 "src/parse-gram.y" + case YYSYMBOL_82_int_opt: /* int.opt */ +#line 252 "src/parse-gram.y" { fprintf (yyo, "%d", ((*yyvaluep).yykind_82)); } -#line 1244 "src/parse-gram.c" +#line 1273 "src/parse-gram.c" break; - case 83: /* alias */ -#line 231 "src/parse-gram.y" + case YYSYMBOL_alias: /* alias */ +#line 255 "src/parse-gram.y" { fprintf (yyo, "%s", ((*yyvaluep).alias) ? ((*yyvaluep).alias)->tag : "<NULL>"); } -#line 1250 "src/parse-gram.c" +#line 1279 "src/parse-gram.c" break; - case 84: /* token_decls_for_prec */ -#line 237 "src/parse-gram.y" + case YYSYMBOL_token_decls_for_prec: /* token_decls_for_prec */ +#line 261 "src/parse-gram.y" { symbol_list_syms_print (((*yyvaluep).token_decls_for_prec), yyo); } -#line 1256 "src/parse-gram.c" +#line 1285 "src/parse-gram.c" break; - case 85: /* token_decl_for_prec.1 */ -#line 237 "src/parse-gram.y" + case YYSYMBOL_85_token_decl_for_prec_1: /* token_decl_for_prec.1 */ +#line 261 "src/parse-gram.y" { symbol_list_syms_print (((*yyvaluep).yykind_85), yyo); } -#line 1262 "src/parse-gram.c" +#line 1291 "src/parse-gram.c" break; - case 86: /* token_decl_for_prec */ -#line 231 "src/parse-gram.y" + case YYSYMBOL_token_decl_for_prec: /* token_decl_for_prec */ +#line 255 "src/parse-gram.y" { fprintf (yyo, "%s", ((*yyvaluep).token_decl_for_prec) ? ((*yyvaluep).token_decl_for_prec)->tag : "<NULL>"); } -#line 1268 "src/parse-gram.c" +#line 1297 "src/parse-gram.c" break; - case 87: /* symbol_decls */ -#line 237 "src/parse-gram.y" + case YYSYMBOL_symbol_decls: /* symbol_decls */ +#line 261 "src/parse-gram.y" { symbol_list_syms_print (((*yyvaluep).symbol_decls), yyo); } -#line 1274 "src/parse-gram.c" +#line 1303 "src/parse-gram.c" break; - case 88: /* symbol_decl.1 */ -#line 237 "src/parse-gram.y" + case YYSYMBOL_88_symbol_decl_1: /* symbol_decl.1 */ +#line 261 "src/parse-gram.y" { symbol_list_syms_print (((*yyvaluep).yykind_88), yyo); } -#line 1280 "src/parse-gram.c" +#line 1309 "src/parse-gram.c" break; - case 96: /* variable */ -#line 221 "src/parse-gram.y" + case YYSYMBOL_variable: /* variable */ +#line 245 "src/parse-gram.y" { fputs (((*yyvaluep).variable), yyo); } -#line 1286 "src/parse-gram.c" +#line 1315 "src/parse-gram.c" break; - case 97: /* value */ -#line 720 "src/parse-gram.y" + case YYSYMBOL_value: /* value */ +#line 740 "src/parse-gram.y" { switch (((*yyvaluep).value).kind) { @@ -1295,31 +1324,31 @@ tron (yyo); case muscle_string: fprintf (yyo, "\"%s\"", ((*yyvaluep).value).chars); break; } } -#line 1299 "src/parse-gram.c" +#line 1328 "src/parse-gram.c" break; - case 98: /* id */ -#line 231 "src/parse-gram.y" + case YYSYMBOL_id: /* id */ +#line 255 "src/parse-gram.y" { fprintf (yyo, "%s", ((*yyvaluep).id) ? ((*yyvaluep).id)->tag : "<NULL>"); } -#line 1305 "src/parse-gram.c" +#line 1334 "src/parse-gram.c" break; - case 99: /* id_colon */ -#line 232 "src/parse-gram.y" + case YYSYMBOL_id_colon: /* id_colon */ +#line 256 "src/parse-gram.y" { fprintf (yyo, "%s:", ((*yyvaluep).id_colon)->tag); } -#line 1311 "src/parse-gram.c" +#line 1340 "src/parse-gram.c" break; - case 100: /* symbol */ -#line 231 "src/parse-gram.y" + case YYSYMBOL_symbol: /* symbol */ +#line 255 "src/parse-gram.y" { fprintf (yyo, "%s", ((*yyvaluep).symbol) ? ((*yyvaluep).symbol)->tag : "<NULL>"); } -#line 1317 "src/parse-gram.c" +#line 1346 "src/parse-gram.c" break; - case 101: /* string_as_id */ -#line 231 "src/parse-gram.y" + case YYSYMBOL_string_as_id: /* string_as_id */ +#line 255 "src/parse-gram.y" { fprintf (yyo, "%s", ((*yyvaluep).string_as_id) ? ((*yyvaluep).string_as_id)->tag : "<NULL>"); } -#line 1323 "src/parse-gram.c" +#line 1352 "src/parse-gram.c" break; default: @@ -1327,10 +1356,10 @@ tron (yyo); } YY_IGNORE_MAYBE_UNINITIALIZED_END /* "%code post-printer" blocks. */ -#line 208 "src/parse-gram.y" +#line 232 "src/parse-gram.y" troff (yyo); -#line 1334 "src/parse-gram.c" +#line 1363 "src/parse-gram.c" } @@ -1761,8 +1790,8 @@ static void yydestruct (const char *yymsg, yysymbol_kind_t yykind, YYSTYPE *yyvaluep, YYLTYPE *yylocationp) { - YYUSE (yyvaluep); - YYUSE (yylocationp); + YY_USE (yyvaluep); + YY_USE (yylocationp); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp); @@ -1770,58 +1799,58 @@ yydestruct (const char *yymsg, YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN switch (yykind) { - case 75: /* generic_symlist */ -#line 236 "src/parse-gram.y" + case YYSYMBOL_generic_symlist: /* generic_symlist */ +#line 260 "src/parse-gram.y" { symbol_list_free (((*yyvaluep).generic_symlist)); } -#line 1777 "src/parse-gram.c" +#line 1806 "src/parse-gram.c" break; - case 76: /* generic_symlist_item */ -#line 236 "src/parse-gram.y" + case YYSYMBOL_generic_symlist_item: /* generic_symlist_item */ +#line 260 "src/parse-gram.y" { symbol_list_free (((*yyvaluep).generic_symlist_item)); } -#line 1783 "src/parse-gram.c" +#line 1812 "src/parse-gram.c" break; - case 78: /* nterm_decls */ -#line 236 "src/parse-gram.y" + case YYSYMBOL_nterm_decls: /* nterm_decls */ +#line 260 "src/parse-gram.y" { symbol_list_free (((*yyvaluep).nterm_decls)); } -#line 1789 "src/parse-gram.c" +#line 1818 "src/parse-gram.c" break; - case 79: /* token_decls */ -#line 236 "src/parse-gram.y" + case YYSYMBOL_token_decls: /* token_decls */ +#line 260 "src/parse-gram.y" { symbol_list_free (((*yyvaluep).token_decls)); } -#line 1795 "src/parse-gram.c" +#line 1824 "src/parse-gram.c" break; - case 80: /* token_decl.1 */ -#line 236 "src/parse-gram.y" + case YYSYMBOL_80_token_decl_1: /* token_decl.1 */ +#line 260 "src/parse-gram.y" { symbol_list_free (((*yyvaluep).yykind_80)); } -#line 1801 "src/parse-gram.c" +#line 1830 "src/parse-gram.c" break; - case 84: /* token_decls_for_prec */ -#line 236 "src/parse-gram.y" + case YYSYMBOL_token_decls_for_prec: /* token_decls_for_prec */ +#line 260 "src/parse-gram.y" { symbol_list_free (((*yyvaluep).token_decls_for_prec)); } -#line 1807 "src/parse-gram.c" +#line 1836 "src/parse-gram.c" break; - case 85: /* token_decl_for_prec.1 */ -#line 236 "src/parse-gram.y" + case YYSYMBOL_85_token_decl_for_prec_1: /* token_decl_for_prec.1 */ +#line 260 "src/parse-gram.y" { symbol_list_free (((*yyvaluep).yykind_85)); } -#line 1813 "src/parse-gram.c" +#line 1842 "src/parse-gram.c" break; - case 87: /* symbol_decls */ -#line 236 "src/parse-gram.y" + case YYSYMBOL_symbol_decls: /* symbol_decls */ +#line 260 "src/parse-gram.y" { symbol_list_free (((*yyvaluep).symbol_decls)); } -#line 1819 "src/parse-gram.c" +#line 1848 "src/parse-gram.c" break; - case 88: /* symbol_decl.1 */ -#line 236 "src/parse-gram.y" + case YYSYMBOL_88_symbol_decl_1: /* symbol_decl.1 */ +#line 260 "src/parse-gram.y" { symbol_list_free (((*yyvaluep).yykind_88)); } -#line 1825 "src/parse-gram.c" +#line 1854 "src/parse-gram.c" break; default: @@ -1842,7 +1871,7 @@ yydestruct (const char *yymsg, int yyparse (void) { -/* The lookahead symbol. */ +/* Lookahead token kind. */ int yychar; @@ -1861,48 +1890,43 @@ static YYLTYPE yyloc_default YYLTYPE yylloc = yyloc_default; /* Number of syntax errors so far. */ - int yynerrs; + int yynerrs = 0; - yy_state_fast_t yystate; + yy_state_fast_t yystate = 0; /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; - - /* The stacks and their tools: - 'yyss': related to states. - 'yyvs': related to semantic values. - 'yyls': related to locations. + int yyerrstatus = 0; - Refer to the stacks through separate pointers, to allow yyoverflow + /* Refer to the stacks through separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* Their size. */ - YYPTRDIFF_T yystacksize; + YYPTRDIFF_T yystacksize = YYINITDEPTH; - /* The state stack. */ + /* The state stack: array, bottom, top. */ yy_state_t yyssa[YYINITDEPTH]; - yy_state_t *yyss; - yy_state_t *yyssp; + yy_state_t *yyss = yyssa; + yy_state_t *yyssp = yyss; - /* The semantic value stack. */ + /* The semantic value stack: array, bottom, top. */ YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs; - YYSTYPE *yyvsp; + YYSTYPE *yyvs = yyvsa; + YYSTYPE *yyvsp = yyvs; - /* The location stack. */ + /* The location stack: array, bottom, top. */ YYLTYPE yylsa[YYINITDEPTH]; - YYLTYPE *yyls; - YYLTYPE *yylsp; + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp = yyls; yy_state_t yyesa[20]; - yy_state_t *yyes; - YYPTRDIFF_T yyes_capacity; + yy_state_t *yyes = yyesa; + YYPTRDIFF_T yyes_capacity = 20 < YYMAXDEPTH ? 20 : YYMAXDEPTH; /* Whether LAC context is established. A Boolean. */ int yy_lac_established = 0; int yyn; /* The return value of yyparse. */ int yyresult; - /* Lookahead token as an internal (translated) token number. */ + /* Lookahead symbol kind. */ yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY; /* The variables used to return semantic value and location from the action routines. */ @@ -1920,27 +1944,12 @@ YYLTYPE yylloc = yyloc_default; Keep to zero when no symbol should be popped. */ int yylen = 0; - yynerrs = 0; - yystate = 0; - yyerrstatus = 0; - - yystacksize = YYINITDEPTH; - yyssp = yyss = yyssa; - yyvsp = yyvs = yyvsa; - yylsp = yyls = yylsa; - - yyes = yyesa; - yyes_capacity = 20; - if (YYMAXDEPTH < yyes_capacity) - yyes_capacity = YYMAXDEPTH; - - YYDPRINTF ((stderr, "Starting parse\n")); yychar = GRAM_EMPTY; /* Cause a token to be read. */ /* User initialization code. */ -#line 136 "src/parse-gram.y" +#line 160 "src/parse-gram.y" { /* Bison's grammar can initial empty locations, hence a default location is needed. */ @@ -1948,7 +1957,7 @@ YYLTYPE yylloc = yyloc_default; boundary_set (&yylloc.end, grammar_file, 1, 1, 1); } -#line 1952 "src/parse-gram.c" +#line 1961 "src/parse-gram.c" yylsp[0] = yylloc; goto yysetstate; @@ -2164,196 +2173,193 @@ yyreduce: int yychar_backup = yychar; switch (yyn) { - case 6: -#line 303 "src/parse-gram.y" + case 6: /* prologue_declaration: "%{...%}" */ +#line 327 "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 2175 "src/parse-gram.c" +#line 2184 "src/parse-gram.c" break; - case 7: -#line 309 "src/parse-gram.y" + case 7: /* prologue_declaration: "%<flag>" */ +#line 333 "src/parse-gram.y" { muscle_percent_define_ensure ((yyvsp[0].PERCENT_FLAG), (yylsp[0]), true); } -#line 2183 "src/parse-gram.c" +#line 2192 "src/parse-gram.c" break; - case 8: -#line 313 "src/parse-gram.y" + case 8: /* prologue_declaration: "%define" variable value */ +#line 337 "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 2192 "src/parse-gram.c" +#line 2201 "src/parse-gram.c" break; - case 9: -#line 317 "src/parse-gram.y" + case 9: /* prologue_declaration: "%defines" */ +#line 341 "src/parse-gram.y" { defines_flag = true; } -#line 2198 "src/parse-gram.c" - break; - - case 10: -#line 319 "src/parse-gram.y" - { - defines_flag = true; - spec_header_file = xstrdup ((yyvsp[0].STRING)); - } #line 2207 "src/parse-gram.c" break; - case 11: -#line 323 "src/parse-gram.y" - { handle_error_verbose (&(yyloc), (yyvsp[0].PERCENT_ERROR_VERBOSE)); } + case 10: /* prologue_declaration: "%defines" "string" */ +#line 342 "src/parse-gram.y" + { handle_defines ((yyvsp[0].STRING)); } #line 2213 "src/parse-gram.c" break; - case 12: -#line 324 "src/parse-gram.y" - { expected_sr_conflicts = (yyvsp[0].INT); } + case 11: /* prologue_declaration: "%error-verbose" */ +#line 343 "src/parse-gram.y" + { handle_error_verbose (&(yyloc), (yyvsp[0].PERCENT_ERROR_VERBOSE)); } #line 2219 "src/parse-gram.c" break; - case 13: -#line 325 "src/parse-gram.y" - { expected_rr_conflicts = (yyvsp[0].INT); } + case 12: /* prologue_declaration: "%expect" "integer literal" */ +#line 344 "src/parse-gram.y" + { expected_sr_conflicts = (yyvsp[0].INT_LITERAL); } #line 2225 "src/parse-gram.c" break; - case 14: -#line 326 "src/parse-gram.y" - { handle_file_prefix (&(yyloc), &(yylsp[-1]), (yyvsp[-1].PERCENT_FILE_PREFIX), (yyvsp[0].STRING)); } + case 13: /* prologue_declaration: "%expect-rr" "integer literal" */ +#line 345 "src/parse-gram.y" + { expected_rr_conflicts = (yyvsp[0].INT_LITERAL); } #line 2231 "src/parse-gram.c" break; - case 15: -#line 328 "src/parse-gram.y" + case 14: /* prologue_declaration: "%file-prefix" "string" */ +#line 346 "src/parse-gram.y" + { handle_file_prefix (&(yyloc), &(yylsp[-1]), (yyvsp[-1].PERCENT_FILE_PREFIX), (yyvsp[0].STRING)); } +#line 2237 "src/parse-gram.c" + break; + + case 15: /* prologue_declaration: "%glr-parser" */ +#line 348 "src/parse-gram.y" { nondeterministic_parser = true; glr_parser = true; } -#line 2240 "src/parse-gram.c" +#line 2246 "src/parse-gram.c" break; - case 16: -#line 333 "src/parse-gram.y" + case 16: /* prologue_declaration: "%initial-action" "{...}" */ +#line 353 "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 2249 "src/parse-gram.c" - break; - - case 17: -#line 337 "src/parse-gram.y" - { language_argmatch ((yyvsp[0].STRING), grammar_prio, (yylsp[-1])); } #line 2255 "src/parse-gram.c" break; - case 18: -#line 338 "src/parse-gram.y" - { handle_name_prefix (&(yyloc), (yyvsp[-1].PERCENT_NAME_PREFIX), (yyvsp[0].STRING)); } + case 17: /* prologue_declaration: "%language" "string" */ +#line 357 "src/parse-gram.y" + { handle_language (&(yylsp[-1]), (yyvsp[0].STRING)); } #line 2261 "src/parse-gram.c" break; - case 19: -#line 339 "src/parse-gram.y" - { no_lines_flag = true; } + case 18: /* prologue_declaration: "%name-prefix" "string" */ +#line 358 "src/parse-gram.y" + { handle_name_prefix (&(yyloc), (yyvsp[-1].PERCENT_NAME_PREFIX), (yyvsp[0].STRING)); } #line 2267 "src/parse-gram.c" break; - case 20: -#line 340 "src/parse-gram.y" - { nondeterministic_parser = true; } + case 19: /* prologue_declaration: "%no-lines" */ +#line 359 "src/parse-gram.y" + { no_lines_flag = true; } #line 2273 "src/parse-gram.c" break; - case 21: -#line 341 "src/parse-gram.y" - { spec_outfile = (yyvsp[0].STRING); } + case 20: /* prologue_declaration: "%nondeterministic-parser" */ +#line 360 "src/parse-gram.y" + { nondeterministic_parser = true; } #line 2279 "src/parse-gram.c" break; - case 22: -#line 342 "src/parse-gram.y" - { current_param = (yyvsp[0].PERCENT_PARAM); } + case 21: /* prologue_declaration: "%output" "string" */ +#line 361 "src/parse-gram.y" + { spec_outfile = unquote ((yyvsp[0].STRING)); gram_scanner_last_string_free (); } #line 2285 "src/parse-gram.c" break; - case 23: -#line 342 "src/parse-gram.y" - { current_param = param_none; } + case 22: /* $@1: %empty */ +#line 362 "src/parse-gram.y" + { current_param = (yyvsp[0].PERCENT_PARAM); } #line 2291 "src/parse-gram.c" break; - case 24: -#line 343 "src/parse-gram.y" - { handle_pure_parser (&(yyloc), (yyvsp[0].PERCENT_PURE_PARSER)); } + case 23: /* prologue_declaration: "%param" $@1 params */ +#line 362 "src/parse-gram.y" + { current_param = param_none; } #line 2297 "src/parse-gram.c" break; - case 25: -#line 344 "src/parse-gram.y" - { handle_require (&(yylsp[0]), (yyvsp[0].STRING)); } + case 24: /* prologue_declaration: "%pure-parser" */ +#line 363 "src/parse-gram.y" + { handle_pure_parser (&(yyloc), (yyvsp[0].PERCENT_PURE_PARSER)); } #line 2303 "src/parse-gram.c" break; - case 26: -#line 345 "src/parse-gram.y" - { handle_skeleton (&(yylsp[0]), (yyvsp[0].STRING)); } + case 25: /* prologue_declaration: "%require" "string" */ +#line 364 "src/parse-gram.y" + { handle_require (&(yylsp[0]), (yyvsp[0].STRING)); } #line 2309 "src/parse-gram.c" break; - case 27: -#line 346 "src/parse-gram.y" - { token_table_flag = true; } + case 26: /* prologue_declaration: "%skeleton" "string" */ +#line 365 "src/parse-gram.y" + { handle_skeleton (&(yylsp[0]), (yyvsp[0].STRING)); } #line 2315 "src/parse-gram.c" break; - case 28: -#line 347 "src/parse-gram.y" - { report_flag |= report_states; } + case 27: /* prologue_declaration: "%token-table" */ +#line 366 "src/parse-gram.y" + { token_table_flag = true; } #line 2321 "src/parse-gram.c" break; - case 29: -#line 348 "src/parse-gram.y" - { handle_yacc (&(yyloc)); } + case 28: /* prologue_declaration: "%verbose" */ +#line 367 "src/parse-gram.y" + { report_flag |= report_states; } #line 2327 "src/parse-gram.c" break; - case 30: -#line 349 "src/parse-gram.y" - { current_class = unknown_sym; yyerrok; } + case 29: /* prologue_declaration: "%yacc" */ +#line 368 "src/parse-gram.y" + { handle_yacc (&(yyloc)); } #line 2333 "src/parse-gram.c" break; - case 32: -#line 354 "src/parse-gram.y" - { add_param (current_param, (yyvsp[0].BRACED_CODE), (yylsp[0])); } + case 30: /* prologue_declaration: error ";" */ +#line 369 "src/parse-gram.y" + { current_class = unknown_sym; yyerrok; } #line 2339 "src/parse-gram.c" break; - case 33: -#line 355 "src/parse-gram.y" + case 32: /* params: params "{...}" */ +#line 374 "src/parse-gram.y" { add_param (current_param, (yyvsp[0].BRACED_CODE), (yylsp[0])); } #line 2345 "src/parse-gram.c" break; - case 35: -#line 366 "src/parse-gram.y" + case 33: /* params: "{...}" */ +#line 375 "src/parse-gram.y" + { add_param (current_param, (yyvsp[0].BRACED_CODE), (yylsp[0])); } +#line 2351 "src/parse-gram.c" + break; + + case 35: /* grammar_declaration: "%start" symbol */ +#line 386 "src/parse-gram.y" { grammar_start_symbol_set ((yyvsp[0].symbol), (yylsp[0])); } -#line 2353 "src/parse-gram.c" +#line 2359 "src/parse-gram.c" break; - case 36: -#line 370 "src/parse-gram.y" + case 36: /* grammar_declaration: code_props_type "{...}" generic_symlist */ +#line 390 "src/parse-gram.y" { code_props code; code_props_symbol_action_init (&code, (yyvsp[-1].BRACED_CODE), (yylsp[-1])); @@ -2364,27 +2370,27 @@ yyreduce: symbol_list_free ((yyvsp[0].generic_symlist)); } } -#line 2368 "src/parse-gram.c" +#line 2374 "src/parse-gram.c" break; - case 37: -#line 381 "src/parse-gram.y" + case 37: /* grammar_declaration: "%default-prec" */ +#line 401 "src/parse-gram.y" { default_prec = true; } -#line 2376 "src/parse-gram.c" +#line 2382 "src/parse-gram.c" break; - case 38: -#line 385 "src/parse-gram.y" + case 38: /* grammar_declaration: "%no-default-prec" */ +#line 405 "src/parse-gram.y" { default_prec = false; } -#line 2384 "src/parse-gram.c" +#line 2390 "src/parse-gram.c" break; - case 39: -#line 389 "src/parse-gram.y" + case 39: /* grammar_declaration: "%code" "{...}" */ +#line 409 "src/parse-gram.y" { /* Do not invoke muscle_percent_code_grow here since it invokes muscle_user_name_list_grow. */ @@ -2392,475 +2398,475 @@ yyreduce: translate_code_braceless ((yyvsp[0].BRACED_CODE), (yylsp[0])), (yylsp[0])); code_scanner_last_string_free (); } -#line 2396 "src/parse-gram.c" +#line 2402 "src/parse-gram.c" break; - case 40: -#line 397 "src/parse-gram.y" + case 40: /* grammar_declaration: "%code" "identifier" "{...}" */ +#line 417 "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 2405 "src/parse-gram.c" +#line 2411 "src/parse-gram.c" break; - case 41: -#line 406 "src/parse-gram.y" + case 41: /* code_props_type: "%destructor" */ +#line 426 "src/parse-gram.y" { (yyval.code_props_type) = destructor; } -#line 2411 "src/parse-gram.c" +#line 2417 "src/parse-gram.c" break; - case 42: -#line 407 "src/parse-gram.y" + case 42: /* code_props_type: "%printer" */ +#line 427 "src/parse-gram.y" { (yyval.code_props_type) = printer; } -#line 2417 "src/parse-gram.c" +#line 2423 "src/parse-gram.c" break; - case 43: -#line 417 "src/parse-gram.y" + case 43: /* union_name: %empty */ +#line 437 "src/parse-gram.y" {} -#line 2423 "src/parse-gram.c" +#line 2429 "src/parse-gram.c" break; - case 44: -#line 418 "src/parse-gram.y" + case 44: /* union_name: "identifier" */ +#line 438 "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 2431 "src/parse-gram.c" +#line 2437 "src/parse-gram.c" break; - case 45: -#line 425 "src/parse-gram.y" + case 45: /* grammar_declaration: "%union" union_name "{...}" */ +#line 445 "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 2441 "src/parse-gram.c" +#line 2447 "src/parse-gram.c" break; - case 46: -#line 437 "src/parse-gram.y" + case 46: /* $@2: %empty */ +#line 457 "src/parse-gram.y" { current_class = nterm_sym; } -#line 2447 "src/parse-gram.c" +#line 2453 "src/parse-gram.c" break; - case 47: -#line 438 "src/parse-gram.y" + case 47: /* symbol_declaration: "%nterm" $@2 nterm_decls */ +#line 458 "src/parse-gram.y" { current_class = unknown_sym; symbol_list_free ((yyvsp[0].nterm_decls)); } -#line 2456 "src/parse-gram.c" +#line 2462 "src/parse-gram.c" break; - case 48: -#line 442 "src/parse-gram.y" + case 48: /* $@3: %empty */ +#line 462 "src/parse-gram.y" { current_class = token_sym; } -#line 2462 "src/parse-gram.c" +#line 2468 "src/parse-gram.c" break; - case 49: -#line 443 "src/parse-gram.y" + case 49: /* symbol_declaration: "%token" $@3 token_decls */ +#line 463 "src/parse-gram.y" { current_class = unknown_sym; symbol_list_free ((yyvsp[0].token_decls)); } -#line 2471 "src/parse-gram.c" +#line 2477 "src/parse-gram.c" break; - case 50: -#line 448 "src/parse-gram.y" + case 50: /* symbol_declaration: "%type" symbol_decls */ +#line 468 "src/parse-gram.y" { symbol_list_free ((yyvsp[0].symbol_decls)); } -#line 2479 "src/parse-gram.c" +#line 2485 "src/parse-gram.c" break; - case 51: -#line 452 "src/parse-gram.y" + case 51: /* symbol_declaration: precedence_declarator token_decls_for_prec */ +#line 472 "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 2490 "src/parse-gram.c" +#line 2496 "src/parse-gram.c" break; - case 52: -#line 461 "src/parse-gram.y" + case 52: /* precedence_declarator: "%left" */ +#line 481 "src/parse-gram.y" { (yyval.precedence_declarator) = left_assoc; } -#line 2496 "src/parse-gram.c" +#line 2502 "src/parse-gram.c" break; - case 53: -#line 462 "src/parse-gram.y" + case 53: /* precedence_declarator: "%right" */ +#line 482 "src/parse-gram.y" { (yyval.precedence_declarator) = right_assoc; } -#line 2502 "src/parse-gram.c" +#line 2508 "src/parse-gram.c" break; - case 54: -#line 463 "src/parse-gram.y" + case 54: /* precedence_declarator: "%nonassoc" */ +#line 483 "src/parse-gram.y" { (yyval.precedence_declarator) = non_assoc; } -#line 2508 "src/parse-gram.c" +#line 2514 "src/parse-gram.c" break; - case 55: -#line 464 "src/parse-gram.y" + case 55: /* precedence_declarator: "%precedence" */ +#line 484 "src/parse-gram.y" { (yyval.precedence_declarator) = precedence_assoc; } -#line 2514 "src/parse-gram.c" +#line 2520 "src/parse-gram.c" break; - case 56: -#line 468 "src/parse-gram.y" + case 56: /* tag.opt: %empty */ +#line 488 "src/parse-gram.y" { (yyval.yykind_74) = NULL; } -#line 2520 "src/parse-gram.c" +#line 2526 "src/parse-gram.c" break; - case 57: -#line 469 "src/parse-gram.y" + case 57: /* tag.opt: "<tag>" */ +#line 489 "src/parse-gram.y" { (yyval.yykind_74) = (yyvsp[0].TAG); } -#line 2526 "src/parse-gram.c" +#line 2532 "src/parse-gram.c" break; - case 59: -#line 475 "src/parse-gram.y" + case 59: /* generic_symlist: generic_symlist generic_symlist_item */ +#line 495 "src/parse-gram.y" { (yyval.generic_symlist) = symbol_list_append ((yyvsp[-1].generic_symlist), (yyvsp[0].generic_symlist_item)); } -#line 2532 "src/parse-gram.c" +#line 2538 "src/parse-gram.c" break; - case 60: -#line 479 "src/parse-gram.y" + case 60: /* generic_symlist_item: symbol */ +#line 499 "src/parse-gram.y" { (yyval.generic_symlist_item) = symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0])); } -#line 2538 "src/parse-gram.c" +#line 2544 "src/parse-gram.c" break; - case 61: -#line 480 "src/parse-gram.y" + case 61: /* generic_symlist_item: tag */ +#line 500 "src/parse-gram.y" { (yyval.generic_symlist_item) = symbol_list_type_new ((yyvsp[0].tag), (yylsp[0])); } -#line 2544 "src/parse-gram.c" +#line 2550 "src/parse-gram.c" break; - case 63: -#line 485 "src/parse-gram.y" + case 63: /* tag: "<*>" */ +#line 505 "src/parse-gram.y" { (yyval.tag) = uniqstr_new ("*"); } -#line 2550 "src/parse-gram.c" +#line 2556 "src/parse-gram.c" break; - case 64: -#line 486 "src/parse-gram.y" + case 64: /* tag: "<>" */ +#line 506 "src/parse-gram.y" { (yyval.tag) = uniqstr_new (""); } -#line 2556 "src/parse-gram.c" +#line 2562 "src/parse-gram.c" break; - case 66: -#line 509 "src/parse-gram.y" + case 66: /* token_decls: token_decl.1 */ +#line 529 "src/parse-gram.y" { (yyval.token_decls) = (yyvsp[0].yykind_80); } -#line 2564 "src/parse-gram.c" +#line 2570 "src/parse-gram.c" break; - case 67: -#line 513 "src/parse-gram.y" + case 67: /* token_decls: "<tag>" token_decl.1 */ +#line 533 "src/parse-gram.y" { - (yyval.token_decls) = symbol_list_type_set ((yyvsp[0].yykind_80), (yyvsp[-1].TAG), (yylsp[-1])); + (yyval.token_decls) = symbol_list_type_set ((yyvsp[0].yykind_80), (yyvsp[-1].TAG)); } -#line 2572 "src/parse-gram.c" +#line 2578 "src/parse-gram.c" break; - case 68: -#line 517 "src/parse-gram.y" + case 68: /* token_decls: token_decls "<tag>" token_decl.1 */ +#line 537 "src/parse-gram.y" { - (yyval.token_decls) = symbol_list_append ((yyvsp[-2].token_decls), symbol_list_type_set ((yyvsp[0].yykind_80), (yyvsp[-1].TAG), (yylsp[-1]))); + (yyval.token_decls) = symbol_list_append ((yyvsp[-2].token_decls), symbol_list_type_set ((yyvsp[0].yykind_80), (yyvsp[-1].TAG))); } -#line 2580 "src/parse-gram.c" +#line 2586 "src/parse-gram.c" break; - case 69: -#line 524 "src/parse-gram.y" + case 69: /* token_decl.1: token_decl */ +#line 544 "src/parse-gram.y" { (yyval.yykind_80) = symbol_list_sym_new ((yyvsp[0].token_decl), (yylsp[0])); } -#line 2586 "src/parse-gram.c" +#line 2592 "src/parse-gram.c" break; - case 70: -#line 525 "src/parse-gram.y" + case 70: /* token_decl.1: token_decl.1 token_decl */ +#line 545 "src/parse-gram.y" { (yyval.yykind_80) = symbol_list_append ((yyvsp[-1].yykind_80), symbol_list_sym_new ((yyvsp[0].token_decl), (yylsp[0]))); } -#line 2592 "src/parse-gram.c" +#line 2598 "src/parse-gram.c" break; - case 71: -#line 530 "src/parse-gram.y" + case 71: /* token_decl: id int.opt alias */ +#line 550 "src/parse-gram.y" { (yyval.token_decl) = (yyvsp[-2].id); symbol_class_set ((yyvsp[-2].id), current_class, (yylsp[-2]), true); if (0 <= (yyvsp[-1].yykind_82)) - symbol_user_token_number_set ((yyvsp[-2].id), (yyvsp[-1].yykind_82), (yylsp[-1])); + symbol_code_set ((yyvsp[-2].id), (yyvsp[-1].yykind_82), (yylsp[-1])); if ((yyvsp[0].alias)) symbol_make_alias ((yyvsp[-2].id), (yyvsp[0].alias), (yylsp[0])); } -#line 2605 "src/parse-gram.c" +#line 2611 "src/parse-gram.c" break; - case 72: -#line 542 "src/parse-gram.y" + case 72: /* int.opt: %empty */ +#line 562 "src/parse-gram.y" { (yyval.yykind_82) = -1; } -#line 2611 "src/parse-gram.c" +#line 2617 "src/parse-gram.c" break; - case 74: -#line 548 "src/parse-gram.y" + case 74: /* alias: %empty */ +#line 568 "src/parse-gram.y" { (yyval.alias) = NULL; } -#line 2617 "src/parse-gram.c" +#line 2623 "src/parse-gram.c" break; - case 75: -#line 549 "src/parse-gram.y" + case 75: /* alias: string_as_id */ +#line 569 "src/parse-gram.y" { (yyval.alias) = (yyvsp[0].string_as_id); } -#line 2623 "src/parse-gram.c" +#line 2629 "src/parse-gram.c" break; - case 76: -#line 551 "src/parse-gram.y" + case 76: /* alias: "translatable string" */ +#line 571 "src/parse-gram.y" { - (yyval.alias) = symbol_get (quotearg_style (c_quoting_style, (yyvsp[0].TSTRING)), (yylsp[0])); + (yyval.alias) = symbol_get ((yyvsp[0].TSTRING), (yylsp[0])); symbol_class_set ((yyval.alias), token_sym, (yylsp[0]), false); (yyval.alias)->translatable = true; } -#line 2633 "src/parse-gram.c" +#line 2639 "src/parse-gram.c" break; - case 77: -#line 569 "src/parse-gram.y" + case 77: /* token_decls_for_prec: token_decl_for_prec.1 */ +#line 589 "src/parse-gram.y" { (yyval.token_decls_for_prec) = (yyvsp[0].yykind_85); } -#line 2641 "src/parse-gram.c" +#line 2647 "src/parse-gram.c" break; - case 78: -#line 573 "src/parse-gram.y" + case 78: /* token_decls_for_prec: "<tag>" token_decl_for_prec.1 */ +#line 593 "src/parse-gram.y" { - (yyval.token_decls_for_prec) = symbol_list_type_set ((yyvsp[0].yykind_85), (yyvsp[-1].TAG), (yylsp[-1])); + (yyval.token_decls_for_prec) = symbol_list_type_set ((yyvsp[0].yykind_85), (yyvsp[-1].TAG)); } -#line 2649 "src/parse-gram.c" +#line 2655 "src/parse-gram.c" break; - case 79: -#line 577 "src/parse-gram.y" + case 79: /* token_decls_for_prec: token_decls_for_prec "<tag>" token_decl_for_prec.1 */ +#line 597 "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_85), (yyvsp[-1].TAG), (yylsp[-1]))); + (yyval.token_decls_for_prec) = symbol_list_append ((yyvsp[-2].token_decls_for_prec), symbol_list_type_set ((yyvsp[0].yykind_85), (yyvsp[-1].TAG))); } -#line 2657 "src/parse-gram.c" +#line 2663 "src/parse-gram.c" break; - case 80: -#line 585 "src/parse-gram.y" + case 80: /* token_decl_for_prec.1: token_decl_for_prec */ +#line 605 "src/parse-gram.y" { (yyval.yykind_85) = symbol_list_sym_new ((yyvsp[0].token_decl_for_prec), (yylsp[0])); } -#line 2663 "src/parse-gram.c" +#line 2669 "src/parse-gram.c" break; - case 81: -#line 587 "src/parse-gram.y" + case 81: /* token_decl_for_prec.1: token_decl_for_prec.1 token_decl_for_prec */ +#line 607 "src/parse-gram.y" { (yyval.yykind_85) = symbol_list_append ((yyvsp[-1].yykind_85), symbol_list_sym_new ((yyvsp[0].token_decl_for_prec), (yylsp[0]))); } -#line 2669 "src/parse-gram.c" +#line 2675 "src/parse-gram.c" break; - case 82: -#line 592 "src/parse-gram.y" + case 82: /* token_decl_for_prec: id int.opt */ +#line 612 "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_82)) - symbol_user_token_number_set ((yyvsp[-1].id), (yyvsp[0].yykind_82), (yylsp[0])); + symbol_code_set ((yyvsp[-1].id), (yyvsp[0].yykind_82), (yylsp[0])); } -#line 2680 "src/parse-gram.c" +#line 2686 "src/parse-gram.c" break; - case 84: -#line 609 "src/parse-gram.y" + case 84: /* symbol_decls: symbol_decl.1 */ +#line 629 "src/parse-gram.y" { (yyval.symbol_decls) = (yyvsp[0].yykind_88); } -#line 2688 "src/parse-gram.c" +#line 2694 "src/parse-gram.c" break; - case 85: -#line 613 "src/parse-gram.y" + case 85: /* symbol_decls: "<tag>" symbol_decl.1 */ +#line 633 "src/parse-gram.y" { - (yyval.symbol_decls) = symbol_list_type_set ((yyvsp[0].yykind_88), (yyvsp[-1].TAG), (yylsp[-1])); + (yyval.symbol_decls) = symbol_list_type_set ((yyvsp[0].yykind_88), (yyvsp[-1].TAG)); } -#line 2696 "src/parse-gram.c" +#line 2702 "src/parse-gram.c" break; - case 86: -#line 617 "src/parse-gram.y" + case 86: /* symbol_decls: symbol_decls "<tag>" symbol_decl.1 */ +#line 637 "src/parse-gram.y" { - (yyval.symbol_decls) = symbol_list_append ((yyvsp[-2].symbol_decls), symbol_list_type_set ((yyvsp[0].yykind_88), (yyvsp[-1].TAG), (yylsp[-1]))); + (yyval.symbol_decls) = symbol_list_append ((yyvsp[-2].symbol_decls), symbol_list_type_set ((yyvsp[0].yykind_88), (yyvsp[-1].TAG))); } -#line 2704 "src/parse-gram.c" +#line 2710 "src/parse-gram.c" break; - case 87: -#line 625 "src/parse-gram.y" + case 87: /* symbol_decl.1: symbol */ +#line 645 "src/parse-gram.y" { symbol_class_set ((yyvsp[0].symbol), pct_type_sym, (yylsp[0]), false); (yyval.yykind_88) = symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0])); } -#line 2713 "src/parse-gram.c" +#line 2719 "src/parse-gram.c" break; - case 88: -#line 630 "src/parse-gram.y" + case 88: /* symbol_decl.1: symbol_decl.1 symbol */ +#line 650 "src/parse-gram.y" { symbol_class_set ((yyvsp[0].symbol), pct_type_sym, (yylsp[0]), false); (yyval.yykind_88) = symbol_list_append ((yyvsp[-1].yykind_88), symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0]))); } -#line 2722 "src/parse-gram.c" +#line 2728 "src/parse-gram.c" break; - case 93: -#line 651 "src/parse-gram.y" + case 93: /* rules_or_grammar_declaration: error ";" */ +#line 671 "src/parse-gram.y" { yyerrok; } -#line 2730 "src/parse-gram.c" +#line 2736 "src/parse-gram.c" break; - case 94: -#line 657 "src/parse-gram.y" + case 94: /* $@4: %empty */ +#line 677 "src/parse-gram.y" { current_lhs ((yyvsp[-1].id_colon), (yylsp[-1]), (yyvsp[0].yykind_95)); } -#line 2736 "src/parse-gram.c" +#line 2742 "src/parse-gram.c" break; - case 95: -#line 658 "src/parse-gram.y" + case 95: /* rules: id_colon named_ref.opt $@4 ":" rhses.1 */ +#line 678 "src/parse-gram.y" { /* Free the current lhs. */ current_lhs (0, (yylsp[-4]), 0); } -#line 2745 "src/parse-gram.c" +#line 2751 "src/parse-gram.c" break; - case 96: -#line 665 "src/parse-gram.y" + case 96: /* rhses.1: rhs */ +#line 685 "src/parse-gram.y" { grammar_current_rule_end ((yylsp[0])); } -#line 2751 "src/parse-gram.c" +#line 2757 "src/parse-gram.c" break; - case 97: -#line 666 "src/parse-gram.y" + case 97: /* rhses.1: rhses.1 "|" rhs */ +#line 686 "src/parse-gram.y" { grammar_current_rule_end ((yylsp[0])); } -#line 2757 "src/parse-gram.c" +#line 2763 "src/parse-gram.c" break; - case 99: -#line 673 "src/parse-gram.y" + case 99: /* rhs: %empty */ +#line 693 "src/parse-gram.y" { grammar_current_rule_begin (current_lhs_symbol, current_lhs_loc, current_lhs_named_ref); } -#line 2764 "src/parse-gram.c" - break; - - case 100: -#line 676 "src/parse-gram.y" - { grammar_current_rule_symbol_append ((yyvsp[-1].symbol), (yylsp[-1]), (yyvsp[0].yykind_95)); } #line 2770 "src/parse-gram.c" break; - case 101: -#line 678 "src/parse-gram.y" - { grammar_current_rule_action_append ((yyvsp[-1].BRACED_CODE), (yylsp[-1]), (yyvsp[0].yykind_95), (yyvsp[-2].yykind_74)); } + case 100: /* rhs: rhs symbol named_ref.opt */ +#line 696 "src/parse-gram.y" + { grammar_current_rule_symbol_append ((yyvsp[-1].symbol), (yylsp[-1]), (yyvsp[0].yykind_95)); } #line 2776 "src/parse-gram.c" break; - case 102: -#line 680 "src/parse-gram.y" - { grammar_current_rule_predicate_append ((yyvsp[0].BRACED_PREDICATE), (yylsp[0])); } + case 101: /* rhs: rhs tag.opt "{...}" named_ref.opt */ +#line 698 "src/parse-gram.y" + { grammar_current_rule_action_append ((yyvsp[-1].BRACED_CODE), (yylsp[-1]), (yyvsp[0].yykind_95), (yyvsp[-2].yykind_74)); } #line 2782 "src/parse-gram.c" break; - case 103: -#line 682 "src/parse-gram.y" - { grammar_current_rule_empty_set ((yylsp[0])); } + case 102: /* rhs: rhs "%?{...}" */ +#line 700 "src/parse-gram.y" + { grammar_current_rule_predicate_append ((yyvsp[0].BRACED_PREDICATE), (yylsp[0])); } #line 2788 "src/parse-gram.c" break; - case 104: -#line 684 "src/parse-gram.y" - { grammar_current_rule_prec_set ((yyvsp[0].symbol), (yylsp[0])); } + case 103: /* rhs: rhs "%empty" */ +#line 702 "src/parse-gram.y" + { grammar_current_rule_empty_set ((yylsp[0])); } #line 2794 "src/parse-gram.c" break; - case 105: -#line 686 "src/parse-gram.y" - { grammar_current_rule_dprec_set ((yyvsp[0].INT), (yylsp[0])); } + case 104: /* rhs: rhs "%prec" symbol */ +#line 704 "src/parse-gram.y" + { grammar_current_rule_prec_set ((yyvsp[0].symbol), (yylsp[0])); } #line 2800 "src/parse-gram.c" break; - case 106: -#line 688 "src/parse-gram.y" - { grammar_current_rule_merge_set ((yyvsp[0].TAG), (yylsp[0])); } + case 105: /* rhs: rhs "%dprec" "integer literal" */ +#line 706 "src/parse-gram.y" + { grammar_current_rule_dprec_set ((yyvsp[0].INT_LITERAL), (yylsp[0])); } #line 2806 "src/parse-gram.c" break; - case 107: -#line 690 "src/parse-gram.y" - { grammar_current_rule_expect_sr ((yyvsp[0].INT), (yylsp[0])); } + case 106: /* rhs: rhs "%merge" "<tag>" */ +#line 708 "src/parse-gram.y" + { grammar_current_rule_merge_set ((yyvsp[0].TAG), (yylsp[0])); } #line 2812 "src/parse-gram.c" break; - case 108: -#line 692 "src/parse-gram.y" - { grammar_current_rule_expect_rr ((yyvsp[0].INT), (yylsp[0])); } + case 107: /* rhs: rhs "%expect" "integer literal" */ +#line 710 "src/parse-gram.y" + { grammar_current_rule_expect_sr ((yyvsp[0].INT_LITERAL), (yylsp[0])); } #line 2818 "src/parse-gram.c" break; - case 109: -#line 696 "src/parse-gram.y" - { (yyval.yykind_95) = NULL; } + case 108: /* rhs: rhs "%expect-rr" "integer literal" */ +#line 712 "src/parse-gram.y" + { grammar_current_rule_expect_rr ((yyvsp[0].INT_LITERAL), (yylsp[0])); } #line 2824 "src/parse-gram.c" break; - case 110: -#line 697 "src/parse-gram.y" - { (yyval.yykind_95) = named_ref_new ((yyvsp[0].BRACKETED_ID), (yylsp[0])); } + case 109: /* named_ref.opt: %empty */ +#line 716 "src/parse-gram.y" + { (yyval.yykind_95) = NULL; } #line 2830 "src/parse-gram.c" break; - case 112: -#line 730 "src/parse-gram.y" - { (yyval.value).kind = muscle_keyword; (yyval.value).chars = ""; } + case 110: /* named_ref.opt: "[identifier]" */ +#line 717 "src/parse-gram.y" + { (yyval.yykind_95) = named_ref_new ((yyvsp[0].BRACKETED_ID), (yylsp[0])); } #line 2836 "src/parse-gram.c" break; - case 113: -#line 731 "src/parse-gram.y" - { (yyval.value).kind = muscle_keyword; (yyval.value).chars = (yyvsp[0].ID); } + case 112: /* value: %empty */ +#line 750 "src/parse-gram.y" + { (yyval.value).kind = muscle_keyword; (yyval.value).chars = ""; } #line 2842 "src/parse-gram.c" break; - case 114: -#line 732 "src/parse-gram.y" - { (yyval.value).kind = muscle_string; (yyval.value).chars = (yyvsp[0].STRING); } + case 113: /* value: "identifier" */ +#line 751 "src/parse-gram.y" + { (yyval.value).kind = muscle_keyword; (yyval.value).chars = (yyvsp[0].ID); } #line 2848 "src/parse-gram.c" break; - case 115: -#line 733 "src/parse-gram.y" - { (yyval.value).kind = muscle_code; (yyval.value).chars = strip_braces ((yyvsp[0].BRACED_CODE)); } + case 114: /* value: "string" */ +#line 752 "src/parse-gram.y" + { (yyval.value).kind = muscle_string; (yyval.value).chars = unquote ((yyvsp[0].STRING)); gram_scanner_last_string_free ();} #line 2854 "src/parse-gram.c" break; - case 116: -#line 746 "src/parse-gram.y" - { (yyval.id) = symbol_from_uniqstr ((yyvsp[0].ID), (yylsp[0])); } + case 115: /* value: "{...}" */ +#line 753 "src/parse-gram.y" + { (yyval.value).kind = muscle_code; (yyval.value).chars = strip_braces ((yyvsp[0].BRACED_CODE)); gram_scanner_last_string_free (); } #line 2860 "src/parse-gram.c" break; - case 117: -#line 748 "src/parse-gram.y" + case 116: /* id: "identifier" */ +#line 766 "src/parse-gram.y" + { (yyval.id) = symbol_from_uniqstr ((yyvsp[0].ID), (yylsp[0])); } +#line 2866 "src/parse-gram.c" + break; + + case 117: /* id: "character literal" */ +#line 768 "src/parse-gram.y" { const char *var = "api.token.raw"; if (current_class == nterm_sym) @@ -2877,39 +2883,39 @@ yyreduce: location loc = muscle_percent_define_get_loc (var); subcomplain (&loc, complaint, _("definition of %s"), var); } - (yyval.id) = symbol_get (char_name ((yyvsp[0].CHAR)), (yylsp[0])); + (yyval.id) = symbol_get (char_name ((yyvsp[0].CHAR_LITERAL)), (yylsp[0])); symbol_class_set ((yyval.id), token_sym, (yylsp[0]), false); - symbol_user_token_number_set ((yyval.id), (yyvsp[0].CHAR), (yylsp[0])); + symbol_code_set ((yyval.id), (yyvsp[0].CHAR_LITERAL), (yylsp[0])); } -#line 2885 "src/parse-gram.c" +#line 2891 "src/parse-gram.c" break; - case 118: -#line 771 "src/parse-gram.y" + case 118: /* id_colon: "identifier:" */ +#line 791 "src/parse-gram.y" { (yyval.id_colon) = symbol_from_uniqstr ((yyvsp[0].ID_COLON), (yylsp[0])); } -#line 2891 "src/parse-gram.c" +#line 2897 "src/parse-gram.c" break; - case 121: -#line 783 "src/parse-gram.y" + case 121: /* string_as_id: "string" */ +#line 803 "src/parse-gram.y" { - (yyval.string_as_id) = symbol_get (quotearg_style (c_quoting_style, (yyvsp[0].STRING)), (yylsp[0])); + (yyval.string_as_id) = symbol_get ((yyvsp[0].STRING), (yylsp[0])); symbol_class_set ((yyval.string_as_id), token_sym, (yylsp[0]), false); } -#line 2900 "src/parse-gram.c" +#line 2906 "src/parse-gram.c" break; - case 123: -#line 792 "src/parse-gram.y" + case 123: /* epilogue.opt: "%%" "epilogue" */ +#line 812 "src/parse-gram.y" { muscle_code_grow ("epilogue", translate_code ((yyvsp[0].EPILOGUE), (yylsp[0]), true), (yylsp[0])); code_scanner_last_string_free (); } -#line 2909 "src/parse-gram.c" +#line 2915 "src/parse-gram.c" break; -#line 2913 "src/parse-gram.c" +#line 2919 "src/parse-gram.c" default: break; } @@ -3088,13 +3094,13 @@ yyabortlab: yyexhaustedlab: yyerror (&yylloc, YY_("memory exhausted")); yyresult = 2; - /* Fall through. */ + goto yyreturn; #endif -/*-----------------------------------------------------. -| yyreturn -- parsing is finished, return the result. | -`-----------------------------------------------------*/ +/*-------------------------------------------------------. +| yyreturn -- parsing is finished, clean up and return. | +`-------------------------------------------------------*/ yyreturn: if (yychar != GRAM_EMPTY) { @@ -3124,7 +3130,7 @@ yyreturn: return yyresult; } -#line 798 "src/parse-gram.y" +#line 818 "src/parse-gram.y" int @@ -3256,6 +3262,17 @@ add_param (param_type type, char *decl, location loc) static void +handle_defines (char const *value) +{ + defines_flag = true; + char *file = unquote (value); + spec_header_file = xstrdup (file); + gram_scanner_last_string_free (); + unquote_free (file); +} + + +static void handle_error_verbose (location const *loc, char const *directive) { bison_directive (loc, directive); @@ -3267,8 +3284,9 @@ handle_error_verbose (location const *loc, char const *directive) static void handle_file_prefix (location const *loc, location const *dir_loc, - char const *directive, char const *value) + char const *directive, char const *value_quoted) { + char *value = unquote (value_quoted); bison_directive (loc, directive); bool warned = false; @@ -3288,11 +3306,18 @@ handle_file_prefix (location const *loc, deprecated_directive (dir_loc, directive, "%file-prefix"); } +static void +handle_language (location const *loc, char const *lang) +{ + language_argmatch (unquote (lang), grammar_prio, *loc); +} + static void handle_name_prefix (location const *loc, - char const *directive, char const *value) + char const *directive, char const *value_quoted) { + char *value = unquote (value_quoted); bison_directive (loc, directive); char buf1[1024]; @@ -3333,65 +3358,37 @@ handle_pure_parser (location const *loc, char const *directive) } -/* Convert VERSION into an int (MAJOR * 100 + MINOR). Return -1 on - errors. - - Changes of behavior are only on minor version changes, so "3.0.5" - is the same as "3.0": 300. */ -static int -str_to_version (char const *version) -{ - IGNORE_TYPE_LIMITS_BEGIN - int res = 0; - errno = 0; - char *cp = NULL; - long major = strtol (version, &cp, 10); - if (errno || cp == version || *cp != '.' || major < 0 - || INT_MULTIPLY_WRAPV (major, 100, &res)) - return -1; - - ++cp; - char *cp1 = NULL; - long minor = strtol (cp, &cp1, 10); - if (errno || cp1 == cp || (*cp1 != '\0' && *cp1 != '.') - || ! (0 <= minor && minor < 100) - || INT_ADD_WRAPV (minor, res, &res)) - return -1; - - IGNORE_TYPE_LIMITS_END - return res; -} - - static void -handle_require (location const *loc, char const *version) +handle_require (location const *loc, char const *version_quoted) { - required_version = str_to_version (version); + char *version = unquote (version_quoted); + required_version = strversion_to_int (version); if (required_version == -1) { complain (loc, complaint, _("invalid version requirement: %s"), version); required_version = 0; - return; } - - /* Pretend to be at least that version, to check features published - in that version while developping it. */ - const char* api_version = "3.6"; - const char* package_version = - 0 < strverscmp (api_version, PACKAGE_VERSION) - ? api_version : PACKAGE_VERSION; - if (0 < strverscmp (version, package_version)) + else { - complain (loc, complaint, _("require bison %s, but have %s"), - version, package_version); - exit (EX_MISMATCH); + const char* package_version = + 0 < strverscmp (api_version, PACKAGE_VERSION) + ? api_version : PACKAGE_VERSION; + if (0 < strverscmp (version, package_version)) + { + complain (loc, complaint, _("require bison %s, but have %s"), + version, package_version); + exit (EX_MISMATCH); + } } + unquote_free (version); + gram_scanner_last_string_free (); } static void -handle_skeleton (location const *loc, char const *skel) +handle_skeleton (location const *loc, char const *skel_quoted) { + char *skel = unquote (skel_quoted); char const *skeleton_user = skel; if (strchr (skeleton_user, '/')) { @@ -3446,8 +3443,7 @@ char_name (char c) } } -static -void +static void current_lhs (symbol *sym, location loc, named_ref *ref) { current_lhs_symbol = sym; @@ -3472,3 +3468,95 @@ static void troff (FILE *yyo) { end_use_class ("value", yyo); } + + +/*----------. +| Unquote. | +`----------*/ + +struct obstack obstack_for_unquote; + +void +parser_init (void) +{ + obstack_init (&obstack_for_unquote); +} + +void +parser_free (void) +{ + obstack_free (&obstack_for_unquote, 0); +} + +static void +unquote_free (char *last_string) +{ + obstack_free (&obstack_for_unquote, last_string); +} + +static char * +unquote (const char *cp) +{ +#define GROW(Char) \ + obstack_1grow (&obstack_for_unquote, Char); + for (++cp; *cp && *cp != '"'; ++cp) + switch (*cp) + { + case '"': + break; + case '\\': + ++cp; + switch (*cp) + { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + { + int c = cp[0] - '0'; + if (c_isdigit (cp[1])) + { + ++cp; + c = c * 8 + cp[0] - '0'; + } + if (c_isdigit (cp[1])) + { + ++cp; + c = c * 8 + cp[0] - '0'; + } + GROW (c); + } + break; + + case 'a': GROW ('\a'); break; + case 'b': GROW ('\b'); break; + case 'f': GROW ('\f'); break; + case 'n': GROW ('\n'); break; + case 'r': GROW ('\r'); break; + case 't': GROW ('\t'); break; + case 'v': GROW ('\v'); break; + + case 'x': + { + int c = 0; + while (c_isxdigit (cp[1])) + { + ++cp; + c = (c * 16 + (c_isdigit (cp[0]) ? cp[0] - '0' + : c_isupper (cp[0]) ? cp[0] - 'A' + : cp[0] - '0')); + } + GROW (c); + break; + } + } + break; + + default: + GROW (*cp); + break; + } + assert (*cp == '"'); + ++cp; + assert (*cp == '\0'); +#undef GROW + return obstack_finish0 (&obstack_for_unquote); +} diff --git a/contrib/tools/bison/src/parse-gram.h b/contrib/tools/bison/src/parse-gram.h index 3193d5af99..10f67c24cd 100644 --- a/contrib/tools/bison/src/parse-gram.h +++ b/contrib/tools/bison/src/parse-gram.h @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 3.6.4. */ +/* A Bison parser, made by GNU Bison 3.7.6. */ /* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation, + Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work @@ -57,7 +57,7 @@ extern int gram_debug; #include "symlist.h" #include "symtab.h" -#line 245 "src/parse-gram.y" +#line 269 "src/parse-gram.y" typedef enum { @@ -66,7 +66,7 @@ extern int gram_debug; param_parse = 1 << 1, param_both = param_lex | param_parse } param_type; -#line 710 "src/parse-gram.y" +#line 730 "src/parse-gram.y" #include "muscle-tab.h" typedef struct @@ -127,7 +127,7 @@ extern int gram_debug; BRACED_CODE = 41, /* "{...}" */ BRACED_PREDICATE = 42, /* "%?{...}" */ BRACKETED_ID = 43, /* "[identifier]" */ - CHAR = 44, /* "character literal" */ + CHAR_LITERAL = 44, /* "character literal" */ COLON = 45, /* ":" */ EPILOGUE = 46, /* "epilogue" */ EQUAL = 47, /* "=" */ @@ -140,7 +140,7 @@ extern int gram_debug; TAG = 54, /* "<tag>" */ TAG_ANY = 55, /* "<*>" */ TAG_NONE = 56, /* "<>" */ - INT = 57, /* "integer literal" */ + INT_LITERAL = 57, /* "integer literal" */ PERCENT_PARAM = 58, /* "%param" */ PERCENT_UNION = 59, /* "%union" */ PERCENT_EMPTY = 60 /* "%empty" */ @@ -160,7 +160,7 @@ union GRAM_STYPE char* EPILOGUE; /* "epilogue" */ char* PROLOGUE; /* "%{...%}" */ code_props_type code_props_type; /* code_props_type */ - int INT; /* "integer literal" */ + int INT_LITERAL; /* "integer literal" */ int yykind_82; /* int.opt */ named_ref* yykind_95; /* named_ref.opt */ param_type PERCENT_PARAM; /* "%param" */ @@ -192,7 +192,7 @@ union GRAM_STYPE uniqstr yykind_74; /* tag.opt */ uniqstr tag; /* tag */ uniqstr variable; /* variable */ - unsigned char CHAR; /* "character literal" */ + unsigned char CHAR_LITERAL; /* "character literal" */ value_type value; /* value */ #line 199 "src/parse-gram.h" @@ -220,5 +220,14 @@ struct GRAM_LTYPE int gram_parse (void); +/* "%code provides" blocks. */ +#line 27 "src/parse-gram.y" + + /* Initialize unquote. */ + void parser_init (void); + /* Deallocate storage for unquote. */ + void parser_free (void); + +#line 232 "src/parse-gram.h" #endif /* !YY_GRAM_SRC_PARSE_GRAM_H_INCLUDED */ diff --git a/contrib/tools/bison/src/parse-simulation.c b/contrib/tools/bison/src/parse-simulation.c new file mode 100644 index 0000000000..38f5b63935 --- /dev/null +++ b/contrib/tools/bison/src/parse-simulation.c @@ -0,0 +1,598 @@ +/* Parser simulator for unifying counterexample search + + Copyright (C) 2020-2021 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +#include "parse-simulation.h" + +#include <gl_linked_list.h> +#include <gl_xlist.h> +#include <stdlib.h> + +#include "lssi.h" +#include "nullable.h" + +struct parse_state +{ + // Path of state-items the parser has traversed. + struct si_chunk + { + // Elements newly added in this chunk. + state_item_list contents; + // Properties of the linked list this chunk represents. + const state_item *head_elt; + const state_item *tail_elt; + size_t total_size; + } state_items; + // List of derivations of the symbols. + struct deriv_chunk + { + derivation_list contents; + const derivation *head_elt; + const derivation *tail_elt; + size_t total_size; + } derivs; + struct parse_state *parent; + int reference_count; + // Incremented during productions, decremented during reductions. + int depth; + // Whether the contents of the chunks should be prepended or + // appended to the list the chunks represent. + bool prepend; + // Causes chunk contents to be freed when the reference count is + // one. Used when only the chunk metadata will be needed. + bool free_contents_early; +}; + + +static void +ps_si_prepend (parse_state *ps, const state_item *si) +{ + struct si_chunk *sic = &ps->state_items; + gl_list_add_first (sic->contents, si); + sic->head_elt = si; + ++sic->total_size; + if (!sic->tail_elt) + sic->tail_elt = si; +} + +static void +ps_si_append (parse_state *ps, const state_item *si) +{ + struct si_chunk *sic = &ps->state_items; + gl_list_add_last (sic->contents, si); + sic->tail_elt = si; + ++sic->total_size; + if (!sic->head_elt) + sic->head_elt = si; +} + +static void +ps_derivs_prepend (parse_state *ps, derivation *d) +{ + struct deriv_chunk *dc = &ps->derivs; + derivation_list_prepend (dc->contents, d); + dc->head_elt = d; + ++dc->total_size; + if (!dc->tail_elt) + dc->tail_elt = d; +} + +static void +ps_derivs_append (parse_state *ps, derivation *d) +{ + struct deriv_chunk *dc = &ps->derivs; + derivation_list_append (dc->contents, d); + dc->tail_elt = d; + ++dc->total_size; + if (!dc->head_elt) + dc->head_elt = d; +} + +static int allocs = 0; +static int frees = 0; + +static parse_state * +empty_parse_state (void) +{ + parse_state *res = xcalloc (1, sizeof *res); + res->state_items.contents + = gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true); + res->derivs.contents = derivation_list_new (); + ++allocs; + return res; +} + +parse_state * +new_parse_state (const state_item *si) +{ + parse_state *res = empty_parse_state (); + ps_si_append (res, si); + ps_derivs_append (res, derivation_dot ()); + return res; +} + +static parse_state * +copy_parse_state (bool prepend, parse_state *parent) +{ + parse_state *res = xmalloc (sizeof *res); + *res = *parent; + res->state_items.contents + = gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true); + res->derivs.contents = derivation_list_new (); + res->parent = parent; + res->prepend = prepend; + res->reference_count = 0; + res->free_contents_early = false; + parse_state_retain (parent); + ++allocs; + return res; +} + +bool +parse_state_derivation_completed (const parse_state *ps) +{ + return ps->derivs.total_size == 1; +} + +derivation * +parse_state_derivation (const parse_state *ps) +{ + return (derivation *) ps->derivs.head_elt; +} + +const state_item * +parse_state_head (const parse_state *ps) +{ + return ps->state_items.head_elt; +} + +const state_item * +parse_state_tail (const parse_state *ps) +{ + return ps->state_items.tail_elt; +} + +int +parse_state_length (const parse_state *ps) +{ + return ps->state_items.total_size; +} + +int +parse_state_depth (const parse_state *ps) +{ + return ps->depth; +} + +void +parse_state_retain (parse_state *ps) +{ + ++ps->reference_count; +} + +void +parse_state_free_contents_early (parse_state *ps) +{ + ps->free_contents_early = true; +} + +void +free_parse_state (parse_state *original_ps) +{ + bool free_contents = true; + parse_state *parent_ps = NULL; + for (parse_state *ps = original_ps; ps && free_contents; ps = parent_ps) + { + --ps->reference_count; + free_contents = (ps->reference_count == 1 && ps->free_contents_early) + || (ps->reference_count == 0 && !ps->free_contents_early); + // need to keep the parse state around for visited hash set, + // but its contents and parent can be freed + if (free_contents) + { + if (ps->state_items.contents) + gl_list_free (ps->state_items.contents); + if (ps->derivs.contents) + derivation_list_free (ps->derivs.contents); + } + parent_ps = ps->parent; + if (ps->reference_count <= 0) + { + free (ps); + ++frees; + } + } +} + +size_t +parse_state_hasher (const parse_state *ps, size_t max) +{ + const struct si_chunk *sis = &ps->state_items; + return ((state_item *) sis->head_elt - state_items + + (state_item *) sis->tail_elt - state_items + sis->total_size) % max; +} + +bool +parse_state_comparator (const parse_state *ps1, const parse_state *ps2) +{ + const struct si_chunk *sis1 = &ps1->state_items; + const struct si_chunk *sis2 = &ps2->state_items; + return sis1->head_elt == sis2->head_elt + && sis1->tail_elt == sis2->tail_elt + && sis1->total_size == sis2->total_size; +} + + +void +parse_state_completed_steps (const parse_state *ps, int *shifts, int *productions) +{ + // traverse to the root parse_state, + // which will have a list of all completed productions. + const parse_state *root_ps = ps; + while (root_ps->parent) + root_ps = root_ps->parent; + + state_item_list sis = root_ps->state_items.contents; + int count = 0; + + state_item *last = NULL; + state_item *next = NULL; + for (gl_list_iterator_t it = gl_list_iterator (sis); + state_item_list_next (&it, &next); + ) + { + if (last && last->state == next->state) + ++count; + last = next; + } + *productions = count; + *shifts = root_ps->state_items.total_size - count; +} + +typedef void (*chunk_append_fn) (gl_list_t, const void *); + +// A version of gl_list_add_last which has the chunk_append_fn +// signature. +static void +list_add_last (gl_list_t list, const void *elt) +{ + gl_list_add_last (list, elt); +} + +// takes an array of n gl_lists and flattens them into two list +// based off of the index split +static void +list_flatten_and_split (gl_list_t *list, gl_list_t *rets, int split, int n, + chunk_append_fn append_fn) +{ + int ret_index = 0; + int ret_array = 0; + for (int i = 0; i < n; ++i) + { + const void *p = NULL; + gl_list_iterator_t it = gl_list_iterator (list[i]); + while (gl_list_iterator_next (&it, &p, NULL)) + if (p) + { + gl_list_t l = (gl_list_t) p; + const void *si = NULL; + gl_list_iterator_t it2 = gl_list_iterator (l); + while (gl_list_iterator_next (&it2, &si, NULL)) + { + if (ret_index++ == split) + ++ret_array; + if (rets[ret_array]) + append_fn (rets[ret_array], si); + } + gl_list_iterator_free (&it2); + } + gl_list_iterator_free (&it); + } +} + +static parse_state_list +parse_state_list_new (void) +{ + return gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, + (gl_listelement_dispose_fn)free_parse_state, + true); +} + +static void +parse_state_list_append (parse_state_list pl, parse_state *ps) +{ + parse_state_retain (ps); + gl_list_add_last (pl, ps); +} + +// Emulates a reduction on a parse state by popping some amount of +// derivations and state_items off of the parse_state and returning +// the result in ret. Returns the derivation of what's popped. +static derivation_list +parser_pop (parse_state *ps, int deriv_index, + int si_index, parse_state *ret) +{ + // prepend sis, append sis, prepend derivs, append derivs + gl_list_t chunks[4]; + for (int i = 0; i < 4; ++i) + chunks[i] = gl_list_create_empty (GL_LINKED_LIST, NULL, NULL, NULL, true); + for (parse_state *pn = ps; pn != NULL; pn = pn->parent) + if (pn->prepend) + { + gl_list_add_last (chunks[0], pn->state_items.contents); + gl_list_add_last (chunks[2], pn->derivs.contents); + } + else + { + gl_list_add_first (chunks[1], pn->state_items.contents); + gl_list_add_first (chunks[3], pn->derivs.contents); + } + derivation_list popped_derivs = derivation_list_new (); + gl_list_t ret_chunks[4] = { ret->state_items.contents, NULL, + ret->derivs.contents, popped_derivs + }; + list_flatten_and_split (chunks, ret_chunks, si_index, 2, + list_add_last); + list_flatten_and_split (chunks + 2, ret_chunks + 2, deriv_index, 2, + (chunk_append_fn)derivation_list_append); + size_t s_size = gl_list_size (ret->state_items.contents); + ret->state_items.total_size = s_size; + if (s_size > 0) + { + ret->state_items.tail_elt = gl_list_get_at (ret->state_items.contents, + s_size - 1); + ret->state_items.head_elt = + gl_list_get_at (ret->state_items.contents, 0); + } + else + { + ret->state_items.tail_elt = NULL; + ret->state_items.head_elt = NULL; + } + size_t d_size = gl_list_size (ret->derivs.contents); + ret->derivs.total_size = d_size; + if (d_size > 0) + { + ret->derivs.tail_elt = gl_list_get_at (ret->derivs.contents, + d_size - 1); + ret->derivs.head_elt = gl_list_get_at (ret->derivs.contents, 0); + } + else + { + ret->derivs.tail_elt = NULL; + ret->derivs.head_elt = NULL; + } + for (int i = 0; i < 4; ++i) + gl_list_free (chunks[i]); + return popped_derivs; +} + +void +parse_state_lists (parse_state *ps, state_item_list *sitems, + derivation_list *derivs) +{ + parse_state *temp = empty_parse_state (); + size_t si_size = ps->state_items.total_size; + size_t deriv_size = ps->derivs.total_size; + derivation_list dl = parser_pop (ps, si_size, deriv_size, temp); + *sitems = temp->state_items.contents; + *derivs = temp->derivs.contents; + // prevent the return lists from being freed + temp->state_items.contents = NULL; + temp->derivs.contents = NULL; + free_parse_state (temp); + derivation_list_free (dl); +} + +/** + * Compute the parse states that result from taking a transition on + * nullable symbols whenever possible from the given state_item. + */ +static void +nullable_closure (parse_state *ps, state_item *si, parse_state_list state_list) +{ + parse_state *current_ps = ps; + state_item_number prev_sin = si - state_items; + for (state_item_number sin = si->trans; sin != -1; + prev_sin = sin, sin = state_items[sin].trans) + { + state_item *psi = &state_items[prev_sin]; + symbol_number sp = item_number_as_symbol_number (*psi->item); + if (ISTOKEN (sp) || !nullable[sp - ntokens]) + break; + + state_item *nsi = &state_items[sin]; + current_ps = copy_parse_state (false, current_ps); + ps_si_append (current_ps, nsi); + ps_derivs_append (current_ps, derivation_new (sp, derivation_list_new ())); + parse_state_list_append (state_list, current_ps); + } +} + +parse_state_list +simulate_transition (parse_state *ps) +{ + const state_item *si = ps->state_items.tail_elt; + symbol_number sym = item_number_as_symbol_number (*si->item); + // Transition on the same next symbol, taking nullable + // symbols into account. + parse_state_list result = parse_state_list_new (); + state_item_number si_next = si->trans; + // Check for disabled transition, shouldn't happen as any + // state_items that lead to these should be disabled. + if (si_next < 0) + return result; + parse_state *next_ps = copy_parse_state (false, ps); + ps_si_append (next_ps, &state_items[si_next]); + ps_derivs_append (next_ps, derivation_new_leaf (sym)); + parse_state_list_append (result, next_ps); + + nullable_closure (next_ps, &state_items[si_next], result); + return result; +} + +/** + * Determine if the given symbols are equal or their first sets + * intersect. + */ +static bool +compatible (symbol_number sym1, symbol_number sym2) +{ + if (sym1 == sym2) + return true; + if (ISTOKEN (sym1) && ISVAR (sym2)) + return bitset_test (FIRSTS (sym2), sym1); + else if (ISVAR (sym1) && ISTOKEN (sym2)) + return bitset_test (FIRSTS (sym1), sym2); + else if (ISVAR (sym1) && ISVAR (sym2)) + return !bitset_disjoint_p (FIRSTS (sym1), FIRSTS (sym2)); + else + return false; +} + +parse_state_list +simulate_production (parse_state *ps, symbol_number compat_sym) +{ + parse_state_list result = parse_state_list_new (); + const state_item *si = parse_state_tail (ps); + if (si->prods) + { + bitset_iterator biter; + state_item_number sin; + BITSET_FOR_EACH (biter, si->prods, sin, 0) + { + // Take production step only if lhs is not nullable and + // if first rhs symbol is compatible with compat_sym + state_item *next = &state_items[sin]; + item_number *itm1 = next->item; + if (!compatible (*itm1, compat_sym) || !production_allowed (si, next)) + continue; + parse_state *next_ps = copy_parse_state (false, ps); + ps_si_append (next_ps, next); + parse_state_list_append (result, next_ps); + if (next_ps->depth >= 0) + ++next_ps->depth; + nullable_closure (next_ps, next, result); + } + } + return result; +} + +// simulates a reduction on the given parse state, conflict_item is the +// item associated with ps's conflict. symbol_set is a lookahead set this +// reduction must be compatible with +parse_state_list +simulate_reduction (parse_state *ps, int rule_len, bitset symbol_set) +{ + parse_state_list result = parse_state_list_new (); + + int s_size = ps->state_items.total_size; + int d_size = ps->derivs.total_size; + if (ps->depth >= 0) + d_size--; // account for dot + parse_state *new_root = empty_parse_state (); + derivation_list popped_derivs = + parser_pop (ps, d_size - rule_len, + s_size - rule_len - 1, new_root); + + // update derivation + state_item *si = (state_item *) ps->state_items.tail_elt; + const rule *r = item_rule (si->item); + symbol_number lhs = r->lhs->number; + derivation *deriv = derivation_new (lhs, popped_derivs); + --new_root->depth; + ps_derivs_append (new_root, deriv); + + if (s_size != rule_len + 1) + { + state_item *tail = (state_item *) new_root->state_items.tail_elt; + ps_si_append (new_root, &state_items[tail->trans]); + parse_state_list_append (result, new_root); + } + else + { + // The head state_item is a production item, so we need to prepend + // with possible source state-items. + const state_item *head = ps->state_items.head_elt; + state_item_list prev = lssi_reverse_production (head, symbol_set); + // TODO: better understand what causes this case. + if (gl_list_size (prev) == 0) + { + // new_root needs to have an RC of 1 to be freed correctly here. + parse_state_retain (new_root); + free_parse_state (new_root); + } + else + { + state_item *psis = NULL; + for (gl_list_iterator_t it = gl_list_iterator (prev); + state_item_list_next (&it, &psis); + ) + { + // Prepend the result from the reverse production. + parse_state *copy = copy_parse_state (true, new_root); + ps_si_prepend (copy, psis); + + // Append the left hand side to the end of the parser state + copy = copy_parse_state (false, copy); + struct si_chunk *sis = ©->state_items; + const state_item *tail = sis->tail_elt; + ps_si_append (copy, &state_items[tail->trans]); + parse_state_list_append (result, copy); + nullable_closure (copy, (state_item *) sis->tail_elt, result); + } + } + gl_list_free (prev); + } + return result; +} + +parse_state_list +parser_prepend (parse_state *ps) +{ + parse_state_list res = parse_state_list_new (); + const state_item *head = ps->state_items.head_elt; + symbol_number prepend_sym = + item_number_as_symbol_number (*(head->item - 1)); + bitset_iterator biter; + state_item_number sin; + BITSET_FOR_EACH (biter, head->revs, sin, 0) + { + parse_state *copy = copy_parse_state (true, ps); + ps_si_prepend (copy, &state_items[sin]); + if (SI_TRANSITION (head)) + ps_derivs_prepend (copy, derivation_new_leaf (prepend_sym)); + parse_state_list_append (res, copy); + } + return res; +} + +void +print_parse_state (parse_state *ps) +{ + FILE *out = stderr; + fprintf (out, "(size %zu depth %d rc %d)\n", + ps->state_items.total_size, ps->depth, ps->reference_count); + state_item_print (ps->state_items.head_elt, out, ""); + state_item_print (ps->state_items.tail_elt, out, ""); + if (ps->derivs.total_size > 0) + derivation_print (ps->derivs.head_elt, out, ""); + putc ('\n', out); +} diff --git a/contrib/tools/bison/src/parse-simulation.h b/contrib/tools/bison/src/parse-simulation.h new file mode 100644 index 0000000000..aa8f84e5ae --- /dev/null +++ b/contrib/tools/bison/src/parse-simulation.h @@ -0,0 +1,146 @@ +/* Parser simulator for unifying counterexample search + + Copyright (C) 2020-2021 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef PARSE_SIMULATION_H +# define PARSE_SIMULATION_H + +# include <stdio.h> +# include <gl_xlist.h> + +# include "derivation.h" +# include "state-item.h" + +/* + Simulating states of the parser: + Each state is an array of state-items and an array of derivations. + Each consecutive state-item represents a transition/goto or production, + and the derivations are the derivation trees associated with the symbols + transitioned on each step. In more detail: + + Parse states are stored as a tree. Each new parse state contains two "chunks," + one corresponding to its state-items and the other corresponding to its derivations. + Chunks only have new elements which weren't present in its parent. + Each chunk also stores the head, tail, and total_size of the list it represents. + So if a parse state was to be copied it retains the list metadata but its + contents are empty. + + A transition gets the state-item which the last state-item of the parse state + transitions to. This is appended to the state-item list, and a derivation with + just the symbol being transitioned on is appended to the derivation list. + A production appends the new state-item, but does not have a derivation + associated with it. + + A reduction looks at the rule of the last state-item in the state, and pops + the last few state-items that make up the rhs of the rule along with their + derivations. The derivations become the derivation of the lhs which is then + shifted over. + + Effectively, every time a derivation is appended, it represents a shift in + the parser. So a parse state that contains + start: A . B C D + start: A B C D . + and the state-items in between will represent a parser that has BCD on the + parse stack. + + However, the above example cannot be reduced, as it's missing A. + Since we start at a state-item that can have a dot in the middle of a rule, + it's necessary to support a prepend operation. Luckily the prepend operations + are very similar to transitions and productions with the difference being that + they operate on the head of the state-item list instead of the tail. + + A production + A transition gets the state-item which the last state-item of the parse state + transitions to. This is appended to the state-item list, and a derivation with + just the symbol being transitioned on is appended to the derivation list. + + */ + +typedef struct parse_state parse_state; +typedef gl_list_t parse_state_list; + +static inline bool +parse_state_list_next (gl_list_iterator_t *it, parse_state **ps) +{ + const void *p = NULL; + bool res = gl_list_iterator_next (it, &p, NULL); + if (res) + *ps = (parse_state *) p; + else + gl_list_iterator_free (it); + return res; +} + +parse_state *new_parse_state (const state_item *conflict); + +size_t parse_state_hasher (const parse_state *ps, size_t max); + +bool parse_state_comparator (const parse_state *ps1, const parse_state *ps2); + +/* Memory management */ + +void parse_state_retain (parse_state *ps); +/* This allows a parse_state to free its contents list + * when its reference count reaches 1. This is used to + * free memory while the parse state is in a hash set. */ +void parse_state_free_contents_early (parse_state *ps); +void free_parse_state (parse_state *ps); + +/* counts the amount of shift and production steps in this parse state */ +void parse_state_completed_steps (const parse_state *ps, int *shifts, int *productions); + +/* parse state getters */ +bool parse_state_derivation_completed (const parse_state *ps); +derivation *parse_state_derivation (const parse_state *ps); +const state_item *parse_state_head (const parse_state *ps); +const state_item *parse_state_tail (const parse_state *ps); +int parse_state_length (const parse_state *ps); +int parse_state_depth (const parse_state *ps); + +/* returns the linked lists that the parse state is supposed to represent */ +void parse_state_lists (parse_state *ps, state_item_list *state_items, + derivation_list *derivs); + +/* various functions that return a list of states based off of + * whatever operation is simulated. After whatever operation, every possible + * transition on nullable nonterminals will be added to the returned list. */ + +/* Look at the tail state-item of the parse state and transition on the symbol + * after its dot. The symbol gets added to derivs, and the resulting state-item + * is appended to state-items. */ +parse_state_list simulate_transition (parse_state *ps); + +/* Look at all of the productions for the nonterminal following the dot in the tail + * state-item. Appends to state-items each production state-item which may start with + * compat_sym. */ +parse_state_list simulate_production (parse_state *ps, symbol_number compat_sym); + +/* Removes the last rule_len state-items along with their derivations. A new state-item is + * appended representing the goto after the reduction. A derivation for the nonterminal that + * was just reduced is appended which consists of the list of derivations that were just removed. */ +parse_state_list simulate_reduction (parse_state *ps, int rule_len, + bitset symbol_set); + +/* Generate states with a state-item prepended for each state-item that has a + * transition or production step to ps's head. */ +parse_state_list parser_prepend (parse_state *ps); + +/* For debugging traces. */ +void print_parse_state (parse_state *ps); + +#endif /* PARSE_SIMULATION_H */ diff --git a/contrib/tools/bison/src/print-graph.c b/contrib/tools/bison/src/print-graph.c index 1dd6b15e7c..3ddf6a54d3 100644 --- a/contrib/tools/bison/src/print-graph.c +++ b/contrib/tools/bison/src/print-graph.c @@ -1,6 +1,6 @@ /* Output a graph of the generated parser, for Bison. - Copyright (C) 2001-2007, 2009-2015, 2018-2020 Free Software + Copyright (C) 2001-2007, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> #include "print-graph.h" @@ -47,7 +47,7 @@ static void print_core (struct obstack *oout, state *s) { - item_number const *sitems = s->items; + item_index const *sitems = s->items; sym_content *previous_lhs = NULL; size_t snritems = s->nitems; @@ -72,22 +72,31 @@ print_core (struct obstack *oout, state *s) obstack_printf (oout, "%*s| ", (int) strlen (previous_lhs->symbol->tag), ""); else - obstack_printf (oout, "%s: ", escape (r->lhs->symbol->tag)); + { + obstack_backslash (oout, r->lhs->symbol->tag); + obstack_printf (oout, ": "); + } previous_lhs = r->lhs; for (item_number const *sp = r->rhs; sp < sp1; sp++) - obstack_printf (oout, "%s ", escape (symbols[*sp]->tag)); + { + obstack_backslash (oout, symbols[*sp]->tag); + obstack_1grow (oout, ' '); + } - obstack_1grow (oout, '.'); + obstack_sgrow (oout, "•"); if (0 <= *r->rhs) for (item_number const *sp = sp1; 0 <= *sp; ++sp) - obstack_printf (oout, " %s", escape (symbols[*sp]->tag)); + { + obstack_1grow (oout, ' '); + obstack_backslash (oout, symbols[*sp]->tag); + } else - obstack_printf (oout, " %%empty"); + obstack_sgrow (oout, " %empty"); /* Experimental feature: display the lookahead tokens. */ - if (report_flag & report_lookahead_tokens + if (report_flag & report_lookaheads && item_number_is_rule_number (*sp1)) { /* Find the reduction we are handling. */ @@ -95,16 +104,16 @@ print_core (struct obstack *oout, state *s) int redno = state_reduction_find (s, r); /* Print them if there are. */ - if (reds->lookahead_tokens && redno != -1) + if (reds->lookaheads && redno != -1) { bitset_iterator biter; int k; char const *sep = ""; obstack_sgrow (oout, " ["); - BITSET_FOR_EACH (biter, reds->lookahead_tokens[redno], k, 0) + BITSET_FOR_EACH (biter, reds->lookaheads[redno], k, 0) { obstack_sgrow (oout, sep); - obstack_sgrow (oout, escape (symbols[k]->tag)); + obstack_backslash (oout, symbols[k]->tag); sep = ", "; } obstack_1grow (oout, ']'); diff --git a/contrib/tools/bison/src/print-graph.h b/contrib/tools/bison/src/print-graph.h index c31a5ca28a..6aa3420ab3 100644 --- a/contrib/tools/bison/src/print-graph.h +++ b/contrib/tools/bison/src/print-graph.h @@ -1,6 +1,6 @@ /* Output a graph of the generated parser, for Bison. - Copyright (C) 2000, 2006, 2009-2015, 2018-2020 Free Software + Copyright (C) 2000, 2006, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef PRINT_GRAPH_H_ # define PRINT_GRAPH_H_ diff --git a/contrib/tools/bison/src/print-xml.c b/contrib/tools/bison/src/print-xml.c index 61fb93b4bf..a61a5c8569 100644 --- a/contrib/tools/bison/src/print-xml.c +++ b/contrib/tools/bison/src/print-xml.c @@ -1,6 +1,6 @@ /* Print an xml on generated parser, for Bison, - Copyright (C) 2007, 2009-2015, 2018-2020 Free Software Foundation, + Copyright (C) 2007, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> #include "print-xml.h" @@ -57,7 +57,7 @@ static struct escape_buf escape_bufs[num_escape_bufs]; static void print_core (FILE *out, int level, state *s) { - item_number *sitems = s->items; + item_index *sitems = s->items; size_t snritems = s->nitems; /* Output all the items of a state, not only its kernel. */ @@ -86,12 +86,12 @@ print_core (FILE *out, int level, state *s) reductions *reds = s->reductions; int red = state_reduction_find (s, r); /* Print item with lookaheads if there are. */ - if (reds->lookahead_tokens && red != -1) + if (reds->lookaheads && red != -1) { xml_printf (out, level + 1, - "<item rule-number=\"%d\" point=\"%d\">", + "<item rule-number=\"%d\" dot=\"%d\">", r->number, sp1 - sp); - state_rule_lookahead_tokens_print_xml (s, r, + state_rule_lookaheads_print_xml (s, r, out, level + 2); xml_puts (out, level + 1, "</item>"); printed = true; @@ -100,7 +100,7 @@ print_core (FILE *out, int level, state *s) if (!printed) xml_printf (out, level + 1, - "<item rule-number=\"%d\" point=\"%d\"/>", + "<item rule-number=\"%d\" dot=\"%d\"/>", r->number, sp1 - sp); } @@ -202,26 +202,26 @@ print_errs (FILE *out, int level, state *s) } -/*-------------------------------------------------------------------------. -| Report a reduction of RULE on LOOKAHEAD_TOKEN (which can be 'default'). | -| If not ENABLED, the rule is masked by a shift or a reduce (S/R and | -| R/R conflicts). | -`-------------------------------------------------------------------------*/ +/*-------------------------------------------------------------------. +| Report a reduction of RULE on LOOKAHEAD (which can be 'default'). | +| If not ENABLED, the rule is masked by a shift or a reduce (S/R and | +| R/R conflicts). | +`-------------------------------------------------------------------*/ static void -print_reduction (FILE *out, int level, char const *lookahead_token, +print_reduction (FILE *out, int level, char const *lookahead, rule *r, bool enabled) { if (r->number) xml_printf (out, level, "<reduction symbol=\"%s\" rule=\"%d\" enabled=\"%s\"/>", - xml_escape (lookahead_token), + xml_escape (lookahead), r->number, enabled ? "true" : "false"); else xml_printf (out, level, "<reduction symbol=\"%s\" rule=\"accept\" enabled=\"%s\"/>", - xml_escape (lookahead_token), + xml_escape (lookahead), enabled ? "true" : "false"); } @@ -258,13 +258,13 @@ print_reductions (FILE *out, int level, state *s) if (default_reduction) report = true; - if (reds->lookahead_tokens) + if (reds->lookaheads) for (i = 0; i < ntokens; i++) { bool count = bitset_test (no_reduce_set, i); for (j = 0; j < reds->num; ++j) - if (bitset_test (reds->lookahead_tokens[j], i)) + if (bitset_test (reds->lookaheads[j], i)) { if (! count) { @@ -289,14 +289,14 @@ print_reductions (FILE *out, int level, state *s) xml_puts (out, level, "<reductions>"); /* Report lookahead tokens (or $default) and reductions. */ - if (reds->lookahead_tokens) + if (reds->lookaheads) for (i = 0; i < ntokens; i++) { bool defaulted = false; bool count = bitset_test (no_reduce_set, i); for (j = 0; j < reds->num; ++j) - if (bitset_test (reds->lookahead_tokens[j], i)) + if (bitset_test (reds->lookaheads[j], i)) { if (! count) { @@ -379,17 +379,20 @@ print_grammar (FILE *out, int level) /* Terminals */ xml_puts (out, level + 1, "<terminals>"); - for (symbol_number i = 0; i < max_user_token_number + 1; i++) + for (int i = 0; i < max_code + 1; i++) if (token_translations[i] != undeftoken->content->number) { - char const *tag = symbols[token_translations[i]]->tag; - int precedence = symbols[token_translations[i]]->content->prec; - assoc associativity = symbols[token_translations[i]]->content->assoc; + symbol const *sym = symbols[token_translations[i]]; + char const *tag = sym->tag; + char const *type = sym->content->type_name; + int precedence = sym->content->prec; + assoc associativity = sym->content->assoc; xml_indent (out, level + 2); fprintf (out, "<terminal symbol-number=\"%d\" token-number=\"%d\"" - " name=\"%s\" usefulness=\"%s\"", - token_translations[i], i, xml_escape (tag), + " name=\"%s\" type=\"%s\" usefulness=\"%s\"", + token_translations[i], i, xml_escape_n (0, tag), + type ? xml_escape_n (1, type) : "", reduce_token_unused_in_grammar (token_translations[i]) ? "unused-in-grammar" : "useful"); if (precedence) @@ -404,12 +407,16 @@ print_grammar (FILE *out, int level) xml_puts (out, level + 1, "<nonterminals>"); for (symbol_number i = ntokens; i < nsyms + nuseless_nonterminals; i++) { - char const *tag = symbols[i]->tag; + symbol const *sym = symbols[i]; + char const *tag = sym->tag; + char const *type = sym->content->type_name; xml_printf (out, level + 2, "<nonterminal symbol-number=\"%d\" name=\"%s\"" + " type=\"%s\"" " usefulness=\"%s\"/>", - i, xml_escape (tag), - reduce_nonterminal_useless_in_grammar (symbols[i]->content) + i, xml_escape_n (0, tag), + type ? xml_escape_n (1, type) : "", + reduce_nonterminal_useless_in_grammar (sym->content) ? "useless-in-grammar" : "useful"); } xml_puts (out, level + 1, "</nonterminals>"); diff --git a/contrib/tools/bison/src/print-xml.h b/contrib/tools/bison/src/print-xml.h index c057780b93..d190d74ab6 100644 --- a/contrib/tools/bison/src/print-xml.h +++ b/contrib/tools/bison/src/print-xml.h @@ -1,6 +1,6 @@ /* Output an xml of the generated parser, for Bison. - Copyright (C) 2007, 2009-2015, 2018-2020 Free Software Foundation, + Copyright (C) 2007, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,13 +16,11 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef PRINT_XML_H_ # define PRINT_XML_H_ -# include <config.h> - # include <stdio.h> void xml_indent (FILE *out, int level); diff --git a/contrib/tools/bison/src/print.c b/contrib/tools/bison/src/print.c index 259c16b3f5..a924bbb1e7 100644 --- a/contrib/tools/bison/src/print.c +++ b/contrib/tools/bison/src/print.c @@ -1,6 +1,6 @@ /* Print information on generated parser, for bison, - Copyright (C) 1984, 1986, 1989, 2000-2005, 2007, 2009-2015, 2018-2020 + Copyright (C) 1984, 1986, 1989, 2000-2005, 2007, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,22 +16,27 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> + +#include "print.h" + #include "system.h" #include <bitset.h> +#include <mbswidth.h> #include "closure.h" +#include "complain.h" #include "conflicts.h" +#include "counterexample.h" #include "files.h" #include "getargs.h" #include "gram.h" #include "lalr.h" #include "lr0.h" #include "muscle-tab.h" -#include "print.h" #include "reader.h" #include "reduce.h" #include "state.h" @@ -49,7 +54,7 @@ static bitset no_reduce_set; static void max_length (size_t *width, const char *str) { - size_t len = strlen (str); + size_t len = mbswidth (str, 0); if (len > *width) *width = len; } @@ -59,9 +64,9 @@ max_length (size_t *width, const char *str) `--------------------------------*/ static void -print_core (FILE *out, state *s) +print_core (FILE *out, const state *s) { - item_number *sitems = s->items; + const item_index *sitems = s->items; size_t snritems = s->nitems; /* Output all the items of a state, not only its kernel. */ if (report_flag & report_itemsets) @@ -85,9 +90,9 @@ print_core (FILE *out, state *s) previous_rule = r; /* Display the lookahead tokens? */ - if (report_flag & report_lookahead_tokens + if (report_flag & report_lookaheads && item_number_is_rule_number (*sp1)) - state_rule_lookahead_tokens_print (s, r, out); + state_rule_lookaheads_print (s, r, out); fputc ('\n', out); } } @@ -99,7 +104,7 @@ print_core (FILE *out, state *s) `------------------------------------------------------------*/ static void -print_transitions (state *s, FILE *out, bool display_transitions_p) +print_transitions (const state *s, FILE *out, bool display_transitions_p) { transitions *trans = s->transitions; size_t width = 0; @@ -127,10 +132,10 @@ print_transitions (state *s, FILE *out, bool display_transitions_p) { symbol *sym = symbols[TRANSITION_SYMBOL (trans, i)]; const char *tag = sym->tag; - state *s1 = trans->states[i]; + const state *s1 = trans->states[i]; fprintf (out, " %s", tag); - for (int j = width - strlen (tag); j > 0; --j) + for (int j = width - mbswidth (tag, 0); j > 0; --j) fputc (' ', out); if (display_transitions_p) fprintf (out, _("shift, and go to state %d\n"), s1->number); @@ -145,7 +150,7 @@ print_transitions (state *s, FILE *out, bool display_transitions_p) `--------------------------------------------------------*/ static void -print_errs (FILE *out, state *s) +print_errs (FILE *out, const state *s) { errs *errp = s->errs; size_t width = 0; @@ -168,26 +173,26 @@ print_errs (FILE *out, state *s) { const char *tag = errp->symbols[i]->tag; fprintf (out, " %s", tag); - for (int j = width - strlen (tag); j > 0; --j) + for (int j = width - mbswidth (tag, 0); j > 0; --j) fputc (' ', out); fputs (_("error (nonassociative)\n"), out); } } -/*-------------------------------------------------------------------------. -| Report a reduction of RULE on LOOKAHEAD_TOKEN (which can be 'default'). | -| If not ENABLED, the rule is masked by a shift or a reduce (S/R and | -| R/R conflicts). | -`-------------------------------------------------------------------------*/ +/*-------------------------------------------------------------------. +| Report a reduction of RULE on LOOKAHEAD (which can be 'default'). | +| If not ENABLED, the rule is masked by a shift or a reduce (S/R and | +| R/R conflicts). | +`-------------------------------------------------------------------*/ static void print_reduction (FILE *out, size_t width, - const char *lookahead_token, + const char *lookahead, rule *r, bool enabled) { - fprintf (out, " %s", lookahead_token); - for (int j = width - strlen (lookahead_token); j > 0; --j) + fprintf (out, " %s", lookahead); + for (int j = width - mbswidth (lookahead, 0); j > 0; --j) fputc (' ', out); if (!enabled) fputc ('[', out); @@ -207,7 +212,7 @@ print_reduction (FILE *out, size_t width, `-------------------------------------------*/ static void -print_reductions (FILE *out, state *s) +print_reductions (FILE *out, const state *s) { reductions *reds = s->reductions; if (reds->num == 0) @@ -232,15 +237,15 @@ print_reductions (FILE *out, state *s) /* Compute the width of the lookahead token column. */ size_t width = 0; if (default_reduction) - width = strlen (_("$default")); + width = mbswidth (_("$default"), 0); - if (reds->lookahead_tokens) + if (reds->lookaheads) for (int i = 0; i < ntokens; i++) { bool count = bitset_test (no_reduce_set, i); for (int j = 0; j < reds->num; ++j) - if (bitset_test (reds->lookahead_tokens[j], i)) + if (bitset_test (reds->lookaheads[j], i)) { if (! count) { @@ -263,7 +268,7 @@ print_reductions (FILE *out, state *s) bool default_reduction_only = true; /* Report lookahead tokens (or $default) and reductions. */ - if (reds->lookahead_tokens) + if (reds->lookaheads) for (int i = 0; i < ntokens; i++) { bool defaulted = false; @@ -272,7 +277,7 @@ print_reductions (FILE *out, state *s) default_reduction_only = false; for (int j = 0; j < reds->num; ++j) - if (bitset_test (reds->lookahead_tokens[j], i)) + if (bitset_test (reds->lookaheads[j], i)) { if (! count) { @@ -323,7 +328,7 @@ print_reductions (FILE *out, state *s) `--------------------------------------------------------------*/ static void -print_actions (FILE *out, state *s) +print_actions (FILE *out, const state *s) { /* Print shifts. */ print_transitions (s, out, true); @@ -339,7 +344,7 @@ print_actions (FILE *out, state *s) `----------------------------------*/ static void -print_state (FILE *out, state *s) +print_state (FILE *out, const state *s) { fputs ("\n\n", out); fprintf (out, _("State %d"), s->number); @@ -351,6 +356,13 @@ print_state (FILE *out, state *s) fputc ('\n', out); fputs (s->solved_conflicts, out); } + if (has_conflicts (s) + && (report_flag & report_cex + || warning_is_enabled (Wcounterexamples))) + { + fputc ('\n', out); + counterexample_report_state (s, out, " "); + } } /*-----------------------------------------. @@ -362,14 +374,14 @@ print_terminal_symbols (FILE *out) { /* TERMINAL (type #) : rule #s terminal is on RHS */ fprintf (out, "%s\n\n", _("Terminals, with rules where they appear")); - for (symbol_number i = 0; i < max_user_token_number + 1; i++) + for (int i = 0; i < max_code + 1; ++i) if (token_translations[i] != undeftoken->content->number) { - const char *tag = symbols[token_translations[i]]->tag; + const symbol *sym = symbols[token_translations[i]]; + const char *tag = sym->tag; fprintf (out, "%4s%s", "", tag); - if (symbols[token_translations[i]]->content->type_name) - fprintf (out, " <%s>", - symbols[token_translations[i]]->content->type_name); + if (sym->content->type_name) + fprintf (out, " <%s>", sym->content->type_name); fprintf (out, " (%d)", i); for (rule_number r = 0; r < nrules; r++) @@ -391,7 +403,8 @@ print_nonterminal_symbols (FILE *out) fprintf (out, "%s\n\n", _("Nonterminals, with rules where they appear")); for (symbol_number i = ntokens; i < nsyms; i++) { - const char *tag = symbols[i]->tag; + const symbol *sym = symbols[i]; + const char *tag = sym->tag; bool on_left = false; bool on_right = false; @@ -404,11 +417,11 @@ print_nonterminal_symbols (FILE *out) break; } - int column = 4 + strlen (tag); + int column = 4 + mbswidth (tag, 0); fprintf (out, "%4s%s", "", tag); - if (symbols[i]->content->type_name) + if (sym->content->type_name) column += fprintf (out, " <%s>", - symbols[i]->content->type_name); + sym->content->type_name); fprintf (out, " (%d)\n", i); if (on_left) @@ -445,7 +458,7 @@ print_results (void) reduce_output (out); grammar_rules_partial_print (out, _("Rules useless in parser due to conflicts"), - rule_useless_in_parser_p); + rule_useless_in_parser_p); conflicts_output (out); grammar_rules_print (out); diff --git a/contrib/tools/bison/src/print.h b/contrib/tools/bison/src/print.h index 027abce46c..3f20d6da58 100644 --- a/contrib/tools/bison/src/print.h +++ b/contrib/tools/bison/src/print.h @@ -1,6 +1,6 @@ /* Print information on generated parser, for bison, - Copyright (C) 2000, 2009-2015, 2018-2020 Free Software Foundation, + Copyright (C) 2000, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef PRINT_H_ # define PRINT_H_ diff --git a/contrib/tools/bison/src/reader.c b/contrib/tools/bison/src/reader.c index bffca16d83..cc8efaf315 100644 --- a/contrib/tools/bison/src/reader.c +++ b/contrib/tools/bison/src/reader.c @@ -1,7 +1,7 @@ /* Input parser for Bison Copyright (C) 1984, 1986, 1989, 1992, 1998, 2000-2003, 2005-2007, - 2009-2015, 2018-2020 Free Software Foundation, Inc. + 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> #include "system.h" @@ -41,7 +41,7 @@ static void check_and_convert_grammar (void); static symbol_list *grammar = NULL; static bool start_flag = false; -merger_list *merge_functions; +merger_list *merge_functions = NULL; /* Was %union seen? */ bool union_seen = false; @@ -93,27 +93,27 @@ get_merge_function (uniqstr name) syms->next->name = uniqstr_new (name); /* After all symbol type declarations have been parsed, packgram invokes record_merge_function_type to set the type. */ - syms->next->type = NULL; + syms->next->sym = NULL; syms->next->next = NULL; merge_functions = head.next; } return n; } -/*-------------------------------------------------------------------------. -| For the existing merging function with index MERGER, record the result | -| type as TYPE as required by the lhs of the rule whose %merge declaration | -| is at DECLARATION_LOC. | -`-------------------------------------------------------------------------*/ +/*-------------------------------------------------------------------. +| For the existing merging function with index MERGER, record that | +| the result type is that of SYM, as required by the lhs (i.e., SYM) | +| of the rule whose %merge declaration is at DECLARATION_LOC. | +`-------------------------------------------------------------------*/ static void -record_merge_function_type (int merger, uniqstr type, location declaration_loc) +record_merge_function_type (int merger, symbol *sym, location declaration_loc) { if (merger <= 0) return; - if (type == NULL) - type = uniqstr_new (""); + uniqstr type + = sym->content->type_name ? sym->content->type_name : uniqstr_new (""); merger_list *merge_function; int merger_find = 1; @@ -122,18 +122,24 @@ record_merge_function_type (int merger, uniqstr type, location declaration_loc) merge_function = merge_function->next) merger_find += 1; aver (merge_function != NULL && merger_find == merger); - if (merge_function->type != NULL && !UNIQSTR_EQ (merge_function->type, type)) + if (merge_function->sym && merge_function->sym->content->type_name) + { + if (!UNIQSTR_EQ (merge_function->sym->content->type_name, type)) + { + complain (&declaration_loc, complaint, + _("result type clash on merge function %s: " + "<%s> != <%s>"), + quote (merge_function->name), type, + merge_function->sym->content->type_name); + subcomplain (&merge_function->type_declaration_loc, complaint, + _("previous declaration")); + } + } + else { - complain (&declaration_loc, complaint, - _("result type clash on merge function %s: " - "<%s> != <%s>"), - quote (merge_function->name), type, - merge_function->type); - subcomplain (&merge_function->type_declaration_loc, complaint, - _("previous declaration")); + merge_function->sym = sym; + merge_function->type_declaration_loc = declaration_loc; } - merge_function->type = uniqstr_new (type); - merge_function->type_declaration_loc = declaration_loc; } /*--------------------------------------. @@ -406,8 +412,8 @@ grammar_midrule_action (void) action. Create the MIDRULE. */ location dummy_loc = current_rule->action_props.location; symbol *dummy = dummy_symbol_get (dummy_loc); - symbol_type_set(dummy, - current_rule->action_props.type, current_rule->action_props.location); + symbol_type_set (dummy, + current_rule->action_props.type, current_rule->action_props.location); symbol_list *midrule = symbol_list_sym_new (dummy, dummy_loc); /* Remember named_ref of previous action. */ @@ -576,8 +582,8 @@ grammar_current_rule_predicate_append (const char *pred, location loc) /* is_predicate */ true); } -/* Set the expected number of shift-reduce (reduce-reduce) conflicts for - * the current rule. If a midrule is encountered later, the count +/* Set the expected number of shift/reduce (reduce/reduce) conflicts + * for the current rule. If a midrule is encountered later, the count * is transferred to it and reset in the current rule to -1. */ void @@ -616,7 +622,7 @@ packgram (void) for (symbol_list *p = grammar; p; p = p->next) { symbol_list *lhs = p; - record_merge_function_type (lhs->merger, lhs->content.sym->content->type_name, + record_merge_function_type (lhs->merger, lhs->content.sym, lhs->merger_declaration_loc); /* If the midrule's $$ is set or its $n is used, remove the '$' from the symbol name so that it's a user-defined symbol so that the default @@ -634,7 +640,7 @@ packgram (void) if (lhs != grammar) grammar_rule_check_and_complete (lhs); - rules[ruleno].user_number = ruleno; + rules[ruleno].code = ruleno; rules[ruleno].number = ruleno; rules[ruleno].lhs = lhs->content.sym->content; rules[ruleno].rhs = ritem + itemno; @@ -695,12 +701,10 @@ packgram (void) } -/*------------------------------------------------------------------. -| Read in the grammar specification and record it in the format | -| described in gram.h. All actions are copied into ACTION_OBSTACK, | -| in each case forming the body of a C function (YYACTION) which | -| contains a switch statement to decide which action to execute. | -`------------------------------------------------------------------*/ +/*--------------------------------------------------------------. +| Read in the grammar specification and record it in the format | +| described in gram.h. | +`--------------------------------------------------------------*/ void reader (const char *gram) @@ -710,6 +714,7 @@ reader (const char *gram) symbols_new (); gram_scanner_open (gram); + parser_init (); gram_parse (); gram_scanner_close (); @@ -775,18 +780,18 @@ check_and_convert_grammar (void) if (nrules == 0) complain (NULL, fatal, _("no rules in the input grammar")); - /* If the user did not define her ENDTOKEN, do it now. */ - if (!endtoken) + /* If the user did not define her EOFTOKEN, do it now. */ + if (!eoftoken) { - endtoken = symbol_get ("YYEOF", empty_loc); - endtoken->content->class = token_sym; - endtoken->content->number = 0; + eoftoken = symbol_get ("YYEOF", empty_loc); + eoftoken->content->class = token_sym; + eoftoken->content->number = 0; /* Value specified by POSIX. */ - endtoken->content->user_token_number = 0; + eoftoken->content->code = 0; { symbol *alias = symbol_get ("$end", empty_loc); symbol_class_set (alias, token_sym, empty_loc, false); - symbol_make_alias (endtoken, alias, empty_loc); + symbol_make_alias (eoftoken, alias, empty_loc); } } @@ -805,10 +810,10 @@ check_and_convert_grammar (void) $accept: %start $end. */ { - symbol_list *p = symbol_list_sym_new (accept, empty_loc); + symbol_list *p = symbol_list_sym_new (acceptsymbol, empty_loc); p->rhs_loc = grammar->rhs_loc; p->next = symbol_list_sym_new (startsymbol, empty_loc); - p->next->next = symbol_list_sym_new (endtoken, empty_loc); + p->next->next = symbol_list_sym_new (eoftoken, empty_loc); p->next->next->next = symbol_list_sym_new (NULL, empty_loc); p->next->next->next->next = grammar; nrules += 1; @@ -816,8 +821,11 @@ check_and_convert_grammar (void) grammar = p; } - aver (nsyms <= SYMBOL_NUMBER_MAXIMUM); - aver (nsyms == ntokens + nvars); + if (SYMBOL_NUMBER_MAXIMUM - nnterms < ntokens) + complain (NULL, fatal, "too many symbols in input grammar (limit is %d)", + SYMBOL_NUMBER_MAXIMUM); + + nsyms = ntokens + nnterms; /* Assign the symbols their symbol numbers. */ symbols_pack (); diff --git a/contrib/tools/bison/src/reader.h b/contrib/tools/bison/src/reader.h index 6b4f57ff1a..1d5635c91b 100644 --- a/contrib/tools/bison/src/reader.h +++ b/contrib/tools/bison/src/reader.h @@ -1,6 +1,6 @@ /* Input parser for Bison - Copyright (C) 2000-2003, 2005-2007, 2009-2015, 2018-2020 Free + Copyright (C) 2000-2003, 2005-2007, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef READER_H_ # define READER_H_ @@ -31,7 +31,10 @@ typedef struct merger_list { struct merger_list* next; uniqstr name; - uniqstr type; + /* One symbol whose type is the one used by all the symbols on which + this merging function is used. */ + symbol *sym; + /* Where SYM was bound to this merging function. */ location type_declaration_loc; } merger_list; diff --git a/contrib/tools/bison/src/reduce.c b/contrib/tools/bison/src/reduce.c index 4ed8531ecc..294e0a0318 100644 --- a/contrib/tools/bison/src/reduce.c +++ b/contrib/tools/bison/src/reduce.c @@ -1,6 +1,6 @@ /* Grammar reduction for Bison. - Copyright (C) 1988-1989, 2000-2003, 2005-2015, 2018-2020 Free + Copyright (C) 1988-1989, 2000-2003, 2005-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ /* Reduce the grammar: Find and eliminate unreachable terminals, @@ -93,7 +93,7 @@ useless_nonterminals (void) /* N is set as built. Np is set being built this iteration. P is set of all productions which have a RHS all in N. */ - bitset Np = bitset_create (nvars, BITSET_FIXED); + bitset Np = bitset_create (nnterms, BITSET_FIXED); /* The set being computed is a set of nonterminals which can derive the empty string or strings consisting of all terminals. At each @@ -160,9 +160,9 @@ inaccessable_symbols (void) bitset Pp = bitset_create (nrules, BITSET_FIXED); /* If the start symbol isn't useful, then nothing will be useful. */ - if (bitset_test (N, accept->content->number - ntokens)) + if (bitset_test (N, acceptsymbol->content->number - ntokens)) { - bitset_set (V, accept->content->number); + bitset_set (V, acceptsymbol->content->number); while (1) { @@ -188,7 +188,7 @@ inaccessable_symbols (void) /* These tokens (numbered 0, 1, and 2) are internal to Bison. Consider them useful. */ - bitset_set (V, endtoken->content->number); /* end-of-input token */ + bitset_set (V, eoftoken->content->number); /* end-of-input token */ bitset_set (V, errtoken->content->number); /* error token */ bitset_set (V, undeftoken->content->number); /* some undefined token */ @@ -201,7 +201,7 @@ inaccessable_symbols (void) int nuseful_nonterminals = 0; for (symbol_number i = ntokens; i < nsyms; ++i) nuseful_nonterminals += bitset_test (V, i); - nuseless_nonterminals = nvars - nuseful_nonterminals; + nuseless_nonterminals = nnterms - nuseful_nonterminals; /* A token that was used in %prec should not be warned about. */ for (rule_number r = 0; r < nrules; ++r) @@ -263,7 +263,7 @@ symbol_number *nterm_map = NULL; static void nonterminals_reduce (void) { - nterm_map = xnmalloc (nvars, sizeof *nterm_map); + nterm_map = xnmalloc (nnterms, sizeof *nterm_map); /* Map the nonterminals to their new index: useful first, useless afterwards. Kept for later report. */ { @@ -284,7 +284,7 @@ nonterminals_reduce (void) /* Shuffle elements of tables indexed by symbol number. */ { - symbol **symbols_sorted = xnmalloc (nvars, sizeof *symbols_sorted); + symbol **symbols_sorted = xnmalloc (nnterms, sizeof *symbols_sorted); for (symbol_number i = ntokens; i < nsyms; ++i) symbols[i]->content->number = nterm_map[i - ntokens]; for (symbol_number i = ntokens; i < nsyms; ++i) @@ -301,11 +301,11 @@ nonterminals_reduce (void) for (item_number *rhsp = rules[r].rhs; 0 <= *rhsp; ++rhsp) if (ISVAR (*rhsp)) *rhsp = symbol_number_as_item_number (nterm_map[*rhsp - ntokens]); - accept->content->number = nterm_map[accept->content->number - ntokens]; + acceptsymbol->content->number = nterm_map[acceptsymbol->content->number - ntokens]; } nsyms -= nuseless_nonterminals; - nvars -= nuseless_nonterminals; + nnterms -= nuseless_nonterminals; } @@ -368,7 +368,7 @@ reduce_grammar (void) { /* Allocate the global sets used to compute the reduced grammar */ - N = bitset_create (nvars, BITSET_FIXED); + N = bitset_create (nnterms, BITSET_FIXED); P = bitset_create (nrules, BITSET_FIXED); V = bitset_create (nsyms, BITSET_FIXED); V1 = bitset_create (nsyms, BITSET_FIXED); @@ -381,7 +381,7 @@ reduce_grammar (void) { reduce_print (); - if (!bitset_test (N, accept->content->number - ntokens)) + if (!bitset_test (N, acceptsymbol->content->number - ntokens)) complain (&startsymbol_loc, fatal, _("start symbol %s does not derive any sentence"), startsymbol->tag); @@ -401,7 +401,7 @@ reduce_grammar (void) fprintf (stderr, "reduced %s defines %d terminals, %d nonterminals" ", and %d productions.\n", - grammar_file, ntokens, nvars, nrules); + grammar_file, ntokens, nnterms, nrules); } } diff --git a/contrib/tools/bison/src/reduce.h b/contrib/tools/bison/src/reduce.h index e55bedb80b..63d6bf132e 100644 --- a/contrib/tools/bison/src/reduce.h +++ b/contrib/tools/bison/src/reduce.h @@ -1,6 +1,6 @@ /* Grammar reduction for Bison. - Copyright (C) 2000-2002, 2007, 2009-2015, 2018-2020 Free Software + Copyright (C) 2000-2002, 2007, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef REDUCE_H_ # define REDUCE_H_ @@ -33,7 +33,7 @@ bool reduce_nonterminal_useless_in_grammar (const sym_content *sym); void reduce_free (void); /** Map initial nterm numbers to the new ones. Built by - * reduce_grammar. Size nvars + nuseless_nonterminals. */ + * reduce_grammar. Size nnterms + nuseless_nonterminals. */ extern symbol_number *nterm_map; extern int nuseless_nonterminals; diff --git a/contrib/tools/bison/src/relation.c b/contrib/tools/bison/src/relation.c index e9c5008603..1a38c863d5 100644 --- a/contrib/tools/bison/src/relation.c +++ b/contrib/tools/bison/src/relation.c @@ -1,6 +1,6 @@ /* Binary relations. - Copyright (C) 2002, 2004-2005, 2009-2015, 2018-2020 Free Software + Copyright (C) 2002, 2004-2005, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> #include "system.h" diff --git a/contrib/tools/bison/src/relation.h b/contrib/tools/bison/src/relation.h index 143663934b..eab6b330a1 100644 --- a/contrib/tools/bison/src/relation.h +++ b/contrib/tools/bison/src/relation.h @@ -1,6 +1,6 @@ /* Binary relations. - Copyright (C) 2002, 2004, 2009-2015, 2018-2020 Free Software + Copyright (C) 2002, 2004, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef RELATION_H_ diff --git a/contrib/tools/bison/src/scan-code.c b/contrib/tools/bison/src/scan-code.c index 86e264fbee..f144e6f595 100644 --- a/contrib/tools/bison/src/scan-code.c +++ b/contrib/tools/bison/src/scan-code.c @@ -852,7 +852,7 @@ char *yytext; #line 1 "/Users/akim/src/gnu/bison/src/scan-code.l" /* Bison Action Scanner -*- C -*- - Copyright (C) 2006-2015, 2018-2020 Free Software Foundation, Inc. + Copyright (C) 2006-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -867,25 +867,25 @@ char *yytext; GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #define YY_NO_INPUT 1 #line 24 "/Users/akim/src/gnu/bison/src/scan-code.l" #include <c-ctype.h> #include <get-errno.h> #include <quote.h> -#include <src/complain.h> -#include <src/getargs.h> -#include <src/muscle-tab.h> -#include <src/reader.h> -#include <src/scan-code.h> -#include <src/symlist.h> +#include "src/complain.h" +#include "src/getargs.h" +#include "src/muscle-tab.h" +#include "src/reader.h" +#include "src/scan-code.h" +#include "src/symlist.h" #define FLEX_PREFIX(Id) code_ ## Id -#include <src/flex-scanner.h> +#include "src/flex-scanner.h" /* Work around a bug in flex 2.5.31. See Debian bug 333231 - <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=333231>. */ + <https://bugs.debian.org/333231>. */ #undef code_wrap #define code_wrap() 1 @@ -1315,7 +1315,7 @@ case 1: /* rule 1 can match eol */ YY_RULE_SETUP #line 116 "/Users/akim/src/gnu/bison/src/scan-code.l" -STRING_GROW; BEGIN sc_context; +STRING_GROW (); BEGIN sc_context; YY_BREAK /*--------------------------------------------------------------. @@ -1327,13 +1327,13 @@ case 2: /* rule 2 can match eol */ YY_RULE_SETUP #line 126 "/Users/akim/src/gnu/bison/src/scan-code.l" -STRING_GROW; BEGIN sc_context; +STRING_GROW (); BEGIN sc_context; YY_BREAK case 3: /* rule 3 can match eol */ YY_RULE_SETUP #line 127 "/Users/akim/src/gnu/bison/src/scan-code.l" -STRING_GROW; +STRING_GROW (); YY_BREAK /*--------------------------------------------. @@ -1345,7 +1345,7 @@ case 4: /* rule 4 can match eol */ YY_RULE_SETUP #line 137 "/Users/akim/src/gnu/bison/src/scan-code.l" -STRING_GROW; +STRING_GROW (); YY_BREAK @@ -1353,7 +1353,7 @@ STRING_GROW; case 5: YY_RULE_SETUP #line 142 "/Users/akim/src/gnu/bison/src/scan-code.l" -STRING_GROW; BEGIN sc_context; +STRING_GROW (); BEGIN sc_context; YY_BREAK @@ -1361,7 +1361,7 @@ STRING_GROW; BEGIN sc_context; case 6: YY_RULE_SETUP #line 147 "/Users/akim/src/gnu/bison/src/scan-code.l" -STRING_GROW; BEGIN sc_context; +STRING_GROW (); BEGIN sc_context; YY_BREAK @@ -1369,24 +1369,24 @@ STRING_GROW; BEGIN sc_context; case 7: YY_RULE_SETUP #line 153 "/Users/akim/src/gnu/bison/src/scan-code.l" -STRING_GROW; BEGIN SC_CHARACTER; +STRING_GROW (); BEGIN SC_CHARACTER; YY_BREAK case 8: YY_RULE_SETUP #line 154 "/Users/akim/src/gnu/bison/src/scan-code.l" -STRING_GROW; BEGIN SC_STRING; +STRING_GROW (); BEGIN SC_STRING; YY_BREAK case 9: /* rule 9 can match eol */ YY_RULE_SETUP #line 155 "/Users/akim/src/gnu/bison/src/scan-code.l" -STRING_GROW; BEGIN SC_COMMENT; +STRING_GROW (); BEGIN SC_COMMENT; YY_BREAK case 10: /* rule 10 can match eol */ YY_RULE_SETUP #line 156 "/Users/akim/src/gnu/bison/src/scan-code.l" -STRING_GROW; BEGIN SC_LINE_COMMENT; +STRING_GROW (); BEGIN SC_LINE_COMMENT; YY_BREAK case 11: YY_RULE_SETUP @@ -1458,7 +1458,7 @@ case 17: /* rule 17 can match eol */ YY_RULE_SETUP #line 203 "/Users/akim/src/gnu/bison/src/scan-code.l" -STRING_GROW; +STRING_GROW (); YY_BREAK /* End of processing. */ case YY_STATE_EOF(INITIAL): @@ -1469,7 +1469,7 @@ case YY_STATE_EOF(SC_CHARACTER): case YY_STATE_EOF(SC_RULE_ACTION): case YY_STATE_EOF(SC_SYMBOL_ACTION): #line 206 "/Users/akim/src/gnu/bison/src/scan-code.l" -STRING_FINISH; return last_string; +STRING_FINISH (); return last_string; YY_BREAK case 18: @@ -3213,7 +3213,7 @@ code_props_translate_code (code_props *self) void code_scanner_last_string_free (void) { - STRING_FREE; + STRING_FREE (); } void diff --git a/contrib/tools/bison/src/scan-code.h b/contrib/tools/bison/src/scan-code.h index 06b6a73a1e..bb31a51483 100644 --- a/contrib/tools/bison/src/scan-code.h +++ b/contrib/tools/bison/src/scan-code.h @@ -1,6 +1,6 @@ /* Bison code properties structure and scanner. - Copyright (C) 2006-2007, 2009-2015, 2018-2020 Free Software + Copyright (C) 2006-2007, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef SCAN_CODE_H_ # define SCAN_CODE_H_ @@ -145,6 +145,7 @@ void code_props_symbol_action_init (code_props *self, char const *code, location code_loc); /** + * \param type type for midrule actions * \pre * - <tt>self != NULL</tt>. * - <tt>code != NULL</tt>. diff --git a/contrib/tools/bison/src/scan-gram.c b/contrib/tools/bison/src/scan-gram.c index 2c439869ac..0d52c61bb1 100644 --- a/contrib/tools/bison/src/scan-gram.c +++ b/contrib/tools/bison/src/scan-gram.c @@ -691,8 +691,8 @@ static void yynoreturn yy_fatal_error ( const char* msg ); /* %% [3.0] code to copy yytext_ptr to yytext[] goes here, if %array \ */\ (yy_c_buf_p) = yy_cp; /* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */ -#define YY_NUM_RULES 130 -#define YY_END_OF_BUFFER 131 +#define YY_NUM_RULES 131 +#define YY_END_OF_BUFFER 132 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -700,75 +700,75 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static const flex_int16_t yy_accept[608] = +static const flex_int16_t yy_accept[606] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 92, 92, 114, 114, 114, 114, - 0, 0, 0, 0, 131, 79, 2, 2, 2, 69, + 0, 0, 0, 0, 92, 92, 115, 115, 115, 115, + 0, 0, 0, 0, 132, 79, 2, 2, 2, 69, 79, 68, 79, 1, 64, 79, 65, 65, 60, 63, 76, 61, 64, 78, 64, 72, 62, 79, 89, 89, - 89, 129, 129, 98, 129, 97, 129, 129, 129, 129, - 129, 129, 129, 129, 80, 94, 129, 93, 96, 129, - 83, 2, 2, 1, 83, 82, 81, 83, 100, 100, - 101, 99, 80, 120, 129, 119, 129, 129, 129, 123, - - 126, 127, 129, 91, 129, 129, 118, 129, 117, 129, - 116, 129, 115, 86, 2, 2, 1, 84, 86, 86, - 85, 86, 87, 2, 2, 1, 87, 87, 79, 2, - 77, 59, 0, 59, 59, 59, 59, 59, 59, 59, + 89, 130, 130, 98, 130, 97, 114, 130, 130, 130, + 130, 130, 130, 130, 80, 94, 93, 96, 130, 83, + 2, 2, 1, 83, 82, 81, 83, 100, 100, 101, + 99, 80, 121, 130, 120, 130, 130, 130, 124, 127, + + 128, 130, 91, 130, 130, 119, 130, 118, 130, 117, + 130, 116, 86, 2, 2, 1, 84, 86, 86, 85, + 86, 87, 2, 2, 1, 87, 87, 79, 2, 77, + 59, 0, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, - 59, 71, 64, 64, 4, 3, 67, 65, 67, 0, - 75, 0, 0, 89, 88, 98, 113, 113, 111, 102, - 113, 104, 105, 106, 107, 108, 109, 113, 110, 113, - 129, 0, 0, 0, 0, 0, 0, 94, 95, 100, - 100, 101, 128, 121, 122, 0, 124, 0, 123, 125, - - 0, 90, 0, 91, 0, 92, 0, 118, 114, 114, - 114, 114, 114, 116, 86, 84, 59, 0, 0, 73, + 71, 64, 64, 4, 3, 67, 65, 67, 0, 75, + 0, 0, 89, 88, 98, 113, 113, 111, 102, 113, + 104, 105, 106, 107, 108, 109, 113, 110, 113, 130, + 0, 0, 0, 0, 0, 0, 95, 100, 100, 101, + 129, 122, 123, 0, 125, 0, 124, 126, 0, 90, + + 0, 91, 0, 92, 0, 119, 115, 115, 115, 115, + 115, 117, 86, 84, 59, 0, 0, 73, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, - 59, 3, 67, 66, 74, 70, 0, 102, 0, 0, - 103, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 3, + 67, 66, 74, 70, 0, 102, 0, 0, 103, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 59, 59, 59, 59, 59, 59, 59, + 0, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 0, + 102, 0, 0, 59, 7, 59, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 21, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, - 59, 0, 102, 0, 0, 59, 7, 59, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, - 21, 59, 59, 59, 59, 59, 59, 59, 59, 59, - 59, 59, 59, 59, 59, 33, 59, 59, 59, 59, - 59, 59, 40, 59, 43, 59, 59, 46, 0, 0, - 0, 59, 8, 59, 59, 59, 13, 14, 59, 59, - 59, 59, 59, 59, 59, 59, 59, 24, 59, 59, - 59, 59, 59, 59, 59, 29, 59, 31, 59, 59, - - 59, 59, 59, 37, 59, 39, 41, 44, 59, 0, - 0, 112, 6, 59, 10, 59, 59, 59, 15, 59, - 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, - 59, 59, 59, 30, 59, 59, 59, 59, 59, 59, - 59, 59, 59, 0, 59, 11, 59, 59, 59, 59, + 59, 59, 59, 33, 59, 59, 59, 59, 59, 59, + 40, 59, 43, 59, 59, 46, 0, 0, 0, 59, + 8, 59, 59, 59, 13, 14, 59, 59, 59, 59, + 59, 59, 59, 59, 59, 24, 59, 59, 59, 59, + 59, 59, 59, 29, 59, 31, 59, 59, 59, 59, + + 59, 37, 59, 39, 41, 44, 59, 0, 0, 112, + 6, 59, 10, 59, 59, 59, 15, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, - 59, 59, 59, 59, 59, 0, 57, 59, 59, 35, - 59, 36, 59, 59, 59, 45, 5, 0, 0, 59, + 59, 30, 59, 59, 59, 59, 59, 59, 59, 59, + 59, 0, 59, 11, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, - 20, 59, 59, 59, 59, 26, 59, 56, 27, 59, - - 59, 59, 59, 38, 59, 59, 0, 59, 59, 59, - 59, 59, 16, 52, 59, 59, 59, 59, 22, 23, - 59, 59, 59, 59, 59, 59, 59, 59, 59, 0, - 0, 59, 59, 12, 59, 59, 59, 59, 19, 59, - 59, 59, 59, 59, 59, 34, 59, 59, 59, 0, - 59, 59, 59, 59, 17, 59, 59, 49, 59, 59, - 59, 32, 47, 42, 58, 9, 50, 59, 59, 0, - 53, 59, 59, 49, 49, 59, 59, 59, 48, 51, - 59, 59, 49, 59, 59, 59, 59, 18, 59, 59, - 59, 59, 25, 55, 59, 59, 59, 59, 59, 54, - - 59, 59, 59, 59, 59, 28, 0 + 59, 59, 59, 0, 57, 59, 59, 35, 59, 36, + 59, 59, 59, 45, 5, 0, 0, 59, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 59, 20, 59, + 59, 59, 59, 26, 59, 56, 27, 59, 59, 59, + + 59, 38, 59, 59, 0, 59, 59, 59, 59, 59, + 16, 52, 59, 59, 59, 59, 22, 23, 59, 59, + 59, 59, 59, 59, 59, 59, 59, 0, 0, 59, + 59, 12, 59, 59, 59, 59, 19, 59, 59, 59, + 59, 59, 59, 34, 59, 59, 59, 0, 59, 59, + 59, 59, 17, 59, 59, 49, 59, 59, 59, 32, + 47, 42, 58, 9, 50, 59, 59, 0, 53, 59, + 59, 49, 49, 59, 59, 59, 48, 51, 59, 59, + 49, 59, 59, 59, 59, 18, 59, 59, 59, 59, + 25, 55, 59, 59, 59, 59, 59, 54, 59, 59, + + 59, 59, 59, 28, 0 } ; static const YY_CHAR yy_ec[256] = @@ -815,153 +815,153 @@ static const YY_CHAR yy_meta[75] = 1, 1, 1, 8 } ; -static const flex_int16_t yy_base[626] = +static const flex_int16_t yy_base[624] = { 0, - 0, 1358, 70, 71, 85, 159, 89, 90, 99, 100, + 0, 1357, 70, 71, 85, 159, 89, 90, 99, 100, 110, 163, 105, 110, 172, 184, 231, 242, 251, 269, 289, 316, 303, 325, 204, 209, 307, 349, 350, 353, - 427, 1357, 195, 364, 1365, 0, 1368, 1368, 1361, 1368, - 492, 1368, 1368, 1368, 552, 63, 59, 103, 0, 1368, - 73, 1368, 0, 1368, 1351, 1368, 1368, 1315, 1368, 1358, - 1342, 1368, 1368, 1368, 1356, 1368, 622, 73, 1292, 76, - 18, 0, 80, 1293, 1368, 1368, 1353, 1368, 1368, 1342, - 1368, 1368, 1351, 1368, 190, 1368, 1368, 1306, 1336, 104, - 1327, 1368, 1334, 1368, 1287, 1368, 203, 101, 137, 1368, - - 1368, 1368, 185, 1368, 1345, 342, 1368, 1344, 1368, 391, - 1368, 1343, 1368, 0, 1368, 1342, 0, 0, 226, 1368, - 1368, 1297, 1368, 1368, 1340, 1368, 243, 1295, 0, 1368, - 1368, 0, 502, 1296, 1290, 135, 215, 1294, 1291, 1288, - 234, 1295, 283, 1279, 211, 241, 63, 229, 1285, 1292, - 1295, 1368, 0, 0, 1368, 0, 0, 381, 647, 1305, - 1368, 1322, 1284, 1368, 1368, 1368, 1368, 1325, 1368, 154, - 653, 1368, 1368, 1368, 1368, 1368, 1368, 677, 1368, 683, - 1368, 339, 342, 345, 348, 351, 354, 1368, 1368, 1311, - 285, 1302, 1368, 1368, 1368, 508, 1368, 552, 1368, 1368, - - 632, 1368, 641, 1368, 705, 1291, 1321, 1368, 1368, 724, - 1289, 1319, 729, 1368, 0, 0, 0, 734, 1318, 1368, - 1271, 1279, 616, 1265, 1266, 1263, 1264, 158, 1261, 1268, - 1263, 193, 1272, 1257, 1261, 273, 1267, 1252, 1253, 290, - 1252, 1252, 1260, 1261, 1264, 1247, 1253, 1247, 1252, 1243, - 1256, 0, 0, 0, 1368, 1368, 1245, 276, 722, 728, - 758, 451, 461, 511, 750, 357, 1290, 769, 264, 1289, - 778, 364, 1288, 786, 594, 1287, 799, 804, 1286, 809, - 814, 628, 1285, 1250, 1245, 1229, 335, 1229, 1242, 1227, - 1231, 1239, 1238, 1237, 1261, 1221, 1232, 1219, 1257, 1235, - - 1228, 1229, 345, 520, 151, 1216, 1217, 466, 1228, 1217, - 1224, 1208, 1219, 1215, 1208, 1212, 1218, 1217, 1207, 1218, - 1216, 1213, 1368, 802, 808, 1200, 0, 1209, 1195, 1201, - 1196, 1209, 1188, 1193, 1206, 1228, 1203, 1191, 1196, 1184, - 0, 1188, 1183, 1196, 326, 1195, 1190, 1193, 1188, 1178, - 1190, 1182, 1173, 1180, 1186, 1185, 1170, 616, 1179, 1168, - 1181, 1166, 0, 1171, 0, 1170, 1168, 0, 1211, 832, - 838, 1157, 0, 1168, 1173, 1157, 0, 0, 645, 1157, - 1160, 647, 1173, 1172, 1171, 1170, 1161, 0, 1154, 1162, - 1154, 1160, 1152, 1146, 1144, 0, 1143, 0, 1181, 1156, - - 1154, 1143, 1140, 0, 1137, 0, 818, 0, 1137, 680, - 862, 1368, 0, 1135, 1135, 1149, 1130, 1129, 819, 1132, - 1134, 1130, 1135, 1138, 1127, 1129, 1125, 1140, 1135, 1138, - 1133, 1123, 1131, 860, 1120, 1129, 1116, 1131, 1126, 1116, - 1110, 1109, 1122, 887, 820, 0, 1107, 1120, 1119, 1106, - 1105, 1116, 1100, 1101, 1138, 1112, 1115, 1102, 1109, 1093, - 1094, 1091, 1092, 1106, 1091, 892, 1368, 1106, 1093, 0, - 1088, 0, 1091, 1102, 1101, 0, 1368, 1134, 1128, 1084, - 1083, 1083, 1079, 1078, 1077, 1076, 1086, 1072, 1085, 1088, - 0, 1076, 1069, 1080, 1074, 0, 1073, 0, 0, 1062, - - 1042, 1043, 1027, 0, 1040, 1039, 1055, 976, 975, 974, - 987, 984, 0, 0, 976, 969, 904, 917, 0, 0, - 910, 893, 892, 895, 896, 890, 883, 876, 869, 907, - 881, 846, 819, 0, 788, 783, 774, 774, 0, 771, - 767, 852, 889, 775, 745, 0, 733, 744, 735, 418, - 719, 711, 692, 691, 907, 689, 668, 916, 654, 618, - 620, 0, 0, 0, 0, 0, 0, 616, 614, 924, - 1368, 898, 601, 933, 940, 597, 595, 586, 0, 0, - 597, 580, 948, 573, 572, 530, 533, 0, 531, 527, - 518, 471, 0, 0, 383, 348, 370, 311, 281, 0, - - 292, 228, 157, 92, 53, 0, 1368, 958, 970, 982, - 994, 1006, 1018, 1025, 1028, 1035, 1041, 1053, 1065, 1075, - 1082, 1085, 1092, 1100, 1107 + 427, 1356, 195, 364, 1364, 0, 1367, 1367, 1360, 1367, + 492, 1367, 1367, 1367, 552, 63, 59, 103, 0, 1367, + 73, 1367, 0, 1367, 1350, 1367, 1367, 1314, 1367, 1357, + 1341, 1367, 1367, 1367, 1355, 1367, 622, 73, 1291, 76, + 18, 0, 80, 1292, 1367, 1367, 1367, 1367, 1342, 1367, + 1367, 1351, 1367, 190, 1367, 1367, 1306, 1336, 104, 1327, + 1367, 1334, 1367, 1287, 1367, 203, 101, 137, 1367, 1367, + + 1367, 185, 1367, 1345, 342, 1367, 1344, 1367, 391, 1367, + 1343, 1367, 0, 1367, 1342, 0, 0, 226, 1367, 1367, + 1297, 1367, 1367, 1340, 1367, 243, 1295, 0, 1367, 1367, + 0, 502, 1296, 1290, 135, 215, 1294, 1291, 1288, 234, + 1295, 283, 1279, 211, 241, 63, 229, 1285, 1292, 1295, + 1367, 0, 0, 1367, 0, 0, 381, 647, 1305, 1367, + 1322, 1284, 1367, 1367, 1367, 1367, 1325, 1367, 154, 653, + 1367, 1367, 1367, 1367, 1367, 1367, 677, 1367, 683, 1367, + 339, 342, 345, 348, 351, 354, 1367, 1311, 285, 1302, + 1367, 1367, 1367, 508, 1367, 552, 1367, 1367, 632, 1367, + + 641, 1367, 705, 1291, 1321, 1367, 1367, 724, 1289, 1319, + 729, 1367, 0, 0, 0, 734, 1318, 1367, 1271, 1279, + 616, 1265, 1266, 1263, 1264, 158, 1261, 1268, 1263, 193, + 1272, 1257, 1261, 273, 1267, 1252, 1253, 290, 1252, 1252, + 1260, 1261, 1264, 1247, 1253, 1247, 1252, 1243, 1256, 0, + 0, 0, 1367, 1367, 1245, 276, 722, 728, 758, 451, + 461, 511, 750, 357, 1290, 769, 264, 1289, 778, 364, + 1288, 786, 594, 1287, 799, 804, 1286, 809, 814, 628, + 1285, 1250, 1245, 1229, 335, 1229, 1242, 1227, 1231, 1239, + 1238, 1237, 1261, 1221, 1232, 1219, 1257, 1235, 1228, 1229, + + 345, 520, 151, 1216, 1217, 466, 1228, 1217, 1224, 1208, + 1219, 1215, 1208, 1212, 1218, 1217, 1207, 1218, 1216, 1213, + 1367, 802, 808, 1200, 0, 1209, 1195, 1201, 1196, 1209, + 1188, 1193, 1206, 1228, 1203, 1191, 1196, 1184, 0, 1188, + 1183, 1196, 326, 1195, 1190, 1193, 1188, 1178, 1190, 1182, + 1173, 1180, 1186, 1185, 1170, 616, 1179, 1168, 1181, 1166, + 0, 1171, 0, 1170, 1168, 0, 1211, 832, 838, 1157, + 0, 1168, 1173, 1157, 0, 0, 645, 1157, 1160, 647, + 1173, 1172, 1171, 1170, 1161, 0, 1154, 1162, 1154, 1160, + 1152, 1146, 1144, 0, 1143, 0, 1181, 1156, 1154, 1143, + + 1140, 0, 1137, 0, 818, 0, 1137, 680, 862, 1367, + 0, 1135, 1135, 1149, 1130, 1129, 819, 1132, 1134, 1130, + 1135, 1138, 1127, 1129, 1125, 1140, 1135, 1138, 1133, 1123, + 1131, 860, 1120, 1129, 1116, 1131, 1126, 1116, 1110, 1109, + 1122, 887, 820, 0, 1107, 1120, 1119, 1106, 1105, 1116, + 1100, 1101, 1138, 1112, 1115, 1102, 1109, 1093, 1094, 1091, + 1092, 1106, 1091, 892, 1367, 1106, 1093, 0, 1088, 0, + 1091, 1102, 1101, 0, 1367, 1134, 1128, 1084, 1083, 1083, + 1079, 1078, 1077, 1076, 1086, 1072, 1085, 1088, 0, 1076, + 1069, 1080, 1074, 0, 1073, 0, 0, 1062, 1042, 1043, + + 1027, 0, 1040, 1039, 1055, 976, 975, 974, 987, 984, + 0, 0, 976, 969, 904, 917, 0, 0, 910, 893, + 892, 895, 896, 890, 883, 876, 869, 907, 881, 846, + 819, 0, 788, 783, 774, 774, 0, 771, 767, 852, + 889, 775, 745, 0, 733, 744, 735, 418, 719, 711, + 692, 691, 907, 689, 668, 916, 654, 618, 620, 0, + 0, 0, 0, 0, 0, 616, 614, 924, 1367, 898, + 601, 933, 940, 597, 595, 586, 0, 0, 597, 580, + 948, 573, 572, 530, 533, 0, 531, 527, 518, 471, + 0, 0, 383, 348, 370, 311, 281, 0, 292, 228, + + 157, 92, 53, 0, 1367, 958, 970, 982, 994, 1006, + 1018, 1025, 1028, 1035, 1041, 1053, 1065, 1075, 1082, 1085, + 1092, 1100, 1107 } ; -static const flex_int16_t yy_def[626] = +static const flex_int16_t yy_def[624] = { 0, - 607, 1, 608, 608, 609, 609, 6, 6, 6, 6, - 610, 610, 611, 611, 6, 6, 6, 6, 6, 6, + 605, 1, 606, 606, 607, 607, 6, 6, 6, 6, + 608, 608, 609, 609, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 607, 31, 612, 612, 607, 613, 607, 607, 607, 607, - 607, 607, 607, 607, 607, 607, 614, 614, 613, 607, - 607, 607, 615, 607, 615, 607, 607, 613, 607, 607, - 607, 607, 607, 607, 607, 607, 616, 607, 607, 607, - 607, 617, 607, 607, 607, 607, 607, 607, 607, 607, - 607, 607, 607, 607, 607, 607, 607, 607, 618, 618, - 607, 607, 618, 607, 607, 607, 607, 607, 607, 607, - - 607, 607, 607, 607, 607, 607, 607, 607, 607, 619, - 607, 607, 607, 620, 607, 607, 620, 621, 607, 607, - 607, 620, 607, 607, 607, 607, 607, 607, 613, 607, - 607, 622, 607, 622, 622, 622, 622, 622, 622, 622, - 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, - 622, 607, 45, 615, 607, 623, 624, 614, 624, 607, - 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, - 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, - 607, 607, 607, 607, 607, 607, 607, 607, 607, 618, - 618, 607, 607, 607, 607, 607, 607, 607, 607, 607, - - 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, - 607, 607, 607, 607, 620, 621, 622, 607, 607, 607, - 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, - 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, - 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, - 622, 623, 624, 159, 607, 607, 607, 607, 607, 607, - 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, - 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, - 607, 619, 607, 622, 622, 622, 622, 622, 622, 622, - 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, - - 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, - 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, - 622, 607, 607, 607, 607, 622, 622, 622, 622, 622, - 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, - 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, - 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, - 622, 622, 622, 622, 622, 622, 622, 622, 607, 607, - 607, 622, 622, 622, 622, 622, 622, 622, 622, 622, - 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, - 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, - - 622, 622, 622, 622, 622, 622, 622, 622, 622, 607, - 607, 607, 622, 622, 622, 622, 622, 622, 622, 622, - 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, - 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, - 622, 622, 622, 607, 622, 622, 622, 622, 622, 622, - 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, - 622, 622, 622, 622, 622, 607, 607, 622, 622, 622, - 622, 622, 622, 622, 622, 622, 607, 607, 607, 622, - 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, - 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, - - 622, 622, 622, 622, 622, 622, 625, 622, 622, 622, - 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, - 622, 622, 622, 622, 622, 622, 622, 622, 622, 625, - 625, 622, 622, 622, 622, 622, 622, 622, 622, 622, - 622, 622, 622, 622, 622, 622, 622, 622, 622, 625, - 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, - 622, 622, 622, 622, 622, 622, 622, 622, 622, 607, - 607, 622, 622, 607, 607, 622, 622, 622, 622, 622, - 622, 622, 607, 622, 622, 622, 622, 622, 622, 622, - 622, 622, 622, 622, 622, 622, 622, 622, 622, 622, - - 622, 622, 622, 622, 622, 622, 0, 607, 607, 607, - 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, - 607, 607, 607, 607, 607 + 605, 31, 610, 610, 605, 611, 605, 605, 605, 605, + 605, 605, 605, 605, 605, 605, 612, 612, 611, 605, + 605, 605, 613, 605, 613, 605, 605, 611, 605, 605, + 605, 605, 605, 605, 605, 605, 614, 605, 605, 605, + 605, 615, 605, 605, 605, 605, 605, 605, 605, 605, + 605, 605, 605, 605, 605, 605, 605, 616, 616, 605, + 605, 616, 605, 605, 605, 605, 605, 605, 605, 605, + + 605, 605, 605, 605, 605, 605, 605, 605, 617, 605, + 605, 605, 618, 605, 605, 618, 619, 605, 605, 605, + 618, 605, 605, 605, 605, 605, 605, 611, 605, 605, + 620, 605, 620, 620, 620, 620, 620, 620, 620, 620, + 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, + 605, 45, 613, 605, 621, 622, 612, 622, 605, 605, + 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, + 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, + 605, 605, 605, 605, 605, 605, 605, 616, 616, 605, + 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, + + 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, + 605, 605, 618, 619, 620, 605, 605, 605, 620, 620, + 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, + 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, + 620, 620, 620, 620, 620, 620, 620, 620, 620, 621, + 622, 158, 605, 605, 605, 605, 605, 605, 605, 605, + 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, + 605, 605, 605, 605, 605, 605, 605, 605, 605, 617, + 605, 620, 620, 620, 620, 620, 620, 620, 620, 620, + 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, + + 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, + 620, 620, 620, 620, 620, 620, 620, 620, 620, 605, + 605, 605, 605, 620, 620, 620, 620, 620, 620, 620, + 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, + 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, + 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, + 620, 620, 620, 620, 620, 620, 605, 605, 605, 620, + 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, + 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, + 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, + + 620, 620, 620, 620, 620, 620, 620, 605, 605, 605, + 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, + 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, + 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, + 620, 605, 620, 620, 620, 620, 620, 620, 620, 620, + 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, + 620, 620, 620, 605, 605, 620, 620, 620, 620, 620, + 620, 620, 620, 620, 605, 605, 605, 620, 620, 620, + 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, + 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, + + 620, 620, 620, 620, 623, 620, 620, 620, 620, 620, + 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, + 620, 620, 620, 620, 620, 620, 620, 623, 623, 620, + 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, + 620, 620, 620, 620, 620, 620, 620, 623, 620, 620, + 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, + 620, 620, 620, 620, 620, 620, 620, 605, 605, 620, + 620, 605, 605, 620, 620, 620, 620, 620, 620, 620, + 605, 620, 620, 620, 620, 620, 620, 620, 620, 620, + 620, 620, 620, 620, 620, 620, 620, 620, 620, 620, + + 620, 620, 620, 620, 0, 605, 605, 605, 605, 605, + 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, + 605, 605, 605 } ; -static const flex_int16_t yy_nxt[1443] = +static const flex_int16_t yy_nxt[1442] = { 0, 36, 37, 38, 37, 39, 37, 36, 40, 36, 41, 42, 36, 36, 43, 44, 36, 45, 46, 47, 48, @@ -970,161 +970,161 @@ static const flex_int16_t yy_nxt[1443] = 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 56, 57, 43, 36, 36, 36, 36, 36, 36, 36, 36, - 36, 36, 36, 36, 60, 60, 155, 158, 158, 158, - 156, 184, 184, 61, 61, 62, 160, 64, 62, 65, - 159, 76, 76, 77, 77, 66, 78, 78, 161, 63, - - 63, 79, 79, 63, 63, 606, 80, 80, 244, 63, - 63, 82, 38, 82, 83, 82, 159, 245, 67, 191, - 90, 158, 158, 158, 84, 90, 197, 85, 91, 190, - 92, 86, 605, 91, 198, 92, 181, 181, 181, 183, - 183, 183, 87, 186, 186, 186, 199, 62, 62, 62, + 36, 36, 36, 36, 60, 60, 154, 157, 157, 157, + 155, 183, 183, 61, 61, 62, 159, 64, 62, 65, + 158, 76, 76, 63, 63, 66, 77, 77, 160, 63, + + 63, 78, 78, 63, 63, 604, 79, 79, 242, 63, + 63, 81, 38, 81, 82, 81, 158, 243, 67, 189, + 89, 157, 157, 157, 83, 89, 195, 84, 90, 188, + 91, 85, 603, 90, 196, 91, 180, 180, 180, 182, + 182, 182, 86, 185, 185, 185, 197, 62, 62, 62, 62, 68, 69, 70, 71, 72, 73, 74, 75, 62, - 200, 64, 62, 65, 82, 38, 82, 83, 82, 66, - 201, 88, 258, 258, 62, 223, 63, 84, 93, 94, - 85, 95, 96, 93, 86, 224, 62, 350, 63, 97, - 351, 94, 67, 95, 96, 87, 124, 38, 124, 125, - - 124, 97, 202, 155, 293, 63, 104, 156, 105, 126, - 604, 104, 127, 105, 63, 294, 194, 63, 203, 63, - 195, 62, 62, 62, 62, 68, 69, 70, 71, 72, - 73, 74, 75, 62, 298, 63, 196, 106, 94, 155, - 98, 96, 106, 156, 62, 62, 63, 239, 97, 94, - 299, 98, 96, 62, 99, 63, 155, 62, 94, 97, - 156, 96, 225, 240, 63, 99, 241, 226, 97, 246, - 231, 62, 227, 63, 232, 63, 94, 62, 247, 96, - 603, 242, 62, 233, 63, 243, 97, 248, 303, 197, - 100, 62, 101, 63, 323, 323, 94, 198, 98, 96, - - 191, 100, 63, 101, 62, 62, 97, 63, 304, 107, - 190, 108, 99, 63, 109, 62, 103, 63, 62, 235, - 63, 305, 63, 94, 62, 98, 96, 62, 602, 63, - 309, 601, 236, 97, 310, 63, 63, 237, 103, 99, - 110, 389, 62, 205, 206, 205, 207, 205, 100, 63, - 102, 107, 111, 108, 112, 111, 109, 112, 63, 63, - 113, 389, 62, 113, 600, 124, 38, 124, 125, 124, - 194, 329, 128, 199, 195, 100, 62, 102, 126, 330, - 62, 127, 110, 110, 346, 599, 110, 200, 598, 62, - 196, 347, 210, 211, 210, 212, 210, 201, 62, 158, - - 158, 158, 181, 181, 181, 181, 181, 181, 181, 181, - 181, 262, 262, 262, 263, 263, 263, 264, 264, 264, - 477, 597, 62, 62, 213, 531, 62, 114, 115, 38, - 115, 116, 115, 114, 114, 114, 114, 114, 114, 114, - 114, 117, 114, 118, 119, 120, 120, 120, 114, 114, - 114, 114, 114, 114, 114, 118, 118, 118, 118, 114, - 114, 121, 118, 118, 118, 118, 118, 118, 118, 118, - 118, 118, 118, 118, 118, 118, 118, 118, 118, 118, - 118, 118, 118, 118, 118, 118, 114, 114, 114, 114, - 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, - - 114, 131, 354, 218, 218, 218, 219, 218, 132, 265, - 266, 265, 267, 265, 181, 181, 181, 596, 133, 355, - 132, 132, 132, 132, 181, 181, 181, 132, 132, 134, - 135, 136, 137, 138, 139, 132, 140, 132, 141, 142, - 143, 144, 145, 132, 146, 147, 148, 149, 150, 132, - 151, 152, 129, 268, 269, 268, 270, 268, 129, 348, - 129, 220, 595, 129, 129, 594, 349, 153, 153, 593, - 154, 154, 154, 129, 181, 181, 181, 592, 129, 129, - 154, 154, 154, 154, 591, 129, 129, 154, 154, 154, - 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, - - 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, - 154, 202, 590, 589, 129, 129, 129, 129, 129, 129, - 129, 129, 129, 129, 129, 129, 168, 203, 588, 169, - 607, 402, 169, 271, 272, 271, 273, 271, 587, 586, - 170, 170, 274, 275, 274, 276, 274, 585, 169, 584, - 582, 402, 171, 286, 580, 169, 579, 287, 172, 173, - 417, 213, 421, 174, 578, 254, 254, 254, 577, 288, - 175, 259, 259, 259, 176, 254, 177, 178, 179, 180, - 418, 259, 421, 254, 254, 254, 254, 254, 254, 259, - 259, 259, 259, 259, 259, 260, 260, 260, 444, 444, - - 444, 261, 261, 261, 576, 260, 205, 206, 205, 207, - 205, 261, 573, 260, 260, 260, 260, 260, 260, 261, - 261, 261, 261, 261, 261, 278, 211, 278, 279, 278, - 281, 282, 281, 283, 281, 218, 218, 218, 219, 218, - 324, 324, 324, 572, 569, 568, 325, 325, 325, 567, - 324, 265, 266, 265, 267, 265, 325, 566, 324, 324, - 324, 324, 324, 324, 325, 325, 325, 325, 325, 325, - 268, 269, 268, 270, 268, 565, 261, 261, 261, 271, - 272, 271, 273, 271, 564, 563, 261, 274, 275, 274, - 276, 274, 562, 220, 261, 261, 261, 261, 261, 261, - - 205, 206, 205, 207, 205, 278, 211, 278, 279, 278, - 278, 211, 278, 279, 278, 281, 282, 281, 283, 281, - 370, 370, 370, 561, 558, 557, 371, 371, 371, 556, - 370, 555, 554, 441, 450, 480, 371, 553, 370, 370, - 370, 370, 370, 370, 371, 371, 371, 371, 371, 371, - 411, 411, 411, 442, 451, 481, 412, 412, 412, 552, - 411, 466, 466, 466, 466, 466, 412, 559, 411, 411, - 411, 411, 411, 411, 412, 412, 412, 412, 412, 412, - 260, 260, 260, 477, 467, 550, 551, 560, 531, 477, - 260, 478, 479, 466, 466, 466, 466, 466, 260, 260, - - 260, 260, 260, 260, 560, 444, 444, 444, 570, 570, - 570, 570, 570, 581, 531, 549, 467, 574, 574, 574, - 574, 574, 548, 547, 560, 570, 570, 570, 570, 570, - 546, 571, 545, 581, 574, 574, 574, 574, 574, 544, - 575, 583, 583, 583, 583, 583, 543, 542, 571, 583, - 583, 583, 583, 583, 541, 540, 539, 575, 59, 59, + 198, 64, 62, 65, 81, 38, 81, 82, 81, 66, + 199, 87, 256, 256, 62, 221, 63, 83, 92, 93, + 84, 94, 95, 92, 85, 222, 62, 348, 63, 96, + 349, 93, 67, 94, 95, 86, 123, 38, 123, 124, + + 123, 96, 200, 154, 291, 63, 103, 155, 104, 125, + 602, 103, 126, 104, 63, 292, 192, 63, 201, 63, + 193, 62, 62, 62, 62, 68, 69, 70, 71, 72, + 73, 74, 75, 62, 296, 63, 194, 105, 93, 154, + 97, 95, 105, 155, 62, 62, 63, 237, 96, 93, + 297, 97, 95, 62, 98, 63, 154, 62, 93, 96, + 155, 95, 223, 238, 63, 98, 239, 224, 96, 244, + 229, 62, 225, 63, 230, 63, 93, 62, 245, 95, + 601, 240, 62, 231, 63, 241, 96, 246, 301, 195, + 99, 62, 100, 63, 321, 321, 93, 196, 97, 95, + + 189, 99, 63, 100, 62, 62, 96, 63, 302, 106, + 188, 107, 98, 63, 108, 62, 102, 63, 62, 233, + 63, 303, 63, 93, 62, 97, 95, 62, 600, 63, + 307, 599, 234, 96, 308, 63, 63, 235, 102, 98, + 109, 387, 62, 203, 204, 203, 205, 203, 99, 63, + 101, 106, 110, 107, 111, 110, 108, 111, 63, 63, + 112, 387, 62, 112, 598, 123, 38, 123, 124, 123, + 192, 327, 127, 197, 193, 99, 62, 101, 125, 328, + 62, 126, 109, 109, 344, 597, 109, 198, 596, 62, + 194, 345, 208, 209, 208, 210, 208, 199, 62, 157, + + 157, 157, 180, 180, 180, 180, 180, 180, 180, 180, + 180, 260, 260, 260, 261, 261, 261, 262, 262, 262, + 475, 595, 62, 62, 211, 529, 62, 113, 114, 38, + 114, 115, 114, 113, 113, 113, 113, 113, 113, 113, + 113, 116, 113, 117, 118, 119, 119, 119, 113, 113, + 113, 113, 113, 113, 113, 117, 117, 117, 117, 113, + 113, 120, 117, 117, 117, 117, 117, 117, 117, 117, + 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, + 117, 117, 117, 117, 117, 117, 113, 113, 113, 113, + 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, + + 113, 130, 352, 216, 216, 216, 217, 216, 131, 263, + 264, 263, 265, 263, 180, 180, 180, 594, 132, 353, + 131, 131, 131, 131, 180, 180, 180, 131, 131, 133, + 134, 135, 136, 137, 138, 131, 139, 131, 140, 141, + 142, 143, 144, 131, 145, 146, 147, 148, 149, 131, + 150, 151, 128, 266, 267, 266, 268, 266, 128, 346, + 128, 218, 593, 128, 128, 592, 347, 152, 152, 591, + 153, 153, 153, 128, 180, 180, 180, 590, 128, 128, + 153, 153, 153, 153, 589, 128, 128, 153, 153, 153, + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + + 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, + 153, 200, 588, 587, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 167, 201, 586, 168, + 605, 400, 168, 269, 270, 269, 271, 269, 585, 584, + 169, 169, 272, 273, 272, 274, 272, 583, 168, 582, + 580, 400, 170, 284, 578, 168, 577, 285, 171, 172, + 415, 211, 419, 173, 576, 252, 252, 252, 575, 286, + 174, 257, 257, 257, 175, 252, 176, 177, 178, 179, + 416, 257, 419, 252, 252, 252, 252, 252, 252, 257, + 257, 257, 257, 257, 257, 258, 258, 258, 442, 442, + + 442, 259, 259, 259, 574, 258, 203, 204, 203, 205, + 203, 259, 571, 258, 258, 258, 258, 258, 258, 259, + 259, 259, 259, 259, 259, 276, 209, 276, 277, 276, + 279, 280, 279, 281, 279, 216, 216, 216, 217, 216, + 322, 322, 322, 570, 567, 566, 323, 323, 323, 565, + 322, 263, 264, 263, 265, 263, 323, 564, 322, 322, + 322, 322, 322, 322, 323, 323, 323, 323, 323, 323, + 266, 267, 266, 268, 266, 563, 259, 259, 259, 269, + 270, 269, 271, 269, 562, 561, 259, 272, 273, 272, + 274, 272, 560, 218, 259, 259, 259, 259, 259, 259, + + 203, 204, 203, 205, 203, 276, 209, 276, 277, 276, + 276, 209, 276, 277, 276, 279, 280, 279, 281, 279, + 368, 368, 368, 559, 556, 555, 369, 369, 369, 554, + 368, 553, 552, 439, 448, 478, 369, 551, 368, 368, + 368, 368, 368, 368, 369, 369, 369, 369, 369, 369, + 409, 409, 409, 440, 449, 479, 410, 410, 410, 550, + 409, 464, 464, 464, 464, 464, 410, 557, 409, 409, + 409, 409, 409, 409, 410, 410, 410, 410, 410, 410, + 258, 258, 258, 475, 465, 548, 549, 558, 529, 475, + 258, 476, 477, 464, 464, 464, 464, 464, 258, 258, + + 258, 258, 258, 258, 558, 442, 442, 442, 568, 568, + 568, 568, 568, 579, 529, 547, 465, 572, 572, 572, + 572, 572, 546, 545, 558, 568, 568, 568, 568, 568, + 544, 569, 543, 579, 572, 572, 572, 572, 572, 542, + 573, 581, 581, 581, 581, 581, 541, 540, 569, 581, + 581, 581, 581, 581, 539, 538, 537, 573, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 81, 81, 81, 81, 81, 81, 81, 81, - 81, 81, 81, 81, 89, 89, 89, 89, 89, 89, - - 89, 89, 89, 89, 89, 89, 123, 123, 123, 123, - 123, 123, 123, 123, 123, 123, 123, 123, 129, 538, - 537, 536, 129, 129, 535, 129, 534, 533, 532, 129, - 157, 157, 154, 154, 154, 167, 167, 167, 167, 167, - 167, 167, 167, 167, 167, 167, 167, 185, 185, 185, - 185, 185, 185, 190, 190, 190, 190, 190, 190, 190, - 190, 190, 531, 190, 190, 209, 209, 209, 209, 209, - 209, 209, 209, 209, 209, 215, 529, 528, 215, 215, - 527, 526, 215, 215, 215, 215, 216, 216, 216, 217, - 217, 217, 252, 252, 525, 252, 252, 252, 252, 252, - - 252, 252, 252, 252, 253, 253, 253, 530, 530, 524, - 530, 530, 530, 530, 530, 530, 530, 530, 530, 523, - 522, 521, 520, 519, 518, 517, 516, 515, 514, 513, - 512, 511, 510, 509, 508, 507, 477, 506, 505, 504, - 503, 502, 501, 500, 499, 498, 497, 496, 495, 494, - 493, 492, 491, 490, 489, 488, 487, 486, 485, 484, - 483, 482, 476, 475, 474, 473, 472, 471, 470, 469, - 468, 465, 464, 463, 462, 461, 460, 459, 458, 457, - 456, 455, 454, 453, 452, 449, 448, 447, 446, 445, - 443, 440, 439, 438, 437, 436, 435, 434, 433, 432, - - 431, 430, 429, 428, 427, 426, 425, 424, 423, 422, - 420, 419, 416, 415, 414, 413, 410, 409, 408, 407, - 406, 405, 404, 403, 401, 400, 399, 398, 397, 396, - 395, 394, 393, 392, 391, 390, 388, 387, 386, 385, - 384, 383, 382, 381, 380, 379, 378, 377, 376, 375, - 374, 373, 372, 369, 368, 367, 366, 365, 364, 363, - 362, 361, 360, 359, 358, 357, 356, 353, 352, 345, - 344, 343, 342, 341, 340, 339, 338, 337, 336, 335, - 334, 333, 332, 331, 328, 327, 326, 282, 211, 275, - 272, 269, 266, 322, 321, 320, 319, 318, 317, 316, - - 315, 314, 313, 312, 311, 308, 307, 306, 302, 301, - 300, 297, 296, 295, 292, 291, 290, 289, 285, 284, - 218, 211, 280, 206, 277, 192, 191, 167, 257, 256, - 255, 251, 250, 249, 238, 234, 230, 229, 228, 222, - 221, 163, 130, 163, 130, 214, 208, 204, 193, 191, - 192, 191, 163, 130, 189, 188, 187, 182, 166, 165, - 164, 163, 162, 130, 607, 122, 58, 35, 607, 607, - 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, - 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, - 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, - - 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, - 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, - 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, - 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, - 607, 607 + 63, 63, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 88, 88, 88, 88, 88, 88, + + 88, 88, 88, 88, 88, 88, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 128, 536, + 535, 534, 128, 128, 533, 128, 532, 531, 530, 128, + 156, 156, 153, 153, 153, 166, 166, 166, 166, 166, + 166, 166, 166, 166, 166, 166, 166, 184, 184, 184, + 184, 184, 184, 188, 188, 188, 188, 188, 188, 188, + 188, 188, 529, 188, 188, 207, 207, 207, 207, 207, + 207, 207, 207, 207, 207, 213, 527, 526, 213, 213, + 525, 524, 213, 213, 213, 213, 214, 214, 214, 215, + 215, 215, 250, 250, 523, 250, 250, 250, 250, 250, + + 250, 250, 250, 250, 251, 251, 251, 528, 528, 522, + 528, 528, 528, 528, 528, 528, 528, 528, 528, 521, + 520, 519, 518, 517, 516, 515, 514, 513, 512, 511, + 510, 509, 508, 507, 506, 505, 475, 504, 503, 502, + 501, 500, 499, 498, 497, 496, 495, 494, 493, 492, + 491, 490, 489, 488, 487, 486, 485, 484, 483, 482, + 481, 480, 474, 473, 472, 471, 470, 469, 468, 467, + 466, 463, 462, 461, 460, 459, 458, 457, 456, 455, + 454, 453, 452, 451, 450, 447, 446, 445, 444, 443, + 441, 438, 437, 436, 435, 434, 433, 432, 431, 430, + + 429, 428, 427, 426, 425, 424, 423, 422, 421, 420, + 418, 417, 414, 413, 412, 411, 408, 407, 406, 405, + 404, 403, 402, 401, 399, 398, 397, 396, 395, 394, + 393, 392, 391, 390, 389, 388, 386, 385, 384, 383, + 382, 381, 380, 379, 378, 377, 376, 375, 374, 373, + 372, 371, 370, 367, 366, 365, 364, 363, 362, 361, + 360, 359, 358, 357, 356, 355, 354, 351, 350, 343, + 342, 341, 340, 339, 338, 337, 336, 335, 334, 333, + 332, 331, 330, 329, 326, 325, 324, 280, 209, 273, + 270, 267, 264, 320, 319, 318, 317, 316, 315, 314, + + 313, 312, 311, 310, 309, 306, 305, 304, 300, 299, + 298, 295, 294, 293, 290, 289, 288, 287, 283, 282, + 216, 209, 278, 204, 275, 190, 189, 166, 255, 254, + 253, 249, 248, 247, 236, 232, 228, 227, 226, 220, + 219, 162, 129, 162, 129, 212, 206, 202, 191, 189, + 190, 189, 162, 129, 187, 186, 181, 165, 164, 163, + 162, 161, 129, 605, 121, 58, 35, 605, 605, 605, + 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, + 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, + 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, + + 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, + 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, + 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, + 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, + 605 } ; -static const flex_int16_t yy_chk[1443] = +static const flex_int16_t yy_chk[1442] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -1137,42 +1137,42 @@ static const flex_int16_t yy_chk[1443] = 46, 71, 71, 3, 4, 5, 51, 5, 5, 5, 47, 7, 8, 7, 8, 5, 7, 8, 51, 7, - 8, 9, 10, 9, 10, 605, 9, 10, 147, 9, - 10, 11, 11, 11, 11, 11, 47, 147, 5, 90, - 13, 48, 48, 48, 11, 14, 98, 11, 13, 90, - 13, 11, 604, 14, 98, 14, 68, 68, 68, 70, - 70, 70, 11, 73, 73, 73, 99, 5, 5, 5, + 8, 9, 10, 9, 10, 603, 9, 10, 146, 9, + 10, 11, 11, 11, 11, 11, 47, 146, 5, 89, + 13, 48, 48, 48, 11, 14, 97, 11, 13, 89, + 13, 11, 602, 14, 97, 14, 68, 68, 68, 70, + 70, 70, 11, 73, 73, 73, 98, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, - 99, 6, 6, 6, 12, 12, 12, 12, 12, 6, - 99, 12, 170, 170, 15, 136, 15, 12, 13, 15, - 12, 15, 15, 14, 12, 136, 16, 305, 16, 15, - 305, 16, 6, 16, 16, 12, 33, 33, 33, 33, - - 33, 16, 103, 85, 228, 15, 25, 85, 25, 33, - 603, 26, 33, 26, 25, 228, 97, 16, 103, 26, - 97, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 17, 232, 17, 97, 25, 17, 119, - 17, 17, 26, 119, 18, 15, 18, 145, 17, 18, - 232, 18, 18, 19, 17, 19, 127, 16, 19, 18, - 127, 19, 137, 145, 17, 18, 145, 137, 19, 148, - 141, 20, 137, 20, 141, 18, 20, 25, 148, 20, - 602, 146, 26, 141, 19, 146, 20, 148, 236, 269, - 17, 21, 17, 21, 258, 258, 21, 269, 21, 21, - - 191, 18, 20, 18, 17, 23, 21, 23, 236, 27, - 191, 27, 21, 23, 27, 18, 23, 27, 22, 143, - 22, 236, 21, 22, 19, 22, 22, 24, 601, 24, - 240, 599, 143, 22, 240, 24, 23, 143, 24, 22, - 27, 345, 20, 106, 106, 106, 106, 106, 21, 22, + 98, 6, 6, 6, 12, 12, 12, 12, 12, 6, + 98, 12, 169, 169, 15, 135, 15, 12, 13, 15, + 12, 15, 15, 14, 12, 135, 16, 303, 16, 15, + 303, 16, 6, 16, 16, 12, 33, 33, 33, 33, + + 33, 16, 102, 84, 226, 15, 25, 84, 25, 33, + 601, 26, 33, 26, 25, 226, 96, 16, 102, 26, + 96, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 17, 230, 17, 96, 25, 17, 118, + 17, 17, 26, 118, 18, 15, 18, 144, 17, 18, + 230, 18, 18, 19, 17, 19, 126, 16, 19, 18, + 126, 19, 136, 144, 17, 18, 144, 136, 19, 147, + 140, 20, 136, 20, 140, 18, 20, 25, 147, 20, + 600, 145, 26, 140, 19, 145, 20, 147, 234, 267, + 17, 21, 17, 21, 256, 256, 21, 267, 21, 21, + + 189, 18, 20, 18, 17, 23, 21, 23, 234, 27, + 189, 27, 21, 23, 27, 18, 23, 27, 22, 142, + 22, 234, 21, 22, 19, 22, 22, 24, 599, 24, + 238, 597, 142, 22, 238, 24, 23, 142, 24, 22, + 27, 343, 20, 105, 105, 105, 105, 105, 21, 22, 21, 28, 29, 28, 29, 30, 28, 30, 24, 28, - 29, 345, 21, 30, 598, 34, 34, 34, 34, 34, - 266, 287, 34, 272, 266, 22, 23, 22, 34, 287, - 27, 34, 28, 29, 303, 597, 30, 272, 596, 22, - 266, 303, 110, 110, 110, 110, 110, 272, 24, 158, - - 158, 158, 182, 182, 182, 183, 183, 183, 184, 184, - 184, 185, 185, 185, 186, 186, 186, 187, 187, 187, - 550, 595, 28, 29, 110, 550, 30, 31, 31, 31, + 29, 343, 21, 30, 596, 34, 34, 34, 34, 34, + 264, 285, 34, 270, 264, 22, 23, 22, 34, 285, + 27, 34, 28, 29, 301, 595, 30, 270, 594, 22, + 264, 301, 109, 109, 109, 109, 109, 270, 24, 157, + + 157, 157, 181, 181, 181, 182, 182, 182, 183, 183, + 183, 184, 184, 184, 185, 185, 185, 186, 186, 186, + 548, 593, 28, 29, 109, 548, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, @@ -1181,110 +1181,110 @@ static const flex_int16_t yy_chk[1443] = 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 31, 41, 308, 133, 133, 133, 133, 133, 41, 196, - 196, 196, 196, 196, 262, 262, 262, 592, 41, 308, - 41, 41, 41, 41, 263, 263, 263, 41, 41, 41, + 31, 41, 306, 132, 132, 132, 132, 132, 41, 194, + 194, 194, 194, 194, 260, 260, 260, 590, 41, 306, + 41, 41, 41, 41, 261, 261, 261, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, - 41, 41, 45, 198, 198, 198, 198, 198, 45, 304, - 45, 133, 591, 45, 45, 590, 304, 45, 45, 589, - 45, 45, 45, 45, 264, 264, 264, 587, 45, 45, - 45, 45, 45, 45, 586, 45, 45, 45, 45, 45, + 41, 41, 45, 196, 196, 196, 196, 196, 45, 302, + 45, 132, 589, 45, 45, 588, 302, 45, 45, 587, + 45, 45, 45, 45, 262, 262, 262, 585, 45, 45, + 45, 45, 45, 45, 584, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, - 45, 275, 585, 584, 45, 45, 45, 45, 45, 45, - 45, 45, 45, 45, 45, 45, 67, 275, 582, 67, - 282, 358, 67, 201, 201, 201, 201, 201, 581, 578, - 67, 67, 203, 203, 203, 203, 203, 577, 67, 576, - 573, 358, 67, 223, 569, 67, 568, 223, 67, 67, - 379, 282, 382, 67, 561, 159, 159, 159, 560, 223, - 67, 171, 171, 171, 67, 159, 67, 67, 67, 67, - 379, 171, 382, 159, 159, 159, 159, 159, 159, 171, - 171, 171, 171, 171, 171, 178, 178, 178, 410, 410, - - 410, 180, 180, 180, 559, 178, 205, 205, 205, 205, - 205, 180, 557, 178, 178, 178, 178, 178, 178, 180, - 180, 180, 180, 180, 180, 210, 210, 210, 210, 210, - 213, 213, 213, 213, 213, 218, 218, 218, 218, 218, - 259, 259, 259, 556, 554, 553, 260, 260, 260, 552, - 259, 265, 265, 265, 265, 265, 260, 551, 259, 259, - 259, 259, 259, 259, 260, 260, 260, 260, 260, 260, - 268, 268, 268, 268, 268, 549, 261, 261, 261, 271, - 271, 271, 271, 271, 548, 547, 261, 274, 274, 274, - 274, 274, 545, 218, 261, 261, 261, 261, 261, 261, - - 277, 277, 277, 277, 277, 278, 278, 278, 278, 278, - 280, 280, 280, 280, 280, 281, 281, 281, 281, 281, - 324, 324, 324, 544, 541, 540, 325, 325, 325, 538, - 324, 537, 536, 407, 419, 445, 325, 535, 324, 324, - 324, 324, 324, 324, 325, 325, 325, 325, 325, 325, - 370, 370, 370, 407, 419, 445, 371, 371, 371, 533, - 370, 434, 434, 434, 434, 434, 371, 542, 370, 370, - 370, 370, 370, 370, 371, 371, 371, 371, 371, 371, - 411, 411, 411, 531, 434, 531, 532, 542, 531, 444, - 411, 444, 444, 466, 466, 466, 466, 466, 411, 411, - - 411, 411, 411, 411, 543, 444, 444, 444, 555, 555, - 555, 555, 555, 572, 530, 529, 466, 558, 558, 558, - 558, 558, 528, 527, 543, 570, 570, 570, 570, 570, - 526, 555, 525, 572, 574, 574, 574, 574, 574, 524, - 558, 575, 575, 575, 575, 575, 523, 522, 570, 583, - 583, 583, 583, 583, 521, 518, 517, 574, 608, 608, - 608, 608, 608, 608, 608, 608, 608, 608, 608, 608, - 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, - 609, 609, 610, 610, 610, 610, 610, 610, 610, 610, - 610, 610, 610, 610, 611, 611, 611, 611, 611, 611, - - 611, 611, 611, 611, 611, 611, 612, 612, 612, 612, - 612, 612, 612, 612, 612, 612, 612, 612, 613, 516, - 515, 512, 613, 613, 511, 613, 510, 509, 508, 613, - 614, 614, 615, 615, 615, 616, 616, 616, 616, 616, - 616, 616, 616, 616, 616, 616, 616, 617, 617, 617, - 617, 617, 617, 618, 618, 618, 618, 618, 618, 618, - 618, 618, 507, 618, 618, 619, 619, 619, 619, 619, - 619, 619, 619, 619, 619, 620, 506, 505, 620, 620, - 503, 502, 620, 620, 620, 620, 621, 621, 621, 622, - 622, 622, 623, 623, 501, 623, 623, 623, 623, 623, - - 623, 623, 623, 623, 624, 624, 624, 625, 625, 500, - 625, 625, 625, 625, 625, 625, 625, 625, 625, 497, - 495, 494, 493, 492, 490, 489, 488, 487, 486, 485, - 484, 483, 482, 481, 480, 479, 478, 475, 474, 473, - 471, 469, 468, 465, 464, 463, 462, 461, 460, 459, - 458, 457, 456, 455, 454, 453, 452, 451, 450, 449, - 448, 447, 443, 442, 441, 440, 439, 438, 437, 436, - 435, 433, 432, 431, 430, 429, 428, 427, 426, 425, - 424, 423, 422, 421, 420, 418, 417, 416, 415, 414, - 409, 405, 403, 402, 401, 400, 399, 397, 395, 394, - - 393, 392, 391, 390, 389, 387, 386, 385, 384, 383, - 381, 380, 376, 375, 374, 372, 369, 367, 366, 364, - 362, 361, 360, 359, 357, 356, 355, 354, 353, 352, - 351, 350, 349, 348, 347, 346, 344, 343, 342, 340, - 339, 338, 337, 336, 335, 334, 333, 332, 331, 330, - 329, 328, 326, 322, 321, 320, 319, 318, 317, 316, - 315, 314, 313, 312, 311, 310, 309, 307, 306, 302, - 301, 300, 299, 298, 297, 296, 295, 294, 293, 292, - 291, 290, 289, 288, 286, 285, 284, 283, 279, 276, - 273, 270, 267, 257, 251, 250, 249, 248, 247, 246, - - 245, 244, 243, 242, 241, 239, 238, 237, 235, 234, - 233, 231, 230, 229, 227, 226, 225, 224, 222, 221, - 219, 212, 211, 207, 206, 192, 190, 168, 163, 162, - 160, 151, 150, 149, 144, 142, 140, 139, 138, 135, - 134, 128, 125, 122, 116, 112, 108, 105, 95, 93, - 91, 89, 88, 83, 80, 77, 74, 69, 65, 61, - 60, 58, 55, 39, 35, 32, 2, 607, 607, 607, - 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, - 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, - 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, - - 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, + 45, 273, 583, 582, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 67, 273, 580, 67, + 280, 356, 67, 199, 199, 199, 199, 199, 579, 576, + 67, 67, 201, 201, 201, 201, 201, 575, 67, 574, + 571, 356, 67, 221, 567, 67, 566, 221, 67, 67, + 377, 280, 380, 67, 559, 158, 158, 158, 558, 221, + 67, 170, 170, 170, 67, 158, 67, 67, 67, 67, + 377, 170, 380, 158, 158, 158, 158, 158, 158, 170, + 170, 170, 170, 170, 170, 177, 177, 177, 408, 408, + + 408, 179, 179, 179, 557, 177, 203, 203, 203, 203, + 203, 179, 555, 177, 177, 177, 177, 177, 177, 179, + 179, 179, 179, 179, 179, 208, 208, 208, 208, 208, + 211, 211, 211, 211, 211, 216, 216, 216, 216, 216, + 257, 257, 257, 554, 552, 551, 258, 258, 258, 550, + 257, 263, 263, 263, 263, 263, 258, 549, 257, 257, + 257, 257, 257, 257, 258, 258, 258, 258, 258, 258, + 266, 266, 266, 266, 266, 547, 259, 259, 259, 269, + 269, 269, 269, 269, 546, 545, 259, 272, 272, 272, + 272, 272, 543, 216, 259, 259, 259, 259, 259, 259, + + 275, 275, 275, 275, 275, 276, 276, 276, 276, 276, + 278, 278, 278, 278, 278, 279, 279, 279, 279, 279, + 322, 322, 322, 542, 539, 538, 323, 323, 323, 536, + 322, 535, 534, 405, 417, 443, 323, 533, 322, 322, + 322, 322, 322, 322, 323, 323, 323, 323, 323, 323, + 368, 368, 368, 405, 417, 443, 369, 369, 369, 531, + 368, 432, 432, 432, 432, 432, 369, 540, 368, 368, + 368, 368, 368, 368, 369, 369, 369, 369, 369, 369, + 409, 409, 409, 529, 432, 529, 530, 540, 529, 442, + 409, 442, 442, 464, 464, 464, 464, 464, 409, 409, + + 409, 409, 409, 409, 541, 442, 442, 442, 553, 553, + 553, 553, 553, 570, 528, 527, 464, 556, 556, 556, + 556, 556, 526, 525, 541, 568, 568, 568, 568, 568, + 524, 553, 523, 570, 572, 572, 572, 572, 572, 522, + 556, 573, 573, 573, 573, 573, 521, 520, 568, 581, + 581, 581, 581, 581, 519, 516, 515, 572, 606, 606, + 606, 606, 606, 606, 606, 606, 606, 606, 606, 606, 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, - 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, - 607, 607, 607, 607, 607, 607, 607, 607, 607, 607, - 607, 607 + 607, 607, 608, 608, 608, 608, 608, 608, 608, 608, + 608, 608, 608, 608, 609, 609, 609, 609, 609, 609, + + 609, 609, 609, 609, 609, 609, 610, 610, 610, 610, + 610, 610, 610, 610, 610, 610, 610, 610, 611, 514, + 513, 510, 611, 611, 509, 611, 508, 507, 506, 611, + 612, 612, 613, 613, 613, 614, 614, 614, 614, 614, + 614, 614, 614, 614, 614, 614, 614, 615, 615, 615, + 615, 615, 615, 616, 616, 616, 616, 616, 616, 616, + 616, 616, 505, 616, 616, 617, 617, 617, 617, 617, + 617, 617, 617, 617, 617, 618, 504, 503, 618, 618, + 501, 500, 618, 618, 618, 618, 619, 619, 619, 620, + 620, 620, 621, 621, 499, 621, 621, 621, 621, 621, + + 621, 621, 621, 621, 622, 622, 622, 623, 623, 498, + 623, 623, 623, 623, 623, 623, 623, 623, 623, 495, + 493, 492, 491, 490, 488, 487, 486, 485, 484, 483, + 482, 481, 480, 479, 478, 477, 476, 473, 472, 471, + 469, 467, 466, 463, 462, 461, 460, 459, 458, 457, + 456, 455, 454, 453, 452, 451, 450, 449, 448, 447, + 446, 445, 441, 440, 439, 438, 437, 436, 435, 434, + 433, 431, 430, 429, 428, 427, 426, 425, 424, 423, + 422, 421, 420, 419, 418, 416, 415, 414, 413, 412, + 407, 403, 401, 400, 399, 398, 397, 395, 393, 392, + + 391, 390, 389, 388, 387, 385, 384, 383, 382, 381, + 379, 378, 374, 373, 372, 370, 367, 365, 364, 362, + 360, 359, 358, 357, 355, 354, 353, 352, 351, 350, + 349, 348, 347, 346, 345, 344, 342, 341, 340, 338, + 337, 336, 335, 334, 333, 332, 331, 330, 329, 328, + 327, 326, 324, 320, 319, 318, 317, 316, 315, 314, + 313, 312, 311, 310, 309, 308, 307, 305, 304, 300, + 299, 298, 297, 296, 295, 294, 293, 292, 291, 290, + 289, 288, 287, 286, 284, 283, 282, 281, 277, 274, + 271, 268, 265, 255, 249, 248, 247, 246, 245, 244, + + 243, 242, 241, 240, 239, 237, 236, 235, 233, 232, + 231, 229, 228, 227, 225, 224, 223, 222, 220, 219, + 217, 210, 209, 205, 204, 190, 188, 167, 162, 161, + 159, 150, 149, 148, 143, 141, 139, 138, 137, 134, + 133, 127, 124, 121, 115, 111, 107, 104, 94, 92, + 90, 88, 87, 82, 79, 74, 69, 65, 61, 60, + 58, 55, 39, 35, 32, 2, 605, 605, 605, 605, + 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, + 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, + 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, + + 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, + 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, + 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, + 605, 605, 605, 605, 605, 605, 605, 605, 605, 605, + 605 } ; static yy_state_type yy_last_accepting_state; @@ -1293,22 +1293,22 @@ static char *yy_last_accepting_cpos; extern int yy_flex_debug; int yy_flex_debug = 1; -static const flex_int16_t yy_rule_linenum[130] = +static const flex_int16_t yy_rule_linenum[131] = { 0, - 215, 218, 219, 220, 226, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 288, 292, 296, 299, - 300, 301, 302, 303, 304, 305, 306, 307, 309, 314, - 315, 316, 317, 319, 326, 327, 331, 337, 340, 341, - 344, 347, 355, 362, 363, 364, 370, 377, 384, 405, + 214, 217, 218, 219, 225, 243, 244, 245, 246, 247, + 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, + 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, + 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, + 278, 279, 280, 281, 282, 283, 287, 291, 295, 298, + 299, 300, 301, 302, 303, 304, 305, 306, 308, 313, + 314, 315, 316, 318, 325, 326, 330, 336, 339, 340, + 343, 346, 354, 361, 362, 363, 369, 376, 383, 404, 419, 434, 440, 459, 473, 492, 508, 525, 526, 537, - 548, 549, 561, 570, 575, 584, 594, 618, 630, 644, + 548, 549, 561, 571, 576, 586, 598, 622, 634, 648, - 645, 656, 661, 666, 667, 668, 669, 670, 671, 672, - 675, 677, 681, 700, 705, 706, 712, 713, 724, 730, - 736, 742, 758, 759, 763, 770, 786, 806, 845 + 649, 660, 664, 668, 669, 670, 671, 672, 673, 674, + 677, 679, 683, 695, 711, 716, 717, 723, 724, 735, + 741, 747, 753, 769, 770, 774, 781, 797, 817, 856 } ; /* The intent behind this definition is that it'll catch @@ -1322,7 +1322,7 @@ char *yytext; #line 1 "/Users/akim/src/gnu/bison/src/scan-gram.l" /* Bison Grammar Scanner -*- C -*- - Copyright (C) 2002-2015, 2018-2020 Free Software Foundation, Inc. + Copyright (C) 2002-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -1337,29 +1337,28 @@ char *yytext; GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #define YY_NO_INPUT 1 #line 24 "/Users/akim/src/gnu/bison/src/scan-gram.l" -#include <errno.h> - #include <c-ctype.h> +#include <errno.h> #include <mbswidth.h> #include <quote.h> #include <quotearg.h> -#include <src/complain.h> -#include <src/files.h> -#include <src/getargs.h> -#include <src/gram.h> -#include <src/reader.h> -#include <src/scan-gram.h> -#include <src/uniqstr.h> +#include "src/complain.h" +#include "src/files.h" +#include "src/getargs.h" +#include "src/gram.h" +#include "src/reader.h" +#include "src/scan-gram.h" +#include "src/uniqstr.h" #define FLEX_PREFIX(Id) gram_ ## Id -#include <src/flex-scanner.h> +#include "src/flex-scanner.h" /* Work around a bug in flex 2.5.31. See Debian bug 333231 - <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=333231>. */ + <https://bugs.debian.org/333231>. */ #undef gram_wrap #define gram_wrap() 1 @@ -1393,7 +1392,7 @@ static boundary scanner_cursor; yyless (0); \ } while (0) -#define DEPRECATED(Msg) \ +#define DEPRECATED_DIRECTIVE(Msg) \ do { \ deprecated_directive (loc, yytext, Msg); \ scanner_cursor.column -= mbsnwidth (Msg, strlen (Msg), 0); \ @@ -1405,17 +1404,17 @@ static boundary scanner_cursor; #define STRING_GROW_ESCAPE(Char) \ do { \ + verify (UCHAR_MAX < ULONG_MAX); \ long c = Char; \ - if (0 < c && c <= UCHAR_MAX) \ - obstack_1grow (&obstack_for_string, c); \ + bool valid = 0 < c && c <= UCHAR_MAX; \ + if (!valid) \ + complain (loc, complaint, \ + _("invalid number after \\-escape: %s"), \ + yytext + 1); \ + if (YY_START == SC_ESCAPED_CHARACTER) \ + STRING_1GROW (valid ? c : '?'); \ else \ - { \ - complain (loc, complaint, \ - _("invalid number after \\-escape: %s"), \ - yytext + 1); \ - /* Avoid additional errors about empty char literal. */ \ - obstack_1grow (&obstack_for_string, '?'); \ - } \ + STRING_GROW (); \ } while (0) @@ -1434,7 +1433,7 @@ static int bracketed_id_context_state = 0; void gram_scanner_last_string_free (void) { - STRING_FREE; + STRING_FREE (); } static void handle_syncline (char *, location); @@ -1443,8 +1442,8 @@ static int convert_ucn_to_byte (char const *hex_text); static void unexpected_eof (boundary, char const *); static void unexpected_newline (boundary, char const *); -#line 1446 "src/scan-gram.c" -#line 129 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 1445 "src/scan-gram.c" +#line 128 "/Users/akim/src/gnu/bison/src/scan-gram.l" /* A C-like comment in directives/rules. */ /* Characters and strings in directives/rules. */ @@ -1475,7 +1474,7 @@ static void unexpected_newline (boundary, char const *); white space between the backslash and the newline. */ /* An equal sign, with optional leading whitespaces. This is used in some deprecated constructs. */ -#line 1478 "src/scan-gram.c" +#line 1477 "src/scan-gram.c" #define INITIAL 0 #define SC_YACC_COMMENT 1 @@ -1774,7 +1773,7 @@ YY_DECL { /* %% [7.0] user's declarations go here */ -#line 176 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 175 "/Users/akim/src/gnu/bison/src/scan-gram.l" /* Nesting level. Either for nested braces, or nested angle brackets @@ -1811,7 +1810,7 @@ YY_DECL | Scanning white space. | `-----------------------*/ -#line 1814 "src/scan-gram.c" +#line 1813 "src/scan-gram.c" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { @@ -1841,13 +1840,13 @@ yy_match: while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 608 ) + if ( yy_current_state >= 606 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; ++yy_cp; } - while ( yy_current_state != 607 ); + while ( yy_current_state != 605 ); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); @@ -1866,13 +1865,13 @@ do_action: /* This label is used only to access EOF actions. */ { if ( yy_act == 0 ) fprintf( stderr, "--scanner backing up\n" ); - else if ( yy_act < 130 ) + else if ( yy_act < 131 ) fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n", (long)yy_rule_linenum[yy_act], yytext ); - else if ( yy_act == 130 ) + else if ( yy_act == 131 ) fprintf( stderr, "--accepting default rule (\"%s\")\n", yytext ); - else if ( yy_act == 131 ) + else if ( yy_act == 132 ) fprintf( stderr, "--(end of buffer or a NUL)\n" ); else fprintf( stderr, "--EOF (start condition %d)\n", YY_START ); @@ -1891,23 +1890,23 @@ do_action: /* This label is used only to access EOF actions. */ /* Comments and white space. */ case 1: YY_RULE_SETUP -#line 215 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 214 "/Users/akim/src/gnu/bison/src/scan-gram.l" { complain (loc, Wother, _("stray ',' treated as white space")); } YY_BREAK case 2: /* rule 2 can match eol */ -#line 219 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 218 "/Users/akim/src/gnu/bison/src/scan-gram.l" case 3: /* rule 3 can match eol */ YY_RULE_SETUP -#line 219 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 218 "/Users/akim/src/gnu/bison/src/scan-gram.l" continue; YY_BREAK case 4: YY_RULE_SETUP -#line 220 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 219 "/Users/akim/src/gnu/bison/src/scan-gram.l" { token_start = loc->start; context_state = YY_START; @@ -1917,7 +1916,7 @@ YY_RULE_SETUP case 5: /* rule 5 can match eol */ YY_RULE_SETUP -#line 226 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 225 "/Users/akim/src/gnu/bison/src/scan-gram.l" { handle_syncline (yytext + sizeof "#line " - 1, *loc); } @@ -1935,221 +1934,221 @@ YY_RULE_SETUP case 6: YY_RULE_SETUP -#line 244 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 243 "/Users/akim/src/gnu/bison/src/scan-gram.l" return BISON_DIRECTIVE (NONASSOC); YY_BREAK case 7: YY_RULE_SETUP -#line 245 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 244 "/Users/akim/src/gnu/bison/src/scan-gram.l" return BISON_DIRECTIVE (CODE); YY_BREAK case 8: YY_RULE_SETUP -#line 246 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 245 "/Users/akim/src/gnu/bison/src/scan-gram.l" RETURN_PERCENT_FLAG ("parse.trace"); YY_BREAK case 9: YY_RULE_SETUP -#line 247 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 246 "/Users/akim/src/gnu/bison/src/scan-gram.l" return BISON_DIRECTIVE (DEFAULT_PREC); YY_BREAK case 10: YY_RULE_SETUP -#line 248 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 247 "/Users/akim/src/gnu/bison/src/scan-gram.l" return BISON_DIRECTIVE (DEFINE); YY_BREAK case 11: YY_RULE_SETUP -#line 249 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 248 "/Users/akim/src/gnu/bison/src/scan-gram.l" return BISON_DIRECTIVE (DEFINES); YY_BREAK case 12: YY_RULE_SETUP -#line 250 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 249 "/Users/akim/src/gnu/bison/src/scan-gram.l" return BISON_DIRECTIVE (DESTRUCTOR); YY_BREAK case 13: YY_RULE_SETUP -#line 251 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 250 "/Users/akim/src/gnu/bison/src/scan-gram.l" return BISON_DIRECTIVE (DPREC); YY_BREAK case 14: YY_RULE_SETUP -#line 252 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 251 "/Users/akim/src/gnu/bison/src/scan-gram.l" return BISON_DIRECTIVE (EMPTY); YY_BREAK case 15: YY_RULE_SETUP -#line 253 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 252 "/Users/akim/src/gnu/bison/src/scan-gram.l" return BISON_DIRECTIVE (EXPECT); YY_BREAK case 16: YY_RULE_SETUP -#line 254 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 253 "/Users/akim/src/gnu/bison/src/scan-gram.l" return BISON_DIRECTIVE (EXPECT_RR); YY_BREAK case 17: YY_RULE_SETUP -#line 255 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 254 "/Users/akim/src/gnu/bison/src/scan-gram.l" RETURN_VALUE (PERCENT_FILE_PREFIX, uniqstr_new (yytext)); YY_BREAK case 18: YY_RULE_SETUP -#line 256 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 255 "/Users/akim/src/gnu/bison/src/scan-gram.l" return BISON_DIRECTIVE (INITIAL_ACTION); YY_BREAK case 19: YY_RULE_SETUP -#line 257 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 256 "/Users/akim/src/gnu/bison/src/scan-gram.l" return BISON_DIRECTIVE (GLR_PARSER); YY_BREAK case 20: YY_RULE_SETUP -#line 258 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 257 "/Users/akim/src/gnu/bison/src/scan-gram.l" return BISON_DIRECTIVE (LANGUAGE); YY_BREAK case 21: YY_RULE_SETUP -#line 259 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 258 "/Users/akim/src/gnu/bison/src/scan-gram.l" return PERCENT_LEFT; YY_BREAK case 22: YY_RULE_SETUP -#line 260 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 259 "/Users/akim/src/gnu/bison/src/scan-gram.l" RETURN_PERCENT_PARAM (lex); YY_BREAK case 23: YY_RULE_SETUP -#line 261 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 260 "/Users/akim/src/gnu/bison/src/scan-gram.l" RETURN_PERCENT_FLAG ("locations"); YY_BREAK case 24: YY_RULE_SETUP -#line 262 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 261 "/Users/akim/src/gnu/bison/src/scan-gram.l" return BISON_DIRECTIVE (MERGE); YY_BREAK case 25: YY_RULE_SETUP -#line 263 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 262 "/Users/akim/src/gnu/bison/src/scan-gram.l" return BISON_DIRECTIVE (NO_DEFAULT_PREC); YY_BREAK case 26: YY_RULE_SETUP -#line 264 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 263 "/Users/akim/src/gnu/bison/src/scan-gram.l" return BISON_DIRECTIVE (NO_LINES); YY_BREAK case 27: YY_RULE_SETUP -#line 265 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 264 "/Users/akim/src/gnu/bison/src/scan-gram.l" return PERCENT_NONASSOC; YY_BREAK case 28: YY_RULE_SETUP -#line 266 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 265 "/Users/akim/src/gnu/bison/src/scan-gram.l" return BISON_DIRECTIVE (NONDETERMINISTIC_PARSER); YY_BREAK case 29: YY_RULE_SETUP -#line 267 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 266 "/Users/akim/src/gnu/bison/src/scan-gram.l" return BISON_DIRECTIVE (NTERM); YY_BREAK case 30: YY_RULE_SETUP -#line 268 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 267 "/Users/akim/src/gnu/bison/src/scan-gram.l" return BISON_DIRECTIVE (OUTPUT); YY_BREAK case 31: YY_RULE_SETUP -#line 269 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 268 "/Users/akim/src/gnu/bison/src/scan-gram.l" RETURN_PERCENT_PARAM (both); YY_BREAK case 32: YY_RULE_SETUP -#line 270 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 269 "/Users/akim/src/gnu/bison/src/scan-gram.l" RETURN_PERCENT_PARAM (parse); YY_BREAK case 33: YY_RULE_SETUP -#line 271 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 270 "/Users/akim/src/gnu/bison/src/scan-gram.l" return PERCENT_PREC; YY_BREAK case 34: YY_RULE_SETUP -#line 272 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 271 "/Users/akim/src/gnu/bison/src/scan-gram.l" return BISON_DIRECTIVE (PRECEDENCE); YY_BREAK case 35: YY_RULE_SETUP -#line 273 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 272 "/Users/akim/src/gnu/bison/src/scan-gram.l" return BISON_DIRECTIVE (PRINTER); YY_BREAK case 36: YY_RULE_SETUP -#line 274 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 273 "/Users/akim/src/gnu/bison/src/scan-gram.l" return BISON_DIRECTIVE (REQUIRE); YY_BREAK case 37: YY_RULE_SETUP -#line 275 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 274 "/Users/akim/src/gnu/bison/src/scan-gram.l" return PERCENT_RIGHT; YY_BREAK case 38: YY_RULE_SETUP -#line 276 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 275 "/Users/akim/src/gnu/bison/src/scan-gram.l" return BISON_DIRECTIVE (SKELETON); YY_BREAK case 39: YY_RULE_SETUP -#line 277 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 276 "/Users/akim/src/gnu/bison/src/scan-gram.l" return PERCENT_START; YY_BREAK case 40: YY_RULE_SETUP -#line 278 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 277 "/Users/akim/src/gnu/bison/src/scan-gram.l" return BISON_DIRECTIVE (TOKEN); YY_BREAK case 41: YY_RULE_SETUP -#line 279 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 278 "/Users/akim/src/gnu/bison/src/scan-gram.l" return PERCENT_TOKEN; YY_BREAK case 42: YY_RULE_SETUP -#line 280 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 279 "/Users/akim/src/gnu/bison/src/scan-gram.l" return BISON_DIRECTIVE (TOKEN_TABLE); YY_BREAK case 43: YY_RULE_SETUP -#line 281 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 280 "/Users/akim/src/gnu/bison/src/scan-gram.l" return PERCENT_TYPE; YY_BREAK case 44: YY_RULE_SETUP -#line 282 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 281 "/Users/akim/src/gnu/bison/src/scan-gram.l" return PERCENT_UNION; YY_BREAK case 45: YY_RULE_SETUP -#line 283 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 282 "/Users/akim/src/gnu/bison/src/scan-gram.l" return BISON_DIRECTIVE (VERBOSE); YY_BREAK case 46: YY_RULE_SETUP -#line 284 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 283 "/Users/akim/src/gnu/bison/src/scan-gram.l" return PERCENT_YACC; YY_BREAK /* Deprecated since Bison 2.3b (2008-05-27), but the warning is issued only since Bison 3.4. */ case 47: YY_RULE_SETUP -#line 288 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 287 "/Users/akim/src/gnu/bison/src/scan-gram.l" RETURN_VALUE (PERCENT_PURE_PARSER, uniqstr_new (yytext)); YY_BREAK /* Deprecated since Bison 3.0 (2013-07-25), but the warning is issued only since Bison 3.3. */ case 48: YY_RULE_SETUP -#line 292 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 291 "/Users/akim/src/gnu/bison/src/scan-gram.l" RETURN_VALUE (PERCENT_ERROR_VERBOSE, uniqstr_new (yytext)); YY_BREAK /* Deprecated since Bison 2.6 (2012-07-19), but the warning is @@ -2157,60 +2156,60 @@ RETURN_VALUE (PERCENT_ERROR_VERBOSE, uniqstr_new (yytext)); case 49: /* rule 49 can match eol */ YY_RULE_SETUP -#line 296 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 295 "/Users/akim/src/gnu/bison/src/scan-gram.l" RETURN_VALUE (PERCENT_NAME_PREFIX, uniqstr_new (yytext)); YY_BREAK /* Deprecated since Bison 2.7.90, 2012. */ case 50: YY_RULE_SETUP -#line 299 "/Users/akim/src/gnu/bison/src/scan-gram.l" -DEPRECATED ("%default-prec"); +#line 298 "/Users/akim/src/gnu/bison/src/scan-gram.l" +DEPRECATED_DIRECTIVE ("%default-prec"); YY_BREAK case 51: YY_RULE_SETUP -#line 300 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 299 "/Users/akim/src/gnu/bison/src/scan-gram.l" RETURN_VALUE (PERCENT_ERROR_VERBOSE, uniqstr_new (yytext)); YY_BREAK case 52: YY_RULE_SETUP -#line 301 "/Users/akim/src/gnu/bison/src/scan-gram.l" -DEPRECATED ("%expect-rr"); +#line 300 "/Users/akim/src/gnu/bison/src/scan-gram.l" +DEPRECATED_DIRECTIVE ("%expect-rr"); YY_BREAK case 53: /* rule 53 can match eol */ YY_RULE_SETUP -#line 302 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 301 "/Users/akim/src/gnu/bison/src/scan-gram.l" RETURN_VALUE (PERCENT_FILE_PREFIX, uniqstr_new (yytext)); YY_BREAK case 54: YY_RULE_SETUP -#line 303 "/Users/akim/src/gnu/bison/src/scan-gram.l" -DEPRECATED ("%output \"y.tab.c\""); +#line 302 "/Users/akim/src/gnu/bison/src/scan-gram.l" +DEPRECATED_DIRECTIVE ("%output \"y.tab.c\""); YY_BREAK case 55: YY_RULE_SETUP -#line 304 "/Users/akim/src/gnu/bison/src/scan-gram.l" -DEPRECATED ("%no-default-prec"); +#line 303 "/Users/akim/src/gnu/bison/src/scan-gram.l" +DEPRECATED_DIRECTIVE ("%no-default-prec"); YY_BREAK case 56: YY_RULE_SETUP -#line 305 "/Users/akim/src/gnu/bison/src/scan-gram.l" -DEPRECATED ("%no-lines"); +#line 304 "/Users/akim/src/gnu/bison/src/scan-gram.l" +DEPRECATED_DIRECTIVE ("%no-lines"); YY_BREAK case 57: /* rule 57 can match eol */ YY_RULE_SETUP -#line 306 "/Users/akim/src/gnu/bison/src/scan-gram.l" -DEPRECATED ("%output"); +#line 305 "/Users/akim/src/gnu/bison/src/scan-gram.l" +DEPRECATED_DIRECTIVE ("%output"); YY_BREAK case 58: YY_RULE_SETUP -#line 307 "/Users/akim/src/gnu/bison/src/scan-gram.l" -DEPRECATED ("%token-table"); +#line 306 "/Users/akim/src/gnu/bison/src/scan-gram.l" +DEPRECATED_DIRECTIVE ("%token-table"); YY_BREAK case 59: YY_RULE_SETUP -#line 309 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 308 "/Users/akim/src/gnu/bison/src/scan-gram.l" { complain (loc, complaint, _("invalid directive: %s"), quote (yytext)); return GRAM_error; @@ -2218,27 +2217,27 @@ YY_RULE_SETUP YY_BREAK case 60: YY_RULE_SETUP -#line 314 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 313 "/Users/akim/src/gnu/bison/src/scan-gram.l" return COLON; YY_BREAK case 61: YY_RULE_SETUP -#line 315 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 314 "/Users/akim/src/gnu/bison/src/scan-gram.l" return EQUAL; YY_BREAK case 62: YY_RULE_SETUP -#line 316 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 315 "/Users/akim/src/gnu/bison/src/scan-gram.l" return PIPE; YY_BREAK case 63: YY_RULE_SETUP -#line 317 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 316 "/Users/akim/src/gnu/bison/src/scan-gram.l" return SEMICOLON; YY_BREAK case 64: YY_RULE_SETUP -#line 319 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 318 "/Users/akim/src/gnu/bison/src/scan-gram.l" { val->ID = uniqstr_new (yytext); id_loc = *loc; @@ -2248,19 +2247,19 @@ YY_RULE_SETUP YY_BREAK case 65: YY_RULE_SETUP -#line 326 "/Users/akim/src/gnu/bison/src/scan-gram.l" -RETURN_VALUE (INT, scan_integer (yytext, 10, *loc)); +#line 325 "/Users/akim/src/gnu/bison/src/scan-gram.l" +RETURN_VALUE (INT_LITERAL, scan_integer (yytext, 10, *loc)); YY_BREAK case 66: YY_RULE_SETUP -#line 327 "/Users/akim/src/gnu/bison/src/scan-gram.l" -RETURN_VALUE (INT, scan_integer (yytext, 16, *loc)); +#line 326 "/Users/akim/src/gnu/bison/src/scan-gram.l" +RETURN_VALUE (INT_LITERAL, scan_integer (yytext, 16, *loc)); YY_BREAK /* Identifiers may not start with a digit. Yet, don't silently accept "1FOO" as "1 FOO". */ case 67: YY_RULE_SETUP -#line 331 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 330 "/Users/akim/src/gnu/bison/src/scan-gram.l" { complain (loc, complaint, _("invalid identifier: %s"), quote (yytext)); return GRAM_error; @@ -2269,32 +2268,32 @@ YY_RULE_SETUP /* Characters. */ case 68: YY_RULE_SETUP -#line 337 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 336 "/Users/akim/src/gnu/bison/src/scan-gram.l" token_start = loc->start; BEGIN SC_ESCAPED_CHARACTER; YY_BREAK /* Strings. */ case 69: YY_RULE_SETUP -#line 340 "/Users/akim/src/gnu/bison/src/scan-gram.l" -token_start = loc->start; BEGIN SC_ESCAPED_STRING; +#line 339 "/Users/akim/src/gnu/bison/src/scan-gram.l" +token_start = loc->start; STRING_1GROW ('"'); BEGIN SC_ESCAPED_STRING; YY_BREAK case 70: YY_RULE_SETUP -#line 341 "/Users/akim/src/gnu/bison/src/scan-gram.l" -token_start = loc->start; BEGIN SC_ESCAPED_TSTRING; +#line 340 "/Users/akim/src/gnu/bison/src/scan-gram.l" +token_start = loc->start; STRING_1GROW ('"'); BEGIN SC_ESCAPED_TSTRING; YY_BREAK /* Prologue. */ case 71: YY_RULE_SETUP -#line 344 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 343 "/Users/akim/src/gnu/bison/src/scan-gram.l" code_start = loc->start; BEGIN SC_PROLOGUE; YY_BREAK /* Code in between braces. */ case 72: YY_RULE_SETUP -#line 347 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 346 "/Users/akim/src/gnu/bison/src/scan-gram.l" { - STRING_GROW; + STRING_GROW (); nesting = 0; code_start = loc->start; BEGIN SC_BRACED_CODE; @@ -2304,7 +2303,7 @@ YY_RULE_SETUP case 73: /* rule 73 can match eol */ YY_RULE_SETUP -#line 355 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 354 "/Users/akim/src/gnu/bison/src/scan-gram.l" { nesting = 0; code_start = loc->start; @@ -2314,17 +2313,17 @@ YY_RULE_SETUP /* A type. */ case 74: YY_RULE_SETUP -#line 362 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 361 "/Users/akim/src/gnu/bison/src/scan-gram.l" return TAG_ANY; YY_BREAK case 75: YY_RULE_SETUP -#line 363 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 362 "/Users/akim/src/gnu/bison/src/scan-gram.l" return TAG_NONE; YY_BREAK case 76: YY_RULE_SETUP -#line 364 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 363 "/Users/akim/src/gnu/bison/src/scan-gram.l" { nesting = 0; token_start = loc->start; @@ -2333,7 +2332,7 @@ YY_RULE_SETUP YY_BREAK case 77: YY_RULE_SETUP -#line 370 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 369 "/Users/akim/src/gnu/bison/src/scan-gram.l" { static int percent_percent_count; if (++percent_percent_count == 2) @@ -2343,7 +2342,7 @@ YY_RULE_SETUP YY_BREAK case 78: YY_RULE_SETUP -#line 377 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 376 "/Users/akim/src/gnu/bison/src/scan-gram.l" { bracketed_id_str = NULL; bracketed_id_start = loc->start; @@ -2353,7 +2352,7 @@ YY_RULE_SETUP YY_BREAK case 79: YY_RULE_SETUP -#line 384 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 383 "/Users/akim/src/gnu/bison/src/scan-gram.l" { complain (loc, complaint, "%s: %s", ngettext ("invalid character", "invalid characters", yyleng), @@ -2362,7 +2361,7 @@ YY_RULE_SETUP } YY_BREAK case YY_STATE_EOF(INITIAL): -#line 391 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 390 "/Users/akim/src/gnu/bison/src/scan-gram.l" { loc->start = loc->end = scanner_cursor; yyterminate (); @@ -2377,10 +2376,11 @@ case YY_STATE_EOF(INITIAL): case 80: YY_RULE_SETUP -#line 405 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 404 "/Users/akim/src/gnu/bison/src/scan-gram.l" { complain (loc, complaint, _("invalid null character")); - STRING_FREE; + STRING_FINISH (); + STRING_FREE (); return GRAM_error; } YY_BREAK @@ -2547,7 +2547,7 @@ case 90: /* rule 90 can match eol */ YY_RULE_SETUP #line 537 "/Users/akim/src/gnu/bison/src/scan-gram.l" -STRING_GROW; BEGIN context_state; +STRING_GROW (); BEGIN context_state; YY_BREAK case YY_STATE_EOF(SC_COMMENT): #line 538 "/Users/akim/src/gnu/bison/src/scan-gram.l" @@ -2563,13 +2563,13 @@ case 91: /* rule 91 can match eol */ YY_RULE_SETUP #line 548 "/Users/akim/src/gnu/bison/src/scan-gram.l" -STRING_GROW; BEGIN context_state; +STRING_GROW (); BEGIN context_state; YY_BREAK case 92: /* rule 92 can match eol */ YY_RULE_SETUP #line 549 "/Users/akim/src/gnu/bison/src/scan-gram.l" -STRING_GROW; +STRING_GROW (); YY_BREAK case YY_STATE_EOF(SC_LINE_COMMENT): #line 550 "/Users/akim/src/gnu/bison/src/scan-gram.l" @@ -2586,7 +2586,8 @@ case 93: YY_RULE_SETUP #line 561 "/Users/akim/src/gnu/bison/src/scan-gram.l" { - STRING_FINISH; + STRING_1GROW ('"'); + STRING_FINISH (); BEGIN INITIAL; loc->start = token_start; complain (loc, Wyacc, @@ -2595,13 +2596,13 @@ YY_RULE_SETUP } YY_BREAK case YY_STATE_EOF(SC_ESCAPED_STRING): -#line 569 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 570 "/Users/akim/src/gnu/bison/src/scan-gram.l" unexpected_eof (token_start, "\""); YY_BREAK case 94: /* rule 94 can match eol */ YY_RULE_SETUP -#line 570 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 571 "/Users/akim/src/gnu/bison/src/scan-gram.l" unexpected_newline (token_start, "\""); YY_BREAK @@ -2609,9 +2610,10 @@ unexpected_newline (token_start, "\""); case 95: YY_RULE_SETUP -#line 575 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 576 "/Users/akim/src/gnu/bison/src/scan-gram.l" { - STRING_FINISH; + STRING_1GROW ('"'); + STRING_FINISH (); BEGIN INITIAL; loc->start = token_start; complain (loc, Wyacc, @@ -2620,14 +2622,14 @@ YY_RULE_SETUP } YY_BREAK case YY_STATE_EOF(SC_ESCAPED_TSTRING): -#line 583 "/Users/akim/src/gnu/bison/src/scan-gram.l" -unexpected_eof (token_start, "\""); +#line 585 "/Users/akim/src/gnu/bison/src/scan-gram.l" +unexpected_eof (token_start, "\")"); YY_BREAK case 96: /* rule 96 can match eol */ YY_RULE_SETUP -#line 584 "/Users/akim/src/gnu/bison/src/scan-gram.l" -unexpected_newline (token_start, "\""); +#line 586 "/Users/akim/src/gnu/bison/src/scan-gram.l" +unexpected_newline (token_start, "\")"); YY_BREAK /*----------------------------------------------------------. @@ -2638,40 +2640,40 @@ unexpected_newline (token_start, "\""); case 97: YY_RULE_SETUP -#line 594 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 598 "/Users/akim/src/gnu/bison/src/scan-gram.l" { - STRING_FINISH; + STRING_FINISH (); BEGIN INITIAL; loc->start = token_start; - val->CHAR = last_string[0]; if (last_string[0] == '\0') { complain (loc, complaint, _("empty character literal")); - STRING_FREE; + STRING_FREE (); return GRAM_error; } else if (last_string[1] != '\0') { complain (loc, complaint, _("extra characters in character literal")); - STRING_FREE; + STRING_FREE (); return GRAM_error; } else { - STRING_FREE; - return CHAR; + val->CHAR_LITERAL = last_string[0]; + STRING_FREE (); + return CHAR_LITERAL; } } YY_BREAK case 98: /* rule 98 can match eol */ YY_RULE_SETUP -#line 618 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 622 "/Users/akim/src/gnu/bison/src/scan-gram.l" unexpected_newline (token_start, "'"); YY_BREAK case YY_STATE_EOF(SC_ESCAPED_CHARACTER): -#line 619 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 623 "/Users/akim/src/gnu/bison/src/scan-gram.l" unexpected_eof (token_start, "'"); YY_BREAK @@ -2682,34 +2684,34 @@ unexpected_eof (token_start, "'"); case 99: YY_RULE_SETUP -#line 630 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 634 "/Users/akim/src/gnu/bison/src/scan-gram.l" { --nesting; if (nesting < 0) { - STRING_FINISH; + STRING_FINISH (); loc->start = token_start; val->TAG = uniqstr_new (last_string); - STRING_FREE; + STRING_FREE (); BEGIN INITIAL; return TAG; } - STRING_GROW; + STRING_GROW (); } YY_BREAK case 100: /* rule 100 can match eol */ YY_RULE_SETUP -#line 644 "/Users/akim/src/gnu/bison/src/scan-gram.l" -STRING_GROW; +#line 648 "/Users/akim/src/gnu/bison/src/scan-gram.l" +STRING_GROW (); YY_BREAK case 101: YY_RULE_SETUP -#line 645 "/Users/akim/src/gnu/bison/src/scan-gram.l" -STRING_GROW; nesting += yyleng; +#line 649 "/Users/akim/src/gnu/bison/src/scan-gram.l" +STRING_GROW (); nesting += yyleng; YY_BREAK case YY_STATE_EOF(SC_TAG): -#line 647 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 651 "/Users/akim/src/gnu/bison/src/scan-gram.l" unexpected_eof (token_start, ">"); YY_BREAK @@ -2720,64 +2722,62 @@ unexpected_eof (token_start, ">"); case 102: YY_RULE_SETUP -#line 656 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 660 "/Users/akim/src/gnu/bison/src/scan-gram.l" { - verify (UCHAR_MAX < ULONG_MAX); STRING_GROW_ESCAPE (strtol (yytext + 1, NULL, 8)); } YY_BREAK case 103: YY_RULE_SETUP -#line 661 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 664 "/Users/akim/src/gnu/bison/src/scan-gram.l" { - verify (UCHAR_MAX < ULONG_MAX); STRING_GROW_ESCAPE (strtol (yytext + 2, NULL, 16)); } YY_BREAK case 104: YY_RULE_SETUP -#line 666 "/Users/akim/src/gnu/bison/src/scan-gram.l" -obstack_1grow (&obstack_for_string, '\a'); +#line 668 "/Users/akim/src/gnu/bison/src/scan-gram.l" +STRING_GROW_ESCAPE ('\a'); YY_BREAK case 105: YY_RULE_SETUP -#line 667 "/Users/akim/src/gnu/bison/src/scan-gram.l" -obstack_1grow (&obstack_for_string, '\b'); +#line 669 "/Users/akim/src/gnu/bison/src/scan-gram.l" +STRING_GROW_ESCAPE ('\b'); YY_BREAK case 106: YY_RULE_SETUP -#line 668 "/Users/akim/src/gnu/bison/src/scan-gram.l" -obstack_1grow (&obstack_for_string, '\f'); +#line 670 "/Users/akim/src/gnu/bison/src/scan-gram.l" +STRING_GROW_ESCAPE ('\f'); YY_BREAK case 107: YY_RULE_SETUP -#line 669 "/Users/akim/src/gnu/bison/src/scan-gram.l" -obstack_1grow (&obstack_for_string, '\n'); +#line 671 "/Users/akim/src/gnu/bison/src/scan-gram.l" +STRING_GROW_ESCAPE ('\n'); YY_BREAK case 108: YY_RULE_SETUP -#line 670 "/Users/akim/src/gnu/bison/src/scan-gram.l" -obstack_1grow (&obstack_for_string, '\r'); +#line 672 "/Users/akim/src/gnu/bison/src/scan-gram.l" +STRING_GROW_ESCAPE ('\r'); YY_BREAK case 109: YY_RULE_SETUP -#line 671 "/Users/akim/src/gnu/bison/src/scan-gram.l" -obstack_1grow (&obstack_for_string, '\t'); +#line 673 "/Users/akim/src/gnu/bison/src/scan-gram.l" +STRING_GROW_ESCAPE ('\t'); YY_BREAK case 110: YY_RULE_SETUP -#line 672 "/Users/akim/src/gnu/bison/src/scan-gram.l" -obstack_1grow (&obstack_for_string, '\v'); +#line 674 "/Users/akim/src/gnu/bison/src/scan-gram.l" +STRING_GROW_ESCAPE ('\v'); YY_BREAK /* \\[\"\'?\\] would be shorter, but it confuses xgettext. */ case 111: YY_RULE_SETUP -#line 675 "/Users/akim/src/gnu/bison/src/scan-gram.l" -obstack_1grow (&obstack_for_string, yytext[1]); +#line 677 "/Users/akim/src/gnu/bison/src/scan-gram.l" +STRING_GROW_ESCAPE (yytext[1]); YY_BREAK case 112: YY_RULE_SETUP -#line 677 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 679 "/Users/akim/src/gnu/bison/src/scan-gram.l" { STRING_GROW_ESCAPE (convert_ucn_to_byte (yytext)); } @@ -2785,7 +2785,7 @@ YY_RULE_SETUP case 113: /* rule 113 can match eol */ YY_RULE_SETUP -#line 681 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 683 "/Users/akim/src/gnu/bison/src/scan-gram.l" { char const *p = yytext + 1; /* Quote only if escaping won't make the character visible. */ @@ -2795,7 +2795,19 @@ YY_RULE_SETUP p = quotearg_style_mem (escape_quoting_style, p, 1); complain (loc, complaint, _("invalid character after \\-escape: %s"), p); - obstack_1grow (&obstack_for_string, '?'); + STRING_1GROW ('?'); + } + YY_BREAK +case 114: +YY_RULE_SETUP +#line 695 "/Users/akim/src/gnu/bison/src/scan-gram.l" +{ + // None of the other rules matched: the last character of this + // file is "\". But Flex does not support "\\<<EOF>>". + unexpected_eof (token_start, + YY_START == SC_ESCAPED_CHARACTER ? "?'" + : YY_START == SC_ESCAPED_STRING ? "?\"" + : "?\")"); } YY_BREAK @@ -2804,46 +2816,46 @@ YY_RULE_SETUP `--------------------------------------------*/ -case 114: -/* rule 114 can match eol */ +case 115: +/* rule 115 can match eol */ YY_RULE_SETUP -#line 700 "/Users/akim/src/gnu/bison/src/scan-gram.l" -STRING_GROW; +#line 711 "/Users/akim/src/gnu/bison/src/scan-gram.l" +STRING_GROW (); YY_BREAK -case 115: +case 116: YY_RULE_SETUP -#line 705 "/Users/akim/src/gnu/bison/src/scan-gram.l" -STRING_GROW; BEGIN context_state; +#line 716 "/Users/akim/src/gnu/bison/src/scan-gram.l" +STRING_GROW (); BEGIN context_state; YY_BREAK -case 116: -/* rule 116 can match eol */ +case 117: +/* rule 117 can match eol */ YY_RULE_SETUP -#line 706 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 717 "/Users/akim/src/gnu/bison/src/scan-gram.l" unexpected_newline (token_start, "'"); YY_BREAK case YY_STATE_EOF(SC_CHARACTER): -#line 707 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 718 "/Users/akim/src/gnu/bison/src/scan-gram.l" unexpected_eof (token_start, "'"); YY_BREAK -case 117: +case 118: YY_RULE_SETUP -#line 712 "/Users/akim/src/gnu/bison/src/scan-gram.l" -STRING_GROW; BEGIN context_state; +#line 723 "/Users/akim/src/gnu/bison/src/scan-gram.l" +STRING_GROW (); BEGIN context_state; YY_BREAK -case 118: -/* rule 118 can match eol */ +case 119: +/* rule 119 can match eol */ YY_RULE_SETUP -#line 713 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 724 "/Users/akim/src/gnu/bison/src/scan-gram.l" unexpected_newline (token_start, "\""); YY_BREAK case YY_STATE_EOF(SC_STRING): -#line 714 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 725 "/Users/akim/src/gnu/bison/src/scan-gram.l" unexpected_eof (token_start, "\""); YY_BREAK @@ -2852,43 +2864,43 @@ unexpected_eof (token_start, "\""); `---------------------------------------------------*/ -case 119: +case 120: YY_RULE_SETUP -#line 724 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 735 "/Users/akim/src/gnu/bison/src/scan-gram.l" { - STRING_GROW; + STRING_GROW (); context_state = YY_START; token_start = loc->start; BEGIN SC_CHARACTER; } YY_BREAK -case 120: +case 121: YY_RULE_SETUP -#line 730 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 741 "/Users/akim/src/gnu/bison/src/scan-gram.l" { - STRING_GROW; + STRING_GROW (); context_state = YY_START; token_start = loc->start; BEGIN SC_STRING; } YY_BREAK -case 121: -/* rule 121 can match eol */ +case 122: +/* rule 122 can match eol */ YY_RULE_SETUP -#line 736 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 747 "/Users/akim/src/gnu/bison/src/scan-gram.l" { - STRING_GROW; + STRING_GROW (); context_state = YY_START; token_start = loc->start; BEGIN SC_COMMENT; } YY_BREAK -case 122: -/* rule 122 can match eol */ +case 123: +/* rule 123 can match eol */ YY_RULE_SETUP -#line 742 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 753 "/Users/akim/src/gnu/bison/src/scan-gram.l" { - STRING_GROW; + STRING_GROW (); context_state = YY_START; BEGIN SC_LINE_COMMENT; } @@ -2900,44 +2912,44 @@ YY_RULE_SETUP `-----------------------------------------------------------*/ -case 123: -/* rule 123 can match eol */ -YY_RULE_SETUP -#line 758 "/Users/akim/src/gnu/bison/src/scan-gram.l" -STRING_GROW; nesting++; - YY_BREAK case 124: /* rule 124 can match eol */ YY_RULE_SETUP -#line 759 "/Users/akim/src/gnu/bison/src/scan-gram.l" -STRING_GROW; nesting--; +#line 769 "/Users/akim/src/gnu/bison/src/scan-gram.l" +STRING_GROW (); nesting++; YY_BREAK -/* Tokenize '<<%' correctly (as '<<' '%') rather than incorrectly - (as '<' '<%'). */ case 125: /* rule 125 can match eol */ YY_RULE_SETUP -#line 763 "/Users/akim/src/gnu/bison/src/scan-gram.l" -STRING_GROW; +#line 770 "/Users/akim/src/gnu/bison/src/scan-gram.l" +STRING_GROW (); nesting--; + YY_BREAK +/* Tokenize '<<%' correctly (as '<<' '%') rather than incorrectly + (as '<' '<%'). */ +case 126: +/* rule 126 can match eol */ +YY_RULE_SETUP +#line 774 "/Users/akim/src/gnu/bison/src/scan-gram.l" +STRING_GROW (); YY_BREAK case YY_STATE_EOF(SC_BRACED_CODE): case YY_STATE_EOF(SC_PREDICATE): -#line 765 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 776 "/Users/akim/src/gnu/bison/src/scan-gram.l" unexpected_eof (code_start, "}"); YY_BREAK -case 126: +case 127: YY_RULE_SETUP -#line 770 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 781 "/Users/akim/src/gnu/bison/src/scan-gram.l" { - obstack_1grow (&obstack_for_string, '}'); + STRING_1GROW ('}'); --nesting; if (nesting < 0) { - STRING_FINISH; + STRING_FINISH (); loc->start = code_start; BEGIN INITIAL; RETURN_VALUE (BRACED_CODE, last_string); @@ -2947,20 +2959,20 @@ YY_RULE_SETUP -case 127: +case 128: YY_RULE_SETUP -#line 786 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 797 "/Users/akim/src/gnu/bison/src/scan-gram.l" { --nesting; if (nesting < 0) { - STRING_FINISH; + STRING_FINISH (); loc->start = code_start; BEGIN INITIAL; RETURN_VALUE (BRACED_PREDICATE, last_string); } else - obstack_1grow (&obstack_for_string, '}'); + STRING_1GROW ('}'); } YY_BREAK @@ -2969,18 +2981,18 @@ YY_RULE_SETUP `--------------------------------------------------------------*/ -case 128: +case 129: YY_RULE_SETUP -#line 806 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 817 "/Users/akim/src/gnu/bison/src/scan-gram.l" { - STRING_FINISH; + STRING_FINISH (); loc->start = code_start; BEGIN INITIAL; RETURN_VALUE (PROLOGUE, last_string); } YY_BREAK case YY_STATE_EOF(SC_PROLOGUE): -#line 813 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 824 "/Users/akim/src/gnu/bison/src/scan-gram.l" unexpected_eof (code_start, "%}"); YY_BREAK @@ -2991,9 +3003,9 @@ unexpected_eof (code_start, "%}"); case YY_STATE_EOF(SC_EPILOGUE): -#line 824 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 835 "/Users/akim/src/gnu/bison/src/scan-gram.l" { - STRING_FINISH; + STRING_FINISH (); loc->start = code_start; BEGIN INITIAL; RETURN_VALUE (EPILOGUE, last_string); @@ -3011,19 +3023,19 @@ case YY_STATE_EOF(SC_EPILOGUE): Add a fallthrough "|." so that non UTF-8 input is still accepted and does not jam the scanner. */ -case 129: -/* rule 129 can match eol */ +case 130: +/* rule 130 can match eol */ YY_RULE_SETUP -#line 845 "/Users/akim/src/gnu/bison/src/scan-gram.l" -STRING_GROW; +#line 856 "/Users/akim/src/gnu/bison/src/scan-gram.l" +STRING_GROW (); YY_BREAK -case 130: +case 131: YY_RULE_SETUP -#line 848 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 859 "/Users/akim/src/gnu/bison/src/scan-gram.l" YY_FATAL_ERROR( "flex scanner jammed" ); YY_BREAK -#line 3026 "src/scan-gram.c" +#line 3038 "src/scan-gram.c" case YY_STATE_EOF(SC_RETURN_BRACKETED_ID): yyterminate(); @@ -3345,7 +3357,7 @@ static int yy_get_next_buffer (void) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 608 ) + if ( yy_current_state >= 606 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; @@ -3378,11 +3390,11 @@ static int yy_get_next_buffer (void) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 608 ) + if ( yy_current_state >= 606 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; - yy_is_jam = (yy_current_state == 607); + yy_is_jam = (yy_current_state == 605); return yy_is_jam ? 0 : yy_current_state; } @@ -4175,7 +4187,7 @@ void yyfree (void * ptr ) /* %ok-for-header */ -#line 848 "/Users/akim/src/gnu/bison/src/scan-gram.l" +#line 859 "/Users/akim/src/gnu/bison/src/scan-gram.l" @@ -4262,9 +4274,9 @@ convert_ucn_to_byte (char const *ucn) } -/*---------------------------------------------------------------------. -| Handle '#line INT( "FILE")?\n'. ARGS has already skipped '#line '. | -`---------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------. +| Handle '#line INT_LITERAL( "FILE")?\n'. ARGS has already skipped '#line '. | +`----------------------------------------------------------------------------*/ static void handle_syncline (char *args, location loc) @@ -4354,7 +4366,7 @@ gram_scanner_open (const char *gram) void -gram_scanner_close () +gram_scanner_close (void) { xfclose (gram_in); /* Reclaim Flex's buffers. */ @@ -4362,7 +4374,6 @@ gram_scanner_close () } - void gram_scanner_free (void) { diff --git a/contrib/tools/bison/src/scan-gram.h b/contrib/tools/bison/src/scan-gram.h index 4483fa816a..f187f32a3c 100644 --- a/contrib/tools/bison/src/scan-gram.h +++ b/contrib/tools/bison/src/scan-gram.h @@ -1,6 +1,6 @@ /* Bison Grammar Scanner - Copyright (C) 2006-2007, 2009-2015, 2018-2020 Free Software + Copyright (C) 2006-2007, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef SCAN_GRAM_H_ # define SCAN_GRAM_H_ diff --git a/contrib/tools/bison/src/scan-skel.c b/contrib/tools/bison/src/scan-skel.c index bda7bd2100..ab429a9923 100644 --- a/contrib/tools/bison/src/scan-skel.c +++ b/contrib/tools/bison/src/scan-skel.c @@ -700,16 +700,15 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static const flex_int16_t yy_accept[72] = +static const flex_int16_t yy_accept[70] = { 0, 0, 0, 0, 0, 0, 0, 26, 14, 13, 1, 12, 15, 22, 24, 23, 23, 14, 1, 12, 6, 12, 5, 2, 12, 12, 12, 3, 4, 15, 22, - 20, 22, 19, 21, 16, 17, 18, 12, 12, 12, - 12, 12, 0, 12, 12, 12, 12, 12, 12, 12, + 20, 19, 21, 16, 17, 18, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 8, 7, 12, 12, 12, 11, 12, 12, 9, 10, - 0 + 12, 12, 12, 12, 12, 12, 12, 12, 8, 7, + 12, 12, 12, 11, 12, 12, 9, 10, 0 } ; static const YY_CHAR yy_ec[256] = @@ -751,66 +750,66 @@ static const YY_CHAR yy_meta[25] = 1, 1, 1, 1 } ; -static const flex_int16_t yy_base[79] = +static const flex_int16_t yy_base[77] = { 0, - 0, 2, 68, 67, 9, 12, 74, 0, 109, 69, - 14, 0, 36, 109, 109, 109, 0, 68, 58, 109, - 17, 109, 109, 62, 52, 13, 109, 109, 0, 109, - 109, 26, 109, 109, 109, 109, 109, 49, 52, 53, - 51, 43, 30, 50, 39, 42, 39, 36, 37, 38, - 40, 39, 28, 40, 39, 39, 38, 24, 26, 22, - 109, 109, 25, 15, 6, 109, 3, 1, 109, 109, - 109, 82, 86, 90, 94, 97, 101, 104 + 0, 2, 63, 62, 9, 12, 69, 0, 109, 64, + 14, 0, 36, 109, 109, 109, 0, 63, 58, 109, + 17, 109, 109, 56, 46, 13, 109, 109, 0, 109, + 109, 109, 109, 109, 109, 109, 42, 42, 43, 42, + 34, 42, 34, 37, 34, 31, 32, 33, 35, 34, + 23, 33, 31, 28, 26, 12, 15, 16, 109, 109, + 23, 15, 6, 109, 3, 1, 109, 109, 109, 82, + 86, 90, 94, 97, 101, 104 } ; -static const flex_int16_t yy_def[79] = +static const flex_int16_t yy_def[77] = { 0, - 72, 72, 73, 73, 74, 74, 71, 75, 71, 75, - 76, 77, 78, 71, 71, 71, 75, 75, 76, 71, - 19, 71, 71, 19, 19, 19, 71, 71, 77, 71, - 71, 71, 71, 71, 71, 71, 71, 19, 19, 19, - 19, 19, 71, 19, 19, 19, 19, 19, 19, 19, + 70, 70, 71, 71, 72, 72, 69, 73, 69, 73, + 74, 75, 76, 69, 69, 69, 73, 73, 74, 69, + 19, 69, 69, 19, 19, 19, 69, 69, 75, 69, + 69, 69, 69, 69, 69, 69, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, - 71, 71, 19, 19, 19, 71, 19, 19, 71, 71, - 0, 71, 71, 71, 71, 71, 71, 71 + 19, 19, 19, 19, 19, 19, 19, 19, 69, 69, + 19, 19, 19, 69, 19, 19, 69, 69, 0, 69, + 69, 69, 69, 69, 69, 69 } ; static const flex_int16_t yy_nxt[134] = { 0, - 71, 71, 9, 10, 9, 10, 70, 11, 69, 11, + 69, 69, 9, 10, 9, 10, 68, 11, 67, 11, 15, 16, 15, 15, 16, 15, 20, 21, 22, 20, - 21, 23, 68, 24, 25, 40, 67, 41, 31, 43, - 66, 26, 31, 43, 42, 65, 27, 28, 31, 32, - 33, 64, 34, 35, 63, 62, 61, 60, 59, 58, - 57, 56, 55, 54, 53, 52, 51, 50, 36, 37, - 71, 49, 71, 48, 47, 71, 46, 45, 44, 39, - 38, 18, 18, 71, 13, 13, 71, 71, 71, 71, - 71, 71, 8, 8, 8, 8, 12, 12, 12, 12, - 14, 14, 14, 14, 17, 71, 17, 19, 19, 71, - - 19, 29, 29, 29, 30, 30, 30, 30, 7, 71, - 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, - 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, - 71, 71, 71 + 21, 23, 66, 24, 25, 39, 65, 40, 64, 63, + 62, 26, 61, 60, 41, 59, 27, 28, 31, 58, + 32, 57, 33, 34, 56, 55, 54, 53, 52, 51, + 50, 49, 48, 47, 46, 45, 44, 43, 35, 36, + 69, 42, 69, 38, 37, 69, 18, 18, 69, 13, + 13, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 8, 8, 8, 8, 12, 12, 12, 12, + 14, 14, 14, 14, 17, 69, 17, 19, 19, 69, + + 19, 29, 29, 29, 30, 30, 30, 30, 7, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69 } ; static const flex_int16_t yy_chk[134] = { 0, - 0, 0, 1, 1, 2, 2, 68, 1, 67, 2, + 0, 0, 1, 1, 2, 2, 66, 1, 65, 2, 5, 5, 5, 6, 6, 6, 11, 11, 11, 21, - 21, 11, 65, 11, 11, 26, 64, 26, 32, 32, - 63, 11, 43, 43, 26, 60, 11, 11, 13, 13, - 13, 59, 13, 13, 58, 57, 56, 55, 54, 53, - 52, 51, 50, 49, 48, 47, 46, 45, 13, 13, - 19, 44, 19, 42, 41, 19, 40, 39, 38, 25, - 24, 18, 10, 7, 4, 3, 0, 0, 0, 0, - 19, 19, 72, 72, 72, 72, 73, 73, 73, 73, - 74, 74, 74, 74, 75, 0, 75, 76, 76, 0, - - 76, 77, 77, 77, 78, 78, 78, 78, 71, 71, - 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, - 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, - 71, 71, 71 + 21, 11, 63, 11, 11, 26, 62, 26, 61, 58, + 57, 11, 56, 55, 26, 54, 11, 11, 13, 53, + 13, 52, 13, 13, 51, 50, 49, 48, 47, 46, + 45, 44, 43, 42, 41, 40, 39, 38, 13, 13, + 19, 37, 19, 25, 24, 19, 18, 10, 7, 4, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 19, 19, 70, 70, 70, 70, 71, 71, 71, 71, + 72, 72, 72, 72, 73, 0, 73, 74, 74, 0, + + 74, 75, 75, 75, 76, 76, 76, 76, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, + 69, 69, 69 } ; static yy_state_type yy_last_accepting_state; @@ -821,9 +820,9 @@ int yy_flex_debug = 1; static const flex_int16_t yy_rule_linenum[25] = { 0, - 74, 75, 76, 77, 78, 79, 81, 82, 84, 85, - 86, 89, 90, 91, 104, 106, 107, 108, 109, 110, - 112, 131, 136, 137 + 75, 76, 77, 78, 79, 80, 82, 83, 85, 86, + 87, 90, 91, 92, 105, 107, 108, 109, 110, 111, + 113, 132, 137, 138 } ; /* The intent behind this definition is that it'll catch @@ -837,7 +836,7 @@ char *yytext; #line 1 "src/scan-skel.l" /* Scan Bison Skeletons. -*- C -*- - Copyright (C) 2001-2015, 2018-2020 Free Software Foundation, Inc. + Copyright (C) 2001-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -852,7 +851,7 @@ char *yytext; GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #define YY_NO_INPUT 1 #line 24 "src/scan-skel.l" #include <dirname.h> @@ -860,16 +859,16 @@ char *yytext; #include <path-join.h> #include <quotearg.h> -#include <src/complain.h> -#include <src/files.h> -#include <src/getargs.h> -#include <src/scan-skel.h> +#include "src/complain.h" +#include "src/files.h" +#include "src/getargs.h" +#include "src/scan-skel.h" #define FLEX_PREFIX(Id) skel_ ## Id -#include <src/flex-scanner.h> +#include "src/flex-scanner.h" /* Work around a bug in flex 2.5.31. See Debian bug 333231 - <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=333231>. */ + <https://bugs.debian.org/333231>. */ #undef skel_wrap #define skel_wrap() 1 @@ -884,6 +883,7 @@ static void at_output (int argc, char *argv[], char **name, int *lineno); static void fail_for_at_directive_too_many_args (char const *at_directive_name); static void fail_for_at_directive_too_few_args (char const *at_directive_name); static void fail_for_invalid_at (char const *at); +static void output_mapped_file (char const *name); #line 887 "src/scan-skel.c" #line 889 "src/scan-skel.c" @@ -1166,11 +1166,11 @@ YY_DECL { /* %% [7.0] user's declarations go here */ -#line 58 "src/scan-skel.l" +#line 59 "src/scan-skel.l" -#line 62 "src/scan-skel.l" +#line 63 "src/scan-skel.l" int out_lineno PACIFY_CC (= 0); char *out_name = NULL; @@ -1212,13 +1212,13 @@ yy_match: while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 72 ) + if ( yy_current_state >= 70 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; ++yy_cp; } - while ( yy_current_state != 71 ); + while ( yy_current_state != 69 ); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); @@ -1261,79 +1261,79 @@ do_action: /* This label is used only to access EOF actions. */ case 1: YY_RULE_SETUP -#line 74 "src/scan-skel.l" +#line 75 "src/scan-skel.l" continue; YY_BREAK case 2: YY_RULE_SETUP -#line 75 "src/scan-skel.l" +#line 76 "src/scan-skel.l" fputc ('@', yyout); YY_BREAK case 3: YY_RULE_SETUP -#line 76 "src/scan-skel.l" +#line 77 "src/scan-skel.l" fputc ('[', yyout); YY_BREAK case 4: YY_RULE_SETUP -#line 77 "src/scan-skel.l" +#line 78 "src/scan-skel.l" fputc (']', yyout); YY_BREAK case 5: YY_RULE_SETUP -#line 78 "src/scan-skel.l" +#line 79 "src/scan-skel.l" continue; /* Used by b4_cat in ../data/bison.m4. */ YY_BREAK case 6: /* rule 6 can match eol */ YY_RULE_SETUP -#line 79 "src/scan-skel.l" +#line 80 "src/scan-skel.l" continue; YY_BREAK case 7: YY_RULE_SETUP -#line 81 "src/scan-skel.l" +#line 82 "src/scan-skel.l" fprintf (yyout, "%d", out_lineno + 1); YY_BREAK case 8: YY_RULE_SETUP -#line 82 "src/scan-skel.l" -fputs (quotearg_style (c_quoting_style, out_name), yyout); +#line 83 "src/scan-skel.l" +output_mapped_file (out_name); YY_BREAK case 9: YY_RULE_SETUP -#line 84 "src/scan-skel.l" +#line 85 "src/scan-skel.l" at_init (&argc, argv, &at_ptr, &at_basename); YY_BREAK case 10: YY_RULE_SETUP -#line 85 "src/scan-skel.l" +#line 86 "src/scan-skel.l" at_init (&argc, argv, &at_ptr, &at_complain); YY_BREAK case 11: YY_RULE_SETUP -#line 86 "src/scan-skel.l" +#line 87 "src/scan-skel.l" at_init (&argc, argv, &at_ptr, &at_output); YY_BREAK /* This pattern must not match more than the previous @ patterns. */ case 12: YY_RULE_SETUP -#line 89 "src/scan-skel.l" +#line 90 "src/scan-skel.l" fail_for_invalid_at (yytext); YY_BREAK case 13: /* rule 13 can match eol */ YY_RULE_SETUP -#line 90 "src/scan-skel.l" +#line 91 "src/scan-skel.l" out_lineno++; ECHO; YY_BREAK case 14: YY_RULE_SETUP -#line 91 "src/scan-skel.l" +#line 92 "src/scan-skel.l" ECHO; YY_BREAK case YY_STATE_EOF(INITIAL): -#line 93 "src/scan-skel.l" +#line 94 "src/scan-skel.l" { if (out_name) { @@ -1348,38 +1348,38 @@ case YY_STATE_EOF(INITIAL): case 15: /* rule 15 can match eol */ YY_RULE_SETUP -#line 104 "src/scan-skel.l" -STRING_GROW; +#line 105 "src/scan-skel.l" +STRING_GROW (); YY_BREAK case 16: YY_RULE_SETUP -#line 106 "src/scan-skel.l" -obstack_1grow (&obstack_for_string, '@'); +#line 107 "src/scan-skel.l" +STRING_1GROW ('@'); YY_BREAK case 17: YY_RULE_SETUP -#line 107 "src/scan-skel.l" -obstack_1grow (&obstack_for_string, '['); +#line 108 "src/scan-skel.l" +STRING_1GROW ('['); YY_BREAK case 18: YY_RULE_SETUP -#line 108 "src/scan-skel.l" -obstack_1grow (&obstack_for_string, ']'); +#line 109 "src/scan-skel.l" +STRING_1GROW (']'); YY_BREAK case 19: YY_RULE_SETUP -#line 109 "src/scan-skel.l" +#line 110 "src/scan-skel.l" continue; /* For starting an argument that begins with whitespace. */ YY_BREAK case 20: /* rule 20 can match eol */ YY_RULE_SETUP -#line 110 "src/scan-skel.l" +#line 111 "src/scan-skel.l" continue; YY_BREAK case 21: YY_RULE_SETUP -#line 112 "src/scan-skel.l" +#line 113 "src/scan-skel.l" { if (argc >= ARGC_MAX) fail_for_at_directive_too_many_args (argv[0]); @@ -1401,7 +1401,7 @@ YY_RULE_SETUP YY_BREAK case 22: YY_RULE_SETUP -#line 131 "src/scan-skel.l" +#line 132 "src/scan-skel.l" fail_for_invalid_at (yytext); YY_BREAK @@ -1410,12 +1410,12 @@ fail_for_invalid_at (yytext); case 23: /* rule 23 can match eol */ YY_RULE_SETUP -#line 136 "src/scan-skel.l" +#line 137 "src/scan-skel.l" continue; YY_BREAK case 24: YY_RULE_SETUP -#line 137 "src/scan-skel.l" +#line 138 "src/scan-skel.l" yyless (0); BEGIN SC_AT_DIRECTIVE_ARGS; YY_BREAK @@ -1423,13 +1423,13 @@ yyless (0); BEGIN SC_AT_DIRECTIVE_ARGS; case YY_STATE_EOF(SC_AT_DIRECTIVE_ARGS): case YY_STATE_EOF(SC_AT_DIRECTIVE_SKIP_WS): -#line 142 "src/scan-skel.l" +#line 143 "src/scan-skel.l" complain (NULL, fatal, _("unclosed %s directive in skeleton"), argv[0]); YY_BREAK case 25: YY_RULE_SETUP -#line 145 "src/scan-skel.l" +#line 146 "src/scan-skel.l" YY_FATAL_ERROR( "flex scanner jammed" ); YY_BREAK #line 1435 "src/scan-skel.c" @@ -1751,7 +1751,7 @@ static int yy_get_next_buffer (void) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 72 ) + if ( yy_current_state >= 70 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; @@ -1784,11 +1784,11 @@ static int yy_get_next_buffer (void) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 72 ) + if ( yy_current_state >= 70 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; - yy_is_jam = (yy_current_state == 71); + yy_is_jam = (yy_current_state == 69); return yy_is_jam ? 0 : yy_current_state; } @@ -2537,7 +2537,7 @@ void yyfree (void * ptr ) /* %ok-for-header */ -#line 145 "src/scan-skel.l" +#line 146 "src/scan-skel.l" static void @@ -2663,3 +2663,11 @@ fail_for_invalid_at (char const *at) complain (NULL, fatal, "invalid @ in skeleton: %s", at); } +static void +output_mapped_file (char const *name) +{ + char *f = map_file_name (name); + fputs (quotearg_style (c_quoting_style, f), yyout); + free (f); +} + diff --git a/contrib/tools/bison/src/scan-skel.h b/contrib/tools/bison/src/scan-skel.h index 5a6b5f3f36..e3479070a9 100644 --- a/contrib/tools/bison/src/scan-skel.h +++ b/contrib/tools/bison/src/scan-skel.h @@ -1,6 +1,6 @@ /* Scan Bison Skeletons. - Copyright (C) 2005-2007, 2009-2015, 2018-2020 Free Software + Copyright (C) 2005-2007, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ void scan_skel (FILE *); diff --git a/contrib/tools/bison/src/state-item.c b/contrib/tools/bison/src/state-item.c new file mode 100644 index 0000000000..5551dd7e11 --- /dev/null +++ b/contrib/tools/bison/src/state-item.c @@ -0,0 +1,580 @@ +/* Counterexample Generation Search Nodes + + Copyright (C) 2020-2021 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +#include "state-item.h" + +#include <assert.h> +#include <gl_linked_list.h> +#include <gl_xlist.h> +#include <stdlib.h> +#include <time.h> + +#include "closure.h" +#include "getargs.h" +#include "nullable.h" + +size_t nstate_items; +state_item_number *state_item_map; +state_item *state_items; + +// Hash functions for index -> bitset hash maps. +typedef struct +{ + int key; + bitset l; +} hash_pair; + +static size_t +hash_pair_hasher (const hash_pair *sl, size_t max) +{ + return sl->key % max; +} + +static bool +hash_pair_comparator (const hash_pair *l, const hash_pair *r) +{ + return l->key == r->key; +} + +static void +hash_pair_free (hash_pair *hp) +{ + bitset_free (hp->l); + free (hp); +} + +static Hash_table * +hash_pair_table_create (int size) +{ + return hash_xinitialize (size, + NULL, + (Hash_hasher) hash_pair_hasher, + (Hash_comparator) hash_pair_comparator, + (Hash_data_freer) hash_pair_free); +} + +static bitset +hash_pair_lookup (Hash_table *tab, int key) +{ + hash_pair probe; + probe.key = key; + hash_pair *hp = hash_lookup (tab, &probe); + return hp ? hp->l : NULL; +} + +static void +hash_pair_insert (Hash_table *tab, int key, bitset val) +{ + hash_pair *hp = xmalloc (sizeof *hp); + hp->key = key; + hp->l = val; + hash_pair *res = hash_xinsert (tab, hp); + // This must be the first insertion. + (void) res; + assert (res == hp); +} + +/* A state_item from a state's id and the offset of the item within + the state. */ +state_item * +state_item_lookup (state_number s, state_item_number off) +{ + return &state_items[state_item_index_lookup (s, off)]; +} + +static inline void +state_item_set (state_item_number sidx, const state *s, item_number off) +{ + state_items[sidx].state = s; + state_items[sidx].item = &ritem[off]; + state_items[sidx].lookahead = NULL; + state_items[sidx].trans = -1; + state_items[sidx].prods = NULL; + state_items[sidx].revs = bitset_create (nstate_items, BITSET_SPARSE); +} + +/** + * Initialize state_items set + */ +static void +init_state_items (void) +{ + nstate_items = 0; + bitsetv production_items = bitsetv_create (nstates, nritems, BITSET_SPARSE); + for (int i = 0; i < nstates; ++i) + { + const state *s = states[i]; + nstate_items += s->nitems; + closure (s->items, s->nitems); + for (size_t j = 0; j < nitemset; ++j) + if (0 < itemset[j] + && item_number_is_rule_number (ritem[itemset[j] - 1])) + { + bitset_set (production_items[i], itemset[j]); + ++nstate_items; + } + } + state_item_map = xnmalloc (nstates + 1, sizeof (state_item_number)); + state_items = xnmalloc (nstate_items, sizeof (state_item)); + state_item_number sidx = 0; + for (int i = 0; i < nstates; ++i) + { + state_item_map[i] = sidx; + int rule_search_idx = 0; + const state *s = states[i]; + const reductions *red = s->reductions; + for (int j = 0; j < s->nitems; ++j) + { + state_item_set (sidx, s, s->items[j]); + state_item *si = &state_items[sidx]; + const rule *r = item_rule (si->item); + if (rule_search_idx < red->num && red->rules[rule_search_idx] < r) + ++rule_search_idx; + if (rule_search_idx < red->num && r == red->rules[rule_search_idx]) + { + bitsetv lookahead = red->lookaheads; + if (lookahead) + si->lookahead = lookahead[rule_search_idx]; + } + ++sidx; + } + bitset_iterator biter; + item_number off; + BITSET_FOR_EACH (biter, production_items[i], off, 0) + { + state_item_set (sidx, s, off); + if (item_number_is_rule_number (ritem[off])) + { + bitsetv lookahead = red->lookaheads; + if (lookahead) + state_items[sidx].lookahead = lookahead[rule_search_idx]; + ++rule_search_idx; + } + ++sidx; + } + + } + state_item_map[nstates] = nstate_items; + bitsetv_free (production_items); +} + +static size_t +state_sym_hasher (const void *st, size_t max) +{ + return ((state *) st)->accessing_symbol % max; +} + +static bool +state_sym_comparator (const void *s1, const void *s2) +{ + return ((state *) s1)->accessing_symbol == ((state *) s2)->accessing_symbol; +} + +static state * +state_sym_lookup (symbol_number sym, Hash_table *h) +{ + state probe; + probe.accessing_symbol = sym; + return hash_lookup (h, &probe); +} + +static void +init_trans (void) +{ + for (state_number i = 0; i < nstates; ++i) + { + // Generate a hash set that maps from accepting symbols to the states + // this state transitions to. + state *s = states[i]; + transitions *t = s->transitions; + Hash_table *transition_set + = hash_xinitialize (t->num, NULL, (Hash_hasher) state_sym_hasher, + (Hash_comparator) state_sym_comparator, NULL); + for (int j = 0; j < t->num; ++j) + if (!TRANSITION_IS_DISABLED (t, j)) + hash_xinsert (transition_set, t->states[j]); + for (state_item_number j = state_item_map[i]; j < state_item_map[i + 1]; ++j) + { + item_number *item = state_items[j].item; + if (item_number_is_rule_number (*item)) + continue; + state *dst = state_sym_lookup (*item, transition_set); + if (!dst) + continue; + // find the item in the destination state that corresponds + // to the transition of item + for (int k = 0; k < dst->nitems; ++k) + if (item + 1 == ritem + dst->items[k]) + { + state_item_number dstSI = + state_item_index_lookup (dst->number, k); + + state_items[j].trans = dstSI; + bitset_set (state_items[dstSI].revs, j); + break; + } + } + hash_free (transition_set); + } +} + +static void +init_prods (void) +{ + for (int i = 0; i < nstates; ++i) + { + state *s = states[i]; + // closure_map is a hash map from nonterminals to a set + // of the items that produce those nonterminals + Hash_table *closure_map = hash_pair_table_create (nsyms - ntokens); + + // Add the nitems of state to skip to the production portion + // of that state's state_items + for (state_item_number j = state_item_map[i] + s->nitems; + j < state_item_map[i + 1]; ++j) + { + state_item *src = &state_items[j]; + item_number *item = src->item; + symbol_number lhs = item_rule (item)->lhs->number; + bitset itms = hash_pair_lookup (closure_map, lhs); + if (!itms) + { + itms = bitset_create (nstate_items, BITSET_SPARSE); + hash_pair_insert (closure_map, lhs, itms); + } + bitset_set (itms, j); + } + // For each item with a dot followed by a nonterminal, + // try to create a production edge. + for (state_item_number j = state_item_map[i]; j < state_item_map[i + 1]; ++j) + { + state_item *src = &state_items[j]; + item_number item = *(src->item); + // Skip reduce items and items with terminals after the dot + if (item_number_is_rule_number (item) || ISTOKEN (item)) + continue; + symbol_number sym = item_number_as_symbol_number (item); + bitset lb = hash_pair_lookup (closure_map, sym); + if (lb) + { + bitset copy = bitset_create (nstate_items, BITSET_SPARSE); + bitset_copy (copy, lb); + // update prods. + state_items[j].prods = copy; + + // update revs. + bitset_iterator biter; + state_item_number prod; + BITSET_FOR_EACH (biter, copy, prod, 0) + bitset_set (state_items[prod].revs, j); + } + } + hash_free (closure_map); + } +} + +/* Since lookaheads are only generated for reductions, we need to + propagate lookahead sets backwards as the searches require each + state_item to have a lookahead. */ +static inline void +gen_lookaheads (void) +{ + for (state_item_number i = 0; i < nstate_items; ++i) + { + state_item *si = &state_items[i]; + if (item_number_is_symbol_number (*(si->item)) || !si->lookahead) + continue; + + bitset lookahead = si->lookahead; + state_item_list queue = + gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1, + (const void **) &si); + + // For each reduction item, traverse through all state_items + // accessible through reverse transition steps, and set their + // lookaheads to the reduction items lookahead + while (gl_list_size (queue) > 0) + { + state_item *prev = (state_item *) gl_list_get_at (queue, 0); + gl_list_remove_at (queue, 0); + prev->lookahead = lookahead; + if (SI_TRANSITION (prev)) + { + bitset rsi = state_items[prev - state_items].revs; + bitset_iterator biter; + state_item_number sin; + BITSET_FOR_EACH (biter, rsi, sin, 0) + gl_list_add_first (queue, &state_items[sin]); + } + } + gl_list_free (queue); + } +} + +bitsetv firsts = NULL; + +static void +init_firsts (void) +{ + firsts = bitsetv_create (nnterms, nsyms, BITSET_FIXED); + for (rule_number i = 0; i < nrules; ++i) + { + rule *r = &rules[i]; + item_number *n = r->rhs; + // Iterate through nullable nonterminals to try to find a terminal. + while (item_number_is_symbol_number (*n) && ISVAR (*n) + && nullable[*n - ntokens]) + ++n; + if (item_number_is_rule_number (*n) || ISVAR (*n)) + continue; + + symbol_number lhs = r->lhs->number; + bitset_set (FIRSTS (lhs), *n); + } + bool change = true; + while (change) + { + change = false; + for (rule_number i = 0; i < nrules; ++i) + { + rule *r = &rules[i]; + symbol_number lhs = r->lhs->number; + bitset f_lhs = FIRSTS (lhs); + for (item_number *n = r->rhs; + item_number_is_symbol_number (*n) && ISVAR (*n); + ++n) + { + bitset f = FIRSTS (*n); + if (!bitset_subset_p (f_lhs, f)) + { + change = true; + bitset_union (f_lhs, f_lhs, f); + } + if (!nullable[*n - ntokens]) + break; + } + } + } +} + +static inline void +disable_state_item (state_item *si) +{ + si->trans = -2; + bitset_free (si->revs); + if (si->prods) + bitset_free (si->prods); +} + +/* Disable all state_item paths that lead to/from SI and nowhere + else. */ +static void +prune_state_item (const state_item *si) +{ + state_item_list queue = + gl_list_create (GL_LINKED_LIST, NULL, NULL, NULL, true, 1, + (const void **) &si); + + while (gl_list_size (queue) > 0) + { + state_item *dsi = (state_item *) gl_list_get_at (queue, 0); + gl_list_remove_at (queue, 0); + if (SI_DISABLED (dsi - state_items)) + continue; + + if (dsi->trans >= 0 && !SI_DISABLED (dsi->trans)) + { + const state_item *trans = &state_items[dsi->trans]; + bitset_reset (trans->revs, dsi - state_items); + if (bitset_empty_p (trans->revs)) + gl_list_add_last (queue, trans); + } + + if (dsi->prods) + { + bitset_iterator biter; + state_item_number sin; + BITSET_FOR_EACH (biter, dsi->prods, sin, 0) + { + if (SI_DISABLED (sin)) + continue; + const state_item *prod = &state_items[sin]; + bitset_reset (prod->revs, dsi - state_items); + if (bitset_empty_p (prod->revs)) + gl_list_add_last (queue, prod); + } + } + + bitset_iterator biter; + state_item_number sin; + BITSET_FOR_EACH (biter, dsi->revs, sin, 0) + { + if (SI_DISABLED (sin)) + continue; + state_item *rev = &state_items[sin]; + if (&state_items[rev->trans] == dsi) + gl_list_add_last (queue, rev); + else if (rev->prods) + { + bitset_reset (rev->prods, dsi - state_items); + if (bitset_empty_p (rev->prods)) + gl_list_add_last (queue, rev); + } + else + gl_list_add_last (queue, rev); + } + disable_state_item (dsi); + } + gl_list_free (queue); +} + +/* To make searches more efficient, prune away paths that are caused + by disabled transitions. */ +static void +prune_disabled_paths (void) +{ + for (int i = nstate_items - 1; i >= 0; --i) + { + state_item *si = &state_items[i]; + if (si->trans == -1 && item_number_is_symbol_number (*si->item)) + prune_state_item (si); + } +} + +void +state_item_print (const state_item *si, FILE *out, const char *prefix) +{ + fputs (prefix, out); + item_print (si->item, NULL, out); + putc ('\n', out); +} + +/** + * Report the state_item graph + */ +static void +state_items_report (FILE *out) +{ + fprintf (out, "# state items: %zu\n", nstate_items); + for (state_number i = 0; i < nstates; ++i) + { + fprintf (out, "State %d:\n", i); + for (state_item_number j = state_item_map[i]; j < state_item_map[i + 1]; ++j) + { + const state_item *si = &state_items[j]; + item_print (si->item, NULL, out); + if (SI_DISABLED (j)) + fputs (" DISABLED\n", out); + else + { + putc ('\n', out); + if (si->trans >= 0) + { + fputs (" -> ", out); + state_item_print (&state_items[si->trans], out, ""); + } + + bitset sets[2] = { si->prods, si->revs }; + const char *txt[2] = { " => ", " <- " }; + for (int seti = 0; seti < 2; ++seti) + { + bitset b = sets[seti]; + if (b) + { + bitset_iterator biter; + state_item_number sin; + BITSET_FOR_EACH (biter, b, sin, 0) + { + fputs (txt[seti], out); + state_item_print (&state_items[sin], out, ""); + } + } + } + } + putc ('\n', out); + } + } + fprintf (out, "FIRSTS\n"); + for (symbol_number i = ntokens; i < nsyms; ++i) + { + fprintf (out, " %s firsts\n", symbols[i]->tag); + bitset_iterator iter; + symbol_number j; + BITSET_FOR_EACH (iter, FIRSTS (i), j, 0) + fprintf (out, " %s\n", symbols[j]->tag); + } + fputs ("\n\n", out); +} + +void +state_items_init (void) +{ + time_t start = time (NULL); + init_state_items (); + init_trans (); + init_prods (); + gen_lookaheads (); + init_firsts (); + prune_disabled_paths (); + if (trace_flag & trace_cex) + { + fprintf (stderr, "init: %f\n", difftime (time (NULL), start)); + state_items_report (stderr); + } +} + +void +state_items_free (void) +{ + for (state_item_number i = 0; i < nstate_items; ++i) + if (!SI_DISABLED (i)) + { + state_item *si = &state_items[i]; + if (si->prods) + bitset_free (si->prods); + bitset_free (si->revs); + } + free (state_items); + bitsetv_free (firsts); +} + +/** + * Determine, using precedence and associativity, whether the next + * production is allowed from the current production. + */ +bool +production_allowed (const state_item *si, const state_item *next) +{ + sym_content *s1 = item_rule (si->item)->lhs; + sym_content *s2 = item_rule (next->item)->lhs; + int prec1 = s1->prec; + int prec2 = s2->prec; + if (prec1 >= 0 && prec2 >= 0) + { + // Do not expand if lower precedence. + if (prec1 > prec2) + return false; + // Do not expand if same precedence, but left-associative. + if (prec1 == prec2 && s1->assoc == left_assoc) + return false; + } + return true; +} diff --git a/contrib/tools/bison/src/state-item.h b/contrib/tools/bison/src/state-item.h new file mode 100644 index 0000000000..90ca79417e --- /dev/null +++ b/contrib/tools/bison/src/state-item.h @@ -0,0 +1,113 @@ +/* Counterexample Generation Search Nodes + + Copyright (C) 2020-2021 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef STATE_ITEM_H +# define STATE_ITEM_H + +# include <bitsetv.h> +# include <gl_list.h> +# include <hash.h> + +# include "gram.h" +# include "state.h" + +/* Initializes a graph connecting (state, production item) pairs to + pairs they can make a transition or production step to. This graph + is used to search for paths that represent counterexamples of some + conflict. + + state_items is an array of state state-item pairs ordered by state. + state_item_map maps state numbers to the first item which + corresponds to it in the array. A state's portion in state_items + begins with its items in the same order as it was in the state. + This is then followed by productions from the closure of the state + in order by rule. + + There are two type of edges in this graph transitions and + productions. Transitions are the same as transitions from the + parser except edges are only between items from the same + rule. + + Productions are edges from items with a nonterminal after the dot to + the production of that nonterminal in the same state. These edges are + stored as a bitset in a state-item. + + The inverses of these edges are stored in a bitset in the state-item, + "revs." A state-item that begins with a dot will have reverse + production edges, and all others will have reverse transition + edges. */ + +# define SI_DISABLED(Sin) (state_items[Sin].trans == -2) +# define SI_PRODUCTION(Si) ((Si) == state_items || *((Si)->item - 1) < 0) +# define SI_TRANSITION(Si) ((Si) != state_items && *((Si)->item - 1) >= 0) + +typedef int state_item_number; + +typedef struct +{ + const state *state; + item_number *item; + state_item_number trans; + bitset prods; + bitset revs; + bitset lookahead; +} state_item; + +// A path of state-items. +typedef gl_list_t state_item_list; + +extern bitsetv firsts; +# define FIRSTS(sym) firsts[(sym) - ntokens] + +extern size_t nstate_items; +extern state_item_number *state_item_map; + +/** Array mapping state_item_numbers to state_items */ +extern state_item *state_items; + +state_item *state_item_lookup (state_number s, state_item_number off); + +static inline state_item_number +state_item_index_lookup (state_number s, state_item_number off) +{ + return state_item_map[s] + off; +} + +void state_items_init (void); +void state_items_free (void); + +void state_item_print (const state_item *si, FILE *out, const char *prefix); + +bool production_allowed (const state_item *si, const state_item *next); + +// Iterating on a state_item_list. +static inline bool +state_item_list_next (gl_list_iterator_t *it, state_item **si) +{ + const void *p = NULL; + bool res = gl_list_iterator_next (it, &p, NULL); + if (res) + *si = (state_item *) p; + else + gl_list_iterator_free (it); + return res; +} + + +#endif /* STATE_ITEM_H */ diff --git a/contrib/tools/bison/src/state.c b/contrib/tools/bison/src/state.c index 356ccdf17f..79ab43b5ad 100644 --- a/contrib/tools/bison/src/state.c +++ b/contrib/tools/bison/src/state.c @@ -1,6 +1,6 @@ /* Type definitions for the finite state machine for Bison. - Copyright (C) 2001-2007, 2009-2015, 2018-2020 Free Software + Copyright (C) 2001-2007, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> #include "state.h" @@ -101,7 +101,7 @@ reductions_new (int num, rule **reds) size_t rules_size = num * sizeof *reds; reductions *res = xmalloc (offsetof (reductions, rules) + rules_size); res->num = num; - res->lookahead_tokens = NULL; + res->lookaheads = NULL; memcpy (res->rules, reds, rules_size); return res; } @@ -126,7 +126,7 @@ state *final_state = NULL; state * state_new (symbol_number accessing_symbol, - size_t nitems, item_number *core) + size_t nitems, item_index *core) { aver (nstates < STATE_NUMBER_MAXIMUM); @@ -231,7 +231,7 @@ state_reductions_set (state *s, int num, rule **reds) int -state_reduction_find (state *s, rule const *r) +state_reduction_find (state const *s, rule const *r) { reductions *reds = s->reductions; for (int i = 0; i < reds->num; ++i) @@ -260,20 +260,20 @@ state_errs_set (state *s, int num, symbol **tokens) `--------------------------------------------------*/ void -state_rule_lookahead_tokens_print (state *s, rule const *r, FILE *out) +state_rule_lookaheads_print (state const *s, rule const *r, FILE *out) { /* Find the reduction we are handling. */ reductions *reds = s->reductions; int red = state_reduction_find (s, r); /* Print them if there are. */ - if (reds->lookahead_tokens && red != -1) + if (reds->lookaheads && red != -1) { bitset_iterator biter; int k; char const *sep = ""; fprintf (out, " ["); - BITSET_FOR_EACH (biter, reds->lookahead_tokens[red], k, 0) + BITSET_FOR_EACH (biter, reds->lookaheads[red], k, 0) { fprintf (out, "%s%s", sep, symbols[k]->tag); sep = ", "; @@ -283,7 +283,7 @@ state_rule_lookahead_tokens_print (state *s, rule const *r, FILE *out) } void -state_rule_lookahead_tokens_print_xml (state *s, rule const *r, +state_rule_lookaheads_print_xml (state const *s, rule const *r, FILE *out, int level) { /* Find the reduction we are handling. */ @@ -291,12 +291,12 @@ state_rule_lookahead_tokens_print_xml (state *s, rule const *r, int red = state_reduction_find (s, r); /* Print them if there are. */ - if (reds->lookahead_tokens && red != -1) + if (reds->lookaheads && red != -1) { bitset_iterator biter; int k; xml_puts (out, level, "<lookaheads>"); - BITSET_FOR_EACH (biter, reds->lookahead_tokens[red], k, 0) + BITSET_FOR_EACH (biter, reds->lookaheads[red], k, 0) { xml_printf (out, level + 1, "<symbol>%s</symbol>", xml_escape (symbols[k]->tag)); @@ -385,8 +385,7 @@ state_hash_free (void) void state_hash_insert (state *s) { - if (!hash_insert (state_table, s)) - xalloc_die (); + hash_xinsert (state_table, s); } @@ -396,7 +395,7 @@ state_hash_insert (state *s) `------------------------------------------------------------------*/ state * -state_hash_lookup (size_t nitems, item_number *core) +state_hash_lookup (size_t nitems, const item_index *core) { size_t items_size = nitems * sizeof *core; state *probe = xmalloc (offsetof (state, items) + items_size); diff --git a/contrib/tools/bison/src/state.h b/contrib/tools/bison/src/state.h index a087dc8373..7398187f5a 100644 --- a/contrib/tools/bison/src/state.h +++ b/contrib/tools/bison/src/state.h @@ -1,6 +1,6 @@ /* Type definitions for the finite state machine for Bison. - Copyright (C) 1984, 1989, 2000-2004, 2007, 2009-2015, 2018-2020 Free + Copyright (C) 1984, 1989, 2000-2004, 2007, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ /* These type definitions are used to represent a nondeterministic @@ -62,7 +62,7 @@ Each reductions structure describes the possible reductions at the state whose number is in the number field. rules is an array of - num rules. lookahead_tokens is an array of bitsets, one per rule. + num rules. lookaheads is an array of bitsets, one per rule. Conflict resolution can decide that certain tokens in certain states should explicitly be errors (for implementing %nonassoc). @@ -187,7 +187,7 @@ errs *errs_new (int num, symbol **tokens); typedef struct { int num; - bitset *lookahead_tokens; + bitset *lookaheads; /* Sorted ascendingly on rule number. */ rule *rules[1]; } reductions; @@ -225,7 +225,7 @@ struct state /* Its items. Must be last, since ITEMS can be arbitrarily large. Sorted ascendingly on item index in RITEM, which is sorted on rule number. */ size_t nitems; - item_number items[1]; + item_index items[1]; }; extern state_number nstates; @@ -233,7 +233,7 @@ extern state *final_state; /* Create a new state with ACCESSING_SYMBOL for those items. */ state *state_new (symbol_number accessing_symbol, - size_t core_size, item_number *core); + size_t core_size, item_index *core); state *state_new_isocore (state const *s); /* Record that from S we can reach all the DST states (NUM of them). */ @@ -247,16 +247,16 @@ void state_reductions_set (state *s, int num, rule **reds); /* The index of the reduction of state S that corresponds to rule R. Aborts if there is no reduction of R in S. */ -int state_reduction_find (state *s, rule const *r); +int state_reduction_find (state const *s, rule const *r); /* Set the errs of STATE. */ void state_errs_set (state *s, int num, symbol **errors); /* Print on OUT all the lookahead tokens such that this STATE wants to reduce R. */ -void state_rule_lookahead_tokens_print (state *s, rule const *r, FILE *out); -void state_rule_lookahead_tokens_print_xml (state *s, rule const *r, - FILE *out, int level); +void state_rule_lookaheads_print (state const *s, rule const *r, FILE *out); +void state_rule_lookaheads_print_xml (state const *s, rule const *r, + FILE *out, int level); /* Create/destroy the states hash table. */ void state_hash_new (void); @@ -264,7 +264,7 @@ void state_hash_free (void); /* Find the state associated to the CORE, and return it. If it does not exist yet, return NULL. */ -state *state_hash_lookup (size_t core_size, item_number *core); +state *state_hash_lookup (size_t core_size, const item_index *core); /* Insert STATE in the state hash table. */ void state_hash_insert (state *s); diff --git a/contrib/tools/bison/src/strversion.c b/contrib/tools/bison/src/strversion.c new file mode 100644 index 0000000000..4100cde759 --- /dev/null +++ b/contrib/tools/bison/src/strversion.c @@ -0,0 +1,67 @@ +/* Convert version string to int. + + Copyright (C) 2020-2021 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> +#include "system.h" + +#include "strversion.h" + +#include <errno.h> +#include <intprops.h> + +int +strversion_to_int (char const *version) +{ + IGNORE_TYPE_LIMITS_BEGIN + int res = 0; + errno = 0; + char *cp = NULL; + + { + long major = strtol (version, &cp, 10); + if (errno || cp == version || *cp != '.' || major < 0 + || INT_MULTIPLY_WRAPV (major, 10000, &res)) + return -1; + } + + { + ++cp; + char *prev = cp; + long minor = strtol (cp, &cp, 10); + if (errno || cp == prev || (*cp != '\0' && *cp != '.') + || ! (0 <= minor && minor < 100) + || INT_MULTIPLY_WRAPV (minor, 100, &minor) + || INT_ADD_WRAPV (minor, res, &res)) + return -1; + } + + if (*cp == '.') + { + ++cp; + char *prev = cp; + long micro = strtol (cp, &cp, 10); + if (errno || cp == prev || (*cp != '\0' && *cp != '.') + || ! (0 <= micro && micro < 100) + || INT_ADD_WRAPV (micro, res, &res)) + return -1; + } + + IGNORE_TYPE_LIMITS_END + return res; +} diff --git a/contrib/tools/bison/src/strversion.h b/contrib/tools/bison/src/strversion.h new file mode 100644 index 0000000000..80b39e3512 --- /dev/null +++ b/contrib/tools/bison/src/strversion.h @@ -0,0 +1,28 @@ +/* Convert version string to int. + + Copyright (C) 2020-2021 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#ifndef STRVERSION_H_ +# define STRVERSION_H_ + +/* Convert VERSION into an int (MAJOR * 10000 + MINOR * 100 + MICRO). + E.g., "3.7.4" => 30704, "3.8" => 30800. + Return -1 on errors. */ +int strversion_to_int (char const *version); + +#endif diff --git a/contrib/tools/bison/src/symlist.c b/contrib/tools/bison/src/symlist.c index 9bb0deaacb..3e6a8d9698 100644 --- a/contrib/tools/bison/src/symlist.c +++ b/contrib/tools/bison/src/symlist.c @@ -1,6 +1,6 @@ /* Lists of symbols for Bison - Copyright (C) 2002, 2005-2007, 2009-2015, 2018-2020 Free Software + Copyright (C) 2002, 2005-2007, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> #include "system.h" @@ -83,10 +83,10 @@ symbol_list_type_new (uniqstr type_name, location loc) symbol_list * -symbol_list_type_set (symbol_list *syms, uniqstr type_name, location loc) +symbol_list_type_set (symbol_list *syms, uniqstr type_name) { for (symbol_list *l = syms; l; l = l->next) - symbol_type_set (l->content.sym, type_name, loc); + symbol_type_set (l->content.sym, type_name, l->sym_loc); return syms; } diff --git a/contrib/tools/bison/src/symlist.h b/contrib/tools/bison/src/symlist.h index d94b7aa1b0..833cdbe8fa 100644 --- a/contrib/tools/bison/src/symlist.h +++ b/contrib/tools/bison/src/symlist.h @@ -1,6 +1,6 @@ /* Lists of symbols for Bison - Copyright (C) 2002, 2005-2007, 2009-2015, 2018-2020 Free Software + Copyright (C) 2002, 2005-2007, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef SYMLIST_H_ # define SYMLIST_H_ @@ -110,8 +110,7 @@ symbol_list *symbol_list_type_new (uniqstr type_name, location loc); /** Assign the type \c type_name to all the members of \c syms. ** \returns \c syms */ -symbol_list *symbol_list_type_set (symbol_list *syms, - uniqstr type_name, location loc); +symbol_list *symbol_list_type_set (symbol_list *syms, uniqstr type_name); /** Print this list. diff --git a/contrib/tools/bison/src/symtab.c b/contrib/tools/bison/src/symtab.c index c9ac27f482..be075d2412 100644 --- a/contrib/tools/bison/src/symtab.c +++ b/contrib/tools/bison/src/symtab.c @@ -1,6 +1,6 @@ /* Symbol table manager for Bison. - Copyright (C) 1984, 1989, 2000-2002, 2004-2015, 2018-2020 Free + Copyright (C) 1984, 1989, 2000-2002, 2004-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> #include "symtab.h" @@ -33,6 +33,13 @@ #include "gram.h" #include "intprops.h" +/** Undefined token code. */ +#define CODE_UNDEFINED (-1) + +/* Undefined symbol number. */ +#define NUMBER_UNDEFINED (-1) + + static struct hash_table *symbol_table = NULL; static struct hash_table *semantic_type_table = NULL; @@ -51,8 +58,8 @@ static semantic_type **semantic_types_sorted = NULL; symbol *errtoken = NULL; symbol *undeftoken = NULL; -symbol *endtoken = NULL; -symbol *accept = NULL; +symbol *eoftoken = NULL; +symbol *acceptsymbol = NULL; symbol *startsymbol = NULL; location startsymbol_loc; @@ -71,9 +78,9 @@ static bool symbol_is_user_defined (symbol *sym) { const bool eof_is_user_defined - = !endtoken->alias || STRNEQ (endtoken->alias->tag, "$end"); + = !eoftoken->alias || STRNEQ (eoftoken->alias->tag, "$end"); return sym->tag[0] != '$' - && (eof_is_user_defined || (sym != endtoken && sym->alias != errtoken)) + && (eof_is_user_defined || (sym != eoftoken && sym->alias != errtoken)) && sym != errtoken && sym->alias != errtoken && sym != undeftoken && sym->alias != undeftoken; } @@ -99,7 +106,7 @@ sym_content_new (symbol *s) res->prec_loc = empty_loc; res->prec = 0; res->assoc = undef_assoc; - res->user_token_number = USER_NUMBER_UNDEFINED; + res->code = CODE_UNDEFINED; res->class = unknown_sym; res->status = undeclared; @@ -130,11 +137,6 @@ symbol_new (uniqstr tag, location loc) res->alias = NULL; res->content = sym_content_new (res); res->is_alias = false; - - if (nsyms == SYMBOL_NUMBER_MAXIMUM) - complain (NULL, fatal, _("too many symbols in input grammar (limit is %d)"), - SYMBOL_NUMBER_MAXIMUM); - nsyms++; return res; } @@ -175,11 +177,11 @@ symbol_free (void *ptr) */ static void -symbols_sort (symbol **first, symbol **second) +symbols_sort (const symbol **first, const symbol **second) { if (0 < location_cmp ((*first)->location, (*second)->location)) { - symbol* tmp = *first; + const symbol* tmp = *first; *first = *second; *second = tmp; } @@ -236,7 +238,11 @@ semantic_type_new (uniqstr tag, const location *loc) | Print a symbol. | `-----------------*/ -#define SYMBOL_ATTR_PRINT(Attr) \ +#define SYMBOL_INT_ATTR_PRINT(Attr) \ + if (s->content) \ + fprintf (f, " %s = %d", #Attr, s->content->Attr) + +#define SYMBOL_STR_ATTR_PRINT(Attr) \ if (s->content && s->content->Attr) \ fprintf (f, " %s { %s }", #Attr, s->content->Attr) @@ -257,7 +263,11 @@ symbol_print (symbol const *s, FILE *f) : c == nterm_sym ? "nterm" : NULL, /* abort. */ s->tag); - SYMBOL_ATTR_PRINT (type_name); + putc (' ', f); + location_print (s->location, f); + SYMBOL_INT_ATTR_PRINT (code); + SYMBOL_INT_ATTR_PRINT (number); + SYMBOL_STR_ATTR_PRINT (type_name); SYMBOL_CODE_PRINT (destructor); SYMBOL_CODE_PRINT (printer); } @@ -364,7 +374,7 @@ symbol_from_uniqstr_fuzzy (const uniqstr key) } static void -complain_symbol_undeclared (symbol *sym) +complain_symbol_undeclared (const symbol *sym) { assert (sym->content->status != declared); const symbol *best = symbol_from_uniqstr_fuzzy (sym->tag); @@ -391,7 +401,10 @@ void symbol_location_as_lhs_set (symbol *sym, location loc) { if (!sym->location_of_lhs) - sym->location = loc; + { + sym->location = loc; + sym->location_of_lhs = true; + } } @@ -541,10 +554,6 @@ symbol_class_set (symbol *sym, symbol_class class, location loc, bool declaring) if (class == token_sym && s->class == pct_type_sym) complain_pct_type_on_token (&sym->location); - if (class == nterm_sym && s->class != nterm_sym) - s->number = nvars++; - else if (class == token_sym && s->number == NUMBER_UNDEFINED) - s->number = ntokens++; s->class = class; if (declaring) @@ -566,36 +575,32 @@ symbol_class_set (symbol *sym, symbol_class class, location loc, bool declaring) } -/*------------------------------------------------. -| Set the USER_TOKEN_NUMBER associated with SYM. | -`------------------------------------------------*/ +/*----------------------------. +| Set the token code of SYM. | +`----------------------------*/ void -symbol_user_token_number_set (symbol *sym, int user_token_number, location loc) +symbol_code_set (symbol *sym, int code, location loc) { - int *user_token_numberp = &sym->content->user_token_number; + int *codep = &sym->content->code; if (sym->content->class != token_sym) complain (&loc, complaint, _("nonterminals cannot be given a token code")); - else if (*user_token_numberp != USER_NUMBER_UNDEFINED - && *user_token_numberp != user_token_number) + else if (*codep != CODE_UNDEFINED + && *codep != code) complain (&loc, complaint, _("redefining code of token %s"), sym->tag); - else if (user_token_number == INT_MAX) + else if (code == INT_MAX) complain (&loc, complaint, _("code of token %s too large"), sym->tag); else { - *user_token_numberp = user_token_number; + *codep = code; /* User defined $end token? */ - if (user_token_number == 0 && !endtoken) + if (code == 0 && !eoftoken) { - endtoken = sym->content->symbol; - /* It is always mapped to 0, so it was already counted in - NTOKENS. */ - if (endtoken->content->number != NUMBER_UNDEFINED) - --ntokens; - endtoken->content->number = 0; + eoftoken = sym->content->symbol; + eoftoken->content->number = 0; } } } @@ -614,9 +619,11 @@ symbol_check_defined (symbol *sym) { complain_symbol_undeclared (sym); s->class = nterm_sym; - s->number = nvars++; } + if (s->number == NUMBER_UNDEFINED) + s->number = s->class == token_sym ? ntokens++ : nnterms++; + if (s->class == token_sym && sym->tag[0] == '"' && !sym->is_alias) @@ -735,7 +742,7 @@ symbol_pack (symbol *sym) } static void -complain_user_token_number_redeclared (int num, symbol *first, symbol *second) +complain_code_redeclared (int num, const symbol *first, const symbol *second) { symbols_sort (&first, &second); complain (&second->location, complaint, @@ -751,20 +758,18 @@ complain_user_token_number_redeclared (int num, symbol *first, symbol *second) `-------------------------------------------------*/ static void -symbol_translation (symbol *sym) +symbol_translation (const symbol *sym) { - /* Nonterminal? */ - if (sym->content->class == token_sym - && !sym->is_alias) + if (sym->content->class == token_sym && !sym->is_alias) { - /* A token which translation has already been set?*/ - if (token_translations[sym->content->user_token_number] + /* A token whose translation has already been set? */ + if (token_translations[sym->content->code] != undeftoken->content->number) - complain_user_token_number_redeclared - (sym->content->user_token_number, - symbols[token_translations[sym->content->user_token_number]], sym); + complain_code_redeclared + (sym->content->code, + symbols[token_translations[sym->content->code]], sym); else - token_translations[sym->content->user_token_number] + token_translations[sym->content->code] = sym->content->number; } } @@ -842,10 +847,10 @@ symbols_new (void) hash_symbol_comparator, symbol_free); - /* Construct the accept symbol. */ - accept = symbol_get ("$accept", empty_loc); - accept->content->class = nterm_sym; - accept->content->number = nvars++; + /* Construct the acceptsymbol symbol. */ + acceptsymbol = symbol_get ("$accept", empty_loc); + acceptsymbol->content->class = nterm_sym; + acceptsymbol->content->number = nnterms++; /* Construct the YYerror/"error" token */ errtoken = symbol_get ("YYerror", empty_loc); @@ -887,17 +892,16 @@ symbol_from_uniqstr (const uniqstr key, location loc) symbol probe; probe.tag = key; - symbol *entry = hash_lookup (symbol_table, &probe); + symbol *res = hash_lookup (symbol_table, &probe); - if (!entry) + if (!res) { /* First insertion in the hash. */ aver (!symbols_sorted); - entry = symbol_new (key, loc); - if (!hash_insert (symbol_table, entry)) - xalloc_die (); + res = symbol_new (key, loc); + hash_xinsert (symbol_table, res); } - return entry; + return res; } @@ -912,16 +916,15 @@ semantic_type_from_uniqstr (const uniqstr key, const location *loc) semantic_type probe; probe.tag = key; - semantic_type *entry = hash_lookup (semantic_type_table, &probe); + semantic_type *res = hash_lookup (semantic_type_table, &probe); - if (!entry) + if (!res) { /* First insertion in the hash. */ - entry = semantic_type_new (key, loc); - if (!hash_insert (semantic_type_table, entry)) - xalloc_die (); + res = semantic_type_new (key, loc); + hash_xinsert (semantic_type_table, res); } - return entry; + return res; } @@ -964,7 +967,6 @@ dummy_symbol_get (location loc) assure (len < sizeof buf); symbol *sym = symbol_get (buf, loc); sym->content->class = nterm_sym; - sym->content->number = nvars++; return sym; } @@ -997,7 +999,7 @@ symbol_cmp (void const *a, void const *b) } /* Store in *SORTED an array of pointers to the symbols contained in - TABLE, sorted (alphabetically) by tag. */ + TABLE, sorted by order of appearance (i.e., by location). */ static void table_sort (struct hash_table *table, symbol ***sorted) @@ -1042,53 +1044,53 @@ symbols_check_defined (void) static void symbols_token_translations_init (void) { - bool num_256_available_p = true; + bool code_256_available_p = true; /* Find the highest token code, and whether 256, the POSIX preferred token code for the error token, is used. */ - max_user_token_number = 0; + max_code = 0; for (int i = 0; i < ntokens; ++i) { sym_content *sym = symbols[i]->content; - if (sym->user_token_number != USER_NUMBER_UNDEFINED) + if (sym->code != CODE_UNDEFINED) { - if (sym->user_token_number > max_user_token_number) - max_user_token_number = sym->user_token_number; - if (sym->user_token_number == 256) - num_256_available_p = false; + if (sym->code > max_code) + max_code = sym->code; + if (sym->code == 256) + code_256_available_p = false; } } /* If 256 is not used, assign it to error, to follow POSIX. */ - if (num_256_available_p - && errtoken->content->user_token_number == USER_NUMBER_UNDEFINED) - errtoken->content->user_token_number = 256; + if (code_256_available_p + && errtoken->content->code == CODE_UNDEFINED) + errtoken->content->code = 256; - /* Set the missing user numbers. */ - if (max_user_token_number < 256) - max_user_token_number = 256; + /* Set the missing codes. */ + if (max_code < 256) + max_code = 256; for (int i = 0; i < ntokens; ++i) { sym_content *sym = symbols[i]->content; - if (sym->user_token_number == USER_NUMBER_UNDEFINED) + if (sym->code == CODE_UNDEFINED) { IGNORE_TYPE_LIMITS_BEGIN - if (INT_ADD_WRAPV (max_user_token_number, 1, &max_user_token_number)) + if (INT_ADD_WRAPV (max_code, 1, &max_code)) complain (NULL, fatal, _("token number too large")); IGNORE_TYPE_LIMITS_END - sym->user_token_number = max_user_token_number; + sym->code = max_code; } - if (sym->user_token_number > max_user_token_number) - max_user_token_number = sym->user_token_number; + if (sym->code > max_code) + max_code = sym->code; } - token_translations = xnmalloc (max_user_token_number + 1, + token_translations = xnmalloc (max_code + 1, sizeof *token_translations); /* Initialize all entries for literal tokens to the internal token number for $undefined, which represents all invalid inputs. */ - for (int i = 0; i < max_user_token_number + 1; ++i) + for (int i = 0; i < max_code + 1; ++i) token_translations[i] = undeftoken->content->number; for (int i = 0; symbols_sorted[i]; ++i) symbol_translation (symbols_sorted[i]); @@ -1158,9 +1160,9 @@ symbols_pack (void) if (has_translations ()) { const bool eof_is_user_defined - = !endtoken->alias || STRNEQ (endtoken->alias->tag, "$end"); + = !eoftoken->alias || STRNEQ (eoftoken->alias->tag, "$end"); if (!eof_is_user_defined) - endtoken->alias->translatable = true; + eoftoken->alias->translatable = true; undeftoken->alias->translatable = true; errtoken->alias->translatable = true; } @@ -1191,10 +1193,10 @@ init_prec_nodes (void) static symgraphlink * symgraphlink_new (graphid id, symgraphlink *next) { - symgraphlink *l = xmalloc (sizeof *l); - l->id = id; - l->next = next; - return l; + symgraphlink *res = xmalloc (sizeof *res); + res->id = id; + res->next = next; + return res; } diff --git a/contrib/tools/bison/src/symtab.h b/contrib/tools/bison/src/symtab.h index d16c027082..86e6d89cfe 100644 --- a/contrib/tools/bison/src/symtab.h +++ b/contrib/tools/bison/src/symtab.h @@ -1,6 +1,6 @@ /* Definitions for symtab.c and callers, part of Bison. - Copyright (C) 1984, 1989, 1992, 2000-2002, 2004-2015, 2018-2020 Free + Copyright (C) 1984, 1989, 1992, 2000-2002, 2004-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ /** * \file symtab.h @@ -149,21 +149,13 @@ struct sym_content int prec; assoc assoc; - /** The user specified token number. - - E.g., %token FOO 42.*/ - int user_token_number; + /** Token code, possibly specified by the user (%token FOO 42). */ + int code; symbol_class class; declaration_status status; }; -/** Undefined user number. */ -# define USER_NUMBER_UNDEFINED -1 - -/* Undefined internal token number. */ -# define NUMBER_UNDEFINED (-1) - /** Fetch (or create) the symbol associated to KEY. */ symbol *symbol_from_uniqstr (const uniqstr key, location loc); @@ -235,8 +227,8 @@ void symbol_precedence_set (symbol *sym, int prec, assoc a, location loc); void symbol_class_set (symbol *sym, symbol_class class, location loc, bool declaring); -/** Set the \c user_token_number associated with \c sym. */ -void symbol_user_token_number_set (symbol *sym, int user_number, location loc); +/** Set the token \c code of \c sym, specified by the user at \c loc. */ +void symbol_code_set (symbol *sym, int code, location loc); @@ -249,11 +241,11 @@ extern symbol *errtoken; /** The token for unknown tokens. */ extern symbol *undeftoken; /** The end of input token. */ -extern symbol *endtoken; +extern symbol *eoftoken; /** The genuine start symbol. $accept: start-symbol $end */ -extern symbol *accept; +extern symbol *acceptsymbol; /** The user start symbol. */ extern symbol *startsymbol; diff --git a/contrib/tools/bison/src/system.h b/contrib/tools/bison/src/system.h index 606d3c4668..bbdf9fd0f8 100644 --- a/contrib/tools/bison/src/system.h +++ b/contrib/tools/bison/src/system.h @@ -1,6 +1,6 @@ /* System-dependent definitions for Bison. - Copyright (C) 2000-2007, 2009-2015, 2018-2020 Free Software + Copyright (C) 2000-2007, 2009-2015, 2018-2021 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify @@ -14,7 +14,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef BISON_SYSTEM_H # define BISON_SYSTEM_H @@ -78,7 +78,7 @@ typedef size_t uintptr_t; # define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) # endif -// See https://lists.gnu.org/archive/html/bug-bison/2019-10/msg00061.html +// See https://lists.gnu.org/r/bug-bison/2019-10/msg00061.html // and https://trac.macports.org/ticket/59927. # if defined GCC_VERSION && 405 <= GCC_VERSION # define IGNORE_TYPE_LIMITS_BEGIN \ @@ -110,28 +110,7 @@ typedef size_t uintptr_t; Bison's performance anyway. */ # define PACIFY_CC(Code) Code -# ifndef __attribute__ -/* This feature is available in gcc versions 2.5 and later. */ -# if (! defined __GNUC__ || __GNUC__ < 2 \ - || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)) -# define __attribute__(Spec) /* empty */ -# endif -# endif - -/* The __-protected variants of 'format' and 'printf' attributes - are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */ -# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) -# define __format__ format -# define __printf__ printf -# endif - -# ifndef ATTRIBUTE_NORETURN -# define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) -# endif - -# ifndef ATTRIBUTE_UNUSED -# define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) -# endif +# include <attribute.h> /*------. @@ -152,6 +131,22 @@ typedef size_t uintptr_t; # include <stdbool.h> +/*-----------. +| Integers. | +`-----------*/ + +static inline int +min_int (int a, int b) +{ + return a < b ? a : b; +} + +static inline int +max_int (int a, int b) +{ + return a >= b ? a : b; +} + /*-------------. | Assertions. | @@ -161,8 +156,8 @@ typedef size_t uintptr_t; a failed assertion. The rationale was that <assert.h>'s assertions were too heavyweight and could be disabled too easily. See discussions at - <http://lists.gnu.org/archive/html/bison-patches/2006-01/msg00080.html> - <http://lists.gnu.org/archive/html/bison-patches/2006-09/msg00111.html>. + <https://lists.gnu.org/r/bison-patches/2006-01/msg00080.html> + <https://lists.gnu.org/r/bison-patches/2006-09/msg00111.html>. However, normal assert output can be helpful during development and in bug reports from users. Moreover, it's not clear now that @@ -170,7 +165,7 @@ typedef size_t uintptr_t; users want to experiment with disabling assertions, it's debatable whether it's our responsibility to stop them. See discussion starting at - <http://lists.gnu.org/archive/html/bison-patches/2009-09/msg00013.html>. + <https://lists.gnu.org/r/bison-patches/2009-09/msg00013.html>. For now, we use assert but we call it aver throughout Bison in case we later wish to try another scheme. @@ -192,6 +187,23 @@ typedef size_t uintptr_t; # define obstack_sgrow(Obs, Str) \ obstack_grow (Obs, Str, strlen (Str)) +/* Output Str escaped to be a string. + + For instance "\"foo\"" -> "\\\"foo\\\"". */ + +# define obstack_backslash(Obs, Str) \ + do { \ + char const *p__; \ + for (p__ = Str; *p__; p__++) \ + switch (*p__) \ + { \ + case '"': obstack_sgrow (Obs, "\\\""); break; \ + case '\\': obstack_sgrow (Obs, "\\\\"); break; \ + default: obstack_1grow (Obs, *p__); break; \ + } \ + } while (0) + + /* Output Str escaped for our postprocessing (i.e., escape M4 special characters). diff --git a/contrib/tools/bison/src/tables.c b/contrib/tools/bison/src/tables.c index b165f0fbdc..23a879cacd 100644 --- a/contrib/tools/bison/src/tables.c +++ b/contrib/tools/bison/src/tables.c @@ -1,6 +1,6 @@ /* Output the generated parsing program for Bison. - Copyright (C) 1984, 1986, 1989, 1992, 2000-2006, 2009-2015, 2018-2020 + Copyright (C) 1984, 1986, 1989, 1992, 2000-2006, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> #include "system.h" @@ -111,9 +111,13 @@ base_number *base = NULL; computation equals to BASE_MINIMUM, later mapped to BASE_NINF to keep parser tables small. */ base_number base_ninf = 0; + /* Bitset representing an integer set in the range - -nstates..table_size (as an upper bound) */ + POS_SET_OFFSET..(POS_SET_OFFSET + SIZE). POS_SET_OFFSET is + nonpositive. */ static bitset pos_set = NULL; +/* The integer denoted by bitno 0 in pos_set. */ +static int pos_set_base = 0; static int *conflrow; int *conflict_table; @@ -138,6 +142,76 @@ int high; state_number *yydefgoto; rule_number *yydefact; + +/*----------. +| pos_set. | +`----------*/ + +#if 0 +static void +pos_set_dump (void) +{ + fprintf (stderr, "pos_set (%ld, %d) =", bitset_size (pos_set), pos_set_base); + bitset_iterator biter; + int i; + BITSET_FOR_EACH (biter, pos_set, i, 0) + fprintf (stderr, " %d", i + pos_set_base); + putc ('\n', stderr); +} +#endif + + +/* The size and base of POS_SET are not known, we need to be able to + move the base farther "on the left", and grow "on the right". + + It would be nice to be able to predict the base accurately, but it + seems difficult (-nstates seems to work most of the time, except + when there are useless tokens). + + FIXME: The current approach is correct, but with poor performances. + Bitsets need to support 'assign' and 'shift'. And instead of + extending POS_SET just for the out-of-range new values, we need + something like doubling the size. + */ + +static void +pos_set_set (int pos) +{ + int bitno = pos - pos_set_base; + if (bitno < 0) + { + // Need more room on the left. + // DELTA is positive. Run 'pos_set >> delta'. + const int delta = pos_set_base - pos; + const int old_size = bitset_size (pos_set); + const int new_size = old_size + delta; + bitset_resize (pos_set, new_size); + // Right-shift all the bits by DELTA. Be sure to reset the new + // bits on the left. + // + // FIXME: add bitset_assign, and bitset_shift? + for (int i = new_size - 1; 0 <= i ; --i) + if (delta <= i && bitset_test (pos_set, i - delta)) + bitset_set (pos_set, i); + else + bitset_reset (pos_set, i); + pos_set_base = pos; + bitno = 0; + } + else if (bitset_size (pos_set) <= bitno) + // Need more room on the right. + bitset_resize (pos_set, bitno + 1); + bitset_set (pos_set, bitno); +} + +static bool +pos_set_test (int pos) +{ + const int bitno = pos - pos_set_base; + return bitset_test (pos_set, bitno); +} + + /*-------------------------------------------------------------------. | If TABLE, CONFLICT_TABLE, and CHECK are too small to be addressed | | at DESIRED, grow them. TABLE[DESIRED] can be used, so the desired | @@ -168,8 +242,6 @@ table_grow (int desired) check = xnrealloc (check, table_size, sizeof *check); for (int i = old_size; i < table_size; ++i) check[i] = -1; - - bitset_resize (pos_set, table_size + nstates); } @@ -200,7 +272,7 @@ conflict_row (state *s) /* Find all reductions for token J, and record all that do not match ACTROW[J]. */ for (int i = 0; i < reds->num; i += 1) - if (bitset_test (reds->lookahead_tokens[i], j) + if (bitset_test (reds->lookaheads[i], j) && (actrow[j] != rule_number_as_item_number (reds->rules[i]->number))) { @@ -247,7 +319,7 @@ action_row (state *s) reductions *reds = s->reductions; bool conflicted = false; - if (reds->lookahead_tokens) + if (reds->lookaheads) /* loop over all the rules available here which require lookahead (in reverse order to give precedence to the first rule) */ @@ -257,7 +329,7 @@ action_row (state *s) { bitset_iterator biter; int j; - BITSET_FOR_EACH (biter, reds->lookahead_tokens[i], j, 0) + BITSET_FOR_EACH (biter, reds->lookaheads[i], j, 0) { /* and record this rule as the rule to use if that token follows. */ @@ -308,7 +380,7 @@ action_row (state *s) } /* Turn off default reductions where requested by the user. See - state_lookahead_tokens_count in lalr.c to understand when states are + state_lookaheads_count in lalr.c to understand when states are labeled as consistent. */ { char *default_reductions = @@ -512,7 +584,14 @@ default_goto (symbol_number sym, size_t state_count[]) { const goto_number begin = goto_map[sym - ntokens]; const goto_number end = goto_map[sym - ntokens + 1]; - state_number res = -1; + + /* In the case this symbol is never reduced to ($accept), use state + 0. We used to use -1, but as a result the yydefgoto table must + be signed, which (1) might trigger compiler warnings when storing + a value from yydefgoto into a state number (nonnegative), and (2) + wastes bits which might result in using a int16 where a uint8 + suffices. */ + state_number res = 0; if (begin != end) { @@ -547,7 +626,7 @@ static void goto_actions (void) { size_t *state_count = xnmalloc (nstates, sizeof *state_count); - yydefgoto = xnmalloc (nvars, sizeof *yydefgoto); + yydefgoto = xnmalloc (nnterms, sizeof *yydefgoto); /* For a given nterm I, STATE_COUNT[S] is the number of times there is a GOTO to S on I. */ @@ -665,7 +744,7 @@ pack_vector (vector_number vector) ok = false; } - if (ok && bitset_test (pos_set, nstates + res)) + if (ok && pos_set_test (res)) ok = false; } @@ -725,6 +804,7 @@ pack_table (void) { base = xnmalloc (nvectors, sizeof *base); pos_set = bitset_create (table_size + nstates, BITSET_FRUGAL); + pos_set_base = -nstates; table = xcalloc (table_size, sizeof *table); conflict_table = xcalloc (table_size, sizeof *conflict_table); check = xnmalloc (table_size, sizeof *check); @@ -750,12 +830,7 @@ pack_table (void) /* Action of I were already coded for S. */ place = base[s]; - /* Store PLACE into POS_SET. PLACE might not belong to the set - of possible values for instance with useless tokens. It - would be more satisfying to eliminate the need for this - 'if'. */ - if (0 <= nstates + place) - bitset_set (pos_set, nstates + place); + pos_set_set (place); base[order[i]] = place; } @@ -780,9 +855,9 @@ tables_generate (void) correlated. In particular the signedness is not taken into account. But it's not useless. */ verify (sizeof nstates <= sizeof nvectors); - verify (sizeof nvars <= sizeof nvectors); + verify (sizeof nnterms <= sizeof nvectors); - nvectors = state_number_as_int (nstates) + nvars; + nvectors = state_number_as_int (nstates) + nnterms; froms = xcalloc (nvectors, sizeof *froms); tos = xcalloc (nvectors, sizeof *tos); diff --git a/contrib/tools/bison/src/tables.h b/contrib/tools/bison/src/tables.h index b0d420ad13..2194a8147c 100644 --- a/contrib/tools/bison/src/tables.h +++ b/contrib/tools/bison/src/tables.h @@ -1,6 +1,6 @@ /* Prepare the LALR and GLR parser tables. - Copyright (C) 2002, 2004, 2009-2015, 2018-2020 Free Software + Copyright (C) 2002, 2004, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef TABLES_H_ # define TABLES_H_ diff --git a/contrib/tools/bison/src/uniqstr.c b/contrib/tools/bison/src/uniqstr.c index d16e254a60..e7dbd5d371 100644 --- a/contrib/tools/bison/src/uniqstr.c +++ b/contrib/tools/bison/src/uniqstr.c @@ -1,6 +1,6 @@ /* Keep a unique copy of strings. - Copyright (C) 2002-2005, 2009-2015, 2018-2020 Free Software + Copyright (C) 2002-2005, 2009-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,11 +16,12 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #include <config.h> #include "system.h" +#include <attribute.h> #include <error.h> #include <hash.h> #include <quotearg.h> @@ -49,8 +50,7 @@ uniqstr_new (char const *str) { /* First insertion in the hash. */ res = xstrdup (str); - if (!hash_insert (uniqstrs_table, res)) - xalloc_die (); + hash_xinsert (uniqstrs_table, res); } return res; } @@ -80,9 +80,7 @@ uniqstr_concat (int nargs, ...) va_end (args); *p = '\0'; - uniqstr res = hash_insert (uniqstrs_table, str); - if (!res) - xalloc_die (); + uniqstr res = hash_xinsert (uniqstrs_table, str); if (res != str) free (str); return res; @@ -117,12 +115,11 @@ uniqstr_print (uniqstr ustr) } static bool -uniqstr_print_processor (void *ustr, void *null ATTRIBUTE_UNUSED) +uniqstr_print_processor (void *ustr, void *null MAYBE_UNUSED) { return uniqstr_print (ustr); } - int uniqstr_cmp (uniqstr l, uniqstr r) { diff --git a/contrib/tools/bison/src/uniqstr.h b/contrib/tools/bison/src/uniqstr.h index 8f61ef4be1..0a1c506fb9 100644 --- a/contrib/tools/bison/src/uniqstr.h +++ b/contrib/tools/bison/src/uniqstr.h @@ -1,6 +1,6 @@ /* Keeping a unique copy of strings. - Copyright (C) 2002-2003, 2008-2015, 2018-2020 Free Software + Copyright (C) 2002-2003, 2008-2015, 2018-2021 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. @@ -16,7 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ + along with this program. If not, see <https://www.gnu.org/licenses/>. */ #ifndef UNIQSTR_H_ # define UNIQSTR_H_ diff --git a/contrib/tools/bison/ya.make b/contrib/tools/bison/ya.make index abcbd4c4f5..9ec7f6aebe 100644 --- a/contrib/tools/bison/ya.make +++ b/contrib/tools/bison/ya.make @@ -5,15 +5,14 @@ PROGRAM(bison) LICENSE( Bison-exception-2.2 AND GPL-3.0-only AND - GPL-3.0-or-later AND - GPL-3.0-or-later WITH Bison-exception-2.2 + GPL-3.0-or-later ) LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -VERSION(3.6.4) +VERSION(3.7.6) -ORIGINAL_SOURCE(mirror://gnu/bison/bison-3.6.4.tar.gz) +ORIGINAL_SOURCE(mirror://gnu/bison/bison-3.7.6.tar.gz) PEERDIR( contrib/tools/bison/lib @@ -30,7 +29,7 @@ NO_RUNTIME() CFLAGS( -DEXEEXT=\"\" - -DINSTALLDIR=\"/var/empty/bison-3.6.4/bin\" + -DINSTALLDIR=\"/var/empty/bison-3.7.6/bin\" ) SRCS( @@ -41,22 +40,27 @@ SRCS( src/closure.c src/complain.c src/conflicts.c + src/counterexample.c + src/derivation.c src/derives.c src/files.c src/fixits.c src/getargs.c + src/glyphs.c src/gram.c src/graphviz.c src/ielr.c src/lalr.c src/location.c src/lr0.c + src/lssi.c src/main.c src/muscle-tab.c src/named-ref.c src/nullable.c src/output.c src/parse-gram.c + src/parse-simulation.c src/print-graph.c src/print-xml.c src/print.c @@ -66,7 +70,9 @@ SRCS( src/scan-code-c.c src/scan-gram-c.c src/scan-skel-c.c + src/state-item.c src/state.c + src/strversion.c src/symlist.c src/symtab.c src/tables.c |