[BACK]Return to reader.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / yacc

Annotation of src/usr.bin/yacc/reader.c, Revision 1.23

1.23    ! chl         1: /*     $OpenBSD: reader.c,v 1.22 2010/07/14 13:13:42 nicm Exp $        */
1.5       deraadt     2: /*     $NetBSD: reader.c,v 1.5 1996/03/19 03:21:43 jtc Exp $   */
                      3:
                      4: /*
                      5:  * Copyright (c) 1989 The Regents of the University of California.
                      6:  * All rights reserved.
                      7:  *
                      8:  * This code is derived from software contributed to Berkeley by
                      9:  * Robert Paul Corbett.
                     10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
1.14      millert    19:  * 3. Neither the name of the University nor the names of its contributors
1.5       deraadt    20:  *    may be used to endorse or promote products derived from this software
                     21:  *    without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     33:  * SUCH DAMAGE.
                     34:  */
1.1       deraadt    35:
                     36: #include "defs.h"
                     37:
                     38: /*  The line size must be a positive integer.  One hundred was chosen  */
                     39: /*  because few lines in Yacc input grammars exceed 100 characters.    */
                     40: /*  Note that if a line exceeds LINESIZE characters, the line buffer   */
1.11      todd       41: /*  will be expanded to accommodate it.                                        */
1.1       deraadt    42:
                     43: #define LINESIZE 100
                     44:
                     45: char *cache;
                     46: int cinc, cache_size;
                     47:
                     48: int ntags, tagmax;
                     49: char **tag_table;
                     50:
                     51: char saw_eof, unionized;
                     52: char *cptr, *line;
                     53: int linesize;
                     54:
                     55: bucket *goal;
                     56: int prec;
                     57: int gensym;
                     58: char last_was_action;
                     59:
                     60: int maxitems;
                     61: bucket **pitem;
                     62:
                     63: int maxrules;
                     64: bucket **plhs;
                     65:
                     66: int name_pool_size;
                     67: char *name_pool;
                     68:
1.10      millert    69: void cachec(int);
                     70: void get_line(void);
                     71: char * dup_line(void);
                     72: void skip_comment(void);
                     73: int nextc(void);
                     74: int keyword(void);
                     75: void copy_ident(void);
                     76: void copy_text(void);
                     77: void copy_union(void);
1.17      deraadt    78: int hexval(int);
1.10      millert    79: bucket * get_literal(void);
                     80: int is_reserved(char *);
                     81: bucket * get_name(void);
                     82: int get_number(void);
                     83: char * get_tag(void);
                     84: void declare_tokens(int);
                     85: void declare_types(void);
                     86: void declare_start(void);
                     87: void handle_expect(void);
                     88: void read_declarations(void);
                     89: void initialize_grammar(void);
                     90: void expand_items(void);
                     91: void expand_rules(void);
                     92: void advance_to_start(void);
                     93: void start_rule(bucket *, int);
                     94: void end_rule(void);
                     95: void insert_empty_rule(void);
                     96: void add_symbol(void);
                     97: void copy_action(void);
                     98: int mark_symbol(void);
                     99: void read_grammar(void);
                    100: void free_tags(void);
                    101: void pack_names(void);
                    102: void check_symbols(void);
                    103: void pack_symbols(void);
                    104: void pack_grammar(void);
                    105: void print_grammar(void);
1.8       pvalchev  106:
1.1       deraadt   107: char line_format[] = "#line %d \"%s\"\n";
                    108:
1.7       deraadt   109: void
1.15      pvalchev  110: cachec(int c)
1.1       deraadt   111: {
                    112:     assert(cinc >= 0);
                    113:     if (cinc >= cache_size)
                    114:     {
                    115:        cache_size += 256;
                    116:        cache = REALLOC(cache, cache_size);
1.23    ! chl       117:        if (cache == NULL) no_space();
1.1       deraadt   118:     }
                    119:     cache[cinc] = c;
                    120:     ++cinc;
                    121: }
                    122:
                    123:
1.7       deraadt   124: void
1.15      pvalchev  125: get_line(void)
1.1       deraadt   126: {
1.9       mpech     127:     FILE *f = input_file;
                    128:     int c;
                    129:     int i;
1.1       deraadt   130:
                    131:     if (saw_eof || (c = getc(f)) == EOF)
                    132:     {
                    133:        if (line) { FREE(line); line = 0; }
                    134:        cptr = 0;
                    135:        saw_eof = 1;
                    136:        return;
                    137:     }
                    138:
1.23    ! chl       139:     if (line == NULL || linesize != (LINESIZE + 1))
1.1       deraadt   140:     {
                    141:        if (line) FREE(line);
                    142:        linesize = LINESIZE + 1;
                    143:        line = MALLOC(linesize);
1.23    ! chl       144:        if (line == NULL) no_space();
1.1       deraadt   145:     }
                    146:
                    147:     i = 0;
                    148:     ++lineno;
                    149:     for (;;)
                    150:     {
                    151:        line[i]  =  c;
                    152:        if (c == '\n') { cptr = line; return; }
                    153:        if (++i >= linesize)
                    154:        {
                    155:            linesize += LINESIZE;
                    156:            line = REALLOC(line, linesize);
                    157:            if (line ==  0) no_space();
                    158:        }
                    159:        c = getc(f);
                    160:        if (c ==  EOF)
                    161:        {
                    162:            line[i] = '\n';
                    163:            saw_eof = 1;
                    164:            cptr = line;
                    165:            return;
                    166:        }
                    167:     }
                    168: }
                    169:
                    170:
                    171: char *
1.15      pvalchev  172: dup_line(void)
1.1       deraadt   173: {
1.9       mpech     174:     char *p, *s, *t;
1.1       deraadt   175:
1.23    ! chl       176:     if (line == NULL) return (0);
1.1       deraadt   177:     s = line;
                    178:     while (*s != '\n') ++s;
                    179:     p = MALLOC(s - line + 1);
1.23    ! chl       180:     if (p == NULL) no_space();
1.1       deraadt   181:
                    182:     s = line;
                    183:     t = p;
                    184:     while ((*t++ = *s++) != '\n') continue;
                    185:     return (p);
                    186: }
                    187:
                    188:
1.7       deraadt   189: void
1.15      pvalchev  190: skip_comment(void)
1.1       deraadt   191: {
1.9       mpech     192:     char *s;
1.1       deraadt   193:
                    194:     int st_lineno = lineno;
                    195:     char *st_line = dup_line();
                    196:     char *st_cptr = st_line + (cptr - line);
                    197:
                    198:     s = cptr + 2;
                    199:     for (;;)
                    200:     {
                    201:        if (*s == '*' && s[1] == '/')
                    202:        {
                    203:            cptr = s + 2;
                    204:            FREE(st_line);
                    205:            return;
                    206:        }
                    207:        if (*s == '\n')
                    208:        {
                    209:            get_line();
1.23    ! chl       210:            if (line == NULL)
1.1       deraadt   211:                unterminated_comment(st_lineno, st_line, st_cptr);
                    212:            s = cptr;
                    213:        }
                    214:        else
                    215:            ++s;
                    216:     }
                    217: }
                    218:
                    219:
                    220: int
1.15      pvalchev  221: nextc(void)
1.1       deraadt   222: {
1.9       mpech     223:     char *s;
1.1       deraadt   224:
1.23    ! chl       225:     if (line == NULL)
1.1       deraadt   226:     {
                    227:        get_line();
1.23    ! chl       228:        if (line == NULL)
1.1       deraadt   229:            return (EOF);
                    230:     }
                    231:
                    232:     s = cptr;
                    233:     for (;;)
                    234:     {
                    235:        switch (*s)
                    236:        {
                    237:        case '\n':
                    238:            get_line();
1.23    ! chl       239:            if (line == NULL) return (EOF);
1.1       deraadt   240:            s = cptr;
                    241:            break;
                    242:
                    243:        case ' ':
                    244:        case '\t':
                    245:        case '\f':
                    246:        case '\r':
                    247:        case '\v':
                    248:        case ',':
                    249:        case ';':
                    250:            ++s;
                    251:            break;
                    252:
                    253:        case '\\':
                    254:            cptr = s;
                    255:            return ('%');
                    256:
                    257:        case '/':
                    258:            if (s[1] == '*')
                    259:            {
                    260:                cptr = s;
                    261:                skip_comment();
                    262:                s = cptr;
                    263:                break;
                    264:            }
                    265:            else if (s[1] == '/')
                    266:            {
                    267:                get_line();
1.23    ! chl       268:                if (line == NULL) return (EOF);
1.1       deraadt   269:                s = cptr;
                    270:                break;
                    271:            }
                    272:            /* fall through */
                    273:
                    274:        default:
                    275:            cptr = s;
                    276:            return (*s);
                    277:        }
                    278:     }
                    279: }
                    280:
                    281:
                    282: int
