Annotation of researchv9/libc/gen/regcomp.c, revision 1.1

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

unix.superglobalmegacorp.com

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