Annotation of researchv10no/cmd/gre/eg.c, revision 1.1.1.1

1.1       root        1: #include       "re.h"
                      2: #include       "lre.h"
                      3: #include       "hdr.h"
                      4: 
                      5: int re_debug = 0;
                      6: 
                      7: #define        RESET(r, ps)    COPY(r, ps, begin)
                      8: #define        SET(r, ps, n)   {if(r->ps.base[n] == 0) r->ps.count++, r->ps.base[n] = r->ps.last, r->ps.last = n; }
                      9: #define        GET(ps, n)      for(n = ps.last; n > 0; n = ps.base[n])
                     10: #define        COPY(r, to, from)       memmove((char *)r->to.base, (char *)r->from.base, r->maxid*sizeof(int)), r->to.count = r->from.count, r->to.last = r->from.last
                     11: 
                     12: static State *addstate(re_re *r, Positionset *ps);
                     13: static int first(re_re *, Expr *);
                     14: static int match(re_re *, Expr *, int);
                     15: static State *nextstate(re_re *, State *, int);
                     16: #ifdef DEBUG
                     17: static void ppr(Positionset *, char *);
                     18: #endif
                     19: 
                     20: typedef enum { NORMAL, ACCEPT, ACCEPT_EOP, FAIL } Out;
                     21: 
                     22: static void
                     23: eptr(register re_re *r, register Expr *e)
                     24: {
                     25:        if((e->id < 0) || (e->id >= r->maxid)){
                     26:                EPR "eptr abort: r=%ld[maxid=%d] e=%ld[id=%d]\n", r, r->maxid, e, e->id);
                     27:                abort();
                     28:        }
                     29:        r->ptr[e->id] = e;
                     30:        if((e->type != Charclass) && (e->type != Compcharclass)){
                     31:                if(e->l)
                     32:                        eptr(r, e->l);
                     33:                if(e->r)
                     34:                        eptr(r, e->r);
                     35:        }
                     36: }
                     37: 
                     38: re_re *
                     39: egprep(enum Parsetype parser, unsigned char *b, unsigned char *e, unsigned char *map, int dotstar)
                     40: {
                     41:        register re_re *r;
                     42:        Expr *ecomp;
                     43:        int i;
                     44: 
                     45:        r = (re_re *)egmalloc(sizeof (re_re), "allocating re_re");
                     46:        if(r == 0)
                     47:                return 0;
                     48:        memset((char *)r, 0, sizeof (re_re));
                     49:        eg_lexinit((char *)b, (char *)e);
                     50:        if(map)
                     51:                memmove(r->mymap, (char *)map, 256);
                     52:        else
                     53:                for(i = 0; i < 256; i++)
                     54:                        r->mymap[i] = i;
                     55:        eg_lex();
                     56:        if(dotstar){
                     57:                ecomp = eg_newexpr(Star, 0, eg_newexpr(Dot, '.', (Expr *)0, (Expr *)0), (Expr *)0);
                     58:                ecomp = eg_newexpr(Cat, 0, ecomp, eg_eall(parser, r->mymap));
                     59:        } else
                     60:                ecomp = eg_eall(parser, r->mymap);
                     61:        r->root = eg_newexpr(EOP, '#', ecomp, (Expr *)0);
                     62:        egpost(r);
                     63:        r->carat = 0;
                     64:        if(r->backref || r->parens)
                     65:                egbr(r);
                     66:        else
                     67:                eginit(r, dotstar);
                     68:        return(r);
                     69: }
                     70: 
                     71: void
                     72: eginit(register re_re *r, int dotstar)
                     73: {
                     74:        int n;
                     75: 
                     76: #ifdef DEBUG
                     77:        if(TRACE(6))
                     78:                PR "eginit(r=%d, dotstar=%d)\n", r, dotstar);
                     79: #endif
                     80: #ifdef DEBUG
                     81:        if(TRACE(10)){
                     82:                char buf[EPRINTSIZE];
                     83:                eg_epr(r->root, buf, 0);
                     84:                PR "eginit: r=%d expr='%s'\n", r, buf);
                     85:        }
                     86: #endif
                     87:        r->ptr = (Expr **)egmalloc(r->maxid*sizeof(Expr *), "ptr");
                     88:        if (!r->ptr)
                     89:                return;
                     90:        eptr(r, r->root);
                     91:        r->firstpos.base = (int *)egmalloc(n = r->maxid*sizeof(int), "first base");
                     92:        if (!r->firstpos.base){
                     93:                free((char*)r->ptr);
                     94:                return;
                     95:        }
                     96:        r->begin.base = (int *)egmalloc(n, "begin base");
                     97:        if (!r->begin.base){
                     98:                free((char*)r->firstpos.base);
                     99:                free((char*)r->ptr);
                    100:                return;
                    101:        }
                    102:        r->tmp.base = (int *)egmalloc(n, "tmp base");
                    103:        if (!r->tmp.base){
                    104:                free((char*)r->begin.base);
                    105:                free((char*)r->firstpos.base);
                    106:                free((char*)r->ptr);
                    107:                return;
                    108:        }
                    109:        memset((char *)r->begin.base, 0, n);
                    110:        r->begin.count = 0;
                    111:        r->begin.last = -1;
                    112:        r->carat = dotstar;
                    113:        RESET(r, firstpos);
                    114:        if(first(r, r->root->l) == 0){
                    115:                /*
                    116:                        nullable, so include me
                    117:                */
                    118:                SET(r, firstpos, r->root->id)
                    119:        }
                    120:        if(dotstar)
                    121:                COPY(r, begin, firstpos);
                    122:        eg_stateinit(r);
                    123:        eg_clrstates(r);
                    124:        eg_posinit(r);
                    125:        (void)addstate(r, &r->firstpos);
                    126:        eg_savestate(r, dotstar? nextstate(r, r->states, RE_CARAT):r->states);
                    127:        eg_posset(r);
                    128: }
                    129: 
                    130: unsigned char *
                    131: eg_quickmatch(register re_re *r, register unsigned char *b, register unsigned char *e, int endpts)
                    132: {
                    133:        register State *s, *t;
                    134: 
                    135: #ifdef DEBUG
                    136:        if(TRACE(10)){
                    137:                char buf[EPRINTSIZE];
                    138:                eg_epr(r->root, buf, 0);
                    139:                PR "qm: r=%d expr='%s' endpts=%d\n", r, buf, endpts);
                    140:        }
                    141: #endif
                    142:        s = eg_startstate(r);
                    143:        if(endpts&RE_BEG){
                    144:                if(!r->carat){
                    145:                        if(t = s->tab[RE_CARAT])
                    146:                                s = t;
                    147:                        else
                    148:                                s = nextstate(r, s, RE_CARAT);
                    149:                        if(s->out == FAIL)
                    150:                                s = eg_startstate(r);
                    151:                }
                    152:                if(s->out){
                    153: #ifdef DEBUG
                    154:                        if(TRACE(6))
                    155:                                PR "match at ^: '%s' out=%d\n", b, s->out);
                    156: #endif
                    157:                        return((s->out == FAIL)? 0:b);
                    158:                }
                    159:        }
                    160:        while(b < e){
                    161: #ifdef DEBUG
                    162:                if(TRACE(4))
                    163:                        PR "state %d@%d[%d pos]: char '%c'\n", s-r->states, (int)s, s->npos, *b);
                    164: #endif
                    165:                if(t = s->tab[*(unsigned char *)b])
                    166:                        s = t;
                    167:                else
                    168:                        s = nextstate(r, s, *(unsigned char *)b);
                    169:                if(s->out){
                    170: #ifdef DEBUG
                    171:                        if(TRACE(6))
                    172:                                PR "match at input '%s' out=%d\n", b, s->out);
                    173: #endif
                    174:                        return((s->out == FAIL)? 0:b);
                    175:                }
                    176:                b++;
                    177:        }
                    178:        if(endpts&RE_END){
                    179:                if(t = s->tab[RE_DOLLAR])
                    180:                        s = t;
                    181:                else
                    182:                        s = nextstate(r, s, RE_DOLLAR);
                    183:        }
                    184:        if(s->out){
                    185: #ifdef DEBUG
                    186:                if(TRACE(6))
                    187:                        PR "match at $ '%s' out=%d\n", b, s->out);
                    188: #endif
                    189:                return((s->out == FAIL)? 0:b);
                    190:        }
                    191: #ifdef DEBUG
                    192:        if(TRACE(3)){
                    193:                char buf[EPRINTSIZE];
                    194: 
                    195:                eg_epr(r->root, buf, 1);
                    196:                PR "pat = %s\n", buf);
                    197:        }
                    198: #endif
                    199:        return(0);
                    200: }
                    201: 
                    202: unsigned char *
                    203: eg_lquickmatch(register re_re *r, register unsigned char *b, register unsigned char *e, int endpts)
                    204: {
                    205:        register State *s, *t;
                    206:        int outedness = 0;
                    207: 
                    208: #ifdef DEBUG
                    209:        if(TRACE(10)){
                    210:                char buf[EPRINTSIZE];
                    211:                eg_epr(r->root, buf, 0);
                    212:                PR "lqm: r=%d carat=%d expr='%s' endpts=%d\n", r, r->carat, buf, endpts);
                    213:        }
                    214: #endif
                    215:        s = eg_startstate(r);
                    216:        if(endpts&RE_BEG){
                    217:                if(!r->carat){
                    218:                        if(t = s->tab[RE_CARAT])
                    219:                                s = t;
                    220:                        else
                    221:                                s = nextstate(r, s, RE_CARAT);
                    222:                        if(s->out == FAIL)
                    223:                                s = eg_startstate(r);
                    224:                }
                    225:                if(s->out){
                    226: #ifdef DEBUG
                    227:                        if(TRACE(6))
                    228:                                PR "match at ^: '%s' out=%d\n", b, s->out);
                    229: #endif
                    230:                        if(s->out == ACCEPT_EOP)
                    231:                                return(b);
                    232:                        else if(s->out == FAIL)
                    233:                                return(0);
                    234:                        outedness = 1;
                    235:                }
                    236:        }
                    237:        /*
                    238:                look for first match
                    239:        */
                    240:        if(outedness == 0)
                    241:        for(; b < e; b++){
                    242: #ifdef DEBUG
                    243:                if(TRACE(4))
                    244:                        PR "state %d@%d[%d pos]: char '%c'\n", s-r->states, (int)s, s->npos, *b);
                    245: #endif
                    246:                if(t = s->tab[*(unsigned char *)b])
                    247:                        s = t;
                    248:                else
                    249:                        s = nextstate(r, s, *(unsigned char *)b);
                    250:                if(s->out){
                    251: #ifdef DEBUG
                    252:                        if(TRACE(4))
                    253:                                PR "    out=%d, state %d@%d\n", s->out,
                    254:                                        s-r->states, (int)s);
                    255: #endif
                    256:                        b++;
                    257:                        if((s->out == ACCEPT_EOP) || (s->out == FAIL))
                    258:                                goto finish;
                    259:                        outedness = 1;
                    260:                        break;
                    261:                }
                    262:        }
                    263:        /*
                    264:                in the following loop, we have seen a match already
                    265:                because only way outedness is zero is if b>=e
                    266:        */
                    267:        for(; b < e; b++){
                    268: #ifdef DEBUG
                    269:                if(TRACE(4))
                    270:                        PR "statex %d@%d[%d pos]: char '%c'\n", s-r->states, (int)s, s->npos, *b);
                    271: #endif
                    272:                if(t = s->tab[*(unsigned char *)b])
                    273:                        s = t;
                    274:                else
                    275:                        s = nextstate(r, s, *(unsigned char *)b);
                    276:                if(s->out == ACCEPT)
                    277:                        continue;
                    278:                if((s->out == NORMAL) || (s->out == FAIL)){
                    279: #ifdef DEBUG
                    280:                        if(TRACE(6))
                    281:                                PR "unmatch at input '%s' out=%d\n", b, s->out);
                    282: #endif
                    283:                        return(b);
                    284:                }
                    285:        }
                    286:        if(endpts&RE_END){
                    287:                if(t = s->tab[RE_DOLLAR])
                    288:                        s = t;
                    289:                else
                    290:                        s = nextstate(r, s, RE_DOLLAR);
                    291:        }
                    292: finish:
                    293:        if((s->out && (s->out != FAIL)) || outedness){
                    294: #ifdef DEBUG
                    295:                if(TRACE(6))
                    296:                        PR "match at $ '%s' out=%d\n", b, s->out);
                    297: #endif
                    298:                return(b);
                    299:        }
                    300: #ifdef DEBUG
                    301:        if(TRACE(3)){
                    302:                char buf[EPRINTSIZE];
                    303: 
                    304:                eg_epr(r->root, buf, 1);
                    305:                PR "lqm('%s') failed; out=%d, s->out=%d \n", buf, outedness, s->out);
                    306:        }
                    307: #endif
                    308:        return(0);
                    309: }
                    310: 
                    311: static
                    312: match(register re_re *r, register Expr *e, int a)
                    313: {
                    314:        switch(e->type)
                    315:        {
                    316:        case Dollar:    return(a == RE_DOLLAR);
                    317:        case Carat:     return(a == RE_CARAT);
                    318:        case Dot:       return(a < 256);
                    319:        case Literal:   return(r->mymap[a] == r->mymap[e->lit]);
                    320:        case Charclass: if(a >= 256) return(0);
                    321:                        return(memchr((char *)e->r, r->mymap[a], (int)e->l) != 0);
                    322:        case Compcharclass:
                    323:                        if(a >= 256) return(0);
                    324:                        return(memchr((char *)e->r, r->mymap[a], (int)e->l) == 0);
                    325:        }
                    326:        return(0);
                    327: }
                    328: 
                    329:        /*
                    330:                generates the followset for a node in firstpos
                    331:        */
                    332: 
                    333: static void
                    334: follow(register re_re *r, register Expr *e)
                    335: {
                    336:        register Expr *p;
                    337: 
                    338:        if(e->type == EOP)
                    339:                return;
                    340:        else
                    341:                p = e->parent;
                    342:        switch(p->type)
                    343:        {
                    344:        case EOP:
                    345:                SET(r, firstpos, p->id)
                    346:                break;
                    347:        case Plus:
                    348:        case Star:
                    349:                (void)first(r, e);
                    350:                follow(r, p);
                    351:                break;
                    352:        case Quest:
                    353:        case Alternate:
                    354:                follow(r, p);
                    355:                break;
                    356:        case Cat:
                    357:                if(e == p->l){
                    358:                        if(first(r, p->r) == 0){
                    359:                                follow(r, p);
                    360:                                break;
                    361:                        }
                    362:                } else
                    363:                        follow(r, p);
                    364:                break;
                    365:        case Group:
                    366:                follow(r, p);
                    367:                break;
                    368:        }
                    369: }
                    370: 
                    371:        /*
                    372:                first returns 0 if e is nullable and in the process,
                    373:                sets up firstpos.
                    374:        */
                    375: 
                    376: static
                    377: first(register re_re *r, register Expr *e)
                    378: {
                    379:        int k;
                    380: 
                    381:        switch(e->type)
                    382:        {
                    383:        case Carat:
                    384:        case Dollar:
                    385:        case Literal:
                    386:        case Dot:
                    387:        case Charclass:
                    388:        case Compcharclass:
                    389:                SET(r, firstpos, e->id)
                    390:                return(1);
                    391:        case EOP:
                    392:        case Star:
                    393:        case Quest:
                    394:                (void)first(r, e->l);
                    395:                return(0);
                    396:        case Group:
                    397:        case Plus:
                    398:                return(first(r, e->l));
                    399:        case Cat:
                    400:                return(first(r, e->l) || first(r, e->r));
                    401:        case Alternate:
                    402:                k = first(r, e->r);
                    403:                return(first(r, e->l) && k);
                    404:        default:
                    405:                EPR "bad type %d\n", e->type);
                    406:                abort();
                    407:                return(0);
                    408:        }
                    409: }
                    410: 
                    411: static void
                    412: efollow(register re_re *r, register Expr *e)
                    413: {
                    414:        register i, *p;
                    415: 
                    416:        RESET(r, firstpos);
                    417:        follow(r, e);
                    418:        e->flen = r->firstpos.count;
                    419:        e->follow = (int *)malloc((unsigned)(e->flen*sizeof(int)));
                    420:        if(e->follow == 0){
                    421:                char buf[100];
                    422:                SPR buf, "efollow malloc fail(%ld)\n", e->flen);
                    423:                re_error(buf);
                    424:                return;
                    425:        }
                    426:        p = e->follow;
                    427:        GET(r->firstpos, i)
                    428:                *p++ = i;
                    429:        if(p != e->follow+e->flen){
                    430:                char buf[100];
                    431:                SPR buf, "efollow length error: %d %ld\n", p-e->follow, e->flen);
                    432:                re_error(buf);
                    433:                return;
                    434:        }
                    435: }
                    436: 
                    437: static State *
                    438: addstate(register re_re *r, register Positionset *ps)
                    439: {
                    440:        register *p, j;
                    441:        register State *s;
                    442: 
                    443:        s = r->states + eg_getstate(r);
                    444:        memset((char *)s->tab, 0, sizeof(s->tab));
                    445:        s->pos = eg_posalloc(r, (int)ps->count);
                    446:        s->npos = ps->count;
                    447:        p = r->posbase+s->pos;
                    448:        GET((*ps), j)
                    449:                *p++ = j;
                    450:        if(s->out = (ps->base[r->root->id] != 0)){
                    451:                if((ps->base[r->root->id] <= 0) && (ps->last == r->root->id))
                    452:                        s->out = ACCEPT_EOP;    /* marker for only the EOP marker */
                    453:                else
                    454:                        s->out = ACCEPT;
                    455:        }
                    456:        if(s->npos == 0)
                    457:                s->out = FAIL;
                    458: #ifdef DEBUG
                    459:        if(TRACE(3)){
                    460:                char buf[2000];
                    461:                eg_spr(s->npos, s->pos+r->posbase, buf);
                    462:                PR "new state[%d]@%d %s,pos=%d out=%d\n", s-r->states, s, buf, s->pos, s->out);
                    463:        }
                    464: #endif
                    465:        return(s);
                    466: }
                    467: 
                    468: static State *
                    469: nextstate(register re_re *r, register State *s, int a)
                    470: {
                    471:        register int p, *q, *eq;
                    472:        register long i;
                    473:        State *news;
                    474:        Expr *e;
                    475: 
                    476:        RESET(r, tmp);
                    477: #ifdef DEBUG
                    478:        if(TRACE(5)){
                    479:                char buf[2000];
                    480:                ppr(&r->tmp, buf);
                    481:                PR "nextstate: reset: %s\n", buf);
                    482:        }
                    483: #endif
                    484:        for(i = s->npos, p = s->pos; i > 0; i--){
                    485:                e = r->ptr[r->posbase[p++]];
                    486: #ifdef DEBUG
                    487:                if(TRACE(11)){
                    488:                        PR "i=%d e->type=%d\n", i, e->type);
                    489:                }
                    490: #endif
                    491:                if(e->type == EOP) continue;
                    492:                if(match(r, e, a)){
                    493: #ifdef DEBUG
                    494:                        if(TRACE(11)){PR "matched %c\n", a);}
                    495: #endif
                    496:                        if(e->follow == 0)
                    497:                                efollow(r, e);
                    498:                        for(q = e->follow, eq = q+e->flen; q < eq; q++){
                    499:                                SET(r, tmp, *q)
                    500:                        }
                    501:                }
                    502:        }
                    503: #ifdef DEBUG
                    504:        if(TRACE(5)){
                    505:                char buf[2000];
                    506:                ppr(&r->tmp, buf);
                    507:                PR "nextstate(%d, '%c'): found %s\n", s-r->states, a, buf);
                    508:        }
                    509: #endif
                    510:        if(news = eg_stateof(r, &r->tmp)){
                    511:                if(a <= RE_DOLLAR)
                    512:                        s->tab[a] = news;
                    513:        } else
                    514:                news = addstate(r, &r->tmp);
                    515: #ifdef DEBUG
                    516:        if(TRACE(5)){
                    517:                PR "nextstate(%d, '%c'): returning %ld %d out=%d\n", s-r->states, a,
                    518:                        (long)news, news-r->states, news->out);
                    519:        }
                    520: #endif
                    521:        return(news);
                    522: }
                    523: 
                    524: void *
                    525: egmalloc(int n, char *s)
                    526: {
                    527:        char *x;
                    528:        char buf[256];
                    529: 
                    530:        if((x = malloc(n)) == 0){
                    531:                SPR buf, "malloc fail(%d): %s", n, s);
                    532:                re_error(buf);
                    533:                return 0;
                    534:        }
                    535:        return((void *)x);
                    536: }
                    537: 
                    538: void *
                    539: egrealloc(char *p, int n, char *s)
                    540: {
                    541:        char *x;
                    542:        char buf[256];
                    543: 
                    544:        if((x = realloc(p, n)) == 0){
                    545:                SPR buf, "realloc fail(%d): %s", n, s);
                    546:                re_error(buf);
                    547:                return 0;
                    548:        }
                    549:        return((void *)x);
                    550: }
                    551: 
                    552: #ifdef DEBUG
                    553: static void
                    554: ppr(register Positionset *ps, register char *p)
                    555: {
                    556:        register n;
                    557: 
                    558:        if(ps->count < 1){
                    559:                SPR p, "{}");
                    560:                return;
                    561:        }
                    562:        *p++ = '{';
                    563:        GET((*ps), n){
                    564:                SPR p, "%d[=%d],", n, ps->base[n]);
                    565:                p = strchr(p, 0);
                    566:        }
                    567:        p[-1] = '}';
                    568: }
                    569: #endif

unix.superglobalmegacorp.com

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