1.15      pvalchev  283: keyword(void)
1.1       deraadt   284: {
1.9       mpech     285:     int c;
1.1       deraadt   286:     char *t_cptr = cptr;
                    287:
                    288:     c = *++cptr;
                    289:     if (isalpha(c))
                    290:     {
                    291:        cinc = 0;
                    292:        for (;;)
                    293:        {
                    294:            if (isalpha(c))
                    295:            {
                    296:                if (isupper(c)) c = tolower(c);
                    297:                cachec(c);
                    298:            }
                    299:            else if (isdigit(c) || c == '_' || c == '.' || c == '$')
                    300:                cachec(c);
                    301:            else
                    302:                break;
                    303:            c = *++cptr;
                    304:        }
                    305:        cachec(NUL);
                    306:
                    307:        if (strcmp(cache, "token") == 0 || strcmp(cache, "term") == 0)
                    308:            return (TOKEN);
                    309:        if (strcmp(cache, "type") == 0)
                    310:            return (TYPE);
                    311:        if (strcmp(cache, "left") == 0)
                    312:            return (LEFT);
                    313:        if (strcmp(cache, "right") == 0)
                    314:            return (RIGHT);
                    315:        if (strcmp(cache, "nonassoc") == 0 || strcmp(cache, "binary") == 0)
                    316:            return (NONASSOC);
                    317:        if (strcmp(cache, "start") == 0)
                    318:            return (START);
                    319:        if (strcmp(cache, "union") == 0)
                    320:            return (UNION);
                    321:        if (strcmp(cache, "ident") == 0)
                    322:            return (IDENT);
1.2       etheisen  323:        if (strcmp(cache, "expect") == 0)
                    324:            return (EXPECT);
1.1       deraadt   325:     }
                    326:     else
                    327:     {
                    328:        ++cptr;
                    329:        if (c == '{')
                    330:            return (TEXT);
                    331:        if (c == '%' || c == '\\')
                    332:            return (MARK);
                    333:        if (c == '<')
                    334:            return (LEFT);
                    335:        if (c == '>')
                    336:            return (RIGHT);
                    337:        if (c == '0')
                    338:            return (TOKEN);
                    339:        if (c == '2')
                    340:            return (NONASSOC);
                    341:     }
                    342:     syntax_error(lineno, line, t_cptr);
                    343:     /*NOTREACHED*/
1.8       pvalchev  344:     return (0);
1.1       deraadt   345: }
                    346:
                    347:
1.7       deraadt   348: void
1.15      pvalchev  349: copy_ident(void)
1.1       deraadt   350: {
1.9       mpech     351:     int c;
                    352:     FILE *f = output_file;
1.1       deraadt   353:
                    354:     c = nextc();
                    355:     if (c == EOF) unexpected_EOF();
                    356:     if (c != '"') syntax_error(lineno, line, cptr);
                    357:     ++outline;
                    358:     fprintf(f, "#ident \"");
                    359:     for (;;)
                    360:     {
                    361:        c = *++cptr;
                    362:        if (c == '\n')
                    363:        {
                    364:            fprintf(f, "\"\n");
                    365:            return;
                    366:        }
                    367:        putc(c, f);
                    368:        if (c == '"')
                    369:        {
                    370:            putc('\n', f);
                    371:            ++cptr;
                    372:            return;
                    373:        }
                    374:     }
                    375: }
                    376:
                    377:
1.8       pvalchev  378: void
1.15      pvalchev  379: copy_text(void)
1.1       deraadt   380: {
1.9       mpech     381:     int c;
1.1       deraadt   382:     int quote;
1.9       mpech     383:     FILE *f = text_file;
1.1       deraadt   384:     int need_newline = 0;
                    385:     int t_lineno = lineno;
                    386:     char *t_line = dup_line();
                    387:     char *t_cptr = t_line + (cptr - line - 2);
                    388:
                    389:     if (*cptr == '\n')
                    390:     {
                    391:        get_line();
1.23    ! chl       392:        if (line == NULL)
1.1       deraadt   393:            unterminated_text(t_lineno, t_line, t_cptr);
                    394:     }
                    395:     if (!lflag) fprintf(f, line_format, lineno, input_file_name);
                    396:
                    397: loop:
                    398:     c = *cptr++;
                    399:     switch (c)
                    400:     {
                    401:     case '\n':
                    402:     next_line:
                    403:        putc('\n', f);
                    404:        need_newline = 0;
                    405:        get_line();
                    406:        if (line) goto loop;
                    407:        unterminated_text(t_lineno, t_line, t_cptr);
                    408:
                    409:     case '\'':
                    410:     case '"':
                    411:        {
                    412:            int s_lineno = lineno;
                    413:            char *s_line = dup_line();
                    414:            char *s_cptr = s_line + (cptr - line - 1);
                    415:
                    416:            quote = c;
                    417:            putc(c, f);
                    418:            for (;;)
                    419:            {
                    420:                c = *cptr++;
                    421:                putc(c, f);
                    422:                if (c == quote)
                    423:                {
                    424:                    need_newline = 1;
                    425:                    FREE(s_line);
                    426:                    goto loop;
                    427:                }
                    428:                if (c == '\n')
                    429:                    unterminated_string(s_lineno, s_line, s_cptr);
                    430:                if (c == '\\')
                    431:                {
                    432:                    c = *cptr++;
                    433:                    putc(c, f);
                    434:                    if (c == '\n')
                    435:                    {
                    436:                        get_line();
1.23    ! chl       437:                        if (line == NULL)
1.1       deraadt   438:                            unterminated_string(s_lineno, s_line, s_cptr);
                    439:                    }
                    440:                }
                    441:            }
                    442:        }
                    443:
                    444:     case '/':
                    445:        putc(c, f);
                    446:        need_newline = 1;
                    447:        c = *cptr;
                    448:        if (c == '/')
                    449:        {
                    450:            putc('*', f);
                    451:            while ((c = *++cptr) != '\n')
                    452:            {
                    453:                if (c == '*' && cptr[1] == '/')
                    454:                    fprintf(f, "* ");
                    455:                else
                    456:                    putc(c, f);
                    457:            }
                    458:            fprintf(f, "*/");
                    459:            goto next_line;
                    460:        }
                    461:        if (c == '*')
                    462:        {
                    463:            int c_lineno = lineno;
                    464:            char *c_line = dup_line();
                    465:            char *c_cptr = c_line + (cptr - line - 1);
                    466:
                    467:            putc('*', f);
                    468:            ++cptr;
                    469:            for (;;)
                    470:            {
                    471:                c = *cptr++;
                    472:                putc(c, f);
                    473:                if (c == '*' && *cptr == '/')
                    474:                {
                    475:                    putc('/', f);
                    476:                    ++cptr;
                    477:                    FREE(c_line);
                    478:                    goto loop;
                    479:                }
                    480:                if (c == '\n')
                    481:                {
                    482:                    get_line();
1.23    ! chl       483:                    if (line == NULL)
1.1       deraadt   484:                        unterminated_comment(c_lineno, c_line, c_cptr);
                    485:                }
                    486:            }
                    487:        }
                    488:        need_newline = 1;
                    489:        goto loop;
                    490:
                    491:     case '%':
                    492:     case '\\':
                    493:        if (*cptr == '}')
                    494:        {
                    495:            if (need_newline) putc('\n', f);
                    496:            ++cptr;
                    497:            FREE(t_line);
                    498:            return;
                    499:        }
                    500:        /* fall through */
                    501:
                    502:     default:
                    503:        putc(c, f);
                    504:        need_newline = 1;
                    505:        goto loop;
                    506:     }
                    507: }
                    508:
                    509:
