Annotation of researchv10no/cmd/awk/b.c, revision 1.1.1.1

1.1       root        1: /*
                      2: Copyright (c) 1989 AT&T
                      3:        All Rights Reserved
                      4: 
                      5: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T.
                      6: 
                      7: The copyright notice above does not evidence any
                      8: actual or intended publication of such source code.
                      9: */
                     10: 
                     11: #define        DEBUG
                     12: 
                     13: #include <ctype.h>
                     14: #include <stdio.h>
                     15: #include <string.h>
                     16: #include <stdlib.h>
                     17: #include "awk.h"
                     18: #include "y.tab.h"
                     19: 
                     20: #define        HAT     (NCHARS-1)      /* matches ^ in regular expr */
                     21:                                /* NCHARS is 2**n */
                     22: #define MAXLIN 512
                     23: 
                     24: #define type(v)                (v)->nobj
                     25: #define left(v)                (v)->narg[0]
                     26: #define right(v)       (v)->narg[1]
                     27: #define parent(v)      (v)->nnext
                     28: 
                     29: #define LEAF   case CCL: case NCCL: case CHAR: case DOT: case FINAL: case ALL:
                     30: #define UNARY  case STAR: case PLUS: case QUEST:
                     31: 
                     32: /* encoding in tree Nodes:
                     33:        leaf (CCL, NCCL, CHAR, DOT, FINAL, ALL):
                     34:                left is index, right contains value or pointer to value
                     35:        unary (STAR, PLUS, QUEST): left is child, right is null
                     36:        binary (CAT, OR): left and right are children
                     37:        parent contains pointer to parent
                     38: */
                     39: 
                     40: 
                     41: uchar  chars[MAXLIN];
                     42: int    setvec[MAXLIN];
                     43: int    tmpset[MAXLIN];
                     44: Node   *point[MAXLIN];
                     45: 
                     46: int    rtok;           /* next token in current re */
                     47: int    rlxval;
                     48: uchar  *rlxstr;
                     49: uchar  *prestr;        /* current position in current re */
                     50: uchar  *lastre;        /* origin of last re */
                     51: 
                     52: static int setcnt;
                     53: static int poscnt;
                     54: 
                     55: uchar  *patbeg;
                     56: int    patlen;
                     57: 
                     58: #define        NFA     20      /* cache this many dynamic fa's */
                     59: fa     *fatab[NFA];
                     60: int    nfatab  = 0;    /* entries in fatab */
                     61: 
                     62: fa *makedfa(uchar *s, int anchor)      /* returns dfa for reg expr s */
                     63: {
                     64:        int i, use, nuse;
                     65:        fa *pfa;
                     66: 
                     67:        if (compile_time)       /* a constant for sure */
                     68:                return mkdfa(s, anchor);
                     69:        for (i = 0; i < nfatab; i++)    /* is it there already? */
                     70:                if (fatab[i]->anchor == anchor && strcmp(fatab[i]->restr,s) == 0) {
                     71:                        fatab[i]->use++;
                     72:                        return fatab[i];
                     73:        }
                     74:        pfa = mkdfa(s, anchor);
                     75:        if (nfatab < NFA) {     /* room for another */
                     76:                fatab[nfatab] = pfa;
                     77:                fatab[nfatab]->use = 1;
                     78:                nfatab++;
                     79:                return pfa;
                     80:        }
                     81:        use = fatab[0]->use;    /* replace least-recently used */
                     82:        nuse = 0;
                     83:        for (i = 1; i < nfatab; i++)
                     84:                if (fatab[i]->use < use) {
                     85:                        use = fatab[i]->use;
                     86:                        nuse = i;
                     87:                }
                     88:        freefa(fatab[nuse]);
                     89:        fatab[nuse] = pfa;
                     90:        pfa->use = 1;
                     91:        return pfa;
                     92: }
                     93: 
                     94: fa *mkdfa(uchar *s, int anchor)        /* does the real work of making a dfa */
                     95:                                /* anchor = 1 for anchored matches, else 0 */
                     96: {
                     97:        Node *p, *p1;
                     98:        fa *f;
                     99: 
                    100:        p = reparse(s);
                    101:        p1 = op2(CAT, op2(STAR, op2(ALL, NIL, NIL), NIL), p);
                    102:                /* put ALL STAR in front of reg.  exp. */
                    103:        p1 = op2(CAT, p1, op2(FINAL, NIL, NIL));
                    104:                /* put FINAL after reg.  exp. */
                    105: 
                    106:        poscnt = 0;
                    107:        penter(p1);     /* enter parent pointers and leaf indices */
                    108:        if ((f = (fa *) calloc(1, sizeof(fa) + poscnt*sizeof(rrow))) == NULL)
                    109:                overflo("out of space for fa");
                    110:        f->accept = poscnt-1;   /* penter has computed number of positions in re */
                    111:        cfoll(f, p1);   /* set up follow sets */
                    112:        freetr(p1);
                    113:        if ((f->posns[0] = (int *) calloc(1, *(f->re[0].lfollow)*sizeof(int))) == NULL)
                    114:                        overflo("out of space in makedfa");
                    115:        if ((f->posns[1] = (int *) calloc(1, sizeof(int))) == NULL)
                    116:                overflo("out of space in makedfa");
                    117:        *f->posns[1] = 0;
                    118:        f->initstat = makeinit(f, anchor);
                    119:        f->anchor = anchor;
                    120:        f->restr = tostring(s);
                    121:        return f;
                    122: }
                    123: 
                    124: int makeinit(fa *f, int anchor)
                    125: {
                    126:        register int i, k;
                    127: 
                    128:        f->curstat = 2;
                    129:        f->out[2] = 0;
                    130:        f->reset = 0;
                    131:        k = *(f->re[0].lfollow);
                    132:        xfree(f->posns[2]);                     
                    133:        if ((f->posns[2] = (int *) calloc(1, (k+1)*sizeof(int))) == NULL)
                    134:                overflo("out of space in makeinit");
                    135:        for (i=0; i<=k; i++) {
                    136:                (f->posns[2])[i] = (f->re[0].lfollow)[i];
                    137:        }
                    138:        if ((f->posns[2])[1] == f->accept)
                    139:                f->out[2] = 1;
                    140:        for (i=0; i<NCHARS; i++)
                    141:                f->gototab[2][i] = 0;
                    142:        f->curstat = cgoto(f, 2, HAT);
                    143:        if (anchor) {
                    144:                *f->posns[2] = k-1;     /* leave out position 0 */
                    145:                for (i=0; i<k; i++) {
                    146:                        (f->posns[0])[i] = (f->posns[2])[i];
                    147:                }
                    148: 
                    149:                f->out[0] = f->out[2];
                    150:                if (f->curstat != 2)
                    151:                        --(*f->posns[f->curstat]);
                    152:        }
                    153:        return f->curstat;
                    154: }
                    155: 
                    156: void penter(Node *p)   /* set up parent pointers and leaf indices */
                    157: {
                    158:        switch(type(p)) {
                    159:        LEAF
                    160:                left(p) = (Node *) poscnt;
                    161:                if (poscnt >= MAXLIN)
                    162:                        overflo("leaf index overflow in penter");
                    163:                point[poscnt++] = p;
                    164:                break;
                    165:        UNARY
                    166:                penter(left(p));
                    167:                parent(left(p)) = p;
                    168:                break;
                    169:        case CAT:
                    170:        case OR:
                    171:                penter(left(p));
                    172:                penter(right(p));
                    173:                parent(left(p)) = p;
                    174:                parent(right(p)) = p;
                    175:                break;
                    176:        default:        /* can't happen */
                    177:                ERROR "unknown type %d in penter", type(p) FATAL;
                    178:                break;
                    179:        }
                    180: }
                    181: 
                    182: void freetr(Node *p)   /* free parse tree */
                    183: {
                    184:        switch (type(p)) {
                    185:        LEAF
                    186:                xfree(p);
                    187:                break;
                    188:        UNARY
                    189:                freetr(left(p));
                    190:                xfree(p);
                    191:                break;
                    192:        case CAT:
                    193:        case OR:
                    194:                freetr(left(p));
                    195:                freetr(right(p));
                    196:                xfree(p);
                    197:                break;
                    198:        default:        /* can't happen */
                    199:                ERROR "unknown type %d in freetr", type(p) FATAL;
                    200:                break;
                    201:        }
                    202: }
                    203: 
                    204: /* in the parsing of regular expressions, metacharacters like . have */
                    205: /* to be seen literally;  \056 is not a metacharacter. */
                    206: 
                    207: hexstr(char **pp)      /* find and eval hex string at pp, return new p */
                    208: {
                    209:        char *p;
                    210:        int n = 0;
                    211: 
                    212:        for (p = *pp; isxdigit(*p); p++) {
                    213:                if (isdigit(*p))
                    214:                        n = 16 * n + *p - '0';
                    215:                else if (*p >= 'a' && *p <= 'f')
                    216:                        n = 16 * n + *p - 'a' + 10;
                    217:                else if (*p >= 'A' && *p <= 'F')
                    218:                        n = 16 * n + *p - 'A' + 10;
                    219:        }
                    220:        *pp = p;
                    221:        return n;
                    222: }
                    223: 
                    224: #define isoctdigit(c) ((c) >= '0' && (c) <= '8')       /* multiple use of arg */
                    225: 
                    226: quoted(char **pp)      /* pick up next thing after a \\ */
                    227:                        /* and increment *pp */
                    228: {
                    229:        char *p = *pp;
                    230:        int c;
                    231: 
                    232:        if ((c = *p++) == 't')
                    233:                c = '\t';
                    234:        else if (c == 'n')
                    235:                c = '\n';
                    236:        else if (c == 'f')
                    237:                c = '\f';
                    238:        else if (c == 'r')
                    239:                c = '\r';
                    240:        else if (c == 'b')
                    241:                c = '\b';
                    242:        else if (c == '\\')
                    243:                c = '\\';
                    244:        else if (c == 'x') {    /* hexadecimal goo follows */
                    245:                c = hexstr(&p);
                    246:        } else if (isoctdigit(c)) {     /* \d \dd \ddd */
                    247:                int n = c - '0';
                    248:                if (isoctdigit(*p)) {
                    249:                        n = 8 * n + *p++ - '0';
                    250:                        if (isoctdigit(*p))
                    251:                                n = 8 * n + *p++ - '0';
                    252:                }
                    253:                c = n;
                    254:        } /* else */
                    255:                /* c = c; */
                    256:        *pp = p;
                    257:        return c;
                    258: }
                    259: 
                    260: uchar *cclenter(uchar *p)
                    261: {
                    262:        register int i, c, c2;
                    263:        uchar *op;
                    264: 
                    265:        op = p;
                    266:        i = 0;
                    267:        while ((c = *p++) != 0) {
                    268:                if (c == '\\') {
                    269:                        c = quoted(&p);
                    270:                } else if (c == '-' && i > 0 && chars[i-1] != 0) {
                    271:                        if (*p != 0) {
                    272:                                c = chars[i-1];
                    273:                                c2 = *p++;
                    274:                                if (c2 == '\\')
                    275:                                        c2 = quoted(&p);
                    276:                                while (c < c2) {
                    277:                                        if (i >= MAXLIN-1)
                    278:                                                overflo("character class too big");
                    279:                                        chars[i++] = ++c;
                    280:                                }
                    281:                                continue;
                    282:                        }
                    283:                }
                    284:                if (i >= MAXLIN-1)
                    285:                        overflo("character class too big");
                    286:                chars[i++] = c;
                    287:        }
                    288:        chars[i++] = '\0';
                    289:        dprintf( ("cclenter: in = |%s|, out = |%s|\n", op, chars) );
                    290:        xfree(op);
                    291:        return(tostring(chars));
                    292: }
                    293: 
                    294: void overflo(uchar *s)
                    295: {
                    296:        ERROR "regular expression too big: %s", s FATAL;
                    297: }
                    298: 
                    299: void cfoll(fa *f, Node *v)     /* enter follow set of each leaf of vertex v into lfollow[leaf] */
                    300: {
                    301:        register int i;
                    302:        register int *p;
                    303: 
                    304:        switch(type(v)) {
                    305:        LEAF
                    306:                f->re[(int) left(v)].ltype = type(v);
                    307:                f->re[(int) left(v)].lval = (long) right(v);    /* assumes ptr & long fit */
                    308:                for (i=0; i<=f->accept; i++)
                    309:                        setvec[i] = 0;
                    310:                setcnt = 0;
                    311:                follow(v);      /* computes setvec and setcnt */
                    312:                if ((p = (int *) calloc(1, (setcnt+1)*sizeof(int))) == NULL)
                    313:                        overflo("out of space building follow set");
                    314:                f->re[(int) left(v)].lfollow = p;
                    315:                *p = setcnt;
                    316:                for (i = f->accept; i >= 0; i--)
                    317:                        if (setvec[i] == 1) *++p = i;
                    318:                break;
                    319:        UNARY
                    320:                cfoll(f,left(v));
                    321:                break;
                    322:        case CAT:
                    323:        case OR:
                    324:                cfoll(f,left(v));
                    325:                cfoll(f,right(v));
                    326:                break;
                    327:        default:        /* can't happen */
                    328:                ERROR "unknown type %d in cfoll", type(v) FATAL;
                    329:        }
                    330: }
                    331: 
                    332: first(Node *p) /* collects initially active leaves of p into setvec */
                    333:                /* returns 0 or 1 depending on whether p matches empty string */
                    334: {
                    335:        register int b;
                    336: 
                    337:        switch(type(p)) {
                    338:        LEAF
                    339:                if (setvec[(int) left(p)] != 1) {
                    340:                        setvec[(int) left(p)] = 1;
                    341:                        setcnt++;
                    342:                }
                    343:                if (type(p) == CCL && (*(uchar *) right(p)) == '\0')
                    344:                        return(0);              /* empty CCL */
                    345:                else return(1);
                    346:        case PLUS:
                    347:                if (first(left(p)) == 0) return(0);
                    348:                return(1);
                    349:        case STAR:
                    350:        case QUEST:
                    351:                first(left(p));
                    352:                return(0);
                    353:        case CAT:
                    354:                if (first(left(p)) == 0 && first(right(p)) == 0) return(0);
                    355:                return(1);
                    356:        case OR:
                    357:                b = first(right(p));
                    358:                if (first(left(p)) == 0 || b == 0) return(0);
                    359:                return(1);
                    360:        }
                    361:        ERROR "unknown type %d in first", type(p) FATAL;        /* can't happen */
                    362:        return(-1);
                    363: }
                    364: 
                    365: void follow(Node *v)   /* collects leaves that can follow v into setvec */
                    366: {
                    367:        Node *p;
                    368: 
                    369:        if (type(v) == FINAL)
                    370:                return;
                    371:        p = parent(v);
                    372:        switch (type(p)) {
                    373:        case STAR:
                    374:        case PLUS:
                    375:                first(v);
                    376:                follow(p);
                    377:                return;
                    378: 
                    379:        case OR:
                    380:        case QUEST:
                    381:                follow(p);
                    382:                return;
                    383: 
                    384:        case CAT:
                    385:                if (v == left(p)) {     /* v is left child of p */
                    386:                        if (first(right(p)) == 0) {
                    387:                                follow(p);
                    388:                                return;
                    389:                        }
                    390:                }
                    391:                else            /* v is right child */
                    392:                        follow(p);
                    393:                return;
                    394:        }
                    395: }
                    396: 
                    397: member(int c, uchar *s)        /* is c in s? */
                    398: {
                    399:        while (*s)
                    400:                if (c == *s++)
                    401:                        return(1);
                    402:        return(0);
                    403: }
                    404: 
                    405: 
                    406: match(fa *f, uchar *p)
                    407: {
                    408:        register int s, ns;
                    409: 
                    410:        s = f->reset?makeinit(f,0):f->initstat;
                    411:        if (f->out[s])
                    412:                return(1);
                    413:        do {
                    414:                if (ns=f->gototab[s][*p])
                    415:                        s=ns;
                    416:                else
                    417:                        s=cgoto(f,s,*p);
                    418:                if (f->out[s])
                    419:                        return(1);
                    420:        } while (*p++ != 0);
                    421:        return(0);
                    422: }
                    423: 
                    424: pmatch(fa *f, uchar *p)
                    425: {
                    426:        register int s, ns;
                    427:        register uchar *q;
                    428:        int i, k;
                    429: 
                    430:        s = f->reset?makeinit(f,1):f->initstat;
                    431:        patbeg = p;
                    432:        patlen = -1;
                    433:        do {
                    434:                q = p;
                    435:                do {
                    436:                        if (f->out[s])          /* final state */
                    437:                                patlen = q-p;
                    438:                        if (ns=f->gototab[s][*q])
                    439:                                s=ns;
                    440:                        else
                    441:                                s=cgoto(f,s,*q);
                    442:                        if (s==1)       /* no transition */
                    443:                                if (patlen >= 0) {
                    444:                                        patbeg = p;
                    445:                                        return(1);
                    446:                                }
                    447:                                else
                    448:                                        goto nextin;    /* no match */
                    449:                } while (*q++ != 0);
                    450:                if (f->out[s])
                    451:                        patlen = q-p-1; /* don't count $ */
                    452:                if (patlen >= 0) {
                    453:                        patbeg = p;
                    454:                        return(1);
                    455:                }
                    456:        nextin:
                    457:                s = 2;
                    458:                if (f->reset) {
                    459:                        for (i=2; i<=f->curstat; i++)
                    460:                                xfree(f->posns[i]);
                    461:                        k = *f->posns[0];                       
                    462:                        if ((f->posns[2] = (int *) calloc(1, (k+1)*sizeof(int))) == NULL)
                    463:                                overflo("out of space in pmatch");
                    464:                        for (i=0; i<=k; i++)
                    465:                                (f->posns[2])[i] = (f->posns[0])[i];
                    466:                        f->initstat = f->curstat = 2;
                    467:                        f->out[2] = f->out[0];
                    468:                        for (i=0; i<NCHARS; i++)
                    469:                                f->gototab[2][i] = 0;
                    470:                }
                    471:        } while (*p++ != 0);
                    472:        return (0);
                    473: }
                    474: 
                    475: nematch(fa *f, uchar *p)
                    476: {
                    477:        register int s, ns;
                    478:        register uchar *q;
                    479:        int i, k;
                    480: 
                    481:        s = f->reset?makeinit(f,1):f->initstat;
                    482:        patlen = -1;
                    483:        while (*p) {
                    484:                q = p;
                    485:                do {
                    486:                        if (f->out[s])          /* final state */
                    487:                                patlen = q-p;
                    488:                        if (ns=f->gototab[s][*q])
                    489:                                s=ns;
                    490:                        else
                    491:                                s=cgoto(f,s,*q);
                    492:                        if (s==1)       /* no transition */
                    493:                                if (patlen > 0) {
                    494:                                        patbeg = p;
                    495:                                        return(1);
                    496:                                }
                    497:                                else
                    498:                                        goto nnextin;   /* no nonempty match */
                    499:                } while (*q++ != 0);
                    500:                if (f->out[s])
                    501:                        patlen = q-p-1; /* don't count $ */
                    502:                if (patlen > 0 ) {
                    503:                        patbeg = p;
                    504:                        return(1);
                    505:                }
                    506:        nnextin:
                    507:                s = 2;
                    508:                if (f->reset) {
                    509:                        for (i=2; i<=f->curstat; i++)
                    510:                                xfree(f->posns[i]);
                    511:                        k = *f->posns[0];                       
                    512:                        if ((f->posns[2] = (int *) calloc(1, (k+1)*sizeof(int))) == NULL)
                    513:                                overflo("out of state space");
                    514:                        for (i=0; i<=k; i++)
                    515:                                (f->posns[2])[i] = (f->posns[0])[i];
                    516:                        f->initstat = f->curstat = 2;
                    517:                        f->out[2] = f->out[0];
                    518:                        for (i=0; i<NCHARS; i++)
                    519:                                f->gototab[2][i] = 0;
                    520:                }
                    521:        p++;
                    522:        }
                    523:        return (0);
                    524: }
                    525: 
                    526: Node *reparse(uchar *p)
                    527: {
                    528:        /* parses regular expression pointed to by p */
                    529:        /* uses relex() to scan regular expression */
                    530:        Node *np;
                    531: 
                    532:        dprintf( ("reparse <%s>\n", p) );
                    533:        lastre = prestr = p;    /* prestr points to string to be parsed */
                    534:        rtok = relex();
                    535:        if (rtok == '\0')
                    536:                ERROR "empty regular expression" FATAL;
                    537:        np = regexp();
                    538:        if (rtok != '\0')
                    539:                ERROR "syntax error in regular expression %s at %s", lastre, prestr FATAL;
                    540:        return(np);
                    541: }
                    542: 
                    543: Node *regexp(void)
                    544: {
                    545:        return (alt(concat(primary())));
                    546: }
                    547: 
                    548: Node *primary(void)
                    549: {
                    550:        Node *np;
                    551: 
                    552:        switch (rtok) {
                    553:        case CHAR:
                    554:                np = op2(CHAR, NIL, (Node *) rlxval);
                    555:                rtok = relex();
                    556:                return (unary(np));
                    557:        case ALL:
                    558:                rtok = relex();
                    559:                return (unary(op2(ALL, NIL, NIL)));
                    560:        case DOT:
                    561:                rtok = relex();
                    562:                return (unary(op2(DOT, NIL, NIL)));
                    563:        case CCL:
                    564:                np = op2(CCL, NIL, (Node*) cclenter(rlxstr));
                    565:                rtok = relex();
                    566:                return (unary(np));
                    567:        case NCCL:
                    568:                np = op2(NCCL, NIL, (Node *) cclenter(rlxstr));
                    569:                rtok = relex();
                    570:                return (unary(np));
                    571:        case '^':
                    572:                rtok = relex();
                    573:                return (unary(op2(CHAR, NIL, (Node *) HAT)));
                    574:        case '$':
                    575:                rtok = relex();
                    576:                return (unary(op2(CHAR, NIL, NIL)));
                    577:        case '(':
                    578:                rtok = relex();
                    579:                if (rtok == ')') {      /* special pleading for () */
                    580:                        rtok = relex();
                    581:                        return unary(op2(CCL, NIL, (Node *) tostring("")));
                    582:                }
                    583:                np = regexp();
                    584:                if (rtok == ')') {
                    585:                        rtok = relex();
                    586:                        return (unary(np));
                    587:                }
                    588:                else
                    589:                        ERROR "syntax error in regular expression %s at %s", lastre, prestr FATAL;
                    590:        default:
                    591:                ERROR "illegal primary in regular expression %s at %s", lastre, prestr FATAL;
                    592:        }
                    593:        return 0;       /*NOTREACHED*/
                    594: }
                    595: 
                    596: Node *concat(Node *np)
                    597: {
                    598:        switch (rtok) {
                    599:        case CHAR: case DOT: case ALL: case CCL: case NCCL: case '$': case '(':
                    600:                return (concat(op2(CAT, np, primary())));
                    601:        }
                    602:        return (np);
                    603: }
                    604: 
                    605: Node *alt(Node *np)
                    606: {
                    607:        if (rtok == OR) {
                    608:                rtok = relex();
                    609:                return (alt(op2(OR, np, concat(primary()))));
                    610:        }
                    611:        return (np);
                    612: }
                    613: 
                    614: Node *unary(Node *np)
                    615: {
                    616:        switch (rtok) {
                    617:        case STAR:
                    618:                rtok = relex();
                    619:                return (unary(op2(STAR, np, NIL)));
                    620:        case PLUS:
                    621:                rtok = relex();
                    622:                return (unary(op2(PLUS, np, NIL)));
                    623:        case QUEST:
                    624:                rtok = relex();
                    625:                return (unary(op2(QUEST, np, NIL)));
                    626:        default:
                    627:                return (np);
                    628:        }
                    629: }
                    630: 
                    631: relex(void)            /* lexical analyzer for reparse */
                    632: {
                    633:        register int c;
                    634:        uchar cbuf[MAXLIN];
                    635:        int clen, cflag;
                    636: 
                    637:        switch (c = *prestr++) {
                    638:        case '|': return OR;
                    639:        case '*': return STAR;
                    640:        case '+': return PLUS;
                    641:        case '?': return QUEST;
                    642:        case '.': return DOT;
                    643:        case '\0': prestr--; return '\0';
                    644:        case '^':
                    645:        case '$':
                    646:        case '(':
                    647:        case ')':
                    648:                return c;
                    649:        case '\\':
                    650:                rlxval = quoted(&prestr);
                    651:                return CHAR;
                    652:        default:
                    653:                rlxval = c;
                    654:                return CHAR;
                    655:        case '[': 
                    656:                clen = 0;
                    657:                if (*prestr == '^') {
                    658:                        cflag = 1;
                    659:                        prestr++;
                    660:                }
                    661:                else
                    662:                        cflag = 0;
                    663:                for ( ; clen < MAXLIN-1; ) {
                    664:                        if ((c = *prestr++) == '\\') {
                    665:                                cbuf[clen++] = '\\';
                    666:                                if ((c = *prestr++) == '\0')
                    667:                                        ERROR "nonterminated character class %.20s...", lastre FATAL;
                    668:                                cbuf[clen++] = c;
                    669:                        } else if (c == ']') {
                    670:                                cbuf[clen] = 0;
                    671:                                rlxstr = tostring(cbuf);
                    672:                                if (cflag == 0)
                    673:                                        return CCL;
                    674:                                else
                    675:                                        return NCCL;
                    676:                        } else if (c == '\n') {
                    677:                                ERROR "newline in character class %.20s...", lastre FATAL;
                    678:                        } else if (c == '\0') {
                    679:                                ERROR "nonterminated character class %.20s", lastre FATAL;
                    680:                        } else
                    681:                                cbuf[clen++] = c;
                    682:                }
                    683:                if (clen >= MAXLIN-1)
                    684:                        ERROR "character class %.20s... too long", cbuf FATAL;
                    685:        }
                    686:        /* can't happen */
                    687:        return 0;
                    688: }
                    689: 
                    690: int cgoto(fa *f, int s, int c)
                    691: {
                    692:        register int i, j, k;
                    693:        register int *p, *q;
                    694: 
                    695:        for (i=0; i<=f->accept; i++)
                    696:                setvec[i] = 0;
                    697:        setcnt = 0;
                    698:        /* compute positions of gototab[s,c] into setvec */
                    699:        p = f->posns[s];
                    700:        for (i=1; i<=*p; i++) {
                    701:                if ((k = f->re[p[i]].ltype) != FINAL) {
                    702:                        if (k == CHAR && c == f->re[p[i]].lval
                    703:                                || k == DOT && c != 0 && c != HAT
                    704:                                || k == ALL && c != 0
                    705:                                || k == CCL && member(c, (uchar *) f->re[p[i]].lval)
                    706:                                || k == NCCL && !member(c, (uchar *) f->re[p[i]].lval) && c != 0 && c != HAT) {
                    707:                                        q = f->re[p[i]].lfollow;
                    708:                                        for (j=1; j<=*q; j++) {
                    709:                                                if (setvec[q[j]] == 0) {
                    710:                                                        setcnt++;
                    711:                                                        setvec[q[j]] = 1;
                    712:                                                }
                    713:                                        }
                    714:                                }
                    715:                }
                    716:        }
                    717:        /* determine if setvec is a previous state */
                    718:        tmpset[0] = setcnt;
                    719:        j = 1;
                    720:        for (i = f->accept; i >= 0; i--)
                    721:                if (setvec[i]) {
                    722:                        tmpset[j++] = i;
                    723:                }
                    724:        /* tmpset == previous state? */
                    725:        for (i=1; i<= f->curstat; i++) {
                    726:                p = f->posns[i];
                    727:                if ((k = tmpset[0]) != p[0])
                    728:                        goto different;
                    729:                for (j = 1; j <= k; j++)
                    730:                        if (tmpset[j] != p[j])
                    731:                                goto different;
                    732:                /* setvec is state i */
                    733:                f->gototab[s][c] = i;
                    734:                return i;
                    735:        different:;
                    736:        }
                    737: 
                    738:        /* add tmpset to current set of states */
                    739:        if (f->curstat >= NSTATES-1) {
                    740:                f->curstat = 2;
                    741:                f->reset = 1;
                    742:                for (i=2; i<NSTATES; i++)
                    743:                        xfree(f->posns[i]);
                    744:        }
                    745:        else
                    746:                ++(f->curstat);
                    747:        for (i=0; i<NCHARS; i++)
                    748:                f->gototab[f->curstat][i] = 0;
                    749:        xfree(f->posns[f->curstat]);
                    750:        if ((p = (int *) calloc(1, (setcnt+1)*sizeof(int))) == NULL)
                    751:                overflo("out of space in cgoto");
                    752: 
                    753:        f->posns[f->curstat] = p;
                    754:        f->gototab[s][c] = f->curstat;
                    755:        for (i = 0; i <= setcnt; i++)
                    756:                p[i] = tmpset[i];
                    757:        if (setvec[f->accept])
                    758:                f->out[f->curstat] = 1;
                    759:        else
                    760:                f->out[f->curstat] = 0;
                    761:        return f->curstat;
                    762: }
                    763: 
                    764: 
                    765: void freefa(fa *f)
                    766: {
                    767: 
                    768:        register int i;
                    769: 
                    770:        if (f == NULL)
                    771:                return;
                    772:        for (i=0; i<=f->curstat; i++)
                    773:                xfree(f->posns[i]);
                    774:        for (i=0; i<=f->accept; i++) {
                    775:                xfree(f->re[i].lfollow);
                    776:                if (f->re[i].ltype == CCL || f->re[i].ltype == NCCL)
                    777:                        xfree(f->re[i].lval);
                    778:        }
                    779:        xfree(f->restr);
                    780:        xfree(f);
                    781: }

unix.superglobalmegacorp.com

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