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

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