1.8       pvalchev  510: void
1.15      pvalchev  511: copy_union(void)
1.1       deraadt   512: {
1.9       mpech     513:     int c;
1.1       deraadt   514:     int quote;
                    515:     int depth;
                    516:     int u_lineno = lineno;
                    517:     char *u_line = dup_line();
                    518:     char *u_cptr = u_line + (cptr - line - 6);
                    519:
                    520:     if (unionized) over_unionized(cptr - 6);
                    521:     unionized = 1;
                    522:
                    523:     if (!lflag)
                    524:        fprintf(text_file, line_format, lineno, input_file_name);
                    525:
1.16      deraadt   526:     fprintf(text_file, "#ifndef YYSTYPE_DEFINED\n");
                    527:     fprintf(text_file, "#define YYSTYPE_DEFINED\n");
1.1       deraadt   528:     fprintf(text_file, "typedef union");
1.16      deraadt   529:     if (dflag) fprintf(union_file, "#ifndef YYSTYPE_DEFINED\n");
                    530:     if (dflag) fprintf(union_file, "#define YYSTYPE_DEFINED\n");
1.1       deraadt   531:     if (dflag) fprintf(union_file, "typedef union");
                    532:
                    533:     depth = 0;
                    534: loop:
                    535:     c = *cptr++;
                    536:     putc(c, text_file);
                    537:     if (dflag) putc(c, union_file);
                    538:     switch (c)
                    539:     {
                    540:     case '\n':
                    541:     next_line:
                    542:        get_line();
1.23    ! chl       543:        if (line == NULL) unterminated_union(u_lineno, u_line, u_cptr);
1.1       deraadt   544:        goto loop;
                    545:
                    546:     case '{':
                    547:        ++depth;
                    548:        goto loop;
                    549:
                    550:     case '}':
                    551:        if (--depth == 0)
                    552:        {
                    553:            fprintf(text_file, " YYSTYPE;\n");
1.16      deraadt   554:            fprintf(text_file, "#endif /* YYSTYPE_DEFINED */\n");
1.1       deraadt   555:            FREE(u_line);
                    556:            return;
                    557:        }
                    558:        goto loop;
                    559:
                    560:     case '\'':
                    561:     case '"':
                    562:        {
                    563:            int s_lineno = lineno;
                    564:            char *s_line = dup_line();
                    565:            char *s_cptr = s_line + (cptr - line - 1);
                    566:
                    567:            quote = c;
                    568:            for (;;)
                    569:            {
                    570:                c = *cptr++;
                    571:                putc(c, text_file);
                    572:                if (dflag) putc(c, union_file);
                    573:                if (c == quote)
                    574:                {
                    575:                    FREE(s_line);
                    576:                    goto loop;
                    577:                }
                    578:                if (c == '\n')
                    579:                    unterminated_string(s_lineno, s_line, s_cptr);
                    580:                if (c == '\\')
                    581:                {
                    582:                    c = *cptr++;
                    583:                    putc(c, text_file);
                    584:                    if (dflag) putc(c, union_file);
                    585:                    if (c == '\n')
                    586:                    {
                    587:                        get_line();
1.23    ! chl       588:                        if (line == NULL)
1.1       deraadt   589:                            unterminated_string(s_lineno, s_line, s_cptr);
                    590:                    }
                    591:                }
                    592:            }
                    593:        }
                    594:
                    595:     case '/':
                    596:        c = *cptr;
                    597:        if (c == '/')
                    598:        {
                    599:            putc('*', text_file);
                    600:            if (dflag) putc('*', union_file);
                    601:            while ((c = *++cptr) != '\n')
                    602:            {
                    603:                if (c == '*' && cptr[1] == '/')
                    604:                {
                    605:                    fprintf(text_file, "* ");
                    606:                    if (dflag) fprintf(union_file, "* ");
                    607:                }
                    608:                else
                    609:                {
                    610:                    putc(c, text_file);
                    611:                    if (dflag) putc(c, union_file);
                    612:                }
                    613:            }
                    614:            fprintf(text_file, "*/\n");
                    615:            if (dflag) fprintf(union_file, "*/\n");
                    616:            goto next_line;
                    617:        }
                    618:        if (c == '*')
                    619:        {
                    620:            int c_lineno = lineno;
                    621:            char *c_line = dup_line();
                    622:            char *c_cptr = c_line + (cptr - line - 1);
                    623:
                    624:            putc('*', text_file);
                    625:            if (dflag) putc('*', union_file);
                    626:            ++cptr;
                    627:            for (;;)
                    628:            {
                    629:                c = *cptr++;
                    630:                putc(c, text_file);
                    631:                if (dflag) putc(c, union_file);
                    632:                if (c == '*' && *cptr == '/')
                    633:                {
                    634:                    putc('/', text_file);
                    635:                    if (dflag) putc('/', union_file);
                    636:                    ++cptr;
                    637:                    FREE(c_line);
                    638:                    goto loop;
                    639:                }
                    640:                if (c == '\n')
                    641:                {
                    642:                    get_line();
1.23    ! chl       643:                    if (line == NULL)
1.1       deraadt   644:                        unterminated_comment(c_lineno, c_line, c_cptr);
                    645:                }
                    646:            }
                    647:        }
                    648:        goto loop;
                    649:
                    650:     default:
                    651:        goto loop;
                    652:     }
                    653: }
                    654:
                    655:
                    656: int
1.15      pvalchev  657: hexval(int c)
1.1       deraadt   658: {
                    659:     if (c >= '0' && c <= '9')
                    660:        return (c - '0');
                    661:     if (c >= 'A' && c <= 'F')
                    662:        return (c - 'A' + 10);
                    663:     if (c >= 'a' && c <= 'f')
                    664:        return (c - 'a' + 10);
                    665:     return (-1);
                    666: }
                    667:
                    668:
                    669: bucket *
1.15      pvalchev  670: get_literal(void)
1.1       deraadt   671: {
1.9       mpech     672:     int c, quote;
                    673:     int i;
                    674:     int n;
                    675:     char *s;
                    676:     bucket *bp;
1.1       deraadt   677:     int s_lineno = lineno;
                    678:     char *s_line = dup_line();
                    679:     char *s_cptr = s_line + (cptr - line);
                    680:
                    681:     quote = *cptr++;
                    682:     cinc = 0;
                    683:     for (;;)
                    684:     {
                    685:        c = *cptr++;
                    686:        if (c == quote) break;
                    687:        if (c == '\n') unterminated_string(s_lineno, s_line, s_cptr);
                    688:        if (c == '\\')
                    689:        {
                    690:            char *c_cptr = cptr - 1;
                    691:
                    692:            c = *cptr++;
                    693:            switch (c)
                    694:            {
                    695:            case '\n':
                    696:                get_line();
1.23    ! chl       697:                if (line == NULL) unterminated_string(s_lineno, s_line, s_cptr);
1.1       deraadt   698:                continue;
                    699:
                    700:            case '0': case '1': case '2': case '3':
                    701:            case '4': case '5': case '6': case '7':
                    702:                n = c - '0';
                    703:                c = *cptr;
                    704:                if (IS_OCTAL(c))
                    705:                {
                    706:                    n = (n << 3) + (c - '0');
                    707:                    c = *++cptr;
                    708:                    if (IS_OCTAL(c))
                    709:                    {
                    710:                        n = (n << 3) + (c - '0');
                    711:                        ++cptr;
                    712:                    }
                    713:                }
                    714:                if (n > MAXCHAR) illegal_character(c_cptr);
                    715:                c = n;
                    716:                break;
                    717:
                    718:            case 'x':
                    719:                c = *cptr++;
                    720:                n = hexval(c);
                    721:                if (n < 0 || n >= 16)
                    722:                    illegal_character(c_cptr);
                    723:                for (;;)
                    724:                {
                    725:                    c = *cptr;
                    726:                    i = hexval(c);
                    727:                    if (i < 0 || i >= 16) break;
                    728:                    ++cptr;
                    729:                    n = (n << 4) + i;
                    730:                    if (n > MAXCHAR) illegal_character(c_cptr);
                    731:                }
                    732:                c = n;
                    733:                break;
                    734:
                    735:            case 'a': c = 7; break;
                    736:            case 'b': c = '\b'; break;
                    737:            case 'f': c = '\f'; break;
                    738:            case 'n': c = '\n'; break;
                    739:            case 'r': c = '\r'; break;
                    740:            case 't': c = '\t'; break;
                    741:            case 'v': c = '\v'; break;
                    742:            }
                    743:        }
                    744:        cachec(c);
                    745:     }
                    746:     FREE(s_line);
                    747:
                    748:     n = cinc;
                    749:     s = MALLOC(n);
1.23    ! chl       750:     if (s == NULL) no_space();
1.17      deraadt   751:
1.23    ! chl       752:     memcpy(s, cache, n);
1.1       deraadt   753:
                    754:     cinc = 0;
                    755:     if (n == 1)
                    756:        cachec('\'');
                    757:     else
                    758:        cachec('"');
                    759:
                    760:     for (i = 0; i < n; ++i)
                    761:     {
                    762:        c = ((unsigned char *)s)[i];
                    763:        if (c == '\\' || c == cache[0])
                    764:        {
                    765:            cachec('\\');
                    766:            cachec(c);
                    767:        }
                    768:        else if (isprint(c))
                    769:            cachec(c);
                    770:        else
                    771:        {
                    772:            cachec('\\');
                    773:            switch (c)
                    774:            {
                    775:            case 7: cachec('a'); break;
                    776:            case '\b': cachec('b'); break;
                    777:            case '\f': cachec('f'); break;
                    778:            case '\n': cachec('n'); break;
                    779:            case '\r': cachec('r'); break;
                    780:            case '\t': cachec('t'); break;
                    781:            case '\v': cachec('v'); break;
                    782:            default:
                    783:                cachec(((c >> 6) & 7) + '0');
                    784:                cachec(((c >> 3) & 7) + '0');
                    785:                cachec((c & 7) + '0');
                    786:                break;
                    787:            }
                    788:        }
                    789:     }
                    790:
                    791:     if (n == 1)
                    792:        cachec('\'');
                    793:     else
                    794:        cachec('"');
                    795:
                    796:     cachec(NUL);
                    797:     bp = lookup(cache);
                    798:     bp->class = TERM;
                    799:     if (n == 1 && bp->value == UNDEFINED)
                    800:        bp->value = *(unsigned char *)s;
                    801:     FREE(s);
                    802:
                    803:     return (bp);
                    804: }
                    805:
                    806:
                    807: int
