diff --git a/.reuse/dep5 b/.reuse/dep5 index 538eb37..930300b 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -8,3 +8,7 @@ Source: https://github.com/fosslinux/live-bootstrap # Files: src/* # Copyright: $YEAR $NAME <$CONTACT> # License: ... + +Files: SHA256SUMS.sources +Copyright: none +License: MIT diff --git a/README.md b/README.md index a5f3354..09f1527 100644 --- a/README.md +++ b/README.md @@ -305,12 +305,23 @@ stage process, first compiling flex using `scan.c` (from `scan.l`) created by old flex, then recompile `scan.c` using the new version of flex to remove any buggy artifacts from the old flex. -#### Part 24: grep 2.4 +#### Part 24: bison 3.4.1 + +GNU `bison` is a parser generator. With `m4` and `flex` we can now bootstrap it +following https://gitlab.com/giomasce/bison-bootstrap. It's a 3 stage process: + +1) Build bison using a handwritten grammar parser in C. +2) Use bison from previous stage on a simplified bison grammar file. +3) Build bison using original grammar file. + +Finally we have a fully functional `bison` executable. + +#### Part 25: grep 2.4 GNU `grep` is a pattern matching utility. Is is not immediately needed but will be useful later for autotools. -#### Part 25: diffutils 2.7 +#### Part 26: diffutils 2.7 `diffutils` is useful for comparing two files. It is not immediately needed but is required later for autotools. diff --git a/SHA256SUMS.sources b/SHA256SUMS.sources index 9f54950..9b51728 100644 --- a/SHA256SUMS.sources +++ b/SHA256SUMS.sources @@ -1,15 +1,15 @@ -c6c37e888b136ccefab903c51149f4b7bd659d69d4aea21245f61053a57aa60a tar-1.12.tar.gz -4d2ce9f314f39c9575f913503b0178d6fb2c92920db8e7b7b176b7bab7980fe6 gzip-1.2.4.tar -ecb5c6469d732bcf01d6ec1afe9e64f1668caba5bfdb103c28d7f537ba3cdb8a patch-2.5.9.tar.gz -64b30b41fde2ebf669e6af489883fb1df6a06ac30555a96cfa3c39ecce7267dd make-3.80.tar.gz +ba03d412998cc54bd0b0f2d6c32100967d3137098affdc2d32e6e7c11b163fe4 bash-2.05b.tar.gz +7007fc89c216fbfaff5525359b02a7e5b612694df5168c74673f67055f015095 bison-3.4.1.tar.gz ab5a03176ee106d3f0fa90e381da478ddae405918153cca248e682cd0c4a2269 bzip2-1.0.8.tar.gz c25b36b8af6e0ad2a875daf4d6196bd0df28a62be7dd252e5f99a4d5d7288d95 coreutils-5.0.tar.bz2 -9f233d8b78e4351fe9dd2d50d83958a0e5af36f54e9818521458a08e058691ba heirloom-devtools-070527.tar.bz2 -ba03d412998cc54bd0b0f2d6c32100967d3137098affdc2d32e6e7c11b163fe4 bash-2.05b.tar.gz -a116c52d314c8e3365756cb1e14c6b460d6bd28769121f92373a362497359d88 m4-1.4.4.tar.gz +d5f2489c4056a31528e3ada4adacc23d498532b0af1a980f2f76158162b139d6 diffutils-2.7.tar.gz bc79b890f35ca38d66ff89a6e3758226131e51ccbd10ef78d5ff150b7bd73689 flex-2.5.11.tar.gz -1370c9a812b2cf2a7d92802510cca0058cc37e66a7bedd70051f0a34015022a3 musl-1.1.24.tar.gz e87aae032bf07c26f85ac0ed3250998c37621d95f8bd748b31f15b33c45ee995 flex-2.6.4.tar.gz a32032bab36208509466654df12f507600dfe0313feebbcd218c32a70bf72a16 grep-2.4.tar.gz -d5f2489c4056a31528e3ada4adacc23d498532b0af1a980f2f76158162b139d6 diffutils-2.7.tar.gz +4d2ce9f314f39c9575f913503b0178d6fb2c92920db8e7b7b176b7bab7980fe6 gzip-1.2.4.tar +9f233d8b78e4351fe9dd2d50d83958a0e5af36f54e9818521458a08e058691ba heirloom-devtools-070527.tar.bz2 093c993767f563a11e41c1cf887f4e9065247129679d4c1e213d0544d16d8303 m4-1.4.7.tar.gz +64b30b41fde2ebf669e6af489883fb1df6a06ac30555a96cfa3c39ecce7267dd make-3.80.tar.gz +1370c9a812b2cf2a7d92802510cca0058cc37e66a7bedd70051f0a34015022a3 musl-1.1.24.tar.gz +ecb5c6469d732bcf01d6ec1afe9e64f1668caba5bfdb103c28d7f537ba3cdb8a patch-2.5.9.tar.gz +c6c37e888b136ccefab903c51149f4b7bd659d69d4aea21245f61053a57aa60a tar-1.12.tar.gz diff --git a/rootfs.sh b/rootfs.sh index e29e318..ba5fb0a 100755 --- a/rootfs.sh +++ b/rootfs.sh @@ -178,6 +178,9 @@ get_file https://ftp.gnu.org/gnu/m4/m4-1.4.7.tar.gz # flex 2.6.4 get_file https://github.com/westes/flex/releases/download/v2.6.4/flex-2.6.4.tar.gz +# bison 3.4.1 +get_file https://ftp.gnu.org/gnu/bison/bison-3.4.1.tar.gz + # grep 2.4 get_file https://ftp.gnu.org/gnu/grep/grep-2.4.tar.gz diff --git a/sysa/bison-3.4.1/files/config.h b/sysa/bison-3.4.1/files/config.h new file mode 100644 index 0000000..ce93393 --- /dev/null +++ b/sysa/bison-3.4.1/files/config.h @@ -0,0 +1,39 @@ +// SPDX-FileCopyrightText: 2020 Andrius Štikonas + +// SPDX-License-Identifier: GPL-3.0-or-later + +#define HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME 1 +#define HAVE_DECL_STRERROR_R 1 +#define HAVE_GETTIMEOFDAY 1 +#define HAVE_PIPE 1 +#define HAVE_SNPRINTF 1 +#define HAVE_STDINT_H 1 +#define HAVE_UNISTD_H 1 +#define M4 "/after/bin/m4" +#define M4_GNU_OPTION "" +#define PACKAGE "bison" +#define PACKAGE_BUGREPORT "bug-bison@gnu.org" +#define PACKAGE_COPYRIGHT_YEAR 2019 +#define PACKAGE_NAME "GNU Bison" +#define PACKAGE_STRING "GNU Bison 3.4.1" +#define PACKAGE_URL "http://www.gnu.org/software/bison/" +#define PACKAGE_VERSION "3.4.1" +#define VERSION "3.4.1" +#define PROMOTED_MODE_T mode_t +#define BOURNE_SHELL "/bin/sh" +#define _GNU_SOURCE 1 +#define _Noreturn +#define _GL_ASYNC_SAFE +#define _GL_EXTERN_INLINE extern inline +#define _GL_INLINE_HEADER_BEGIN +#define _GL_INLINE_HEADER_END +#define _GL_UNUSED +#define _GL_UNUSED_LABEL +#define _GL_ATTRIBUTE_PURE +#define _GL_ATTRIBUTE_CONST +#define _GL_ATTRIBUTE_MALLOC +#define _GL_ATTRIBUTE_FORMAT_PRINTF(x, y) +#define _GL_ARG_NONNULL(x) +#ifndef _GL_INLINE +#define _GL_INLINE static inline +#endif diff --git a/sysa/bison-3.4.1/files/configmake.h b/sysa/bison-3.4.1/files/configmake.h new file mode 100644 index 0000000..b26090f --- /dev/null +++ b/sysa/bison-3.4.1/files/configmake.h @@ -0,0 +1,6 @@ +// SPDX-FileCopyrightText: 2020 Andrius Štikonas + +// SPDX-License-Identifier: GPL-3.0-or-later + +#define LOCALEDIR "/after/share/locale" +#define PKGDATADIR "/after/share/bison" diff --git a/sysa/bison-3.4.1/files/parse-gram.c b/sysa/bison-3.4.1/files/parse-gram.c new file mode 100644 index 0000000..945df15 --- /dev/null +++ b/sysa/bison-3.4.1/files/parse-gram.c @@ -0,0 +1,972 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +/* + * This file is based on parse-gram.y from GNU Bison 3.4.1. It + * implements a subset of the grammar described by parse-gram.y, just + * enough to provide a bootstrapping path for Bison. + * + * Copyright (c) 2020, Giovanni Mascellani + * + * The copyright notice of the original file follows. This file is + * distributed under the same license and with the same conditions. + */ + +/* Bison Grammar Parser -*- C -*- + + Copyright (C) 2002-2015, 2018-2019 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 . */ + +/* + * Since this code is intended to provide a bootstrapping path for GNU + * Bison, it is important that it is as easy to understand as + * possible. Fortunately Bison's grammar is rather simple. I believe + * that if you know how Bison works, you should not find it hard to + * follow the logic in this file and compare it with the original + * grammar. + * + * Apart from the code literally copied from the grammar file + * (prologues and epilogue), this file basically contains a few + * wrappers over the lexer interface (the functions gram_*), basically + * adding the feature to give back one lexeme and a lot of functions + * parse_* or maybe_parse_*, parsing the corresponding grammar + * rule. Functions maybe_parse_* are allowed to fail, and return + * accordingly. + * + * Error checking is very simple and just made of assertions. This is + * just boostrapping code, not meant for end users, so it should not + * be a problem. + */ + +/* %code top */ + /* On column 0 to please syntax-check. */ +#include + +#include + +#define YYLTYPE GRAM_LTYPE + +#include "parse-gram.h" + +/* %code */ + #include "system.h" + #include + + #include "c-ctype.h" + #include "complain.h" + #include "conflicts.h" + #include "files.h" + #include "getargs.h" + #include "gram.h" + #include "named-ref.h" + #include "quotearg.h" + #include "reader.h" + #include "scan-code.h" + #include "scan-gram.h" + #include "vasnprintf.h" + #include "xmemdup0.h" + + static int current_prec = 0; + static location current_lhs_loc; + static named_ref *current_lhs_named_ref; + static symbol *current_lhs_symbol; + static symbol_class current_class = unknown_sym; + + /** Set the new current left-hand side symbol, possibly common + * to several right-hand side parts of rule. + */ + static void current_lhs (symbol *sym, location loc, named_ref *ref); + + #define YYLLOC_DEFAULT(Current, Rhs, N) \ + (Current) = lloc_default (Rhs, N) + static YYLTYPE lloc_default (YYLTYPE const *, int); + + #define YY_LOCATION_PRINT(File, Loc) \ + location_print (Loc, File) + + /* Strip initial '{' and final '}' (must be first and last characters). + Return the result. */ + static char *strip_braces (char *code); + + /* Convert CODE by calling code_props_plain_init if PLAIN, otherwise + code_props_symbol_action_init. Call + 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 + string from the scanner (should be CODE). */ + static char const *translate_code_braceless (char *code, location loc); + + /* Handle a %error-verbose directive. */ + static void handle_error_verbose (location const *loc, char const *directive); + + /* Handle a %file-prefix directive. */ + static void handle_file_prefix (location const *loc, + location const *dir_loc, + char const *directive, char const *value); + + /* Handle a %name-prefix directive. */ + static void handle_name_prefix (location const *loc, + char const *directive, char const *value); + + /* Handle a %pure-parser directive. */ + static void handle_pure_parser (location const *loc, char const *directive); + + /* Handle a %require directive. */ + static void handle_require (location const *loc, char const *version); + + /* Handle a %skeleton directive. */ + static void handle_skeleton (location const *loc, char const *skel); + + /* Handle a %yacc directive. */ + static void handle_yacc (location const *loc, char const *directive); + + static void gram_error (location const *, char const *); + + /* A string that describes a char (e.g., 'a' -> "'a'"). */ + static char const *char_name (char); + + #define YYTYPE_INT16 int_fast16_t + #define YYTYPE_INT8 int_fast8_t + #define YYTYPE_UINT16 uint_fast16_t + #define YYTYPE_UINT8 uint_fast8_t + + /* Add style to semantic values in traces. */ + static void tron (FILE *yyo); + static void troff (FILE *yyo); + +int gram_debug; + +typedef struct { + GRAM_STYPE s; + GRAM_LTYPE l; + int t; +} gram_lex_ctx; + +static int gram_lex_wrap(gram_lex_ctx *ctx, GRAM_STYPE *sx, GRAM_LTYPE *lx) { + int type; + if (ctx->t == 0) { + type = gram_lex(&ctx->s, &ctx->l); + } else { + type = ctx->t; + } + /*fprintf(stderr, "%s %d from %s:%d:%d:%d to %s:%d:%d:%d\n", + ctx->t == 0 ? "Scanned" : "Rescanned", type, + ctx->l.start.file, ctx->l.start.line, ctx->l.start.column, ctx->l.start.byte, + ctx->l.end.file, ctx->l.end.line, ctx->l.end.column, ctx->l.end.byte);*/ + ctx->t = 0; + if (sx) *sx = ctx->s; + if (lx) *lx = ctx->l; + return type; +} + +static int gram_unlex_wrap(gram_lex_ctx *ctx, int t, GRAM_STYPE *s, GRAM_LTYPE *l) { + assert(ctx->t == 0); + ctx->t = t; + ctx->s = *s; + ctx->l = *l; + /*fprintf(stderr, "Unscanned %d from %s:%d:%d:%d to %s:%d:%d:%d\n", + t, + ctx->l.start.file, ctx->l.start.line, ctx->l.start.column, ctx->l.start.byte, + ctx->l.end.file, ctx->l.end.line, ctx->l.end.column, ctx->l.end.byte);*/ +} + +static void gram_get_last_loc(gram_lex_ctx *ctx, GRAM_LTYPE *l) { + *l = ctx->l; +} + +static void parse_value(gram_lex_ctx *ctx, GRAM_STYPE *sx, GRAM_LTYPE *lx) { + GRAM_STYPE s[2]; + GRAM_LTYPE l[2]; + gram_get_last_loc(ctx, &l[0]); + int t = gram_lex_wrap(ctx, &s[1], &l[1]); + switch (t) { + case ID: + YYLLOC_DEFAULT(*lx, l, 1); + sx->value.kind = muscle_keyword; + sx->value.chars = s[1].ID; + break; + case STRING: + YYLLOC_DEFAULT(*lx, l, 1); + sx->value.kind = muscle_string; + sx->value.chars = s[1].STRING; + break; + case BRACED_CODE: + YYLLOC_DEFAULT(*lx, l, 1); + sx->value.kind = muscle_code; + sx->value.chars = strip_braces(s[1].BRACED_CODE); + break; + default: + gram_unlex_wrap(ctx, t, &s[1], &l[1]); + YYLLOC_DEFAULT(*lx, l, 0); + sx->value.kind = muscle_keyword; + sx->value.chars = ""; + break; + } +} + +static void parse_int_opt(gram_lex_ctx *ctx, GRAM_STYPE *sx, GRAM_LTYPE *lx) { + GRAM_STYPE s[2]; + GRAM_LTYPE l[2]; + gram_get_last_loc(ctx, &l[0]); + int t = gram_lex_wrap(ctx, &s[1], &l[1]); + if (t == INT) { + YYLLOC_DEFAULT(*lx, l, 1); + sx->int_opt = s[1].INT; + } else { + gram_unlex_wrap(ctx, t, &s[1], &l[1]); + YYLLOC_DEFAULT(*lx, l, 0); + sx->int_opt = -1; + } +} + +static int maybe_parse_string_as_id(gram_lex_ctx *ctx, GRAM_STYPE *sx, GRAM_LTYPE *lx) { + GRAM_STYPE s[2]; + GRAM_LTYPE l[2]; + int t = gram_lex_wrap(ctx, &s[1], &l[1]); + if (t == STRING) { + YYLLOC_DEFAULT(*lx, l, 1); + sx->string_as_id = symbol_get(quotearg_style(c_quoting_style, s[1].STRING), l[1]); + symbol_class_set(sx->string_as_id, token_sym, l[1], false); + return 1; + } else { + gram_unlex_wrap(ctx, t, &s[1], &l[1]); + return 0; + } +} + +static void parse_string_as_id(gram_lex_ctx *ctx, GRAM_STYPE *sx, GRAM_LTYPE *lx) { + int x = maybe_parse_string_as_id(ctx, sx, lx); + assert(x); +} + +static void parse_string_as_id_opt(gram_lex_ctx *ctx, GRAM_STYPE *sx, GRAM_LTYPE *lx) { + GRAM_STYPE s[2]; + GRAM_LTYPE l[2]; + gram_get_last_loc(ctx, &l[0]); + int x = maybe_parse_string_as_id(ctx, &s[1], &l[1]); + if (x) { + YYLLOC_DEFAULT(*lx, l, 1); + sx->string_as_id_opt = s[1].string_as_id; + } else { + YYLLOC_DEFAULT(*lx, l, 0); + sx->string_as_id_opt = NULL; + } +} + +static int maybe_parse_id(gram_lex_ctx *ctx, GRAM_STYPE *sx, GRAM_LTYPE *lx) { + GRAM_STYPE s[2]; + GRAM_LTYPE l[2]; + gram_get_last_loc(ctx, &l[0]); + int t = gram_lex_wrap(ctx, &s[1], &l[1]); + if (t == ID) { + YYLLOC_DEFAULT(*lx, l, 1); + sx->id = symbol_from_uniqstr(s[1].ID, l[1]); + return 1; + } else { + gram_unlex_wrap(ctx, t, &s[1], &l[1]); + return 0; + } +} + +static void parse_id(gram_lex_ctx *ctx, GRAM_STYPE *sx, GRAM_LTYPE *lx) { + int x = maybe_parse_id(ctx, sx, lx); + assert(x); +} + +static void parse_token_decl(gram_lex_ctx *ctx, GRAM_STYPE *sx, GRAM_LTYPE *lx) { + GRAM_STYPE s[4]; + GRAM_LTYPE l[4]; + parse_id(ctx, &s[1], &l[1]); + parse_int_opt(ctx, &s[2], &l[2]); + parse_string_as_id_opt(ctx, &s[3], &l[3]); + YYLLOC_DEFAULT(*lx, l, 3); + sx->token_decl = s[1].id; + symbol_class_set(s[1].id, current_class, l[1], true); + if (0 <= s[2].int_opt) + symbol_user_token_number_set(s[1].id, s[2].int_opt, l[2]); + if (s[3].string_as_id_opt) + symbol_make_alias(s[1].id, s[3].string_as_id_opt, l[3]); +} + +static int maybe_parse_token_decl_1(gram_lex_ctx *ctx, GRAM_STYPE *sx, GRAM_LTYPE *lx) { + GRAM_STYPE s[3]; + GRAM_LTYPE l[3]; + int t = gram_lex_wrap(ctx, &s[1], &l[1]); + gram_unlex_wrap(ctx, t, &s[1], &l[1]); + if (t != ID) { + return 0; + } + parse_token_decl(ctx, &s[1], &l[1]); + YYLLOC_DEFAULT(*lx, l, 1); + sx->token_decl_1 = symbol_list_sym_new(s[1].token_decl, l[1]); + while (1) { + int t = gram_lex_wrap(ctx, &s[1], &l[1]); + gram_unlex_wrap(ctx, t, &s[1], &l[1]); + if (t != ID) { + return 1; + } + s[1] = *sx; + l[1] = *lx; + parse_token_decl(ctx, &s[2], &l[2]); + YYLLOC_DEFAULT(*lx, l, 2); + sx->token_decl_1 = symbol_list_append(s[1].token_decl_1, symbol_list_sym_new(s[2].token_decl, l[2])); + } +} + +static void parse_token_decl_1(gram_lex_ctx *ctx, GRAM_STYPE *sx, GRAM_LTYPE *lx) { + int x = maybe_parse_token_decl_1(ctx, sx, lx); + assert(x); +} + +static void parse_token_decls(gram_lex_ctx *ctx, GRAM_STYPE *sx, GRAM_LTYPE *lx) { + GRAM_STYPE s[4]; + GRAM_LTYPE l[4]; + int begin_with_tokens = maybe_parse_token_decl_1(ctx, &s[1], &l[1]); + if (begin_with_tokens) { + YYLLOC_DEFAULT(*lx, l, 1); + sx->token_decls = s[1].token_decl_1; + } else { + int t = gram_lex_wrap(ctx, &s[1], &l[1]); + assert(t == TAG); + parse_token_decl_1(ctx, &s[2], &l[2]); + YYLLOC_DEFAULT(*lx, l, 2); + sx->token_decls = symbol_list_type_set(s[2].token_decl_1, s[1].TAG, l[1]); + } + while (1) { + s[1] = *sx; + l[1] = *lx; + int t = gram_lex_wrap(ctx, &s[2], &l[2]); + if (t != TAG) { + gram_unlex_wrap(ctx, t, &s[2], &l[2]); + return; + } + parse_token_decl_1(ctx, &s[3], &l[3]); + YYLLOC_DEFAULT(*lx, l, 3); + sx->token_decls = symbol_list_append(s[1].token_decls, symbol_list_type_set(s[3].token_decl_1, s[2].TAG, l[2])); + } +} + +static int maybe_parse_symbol(gram_lex_ctx *ctx, GRAM_STYPE *sx, GRAM_LTYPE *lx) { + GRAM_STYPE s[2]; + GRAM_LTYPE l[2]; + int x = maybe_parse_string_as_id(ctx, &s[1], &l[1]); + if (x) { + YYLLOC_DEFAULT(*lx, l, 1); + sx->symbol = s[1].string_as_id; + return 1; + } + x = maybe_parse_id(ctx, &s[1], &l[1]); + if (x) { + YYLLOC_DEFAULT(*lx, l, 1); + sx->symbol = s[1].id; + return 1; + } + return 0; +} + +static void parse_symbol(gram_lex_ctx *ctx, GRAM_STYPE *sx, GRAM_LTYPE *lx) { + int x = maybe_parse_symbol(ctx, sx, lx); + assert(x); +} + +static int maybe_parse_symbol_decl_1(gram_lex_ctx *ctx, GRAM_STYPE *sx, GRAM_LTYPE *lx) { + GRAM_STYPE s[3]; + GRAM_LTYPE l[3]; + int x = maybe_parse_symbol(ctx, &s[1], &l[1]); + if (!x) { + return 0; + } + YYLLOC_DEFAULT(*lx, l, 1); + sx->symbol_decl_1 = symbol_list_sym_new(s[1].symbol, l[1]); + while (1) { + s[1] = *sx; + l[1] = *lx; + x = maybe_parse_symbol(ctx, &s[2], &l[2]); + if (!x) { + return 1; + } + YYLLOC_DEFAULT(*lx, l, 2); + sx->symbol_decl_1 = symbol_list_append(s[1].symbol_decl_1, symbol_list_sym_new(s[2].symbol, l[2])); + } +} + +static void parse_symbol_decl_1(gram_lex_ctx *ctx, GRAM_STYPE *sx, GRAM_LTYPE *lx) { + int x = maybe_parse_symbol_decl_1(ctx, sx, lx); + assert(x); +} + +static void parse_symbol_decls(gram_lex_ctx *ctx, GRAM_STYPE *sx, GRAM_LTYPE *lx) { + GRAM_STYPE s[4]; + GRAM_LTYPE l[4]; + int begin_with_tokens = maybe_parse_symbol_decl_1(ctx, &s[1], &l[1]); + if (begin_with_tokens) { + YYLLOC_DEFAULT(*lx, l, 1); + sx->symbol_decls = s[1].symbol_decl_1; + } else { + int t = gram_lex_wrap(ctx, &s[1], &l[1]); + assert(t == TAG); + parse_symbol_decl_1(ctx, &s[2], &l[2]); + YYLLOC_DEFAULT(*lx, l, 2); + sx->symbol_decls = symbol_list_type_set(s[2].symbol_decl_1, s[1].TAG, l[1]); + } + while (1) { + s[1] = *sx; + l[1] = *lx; + int t = gram_lex_wrap(ctx, &s[2], &l[2]); + if (t != TAG) { + gram_unlex_wrap(ctx, t, &s[2], &l[2]); + return; + } + parse_symbol_decl_1(ctx, &s[3], &l[3]); + YYLLOC_DEFAULT(*lx, l, 3); + sx->symbol_decls = symbol_list_append(s[1].symbol_decls, symbol_list_type_set(s[3].symbol_decl_1, s[2].TAG, l[2])); + } +} + +static int maybe_parse_declaration(gram_lex_ctx *ctx, int prologue) { + GRAM_STYPE s[4]; + GRAM_LTYPE l[4]; + int t[4]; + t[1] = gram_lex_wrap(ctx, &s[1], &l[1]); + if (prologue) { + switch (t[1]) { + /* Prologue declarations */ + case PERCENT_DEFINE: + t[2] = gram_lex_wrap(ctx, &s[2], &l[2]); + assert(t[2] == ID); + parse_value(ctx, &s[3], &l[3]); + YYLLOC_DEFAULT(l[0], l, 3); + muscle_percent_define_insert(s[2].ID, l[0], s[3].value.kind, s[3].value.chars, + MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE); + return 1; + case PERCENT_DEFINES: + defines_flag = true; + return 1; + case PERCENT_EXPECT: + t[2] = gram_lex_wrap(ctx, &s[2], &l[2]); + assert(t[2] == INT); + expected_sr_conflicts = s[2].INT; + return 1; + case PERCENT_INITIAL_ACTION: + t[2] = gram_lex_wrap(ctx, &s[2], &l[2]); + assert(t[2] == BRACED_CODE); + muscle_code_grow("initial_action", translate_code(s[2].BRACED_CODE, l[2], false), l[2]); + code_scanner_last_string_free(); + return 1; + case PERCENT_VERBOSE: + report_flag |= report_states; + return 1; + case SEMICOLON: + return 1; + } + } + + switch (t[1]) { + /* Grammar declarations */ + case PERCENT_CODE: + t[2] = gram_lex_wrap(ctx, &s[2], &l[2]); + if (t[2] == ID) { + t[3] = gram_lex_wrap(ctx, &s[3], &l[3]); + assert(t[3] == BRACED_CODE); + muscle_percent_code_grow(s[2].ID, l[2], translate_code_braceless(s[3].BRACED_CODE, l[3]), l[3]); + code_scanner_last_string_free(); + } else { + assert(t[2] == BRACED_CODE); + muscle_code_grow("percent_code()", translate_code_braceless(s[2].BRACED_CODE, l[2]), l[2]); + code_scanner_last_string_free(); + } + return 1; + + /* Symbol declarations */ + case PERCENT_TOKEN: + current_class = token_sym; + parse_token_decls(ctx, &s[2], &l[2]); + current_class = unknown_sym; + symbol_list_free(s[2].token_decls); + return 1; + case PERCENT_TYPE: + parse_symbol_decls(ctx, &s[2], &l[2]); + symbol_list_free(s[2].symbol_decls); + return 1; + case PERCENT_PERCENT: + return 2; + default: + gram_unlex_wrap(ctx, t[1], &s[1], &l[1]); + return 0; + } +} + +static void parse_prologue_declarations(gram_lex_ctx *ctx) { + while (1) { + int x = maybe_parse_declaration(ctx, 1); + assert(x); + if (x == 2) { + return; + } + } +} + +static void parse_id_colon(gram_lex_ctx *ctx, GRAM_STYPE *sx, GRAM_LTYPE *lx) { + GRAM_STYPE s[2]; + GRAM_LTYPE l[2]; + int t = gram_lex_wrap(ctx, &s[1], &l[1]); + assert(t == ID_COLON); + YYLLOC_DEFAULT(*lx, l, 1); + sx->id_colon = symbol_from_uniqstr(s[1].ID_COLON, l[1]); +} + +static void parse_named_ref_opt(gram_lex_ctx *ctx, GRAM_STYPE *sx, GRAM_LTYPE *lx) { + GRAM_STYPE s[2]; + GRAM_LTYPE l[2]; + gram_get_last_loc(ctx, &l[0]); + int t = gram_lex_wrap(ctx, &s[1], &l[1]); + if (t == BRACKETED_ID) { + YYLLOC_DEFAULT(*lx, l, 1); + sx->named_ref_opt = named_ref_new(s[1].BRACKETED_ID, l[1]); + } else { + gram_unlex_wrap(ctx, t, &s[1], &l[1]); + YYLLOC_DEFAULT(*lx, l, 0); + sx->named_ref_opt = NULL; + } +} + +static void parse_rhs(gram_lex_ctx *ctx, GRAM_STYPE *sx, GRAM_LTYPE *lx) { + GRAM_STYPE s[5]; + GRAM_LTYPE l[5]; + gram_get_last_loc(ctx, &l[0]); + YYLLOC_DEFAULT(*lx, l, 0); + grammar_current_rule_begin(current_lhs_symbol, current_lhs_loc, current_lhs_named_ref); + while (1) { + s[1] = *sx; + l[1] = *lx; + int x = maybe_parse_symbol(ctx, &s[2], &l[2]); + if (x) { + parse_named_ref_opt(ctx, &s[3], &l[3]); + YYLLOC_DEFAULT(*lx, l, 3); + grammar_current_rule_symbol_append(s[2].symbol, l[2], s[3].named_ref_opt); + } else { + int t = gram_lex_wrap(ctx, &s[2], &l[2]); + switch (t) { + case BRACED_CODE: + /* Probably good */ + s[3] = s[2]; + l[3] = l[2]; + s[2].tag_opt = NULL; + l[2] = l[1]; + parse_named_ref_opt(ctx, &s[4], &l[4]); + YYLLOC_DEFAULT(*lx, l, 4); + grammar_current_rule_action_append(s[3].BRACED_CODE, l[3], s[4].named_ref_opt, s[2].tag_opt); + break; + case PERCENT_EMPTY: + YYLLOC_DEFAULT(*lx, l, 2); + grammar_current_rule_empty_set(l[2]); + break; + default: + gram_unlex_wrap(ctx, t, &s[2], &l[2]); + return; + } + } + } +} + +static void parse_rhses_1(gram_lex_ctx *ctx, GRAM_STYPE *sx, GRAM_LTYPE *lx) { + GRAM_STYPE s[4]; + GRAM_LTYPE l[4]; + parse_rhs(ctx, &s[1], &l[1]); + YYLLOC_DEFAULT(*lx, l, 1); + grammar_current_rule_end(l[1]); + while (1) { + s[1] = *sx; + l[1] = *lx; + int t = gram_lex_wrap(ctx, &s[2], &l[2]); + switch (t) { + case PIPE: + parse_rhs(ctx, &s[3], &l[3]); + YYLLOC_DEFAULT(*lx, l, 3); + grammar_current_rule_end(l[3]); + break; + case SEMICOLON: + YYLLOC_DEFAULT(*lx, l, 2); + break; + default: + gram_unlex_wrap(ctx, t, &s[2], &l[2]); + return; + } + } +} + +static void parse_rules(gram_lex_ctx *ctx) { + GRAM_STYPE s[6]; + GRAM_LTYPE l[6]; + parse_id_colon(ctx, &s[1], &l[1]); + parse_named_ref_opt(ctx, &s[2], &l[2]); + gram_get_last_loc(ctx, &l[3]); + current_lhs(s[1].id_colon, l[1], s[2].named_ref_opt); + int t = gram_lex_wrap(ctx, &s[4], &l[4]); + assert(t == COLON); + parse_rhses_1(ctx, &s[5], &l[5]); + current_lhs(0, l[1], 0); +} + +static void parse_grammar(gram_lex_ctx *ctx) { + while (1) { + int x = maybe_parse_declaration(ctx, 0); + if (x == 1) { + int t = gram_lex_wrap(ctx, NULL, NULL); + assert(t == SEMICOLON); + } if (x == 2) { + return; + } else if (x == 0) { + parse_rules(ctx); + } + } +} + +static void parse_epilogue(gram_lex_ctx *ctx) { + GRAM_STYPE s; + GRAM_LTYPE l; + int t = gram_lex_wrap(ctx, &s, &l); + assert(t == EPILOGUE); + muscle_code_grow("epilogue", translate_code(s.EPILOGUE, l, true), l); + code_scanner_last_string_free(); +} + +int gram_parse(void) { + gram_lex_ctx ctx = {}; + boundary_set(&ctx.l.start, current_file, 1, 1, 1); + boundary_set(&ctx.l.end, current_file, 1, 1, 1); + parse_prologue_declarations(&ctx); + parse_grammar(&ctx); + parse_epilogue(&ctx); + assert(gram_lex_wrap(&ctx, NULL, NULL) == 0); + return 0; +} + +// Epilogue + +/* Return the location of the left-hand side of a rule whose + right-hand side is RHS[1] ... RHS[N]. Ignore empty nonterminals in + the right-hand side, and return an empty location equal to the end + boundary of RHS[0] if the right-hand side is empty. */ + +static YYLTYPE +lloc_default (YYLTYPE const *rhs, int n) +{ + YYLTYPE loc; + + /* SGI MIPSpro 7.4.1m miscompiles "loc.start = loc.end = rhs[n].end;". + The bug is fixed in 7.4.2m, but play it safe for now. */ + loc.start = rhs[n].end; + loc.end = rhs[n].end; + + /* Ignore empty nonterminals the start of the right-hand side. + Do not bother to ignore them at the end of the right-hand side, + since empty nonterminals have the same end as their predecessors. */ + for (int i = 1; i <= n; i++) + if (! equal_boundaries (rhs[i].start, rhs[i].end)) + { + loc.start = rhs[i].start; + break; + } + + return loc; +} + +static +char *strip_braces (char *code) +{ + code[strlen (code) - 1] = 0; + return code + 1; +} + +static +char const * +translate_code (char *code, location loc, bool plain) +{ + code_props plain_code; + if (plain) + code_props_plain_init (&plain_code, code, loc); + else + code_props_symbol_action_init (&plain_code, code, loc); + code_props_translate_code (&plain_code); + gram_scanner_last_string_free (); + return plain_code.code; +} + +static +char const * +translate_code_braceless (char *code, location loc) +{ + return translate_code (strip_braces (code), loc, true); +} + +static void +add_param (param_type type, char *decl, location loc) +{ + static char const alphanum[26 + 26 + 1 + 10 + 1] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "_" + "0123456789"; + + char const *name_start = NULL; + { + char *p; + /* Stop on last actual character. */ + for (p = decl; p[1]; p++) + if ((p == decl + || ! memchr (alphanum, p[-1], sizeof alphanum - 1)) + && memchr (alphanum, p[0], sizeof alphanum - 10 - 1)) + name_start = p; + + /* Strip the surrounding '{' and '}', and any blanks just inside + the braces. */ + --p; + while (c_isspace ((unsigned char) *p)) + --p; + p[1] = '\0'; + ++decl; + while (c_isspace ((unsigned char) *decl)) + ++decl; + } + + if (! name_start) + complain (&loc, complaint, _("missing identifier in parameter declaration")); + else + { + char *name = xmemdup0 (name_start, strspn (name_start, alphanum)); + if (type & param_lex) + muscle_pair_list_grow ("lex_param", decl, name); + if (type & param_parse) + muscle_pair_list_grow ("parse_param", decl, name); + free (name); + } + + gram_scanner_last_string_free (); +} + + +static void +handle_error_verbose (location const *loc, char const *directive) +{ + bison_directive (loc, directive); + muscle_percent_define_insert (directive, *loc, muscle_keyword, "", + MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE); +} + + +static void +handle_file_prefix (location const *loc, + location const *dir_loc, + char const *directive, char const *value) +{ + bison_directive (loc, directive); + bool warned = false; + + if (location_empty (spec_file_prefix_loc)) + { + spec_file_prefix_loc = *loc; + spec_file_prefix = value; + } + else + { + duplicate_directive (directive, spec_file_prefix_loc, *loc); + warned = true; + } + + if (!warned + && STRNEQ (directive, "%file-prefix")) + deprecated_directive (dir_loc, directive, "%file-prefix"); +} + + +static void +handle_name_prefix (location const *loc, + char const *directive, char const *value) +{ + bison_directive (loc, directive); + + char buf1[1024]; + size_t len1 = sizeof (buf1); + char *old = asnprintf (buf1, &len1, "%s\"%s\"", directive, value); + if (!old) + xalloc_die (); + + if (location_empty (spec_name_prefix_loc)) + { + spec_name_prefix = value; + spec_name_prefix_loc = *loc; + + char buf2[1024]; + size_t len2 = sizeof (buf2); + char *new = asnprintf (buf2, &len2, "%%define api.prefix {%s}", value); + if (!new) + xalloc_die (); + deprecated_directive (loc, old, new); + if (new != buf2) + free (new); + } + else + duplicate_directive (old, spec_file_prefix_loc, *loc); + + if (old != buf1) + free (old); +} + + +static void +handle_pure_parser (location const *loc, char const *directive) +{ + bison_directive (loc, directive); + deprecated_directive (loc, directive, "%define api.pure"); + muscle_percent_define_insert ("api.pure", *loc, muscle_keyword, "", + MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE); +} + + +static void +handle_require (location const *loc, char const *version) +{ + /* Changes of behavior are only on minor version changes, so "3.0.5" + is the same as "3.0". */ + errno = 0; + char* cp = NULL; + unsigned long major = strtoul (version, &cp, 10); + if (errno || *cp != '.') + { + complain (loc, complaint, _("invalid version requirement: %s"), + version); + return; + } + ++cp; + unsigned long minor = strtoul (cp, NULL, 10); + if (errno) + { + complain (loc, complaint, _("invalid version requirement: %s"), + version); + return; + } + required_version = major * 100 + minor; + /* Pretend to be at least 3.4, to check features published in 3.4 + while developping it. */ + const char* api_version = "3.4"; + const char* package_version = + strverscmp (api_version, PACKAGE_VERSION) > 0 + ? api_version : PACKAGE_VERSION; + if (strverscmp (version, package_version) > 0) + { + complain (loc, complaint, _("require bison %s, but have %s"), + version, package_version); + exit (EX_MISMATCH); + } +} + +static void +handle_skeleton (location const *loc, char const *skel) +{ + char const *skeleton_user = skel; + if (strchr (skeleton_user, '/')) + { + size_t dir_length = strlen (current_file); + while (dir_length && current_file[dir_length - 1] != '/') + --dir_length; + while (dir_length && current_file[dir_length - 1] == '/') + --dir_length; + char *skeleton_build = + xmalloc (dir_length + 1 + strlen (skeleton_user) + 1); + if (dir_length > 0) + { + memcpy (skeleton_build, current_file, dir_length); + skeleton_build[dir_length++] = '/'; + } + strcpy (skeleton_build + dir_length, skeleton_user); + skeleton_user = uniqstr_new (skeleton_build); + free (skeleton_build); + } + skeleton_arg (skeleton_user, grammar_prio, *loc); +} + + +static void +handle_yacc (location const *loc, char const *directive) +{ + bison_directive (loc, directive); + bool warned = false; + + if (location_empty (yacc_loc)) + yacc_loc = *loc; + else + { + duplicate_directive (directive, yacc_loc, *loc); + warned = true; + } + + if (!warned + && STRNEQ (directive, "%fixed-output-files") + && STRNEQ (directive, "%yacc")) + deprecated_directive (loc, directive, "%fixed-output-files"); +} + + +static void +gram_error (location const *loc, char const *msg) +{ + complain (loc, complaint, "%s", msg); +} + +static char const * +char_name (char c) +{ + if (c == '\'') + return "'\\''"; + else + { + char buf[4]; + buf[0] = '\''; buf[1] = c; buf[2] = '\''; buf[3] = '\0'; + return quotearg_style (escape_quoting_style, buf); + } +} + +static +void +current_lhs (symbol *sym, location loc, named_ref *ref) +{ + current_lhs_symbol = sym; + current_lhs_loc = loc; + if (sym) + symbol_location_as_lhs_set (sym, loc); + /* In order to simplify memory management, named references for lhs + are always assigned by deep copy into the current symbol_list + node. This is because a single named-ref in the grammar may + result in several uses when the user factors lhs between several + rules using "|". Therefore free the parser's original copy. */ + free (current_lhs_named_ref); + current_lhs_named_ref = ref; +} + +static void tron (FILE *yyo) +{ + begin_use_class ("value", yyo); +} + +static void troff (FILE *yyo) +{ + end_use_class ("value", yyo); +} diff --git a/sysa/bison-3.4.1/files/parse-gram.h b/sysa/bison-3.4.1/files/parse-gram.h new file mode 100644 index 0000000..7a6e749 --- /dev/null +++ b/sysa/bison-3.4.1/files/parse-gram.h @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +/* + * This file is based on parse-gram.y from GNU Bison 3.4.1. It is the + * header for an implementation of a subset of the grammar described + * by parse-gram.y, just enough to provide a bootstrapping path for + * Bison. + * + * Copyright (c) 2020, Giovanni Mascellani + * + * The copyright notice of the original file follows. This file is + * distributed under the same license and with the same conditions. + */ + +/* Bison Grammar Parser -*- C -*- + + Copyright (C) 2002-2015, 2018-2019 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 . */ + +#ifndef PARSE_GRAM_H +#define PARSE_GRAM_H + +/* %code requires */ + + #include "symlist.h" + #include "symtab.h" + + typedef enum + { + param_none = 0, + param_lex = 1 << 0, + param_parse = 1 << 1, + param_both = param_lex | param_parse + } param_type; + + #include "muscle-tab.h" + typedef struct + { + char const *chars; + muscle_kind kind; + } value_type; + + +enum gram_tokentype { + GRAM_EOF = 0, + ID = 300, + STRING, + BRACED_CODE, + INT, + PERCENT_DEFINE, + PERCENT_DEFINES, + PERCENT_VERBOSE, + SEMICOLON, + PERCENT_TOKEN, + PERCENT_TYPE, + PERCENT_EMPTY, + COLON, + PERCENT_EXPECT, + PERCENT_PERCENT, + PERCENT_INITIAL_ACTION, + BRACKETED_ID, + PIPE, + EPILOGUE, + TAG, + PERCENT_CODE, + ID_COLON, + + PERCENT_NONASSOC, + PERCENT_FLAG, + PERCENT_DEFAULT_PREC, + PERCENT_DESTRUCTOR, + PERCENT_DPREC, + PERCENT_EXPECT_RR, + EQUAL, + TAG_ANY, + CHAR, + BRACED_PREDICATE, + PERCENT_START, + PERCENT_UNION, + PERCENT_ERROR_VERBOSE, + PERCENT_NAME_PREFIX, + PERCENT_PURE_PARSER, + PERCENT_RIGHT, + PERCENT_PREC, + PERCENT_FILE_PREFIX, + PERCENT_YACC, + PERCENT_GLR_PARSER, + PERCENT_LANGUAGE, + PERCENT_LEFT, + PERCENT_PARAM, + PERCENT_MERGE, + PERCENT_NO_DEFAULT_PREC, + PERCENT_NO_LINES, + PERCENT_NONDETERMINISTIC_PARSER, + PERCENT_NTERM, + PERCENT_OUTPUT, + PERCENT_PRECEDENCE, + PRECENT_PRINTER, + PERCENT_REQUIRE, + PERCENT_SKELETON, + PERCENT_TOKEN_TABLE, + TAG_NONE, + PROLOGUE, + PERCENT_PRINTER, +}; + +union GRAM_STYPE { + value_type value; + uniqstr ID; + char *STRING; + symbol *symbol; + named_ref *named_ref_opt; + uniqstr tag_opt; + char *BRACED_CODE; + char *EPILOGUE; + symbol *id_colon; + uniqstr ID_COLON; + int int_opt; + int INT; + symbol *string_as_id; + symbol *string_as_id_opt; + symbol *token_decl; + symbol_list *token_decl_1; + symbol_list *token_decls; + symbol_list *symbol_decls; + symbol_list *symbol_decl_1; + uniqstr BRACKETED_ID; + symbol *id; + uniqstr TAG; + + uniqstr PERCENT_FLAG; + uniqstr PERCENT_FILE_PREFIX; + uniqstr PERCENT_NAME_PREFIX; + uniqstr PERCENT_YACC; + param_type PERCENT_PARAM; + uniqstr PERCENT_PURE_PARSER; + uniqstr PERCENT_ERROR_VERBOSE; + unsigned char CHAR; + char *BRACED_PREDICATE; + char *PROLOGUE; +}; +typedef union GRAM_STYPE GRAM_STYPE; + +int gram_parse (void); + +#endif diff --git a/sysa/bison-3.4.1/files/parse-gram.y b/sysa/bison-3.4.1/files/parse-gram.y new file mode 100644 index 0000000..1dfe44d --- /dev/null +++ b/sysa/bison-3.4.1/files/parse-gram.y @@ -0,0 +1,1070 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +/* Bison Grammar Parser -*- C -*- + + Copyright (C) 2002-2015, 2018-2019 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 . */ + +/* + * This file is identical to the file parse-gram.y distributed with + * GNU Bison 3.4.1, except that all %printer and %destructor + * directives were removed (and this comment was added). It thus + * accepts the same grammar and produce the same actions, although it + * won't clean up things properly and it will have partially impaired + * printing. + * + * It was produced by Giovanni Mascellani on 26th + * March 2020. Since the modifications are so trivial, no copyright is + * claimed. + */ + +%code requires +{ + #include "symlist.h" + #include "symtab.h" +} + +%code top +{ + /* On column 0 to please syntax-check. */ +#include +} + +%code +{ + #include "system.h" + #include + + #include "c-ctype.h" + #include "complain.h" + #include "conflicts.h" + #include "files.h" + #include "getargs.h" + #include "gram.h" + #include "named-ref.h" + #include "quotearg.h" + #include "reader.h" + #include "scan-code.h" + #include "scan-gram.h" + #include "vasnprintf.h" + #include "xmemdup0.h" + + static int current_prec = 0; + static location current_lhs_loc; + static named_ref *current_lhs_named_ref; + static symbol *current_lhs_symbol; + static symbol_class current_class = unknown_sym; + + /** Set the new current left-hand side symbol, possibly common + * to several right-hand side parts of rule. + */ + static void current_lhs (symbol *sym, location loc, named_ref *ref); + + #define YYLLOC_DEFAULT(Current, Rhs, N) \ + (Current) = lloc_default (Rhs, N) + static YYLTYPE lloc_default (YYLTYPE const *, int); + + #define YY_LOCATION_PRINT(File, Loc) \ + location_print (Loc, File) + + /* Strip initial '{' and final '}' (must be first and last characters). + Return the result. */ + static char *strip_braces (char *code); + + /* Convert CODE by calling code_props_plain_init if PLAIN, otherwise + code_props_symbol_action_init. Call + 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 + string from the scanner (should be CODE). */ + static char const *translate_code_braceless (char *code, location loc); + + /* Handle a %error-verbose directive. */ + static void handle_error_verbose (location const *loc, char const *directive); + + /* Handle a %file-prefix directive. */ + static void handle_file_prefix (location const *loc, + location const *dir_loc, + char const *directive, char const *value); + + /* Handle a %name-prefix directive. */ + static void handle_name_prefix (location const *loc, + char const *directive, char const *value); + + /* Handle a %pure-parser directive. */ + static void handle_pure_parser (location const *loc, char const *directive); + + /* Handle a %require directive. */ + static void handle_require (location const *loc, char const *version); + + /* Handle a %skeleton directive. */ + static void handle_skeleton (location const *loc, char const *skel); + + /* Handle a %yacc directive. */ + static void handle_yacc (location const *loc, char const *directive); + + static void gram_error (location const *, char const *); + + /* A string that describes a char (e.g., 'a' -> "'a'"). */ + static char const *char_name (char); + + #define YYTYPE_INT16 int_fast16_t + #define YYTYPE_INT8 int_fast8_t + #define YYTYPE_UINT16 uint_fast16_t + #define YYTYPE_UINT8 uint_fast8_t + + /* Add style to semantic values in traces. */ + static void tron (FILE *yyo); + static void troff (FILE *yyo); +} + +%define api.header.include {"parse-gram.h"} +%define api.prefix {gram_} +%define api.pure full +%define api.value.type union +%define locations +%define parse.error verbose +%define parse.lac full +%define parse.trace +%defines +%expect 0 +%verbose + +%initial-action +{ + /* Bison's grammar can initial empty locations, hence a default + location is needed. */ + boundary_set (&@$.start, current_file, 1, 1, 1); + boundary_set (&@$.end, current_file, 1, 1, 1); +} + +/* Define the tokens together with their human representation. */ +%token GRAM_EOF 0 "end of file" +%token STRING "string" + +%token PERCENT_TOKEN "%token" +%token PERCENT_NTERM "%nterm" + +%token PERCENT_TYPE "%type" +%token PERCENT_DESTRUCTOR "%destructor" +%token PERCENT_PRINTER "%printer" + +%token PERCENT_LEFT "%left" +%token PERCENT_RIGHT "%right" +%token PERCENT_NONASSOC "%nonassoc" +%token PERCENT_PRECEDENCE "%precedence" + +%token PERCENT_PREC "%prec" +%token PERCENT_DPREC "%dprec" +%token PERCENT_MERGE "%merge" + +/*----------------------. +| Global Declarations. | +`----------------------*/ + +%token + PERCENT_CODE "%code" + PERCENT_DEFAULT_PREC "%default-prec" + PERCENT_DEFINE "%define" + PERCENT_DEFINES "%defines" + PERCENT_ERROR_VERBOSE "%error-verbose" + PERCENT_EXPECT "%expect" + PERCENT_EXPECT_RR "%expect-rr" + PERCENT_FLAG "%" + PERCENT_FILE_PREFIX "%file-prefix" + PERCENT_GLR_PARSER "%glr-parser" + PERCENT_INITIAL_ACTION "%initial-action" + PERCENT_LANGUAGE "%language" + PERCENT_NAME_PREFIX "%name-prefix" + PERCENT_NO_DEFAULT_PREC "%no-default-prec" + PERCENT_NO_LINES "%no-lines" + PERCENT_NONDETERMINISTIC_PARSER + "%nondeterministic-parser" + PERCENT_OUTPUT "%output" + PERCENT_PURE_PARSER "%pure-parser" + PERCENT_REQUIRE "%require" + PERCENT_SKELETON "%skeleton" + PERCENT_START "%start" + PERCENT_TOKEN_TABLE "%token-table" + PERCENT_VERBOSE "%verbose" + PERCENT_YACC "%yacc" +; + +%token BRACED_CODE "{...}" +%token BRACED_PREDICATE "%?{...}" +%token BRACKETED_ID "[identifier]" +%token CHAR "char" +%token COLON ":" +%token EPILOGUE "epilogue" +%token EQUAL "=" +%token ID "identifier" +%token ID_COLON "identifier:" +%token PERCENT_PERCENT "%%" +%token PIPE "|" +%token PROLOGUE "%{...%}" +%token SEMICOLON ";" +%token TAG "" +%token TAG_ANY "<*>" +%token TAG_NONE "<>" + + /* Experimental feature, don't rely on it. */ +%code pre-printer {tron (yyo);} +%code post-printer {troff (yyo);} + +%type CHAR + +%type "{...}" "%?{...}" "%{...%}" EPILOGUE STRING + +%type + BRACKETED_ID ID ID_COLON + PERCENT_ERROR_VERBOSE PERCENT_FILE_PREFIX PERCENT_FLAG PERCENT_NAME_PREFIX + PERCENT_PURE_PARSER PERCENT_YACC + TAG tag tag.opt variable + +%token INT "integer" + +%type id id_colon string_as_id symbol token_decl token_decl_for_prec + +%type precedence_declarator + +%type named_ref.opt + +/*---------. +| %param. | +`---------*/ +%code requires +{ + typedef enum + { + param_none = 0, + param_lex = 1 << 0, + param_parse = 1 << 1, + param_both = param_lex | param_parse + } param_type; +}; +%code +{ + /** Add a lex-param and/or a parse-param. + * + * \param type where to push this formal argument. + * \param decl the formal argument. Destroyed. + * \param loc the location in the source. + */ + static void add_param (param_type type, char *decl, location loc); + static param_type current_param = param_none; +}; +%token PERCENT_PARAM "%param"; + + + /*==========\ + | Grammar. | + \==========*/ +%% + +input: + prologue_declarations "%%" grammar epilogue.opt +; + + + /*------------------------------------. + | Declarations: before the first %%. | + `------------------------------------*/ + +prologue_declarations: + %empty +| prologue_declarations prologue_declaration +; + +prologue_declaration: + grammar_declaration +| "%{...%}" + { + muscle_code_grow (union_seen ? "post_prologue" : "pre_prologue", + translate_code ($1, @1, true), @1); + code_scanner_last_string_free (); + } +| "%" + { + muscle_percent_define_ensure ($1, @1, true); + } +| "%define" variable value + { + muscle_percent_define_insert ($2, @$, $3.kind, $3.chars, + MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE); + } +| "%defines" { defines_flag = true; } +| "%defines" STRING + { + defines_flag = true; + spec_header_file = xstrdup ($2); + } +| "%error-verbose" { handle_error_verbose (&@$, $1); } +| "%expect" INT { expected_sr_conflicts = $2; } +| "%expect-rr" INT { expected_rr_conflicts = $2; } +| "%file-prefix" STRING { handle_file_prefix (&@$, &@1, $1, $2); } +| "%glr-parser" + { + nondeterministic_parser = true; + glr_parser = true; + } +| "%initial-action" "{...}" + { + muscle_code_grow ("initial_action", translate_code ($2, @2, false), @2); + code_scanner_last_string_free (); + } +| "%language" STRING { language_argmatch ($2, grammar_prio, @1); } +| "%name-prefix" STRING { handle_name_prefix (&@$, $1, $2); } +| "%no-lines" { no_lines_flag = true; } +| "%nondeterministic-parser" { nondeterministic_parser = true; } +| "%output" STRING { spec_outfile = $2; } +| "%param" { current_param = $1; } params { current_param = param_none; } +| "%pure-parser" { handle_pure_parser (&@$, $1); } +| "%require" STRING { handle_require (&@2, $2); } +| "%skeleton" STRING { handle_skeleton (&@2, $2); } +| "%token-table" { token_table_flag = true; } +| "%verbose" { report_flag |= report_states; } +| "%yacc" { handle_yacc (&@$, $1); } +| error ";" { current_class = unknown_sym; yyerrok; } +| /*FIXME: Err? What is this horror doing here? */ ";" +; + +params: + params "{...}" { add_param (current_param, $2, @2); } +| "{...}" { add_param (current_param, $1, @1); } +; + + +/*----------------------. +| grammar_declaration. | +`----------------------*/ + +grammar_declaration: + symbol_declaration +| "%start" symbol + { + grammar_start_symbol_set ($2, @2); + } +| code_props_type "{...}" generic_symlist + { + code_props code; + code_props_symbol_action_init (&code, $2, @2); + code_props_translate_code (&code); + { + for (symbol_list *list = $3; list; list = list->next) + symbol_list_code_props_set (list, $1, &code); + symbol_list_free ($3); + } + } +| "%default-prec" + { + default_prec = true; + } +| "%no-default-prec" + { + default_prec = false; + } +| "%code" "{...}" + { + /* Do not invoke muscle_percent_code_grow here since it invokes + muscle_user_name_list_grow. */ + muscle_code_grow ("percent_code()", + translate_code_braceless ($2, @2), @2); + code_scanner_last_string_free (); + } +| "%code" ID "{...}" + { + muscle_percent_code_grow ($2, @2, translate_code_braceless ($3, @3), @3); + code_scanner_last_string_free (); + } +; + +%type code_props_type; +code_props_type: + "%destructor" { $$ = destructor; } +| "%printer" { $$ = printer; } +; + +/*---------. +| %union. | +`---------*/ + +%token PERCENT_UNION "%union"; + +union_name: + %empty {} +| ID { muscle_percent_define_insert ("api.value.union.name", + @1, muscle_keyword, $1, + MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE); } +; + +grammar_declaration: + "%union" union_name "{...}" + { + union_seen = true; + muscle_code_grow ("union_members", translate_code_braceless ($3, @3), @3); + code_scanner_last_string_free (); + } +; + + +%type nterm_decls symbol_decls symbol_decl.1 + token_decls token_decls_for_prec + token_decl.1 token_decl_for_prec.1; +symbol_declaration: + "%nterm" { current_class = nterm_sym; } nterm_decls[syms] + { + current_class = unknown_sym; + symbol_list_free ($syms); + } +| "%token" { current_class = token_sym; } token_decls[syms] + { + current_class = unknown_sym; + symbol_list_free ($syms); + } +| "%type" symbol_decls[syms] + { + symbol_list_free ($syms); + } +| precedence_declarator token_decls_for_prec[syms] + { + ++current_prec; + for (symbol_list *list = $syms; list; list = list->next) + symbol_precedence_set (list->content.sym, current_prec, $1, @1); + symbol_list_free ($syms); + } +; + +precedence_declarator: + "%left" { $$ = left_assoc; } +| "%right" { $$ = right_assoc; } +| "%nonassoc" { $$ = non_assoc; } +| "%precedence" { $$ = precedence_assoc; } +; + +tag.opt: + %empty { $$ = NULL; } +| TAG { $$ = $1; } +; + +%type generic_symlist generic_symlist_item; +generic_symlist: + generic_symlist_item +| generic_symlist generic_symlist_item { $$ = symbol_list_append ($1, $2); } +; + +generic_symlist_item: + symbol { $$ = symbol_list_sym_new ($1, @1); } +| tag { $$ = symbol_list_type_new ($1, @1); } +; + +tag: + TAG +| "<*>" { $$ = uniqstr_new ("*"); } +| "<>" { $$ = uniqstr_new (""); } +; + +/*-----------------------. +| nterm_decls (%nterm). | +`-----------------------*/ + +// A non empty list of possibly tagged symbols for %nterm. +// +// Can easily be defined like symbol_decls but restricted to ID, but +// using token_decls allows to reudce the number of rules, and also to +// make nicer error messages on "%nterm 'a'" or '%nterm FOO "foo"'. +nterm_decls: + token_decls +; + +/*-----------------------------------. +| token_decls (%token, and %nterm). | +`-----------------------------------*/ + +// A non empty list of possibly tagged symbols for %token or %nterm. +token_decls: + token_decl.1[syms] + { + $$ = $syms; + } +| TAG token_decl.1[syms] + { + $$ = symbol_list_type_set ($syms, $TAG, @TAG); + } +| token_decls TAG token_decl.1[syms] + { + $$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG, @TAG)); + } +; + +// One or more symbol declarations for %token or %nterm. +token_decl.1: + token_decl { $$ = symbol_list_sym_new ($1, @1); } +| token_decl.1 token_decl { $$ = symbol_list_append ($1, symbol_list_sym_new ($2, @2)); } + +// One symbol declaration for %token or %nterm. +token_decl: + id int.opt[num] string_as_id.opt[alias] + { + $$ = $id; + symbol_class_set ($id, current_class, @id, true); + if (0 <= $num) + symbol_user_token_number_set ($id, $num, @num); + if ($alias) + symbol_make_alias ($id, $alias, @alias); + } +; + +%type int.opt; +int.opt: + %empty { $$ = -1; } +| INT +; + +/*-------------------------------------. +| token_decls_for_prec (%left, etc.). | +`-------------------------------------*/ + +// A non empty list of possibly tagged tokens for precedence declaration. +// +// Similar to %token (token_decls), but in '%left FOO 1 "foo"', it treats +// FOO and "foo" as two different symbols instead of aliasing them. +token_decls_for_prec: + token_decl_for_prec.1[syms] + { + $$ = $syms; + } +| TAG token_decl_for_prec.1[syms] + { + $$ = symbol_list_type_set ($syms, $TAG, @TAG); + } +| token_decls_for_prec TAG token_decl_for_prec.1[syms] + { + $$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG, @TAG)); + } +; + +// One or more token declarations for precedence declaration. +token_decl_for_prec.1: + token_decl_for_prec + { $$ = symbol_list_sym_new ($1, @1); } +| token_decl_for_prec.1 token_decl_for_prec + { $$ = symbol_list_append ($1, symbol_list_sym_new ($2, @2)); } + +// One token declaration for precedence declaration. +token_decl_for_prec: + id int.opt[num] + { + $$ = $id; + symbol_class_set ($id, token_sym, @id, false); + if (0 <= $num) + symbol_user_token_number_set ($id, $num, @num); + } +| string_as_id +; + + +/*-----------------------. +| symbol_decls (%type). | +`-----------------------*/ + +// A non empty list of typed symbols. +symbol_decls: + symbol_decl.1[syms] + { + $$ = $syms; + } +| TAG symbol_decl.1[syms] + { + $$ = symbol_list_type_set ($syms, $TAG, @TAG); + } +| symbol_decls TAG symbol_decl.1[syms] + { + $$ = symbol_list_append ($1, symbol_list_type_set ($syms, $TAG, @TAG)); + } +; + +// One or more token declarations. +symbol_decl.1: + symbol { $$ = symbol_list_sym_new ($1, @1); } +| symbol_decl.1 symbol { $$ = symbol_list_append ($1, symbol_list_sym_new ($2, @2)); } +; + + /*------------------------------------------. + | The grammar section: between the two %%. | + `------------------------------------------*/ + +grammar: + rules_or_grammar_declaration +| grammar rules_or_grammar_declaration +; + +/* As a Bison extension, one can use the grammar declarations in the + body of the grammar. */ +rules_or_grammar_declaration: + rules +| grammar_declaration ";" +| error ";" + { + yyerrok; + } +; + +rules: + id_colon named_ref.opt { current_lhs ($1, @1, $2); } ":" rhses.1 + { + /* Free the current lhs. */ + current_lhs (0, @1, 0); + } +; + +rhses.1: + rhs { grammar_current_rule_end (@rhs); } +| rhses.1 "|" rhs { grammar_current_rule_end (@rhs); } +| rhses.1 ";" +; + +%token PERCENT_EMPTY "%empty"; +rhs: + %empty + { grammar_current_rule_begin (current_lhs_symbol, current_lhs_loc, + current_lhs_named_ref); } +| rhs symbol named_ref.opt + { grammar_current_rule_symbol_append ($2, @2, $3); } +| rhs tag.opt "{...}"[act] named_ref.opt[name] + { grammar_current_rule_action_append ($act, @act, $name, $[tag.opt]); } +| rhs "%?{...}" + { grammar_current_rule_predicate_append ($2, @2); } +| rhs "%empty" + { grammar_current_rule_empty_set (@2); } +| rhs "%prec" symbol + { grammar_current_rule_prec_set ($3, @3); } +| rhs "%dprec" INT + { grammar_current_rule_dprec_set ($3, @3); } +| rhs "%merge" TAG + { grammar_current_rule_merge_set ($3, @3); } +| rhs "%expect" INT + { grammar_current_rule_expect_sr ($3, @3); } +| rhs "%expect-rr" INT + { grammar_current_rule_expect_rr ($3, @3); } +; + +named_ref.opt: + %empty { $$ = NULL; } +| BRACKETED_ID { $$ = named_ref_new ($1, @1); } +; + + +/*---------------------. +| variable and value. | +`---------------------*/ + +variable: + ID +; + +/* Some content or empty by default. */ +%code requires { + #include "muscle-tab.h" + typedef struct + { + char const *chars; + muscle_kind kind; + } value_type; +}; +%type value; + +value: + %empty { $$.kind = muscle_keyword; $$.chars = ""; } +| ID { $$.kind = muscle_keyword; $$.chars = $1; } +| STRING { $$.kind = muscle_string; $$.chars = $1; } +| "{...}" { $$.kind = muscle_code; $$.chars = strip_braces ($1); } +; + + +/*--------------. +| Identifiers. | +`--------------*/ + +/* Identifiers are returned as uniqstr values by the scanner. + Depending on their use, we may need to make them genuine symbols. */ + +id: + ID + { $$ = symbol_from_uniqstr ($1, @1); } +| CHAR + { + if (current_class == nterm_sym) + { + gram_error (&@1, + _("character literals cannot be nonterminals")); + YYERROR; + } + $$ = symbol_get (char_name ($1), @1); + symbol_class_set ($$, token_sym, @1, false); + symbol_user_token_number_set ($$, $1, @1); + } +; + +id_colon: + ID_COLON { $$ = symbol_from_uniqstr ($1, @1); } +; + + +symbol: + id +| string_as_id +; + +/* A string used as an ID: quote it. */ +string_as_id: + STRING + { + $$ = symbol_get (quotearg_style (c_quoting_style, $1), @1); + symbol_class_set ($$, token_sym, @1, false); + } +; + +%type string_as_id.opt; +string_as_id.opt: + %empty { $$ = NULL; } +| string_as_id +; + +epilogue.opt: + %empty +| "%%" EPILOGUE + { + muscle_code_grow ("epilogue", translate_code ($2, @2, true), @2); + code_scanner_last_string_free (); + } +; + +%% + +/* Return the location of the left-hand side of a rule whose + right-hand side is RHS[1] ... RHS[N]. Ignore empty nonterminals in + the right-hand side, and return an empty location equal to the end + boundary of RHS[0] if the right-hand side is empty. */ + +static YYLTYPE +lloc_default (YYLTYPE const *rhs, int n) +{ + YYLTYPE loc; + + /* SGI MIPSpro 7.4.1m miscompiles "loc.start = loc.end = rhs[n].end;". + The bug is fixed in 7.4.2m, but play it safe for now. */ + loc.start = rhs[n].end; + loc.end = rhs[n].end; + + /* Ignore empty nonterminals the start of the right-hand side. + Do not bother to ignore them at the end of the right-hand side, + since empty nonterminals have the same end as their predecessors. */ + for (int i = 1; i <= n; i++) + if (! equal_boundaries (rhs[i].start, rhs[i].end)) + { + loc.start = rhs[i].start; + break; + } + + return loc; +} + +static +char *strip_braces (char *code) +{ + code[strlen (code) - 1] = 0; + return code + 1; +} + +static +char const * +translate_code (char *code, location loc, bool plain) +{ + code_props plain_code; + if (plain) + code_props_plain_init (&plain_code, code, loc); + else + code_props_symbol_action_init (&plain_code, code, loc); + code_props_translate_code (&plain_code); + gram_scanner_last_string_free (); + return plain_code.code; +} + +static +char const * +translate_code_braceless (char *code, location loc) +{ + return translate_code (strip_braces (code), loc, true); +} + +static void +add_param (param_type type, char *decl, location loc) +{ + static char const alphanum[26 + 26 + 1 + 10 + 1] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "_" + "0123456789"; + + char const *name_start = NULL; + { + char *p; + /* Stop on last actual character. */ + for (p = decl; p[1]; p++) + if ((p == decl + || ! memchr (alphanum, p[-1], sizeof alphanum - 1)) + && memchr (alphanum, p[0], sizeof alphanum - 10 - 1)) + name_start = p; + + /* Strip the surrounding '{' and '}', and any blanks just inside + the braces. */ + --p; + while (c_isspace ((unsigned char) *p)) + --p; + p[1] = '\0'; + ++decl; + while (c_isspace ((unsigned char) *decl)) + ++decl; + } + + if (! name_start) + complain (&loc, complaint, _("missing identifier in parameter declaration")); + else + { + char *name = xmemdup0 (name_start, strspn (name_start, alphanum)); + if (type & param_lex) + muscle_pair_list_grow ("lex_param", decl, name); + if (type & param_parse) + muscle_pair_list_grow ("parse_param", decl, name); + free (name); + } + + gram_scanner_last_string_free (); +} + + +static void +handle_error_verbose (location const *loc, char const *directive) +{ + bison_directive (loc, directive); + muscle_percent_define_insert (directive, *loc, muscle_keyword, "", + MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE); +} + + +static void +handle_file_prefix (location const *loc, + location const *dir_loc, + char const *directive, char const *value) +{ + bison_directive (loc, directive); + bool warned = false; + + if (location_empty (spec_file_prefix_loc)) + { + spec_file_prefix_loc = *loc; + spec_file_prefix = value; + } + else + { + duplicate_directive (directive, spec_file_prefix_loc, *loc); + warned = true; + } + + if (!warned + && STRNEQ (directive, "%file-prefix")) + deprecated_directive (dir_loc, directive, "%file-prefix"); +} + + +static void +handle_name_prefix (location const *loc, + char const *directive, char const *value) +{ + bison_directive (loc, directive); + + char buf1[1024]; + size_t len1 = sizeof (buf1); + char *old = asnprintf (buf1, &len1, "%s\"%s\"", directive, value); + if (!old) + xalloc_die (); + + if (location_empty (spec_name_prefix_loc)) + { + spec_name_prefix = value; + spec_name_prefix_loc = *loc; + + char buf2[1024]; + size_t len2 = sizeof (buf2); + char *new = asnprintf (buf2, &len2, "%%define api.prefix {%s}", value); + if (!new) + xalloc_die (); + deprecated_directive (loc, old, new); + if (new != buf2) + free (new); + } + else + duplicate_directive (old, spec_file_prefix_loc, *loc); + + if (old != buf1) + free (old); +} + + +static void +handle_pure_parser (location const *loc, char const *directive) +{ + bison_directive (loc, directive); + deprecated_directive (loc, directive, "%define api.pure"); + muscle_percent_define_insert ("api.pure", *loc, muscle_keyword, "", + MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE); +} + + +static void +handle_require (location const *loc, char const *version) +{ + /* Changes of behavior are only on minor version changes, so "3.0.5" + is the same as "3.0". */ + errno = 0; + char* cp = NULL; + unsigned long major = strtoul (version, &cp, 10); + if (errno || *cp != '.') + { + complain (loc, complaint, _("invalid version requirement: %s"), + version); + return; + } + ++cp; + unsigned long minor = strtoul (cp, NULL, 10); + if (errno) + { + complain (loc, complaint, _("invalid version requirement: %s"), + version); + return; + } + required_version = major * 100 + minor; + /* Pretend to be at least 3.4, to check features published in 3.4 + while developping it. */ + const char* api_version = "3.4"; + const char* package_version = + strverscmp (api_version, PACKAGE_VERSION) > 0 + ? api_version : PACKAGE_VERSION; + if (strverscmp (version, package_version) > 0) + { + complain (loc, complaint, _("require bison %s, but have %s"), + version, package_version); + exit (EX_MISMATCH); + } +} + +static void +handle_skeleton (location const *loc, char const *skel) +{ + char const *skeleton_user = skel; + if (strchr (skeleton_user, '/')) + { + size_t dir_length = strlen (current_file); + while (dir_length && current_file[dir_length - 1] != '/') + --dir_length; + while (dir_length && current_file[dir_length - 1] == '/') + --dir_length; + char *skeleton_build = + xmalloc (dir_length + 1 + strlen (skeleton_user) + 1); + if (dir_length > 0) + { + memcpy (skeleton_build, current_file, dir_length); + skeleton_build[dir_length++] = '/'; + } + strcpy (skeleton_build + dir_length, skeleton_user); + skeleton_user = uniqstr_new (skeleton_build); + free (skeleton_build); + } + skeleton_arg (skeleton_user, grammar_prio, *loc); +} + + +static void +handle_yacc (location const *loc, char const *directive) +{ + bison_directive (loc, directive); + bool warned = false; + + if (location_empty (yacc_loc)) + yacc_loc = *loc; + else + { + duplicate_directive (directive, yacc_loc, *loc); + warned = true; + } + + if (!warned + && STRNEQ (directive, "%fixed-output-files") + && STRNEQ (directive, "%yacc")) + deprecated_directive (loc, directive, "%fixed-output-files"); +} + + +static void +gram_error (location const *loc, char const *msg) +{ + complain (loc, complaint, "%s", msg); +} + +static char const * +char_name (char c) +{ + if (c == '\'') + return "'\\''"; + else + { + char buf[4]; + buf[0] = '\''; buf[1] = c; buf[2] = '\''; buf[3] = '\0'; + return quotearg_style (escape_quoting_style, buf); + } +} + +static +void +current_lhs (symbol *sym, location loc, named_ref *ref) +{ + current_lhs_symbol = sym; + current_lhs_loc = loc; + if (sym) + symbol_location_as_lhs_set (sym, loc); + /* In order to simplify memory management, named references for lhs + are always assigned by deep copy into the current symbol_list + node. This is because a single named-ref in the grammar may + result in several uses when the user factors lhs between several + rules using "|". Therefore free the parser's original copy. */ + free (current_lhs_named_ref); + current_lhs_named_ref = ref; +} + +static void tron (FILE *yyo) +{ + begin_use_class ("value", yyo); +} + +static void troff (FILE *yyo) +{ + end_use_class ("value", yyo); +} diff --git a/sysa/bison-3.4.1/mk/lib.mk b/sysa/bison-3.4.1/mk/lib.mk new file mode 100644 index 0000000..d3749be --- /dev/null +++ b/sysa/bison-3.4.1/mk/lib.mk @@ -0,0 +1,10 @@ +# SPDX-FileCopyrightText: 2020 Giovanni Mascellani gio@debian.org +# SPDX-FileCopyrightText: 2021 Andrius Štikonas +# +# SPDX-License-Identifier: GPL-3.0-or-later + +lib.a: allocator.o areadlink.o argmatch.o asnprintf.o basename.o basename-lgpl.o binary-io.o bitrotate.o bitset.o bitsetv.o calloc.o canonicalize-lgpl.o careadlinkat.o c-ctype.o cloexec.o close.o closeout.o close-stream.o concat-filename.o c-strcasecmp.o c-strncasecmp.o dirname.o dirname-lgpl.o dup2.o dup-safer.o dup-safer-flag.o exitfail.o fatal-signal.o fd-hook.o fd-safer.o fd-safer-flag.o fopen.o fopen-safer.o fprintf.o frexp.o frexpl.o fstat.o getdtablesize.o get-errno.o gethrxtime.o getopt.o getprogname.o getrusage.o gettime.o gettimeofday.o gl_array_list.o gl_list.o gl_xlist.o hard-locale.o hash.o isnan.o isnand.o isnanf.o isnanl.o itold.o ldexpl.o localcharset.o localtime-buffer.o lstat.o main.o malloca.o malloc.o math.o mbrtowc.o mbsinit.o mbswidth.o memchr.o msvc-inval.o obstack.o obstack_printf.o open.o path-join.o perror.o pipe2-safer.o pipe-safer.o printf-args.o printf.o printf-frexp.o printf-frexpl.o printf-parse.o progname.o progreloc.o quotearg.o raise.o rawmemchr.o readlink.o realloc.o relocatable.o rename.o rmdir.o setenv.o sig-handler.o signbitd.o signbitf.o signbitl.o spawnattr_destroy.o spawnattr_init.o sprintf.o stat.o stat-time.o stat-w32.o stpcpy.o strchrnul.o strdup.o strerror.o stripslash.o strndup.o strnlen.o strverscmp.o timespec.o timevar.o unistd.o unlink.o unsetenv.o vasnprintf.o wait-process.o wctype-h.o xalloc-die.o xconcat-filename.o xmalloc.o xmemdup0.o xreadlink.o xsize.o xstrndup.o xtime.o yyerror.o error.o bitset/array.o bitset/list.o bitset/stats.o bitset/table.o bitset/vector.o fseterr.o spawn-pipe.o + $(AR) r $@ $^ + +%.o: %.c + $(CC) $(CFLAGS) -g -c -I.. -I../lib -o $@ $< diff --git a/sysa/bison-3.4.1/mk/main.mk b/sysa/bison-3.4.1/mk/main.mk new file mode 100644 index 0000000..13b5a36 --- /dev/null +++ b/sysa/bison-3.4.1/mk/main.mk @@ -0,0 +1,27 @@ +# SPDX-FileCopyrightText: 2020 Giovanni Mascellani gio@debian.org +# SPDX-FileCopyrightText: 2021 Andrius Štikonas +# +# SPDX-License-Identifier: GPL-3.0-or-later + +CC=tcc +AR="tcc -ar" + +all: bison + +bison: src.a lib.a + $(CC) $(CFLAGS) -g -o $@ $^ + +%.a: FORCE + set -e ;\ + DIR=$(basename $@ .a) ;\ + $(MAKE) CC=$(CC) AR=$(AR) CFLAGS=$(CGLAGS) -C $$DIR $@ ;\ + cp $$DIR/$@ $@ + +FORCE: + +install: + install bison $(PREFIX)/bin + rm -rf $(PREFIX)/share/bison + install -d $(PREFIX)/share/bison + mv data/skeletons/ $(PREFIX)/share/bison + mv data/m4sugar/ $(PREFIX)/share/bison diff --git a/sysa/bison-3.4.1/mk/src.mk b/sysa/bison-3.4.1/mk/src.mk new file mode 100644 index 0000000..6d41b7c --- /dev/null +++ b/sysa/bison-3.4.1/mk/src.mk @@ -0,0 +1,23 @@ +# SPDX-FileCopyrightText: 2020 Giovanni Mascellani gio@debian.org +# SPDX-FileCopyrightText: 2021 Andrius Štikonas +# +# SPDX-License-Identifier: GPL-3.0-or-later + +src.a: AnnotationList.o assoc.o closure.o complain.o conflicts.o derives.o files.o fixits.o getargs.o gram.o graphviz.o ielr.o InadequacyList.o lalr.o location.o lr0.o main.o muscle-tab.o named-ref.o nullable.o output.o parse-gram.o print.o print-graph.o print-xml.o reader.o reduce.o relation.o Sbitset.o scan-code.o scan-gram.o scan-skel.o state.o symlist.o symtab.o tables.o uniqstr.o + $(AR) r $@ $^ + +closure.o: parse-gram.h +parse-gram.h: parse-gram.c + +%.o: %.c + $(CC) $(CFLAGS) -g -c -I. -I.. -I../lib -o $@ $< + +%.c: %.y + bison -dv $< + mv $(shell echo $@ | sed -e 's/c$$/tab.c/') $@ + mv $(shell echo $@ | sed -e 's/c$$/tab.h/') $(shell echo $@ | sed -e 's/c$$/h/') + +%.c: %.l + /bin/sh ../build-aux/ylwrap $< lex.yy.c $@ -- flex + +.PRECIOUS: %.c %.o %.h diff --git a/sysa/bison-3.4.1/patches/fseterr.patch b/sysa/bison-3.4.1/patches/fseterr.patch new file mode 100644 index 0000000..eafe0ca --- /dev/null +++ b/sysa/bison-3.4.1/patches/fseterr.patch @@ -0,0 +1,23 @@ +SPDX-FileCopyrightText: 2020 Giovanni Mascellani + +SPDX-License-Identifier: GPL-3.0-or-later + +commit b1127f6821cc9c40c5a9ee406bee7564c549d9a3 +Author: Giovanni Mascellani +Date: Thu Mar 26 18:02:01 2020 +0100 + + Compile bison. + +diff --git lib/fseterr.c lib/fseterr.c +index 8cd68e8..0ec7e2c 100644 +--- lib/fseterr.c ++++ lib/fseterr.c +@@ -53,7 +53,7 @@ fseterr (FILE *fp) + #elif defined EPLAN9 /* Plan9 */ + if (fp->state != 0 /* CLOSED */) + fp->state = 5 /* ERR */; +-#elif 0 /* unknown */ ++#elif 1 /* unknown */ + /* Portable fallback, based on an idea by Rich Felker. + Wow! 6 system calls for something that is just a bit operation! + Not activated on any system, because there is no way to repair FP when diff --git a/sysa/bison-3.4.1/patches/missing-includes.patch b/sysa/bison-3.4.1/patches/missing-includes.patch new file mode 100644 index 0000000..96f5f1d --- /dev/null +++ b/sysa/bison-3.4.1/patches/missing-includes.patch @@ -0,0 +1,70 @@ +SPDX-FileCopyrightText: 2020 Giovanni Mascellani + +SPDX-License-Identifier: GPL-3.0-or-later + +commit b1127f6821cc9c40c5a9ee406bee7564c549d9a3 +Author: Giovanni Mascellani +Date: Thu Mar 26 18:02:01 2020 +0100 + + Compile bison. + +diff --git src/scan-code.l src/scan-code.l +index 73a3b2d..f348b20 100644 +--- src/scan-code.l ++++ src/scan-code.l +@@ -21,6 +21,7 @@ + %option prefix="code_" outfile="lex.yy.c" + + %{ ++#include "config.h" + #include + #include + #include +@@ -31,6 +32,7 @@ + #include + #include + #include ++#include "system.h" + + #define FLEX_PREFIX(Id) code_ ## Id + #include +diff --git src/scan-gram.l src/scan-gram.l +index 66a8caa..efa391a 100644 +--- src/scan-gram.l ++++ src/scan-gram.l +@@ -21,6 +21,7 @@ + %option prefix="gram_" outfile="lex.yy.c" + + %{ ++#include "config.h" + #include + #include + #include +@@ -33,6 +34,7 @@ + #include + #include + #include ++#include "system.h" + + #define FLEX_PREFIX(Id) gram_ ## Id + #include +diff --git src/scan-skel.l src/scan-skel.l +index 487e9f5..19f4832 100644 +--- src/scan-skel.l ++++ src/scan-skel.l +@@ -21,6 +21,7 @@ + %option prefix="skel_" outfile="lex.yy.c" + + %{ ++#include "config.h" + #include + #include + #include +@@ -30,6 +31,7 @@ + #include + #include + #include ++#include "system.h" + + #define FLEX_PREFIX(Id) skel_ ## Id + #include diff --git a/sysa/bison-3.4.1/stage1.sh b/sysa/bison-3.4.1/stage1.sh new file mode 100755 index 0000000..cb37721 --- /dev/null +++ b/sysa/bison-3.4.1/stage1.sh @@ -0,0 +1,21 @@ +# SPDX-FileCopyrightText: 2021 Andrius Štikonas +# +# SPDX-License-Identifier: GPL-3.0-or-later + +src_prepare() { + default_src_prepare + + mv lib/textstyle.in.h lib/textstyle.h + + # Remove pre-generated flex/bison files + rm src/parse-gram.c src/parse-gram.h + rm src/scan-code.c + rm src/scan-gram.c + rm src/scan-skel.c + + # Handwritten bison parser + mv parse-gram.c parse-gram.h src/ + + cp ../../mk/lib.mk lib/Makefile + cp ../../mk/src.mk src/Makefile +} diff --git a/sysa/bison-3.4.1/stage2.sh b/sysa/bison-3.4.1/stage2.sh new file mode 100755 index 0000000..2fbbe62 --- /dev/null +++ b/sysa/bison-3.4.1/stage2.sh @@ -0,0 +1,21 @@ +# SPDX-FileCopyrightText: 2021 Andrius Štikonas +# +# SPDX-License-Identifier: GPL-3.0-or-later + +src_prepare() { + default_src_prepare + + mv lib/textstyle.in.h lib/textstyle.h + + # Remove pre-generated flex/bison files + rm src/parse-gram.c src/parse-gram.h + rm src/scan-code.c + rm src/scan-gram.c + rm src/scan-skel.c + + # Simplified bison grammar + mv parse-gram.y src/ + + cp ../../mk/lib.mk lib/Makefile + cp ../../mk/src.mk src/Makefile +} diff --git a/sysa/bison-3.4.1/stage3.sh b/sysa/bison-3.4.1/stage3.sh new file mode 100755 index 0000000..37fb2ab --- /dev/null +++ b/sysa/bison-3.4.1/stage3.sh @@ -0,0 +1,18 @@ +# SPDX-FileCopyrightText: 2021 Andrius Štikonas +# +# SPDX-License-Identifier: GPL-3.0-or-later + +src_prepare() { + default_src_prepare + + mv lib/textstyle.in.h lib/textstyle.h + + # Remove pre-generated flex/bison files + rm src/parse-gram.c src/parse-gram.h + rm src/scan-code.c + rm src/scan-gram.c + rm src/scan-skel.c + + cp ../../mk/lib.mk lib/Makefile + cp ../../mk/src.mk src/Makefile +} diff --git a/sysa/run.sh b/sysa/run.sh index dc3b607..8475704 100755 --- a/sysa/run.sh +++ b/sysa/run.sh @@ -25,9 +25,14 @@ build m4-1.4.7 build flex-2.6.4 # Part 24 -build grep-2.4 +build bison-3.4.1 stage1.sh +build bison-3.4.1 stage2.sh +build bison-3.4.1 stage3.sh # Part 25 +build grep-2.4 + +# Part 26 build diffutils-2.7 echo "Bootstrapping completed."