Annotation of researchv10no/cmd/mk/export/libc/regcomp.c, revision 1.1

1.1     ! root        1: #include <libc.h>
        !             2: #include "regprog.h"
        !             3: 
        !             4: /*
        !             5:  * Parser Information
        !             6:  */
        !             7: typedef struct Node{
        !             8:        Inst    *first;
        !             9:        Inst    *last;
        !            10: }Node;
        !            11: #define        NSTACK  20
        !            12: static Node    andstack[NSTACK];
        !            13: static Node    *andp;
        !            14: static int     atorstack[NSTACK];
        !            15: static int     *atorp;
        !            16: static int     cursubid;               /* id of current subexpression */
        !            17: static int     subidstack[NSTACK];     /* parallel to atorstack */
        !            18: static int     *subidp;
        !            19: static int     lastwasand;     /* Last token was operand */
        !            20: static int     nbra;
        !            21: static char    *exprp;         /* pointer to next character in source expression */
        !            22: static int     nclass;
        !            23: static Class   *classp;
        !            24: static Inst    *freep;
        !            25: static int     errors;
        !            26: 
        !            27: /* predeclared crap */
        !            28: static void operator();
        !            29: static void pushand();
        !            30: static void pushator();
        !            31: static void evaluntil();
        !            32: static void bldcclass();
        !            33: 
        !            34: static void
        !            35: rcerror(s)
        !            36:        char *s;
        !            37: {
        !            38:        errors++;
        !            39:        regerror(s);
        !            40: }
        !            41: 
        !            42: static Inst *
        !            43: newinst(t)
        !            44:        int t;
        !            45: {
        !            46:        freep->type=t;
        !            47:        freep->left=0;
        !            48:        freep->right=0;
        !            49:        return freep++;
        !            50: }
        !            51: 
        !            52: static void
        !            53: operand(t)
        !            54:        int t;
        !            55: {
        !            56:        register Inst *i;
        !            57:        if(lastwasand)
        !            58:                operator(CAT);  /* catenate is implicit */
        !            59:        i=newinst(t);
        !            60:        if(t==CCLASS)   /* ugh */
        !            61:                i->right=(Inst *)&(classp[nclass-1]);   /* UGH! */
        !            62:        pushand(i, i);
        !            63:        lastwasand=TRUE;
        !            64: }
        !            65: 
        !            66: static void
        !            67: operator(t)
        !            68:        int t;
        !            69: {
        !            70:        if(t==RBRA && --nbra<0)
        !            71:                rcerror("unmatched right paren");
        !            72:        if(t==LBRA) {
        !            73:                if (++cursubid >= NSUBEXP)
        !            74:                        rcerror ("too many subexpressions");
        !            75:                nbra++;
        !            76:                if (lastwasand)
        !            77:                        operator(CAT);
        !            78:        } else
        !            79:                evaluntil(t);
        !            80:        if(t!=RBRA)
        !            81:                pushator(t);
        !            82:        lastwasand=FALSE;
        !            83:        if(t==STAR || t==QUEST || t==PLUS || t==RBRA)
        !            84:                lastwasand=TRUE;        /* these look like operands */
        !            85: }
        !            86: 
        !            87: static void
        !            88: regerr2(s, c)
        !            89:        char *s;
        !            90: {
        !            91:        char buf[100];
        !            92:        char *cp = buf;
        !            93:        while(*s)
        !            94:                *cp++ = *s++;
        !            95:        *cp++ = c;
        !            96:        *cp = '\0'; 
        !            97:        rcerror(buf);
        !            98: }
        !            99: 
        !           100: static void
        !           101: cant(s)
        !           102:        char *s;
        !           103: {
        !           104:        char buf[100];
        !           105:        strcpy(buf, "can't happen: ");
        !           106:        strcat(buf, s);
        !           107:        rcerror(buf);
        !           108: }
        !           109: 
        !           110: static void
        !           111: pushand(f, l)
        !           112:        Inst *f, *l;
        !           113: {
        !           114:        if(andp >= &andstack[NSTACK])
        !           115:                cant("operand stack overflow");
        !           116:        andp->first=f;
        !           117:        andp->last=l;
        !           118:        andp++;
        !           119: }
        !           120: 
        !           121: static void
        !           122: pushator(t)
        !           123:        int t;
        !           124: {
        !           125:        if(atorp >= &atorstack[NSTACK])
        !           126:                cant("operator stack overflow");
        !           127:        *atorp++=t;
        !           128:        *subidp++=cursubid;
        !           129: }
        !           130: 
        !           131: static Node *
        !           132: popand(op)
        !           133: {
        !           134:        register Inst *inst;
        !           135: 
        !           136:        if(andp <= &andstack[0]) {
        !           137:                regerr2("missing operand for ", op);
        !           138:                inst=newinst(NOP);
        !           139:                pushand(inst,inst);
        !           140:        }
        !           141:        return --andp;
        !           142: }
        !           143: 
        !           144: static int
        !           145: popator()
        !           146: {
        !           147:        if(atorp <= &atorstack[0])
        !           148:                cant("operator stack underflow");
        !           149:        --subidp;
        !           150:        return *--atorp;
        !           151: }
        !           152: 
        !           153: static void
        !           154: evaluntil(pri)
        !           155:        register pri;
        !           156: {
        !           157:        register Node *op1, *op2;
        !           158:        register Inst *inst1, *inst2;
        !           159: 
        !           160:        while(pri==RBRA || atorp[-1]>=pri){
        !           161:                switch(popator()){
        !           162:                default:
        !           163:                        rcerror("unknown operator in evaluntil");
        !           164:                        break;
        !           165:                case LBRA:              /* must have been RBRA */
        !           166:                        op1=popand('(');
        !           167:                        inst2=newinst(RBRA);
        !           168:                        inst2->subid = *subidp;
        !           169:                        op1->last->next = inst2;
        !           170:                        inst1=newinst(LBRA);
        !           171:                        inst1->subid = *subidp;
        !           172:                        inst1->next=op1->first;
        !           173:                        pushand(inst1, inst2);
        !           174:                        return;
        !           175:                case OR:
        !           176:                        op2=popand('|');
        !           177:                        op1=popand('|');
        !           178:                        inst2=newinst(NOP);
        !           179:                        op2->last->next=inst2;
        !           180:                        op1->last->next=inst2;
        !           181:                        inst1=newinst(OR);
        !           182:                        inst1->right=op1->first;
        !           183:                        inst1->left=op2->first;
        !           184:                        pushand(inst1, inst2);
        !           185:                        break;
        !           186:                case CAT:
        !           187:                        op2=popand(0);
        !           188:                        op1=popand(0);
        !           189:                        op1->last->next=op2->first;
        !           190:                        pushand(op1->first, op2->last);
        !           191:                        break;
        !           192:                case STAR:
        !           193:                        op2=popand('*');
        !           194:                        inst1=newinst(OR);
        !           195:                        op2->last->next=inst1;
        !           196:                        inst1->right=op2->first;
        !           197:                        pushand(inst1, inst1);
        !           198:                        break;
        !           199:                case PLUS:
        !           200:                        op2=popand('+');
        !           201:                        inst1=newinst(OR);
        !           202:                        op2->last->next=inst1;
        !           203:                        inst1->right=op2->first;
        !           204:                        pushand(op2->first, inst1);
        !           205:                        break;
        !           206:                case QUEST:
        !           207:                        op2=popand('?');
        !           208:                        inst1=newinst(OR);
        !           209:                        inst2=newinst(NOP);
        !           210:                        inst1->left=inst2;
        !           211:                        inst1->right=op2->first;
        !           212:                        op2->last->next=inst2;
        !           213:                        pushand(inst1, inst2);
        !           214:                        break;
        !           215:                }
        !           216:        }
        !           217: }
        !           218: 
        !           219: static Prog *
        !           220: optimize(pp)
        !           221:        Prog *pp;
        !           222: {
        !           223:        register Inst *inst, *target;
        !           224:        int size;
        !           225:        Prog *npp;
        !           226:        int diff;
        !           227: 
        !           228:        /*
        !           229:         *  get rid of NOOP chains
        !           230:         */
        !           231:        for(inst=pp->firstinst; inst->type!=END; inst++){
        !           232:                target=inst->next;
        !           233:                while(target->type == NOP)
        !           234:                        target=target->next;
        !           235:                inst->next=target;
        !           236:        }
        !           237: 
        !           238:        /*
        !           239:         *  The original allocation is for an area larger than
        !           240:         *  necessary.  Reallocate to the actual space used
        !           241:         *  and then relocate the code.
        !           242:         */
        !           243:        size = sizeof(Prog) + (freep - pp->firstinst)*sizeof(Inst);
        !           244:        npp = (Prog *)realloc((char *)pp, size);
        !           245:        if(npp==NULL || npp==pp)
        !           246:                return(pp);
        !           247:        diff = (char *)npp - (char *)pp;
        !           248:        freep = (Inst *)((char *)freep + diff);
        !           249:        for(inst=npp->firstinst; inst<freep; inst++){
        !           250:                switch(inst->type){
        !           251:                case OR:
        !           252:                case STAR:
        !           253:                case PLUS:
        !           254:                case QUEST:
        !           255:                case CCLASS:
        !           256:                        *(char **)&inst->right += diff;
        !           257:                        break;
        !           258:                }
        !           259:                *(char **)&inst->left += diff;
        !           260:        }
        !           261:        *(char **)&npp->startinst += diff;
        !           262:        return(npp);
        !           263: }
        !           264: 
        !           265: #ifdef DEBUG
        !           266: static void
        !           267: dumpstack(){
        !           268:        Node *stk;
        !           269:        int *ip;
        !           270: 
        !           271:        printf("operators\n");
        !           272:        for(ip=atorstack; ip<atorp; ip++)
        !           273:                printf("0%o\n", *ip);
        !           274:        printf("operands\n");
        !           275:        for(stk=andstack; stk<andp; stk++)
        !           276:                printf("0%o\t0%o\n", stk->first->type, stk->last->type);
        !           277: }
        !           278: 
        !           279: static void
        !           280: dump(pp)
        !           281:        Prog *pp;
        !           282: {
        !           283:        Inst *l;
        !           284: 
        !           285:        l=pp->firstinst;
        !           286:        do{
        !           287:                printf("%d:\t0%o\t%d\t%d\n", l-pp->firstinst, l->type,
        !           288:                        l->left-pp->firstinst, l->right-pp->firstinst);
        !           289:        }while(l++->type);
        !           290: }
        !           291: #endif
        !           292: 
        !           293: static void
        !           294: startlex(s)
        !           295:        char *s;
        !           296: {
        !           297:        exprp=s;
        !           298:        nclass=0;
        !           299:        nbra=0;
        !           300: }
        !           301: 
        !           302: static Class *
        !           303: newclass(){
        !           304:        register Class *p;
        !           305:        register n;
        !           306: 
        !           307:        if(nclass >= NCLASS)
        !           308:                regerr2("too many character classes; limit", NCLASS+'0');
        !           309:        p = &(classp[nclass++]);
        !           310:        for(n=0; n<16; n++)
        !           311:                p->map[n]=0;
        !           312:        return p;
        !           313: }
        !           314: 
        !           315: static int
        !           316: lex(){
        !           317:        register c= *exprp++;
        !           318: 
        !           319:        switch(c){
        !           320:        case '\\':
        !           321:                if(*exprp)
        !           322:                        c= *exprp++;
        !           323:                break;
        !           324:        case 0:
        !           325:                c=END;
        !           326:                --exprp;        /* In case we come here again */
        !           327:                break;
        !           328:        case '*':
        !           329:                c=STAR;
        !           330:                break;
        !           331:        case '?':
        !           332:                c=QUEST;
        !           333:                break;
        !           334:        case '+':
        !           335:                c=PLUS;
        !           336:                break;
        !           337:        case '|':
        !           338:                c=OR;
        !           339:                break;
        !           340:        case '.':
        !           341:                c=ANY;
        !           342:                break;
        !           343:        case '(':
        !           344:                c=LBRA;
        !           345:                break;
        !           346:        case ')':
        !           347:                c=RBRA;
        !           348:                break;
        !           349:        case '^':
        !           350:                c=BOL;
        !           351:                break;
        !           352:        case '$':
        !           353:                c=EOL;
        !           354:                break;
        !           355:        case '[':
        !           356:                c=CCLASS;
        !           357:                bldcclass();
        !           358:                break;
        !           359:        }
        !           360:        return c;
        !           361: }
        !           362: 
        !           363: static int
        !           364: nextc(){
        !           365:        if(exprp[0]==0 || (exprp[0]=='\\' && exprp[1]==0))
        !           366:                rcerror("malformed '[]'");
        !           367:        if(exprp[0]=='\\'){
        !           368:                exprp++;
        !           369:                return *exprp++|0200;
        !           370:        }
        !           371:        return *exprp++;
        !           372: }
        !           373: 
        !           374: static void
        !           375: bldcclass(){
        !           376:        register c1, c2;
        !           377:        register Class *classp;
        !           378:        register negate=FALSE;
        !           379: 
        !           380:        classp=newclass();
        !           381:        /* we have already seen the '[' */
        !           382:        if(*exprp=='^'){
        !           383:                negate=TRUE;
        !           384:                exprp++;
        !           385:        }
        !           386:        while((c1=c2=nextc()) != ']'){
        !           387:                if(*exprp=='-'){
        !           388:                        exprp++;        /* eat '-' */
        !           389:                        if((c2=nextc()) == ']')
        !           390:                                rcerror("malformed '[]'");
        !           391:                }
        !           392:                for((c1&=0177), (c2&=0177); c1<=c2; c1++)
        !           393:                        classp->map[c1/8] |= 1<<(c1&07);
        !           394:        }
        !           395:        if(negate)
        !           396:                for(c1=0; c1<16; c1++)
        !           397:                        classp->map[c1]^=0377;
        !           398:        classp->map[0] &= 0376;         /* exclude NUL */
        !           399: }
        !           400: 
        !           401: extern regexp *
        !           402: regcomp(s)
        !           403:        char *s;
        !           404: {
        !           405:        register token;
        !           406:        Prog *pp;
        !           407: 
        !           408:        /* get memory for the program */
        !           409:        pp = (Prog *)malloc(sizeof(Prog) + 3*sizeof(Inst)*strlen(s));
        !           410:        if (pp == NULL) {
        !           411:                rcerror("out of memory");
        !           412:                return NULL;
        !           413:        }
        !           414:        freep = pp->firstinst;
        !           415:        classp = pp->class;
        !           416:        errors = 0;
        !           417: 
        !           418:        /* go compile the sucker */
        !           419:        startlex(s);
        !           420:        atorp=atorstack;
        !           421:        andp=andstack;
        !           422:        subidp=subidstack;
        !           423:        lastwasand=FALSE;
        !           424:        cursubid=0;
        !           425: 
        !           426:        /* Start with a low priority operator to prime parser */
        !           427:        pushator(START-1);
        !           428:        while((token=lex()) != END){
        !           429:                if((token&0300) == OPERATOR)
        !           430:                        operator(token);
        !           431:                else
        !           432:                        operand(token);
        !           433:        }
        !           434: 
        !           435:        /* Close with a low priority operator */
        !           436:        evaluntil(START);
        !           437: 
        !           438:        /* Force END */
        !           439:        operand(END);
        !           440:        evaluntil(START);
        !           441: #ifdef DEBUG
        !           442:        dumpstack();
        !           443: #endif
        !           444:        if(nbra)
        !           445:                rcerror("unmatched left paren");
        !           446:        --andp; /* points to first and only operand */
        !           447:        pp->startinst=andp->first;
        !           448: #ifdef DEBUG
        !           449:        dump(pp);
        !           450: #endif
        !           451:        pp = optimize(pp);
        !           452: #ifdef DEBUG
        !           453:        printf("start: %d\n", andp->first-pp->firstinst);
        !           454:        dump(pp);
        !           455: #endif
        !           456:        if (errors) {
        !           457:                free((char *)pp);
        !           458:                pp = NULL;
        !           459:        }
        !           460:        return (regexp *)pp;
        !           461: }

unix.superglobalmegacorp.com

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