1.15      pvalchev  808: is_reserved(char *name)
1.1       deraadt   809: {
                    810:     char *s;
                    811:
                    812:     if (strcmp(name, ".") == 0 ||
                    813:            strcmp(name, "$accept") == 0 ||
                    814:            strcmp(name, "$end") == 0)
                    815:        return (1);
                    816:
                    817:     if (name[0] == '$' && name[1] == '$' && isdigit(name[2]))
                    818:     {
                    819:        s = name + 3;
                    820:        while (isdigit(*s)) ++s;
                    821:        if (*s == NUL) return (1);
                    822:     }
                    823:
                    824:     return (0);
                    825: }
                    826:
                    827:
                    828: bucket *
1.15      pvalchev  829: get_name(void)
1.1       deraadt   830: {
1.9       mpech     831:     int c;
1.1       deraadt   832:
                    833:     cinc = 0;
                    834:     for (c = *cptr; IS_IDENT(c); c = *++cptr)
                    835:        cachec(c);
                    836:     cachec(NUL);
                    837:
                    838:     if (is_reserved(cache)) used_reserved(cache);
                    839:
                    840:     return (lookup(cache));
                    841: }
                    842:
                    843:
                    844: int
1.15      pvalchev  845: get_number(void)
1.1       deraadt   846: {
1.9       mpech     847:     int c;
                    848:     int n;
1.1       deraadt   849:
                    850:     n = 0;
                    851:     for (c = *cptr; isdigit(c); c = *++cptr)
                    852:        n = 10*n + (c - '0');
                    853:
                    854:     return (n);
                    855: }
                    856:
                    857:
                    858: char *
1.15      pvalchev  859: get_tag(void)
1.1       deraadt   860: {
1.9       mpech     861:     int c;
                    862:     int i;
                    863:     char *s;
1.1       deraadt   864:     int t_lineno = lineno;
                    865:     char *t_line = dup_line();
                    866:     char *t_cptr = t_line + (cptr - line);
                    867:
                    868:     ++cptr;
                    869:     c = nextc();
                    870:     if (c == EOF) unexpected_EOF();
                    871:     if (!isalpha(c) && c != '_' && c != '$')
                    872:        illegal_tag(t_lineno, t_line, t_cptr);
                    873:
                    874:     cinc = 0;
                    875:     do { cachec(c); c = *++cptr; } while (IS_IDENT(c));
                    876:     cachec(NUL);
                    877:
                    878:     c = nextc();
                    879:     if (c == EOF) unexpected_EOF();
                    880:     if (c != '>')
                    881:        illegal_tag(t_lineno, t_line, t_cptr);
1.6       deraadt   882:     FREE(t_line);
1.1       deraadt   883:     ++cptr;
                    884:
                    885:     for (i = 0; i < ntags; ++i)
                    886:     {
                    887:        if (strcmp(cache, tag_table[i]) == 0)
                    888:            return (tag_table[i]);
                    889:     }
                    890:
                    891:     if (ntags >= tagmax)
                    892:     {
                    893:        tagmax += 16;
                    894:        tag_table = (char **)
                    895:                        (tag_table ? REALLOC(tag_table, tagmax*sizeof(char *))
                    896:                                   : MALLOC(tagmax*sizeof(char *)));
1.23    ! chl       897:        if (tag_table == NULL) no_space();
1.1       deraadt   898:     }
                    899:
                    900:     s = MALLOC(cinc);
1.23    ! chl       901:     if  (s == NULL) no_space();
1.13      deraadt   902:     strlcpy(s, cache, cinc);
1.1       deraadt   903:     tag_table[ntags] = s;
                    904:     ++ntags;
                    905:     return (s);
                    906: }
                    907:
                    908:
1.8       pvalchev  909: void
1.15      pvalchev  910: declare_tokens(int assoc)
1.1       deraadt   911: {
1.9       mpech     912:     int c;
                    913:     bucket *bp;
1.1       deraadt   914:     int value;
                    915:     char *tag = 0;
                    916:
                    917:     if (assoc != TOKEN) ++prec;
                    918:
                    919:     c = nextc();
                    920:     if (c == EOF) unexpected_EOF();
                    921:     if (c == '<')
                    922:     {
                    923:        tag = get_tag();
                    924:        c = nextc();
                    925:        if (c == EOF) unexpected_EOF();
                    926:     }
                    927:
                    928:     for (;;)
                    929:     {
                    930:        if (isalpha(c) || c == '_' || c == '.' || c == '$')
                    931:            bp = get_name();
                    932:        else if (c == '\'' || c == '"')
                    933:            bp = get_literal();
                    934:        else
                    935:            return;
                    936:
                    937:        if (bp == goal) tokenized_start(bp->name);
                    938:        bp->class = TERM;
                    939:
                    940:        if (tag)
                    941:        {
                    942:            if (bp->tag && tag != bp->tag)
                    943:                retyped_warning(bp->name);
                    944:            bp->tag = tag;
                    945:        }
                    946:
                    947:        if (assoc != TOKEN)
                    948:        {
                    949:            if (bp->prec && prec != bp->prec)
                    950:                reprec_warning(bp->name);
                    951:            bp->assoc = assoc;
                    952:            bp->prec = prec;
                    953:        }
                    954:
                    955:        c = nextc();
                    956:        if (c == EOF) unexpected_EOF();
                    957:        value = UNDEFINED;
                    958:        if (isdigit(c))
                    959:        {
                    960:            value = get_number();
                    961:            if (bp->value != UNDEFINED && value != bp->value)
                    962:                revalued_warning(bp->name);
                    963:            bp->value = value;
                    964:            c = nextc();
                    965:            if (c == EOF) unexpected_EOF();
                    966:        }
                    967:     }
                    968: }
                    969:
                    970:
1.4       etheisen  971: /*
                    972:  * %expect requires special handling
                    973:  * as it really isn't part of the yacc
                    974:  * grammar only a flag for yacc proper.
                    975:  */
1.8       pvalchev  976: void
1.15      pvalchev  977: declare_expect(int assoc)
1.4       etheisen  978: {
1.9       mpech     979:     int c;
1.4       etheisen  980:
                    981:     if (assoc != EXPECT) ++prec;
                    982:
                    983:     /*
                    984:      * Stay away from nextc - doesn't
                    985:      * detect EOL and will read to EOF.
                    986:      */
                    987:     c = *++cptr;
                    988:     if (c == EOF) unexpected_EOF();
                    989:
1.23    ! chl       990:     for (;;)
1.4       etheisen  991:     {
                    992:         if (isdigit(c))
                    993:         {
                    994:            SRexpect = get_number();
                    995:             break;
                    996:         }
                    997:         /*
                    998:          * Looking for number before EOL.
                    999:          * Spaces, tabs, and numbers are ok,
                   1000:          * words, punc., etc. are syntax errors.
                   1001:          */
                   1002:         else if (c == '\n' || isalpha(c) || !isspace(c))
                   1003:         {
                   1004:             syntax_error(lineno, line, cptr);
                   1005:         }
                   1006:         else
                   1007:         {
                   1008:             c = *++cptr;
                   1009:             if (c == EOF) unexpected_EOF();
                   1010:         }
                   1011:     }
                   1012: }
                   1013:
                   1014:
1.8       pvalchev 1015: void
1.15      pvalchev 1016: declare_types(void)
1.1       deraadt  1017: {
1.9       mpech    1018:     int c;
                   1019:     bucket *bp;
1.1       deraadt  1020:     char *tag;
                   1021:
                   1022:     c = nextc();
                   1023:     if (c == EOF) unexpected_EOF();
                   1024:     if (c != '<') syntax_error(lineno, line, cptr);
                   1025:     tag = get_tag();
                   1026:
                   1027:     for (;;)
                   1028:     {
                   1029:        c = nextc();
                   1030:        if (isalpha(c) || c == '_' || c == '.' || c == '$')
                   1031:            bp = get_name();
                   1032:        else if (c == '\'' || c == '"')
                   1033:            bp = get_literal();
                   1034:        else
                   1035:            return;
                   1036:
                   1037:        if (bp->tag && tag != bp->tag)
                   1038:            retyped_warning(bp->name);
                   1039:        bp->tag = tag;
                   1040:     }
                   1041: }
                   1042:
                   1043:
