Imported Upstream version 20221229
[platform/upstream/byacc.git] / reader.c
index ebf40d2..5e8ca67 100644 (file)
--- a/reader.c
+++ b/reader.c
@@ -1,11 +1,11 @@
-/* $Id: reader.c,v 1.73 2017/07/09 19:15:35 tom Exp $ */
+/* $Id: reader.c,v 1.91 2022/01/09 18:04:58 tom Exp $ */
 
 #include "defs.h"
 
 /*  The line size must be a positive integer.  One hundred was chosen  */
 /*  because few lines in Yacc input grammars exceed 100 characters.    */
 /*  Note that if a line exceeds LINESIZE characters, the line buffer   */
-/*  will be expanded to accomodate it.                                 */
+/*  will be expanded to accommodate it.                                        */
 
 #define LINESIZE 100
 
 /* this is a hard limit, but seems more than adequate */
 #define MAXARGS        20
 
+#define begin_case(f,n) fprintf(f, "case %d:\n", (int)(n))
+
+#define end_case(f) \
+           fprintf(f, "\n"); \
+           fprintf_lineno(f, 1, ""); \
+           fprintf(f, "break;\n")
+
 static void start_rule(bucket *bp, int s_lineno);
 #if defined(YYBTYACC)
 static void copy_initial_action(void);
@@ -62,6 +69,13 @@ char line_format[] = "#line %d \"%s\"\n";
 param *lex_param;
 param *parse_param;
 
+static const char *code_keys[] =
+{
+    "", "requires", "provides", "top", "imports",
+};
+
+struct code_lines code_lines[CODE_MAX];
+
 #if defined(YYBTYACC)
 int destructor = 0;    /* =1 if at least one %destructor */
 
@@ -178,7 +192,7 @@ line_directive(void)
            else
                UNLESS(!isdigit(UCH(ch)));
            line_1st = n;
-           ld = ldNUM;
+           ld = ldNUM;         /* this is needed, but cppcheck says no... */
            /* FALLTHRU */
        case ldNUM:
            if (isdigit(UCH(ch)))
