Annotation of coherent/f/f0/lex/lex2.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * lex/lex2.c
                      3:  * lexical analyser and utilities
                      4:  */
                      5: 
                      6: #include "lex.h"
                      7: #define        CMAX    3
                      8: 
                      9: char   cbuf[CMAX];
                     10: int    bufc = 0;
                     11: int    lstchr = '\n';
                     12: int    line = 0;
                     13: 
                     14: char *
                     15: alloc(n)
                     16: register n;
                     17: {
                     18:        register char *pc;
                     19: 
                     20:        if ((pc=malloc(n)) == NULL)
                     21:                error(outmem);
                     22:        return (pc);
                     23: }
                     24: 
                     25: char *
                     26: ralloc(pc, n)
                     27: char *pc;
                     28: {
                     29:        if ((pc=realloc(pc, n)) == NULL)
                     30:                error(outmem);
                     31:        return (pc);
                     32: }
                     33: 
                     34: /*
                     35:  * lexical ananlyser for regular expressions
                     36:  */
                     37: yylex()
                     38: {
                     39:        switch (yylval = next()) {
                     40:        case '\\':
                     41:                yylval = escape();
                     42:                return (LX_CHAR);
                     43:        case '"':
                     44:                inquotes = 1-inquotes;
                     45:                return (LX_OPER);
                     46:        case EOF:
                     47:                error(eoferr);
                     48:        default:
                     49:                if (inquotes)
                     50:                        if (yylval == '\n')
                     51:                                error("%s in quoted string", illnln);
                     52:                        else
                     53:                                return (LX_CHAR);
                     54:        }
                     55:        switch (yylval) {
                     56:        case '[':
                     57:                yylval = getclas();
                     58:                return (LX_CLAS);
                     59:        case '.':
                     60:                return (LX_ANYC);
                     61:        case ' ':
                     62:        case '\t':
                     63:        case '\n':
                     64:                return (LX_TERM);
                     65:        case '/':
                     66:                return (indefs? LX_OPER : LX_TERM);
                     67:        case '$':
                     68:                if (!indefs && isspace(look(0)))
                     69:                        return (LX_TERM);
                     70:        case '^':
                     71:        case '<':
                     72:        case '(':
                     73:        case ')':
                     74:        case '{':
                     75:        case '*':
                     76:        case '?':
                     77:        case '+':
                     78:        case '|':
                     79:                return (LX_OPER);
                     80:        default:
                     81:                if (!isascii(yylval) || iscntrl(yylval))
                     82:                        error("%s in regular expression", illchr);
                     83:                return (LX_CHAR);
                     84:        }
                     85: }
                     86: 
                     87: /*
                     88:  * get a backslashed character
                     89:  */
                     90: escape()
                     91: {
                     92:        register c, i;
                     93: 
                     94:        switch (c = next()) {
                     95:        case 'b':
                     96:                return ('\b');
                     97:        case 'f':
                     98:                return ('\f');
                     99:        case 'n':
                    100:                return ('\n');
                    101:        case 'r':
                    102:                return ('\r');
                    103:        case 't':
                    104:                return ('\t');
                    105:        default:
                    106:                if (isoctl(c)) {
                    107:                        for (i=0; c-='0', i<2 && isoctl(look(0)); ++i)
                    108:                                c = c * 8 + next();
                    109:                        if (c > MAXUCHAR)
                    110:                                error(illoct);
                    111:                }
                    112:                return (c);
                    113:        }
                    114: }
                    115: 
                    116: /*
                    117:  * read and store a class specification
                    118:  */
                    119: getclas()
                    120: {
                    121:        register unsigned int c,d;
                    122:        register unsigned char *index;
                    123:        register int bit;
                    124:        register int invert;
                    125: 
                    126:        if (clas == 0) {
                    127:                classptr = alloc(MAXUCHAR+1);
                    128:                index = classptr + (c = MAXUCHAR + 1);
                    129:                while (c--)
                    130:                        *--index = 0;
                    131:        } else if ((clas % NBCHAR) == 0) {
                    132:                c = classindex(clas + NBCHAR);
                    133:                classptr = ralloc(classptr, c);
                    134:                index = classptr + c;
                    135:                c = MAXUCHAR + 1;
                    136:                while (c--)
                    137:                        *--index = 0;
                    138:        } else
                    139:                index = classptr + classindex(clas);
                    140:        bit = classbit(clas);
                    141:        if (look(0) == '^') {
                    142:                invert = 1;
                    143:                next();
                    144:        } else
                    145:                invert = 0;
                    146:        while ((c=next()) != ']') {
                    147:                if (iscntrl(c))
                    148:                        error("%s in class", illchr);
                    149:                if (c == EOF)
                    150:                        error(eoferr);
                    151:                if (c == '.') {
                    152:                        c = index['\n'] & bit;
                    153:                        for (d=0; d<=MAXUCHAR; ++d)
                    154:                                index[d] |= bit;
                    155:                        if (!c)
                    156:                                index['\n'] ^= bit;
                    157:                } else {
                    158:                        if (c == '\\')
                    159:                                c = escape();
                    160:                        d = c;
                    161:                        if (look(0) == '-')
                    162:                                if (next(), look(0) != ']') {
                    163:                                        if ((d=next()) == '\\')
                    164:                                                d = escape();
                    165:                                        if (d < c)
                    166:                                                error(illrng);
                    167:                                } else
                    168:                                        index['-'] |= bit;
                    169:                        do {
                    170:                                index[c] |= bit;
                    171:                        } while (c++ < d);
                    172:                }
                    173:        }
                    174:        if (invert) {
                    175:                for (d=0; d<=MAXUCHAR; ++d)
                    176:                        index[d] ^= bit;
                    177:        }
                    178:        return (clas++);
                    179: }
                    180: 
                    181: /*
                    182:  * get next character from input
                    183:  */
                    184: next()
                    185: {
                    186:        static l = '\n';
                    187:        register c, i;
                    188: 
                    189:        if (l == '\n')
                    190:                ++line;
                    191:        if (bufc == 0)
                    192:                c = lstchr = getc(filein);
                    193:        else {
                    194:                c = cbuf[0];
                    195:                for (i=1; i < bufc; i++)
                    196:                        cbuf[i-1] = cbuf[i];
                    197:                --bufc;
                    198:        }
                    199:        return (l=c);
                    200: }
                    201: 
                    202: /*
                    203:  * look into input for the n+1th character
                    204:  * practically, n never exceeds 2
                    205:  */
                    206: look(n)
                    207: register int n;
                    208: {
                    209:        while (bufc <= n)
                    210:                cbuf[bufc++] = lstchr = getc(filein);
                    211:        return (cbuf[n]);
                    212: }
                    213: 
                    214: /*
                    215:  * delete input up to and including the next newline
                    216:  */
                    217: dnl()
                    218: {
                    219:        while (next() != '\n')
                    220:                ;
                    221:        setltype();
                    222: }
                    223: 
                    224: /*
                    225:  * eat up white space
                    226:  */
                    227: eatspc()
                    228: {
                    229:        register c;
                    230: 
                    231:        while (c=look(0), c==' ' || c=='\t')
                    232:                next();
                    233:        if (c == EOF)
                    234:                error(eoferr);
                    235: }
                    236: 
                    237: /*
                    238:  * eat input until white space
                    239:  */
                    240: eatlbl()
                    241: {
                    242:        register c;
                    243: 
                    244:        while (c=look(0), !isspace(c))
                    245:                next();
                    246:        if (c == '\n')
                    247:                return (1);
                    248:        return (0);
                    249: }
                    250: 
                    251: /*
                    252:  * copy an input line to the output file
                    253:  */
                    254: lcopy()
                    255: {
                    256:        register c;
                    257: 
                    258:        do {
                    259:                putc(c=next(), fileout);
                    260:        } while (c != '\n');
                    261:        setltype();
                    262: }
                    263: 
                    264: /*
                    265:  * set external variable ltype to the type of the next line
                    266:  */
                    267: setltype()
                    268: {
                    269:        ltype = getltype();
                    270: }
                    271: 
                    272: /*
                    273:  * return line type based on the first couple of characters
                    274:  */
                    275: getltype()
                    276: {
                    277:        switch (look(0)) {
                    278:        case '\t':
                    279:        case '\n':
                    280:        case ' ':
                    281:                return (LN_LSPC);
                    282:        case EOF:
                    283:                return (LN_EOFL);
                    284:        case '%':
                    285:                switch (look(1)) {
                    286:                case '%':
                    287:                        return (LN_DLIM);
                    288:                case '{':
                    289:                        return (LN_LCOM);
                    290:                case '}':
                    291:                        return (LN_RCOM);
                    292:                case 's':
                    293:                case 'S':
                    294:                        return (LN_SCON);
                    295:                case 'c':
                    296:                case 'C':
                    297:                        return (LN_CTXT);
                    298:                case 'x':
                    299:                case 'X':
                    300:                        return (LN_OPTN);
                    301:                }
                    302:        }
                    303:        return (LN_DFLT);
                    304: }
                    305: 
                    306: /*
                    307:  * put out a #line command for the C preprocessor
                    308:  */
                    309: outlnum(i)
                    310: {
                    311:        loutput(0, "#line %d", line+i);
                    312: }
                    313: 
                    314: /*
                    315:  * copy a user-specified action to the output
                    316:  */
                    317: getactn()
                    318: {
                    319:        enum cstate { /* states of c source */
                    320:                start, slash, comment, star, bsl, dquote, squote
                    321:        } pstate;
                    322:        register enum cstate state;
                    323:        register c;
                    324:        int bct;
                    325: 
                    326:        for (state = start, bct = 0;;) {
                    327:                if (EOF == (c = next()))
                    328:                        error(eoferr);
                    329:                putc(c, fileout);
                    330: 
                    331:                switch (state) {
                    332:                case slash:     /* maybe a comment */
                    333:                        if ('*' == c) {
                    334:                                state = comment;
                    335:                                break;
                    336:                        }
                    337:                        state = start;
                    338:                case start:     /* normal text state */
                    339:                        switch (c) {
                    340:                        case '/':
                    341:                                state = slash;
                    342:                                break;
                    343:                        case '\\':
                    344:                                pstate = state;
                    345:                                state = bsl;
                    346:                                break;
                    347:                        case '"':
                    348:                                state = dquote;
                    349:                                break;
                    350:                        case '\'':
                    351:                                state = squote;
                    352:                                break;
                    353:                        case '{':
                    354:                                bct++;
                    355:                                break;
                    356:                        case '}':
                    357:                                if (--bct < 0)
                    358:                                        error(actsyn);
                    359:                                break;
                    360:                        case '\n':
                    361:                                if (!bct) {
                    362:                                        setltype();
                    363:                                        return;
                    364:                                }
                    365:                        }
                    366:                        break;
                    367:                case star:      /* saw * in comment */
                    368:                        if ('/' == c) {
                    369:                                state = start;
                    370:                                break;
                    371:                        }
                    372:                        state = comment;
                    373:                case comment:   /* in comment */
                    374:                        if ('*' == c)
                    375:                                state = star;
                    376:                        break;
                    377:                case bsl:       /* char after backslash */
                    378:                        state = pstate;
                    379:                        break;
                    380:                case dquote:    /* in double quoted string */
                    381:                case squote:    /* in single quoted string */
                    382:                        switch (c) {
                    383:                        case '"':
                    384:                                if (dquote == state)
                    385:                                        state = start;
                    386:                                break;
                    387:                        case '\'':
                    388:                                if (squote == state)
                    389:                                        state = start;
                    390:                                break;
                    391:                        case '\n':
                    392:                                error(actsyn);
                    393:                                break;
                    394:                        case '\\':
                    395:                                pstate = state;
                    396:                                state = bsl;
                    397:                        }
                    398:                }
                    399:        }
                    400: }
                    401: 
                    402: /*
                    403:  * read an identifier
                    404:  */
                    405: char *
                    406: getident()
                    407: {
                    408:        register c, i = 0;
                    409:        register char *pc;
                    410: 
                    411:        eatspc();
                    412:        pc = alloc(NCBLK);
                    413:        while (c=look(0), isalnum(c) || c=='_') {
                    414:                pc[i++] = next();
                    415:                if (i%NCBLK == 0)
                    416:                        pc = ralloc((char *)pc, i+NCBLK);
                    417:        }
                    418:        pc[i] = '\0';
                    419:        eatspc();
                    420:        return (pc);
                    421: }
                    422: 
                    423: /*
                    424:  * interpret an identifier as the name of a
                    425:  * start condition, try to return its value
                    426:  */
                    427: getstart()
                    428: {
                    429:        register struct def *pd;
                    430:        register char *pc;
                    431: 
                    432:        pd = scnstart;
                    433:        pc = getident();
                    434:        do {
                    435:                if (strcmp(pc, pd->d_name) == 0) {
                    436:                        free(pc);
                    437:                        return (pd->d_data);
                    438:                }
                    439:        } while ((pd=pd->d_next) != NULL);
                    440:        error(undstc);
                    441: }
                    442: 
                    443: /*
                    444:  * add a string of identifiers to the start condition
                    445:  * list, numbering them as we go, too bad if they
                    446:  * are duplicates
                    447:  */
                    448: addstart()
                    449: {
                    450:        register struct def *pd;
                    451: 
                    452:        if (eatlbl())
                    453:                return;
                    454:        pd = scnstart;
                    455:        while (look(0) != '\n') {
                    456:                pd->d_next = alloc(sizeof(struct def));
                    457:                pd->d_next->d_data = pd->d_data + 1;
                    458:                pd = pd->d_next;
                    459:                pd->d_next = NULL;
                    460:                pd->d_name = getident();
                    461:        }
                    462: }
                    463: 
                    464: /*
                    465:  * like addstart, except with names of contexts
                    466:  */
                    467: addcontext()
                    468: {
                    469:        register struct def *pd;
                    470: 
                    471:        if (eatlbl())
                    472:                return;
                    473:        pd = ctxstart;
                    474:        while (pd->d_next != NULL)
                    475:                pd = pd->d_next;
                    476:        pd->d_next = alloc(sizeof(struct def));
                    477:        pd = pd->d_next;
                    478:        for (;;) {
                    479:                pd->d_name = getident();
                    480:                pd->d_data = 0;
                    481:                if (look(0) == '\n') {
                    482:                        pd->d_next = NULL;
                    483:                        break;
                    484:                } else {
                    485:                        pd->d_next = alloc(sizeof(struct def));
                    486:                        pd = pd->d_next;
                    487:                }
                    488:        }
                    489: }
                    490: 
                    491: /*
                    492:  * this is called to mark the context name with its
                    493:  * associated section of the nfa
                    494:  */
                    495: markcontext(t)
                    496: {
                    497:        register char *pc;
                    498:        register struct def *pd;
                    499: 
                    500:        eatlbl();
                    501:        pc = getident();
                    502:        pd = ctxstart;
                    503:        while ((pd=pd->d_next) != NULL)
                    504:                if (strcmp(pc, pd->d_name) == 0) {
                    505:                        pd->d_data = t;
                    506:                        free(pc);
                    507:                        return;
                    508:                }
                    509:        error(undctx);
                    510: }
                    511: 
                    512: /*
                    513:  * read the name of the definition, try
                    514:  * to return where it starts
                    515:  */
                    516: getdefn()
                    517: {
                    518:        register char *pc;
                    519:        register struct def *pd;
                    520: 
                    521:        pc = getident();
                    522:        if (look(0) == '}')
                    523:                next();
                    524:        else
                    525:                error("%s in definition name", illchr);
                    526:        for (pd=defstart; pd!=NULL; pd=pd->d_next)
                    527:                if (strcmp(pc, pd->d_name) == 0) {
                    528:                        free(pc);
                    529:                        return (pd->d_data);
                    530:                }
                    531:        error(unddef);
                    532: }
                    533: 
                    534: /*
                    535:  * recursive, costly but elegant
                    536:  */
                    537: freedef(pd)
                    538: register struct def *pd;
                    539: {
                    540:        if (pd != NULL) {
                    541:                freedef(pd->d_next);
                    542:                if (pd->d_name != NULL)
                    543:                        free(pd->d_name);
                    544:                free((char *)pd);
                    545:        }
                    546: }
                    547: 
                    548: /*
                    549:  * cleanup and abort
                    550:  */
                    551: /* VARARGS */
                    552: error(s)
                    553: {
                    554:        fprintf(stderr, "lex: ");
                    555:        if (line)
                    556:                fprintf(stderr, "%d: ", line);
                    557:        fprintf(stderr, "%r\n", &s);
                    558:        if (filein == stdin)
                    559:                while (lstchr!='\n' && lstchr!=EOF)
                    560:                        next();
                    561:        if (fileout != stdout)
                    562:                unlink(OUTFILE);
                    563:        exit (1);
                    564: }
                    565: 
                    566: usage()
                    567: {
                    568:        fprintf(stderr, "Usage: lex [-tv] [filename]\n");
                    569:        exit (1);
                    570: }
                    571: 
                    572: /* end of lex2.c */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.