1.8       pvalchev 1044: void
1.15      pvalchev 1045: declare_start(void)
1.1       deraadt  1046: {
1.9       mpech    1047:     int c;
                   1048:     bucket *bp;
1.1       deraadt  1049:
                   1050:     c = nextc();
                   1051:     if (c == EOF) unexpected_EOF();
                   1052:     if (!isalpha(c) && c != '_' && c != '.' && c != '$')
                   1053:        syntax_error(lineno, line, cptr);
                   1054:     bp = get_name();
                   1055:     if (bp->class == TERM)
                   1056:        terminal_start(bp->name);
                   1057:     if (goal && goal != bp)
                   1058:        restarted_warning();
                   1059:     goal = bp;
                   1060: }
                   1061:
                   1062:
1.8       pvalchev 1063: void
1.15      pvalchev 1064: read_declarations(void)
1.1       deraadt  1065: {
1.9       mpech    1066:     int c, k;
1.1       deraadt  1067:
                   1068:     cache_size = 256;
                   1069:     cache = MALLOC(cache_size);
1.23    ! chl      1070:     if (cache == NULL) no_space();
1.1       deraadt  1071:
                   1072:     for (;;)
                   1073:     {
                   1074:        c = nextc();
                   1075:        if (c == EOF) unexpected_EOF();
                   1076:        if (c != '%') syntax_error(lineno, line, cptr);
                   1077:        switch (k = keyword())
                   1078:        {
                   1079:        case MARK:
                   1080:            return;
                   1081:
                   1082:        case IDENT:
                   1083:            copy_ident();
                   1084:            break;
                   1085:
                   1086:        case TEXT:
                   1087:            copy_text();
                   1088:            break;
                   1089:
                   1090:        case UNION:
                   1091:            copy_union();
                   1092:            break;
                   1093:
                   1094:        case TOKEN:
                   1095:        case LEFT:
                   1096:        case RIGHT:
                   1097:        case NONASSOC:
                   1098:            declare_tokens(k);
                   1099:            break;
1.2       etheisen 1100:
1.4       etheisen 1101:        case EXPECT:
                   1102:            declare_expect(k);
                   1103:             break;
                   1104:
1.1       deraadt  1105:        case TYPE:
                   1106:            declare_types();
                   1107:            break;
                   1108:
                   1109:        case START:
                   1110:            declare_start();
                   1111:            break;
                   1112:        }
                   1113:     }
                   1114: }
                   1115:
                   1116:
1.8       pvalchev 1117: void
1.15      pvalchev 1118: initialize_grammar(void)
1.1       deraadt  1119: {
                   1120:     nitems = 4;
                   1121:     maxitems = 300;
1.22      nicm     1122:     pitem = (bucket **) CALLOC(maxitems, sizeof(bucket *));
1.23    ! chl      1123:     if (pitem == NULL) no_space();
1.1       deraadt  1124:
                   1125:     nrules = 3;
                   1126:     maxrules = 100;
                   1127:     plhs = (bucket **) MALLOC(maxrules*sizeof(bucket *));
1.23    ! chl      1128:     if (plhs == NULL) no_space();
1.1       deraadt  1129:     plhs[0] = 0;
                   1130:     plhs[1] = 0;
                   1131:     plhs[2] = 0;
                   1132:     rprec = (short *) MALLOC(maxrules*sizeof(short));
1.23    ! chl      1133:     if (rprec == NULL) no_space();
1.1       deraadt  1134:     rprec[0] = 0;
                   1135:     rprec[1] = 0;
                   1136:     rprec[2] = 0;
                   1137:     rassoc = (char *) MALLOC(maxrules*sizeof(char));
1.23    ! chl      1138:     if (rassoc == NULL) no_space();
1.1       deraadt  1139:     rassoc[0] = TOKEN;
                   1140:     rassoc[1] = TOKEN;
                   1141:     rassoc[2] = TOKEN;
                   1142: }
                   1143:
                   1144:
1.8       pvalchev 1145: void
1.15      pvalchev 1146: expand_items(void)
1.1       deraadt  1147: {
1.22      nicm     1148:     int olditems = maxitems;
1.1       deraadt  1149:     maxitems += 300;
                   1150:     pitem = (bucket **) REALLOC(pitem, maxitems*sizeof(bucket *));
1.23    ! chl      1151:     if (pitem == NULL) no_space();
1.22      nicm     1152:     memset(pitem + olditems, 0, (maxitems - olditems)*sizeof(bucket *));
1.1       deraadt  1153: }
                   1154:
                   1155:
1.8       pvalchev 1156: void
1.15      pvalchev 1157: expand_rules(void)
1.1       deraadt  1158: {
                   1159:     maxrules += 100;
                   1160:     plhs = (bucket **) REALLOC(plhs, maxrules*sizeof(bucket *));
1.23    ! chl      1161:     if (plhs == NULL) no_space();
1.1       deraadt  1162:     rprec = (short *) REALLOC(rprec, maxrules*sizeof(short));
1.23    ! chl      1163:     if (rprec == NULL) no_space();
1.1       deraadt  1164:     rassoc = (char *) REALLOC(rassoc, maxrules*sizeof(char));
1.23    ! chl      1165:     if (rassoc == NULL) no_space();
1.1       deraadt  1166: }
                   1167:
                   1168:
1.8       pvalchev 1169: void
1.15      pvalchev 1170: advance_to_start(void)
1.1       deraadt  1171: {
1.9       mpech    1172:     int c;
                   1173:     bucket *bp;
1.1       deraadt  1174:     char *s_cptr;
                   1175:     int s_lineno;
                   1176:
                   1177:     for (;;)
                   1178:     {
                   1179:        c = nextc();
                   1180:        if (c != '%') break;
                   1181:        s_cptr = cptr;
                   1182:        switch (keyword())
                   1183:        {
                   1184:        case MARK:
                   1185:            no_grammar();
                   1186:
                   1187:        case TEXT:
                   1188:            copy_text();
                   1189:            break;
                   1190:
                   1191:        case START:
                   1192:            declare_start();
                   1193:            break;
                   1194:
                   1195:        default:
                   1196:            syntax_error(lineno, line, s_cptr);
                   1197:        }
                   1198:     }
                   1199:
                   1200:     c = nextc();
                   1201:     if (!isalpha(c) && c != '_' && c != '.' && c != '_')
                   1202:        syntax_error(lineno, line, cptr);
                   1203:     bp = get_name();
1.23    ! chl      1204:     if (goal == NULL)
1.1       deraadt  1205:     {
                   1206:        if (bp->class == TERM)
                   1207:            terminal_start(bp->name);
                   1208:        goal = bp;
                   1209:     }
                   1210:
                   1211:     s_lineno = lineno;
                   1212:     c = nextc();
                   1213:     if (c == EOF) unexpected_EOF();
                   1214:     if (c != ':') syntax_error(lineno, line, cptr);
                   1215:     start_rule(bp, s_lineno);
                   1216:     ++cptr;
                   1217: }
                   1218:
                   1219:
1.8       pvalchev 1220: void
1.15      pvalchev 1221: start_rule(bucket *bp, int s_lineno)
1.1       deraadt  1222: {
                   1223:     if (bp->class == TERM)
                   1224:        terminal_lhs(s_lineno);
                   1225:     bp->class = NONTERM;
                   1226:     if (nrules >= maxrules)
                   1227:        expand_rules();
                   1228:     plhs[nrules] = bp;
                   1229:     rprec[nrules] = UNDEFINED;
                   1230:     rassoc[nrules] = TOKEN;
                   1231: }
                   1232:
                   1233:
1.8       pvalchev 1234: void
1.15      pvalchev 1235: end_rule(void)
1.1       deraadt  1236: {
1.9       mpech    1237:     int i;
1.1       deraadt  1238:
                   1239:     if (!last_was_action && plhs[nrules]->tag)
                   1240:     {
                   1241:        for (i = nitems - 1; pitem[i]; --i) continue;
1.22      nicm     1242:        if (i == maxitems - 1 || pitem[i+1] == 0 ||
                   1243:            pitem[i+1]->tag != plhs[nrules]->tag)
1.1       deraadt  1244:            default_action_warning();
                   1245:     }
                   1246:
                   1247:     last_was_action = 0;
                   1248:     if (nitems >= maxitems) expand_items();
                   1249:     pitem[nitems] = 0;
                   1250:     ++nitems;
                   1251:     ++nrules;
                   1252: }
                   1253:
                   1254:
1.8       pvalchev 1255: void
1.15      pvalchev 1256: insert_empty_rule(void)
1.1       deraadt  1257: {
1.9       mpech    1258:     bucket *bp, **bpp;
1.1       deraadt  1259:
                   1260:     assert(cache);
1.12      deraadt  1261:     snprintf(cache, cache_size, "$$%d", ++gensym);
1.1       deraadt  1262:     bp = make_bucket(cache);
                   1263:     last_symbol->next = bp;
                   1264:     last_symbol = bp;
                   1265:     bp->tag = plhs[nrules]->tag;
                   1266:     bp->class = NONTERM;
                   1267:
                   1268:     if ((nitems += 2) > maxitems)
                   1269:        expand_items();
                   1270:     bpp = pitem + nitems - 1;
                   1271:     *bpp-- = bp;
1.8       pvalchev 1272:     while ((bpp[0] = bpp[-1])) --bpp;
1.1       deraadt  1273:
                   1274:     if (++nrules >= maxrules)
                   1275:        expand_rules();
                   1276:     plhs[nrules] = plhs[nrules-1];
                   1277:     plhs[nrules-1] = bp;
                   1278:     rprec[nrules] = rprec[nrules-1];
                   1279:     rprec[nrules-1] = 0;
                   1280:     rassoc[nrules] = rassoc[nrules-1];
                   1281:     rassoc[nrules-1] = TOKEN;
                   1282: }
                   1283:
                   1284:
1.8       pvalchev 1285: void
1.15      pvalchev 1286: add_symbol(void)
1.1       deraadt  1287: {
1.9       mpech    1288:     int c;
                   1289:     bucket *bp;
1.1       deraadt  1290:     int s_lineno = lineno;
                   1291:
                   1292:     c = *cptr;
                   1293:     if (c == '\'' || c == '"')
                   1294:        bp = get_literal();
                   1295:     else
                   1296:        bp = get_name();
                   1297:
                   1298:     c = nextc();
                   1299:     if (c == ':')
                   1300:     {
                   1301:        end_rule();
                   1302:        start_rule(bp, s_lineno);
                   1303:        ++cptr;
                   1304:        return;
                   1305:     }
                   1306:
                   1307:     if (last_was_action)
                   1308:        insert_empty_rule();
                   1309:     last_was_action = 0;
                   1310:
                   1311:     if (++nitems > maxitems)
                   1312:        expand_items();
                   1313:     pitem[nitems-1] = bp;
                   1314: }
                   1315:
                   1316:
1.8       pvalchev 1317: void
1.15      pvalchev 1318: copy_action(void)
1.1       deraadt  1319: {
1.9       mpech    1320:     int c;
                   1321:     int i, n;
1.1       deraadt  1322:     int depth;
                   1323:     int quote;
                   1324:     char *tag;
1.9       mpech    1325:     FILE *f = action_file;
1.1       deraadt  1326:     int a_lineno = lineno;
                   1327:     char *a_line = dup_line();
                   1328:     char *a_cptr = a_line + (cptr - line);
                   1329:
                   1330:     if (last_was_action)
                   1331:        insert_empty_rule();
                   1332:     last_was_action = 1;
                   1333:
                   1334:     fprintf(f, "case %d:\n", nrules - 2);
                   1335:     if (!lflag)
                   1336:        fprintf(f, line_format, lineno, input_file_name);
                   1337:     if (*cptr == '=') ++cptr;
                   1338:
                   1339:     n = 0;
                   1340:     for (i = nitems - 1; pitem[i]; --i) ++n;
                   1341:
                   1342:     depth = 0;
                   1343: loop:
                   1344:     c = *cptr;
                   1345:     if (c == '$')
                   1346:     {
                   1347:        if (cptr[1] == '<')
                   1348:        {
                   1349:            int d_lineno = lineno;
                   1350:            char *d_line = dup_line();
                   1351:            char *d_cptr = d_line + (cptr - line);
                   1352:
                   1353:            ++cptr;
                   1354:            tag = get_tag();
                   1355:            c = *cptr;
                   1356:            if (c == '$')
                   1357:            {
                   1358:                fprintf(f, "yyval.%s", tag);
                   1359:                ++cptr;
                   1360:                FREE(d_line);
                   1361:                goto loop;
                   1362:            }
                   1363:            else if (isdigit(c))
                   1364:            {
                   1365:                i = get_number();
                   1366:                if (i > n) dollar_warning(d_lineno, i);
                   1367:                fprintf(f, "yyvsp[%d].%s", i - n, tag);
                   1368:                FREE(d_line);
                   1369:                goto loop;
                   1370:            }
                   1371:            else if (c == '-' && isdigit(cptr[1]))
                   1372:            {
                   1373:                ++cptr;
                   1374:                i = -get_number() - n;
                   1375:                fprintf(f, "yyvsp[%d].%s", i, tag);
                   1376:                FREE(d_line);
                   1377:                goto loop;
                   1378:            }
                   1379:            else
                   1380:                dollar_error(d_lineno, d_line, d_cptr);
                   1381:        }
                   1382:        else if (cptr[1] == '$')
                   1383:        {
                   1384:            if (ntags)
                   1385:            {
                   1386:                tag = plhs[nrules]->tag;
1.23    ! chl      1387:                if (tag == NULL) untyped_lhs();
1.1       deraadt  1388:                fprintf(f, "yyval.%s", tag);
                   1389:            }
                   1390:            else
                   1391:                fprintf(f, "yyval");
                   1392:            cptr += 2;
                   1393:            goto loop;
                   1394:        }
                   1395:        else if (isdigit(cptr[1]))
                   1396:        {
                   1397:            ++cptr;
                   1398:            i = get_number();
                   1399:            if (ntags)
                   1400:            {
                   1401:                if (i <= 0 || i > n)
                   1402:                    unknown_rhs(i);
                   1403:                tag = pitem[nitems + i - n - 1]->tag;
1.23    ! chl      1404:                if (tag == NULL) untyped_rhs(i, pitem[nitems + i - n - 1]->name);
1.1       deraadt  1405:                fprintf(f, "yyvsp[%d].%s", i - n, tag);
                   1406:            }
                   1407:            else
                   1408:            {
                   1409:                if (i > n)
                   1410:                    dollar_warning(lineno, i);
                   1411:                fprintf(f, "yyvsp[%d]", i - n);
                   1412:            }
                   1413:            goto loop;
                   1414:        }
                   1415:        else if (cptr[1] == '-')
                   1416:        {
                   1417:            cptr += 2;
                   1418:            i = get_number();
                   1419:            if (ntags)
                   1420:                unknown_rhs(-i);
                   1421:            fprintf(f, "yyvsp[%d]", -i - n);
                   1422:            goto loop;
                   1423:        }
                   1424:     }
                   1425:     if (isalpha(c) || c == '_' || c == '$')
                   1426:     {
                   1427:        do
                   1428:        {
                   1429:            putc(c, f);
                   1430:            c = *++cptr;
                   1431:        } while (isalnum(c) || c == '_' || c == '$');
                   1432:        goto loop;
                   1433:     }
                   1434:     putc(c, f);
                   1435:     ++cptr;
                   1436:     switch (c)
                   1437:     {
                   1438:     case '\n':
                   1439:     next_line:
                   1440:        get_line();
                   1441:        if (line) goto loop;
                   1442:        unterminated_action(a_lineno, a_line, a_cptr);
                   1443:
                   1444:     case ';':
                   1445:        if (depth > 0) goto loop;
                   1446:        fprintf(f, "\nbreak;\n");
1.6       deraadt  1447:        FREE(a_line);
1.1       deraadt  1448:        return;
                   1449:
                   1450:     case '{':
                   1451:        ++depth;
                   1452:        goto loop;
                   1453:
                   1454:     case '}':
                   1455:        if (--depth > 0) goto loop;
                   1456:        fprintf(f, "\nbreak;\n");
1.6       deraadt  1457:        FREE(a_line);
1.1       deraadt  1458:        return;
                   1459:
                   1460:     case '\'':
                   1461:     case '"':
                   1462:        {
                   1463:            int s_lineno = lineno;
                   1464:            char *s_line = dup_line();
                   1465:            char *s_cptr = s_line + (cptr - line - 1);
                   1466:
                   1467:            quote = c;
                   1468:            for (;;)
                   1469:            {
                   1470:                c = *cptr++;
                   1471:                putc(c, f);
                   1472:                if (c == quote)
                   1473:                {
                   1474:                    FREE(s_line);
                   1475:                    goto loop;
                   1476:                }
                   1477:                if (c == '\n')
                   1478:                    unterminated_string(s_lineno, s_line, s_cptr);
                   1479:                if (c == '\\')
                   1480:                {
                   1481:                    c = *cptr++;
                   1482:                    putc(c, f);
                   1483:                    if (c == '\n')
                   1484:                    {
                   1485:                        get_line();
1.23    ! chl      1486:                        if (line == NULL)
1.1       deraadt  1487:                            unterminated_string(s_lineno, s_line, s_cptr);
                   1488:                    }
                   1489:                }
                   1490:            }
                   1491:        }
                   1492:
                   1493:     case '/':
                   1494:        c = *cptr;
                   1495:        if (c == '/')
                   1496:        {
                   1497:            putc('*', f);
                   1498:            while ((c = *++cptr) != '\n')
                   1499:            {
                   1500:                if (c == '*' && cptr[1] == '/')
                   1501:                    fprintf(f, "* ");
                   1502:                else
                   1503:                    putc(c, f);
                   1504:            }
                   1505:            fprintf(f, "*/\n");
                   1506:            goto next_line;
                   1507:        }
                   1508:        if (c == '*')
                   1509:        {
                   1510:            int c_lineno = lineno;
                   1511:            char *c_line = dup_line();
                   1512:            char *c_cptr = c_line + (cptr - line - 1);
                   1513:
                   1514:            putc('*', f);
                   1515:            ++cptr;
                   1516:            for (;;)
                   1517:            {
                   1518:                c = *cptr++;
                   1519:                putc(c, f);
                   1520:                if (c == '*' && *cptr == '/')
                   1521:                {
                   1522:                    putc('/', f);
                   1523:                    ++cptr;
                   1524:                    FREE(c_line);
                   1525:                    goto loop;
                   1526:                }
                   1527:                if (c == '\n')
                   1528:                {
                   1529:                    get_line();
1.23    ! chl      1530:                    if (line == NULL)
1.1       deraadt  1531:                        unterminated_comment(c_lineno, c_line, c_cptr);
                   1532:                }
                   1533:            }
                   1534:        }
                   1535:        goto loop;
                   1536:
                   1537:     default:
                   1538:        goto loop;
                   1539:     }
                   1540: }
                   1541:
                   1542:
                   1543: int
