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

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