Imported Upstream version 20200910
[platform/upstream/byacc.git] / reader.c
index efcbaa5..5a9bd38 100644 (file)
--- a/reader.c
+++ b/reader.c
@@ -1,11 +1,11 @@
-/* $Id: reader.c,v 1.68 2017/02/02 01:05:36 tom Exp $ */
+/* $Id: reader.c,v 1.84 2020/09/10 20:26:13 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
 
@@ -62,6 +62,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 */
 
@@ -144,7 +151,7 @@ line_directive(void)
        switch (ld)
        {
        case ldSPC1:
-           if (isspace(ch))
+           if (isspace(UCH(ch)))
            {
                break;
            }
@@ -153,7 +160,7 @@ line_directive(void)
            ld = ldSPC2;
            break;
        case ldSPC2:
-           if (isspace(ch))
+           if (isspace(UCH(ch)))
            {
                break;
            }
@@ -171,26 +178,26 @@ line_directive(void)
            ld = ldSPC3;
            break;
        case ldSPC3:
-           if (isspace(ch))
+           if (isspace(UCH(ch)))
            {
                break;
            }
            else
-               UNLESS(!isdigit(ch));
+               UNLESS(!isdigit(UCH(ch)));
            line_1st = n;
-           ld = ldNUM;
+           ld = ldNUM;         /* this is needed, but cppcheck says no... */
            /* FALLTHRU */
        case ldNUM:
-           if (isdigit(ch))
+           if (isdigit(UCH(ch)))
            {
                break;
            }
            else
-               UNLESS(!isspace(ch));
+               UNLESS(!isspace(UCH(ch)));
            ld = ldSPC4;
            break;
        case ldSPC4:
-           if (isspace(ch))
+           if (isspace(UCH(ch)))
            {
                break;
            }
@@ -217,19 +224,33 @@ line_directive(void)
     if (ld == ldOK)
     {
        size_t need = (size_t) (name_end - name_1st);
-       if (need > input_file_name_len)
+       if ((long)need > (long)input_file_name_len)
        {
-           input_file_name_len = need;
-           input_file_name = TREALLOC(char, input_file_name, need + 1);
+           input_file_name_len = ((need + 1) * 3) / 2;
+           input_file_name = TREALLOC(char, input_file_name, input_file_name_len);
            NO_SPACE(input_file_name);
        }
-       memcpy(input_file_name, line + name_1st + 1, need - 1);
-       input_file_name[need - 1] = '\0';
+       if ((long)need > 0)
+       {
+           memcpy(input_file_name, line + name_1st + 1, need - 1);
+           input_file_name[need - 1] = '\0';
+       }
+       else
+       {
+           input_file_name[0] = '\0';
+       }
     }
 
     if (ld >= ldNUM && ld < ldERR)
     {
-       lineno = (int)strtol(line + line_1st, NULL, 10) - 1;
+       if (line_1st >= 0)
+       {
+           lineno = (int)strtol(line + line_1st, NULL, 10) - 1;
+       }
+       else
+       {
+           lineno = 0;
+       }
     }
 
     return (ld == ldOK);
@@ -240,11 +261,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)
@@ -423,11 +445,12 @@ nextc(void)
 /* *INDENT-OFF* */
 static struct keyword
 {
-    char name[14];
+    char name[16];
     int token;
 }
 keywords[] = {
     { "binary",      NONASSOC },
+    { "code",        XCODE },
     { "debug",       XXXDEBUG },
 #if defined(YYBTYACC)
     { "destructor",  DESTRUCTOR },
@@ -435,7 +458,7 @@ keywords[] = {
     { "error-verbose",ERROR_VERBOSE },
     { "expect",      EXPECT },
     { "expect-rr",   EXPECT_RR },
-    { "ident",       IDENT }, 
+    { "ident",       IDENT },
 #if defined(YYBTYACC)
     { "initial-action", INITIAL_ACTION },
 #endif
@@ -447,11 +470,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 },
@@ -471,21 +494,22 @@ keyword(void)
 {
     int c;
     char *t_cptr = cptr;
-    struct keyword *key;
 
     c = *++cptr;
-    if (isalpha(c))
+    if (isalpha(UCH(c)))
     {
+       struct keyword *key;
+
        cinc = 0;
        for (;;)
        {
-           if (isalpha(c))
+           if (isalpha(UCH(c)))
            {
-               if (isupper(c))
+               if (isupper(UCH(c)))
                    c = tolower(c);
                cachec(c);
            }
-           else if (isdigit(c)
+           else if (isdigit(UCH(c))
                     || c == '-'
                     || c == '.'
                     || c == '$')
@@ -565,7 +589,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();
@@ -573,7 +596,8 @@ copy_string(int quote)
 
     for (;;)
     {
-       c = *cptr++;
+       int c = *cptr++;
+
        mputc(temp, c);
        if (c == quote)
        {
@@ -646,6 +670,127 @@ 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++;
+    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)
 {
@@ -999,17 +1144,21 @@ copy_param(int k)
        {
            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);
+           tmp = TREALLOC(char, buf, buf_size);
+           NO_SPACE(tmp);
+           buf = tmp;
        }
-       NO_SPACE(buf);
        if (curly)
        {
            if ((state == 2) && (c == L_CURL))
@@ -1060,13 +1209,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();
@@ -1235,7 +1392,7 @@ get_literal(void)
            cachec('\\');
            cachec(c);
        }
-       else if (isprint(c))
+       else if (isprint(UCH(c)))
            cachec(c);
        else
        {
@@ -1290,8 +1447,6 @@ get_literal(void)
 static int
 is_reserved(char *name)
 {
-    char *s;
-
     if (strcmp(name, ".") == 0 ||
        strcmp(name, "$accept") == 0 ||
        strcmp(name, "$end") == 0)
@@ -1299,7 +1454,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)
@@ -1329,13 +1485,21 @@ static Value_t
 get_number(void)
 {
     int c;
-    Value_t n;
+    long n;
+    char *base = cptr;
 
     n = 0;
-    for (c = *cptr; isdigit(c); c = *++cptr)
-       n = (Value_t)(10 * n + (c - '0'));
+    for (c = *cptr; isdigit(UCH(c)); c = *++cptr)
+    {
+       n = (10 * n + (c - '0'));
+       if (n > MAXYYINT)
+       {
+           syntax_error(lineno, line, base);
+           /*NOTREACHED */
+       }
+    }
 
-    return (n);
+    return (Value_t)(n);
 }
 
 static char *
@@ -1382,7 +1546,7 @@ get_tag(void)
     c = nextc();
     if (c == EOF)
        unexpected_EOF();
-    if (!isalpha(c) && c != '_' && c != '$')
+    if (!IS_NAME1(c))
        illegal_tag(t_lineno, t_line, t_cptr);
 
     cinc = 0;
@@ -1412,7 +1576,7 @@ scan_id(void)
 {
     char *b = cptr;
 
-    while (isalnum(UCH(*cptr)) || *cptr == '_' || *cptr == '$')
+    while (IS_NAME2(UCH(*cptr)))
        cptr++;
     return cache_tag(b, (size_t) (cptr - b));
 }
@@ -1442,7 +1606,7 @@ declare_tokens(int assoc)
 
     for (;;)
     {
-       if (isalpha(c) || c == '_' || c == '.' || c == '$')
+       if (isalpha(UCH(c)) || c == '_' || c == '.' || c == '$')
            bp = get_name();
        else if (c == '\'' || c == '"')
            bp = get_literal();
@@ -1472,8 +1636,7 @@ declare_tokens(int assoc)
        if (c == EOF)
            unexpected_EOF();
 
-       value = UNDEFINED;
-       if (isdigit(c))
+       if (isdigit(UCH(c)))
        {
            value = get_number();
            if (bp->value != UNDEFINED && value != bp->value)
@@ -1509,7 +1672,7 @@ declare_expect(int assoc)
 
     for (;;)
     {
-       if (isdigit(c))
+       if (isdigit(UCH(c)))
        {
            if (assoc == EXPECT)
                SRexpect = get_number();
@@ -1522,7 +1685,7 @@ declare_expect(int assoc)
         * Spaces, tabs, and numbers are ok,
         * words, punc., etc. are syntax errors.
         */
-       else if (c == '\n' || isalpha(c) || !isspace(c))
+       else if (c == '\n' || isalpha(UCH(c)) || !isspace(UCH(c)))
        {
            syntax_error(lineno, line, cptr);
        }
@@ -1540,14 +1703,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 != '<')
@@ -1591,7 +1754,7 @@ declare_types(void)
        c = nextc();
        if (c == EOF)
            unexpected_EOF();
-       if (isalpha(c) || c == '_' || c == '.' || c == '$')
+       if (isalpha(UCH(c)) || c == '_' || c == '.' || c == '$')
        {
            bp = get_name();
 #if defined(YYBTYACC)
@@ -1629,7 +1792,7 @@ declare_start(void)
     c = nextc();
     if (c == EOF)
        unexpected_EOF();
-    if (!isalpha(c) && c != '_' && c != '.' && c != '$')
+    if (!isalpha(UCH(c)) && c != '_' && c != '.' && c != '$')
        syntax_error(lineno, line, cptr);
     bp = get_name();
     if (bp->class == TERM)
@@ -1642,15 +1805,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 != '%')
@@ -1664,6 +1827,10 @@ read_declarations(void)
            copy_ident();
            break;
 
+       case XCODE:
+           copy_code();
+           break;
+
        case TEXT:
            copy_text();
            break;
@@ -1871,7 +2038,7 @@ parse_id(char *p, char **save)
     if (!isalpha(UCH(*p)) && *p != '_')
        return NULL;
     b = p;
-    while (isalnum(UCH(*p)) || *p == '_' || *p == '$')
+    while (IS_NAME2(UCH(*p)))
        p++;
     if (save)
     {
@@ -1973,7 +2140,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;
 
@@ -1987,6 +2154,8 @@ compile_arg(char **theptr, char *yyvaltag)
     }
     if (maxoffset > 0)
     {
+       int j;
+
        offsets = TMALLOC(Value_t, maxoffset + 1);
        NO_SPACE(offsets);
 
@@ -2076,7 +2245,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;
@@ -2096,6 +2265,8 @@ can_elide_arg(char **theptr, char *yyvaltag)
     }
     if (maxoffset > 0)
     {
+       int j;
+
        offsets = TMALLOC(Value_t, maxoffset + 1);
        NO_SPACE(offsets);
 
@@ -2129,7 +2300,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;
@@ -2149,7 +2323,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;
@@ -2213,7 +2387,6 @@ advance_to_start(void)
 {
     int c;
     bucket *bp;
-    char *s_cptr;
     int s_lineno;
 #if defined(YYBTYACC)
     char *args = NULL;
@@ -2222,12 +2395,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();
 
@@ -2245,7 +2424,7 @@ advance_to_start(void)
     }
 
     c = nextc();
-    if (!isalpha(c) && c != '_' && c != '.' && c != '_')
+    if (!isalpha(UCH(c)) && c != '_' && c != '.' && c != '_')
        syntax_error(lineno, line, cptr);
     bp = get_name();
     if (goal == 0)
@@ -2296,12 +2475,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)
@@ -2572,7 +2751,7 @@ copy_action(void)
                FREE(d_line);
                goto loop;
            }
-           else if (isdigit(c))
+           else if (isdigit(UCH(c)))
            {
                i = get_number();
                if (i == 0)
@@ -2596,7 +2775,7 @@ copy_action(void)
                goto loop;
            }
 #if defined(YYBTYACC)
-           else if (isalpha(c) || c == '_')
+           else if (isalpha(UCH(c)) || c == '_')
            {
                char *arg = scan_id();
                for (i = plhs[nrules]->args - 1; i >= 0; i--)
@@ -2727,14 +2906,14 @@ copy_action(void)
        }
     }
 #endif
-    if (isalpha(c) || c == '_' || c == '$')
+    if (IS_NAME1(c))
     {
        do
        {
            putc(c, f);
            c = *++cptr;
        }
-       while (isalnum(c) || c == '_' || c == '$');
+       while (IS_NAME2(c));
        goto loop;
     }
     ++cptr;
@@ -2923,14 +3102,14 @@ get_code(struct ainfo *a, const char *loc)
        cptr += 2;
        goto loop;
     }
-    if (isalpha(c) || c == '_' || c == '$')
+    if (IS_NAME1(c))
     {
        do
        {
            mputc(code_mstr, c);
            c = *++cptr;
        }
-       while (isalnum(c) || c == '_' || c == '$');
+       while (IS_NAME2(c));
        goto loop;
     }
     ++cptr;
@@ -2989,7 +3168,6 @@ static void
 copy_destructor(void)
 {
     char *code_text;
-    int c;
     struct ainfo a;
     bucket *bp;
 
@@ -2997,7 +3175,7 @@ copy_destructor(void)
 
     for (;;)
     {
-       c = nextc();
+       int c = nextc();
        if (c == EOF)
            unexpected_EOF();
        if (c == '<')
@@ -3049,7 +3227,7 @@ copy_destructor(void)
                    bp->destructor = process_destructor_XX(code_text, tag);
            }
        }
-       else if (isalpha(c) || c == '_' || c == '.' || c == '$')
+       else if (isalpha(UCH(c)) || c == '_' || c == '.' || c == '$')
        {                       /* "symbol" destructor */
            bp = get_name();
            if (bp->destructor != NULL)
@@ -3090,14 +3268,14 @@ process_destructor_XX(char *code, char *tag)
            msprintf(new_code, "(*val).%s", tag);
        goto loop;
     }
-    if (isalpha(c) || c == '_' || c == '$')
+    if (IS_NAME1(c))
     {
        do
        {
            mputc(new_code, c);
            c = *++codeptr;
        }
-       while (isalnum(c) || c == '_' || c == '$');
+       while (IS_NAME2(c));
        goto loop;
     }
     ++codeptr;
@@ -3180,7 +3358,7 @@ mark_symbol(void)
        syntax_error(lineno, line, cptr);
 
     c = nextc();
-    if (isalpha(c) || c == '_' || c == '.' || c == '$')
+    if (isalpha(UCH(c)) || c == '_' || c == '.' || c == '$')
        bp = get_name();
     else if (c == '\'' || c == '"')
        bp = get_literal();
@@ -3201,17 +3379,16 @@ 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(c)
+       if (isalpha(UCH(c))
            || c == '_'
            || c == '.'
            || c == '$'
@@ -3265,7 +3442,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)
@@ -3279,8 +3457,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);
@@ -3309,14 +3488,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)
        {
@@ -3527,8 +3706,6 @@ pack_grammar(void)
 {
     int i;
     Value_t j;
-    Assoc_t assoc;
-    Value_t prec2;
 
     ritem = TMALLOC(Value_t, nitems);
     NO_SPACE(ritem);
@@ -3559,6 +3736,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)
        {
@@ -3650,11 +3830,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)