[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.22

1.22    ! nicm        1: /*     $OpenBSD: reader.c,v 1.21 2009/10/27 23:59:50 deraadt 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);
                    117:        if (cache == 0) no_space();
                    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:
                    139:     if (line == 0 || linesize != (LINESIZE + 1))
                    140:     {
                    141:        if (line) FREE(line);
                    142:        linesize = LINESIZE + 1;
                    143:        line = MALLOC(linesize);
                    144:        if (line == 0) no_space();
                    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:
                    176:     if (line == 0) return (0);
                    177:     s = line;
                    178:     while (*s != '\n') ++s;
                    179:     p = MALLOC(s - line + 1);
                    180:     if (p == 0) no_space();
                    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();
                    210:            if (line == 0)
                    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:
                    225:     if (line == 0)
                    226:     {
                    227:        get_line();
                    228:        if (line == 0)
                    229:            return (EOF);
                    230:     }
                    231:
                    232:     s = cptr;
                    233:     for (;;)
                    234:     {
                    235:        switch (*s)
                    236:        {
                    237:        case '\n':
                    238:            get_line();
                    239:            if (line == 0) return (EOF);
                    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();
                    268:                if (line == 0) return (EOF);
                    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();
                    392:        if (line == 0)
                    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();
                    437:                        if (line == 0)
                    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();
                    483:                    if (line == 0)
                    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();
                    543:        if (line == 0) unterminated_union(u_lineno, u_line, u_cptr);
                    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();
                    588:                        if (line == 0)
                    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();
                    643:                    if (line == 0)
                    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();
                    697:                if (line == 0) unterminated_string(s_lineno, s_line, s_cptr);
                    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);
                    750:     if (s == 0) no_space();
1.17      deraadt   751:
1.1       deraadt   752:     for (i = 0; i < n; ++i)
                    753:        s[i] = cache[i];
                    754:
                    755:     cinc = 0;
                    756:     if (n == 1)
                    757:        cachec('\'');
                    758:     else
                    759:        cachec('"');
                    760:
                    761:     for (i = 0; i < n; ++i)
                    762:     {
                    763:        c = ((unsigned char *)s)[i];
                    764:        if (c == '\\' || c == cache[0])
                    765:        {
                    766:            cachec('\\');
                    767:            cachec(c);
                    768:        }
                    769:        else if (isprint(c))
                    770:            cachec(c);
                    771:        else
                    772:        {
                    773:            cachec('\\');
                    774:            switch (c)
                    775:            {
                    776:            case 7: cachec('a'); break;
                    777:            case '\b': cachec('b'); break;
                    778:            case '\f': cachec('f'); break;
                    779:            case '\n': cachec('n'); break;
                    780:            case '\r': cachec('r'); break;
                    781:            case '\t': cachec('t'); break;
                    782:            case '\v': cachec('v'); break;
                    783:            default:
                    784:                cachec(((c >> 6) & 7) + '0');
                    785:                cachec(((c >> 3) & 7) + '0');
                    786:                cachec((c & 7) + '0');
                    787:                break;
                    788:            }
                    789:        }
                    790:     }
                    791:
                    792:     if (n == 1)
                    793:        cachec('\'');
                    794:     else
                    795:        cachec('"');
                    796:
                    797:     cachec(NUL);
                    798:     bp = lookup(cache);
                    799:     bp->class = TERM;
                    800:     if (n == 1 && bp->value == UNDEFINED)
                    801:        bp->value = *(unsigned char *)s;
                    802:     FREE(s);
                    803:
                    804:     return (bp);
                    805: }
                    806:
                    807:
                    808: int
1.15      pvalchev  809: is_reserved(char *name)
1.1       deraadt   810: {
                    811:     char *s;
                    812:
                    813:     if (strcmp(name, ".") == 0 ||
                    814:            strcmp(name, "$accept") == 0 ||
                    815:            strcmp(name, "$end") == 0)
                    816:        return (1);
                    817:
                    818:     if (name[0] == '$' && name[1] == '$' && isdigit(name[2]))
                    819:     {
                    820:        s = name + 3;
                    821:        while (isdigit(*s)) ++s;
                    822:        if (*s == NUL) return (1);
                    823:     }
                    824:
                    825:     return (0);
                    826: }
                    827:
                    828:
                    829: bucket *
1.15      pvalchev  830: get_name(void)
1.1       deraadt   831: {
1.9       mpech     832:     int c;
1.1       deraadt   833:
                    834:     cinc = 0;
                    835:     for (c = *cptr; IS_IDENT(c); c = *++cptr)
                    836:        cachec(c);
                    837:     cachec(NUL);
                    838:
                    839:     if (is_reserved(cache)) used_reserved(cache);
                    840:
                    841:     return (lookup(cache));
                    842: }
                    843:
                    844:
                    845: int
1.15      pvalchev  846: get_number(void)
1.1       deraadt   847: {
1.9       mpech     848:     int c;
                    849:     int n;
1.1       deraadt   850:
                    851:     n = 0;
                    852:     for (c = *cptr; isdigit(c); c = *++cptr)
                    853:        n = 10*n + (c - '0');
                    854:
                    855:     return (n);
                    856: }
                    857:
                    858:
                    859: char *
1.15      pvalchev  860: get_tag(void)
1.1       deraadt   861: {
1.9       mpech     862:     int c;
                    863:     int i;
                    864:     char *s;
1.1       deraadt   865:     int t_lineno = lineno;
                    866:     char *t_line = dup_line();
                    867:     char *t_cptr = t_line + (cptr - line);
                    868:
                    869:     ++cptr;
                    870:     c = nextc();
                    871:     if (c == EOF) unexpected_EOF();
                    872:     if (!isalpha(c) && c != '_' && c != '$')
                    873:        illegal_tag(t_lineno, t_line, t_cptr);
                    874:
                    875:     cinc = 0;
                    876:     do { cachec(c); c = *++cptr; } while (IS_IDENT(c));
                    877:     cachec(NUL);
                    878:
                    879:     c = nextc();
                    880:     if (c == EOF) unexpected_EOF();
                    881:     if (c != '>')
                    882:        illegal_tag(t_lineno, t_line, t_cptr);
1.6       deraadt   883:     FREE(t_line);
1.1       deraadt   884:     ++cptr;
                    885:
                    886:     for (i = 0; i < ntags; ++i)
                    887:     {
                    888:        if (strcmp(cache, tag_table[i]) == 0)
                    889:            return (tag_table[i]);
                    890:     }
                    891:
                    892:     if (ntags >= tagmax)
                    893:     {
                    894:        tagmax += 16;
                    895:        tag_table = (char **)
                    896:                        (tag_table ? REALLOC(tag_table, tagmax*sizeof(char *))
                    897:                                   : MALLOC(tagmax*sizeof(char *)));
                    898:        if (tag_table == 0) no_space();
                    899:     }
                    900:
                    901:     s = MALLOC(cinc);
                    902:     if  (s == 0) no_space();
1.13      deraadt   903:     strlcpy(s, cache, cinc);
1.1       deraadt   904:     tag_table[ntags] = s;
                    905:     ++ntags;
                    906:     return (s);
                    907: }
                    908:
                    909:
1.8       pvalchev  910: void
1.15      pvalchev  911: declare_tokens(int assoc)
1.1       deraadt   912: {
1.9       mpech     913:     int c;
                    914:     bucket *bp;
1.1       deraadt   915:     int value;
                    916:     char *tag = 0;
                    917:
                    918:     if (assoc != TOKEN) ++prec;
                    919:
                    920:     c = nextc();
                    921:     if (c == EOF) unexpected_EOF();
                    922:     if (c == '<')
                    923:     {
                    924:        tag = get_tag();
                    925:        c = nextc();
                    926:        if (c == EOF) unexpected_EOF();
                    927:     }
                    928:
                    929:     for (;;)
                    930:     {
                    931:        if (isalpha(c) || c == '_' || c == '.' || c == '$')
                    932:            bp = get_name();
                    933:        else if (c == '\'' || c == '"')
                    934:            bp = get_literal();
                    935:        else
                    936:            return;
                    937:
                    938:        if (bp == goal) tokenized_start(bp->name);
                    939:        bp->class = TERM;
                    940:
                    941:        if (tag)
                    942:        {
                    943:            if (bp->tag && tag != bp->tag)
                    944:                retyped_warning(bp->name);
                    945:            bp->tag = tag;
                    946:        }
                    947:
                    948:        if (assoc != TOKEN)
                    949:        {
                    950:            if (bp->prec && prec != bp->prec)
                    951:                reprec_warning(bp->name);
                    952:            bp->assoc = assoc;
                    953:            bp->prec = prec;
                    954:        }
                    955:
                    956:        c = nextc();
                    957:        if (c == EOF) unexpected_EOF();
                    958:        value = UNDEFINED;
                    959:        if (isdigit(c))
                    960:        {
                    961:            value = get_number();
                    962:            if (bp->value != UNDEFINED && value != bp->value)
                    963:                revalued_warning(bp->name);
                    964:            bp->value = value;
                    965:            c = nextc();
                    966:            if (c == EOF) unexpected_EOF();
                    967:        }
                    968:     }
                    969: }
                    970:
                    971:
1.4       etheisen  972: /*
                    973:  * %expect requires special handling
                    974:  * as it really isn't part of the yacc
                    975:  * grammar only a flag for yacc proper.
                    976:  */
1.8       pvalchev  977: void
1.15      pvalchev  978: declare_expect(int assoc)
1.4       etheisen  979: {
1.9       mpech     980:     int c;
1.4       etheisen  981:
                    982:     if (assoc != EXPECT) ++prec;
                    983:
                    984:     /*
                    985:      * Stay away from nextc - doesn't
                    986:      * detect EOL and will read to EOF.
                    987:      */
                    988:     c = *++cptr;
                    989:     if (c == EOF) unexpected_EOF();
                    990:
                    991:     for(;;)
                    992:     {
                    993:         if (isdigit(c))
                    994:         {
                    995:            SRexpect = get_number();
                    996:             break;
                    997:         }
                    998:         /*
                    999:          * Looking for number before EOL.
                   1000:          * Spaces, tabs, and numbers are ok,
                   1001:          * words, punc., etc. are syntax errors.
                   1002:          */
                   1003:         else if (c == '\n' || isalpha(c) || !isspace(c))
                   1004:         {
                   1005:             syntax_error(lineno, line, cptr);
                   1006:         }
                   1007:         else
                   1008:         {
                   1009:             c = *++cptr;
                   1010:             if (c == EOF) unexpected_EOF();
                   1011:         }
                   1012:     }
                   1013: }
                   1014:
                   1015:
1.8       pvalchev 1016: void
1.15      pvalchev 1017: declare_types(void)
1.1       deraadt  1018: {
1.9       mpech    1019:     int c;
                   1020:     bucket *bp;
1.1       deraadt  1021:     char *tag;
                   1022:
                   1023:     c = nextc();
                   1024:     if (c == EOF) unexpected_EOF();
                   1025:     if (c != '<') syntax_error(lineno, line, cptr);
                   1026:     tag = get_tag();
                   1027:
                   1028:     for (;;)
                   1029:     {
                   1030:        c = nextc();
                   1031:        if (isalpha(c) || c == '_' || c == '.' || c == '$')
                   1032:            bp = get_name();
                   1033:        else if (c == '\'' || c == '"')
                   1034:            bp = get_literal();
                   1035:        else
                   1036:            return;
                   1037:
                   1038:        if (bp->tag && tag != bp->tag)
                   1039:            retyped_warning(bp->name);
                   1040:        bp->tag = tag;
                   1041:     }
                   1042: }
                   1043:
                   1044:
1.8       pvalchev 1045: void
1.15      pvalchev 1046: declare_start(void)
1.1       deraadt  1047: {
1.9       mpech    1048:     int c;
                   1049:     bucket *bp;
1.1       deraadt  1050:
                   1051:     c = nextc();
                   1052:     if (c == EOF) unexpected_EOF();
                   1053:     if (!isalpha(c) && c != '_' && c != '.' && c != '$')
                   1054:        syntax_error(lineno, line, cptr);
                   1055:     bp = get_name();
                   1056:     if (bp->class == TERM)
                   1057:        terminal_start(bp->name);
                   1058:     if (goal && goal != bp)
                   1059:        restarted_warning();
                   1060:     goal = bp;
                   1061: }
                   1062:
                   1063:
1.8       pvalchev 1064: void
1.15      pvalchev 1065: read_declarations(void)
1.1       deraadt  1066: {
1.9       mpech    1067:     int c, k;
1.1       deraadt  1068:
                   1069:     cache_size = 256;
                   1070:     cache = MALLOC(cache_size);
                   1071:     if (cache == 0) no_space();
                   1072:
                   1073:     for (;;)
                   1074:     {
                   1075:        c = nextc();
                   1076:        if (c == EOF) unexpected_EOF();
                   1077:        if (c != '%') syntax_error(lineno, line, cptr);
                   1078:        switch (k = keyword())
                   1079:        {
                   1080:        case MARK:
                   1081:            return;
                   1082:
                   1083:        case IDENT:
                   1084:            copy_ident();
                   1085:            break;
                   1086:
                   1087:        case TEXT:
                   1088:            copy_text();
                   1089:            break;
                   1090:
                   1091:        case UNION:
                   1092:            copy_union();
                   1093:            break;
                   1094:
                   1095:        case TOKEN:
                   1096:        case LEFT:
                   1097:        case RIGHT:
                   1098:        case NONASSOC:
                   1099:            declare_tokens(k);
                   1100:            break;
1.2       etheisen 1101:
1.4       etheisen 1102:        case EXPECT:
                   1103:            declare_expect(k);
                   1104:             break;
                   1105:
1.1       deraadt  1106:        case TYPE:
                   1107:            declare_types();
                   1108:            break;
                   1109:
                   1110:        case START:
                   1111:            declare_start();
                   1112:            break;
                   1113:        }
                   1114:     }
                   1115: }
                   1116:
                   1117:
1.8       pvalchev 1118: void
1.15      pvalchev 1119: initialize_grammar(void)
1.1       deraadt  1120: {
                   1121:     nitems = 4;
                   1122:     maxitems = 300;
1.22    ! nicm     1123:     pitem = (bucket **) CALLOC(maxitems, sizeof(bucket *));
1.1       deraadt  1124:     if (pitem == 0) no_space();
                   1125:
                   1126:     nrules = 3;
                   1127:     maxrules = 100;
                   1128:     plhs = (bucket **) MALLOC(maxrules*sizeof(bucket *));
                   1129:     if (plhs == 0) no_space();
                   1130:     plhs[0] = 0;
                   1131:     plhs[1] = 0;
                   1132:     plhs[2] = 0;
                   1133:     rprec = (short *) MALLOC(maxrules*sizeof(short));
                   1134:     if (rprec == 0) no_space();
                   1135:     rprec[0] = 0;
                   1136:     rprec[1] = 0;
                   1137:     rprec[2] = 0;
                   1138:     rassoc = (char *) MALLOC(maxrules*sizeof(char));
                   1139:     if (rassoc == 0) no_space();
                   1140:     rassoc[0] = TOKEN;
                   1141:     rassoc[1] = TOKEN;
                   1142:     rassoc[2] = TOKEN;
                   1143: }
                   1144:
                   1145:
1.8       pvalchev 1146: void
1.15      pvalchev 1147: expand_items(void)
1.1       deraadt  1148: {
1.22    ! nicm     1149:     int olditems = maxitems;
1.1       deraadt  1150:     maxitems += 300;
                   1151:     pitem = (bucket **) REALLOC(pitem, maxitems*sizeof(bucket *));
                   1152:     if (pitem == 0) no_space();
1.22    ! nicm     1153:     memset(pitem + olditems, 0, (maxitems - olditems)*sizeof(bucket *));
1.1       deraadt  1154: }
                   1155:
                   1156:
1.8       pvalchev 1157: void
1.15      pvalchev 1158: expand_rules(void)
1.1       deraadt  1159: {
                   1160:     maxrules += 100;
                   1161:     plhs = (bucket **) REALLOC(plhs, maxrules*sizeof(bucket *));
                   1162:     if (plhs == 0) no_space();
                   1163:     rprec = (short *) REALLOC(rprec, maxrules*sizeof(short));
                   1164:     if (rprec == 0) no_space();
                   1165:     rassoc = (char *) REALLOC(rassoc, maxrules*sizeof(char));
                   1166:     if (rassoc == 0) no_space();
                   1167: }
                   1168:
                   1169:
1.8       pvalchev 1170: void
1.15      pvalchev 1171: advance_to_start(void)
1.1       deraadt  1172: {
1.9       mpech    1173:     int c;
                   1174:     bucket *bp;
1.1       deraadt  1175:     char *s_cptr;
                   1176:     int s_lineno;
                   1177:
                   1178:     for (;;)
                   1179:     {
                   1180:        c = nextc();
                   1181:        if (c != '%') break;
                   1182:        s_cptr = cptr;
                   1183:        switch (keyword())
                   1184:        {
                   1185:        case MARK:
                   1186:            no_grammar();
                   1187:
                   1188:        case TEXT:
                   1189:            copy_text();
                   1190:            break;
                   1191:
                   1192:        case START:
                   1193:            declare_start();
                   1194:            break;
                   1195:
                   1196:        default:
                   1197:            syntax_error(lineno, line, s_cptr);
                   1198:        }
                   1199:     }
                   1200:
                   1201:     c = nextc();
                   1202:     if (!isalpha(c) && c != '_' && c != '.' && c != '_')
                   1203:        syntax_error(lineno, line, cptr);
                   1204:     bp = get_name();
                   1205:     if (goal == 0)
                   1206:     {
                   1207:        if (bp->class == TERM)
                   1208:            terminal_start(bp->name);
                   1209:        goal = bp;
                   1210:     }
                   1211:
                   1212:     s_lineno = lineno;
                   1213:     c = nextc();
                   1214:     if (c == EOF) unexpected_EOF();
                   1215:     if (c != ':') syntax_error(lineno, line, cptr);
                   1216:     start_rule(bp, s_lineno);
                   1217:     ++cptr;
                   1218: }
                   1219:
                   1220:
1.8       pvalchev 1221: void
1.15      pvalchev 1222: start_rule(bucket *bp, int s_lineno)
1.1       deraadt  1223: {
                   1224:     if (bp->class == TERM)
                   1225:        terminal_lhs(s_lineno);
                   1226:     bp->class = NONTERM;
                   1227:     if (nrules >= maxrules)
                   1228:        expand_rules();
                   1229:     plhs[nrules] = bp;
                   1230:     rprec[nrules] = UNDEFINED;
                   1231:     rassoc[nrules] = TOKEN;
                   1232: }
                   1233:
                   1234:
1.8       pvalchev 1235: void
1.15      pvalchev 1236: end_rule(void)
1.1       deraadt  1237: {
1.9       mpech    1238:     int i;
1.1       deraadt  1239:
                   1240:     if (!last_was_action && plhs[nrules]->tag)
                   1241:     {
                   1242:        for (i = nitems - 1; pitem[i]; --i) continue;
1.22    ! nicm     1243:        if (i == maxitems - 1 || pitem[i+1] == 0 ||
        !          1244:            pitem[i+1]->tag != plhs[nrules]->tag)
1.1       deraadt  1245:            default_action_warning();
                   1246:     }
                   1247:
                   1248:     last_was_action = 0;
                   1249:     if (nitems >= maxitems) expand_items();
                   1250:     pitem[nitems] = 0;
                   1251:     ++nitems;
                   1252:     ++nrules;
                   1253: }
                   1254:
                   1255:
1.8       pvalchev 1256: void
1.15      pvalchev 1257: insert_empty_rule(void)
1.1       deraadt  1258: {
1.9       mpech    1259:     bucket *bp, **bpp;
1.1       deraadt  1260:
                   1261:     assert(cache);
1.12      deraadt  1262:     snprintf(cache, cache_size, "$$%d", ++gensym);
1.1       deraadt  1263:     bp = make_bucket(cache);
                   1264:     last_symbol->next = bp;
                   1265:     last_symbol = bp;
                   1266:     bp->tag = plhs[nrules]->tag;
                   1267:     bp->class = NONTERM;
                   1268:
                   1269:     if ((nitems += 2) > maxitems)
                   1270:        expand_items();
                   1271:     bpp = pitem + nitems - 1;
                   1272:     *bpp-- = bp;
1.8       pvalchev 1273:     while ((bpp[0] = bpp[-1])) --bpp;
1.1       deraadt  1274:
                   1275:     if (++nrules >= maxrules)
                   1276:        expand_rules();
                   1277:     plhs[nrules] = plhs[nrules-1];
                   1278:     plhs[nrules-1] = bp;
                   1279:     rprec[nrules] = rprec[nrules-1];
                   1280:     rprec[nrules-1] = 0;
                   1281:     rassoc[nrules] = rassoc[nrules-1];
                   1282:     rassoc[nrules-1] = TOKEN;
                   1283: }
                   1284:
                   1285:
1.8       pvalchev 1286: void
1.15      pvalchev 1287: add_symbol(void)
1.1       deraadt  1288: {
1.9       mpech    1289:     int c;
                   1290:     bucket *bp;
1.1       deraadt  1291:     int s_lineno = lineno;
                   1292:
                   1293:     c = *cptr;
                   1294:     if (c == '\'' || c == '"')
                   1295:        bp = get_literal();
                   1296:     else
                   1297:        bp = get_name();
                   1298:
                   1299:     c = nextc();
                   1300:     if (c == ':')
                   1301:     {
                   1302:        end_rule();
                   1303:        start_rule(bp, s_lineno);
                   1304:        ++cptr;
                   1305:        return;
                   1306:     }
                   1307:
                   1308:     if (last_was_action)
                   1309:        insert_empty_rule();
                   1310:     last_was_action = 0;
                   1311:
                   1312:     if (++nitems > maxitems)
                   1313:        expand_items();
                   1314:     pitem[nitems-1] = bp;
                   1315: }
                   1316:
                   1317:
1.8       pvalchev 1318: void
1.15      pvalchev 1319: copy_action(void)
1.1       deraadt  1320: {
1.9       mpech    1321:     int c;
                   1322:     int i, n;
1.1       deraadt  1323:     int depth;
                   1324:     int quote;
                   1325:     char *tag;
1.9       mpech    1326:     FILE *f = action_file;
1.1       deraadt  1327:     int a_lineno = lineno;
                   1328:     char *a_line = dup_line();
                   1329:     char *a_cptr = a_line + (cptr - line);
                   1330:
                   1331:     if (last_was_action)
                   1332:        insert_empty_rule();
                   1333:     last_was_action = 1;
                   1334:
                   1335:     fprintf(f, "case %d:\n", nrules - 2);
                   1336:     if (!lflag)
                   1337:        fprintf(f, line_format, lineno, input_file_name);
                   1338:     if (*cptr == '=') ++cptr;
                   1339:
                   1340:     n = 0;
                   1341:     for (i = nitems - 1; pitem[i]; --i) ++n;
                   1342:
                   1343:     depth = 0;
                   1344: loop:
                   1345:     c = *cptr;
                   1346:     if (c == '$')
                   1347:     {
                   1348:        if (cptr[1] == '<')
                   1349:        {
                   1350:            int d_lineno = lineno;
                   1351:            char *d_line = dup_line();
                   1352:            char *d_cptr = d_line + (cptr - line);
                   1353:
                   1354:            ++cptr;
                   1355:            tag = get_tag();
                   1356:            c = *cptr;
                   1357:            if (c == '$')
                   1358:            {
                   1359:                fprintf(f, "yyval.%s", tag);
                   1360:                ++cptr;
                   1361:                FREE(d_line);
                   1362:                goto loop;
                   1363:            }
                   1364:            else if (isdigit(c))
                   1365:            {
                   1366:                i = get_number();
                   1367:                if (i > n) dollar_warning(d_lineno, i);
                   1368:                fprintf(f, "yyvsp[%d].%s", i - n, tag);
                   1369:                FREE(d_line);
                   1370:                goto loop;
                   1371:            }
                   1372:            else if (c == '-' && isdigit(cptr[1]))
                   1373:            {
                   1374:                ++cptr;
                   1375:                i = -get_number() - n;
                   1376:                fprintf(f, "yyvsp[%d].%s", i, tag);
                   1377:                FREE(d_line);
                   1378:                goto loop;
                   1379:            }
                   1380:            else
                   1381:                dollar_error(d_lineno, d_line, d_cptr);
                   1382:        }
                   1383:        else if (cptr[1] == '$')
                   1384:        {
                   1385:            if (ntags)
                   1386:            {
                   1387:                tag = plhs[nrules]->tag;
                   1388:                if (tag == 0) untyped_lhs();
                   1389:                fprintf(f, "yyval.%s", tag);
                   1390:            }
                   1391:            else
                   1392:                fprintf(f, "yyval");
                   1393:            cptr += 2;
                   1394:            goto loop;
                   1395:        }
                   1396:        else if (isdigit(cptr[1]))
                   1397:        {
                   1398:            ++cptr;
                   1399:            i = get_number();
                   1400:            if (ntags)
                   1401:            {
                   1402:                if (i <= 0 || i > n)
                   1403:                    unknown_rhs(i);
                   1404:                tag = pitem[nitems + i - n - 1]->tag;
                   1405:                if (tag == 0) untyped_rhs(i, pitem[nitems + i - n - 1]->name);
                   1406:                fprintf(f, "yyvsp[%d].%s", i - n, tag);
                   1407:            }
                   1408:            else
                   1409:            {
                   1410:                if (i > n)
                   1411:                    dollar_warning(lineno, i);
                   1412:                fprintf(f, "yyvsp[%d]", i - n);
                   1413:            }
                   1414:            goto loop;
                   1415:        }
                   1416:        else if (cptr[1] == '-')
                   1417:        {
                   1418:            cptr += 2;
                   1419:            i = get_number();
                   1420:            if (ntags)
                   1421:                unknown_rhs(-i);
                   1422:            fprintf(f, "yyvsp[%d]", -i - n);
                   1423:            goto loop;
                   1424:        }
                   1425:     }
                   1426:     if (isalpha(c) || c == '_' || c == '$')
                   1427:     {
                   1428:        do
                   1429:        {
                   1430:            putc(c, f);
                   1431:            c = *++cptr;
                   1432:        } while (isalnum(c) || c == '_' || c == '$');
                   1433:        goto loop;
                   1434:     }
                   1435:     putc(c, f);
                   1436:     ++cptr;
                   1437:     switch (c)
                   1438:     {
                   1439:     case '\n':
                   1440:     next_line:
                   1441:        get_line();
                   1442:        if (line) goto loop;
                   1443:        unterminated_action(a_lineno, a_line, a_cptr);
                   1444:
                   1445:     case ';':
                   1446:        if (depth > 0) goto loop;
                   1447:        fprintf(f, "\nbreak;\n");
1.6       deraadt  1448:        FREE(a_line);
1.1       deraadt  1449:        return;
                   1450:
                   1451:     case '{':
                   1452:        ++depth;
                   1453:        goto loop;
                   1454:
                   1455:     case '}':
                   1456:        if (--depth > 0) goto loop;
                   1457:        fprintf(f, "\nbreak;\n");
1.6       deraadt  1458:        FREE(a_line);
1.1       deraadt  1459:        return;
                   1460:
                   1461:     case '\'':
                   1462:     case '"':
                   1463:        {
                   1464:            int s_lineno = lineno;
                   1465:            char *s_line = dup_line();
                   1466:            char *s_cptr = s_line + (cptr - line - 1);
                   1467:
                   1468:            quote = c;
                   1469:            for (;;)
                   1470:            {
                   1471:                c = *cptr++;
                   1472:                putc(c, f);
                   1473:                if (c == quote)
                   1474:                {
                   1475:                    FREE(s_line);
                   1476:                    goto loop;
                   1477:                }
                   1478:                if (c == '\n')
                   1479:                    unterminated_string(s_lineno, s_line, s_cptr);
                   1480:                if (c == '\\')
                   1481:                {
                   1482:                    c = *cptr++;
                   1483:                    putc(c, f);
                   1484:                    if (c == '\n')
                   1485:                    {
                   1486:                        get_line();
                   1487:                        if (line == 0)
                   1488:                            unterminated_string(s_lineno, s_line, s_cptr);
                   1489:                    }
                   1490:                }
                   1491:            }
                   1492:        }
                   1493:
                   1494:     case '/':
                   1495:        c = *cptr;
                   1496:        if (c == '/')
                   1497:        {
                   1498:            putc('*', f);
                   1499:            while ((c = *++cptr) != '\n')
                   1500:            {
                   1501:                if (c == '*' && cptr[1] == '/')
                   1502:                    fprintf(f, "* ");
                   1503:                else
                   1504:                    putc(c, f);
                   1505:            }
                   1506:            fprintf(f, "*/\n");
                   1507:            goto next_line;
                   1508:        }
                   1509:        if (c == '*')
                   1510:        {
                   1511:            int c_lineno = lineno;
                   1512:            char *c_line = dup_line();
                   1513:            char *c_cptr = c_line + (cptr - line - 1);
                   1514:
                   1515:            putc('*', f);
                   1516:            ++cptr;
                   1517:            for (;;)
                   1518:            {
                   1519:                c = *cptr++;
                   1520:                putc(c, f);
                   1521:                if (c == '*' && *cptr == '/')
                   1522:                {
                   1523:                    putc('/', f);
                   1524:                    ++cptr;
                   1525:                    FREE(c_line);
                   1526:                    goto loop;
                   1527:                }
                   1528:                if (c == '\n')
                   1529:                {
                   1530:                    get_line();
                   1531:                    if (line == 0)
                   1532:                        unterminated_comment(c_lineno, c_line, c_cptr);
                   1533:                }
                   1534:            }
                   1535:        }
                   1536:        goto loop;
                   1537:
                   1538:     default:
                   1539:        goto loop;
                   1540:     }
                   1541: }
                   1542:
                   1543:
                   1544: int
1.15      pvalchev 1545: mark_symbol(void)
1.1       deraadt  1546: {
1.9       mpech    1547:     int c;
1.18      pvalchev 1548:     bucket *bp = NULL;
1.1       deraadt  1549:
                   1550:     c = cptr[1];
                   1551:     if (c == '%' || c == '\\')
                   1552:     {
                   1553:        cptr += 2;
                   1554:        return (1);
                   1555:     }
                   1556:
                   1557:     if (c == '=')
                   1558:        cptr += 2;
                   1559:     else if ((c == 'p' || c == 'P') &&
                   1560:             ((c = cptr[2]) == 'r' || c == 'R') &&
                   1561:             ((c = cptr[3]) == 'e' || c == 'E') &&
                   1562:             ((c = cptr[4]) == 'c' || c == 'C') &&
                   1563:             ((c = cptr[5], !IS_IDENT(c))))
                   1564:        cptr += 5;
                   1565:     else
                   1566:        syntax_error(lineno, line, cptr);
                   1567:
                   1568:     c = nextc();
                   1569:     if (isalpha(c) || c == '_' || c == '.' || c == '$')
                   1570:        bp = get_name();
                   1571:     else if (c == '\'' || c == '"')
                   1572:        bp = get_literal();
                   1573:     else
                   1574:     {
                   1575:        syntax_error(lineno, line, cptr);
                   1576:        /*NOTREACHED*/
                   1577:     }
                   1578:
                   1579:     if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
                   1580:        prec_redeclared();
                   1581:
                   1582:     rprec[nrules] = bp->prec;
                   1583:     rassoc[nrules] = bp->assoc;
                   1584:     return (0);
                   1585: }
                   1586:
                   1587:
1.8       pvalchev 1588: void
1.15      pvalchev 1589: read_grammar(void)
1.1       deraadt  1590: {
1.9       mpech    1591:     int c;
1.1       deraadt  1592:
                   1593:     initialize_grammar();
                   1594:     advance_to_start();
                   1595:
                   1596:     for (;;)
                   1597:     {
                   1598:        c = nextc();
                   1599:        if (c == EOF) break;
                   1600:        if (isalpha(c) || c == '_' || c == '.' || c == '$' || c == '\'' ||
                   1601:                c == '"')
                   1602:            add_symbol();
                   1603:        else if (c == '{' || c == '=')
                   1604:            copy_action();
                   1605:        else if (c == '|')
                   1606:        {
                   1607:            end_rule();
                   1608:            start_rule(plhs[nrules-1], 0);
                   1609:            ++cptr;
                   1610:        }
                   1611:        else if (c == '%')
                   1612:        {
                   1613:            if (mark_symbol()) break;
                   1614:        }
                   1615:        else
                   1616:            syntax_error(lineno, line, cptr);
                   1617:     }
                   1618:     end_rule();
                   1619: }
                   1620:
                   1621:
1.8       pvalchev 1622: void
1.15      pvalchev 1623: free_tags(void)
1.1       deraadt  1624: {
1.9       mpech    1625:     int i;
1.1       deraadt  1626:
                   1627:     if (tag_table == 0) return;
                   1628:
                   1629:     for (i = 0; i < ntags; ++i)
                   1630:     {
                   1631:        assert(tag_table[i]);
                   1632:        FREE(tag_table[i]);
                   1633:     }
                   1634:     FREE(tag_table);
                   1635: }
                   1636:
                   1637:
1.8       pvalchev 1638: void
1.15      pvalchev 1639: pack_names(void)
1.1       deraadt  1640: {
1.9       mpech    1641:     bucket *bp;
                   1642:     char *p, *s, *t;
1.1       deraadt  1643:
                   1644:     name_pool_size = 13;  /* 13 == sizeof("$end") + sizeof("$accept") */
                   1645:     for (bp = first_symbol; bp; bp = bp->next)
                   1646:        name_pool_size += strlen(bp->name) + 1;
                   1647:     name_pool = MALLOC(name_pool_size);
                   1648:     if (name_pool == 0) no_space();
                   1649:
1.13      deraadt  1650:     strlcpy(name_pool, "$accept", name_pool_size);
                   1651:     strlcpy(name_pool+8, "$end", name_pool_size - 8);
1.1       deraadt  1652:     t = name_pool + 13;
                   1653:     for (bp = first_symbol; bp; bp = bp->next)
                   1654:     {
                   1655:        p = t;
                   1656:        s = bp->name;
1.8       pvalchev 1657:        while ((*t++ = *s++)) continue;
1.1       deraadt  1658:        FREE(bp->name);
                   1659:        bp->name = p;
                   1660:     }
                   1661: }
                   1662:
                   1663:
1.8       pvalchev 1664: void
1.15      pvalchev 1665: check_symbols(void)
1.1       deraadt  1666: {
1.9       mpech    1667:     bucket *bp;
1.1       deraadt  1668:
                   1669:     if (goal->class == UNKNOWN)
                   1670:        undefined_goal(goal->name);
                   1671:
                   1672:     for (bp = first_symbol; bp; bp = bp->next)
                   1673:     {
                   1674:        if (bp->class == UNKNOWN)
                   1675:        {
                   1676:            undefined_symbol_warning(bp->name);
                   1677:            bp->class = TERM;
                   1678:        }
                   1679:     }
                   1680: }
                   1681:
                   1682:
1.8       pvalchev 1683: void
1.15      pvalchev 1684: pack_symbols(void)
1.1       deraadt  1685: {
1.9       mpech    1686:     bucket *bp;
                   1687:     bucket **v;
                   1688:     int i, j, k, n;
1.1       deraadt  1689:
                   1690:     nsyms = 2;
                   1691:     ntokens = 1;
                   1692:     for (bp = first_symbol; bp; bp = bp->next)
                   1693:     {
                   1694:        ++nsyms;
                   1695:        if (bp->class == TERM) ++ntokens;
                   1696:     }
                   1697:     start_symbol = ntokens;
                   1698:     nvars = nsyms - ntokens;
                   1699:
                   1700:     symbol_name = (char **) MALLOC(nsyms*sizeof(char *));
                   1701:     if (symbol_name == 0) no_space();
                   1702:     symbol_value = (short *) MALLOC(nsyms*sizeof(short));
                   1703:     if (symbol_value == 0) no_space();
                   1704:     symbol_prec = (short *) MALLOC(nsyms*sizeof(short));
                   1705:     if (symbol_prec == 0) no_space();
                   1706:     symbol_assoc = MALLOC(nsyms);
                   1707:     if (symbol_assoc == 0) no_space();
                   1708:
                   1709:     v = (bucket **) MALLOC(nsyms*sizeof(bucket *));
                   1710:     if (v == 0) no_space();
                   1711:
                   1712:     v[0] = 0;
                   1713:     v[start_symbol] = 0;
                   1714:
                   1715:     i = 1;
                   1716:     j = start_symbol + 1;
                   1717:     for (bp = first_symbol; bp; bp = bp->next)
                   1718:     {
                   1719:        if (bp->class == TERM)
                   1720:            v[i++] = bp;
                   1721:        else
                   1722:            v[j++] = bp;
                   1723:     }
                   1724:     assert(i == ntokens && j == nsyms);
                   1725:
                   1726:     for (i = 1; i < ntokens; ++i)
                   1727:        v[i]->index = i;
                   1728:
                   1729:     goal->index = start_symbol + 1;
                   1730:     k = start_symbol + 2;
                   1731:     while (++i < nsyms)
                   1732:        if (v[i] != goal)
                   1733:        {
                   1734:            v[i]->index = k;
                   1735:            ++k;
                   1736:        }
                   1737:
                   1738:     goal->value = 0;
                   1739:     k = 1;
                   1740:     for (i = start_symbol + 1; i < nsyms; ++i)
                   1741:     {
                   1742:        if (v[i] != goal)
                   1743:        {
                   1744:            v[i]->value = k;
                   1745:            ++k;
                   1746:        }
                   1747:     }
                   1748:
                   1749:     k = 0;
                   1750:     for (i = 1; i < ntokens; ++i)
                   1751:     {
                   1752:        n = v[i]->value;
                   1753:        if (n > 256)
                   1754:        {
                   1755:            for (j = k++; j > 0 && symbol_value[j-1] > n; --j)
                   1756:                symbol_value[j] = symbol_value[j-1];
                   1757:            symbol_value[j] = n;
                   1758:        }
                   1759:     }
                   1760:
                   1761:     if (v[1]->value == UNDEFINED)
                   1762:        v[1]->value = 256;
                   1763:
                   1764:     j = 0;
                   1765:     n = 257;
                   1766:     for (i = 2; i < ntokens; ++i)
                   1767:     {
                   1768:        if (v[i]->value == UNDEFINED)
                   1769:        {
                   1770:            while (j < k && n == symbol_value[j])
                   1771:            {
                   1772:                while (++j < k && n == symbol_value[j]) continue;
                   1773:                ++n;
                   1774:            }
                   1775:            v[i]->value = n;
                   1776:            ++n;
                   1777:        }
                   1778:     }
                   1779:
                   1780:     symbol_name[0] = name_pool + 8;
                   1781:     symbol_value[0] = 0;
                   1782:     symbol_prec[0] = 0;
                   1783:     symbol_assoc[0] = TOKEN;
                   1784:     for (i = 1; i < ntokens; ++i)
                   1785:     {
                   1786:        symbol_name[i] = v[i]->name;
                   1787:        symbol_value[i] = v[i]->value;
                   1788:        symbol_prec[i] = v[i]->prec;
                   1789:        symbol_assoc[i] = v[i]->assoc;
                   1790:     }
                   1791:     symbol_name[start_symbol] = name_pool;
                   1792:     symbol_value[start_symbol] = -1;
                   1793:     symbol_prec[start_symbol] = 0;
                   1794:     symbol_assoc[start_symbol] = TOKEN;
                   1795:     for (++i; i < nsyms; ++i)
                   1796:     {
                   1797:        k = v[i]->index;
                   1798:        symbol_name[k] = v[i]->name;
                   1799:        symbol_value[k] = v[i]->value;
                   1800:        symbol_prec[k] = v[i]->prec;
                   1801:        symbol_assoc[k] = v[i]->assoc;
                   1802:     }
                   1803:
                   1804:     FREE(v);
                   1805: }
                   1806:
                   1807:
1.8       pvalchev 1808: void
1.15      pvalchev 1809: pack_grammar(void)
1.1       deraadt  1810: {
1.9       mpech    1811:     int i, j;
1.1       deraadt  1812:     int assoc, prec;
                   1813:
                   1814:     ritem = (short *) MALLOC(nitems*sizeof(short));
                   1815:     if (ritem == 0) no_space();
                   1816:     rlhs = (short *) MALLOC(nrules*sizeof(short));
                   1817:     if (rlhs == 0) no_space();
                   1818:     rrhs = (short *) MALLOC((nrules+1)*sizeof(short));
                   1819:     if (rrhs == 0) no_space();
                   1820:     rprec = (short *) REALLOC(rprec, nrules*sizeof(short));
                   1821:     if (rprec == 0) no_space();
                   1822:     rassoc = REALLOC(rassoc, nrules);
                   1823:     if (rassoc == 0) no_space();
                   1824:
                   1825:     ritem[0] = -1;
                   1826:     ritem[1] = goal->index;
                   1827:     ritem[2] = 0;
                   1828:     ritem[3] = -2;
                   1829:     rlhs[0] = 0;
                   1830:     rlhs[1] = 0;
                   1831:     rlhs[2] = start_symbol;
                   1832:     rrhs[0] = 0;
                   1833:     rrhs[1] = 0;
                   1834:     rrhs[2] = 1;
                   1835:
                   1836:     j = 4;
                   1837:     for (i = 3; i < nrules; ++i)
                   1838:     {
                   1839:        rlhs[i] = plhs[i]->index;
                   1840:        rrhs[i] = j;
                   1841:        assoc = TOKEN;
                   1842:        prec = 0;
                   1843:        while (pitem[j])
                   1844:        {
                   1845:            ritem[j] = pitem[j]->index;
                   1846:            if (pitem[j]->class == TERM)
                   1847:            {
                   1848:                prec = pitem[j]->prec;
                   1849:                assoc = pitem[j]->assoc;
                   1850:            }
                   1851:            ++j;
                   1852:        }
                   1853:        ritem[j] = -i;
                   1854:        ++j;
                   1855:        if (rprec[i] == UNDEFINED)
                   1856:        {
                   1857:            rprec[i] = prec;
                   1858:            rassoc[i] = assoc;
                   1859:        }
                   1860:     }
                   1861:     rrhs[i] = j;
                   1862:
                   1863:     FREE(plhs);
                   1864:     FREE(pitem);
                   1865: }
                   1866:
                   1867:
1.8       pvalchev 1868: void
1.15      pvalchev 1869: print_grammar(void)
1.1       deraadt  1870: {
1.9       mpech    1871:     int i, j, k;
1.18      pvalchev 1872:     int spacing = 0;
1.9       mpech    1873:     FILE *f = verbose_file;
1.1       deraadt  1874:
                   1875:     if (!vflag) return;
                   1876:
                   1877:     k = 1;
                   1878:     for (i = 2; i < nrules; ++i)
                   1879:     {
                   1880:        if (rlhs[i] != rlhs[i-1])
                   1881:        {
                   1882:            if (i != 2) fprintf(f, "\n");
                   1883:            fprintf(f, "%4d  %s :", i - 2, symbol_name[rlhs[i]]);
                   1884:            spacing = strlen(symbol_name[rlhs[i]]) + 1;
                   1885:        }
                   1886:        else
                   1887:        {
                   1888:            fprintf(f, "%4d  ", i - 2);
                   1889:            j = spacing;
                   1890:            while (--j >= 0) putc(' ', f);
                   1891:            putc('|', f);
                   1892:        }
                   1893:
                   1894:        while (ritem[k] >= 0)
                   1895:        {
                   1896:            fprintf(f, " %s", symbol_name[ritem[k]]);
                   1897:            ++k;
                   1898:        }
                   1899:        ++k;
                   1900:        putc('\n', f);
                   1901:     }
                   1902: }
                   1903:
                   1904:
1.8       pvalchev 1905: void
1.15      pvalchev 1906: reader(void)
1.1       deraadt  1907: {
                   1908:     write_section(banner);
                   1909:     create_symbol_table();
                   1910:     read_declarations();
                   1911:     read_grammar();
                   1912:     free_symbol_table();
                   1913:     free_tags();
                   1914:     pack_names();
                   1915:     check_symbols();
                   1916:     pack_symbols();
                   1917:     pack_grammar();
                   1918:     free_symbols();
                   1919:     print_grammar();
                   1920: }