@@ -216,7 +230,7 @@ line_directive(void)
 
     if (ld == ldOK)
     {
-       size_t need = (size_t) (name_end - name_1st);
+       size_t need = (size_t)(name_end - name_1st);
        if ((long)need > (long)input_file_name_len)
        {
            input_file_name_len = ((need + 1) * 3) / 2;
@@ -254,11 +268,12 @@ static void
 get_line(void)
 {
     FILE *f = input_file;
-    int c;
-    int i;
 
     do
     {
+       int c;
+       int i;
+
        if (saw_eof || (c = getc(f)) == EOF)
        {
            if (line)
@@ -437,19 +452,20 @@ nextc(void)
 /* *INDENT-OFF* */
 static struct keyword
 {
-    char name[14];
+    char name[16];
     int token;
 }
 keywords[] = {
     { "binary",      NONASSOC },
-    { "debug",       XXXDEBUG },
+    { "code",        XCODE },
+    { "debug",       NONPOSIX_DEBUG },
 #if defined(YYBTYACC)
     { "destructor",  DESTRUCTOR },
 #endif
     { "error-verbose",ERROR_VERBOSE },
     { "expect",      EXPECT },
     { "expect-rr",   EXPECT_RR },
-    { "ident",       IDENT }, 
+    { "ident",       IDENT },
 #if defined(YYBTYACC)
     { "initial-action", INITIAL_ACTION },
 #endif
@@ -461,11 +477,11 @@ keywords[] = {
     { "nonassoc",    NONASSOC },
     { "parse-param", PARSE_PARAM },
     { "pure-parser", PURE_PARSER },
-    { "right",       RIGHT }, 
+    { "right",       RIGHT },
     { "start",       START },
     { "term",        TOKEN },
     { "token",       TOKEN },
-    { "token-table", TOKEN_TABLE }, 
+    { "token-table", TOKEN_TABLE },
     { "type",        TYPE },
     { "union",       UNION },
     { "yacc",        POSIX_YACC },
@@ -485,11 +501,12 @@ keyword(void)
 {
     int c;
     char *t_cptr = cptr;
-    struct keyword *key;
 
     c = *++cptr;
     if (isalpha(UCH(c)))
     {
+       struct keyword *key;
+
        cinc = 0;
        for (;;)
        {
@@ -579,7 +596,6 @@ static char *
 copy_string(int quote)
 {
     struct mstring *temp = msnew();
-    int c;
     struct ainfo a;
     a.a_lineno = lineno;
     a.a_line = dup_line();
@@ -587,7 +603,8 @@ copy_string(int quote)
 
     for (;;)
     {
-       c = *cptr++;
+       int c = *cptr++;
+
        mputc(temp, c);
        if (c == quote)
        {
@@ -660,6 +677,128 @@ copy_comment(void)
     return msdone(temp);
 }
 
+static int
+check_key(int pos)
+{
+    const char *key = code_keys[pos];
+    while (*cptr && *key)
+       if (*key++ != *cptr++)
+           return 0;
+    if (*key || (!isspace(UCH(*cptr)) && *cptr != L_CURL))
+       return 0;
+    cptr--;
+    return 1;
+}
+
+static void
+copy_code(void)
+{
+    int c;
+    int curl;
+    int cline;
+    int on_line = 0;
+    int pos = CODE_HEADER;
+    struct mstring *code_mstr;
+
+    /* read %code <keyword> { */
+    for (;;)
+    {
+       c = *++cptr;
+       if (c == EOF)
+           unexpected_EOF();
+       if (isspace(UCH(c)))
+           continue;
+
+       if (c == L_CURL)
+           break;
+
+       if (pos == CODE_HEADER)
+       {
+           switch (UCH(c))
+           {
+           case 'r':
+               pos = CODE_REQUIRES;
+               break;
+           case 'p':
+               pos = CODE_PROVIDES;
+               break;
+           case 't':
+               pos = CODE_TOP;
+               break;
+           case 'i':
+               pos = CODE_IMPORTS;
+               break;
+           default:
+               break;
+           }
+
+           if (pos == -1 || !check_key(pos))
+           {
+               syntax_error(lineno, line, cptr);
+               /*NOTREACHED */
+           }
+       }
+    }
+
+    cptr++;                    /* skip initial curl */
+    while (*cptr && isspace(UCH(*cptr)))       /* skip space */
+       cptr++;
+    curl = 1;                  /* nesting count */
+
+    /* gather text */
+    code_lines[pos].name = code_keys[pos];
+    if ((cline = (int)code_lines[pos].num) != 0)
+    {
+       code_mstr = msrenew(code_lines[pos].lines);
+    }
+    else
+    {
+       code_mstr = msnew();
+    }
+    cline++;
+    if (!lflag)
+       msprintf(code_mstr, line_format, lineno, input_file_name);
+    for (;;)
+    {
+       c = *cptr++;
+       switch (c)
+       {
+       case '\0':
+           get_line();
+           if (line == NULL)
+           {
+               unexpected_EOF();
+               /*NOTREACHED */
+           }
+           continue;
+       case '\n':
+           cline++;
+           on_line = 0;
+           break;
+       case L_CURL:
+           curl++;
+           break;
+       case R_CURL:
+           if (--curl == 0)
+           {
+               if (on_line > 1)
+               {
+                   mputc(code_mstr, '\n');
+                   cline++;
+               }
+               code_lines[pos].lines = msdone(code_mstr);
+               code_lines[pos].num = (size_t)cline;
+               return;
+           }
+           break;
+       default:
+           break;
+       }
+       mputc(code_mstr, c);
+       on_line++;
+    }
+}
+
 static void
 copy_text(void)
 {
@@ -677,8 +816,7 @@ copy_text(void)
        if (line == NULL)
            unterminated_text(&a);
     }
-    if (!lflag)
-       fprintf(f, line_format, lineno, input_file_name);
+    fprintf_lineno(f, lineno, input_file_name);
 
   loop:
     c = *cptr++;
@@ -769,9 +907,8 @@ copy_union(void)
     puts_both("#ifndef YYSTYPE_IS_DECLARED\n");
     puts_both("#define YYSTYPE_IS_DECLARED 1\n");
 
-    if (!lflag)
-       fprintf(text_file, line_format, lineno, input_file_name);
-    puts_both("typedef union");
+    fprintf_lineno(text_file, lineno, input_file_name);
+    puts_both("typedef union YYSTYPE");
 
     depth = 0;
   loop:
@@ -1011,19 +1148,23 @@ copy_param(int k)
        }
        if (buf == 0)
        {
-           buf_size = (size_t) linesize;
+           buf_size = (size_t)linesize;
            buf = TMALLOC(char, buf_size);
+           NO_SPACE(buf);
        }
        else if (c == '\n')
        {
+           char *tmp;
+
            get_line();
            if (line == NULL)
                unexpected_EOF();
            --cptr;
-           buf_size += (size_t) linesize;
-           buf = TREALLOC(char, buf, buf_size);
+           buf_size += (size_t)linesize;
+           tmp = TREALLOC(char, buf, buf_size);
+           NO_SPACE(tmp);
+           buf = tmp;
        }
-       NO_SPACE(buf);
        if (curly)
        {
            if ((state == 2) && (c == L_CURL))
@@ -1074,13 +1215,21 @@ copy_param(int k)
        if (parms[i] == ']')
        {
            int level = 1;
-           while (i >= 0 && level > 0 && parms[i] != '[')
+           while (i >= 0)
            {
-               if (parms[i] == ']')
+               char ch = parms[i--];
+               if (ch == ']')
+               {
                    ++level;
-               else if (parms[i] == '[')
-                   --level;
-               i--;
+               }
+               else if (ch == '[')
+               {
+                   if (--level <= 1)
+                   {
+                       ++i;
+                       break;
+                   }
+               }
            }
            if (i <= 0)
                unexpected_EOF();
@@ -1304,8 +1453,6 @@ get_literal(void)
 static int
 is_reserved(char *name)
 {
-    char *s;
-
     if (strcmp(name, ".") == 0 ||
        strcmp(name, "$accept") == 0 ||
        strcmp(name, "$end") == 0)
@@ -1313,7 +1460,8 @@ is_reserved(char *name)
 
     if (name[0] == '$' && name[1] == '$' && isdigit(UCH(name[2])))
     {
-       s = name + 3;
+       char *s = name + 3;
+
        while (isdigit(UCH(*s)))
            ++s;
        if (*s == NUL)
@@ -1353,8 +1501,7 @@ get_number(void)
        if (n > MAXYYINT)
        {
            syntax_error(lineno, line, base);
-           n = 0;
-           break;
+           /*NOTREACHED */
        }
     }
 
@@ -1426,7 +1573,7 @@ get_tag(void)
 
     FREE(t_line);
     havetags = 1;
-    return cache_tag(cache, (size_t) cinc);
+    return cache_tag(cache, (size_t)cinc);
 }
 
 #if defined(YYBTYACC)
@@ -1437,7 +1584,7 @@ scan_id(void)
 
     while (IS_NAME2(UCH(*cptr)))
        cptr++;
-    return cache_tag(b, (size_t) (cptr - b));
+    return cache_tag(b, (size_t)(cptr - b));
 }
 #endif
 
@@ -1562,14 +1709,14 @@ static void
 declare_argtypes(bucket *bp)
 {
     char *tags[MAXARGS];
-    int args = 0, c;
+    int args = 0;
 
     if (bp->args >= 0)
        retyped_warning(bp->name);
     cptr++;                    /* skip open paren */
     for (;;)
     {
-       c = nextc();
+       int c = nextc();
        if (c == EOF)
            unexpected_EOF();
        if (c != '<')
@@ -1664,15 +1811,15 @@ declare_start(void)
 static void
 read_declarations(void)
 {
-    int c, k;
-
     cache_size = CACHE_SIZE;
     cache = TMALLOC(char, cache_size);
     NO_SPACE(cache);
 
     for (;;)
     {
-       c = nextc();
+       int k;
+       int c = nextc();
+
        if (c == EOF)
            unexpected_EOF();
        if (c != '%')
@@ -1686,6 +1833,10 @@ read_declarations(void)
            copy_ident();
            break;
 
+       case XCODE:
+           copy_code();
+           break;
+
        case TEXT:
            copy_text();
            break;
@@ -1745,8 +1896,8 @@ read_declarations(void)
            break;
 #endif
 
-       case XXXDEBUG:
-           /* XXX: FIXME */
+       case NONPOSIX_DEBUG:
+           tflag = 1;
            break;
 
        case POSIX_YACC:
@@ -1897,7 +2048,7 @@ parse_id(char *p, char **save)
        p++;
     if (save)
     {
-       *save = cache_tag(b, (size_t) (p - b));
+       *save = cache_tag(b, (size_t)(p - b));
     }
     return p;
 }
@@ -1995,7 +2146,7 @@ compile_arg(char **theptr, char *yyvaltag)
 {
     char *p = *theptr;
     struct mstring *c = msnew();
-    int i, j, n;
+    int i, n;
     Value_t *offsets = NULL, maxoffset;
     bucket **rhs;
 
@@ -2009,7 +2160,9 @@ compile_arg(char **theptr, char *yyvaltag)
     }
     if (maxoffset > 0)
     {
-       offsets = TMALLOC(Value_t, maxoffset + 1);
+       int j;
+
+       offsets = TCMALLOC(Value_t, maxoffset + 1);
        NO_SPACE(offsets);
 
        for (j = 0, i++; i < nitems; i++)
@@ -2098,7 +2251,7 @@ can_elide_arg(char **theptr, char *yyvaltag)
 {
     char *p = *theptr;
     int rv = 0;
-    int i, j, n = 0;
+    int i, n = 0;
     Value_t *offsets = NULL, maxoffset = 0;
     bucket **rhs;
     char *tag = 0;
@@ -2118,7 +2271,9 @@ can_elide_arg(char **theptr, char *yyvaltag)
     }
     if (maxoffset > 0)
     {
-       offsets = TMALLOC(Value_t, maxoffset + 1);
+       int j;
+
+       offsets = TCMALLOC(Value_t, maxoffset + 1);
        NO_SPACE(offsets);
 
        for (j = 0, i++; i < nitems; i++)
@@ -2151,7 +2306,10 @@ can_elide_arg(char **theptr, char *yyvaltag)
     {
        char *arg;
        if (!(p = parse_id(p, &arg)))
+       {
+           FREE(offsets);
            return 0;
+       }
        for (i = plhs[nrules]->args - 1; i >= 0; i--)
            if (arg == plhs[nrules]->argnames[i])
                break;
@@ -2171,7 +2329,7 @@ can_elide_arg(char **theptr, char *yyvaltag)
        rv = 0;
     if (maxoffset > 0)
        FREE(offsets);
-    if (*p || rv <= 0)
+    if (p == 0 || *p || rv <= 0)
        return 0;
     *theptr = p + 1;
     return rv;
@@ -2235,7 +2393,6 @@ advance_to_start(void)
 {
     int c;
     bucket *bp;
-    char *s_cptr;
     int s_lineno;
 #if defined(YYBTYACC)
     char *args = NULL;
@@ -2244,12 +2401,18 @@ advance_to_start(void)
 
     for (;;)
     {
+       char *s_cptr;
+
        c = nextc();
        if (c != '%')
            break;
        s_cptr = cptr;
        switch (keyword())
        {
+       case XCODE:
+           copy_code();
+           break;
+
        case MARK:
            no_grammar();
 
@@ -2318,12 +2481,12 @@ start_rule(bucket *bp, int s_lineno)
 static void
 end_rule(void)
 {
-    int i;
-
     if (!last_was_action && plhs[nrules]->tag)
     {
        if (pitem[nitems - 1])
        {
+           int i;
+
            for (i = nitems - 1; (i > 0) && pitem[i]; --i)
                continue;
            if (pitem[i + 1] == 0 || pitem[i + 1]->tag != plhs[nrules]->tag)
@@ -2390,11 +2553,10 @@ insert_arg_rule(char *arg, char *tag)
        rule = nrules;
        insert_arg_cache(code, rule);
        trialaction = 1;        /* arg rules always run in trial mode */
-       fprintf(f, "case %d:\n", rule - 2);
-       if (!lflag)
-           fprintf(f, line_format, line_number, input_file_name);
-       fprintf(f, "%s;\n", code);
-       fprintf(f, "break;\n");
+       begin_case(f, rule - 2);
+       fprintf_lineno(f, line_number, input_file_name);
+       fprintf(f, "%s;", code);
+       end_case(f);
        insert_empty_rule();
        plhs[rule]->tag = cache_tag(tag, strlen(tag));
        plhs[rule]->class = ARGUMENT;
@@ -2530,7 +2692,7 @@ copy_action(void)
     trialaction = (*cptr == L_BRAC);
 #endif
 
-    fprintf(f, "case %d:\n", nrules - 2);
+    begin_case(f, nrules - 2);
 #if defined(YYBTYACC)
     if (backtrack)
     {
@@ -2538,8 +2700,7 @@ copy_action(void)
            fprintf(f, "  if (!yytrial)\n");
     }
 #endif
-    if (!lflag)
-       fprintf(f, line_format, lineno, input_file_name);
+    fprintf_lineno(f, lineno, input_file_name);
     if (*cptr == '=')
        ++cptr;
 
@@ -2602,10 +2763,12 @@ copy_action(void)
                else if (i > maxoffset)
                {
                    dollar_warning(d_lineno, i);
-                   fprintf(f, "yystack.l_mark[%d].%s", i - maxoffset, tag);
+                   fprintf(f, "yystack.l_mark[%ld].%s",
+                           (long)(i - maxoffset), tag);
                }
                else if (offsets)
-                   fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
+                   fprintf(f, "yystack.l_mark[%ld].%s",
+                           (long)offsets[i], tag);
                FREE(d_line);
                goto loop;
            }
@@ -2663,7 +2826,7 @@ copy_action(void)
                tag = rhs[offsets[i]]->tag;
                if (tag == 0)
                    untyped_rhs(i, rhs[offsets[i]]->name);
-               fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
+               fprintf(f, "yystack.l_mark[%ld].%s", (long)offsets[i], tag);
            }
            else
            {
@@ -2672,10 +2835,10 @@ copy_action(void)
                else if (i > maxoffset)
                {
                    dollar_warning(lineno, i);
-                   fprintf(f, "yystack.l_mark[%d]", i - maxoffset);
+                   fprintf(f, "yystack.l_mark[%ld]", (long)(i - maxoffset));
                }
                else if (offsets)
-                   fprintf(f, "yystack.l_mark[%d]", offsets[i]);
+                   fprintf(f, "yystack.l_mark[%ld]", (long)offsets[i]);
            }
            goto loop;
        }
@@ -2781,12 +2944,11 @@ copy_action(void)
            if (c == L_CURL && !haveyyval)
            {
                fprintf(f, "  if (!yytrial)\n");
-               if (!lflag)
-                   fprintf(f, line_format, lineno, input_file_name);
+               fprintf_lineno(f, lineno, input_file_name);
                trialaction = 0;
                goto loop;
            }
-           fprintf(f, "\nbreak;\n");
+           end_case(f);
            FREE(a.a_line);
            if (maxoffset > 0)
                FREE(offsets);
@@ -2806,7 +2968,7 @@ copy_action(void)
     case ';':
        if (depth > 0)
            goto loop;
-       fprintf(f, "\nbreak;\n");
+       end_case(f);
        free(a.a_line);
        if (maxoffset > 0)
            FREE(offsets);
@@ -2843,13 +3005,12 @@ copy_action(void)
            if (c == L_CURL && !haveyyval)
            {
                fprintf(f, "  if (!yytrial)\n");
-               if (!lflag)
-                   fprintf(f, line_format, lineno, input_file_name);
+               fprintf_lineno(f, lineno, input_file_name);
                goto loop;
            }
        }
 #endif
-       fprintf(f, "\nbreak;\n");
+       end_case(f);
        free(a.a_line);
        if (maxoffset > 0)
            FREE(offsets);
@@ -3011,7 +3172,6 @@ static void
 copy_destructor(void)
 {
     char *code_text;
-    int c;
     struct ainfo a;
     bucket *bp;
 
@@ -3019,7 +3179,7 @@ copy_destructor(void)
 
     for (;;)
     {
-       c = nextc();
+       int c = nextc();
        if (c == EOF)
            unexpected_EOF();
        if (c == '<')
@@ -3198,6 +3358,16 @@ mark_symbol(void)
             ((c = cptr[4]) == 'c' || c == 'C') &&
             ((c = cptr[5], !IS_IDENT(c))))
        cptr += 5;
+    else if ((c == 'e' || c == 'E') &&
+            ((c = cptr[2]) == 'm' || c == 'M') &&
+            ((c = cptr[3]) == 'p' || c == 'P') &&
+            ((c = cptr[4]) == 't' || c == 'T') &&
+            ((c = cptr[5]) == 'y' || c == 'Y') &&
+            ((c = cptr[6], !IS_IDENT(c))))
+    {
+       cptr += 6;
+       return (1);
+    }
     else
        syntax_error(lineno, line, cptr);
 
@@ -3223,14 +3393,13 @@ mark_symbol(void)
 static void
 read_grammar(void)
 {
-    int c;
-
     initialize_grammar();
     advance_to_start();
 
     for (;;)
     {
-       c = nextc();
+       int c = nextc();
+
        if (c == EOF)
            break;
        if (isalpha(UCH(c))
@@ -3239,13 +3408,17 @@ read_grammar(void)
            || c == '$'
            || c == '\''
            || c == '"')
+       {
            add_symbol();
+       }
+       else if (c == L_CURL || c == '='
 #if defined(YYBTYACC)
-       else if (c == L_CURL || c == '=' || (backtrack && c == L_BRAC))
-#else
-       else if (c == L_CURL || c == '=')
+                || (backtrack && c == L_BRAC)
 #endif
+           )
+       {
            copy_action();
+       }
        else if (c == '|')
        {
            end_rule();
@@ -3287,7 +3460,8 @@ static void
 pack_names(void)
 {
     bucket *bp;
-    char *p, *s, *t;
+    char *p;
+    char *t;
 
     name_pool_size = 13;       /* 13 == sizeof("$end") + sizeof("$accept") */
     for (bp = first_symbol; bp; bp = bp->next)
@@ -3301,8 +3475,9 @@ pack_names(void)
     t = name_pool + 13;
     for (bp = first_symbol; bp; bp = bp->next)
     {
+       char *s = bp->name;
+
        p = t;
-       s = bp->name;
        while ((*t++ = *s++) != 0)
            continue;
        FREE(bp->name);
@@ -3331,14 +3506,14 @@ check_symbols(void)
 static void
 protect_string(char *src, char **des)
 {
-    unsigned len;
-    char *s;
-    char *d;
-
     *des = src;
     if (src)
     {
-       len = 1;
+       char *s;
+       char *d;
+
+       unsigned len = 1;
+
        s = src;
        while (*s)
        {
@@ -3549,8 +3724,6 @@ pack_grammar(void)
 {
     int i;
     Value_t j;
-    Assoc_t assoc;
-    Value_t prec2;
 
     ritem = TMALLOC(Value_t, nitems);
     NO_SPACE(ritem);
@@ -3581,6 +3754,9 @@ pack_grammar(void)
     j = 4;
     for (i = 3; i < nrules; ++i)
     {
+       Assoc_t assoc;
+       Value_t prec2;
+
 #if defined(YYBTYACC)
        if (plhs[i]->args > 0)
        {
@@ -3672,11 +3848,11 @@ finalize_destructors(void)
 {
     int i;
     bucket *bp;
-    char *tag;
 
     for (i = 2; i < nsyms; ++i)
     {
-       tag = symbol_type_tag[i];
+       char *tag = symbol_type_tag[i];
+
        if (symbol_destructor[i] == NULL)
        {
            if (tag == NULL)
@@ -3710,8 +3886,10 @@ finalize_destructors(void)
        }
        else
        {                       /* replace "$$" with "(*val)[.tag]" in destructor code */
+           char *destructor_source = symbol_destructor[i];
            symbol_destructor[i]
-               = process_destructor_XX(symbol_destructor[i], tag);
+               = process_destructor_XX(destructor_source, tag);
+           FREE(destructor_source);
        }
     }
     /* 'symbol_type_tag[]' elements are freed by 'free_tags()' */