1.15      pvalchev 1544: mark_symbol(void)
1.1       deraadt  1545: {
1.9       mpech    1546:     int c;
1.18      pvalchev 1547:     bucket *bp = NULL;
1.1       deraadt  1548:
                   1549:     c = cptr[1];
                   1550:     if (c == '%' || c == '\\')
                   1551:     {
                   1552:        cptr += 2;
                   1553:        return (1);
                   1554:     }
                   1555:
                   1556:     if (c == '=')
                   1557:        cptr += 2;
                   1558:     else if ((c == 'p' || c == 'P') &&
                   1559:             ((c = cptr[2]) == 'r' || c == 'R') &&
                   1560:             ((c = cptr[3]) == 'e' || c == 'E') &&
                   1561:             ((c = cptr[4]) == 'c' || c == 'C') &&
                   1562:             ((c = cptr[5], !IS_IDENT(c))))
                   1563:        cptr += 5;
                   1564:     else
                   1565:        syntax_error(lineno, line, cptr);
                   1566:
                   1567:     c = nextc();
                   1568:     if (isalpha(c) || c == '_' || c == '.' || c == '$')
                   1569:        bp = get_name();
                   1570:     else if (c == '\'' || c == '"')
                   1571:        bp = get_literal();
                   1572:     else
                   1573:     {
                   1574:        syntax_error(lineno, line, cptr);
                   1575:        /*NOTREACHED*/
                   1576:     }
                   1577:
                   1578:     if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
                   1579:        prec_redeclared();
                   1580:
                   1581:     rprec[nrules] = bp->prec;
                   1582:     rassoc[nrules] = bp->assoc;
                   1583:     return (0);
                   1584: }
                   1585:
                   1586:
1.8       pvalchev 1587: void
1.15      pvalchev 1588: read_grammar(void)
1.1       deraadt  1589: {
1.9       mpech    1590:     int c;
1.1       deraadt  1591:
                   1592:     initialize_grammar();
                   1593:     advance_to_start();
                   1594:
                   1595:     for (;;)
                   1596:     {
                   1597:        c = nextc();
                   1598:        if (c == EOF) break;
                   1599:        if (isalpha(c) || c == '_' || c == '.' || c == '$' || c == '\'' ||
                   1600:                c == '"')
                   1601:            add_symbol();
                   1602:        else if (c == '{' || c == '=')
                   1603:            copy_action();
                   1604:        else if (c == '|')
                   1605:        {
                   1606:            end_rule();
                   1607:            start_rule(plhs[nrules-1], 0);
                   1608:            ++cptr;
                   1609:        }
                   1610:        else if (c == '%')
                   1611:        {
                   1612:            if (mark_symbol()) break;
                   1613:        }
                   1614:        else
                   1615:            syntax_error(lineno, line, cptr);
                   1616:     }
                   1617:     end_rule();
                   1618: }
                   1619:
                   1620:
1.8       pvalchev 1621: void
1.15      pvalchev 1622: free_tags(void)
1.1       deraadt  1623: {
1.9       mpech    1624:     int i;
1.1       deraadt  1625:
1.23    ! chl      1626:     if (tag_table == NULL) return;
1.1       deraadt  1627:
                   1628:     for (i = 0; i < ntags; ++i)
                   1629:     {
                   1630:        assert(tag_table[i]);
                   1631:        FREE(tag_table[i]);
                   1632:     }
                   1633:     FREE(tag_table);
                   1634: }
                   1635:
                   1636:
1.8       pvalchev 1637: void
1.15      pvalchev 1638: pack_names(void)
1.1       deraadt  1639: {
1.9       mpech    1640:     bucket *bp;
                   1641:     char *p, *s, *t;
1.1       deraadt  1642:
                   1643:     name_pool_size = 13;  /* 13 == sizeof("$end") + sizeof("$accept") */
                   1644:     for (bp = first_symbol; bp; bp = bp->next)
                   1645:        name_pool_size += strlen(bp->name) + 1;
                   1646:     name_pool = MALLOC(name_pool_size);
1.23    ! chl      1647:     if (name_pool == NULL) no_space();
1.1       deraadt  1648:
1.13      deraadt  1649:     strlcpy(name_pool, "$accept", name_pool_size);
                   1650:     strlcpy(name_pool+8, "$end", name_pool_size - 8);
1.1       deraadt  1651:     t = name_pool + 13;
                   1652:     for (bp = first_symbol; bp; bp = bp->next)
                   1653:     {
                   1654:        p = t;
                   1655:        s = bp->name;
1.8       pvalchev 1656:        while ((*t++ = *s++)) continue;
1.1       deraadt  1657:        FREE(bp->name);
                   1658:        bp->name = p;
                   1659:     }
                   1660: }
                   1661:
                   1662:
1.8       pvalchev 1663: void
1.15      pvalchev 1664: check_symbols(void)
1.1       deraadt  1665: {
1.9       mpech    1666:     bucket *bp;
1.1       deraadt  1667:
                   1668:     if (goal->class == UNKNOWN)
                   1669:        undefined_goal(goal->name);
                   1670:
                   1671:     for (bp = first_symbol; bp; bp = bp->next)
                   1672:     {
                   1673:        if (bp->class == UNKNOWN)
                   1674:        {
                   1675:            undefined_symbol_warning(bp->name);
                   1676:            bp->class = TERM;
                   1677:        }
                   1678:     }
                   1679: }
                   1680:
                   1681:
