Annotation of coherent/d/bin/lex/lex2.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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