1.8       pvalchev 1682: void
1.15      pvalchev 1683: pack_symbols(void)
1.1       deraadt  1684: {
1.9       mpech    1685:     bucket *bp;
                   1686:     bucket **v;
                   1687:     int i, j, k, n;
1.1       deraadt  1688:
                   1689:     nsyms = 2;
                   1690:     ntokens = 1;
                   1691:     for (bp = first_symbol; bp; bp = bp->next)
                   1692:     {
                   1693:        ++nsyms;
                   1694:        if (bp->class == TERM) ++ntokens;
                   1695:     }
                   1696:     start_symbol = ntokens;
                   1697:     nvars = nsyms - ntokens;
                   1698:
                   1699:     symbol_name = (char **) MALLOC(nsyms*sizeof(char *));
1.23    ! chl      1700:     if (symbol_name == NULL) no_space();
1.1       deraadt  1701:     symbol_value = (short *) MALLOC(nsyms*sizeof(short));
1.23    ! chl      1702:     if (symbol_value == NULL) no_space();
1.1       deraadt  1703:     symbol_prec = (short *) MALLOC(nsyms*sizeof(short));
1.23    ! chl      1704:     if (symbol_prec == NULL) no_space();
1.1       deraadt  1705:     symbol_assoc = MALLOC(nsyms);
1.23    ! chl      1706:     if (symbol_assoc == NULL) no_space();
1.1       deraadt  1707:
                   1708:     v = (bucket **) MALLOC(nsyms*sizeof(bucket *));
1.23    ! chl      1709:     if (v == NULL) no_space();
1.1       deraadt  1710:
                   1711:     v[0] = 0;
                   1712:     v[start_symbol] = 0;
                   1713:
                   1714:     i = 1;
                   1715:     j = start_symbol + 1;
                   1716:     for (bp = first_symbol; bp; bp = bp->next)
                   1717:     {
                   1718:        if (bp->class == TERM)
                   1719:            v[i++] = bp;
                   1720:        else
                   1721:            v[j++] = bp;
                   1722:     }
                   1723:     assert(i == ntokens && j == nsyms);
                   1724:
                   1725:     for (i = 1; i < ntokens; ++i)
                   1726:        v[i]->index = i;
                   1727:
                   1728:     goal->index = start_symbol + 1;
                   1729:     k = start_symbol + 2;
                   1730:     while (++i < nsyms)
                   1731:        if (v[i] != goal)
                   1732:        {
                   1733:            v[i]->index = k;
                   1734:            ++k;
                   1735:        }
                   1736:
                   1737:     goal->value = 0;
                   1738:     k = 1;
                   1739:     for (i = start_symbol + 1; i < nsyms; ++i)
                   1740:     {
                   1741:        if (v[i] != goal)
                   1742:        {
                   1743:            v[i]->value = k;
                   1744:            ++k;
                   1745:        }
                   1746:     }
                   1747:
                   1748:     k = 0;
                   1749:     for (i = 1; i < ntokens; ++i)
                   1750:     {
                   1751:        n = v[i]->value;
                   1752:        if (n > 256)
                   1753:        {
                   1754:            for (j = k++; j > 0 && symbol_value[j-1] > n; --j)
                   1755:                symbol_value[j] = symbol_value[j-1];
                   1756:            symbol_value[j] = n;
                   1757:        }
                   1758:     }
                   1759:
                   1760:     if (v[1]->value == UNDEFINED)
                   1761:        v[1]->value = 256;
                   1762:
                   1763:     j = 0;
                   1764:     n = 257;
                   1765:     for (i = 2; i < ntokens; ++i)
                   1766:     {
                   1767:        if (v[i]->value == UNDEFINED)
                   1768:        {
                   1769:            while (j < k && n == symbol_value[j])
                   1770:            {
                   1771:                while (++j < k && n == symbol_value[j]) continue;
                   1772:                ++n;
                   1773:            }
                   1774:            v[i]->value = n;
                   1775:            ++n;
                   1776:        }
                   1777:     }
                   1778:
                   1779:     symbol_name[0] = name_pool + 8;
                   1780:     symbol_value[0] = 0;
                   1781:     symbol_prec[0] = 0;
                   1782:     symbol_assoc[0] = TOKEN;
                   1783:     for (i = 1; i < ntokens; ++i)
                   1784:     {
                   1785:        symbol_name[i] = v[i]->name;
                   1786:        symbol_value[i] = v[i]->value;
                   1787:        symbol_prec[i] = v[i]->prec;
                   1788:        symbol_assoc[i] = v[i]->assoc;
                   1789:     }
                   1790:     symbol_name[start_symbol] = name_pool;
                   1791:     symbol_value[start_symbol] = -1;
                   1792:     symbol_prec[start_symbol] = 0;
                   1793:     symbol_assoc[start_symbol] = TOKEN;
                   1794:     for (++i; i < nsyms; ++i)
                   1795:     {
                   1796:        k = v[i]->index;
                   1797:        symbol_name[k] = v[i]->name;
                   1798:        symbol_value[k] = v[i]->value;
                   1799:        symbol_prec[k] = v[i]->prec;
                   1800:        symbol_assoc[k] = v[i]->assoc;
                   1801:     }
                   1802:
                   1803:     FREE(v);
                   1804: }
                   1805:
                   1806:
1.8       pvalchev 1807: void
1.15      pvalchev 1808: pack_grammar(void)
1.1       deraadt  1809: {
1.9       mpech    1810:     int i, j;
1.1       deraadt  1811:     int assoc, prec;
                   1812:
                   1813:     ritem = (short *) MALLOC(nitems*sizeof(short));
1.23    ! chl      1814:     if (ritem == NULL) no_space();
1.1       deraadt  1815:     rlhs = (short *) MALLOC(nrules*sizeof(short));
1.23    ! chl      1816:     if (rlhs == NULL) no_space();
1.1       deraadt  1817:     rrhs = (short *) MALLOC((nrules+1)*sizeof(short));
1.23    ! chl      1818:     if (rrhs == NULL) no_space();
1.1       deraadt  1819:     rprec = (short *) REALLOC(rprec, nrules*sizeof(short));
1.23    ! chl      1820:     if (rprec == NULL) no_space();
1.1       deraadt  1821:     rassoc = REALLOC(rassoc, nrules);
1.23    ! chl      1822:     if (rassoc == NULL) no_space();
1.1       deraadt  1823:
                   1824:     ritem[0] = -1;
                   1825:     ritem[1] = goal->index;
                   1826:     ritem[2] = 0;
                   1827:     ritem[3] = -2;
                   1828:     rlhs[0] = 0;
                   1829:     rlhs[1] = 0;
                   1830:     rlhs[2] = start_symbol;
                   1831:     rrhs[0] = 0;
                   1832:     rrhs[1] = 0;
                   1833:     rrhs[2] = 1;
                   1834:
                   1835:     j = 4;
                   1836:     for (i = 3; i < nrules; ++i)
                   1837:     {
                   1838:        rlhs[i] = plhs[i]->index;
                   1839:        rrhs[i] = j;
                   1840:        assoc = TOKEN;
                   1841:        prec = 0;
                   1842:        while (pitem[j])
                   1843:        {
                   1844:            ritem[j] = pitem[j]->index;
                   1845:            if (pitem[j]->class == TERM)
                   1846:            {
                   1847:                prec = pitem[j]->prec;
                   1848:                assoc = pitem[j]->assoc;
                   1849:            }
                   1850:            ++j;
                   1851:        }
                   1852:        ritem[j] = -i;
                   1853:        ++j;
                   1854:        if (rprec[i] == UNDEFINED)
                   1855:        {
                   1856:            rprec[i] = prec;
                   1857:            rassoc[i] = assoc;
                   1858:        }
                   1859:     }
                   1860:     rrhs[i] = j;
                   1861:
                   1862:     FREE(plhs);
                   1863:     FREE(pitem);
                   1864: }
                   1865:
                   1866:
1.8       pvalchev 1867: void
1.15      pvalchev 1868: print_grammar(void)
1.1       deraadt  1869: {
1.9       mpech    1870:     int i, j, k;
1.18      pvalchev 1871:     int spacing = 0;
1.9       mpech    1872:     FILE *f = verbose_file;
1.1       deraadt  1873:
                   1874:     if (!vflag) return;
                   1875:
                   1876:     k = 1;
                   1877:     for (i = 2; i < nrules; ++i)
                   1878:     {
                   1879:        if (rlhs[i] != rlhs[i-1])
                   1880:        {
                   1881:            if (i != 2) fprintf(f, "\n");
                   1882:            fprintf(f, "%4d  %s :", i - 2, symbol_name[rlhs[i]]);
                   1883:            spacing = strlen(symbol_name[rlhs[i]]) + 1;
                   1884:        }
                   1885:        else
                   1886:        {
                   1887:            fprintf(f, "%4d  ", i - 2);
                   1888:            j = spacing;
                   1889:            while (--j >= 0) putc(' ', f);
                   1890:            putc('|', f);
                   1891:        }
                   1892:
                   1893:        while (ritem[k] >= 0)
                   1894:        {
                   1895:            fprintf(f, " %s", symbol_name[ritem[k]]);
                   1896:            ++k;
                   1897:        }
                   1898:        ++k;
                   1899:        putc('\n', f);
                   1900:     }
                   1901: }
                   1902:
                   1903:
1.8       pvalchev 1904: void
1.15      pvalchev 1905: reader(void)
1.1       deraadt  1906: {
                   1907:     write_section(banner);
                   1908:     create_symbol_table();
                   1909:     read_declarations();
                   1910:     read_grammar();
                   1911:     free_symbol_table();
                   1912:     free_tags();
                   1913:     pack_names();
                   1914:     check_symbols();
                   1915:     pack_symbols();
                   1916:     pack_grammar();
                   1917:     free_symbols();
                   1918:     print_grammar();
                   1919: }