Annotation of researchv10no/cmd/twig/rawwalker.c1, revision 1.1

1.1     ! root        1: /*
        !             2:  * See Aho, Corasick Comm ACM 18:6, and Hoffman and O'Donell JACM 29:1
        !             3:  * for detail of the matching algorithm
        !             4:  */
        !             5: 
        !             6: /* turn this flag on if your machine has a fast byte string zero operation */
        !             7: /*#define BZERO        1*/
        !             8: int mtDebug = 0;
        !             9: int treedebug = 0;
        !            10: extern int _machstep();
        !            11: extern short int mtStart;
        !            12: extern short int mtTable[], mtAccept[], mtMap[], mtPaths[], mtPathStart[];
        !            13: #ifdef LINE_XREF
        !            14:        extern short int mtLine[];
        !            15: #endif
        !            16: extern NODEPTR mtGetNodes(), mtAction();
        !            17: extern skeleton *_allocskel();
        !            18: extern __match *_allocmatch();
        !            19: extern __partial *_allocpartial();
        !            20: 
        !            21: #define MPBLOCKSIZ 3000
        !            22: __match *_mpblock[MPBLOCKSIZ], **_mpbtop;
        !            23: 
        !            24: /*
        !            25:  * See sym.h in the preprocessor for details
        !            26:  * Basically used to support eh $%n$ construct.
        !            27:  */
        !            28: __match **
        !            29: _getleaves (mp, skp)
        !            30:        register __match *mp; register skeleton *skp;
        !            31: {
        !            32:        skeleton *stack[MAXDEPTH];
        !            33:        skeleton **stp = stack;
        !            34:        register short int *sip = &mtPaths[mtPathStart[mp->tree]];
        !            35:        register __match **mmp = _mpbtop;
        !            36:        __match **mmp2 = mmp;
        !            37:        if((_mpbtop += *sip++ + 1) > &_mpblock[MPBLOCKSIZ]) {
        !            38:                printf ("ich: %d\n", _mpbtop-_mpblock);
        !            39:                assert(0);
        !            40:        }
        !            41: 
        !            42:        for(;;)
        !            43:                switch(*sip++) {
        !            44:                case ePUSH:
        !            45:                        *stp++ = skp;
        !            46:                        skp = skp->leftchild;
        !            47:                        break;
        !            48: 
        !            49:                case eNEXT:
        !            50:                        skp = skp->sibling;
        !            51:                        break;
        !            52: 
        !            53:                case eEVAL:
        !            54:                        if ((mp = skp->succ[M_DETAG(*sip++)])==NULL) abort();
        !            55:                        *mmp++ = mp;
        !            56:                        break;
        !            57: 
        !            58:                case ePOP:
        !            59:                        skp = *--stp;
        !            60:                        break;
        !            61: 
        !            62:                case eSTOP:
        !            63:                        *mmp = NULL;
        !            64:                        return (mmp2);
        !            65:                }
        !            66: }
        !            67: 
        !            68: _evalleaves (mpp)
        !            69:        register __match **mpp;
        !            70: {
        !            71:        for (; *mpp!=NULL; mpp++) {
        !            72:                register __match *mp = *mpp;
        !            73:                _do (mp->skel, mp, 1);
        !            74:        }
        !            75: }
        !            76: 
        !            77: 
        !            78: _do(sp, winner, evalall)
        !            79:        skeleton *sp; register __match *winner; int evalall;
        !            80: {
        !            81:        register __match **mpp;
        !            82:        register skeleton *skel = winner->skel;
        !            83:        if(winner==NULL) {
        !            84:                _prskel(sp, 0);
        !            85:                puts ("no winner");
        !            86:                return;
        !            87:        }
        !            88:        if(winner->mode==xDEFER || (evalall && winner->mode!=xTOPDOWN))
        !            89:                REORDER (winner->lleaves);
        !            90:        mtSetNodes (skel->parent, skel->nson,
        !            91:                skel->root=mtAction (winner->tree, winner->lleaves, sp));
        !            92: }
        !            93: 
        !            94: skeleton *
        !            95: _walk(sp, ostate)
        !            96:        register skeleton *sp;
        !            97:        int ostate;
        !            98: {
        !            99:        int state, nstate, nson;
        !           100:        register __partial *pp;
        !           101:        register __match *mp, *mp2;
        !           102:        register skeleton *nsp, *lastchild = NULL;
        !           103:        NODEPTR son, root;
        !           104: 
        !           105:        root = sp->root;
        !           106:        nson = 1; sp->mincost = INFINITY;
        !           107:        state = _machstep (ostate, root, mtValue(root));
        !           108: 
        !           109:        while((son = mtGetNodes(root, nson))!=NULL) {
        !           110:                nstate = _machstep (state, NULL, MV_BRANCH(nson));
        !           111:                nsp = _allocskel();
        !           112:                nsp->root = son;
        !           113:                nsp->parent = root;
        !           114:                nsp->nson = nson;
        !           115:                _walk(nsp, nstate);
        !           116:                if(COSTLESS(nsp->mincost, INFINITY)) {
        !           117:                        assert (nsp->winner->mode==xREWRITE);
        !           118:                        if (mtDebug || treedebug) {
        !           119:                                printf ("rewrite\n");
        !           120:                                _prskel (nsp, 0);
        !           121:                        }
        !           122:                        _do(nsp, nsp->winner, 0);
        !           123:                        _freeskel(nsp);
        !           124:                        continue;
        !           125:                }
        !           126:                _merge (sp, nsp);
        !           127:                if (lastchild==NULL) sp->leftchild = nsp;
        !           128:                else lastchild->sibling = nsp;
        !           129:                lastchild = nsp;
        !           130:                nson++;
        !           131:        }
        !           132: 
        !           133:        for (pp = sp->partial; pp < &sp->partial[sp->treecnt]; pp++)
        !           134:                if (pp->bits&01==1) {
        !           135:                        mp = _allocmatch();
        !           136:                        mp->tree = pp->treeno;
        !           137:                        _addmatches (ostate, sp, mp);
        !           138:                }
        !           139:        if(son==NULL && nson==1)
        !           140:                _closure (state, ostate, sp);
        !           141: 
        !           142:        sp->rightchild = lastchild;
        !           143:        if (root==NULL) {
        !           144:                COST c; __match *win; int i; nsp = sp->leftchild;
        !           145:                c = INFINITY;
        !           146:                win = NULL;
        !           147:                for (i = 0; i < MAXLABELS; i++) {
        !           148:                        mp = nsp->succ[i];
        !           149:                        if (mp!=NULL && COSTLESS (mp->cost, c))
        !           150:                                { c = mp->cost; win = mp; }
        !           151:                }
        !           152:                if (mtDebug || treedebug)
        !           153:                        _prskel (nsp, 0);
        !           154:                _do (nsp, win, 0);
        !           155:        }
        !           156:        if (mtDebug)
        !           157:                _prskel (sp, 0);
        !           158:        return(sp);
        !           159: }
        !           160: 
        !           161: static short int _nodetab[MAXNDVAL], _labeltab[MAXLABELS];
        !           162: 
        !           163: /*
        !           164:  * Convert the start state which has a large branching factor into
        !           165:  * a index table.  This must be called before the matcher is used.
        !           166:  */
        !           167: _matchinit()
        !           168: {
        !           169:        short int *sp;
        !           170:        struct pair { short int val, where } *pp;
        !           171:        for (sp=_nodetab; sp < &_nodetab[MAXNDVAL]; sp++) *sp = HANG;
        !           172:        for (sp=_labeltab; sp < &_labeltab[MAXLABELS]; sp++) *sp = HANG;
        !           173:        sp = &mtTable[mtStart];
        !           174:        assert (*sp==TABLE);
        !           175:        for (pp = (struct pair *) ++sp; pp->val!=EOF; pp++) {
        !           176:                if (MI_NODE(pp->val))
        !           177:                        _nodetab[M_DETAG(pp->val)] = pp->where;
        !           178:                else if (MI_LABEL(pp->val))
        !           179:                        _labeltab[M_DETAG(pp->val)] = pp->where;
        !           180:        }
        !           181: }
        !           182: 
        !           183: int
        !           184: _machstep(state, root, input)
        !           185:        short int state, input;
        !           186:        NODEPTR root;
        !           187: {
        !           188:        register short int *stp = &mtTable[state];
        !           189:        int start = 0;
        !           190:        if (state==HANG)
        !           191:                return (input==(MV_BRANCH(1)) ? mtStart : HANG);
        !           192: rescan:
        !           193:        if (stp==&mtTable[mtStart]) {
        !           194:                if (MI_NODE(input)) return(_nodetab[M_DETAG(input)]);
        !           195:                if (MI_LABEL(input)) return(_labeltab[M_DETAG(input)]);
        !           196:        }
        !           197:        
        !           198:        for(;;) {
        !           199:                if(*stp==ACCEPT) stp += 2;
        !           200: 
        !           201:                if(*stp==TABLE) {
        !           202:                        stp++;
        !           203:                        while(*stp!=EOT) {
        !           204:                                if(input==*stp) {
        !           205:                                        return(*++stp);
        !           206:                                }
        !           207:                                stp += 2;
        !           208:                        }
        !           209:                        stp++;
        !           210:                }
        !           211:                if(*stp!=FAIL) {
        !           212:                        if (start) return (HANG);
        !           213:                        else { stp = &mtTable[mtStart]; start = 1;  goto rescan;}
        !           214:                } else {
        !           215:                        stp++;
        !           216:                        stp = &mtTable[*stp];
        !           217:                        goto rescan;
        !           218:                }
        !           219:        }
        !           220: }
        !           221: 
        !           222: _addmatches(ostate, sp, np)
        !           223:        int ostate;
        !           224:        register skeleton *sp;
        !           225:        register __match *np;
        !           226: {
        !           227:        int label;
        !           228:        int state;
        !           229:        register __match *mp;
        !           230: 
        !           231:         label = mtMap[np->tree];
        !           232: 
        !           233:        /*
        !           234:         * this is a very poor substitute for good design of the DFA.
        !           235:         * What we need is a special case that allows any label to be accepted
        !           236:         * by the start state but we don't want the start state to recognize
        !           237:         * them after a failure.
        !           238:         */
        !           239:        state = _machstep(ostate, NULL, MV_LABEL(label));
        !           240:        if (ostate!=mtStart  && state==HANG) {
        !           241:                _freematch(np);
        !           242:                return;
        !           243:        }
        !           244: 
        !           245:        np->lleaves = _getleaves (np, sp);
        !           246:        np->skel = sp;
        !           247:         if((np->mode = mtEvalCost(np, np->lleaves, sp))==xABORT)
        !           248:        {
        !           249:                _freematch(np);
        !           250:                return;
        !           251:        }
        !           252: 
        !           253: /*
        !           254:        if(np->mode==xREWRITE && COSTLESS(np->cost, sp->mincost)) {
        !           255:                sp->mincost = np->cost;
        !           256:                sp->winner = np;
        !           257:        }
        !           258: */
        !           259:        if ((mp = sp->succ[label])!=NULL) {
        !           260:                if (!COSTLESS (np->cost, mp->cost))
        !           261:                        { _freematch(np); return; }
        !           262:                else _freematch(mp);
        !           263:        }
        !           264:        if(COSTLESS(np->cost,sp->mincost)) {
        !           265:                if(np->mode==xREWRITE) {
        !           266:                        sp->mincost = np->cost; sp->winner = np; }
        !           267:                else { sp->mincost = INFINITY; sp->winner = NULL; }
        !           268:        }
        !           269:        sp->succ[label] = np;
        !           270:        _closure(state, ostate, sp);
        !           271: }
        !           272: 
        !           273: _closure(state, ostate, skp)
        !           274:        int state, ostate;
        !           275:        skeleton *skp;
        !           276: {
        !           277:        register struct ap { short int tree, depth; } *ap;
        !           278:        short int *sp = &mtTable[state];
        !           279:        register __match *mp;
        !           280: 
        !           281:        if(state==HANG || *sp!=ACCEPT) return(NULL);
        !           282: 
        !           283:        for(ap = (struct ap *) &mtAccept[*++sp]; ap->tree!=-1; ap++)
        !           284:                if (ap->depth==0) {
        !           285:                        mp = _allocmatch();     
        !           286:                        mp->tree = ap->tree;
        !           287:                        _addmatches (ostate, skp, mp);
        !           288:                } else {
        !           289:                        register __partial *pp, *lim = &skp->partial[skp->treecnt];
        !           290:                        for(pp=skp->partial; pp < lim; pp++)
        !           291:                                if(pp->treeno==ap->tree)
        !           292:                                        break;
        !           293:                        if(pp==lim) {
        !           294:                                skp->treecnt++;
        !           295:                                pp->treeno = ap->tree;
        !           296:                                pp->bits = (1<<(ap->depth));
        !           297:                        } else pp->bits |= (1<<(ap->depth));
        !           298:                }
        !           299: }
        !           300: 
        !           301: _merge (old, new)
        !           302:        skeleton *old, *new;
        !           303: {
        !           304:        register __partial *op = old->partial, *np = new->partial;
        !           305:        int nson = new->nson;
        !           306:        register __partial *lim = np + new->treecnt;
        !           307:        if (nson==1) {
        !           308:                old->treecnt = new->treecnt;
        !           309:                for(; np < lim; op++, np++) {
        !           310:                        op->treeno = np->treeno;
        !           311:                        op->bits = np->bits/2;
        !           312:                }
        !           313:        } else {
        !           314:                __partial *newer = _allocpartial();
        !           315:                register __partial *newerp = newer;
        !           316:                register int cnt;
        !           317:                lim = op+old->treecnt;
        !           318:                for(cnt=new->treecnt; cnt-- ; np++) {
        !           319:                        for(op = old->partial; op < lim; op++)
        !           320:                                if (op->treeno == np->treeno) {
        !           321:                                        newerp->treeno = op->treeno;
        !           322:                                        newerp++->bits = op->bits & (np->bits/2);
        !           323:                                        break;
        !           324:                                }
        !           325:                }
        !           326:                _freepartial(old->partial);
        !           327:                old->partial = newer;
        !           328:                old->treecnt = newerp-newer;
        !           329:        }
        !           330: }
        !           331:  
        !           332: /* Save and Allocate Matches */
        !           333: #define BLKF   100
        !           334: __match *freep = NULL;
        !           335: static int _count = 0;
        !           336: static __match *_blockp = NULL;
        !           337: #ifdef CHECKMEM
        !           338: int x_matches, f_matches;
        !           339: #endif
        !           340: 
        !           341: __match *
        !           342: _allocmatch()
        !           343: {
        !           344:        __match *mp;
        !           345: 
        !           346:        if(freep!=NULL) {
        !           347:                mp = freep;
        !           348:                freep = ((__match *)((struct freeb *) freep)->next);
        !           349: #ifdef CHECKMEM
        !           350:                f_matches--;
        !           351: #endif
        !           352:        } else {
        !           353:                if(_count==0) {
        !           354:                        _blockp = (__match *) malloc (BLKF*sizeof (__match));
        !           355:                        _count = BLKF;
        !           356: #ifdef CHECKMEM
        !           357:                        x_matches += BLKF;
        !           358: #endif
        !           359:                }
        !           360:                mp = _blockp++;
        !           361:                _count--;
        !           362:        }
        !           363:        return(mp);
        !           364: }
        !           365: 
        !           366: _freematch(mp)
        !           367:        __match *mp;
        !           368: {
        !           369:        ((struct freeb *) mp)->next = (struct freeb *) freep;
        !           370:        freep = mp;
        !           371: #ifdef CHECKMEM
        !           372:        f_matches++;
        !           373: #endif
        !           374: }
        !           375: 
        !           376: static __partial *pfreep = NULL;
        !           377: static int pcount = 0;
        !           378: static __partial *pblock = NULL;
        !           379: #ifdef CHECKMEM
        !           380: static int x_partials, f_partials;
        !           381: #endif
        !           382: 
        !           383: __partial *
        !           384: _allocpartial()
        !           385: {
        !           386:        __partial *pp;
        !           387:        if (pfreep!=NULL) {
        !           388:                pp = pfreep;
        !           389:                pfreep = *(__partial **) pp;
        !           390: #ifdef CHECKMEM
        !           391:                f_partials--;
        !           392: #endif
        !           393:        } else {
        !           394:                if (pcount==0) {
        !           395:                        pblock=(__partial *)malloc(BLKF*MAXTREES*sizeof(__partial));
        !           396:                        pcount = BLKF;
        !           397: #ifdef CHECKMEM
        !           398:                        x_partials += BLKF;
        !           399: #endif
        !           400:                }
        !           401:                pp = pblock;
        !           402:                pblock += MAXTREES;
        !           403:                pcount--;
        !           404:        }
        !           405:        return(pp);
        !           406: }
        !           407: 
        !           408: _freepartial(pp)
        !           409:        __partial *pp;
        !           410: {
        !           411:        * (__partial **)pp = pfreep;
        !           412:        pfreep = pp;
        !           413: #ifdef CHECKMEM
        !           414:        f_partials++;
        !           415: #endif
        !           416: }
        !           417: 
        !           418: 
        !           419: /* storage management */
        !           420: static skeleton *sfreep = NULL;
        !           421: static int scount = 0;
        !           422: static skeleton * sblock = NULL;
        !           423: 
        !           424: skeleton *
        !           425: _allocskel()
        !           426: {
        !           427:        skeleton *sp;
        !           428:        int i;
        !           429:        if(sfreep!=NULL) {
        !           430:                sp = sfreep;
        !           431:                sfreep = sp->sibling;
        !           432:        } else {
        !           433:                if(scount==0) {
        !           434:                        sblock = (skeleton *) malloc (BLKF * sizeof (skeleton));
        !           435:                        scount = BLKF;
        !           436:                }
        !           437:                sp = sblock++;
        !           438:                scount--;
        !           439:        }
        !           440:        sp->sibling = NULL; sp->leftchild = NULL;
        !           441:        for (i=0; i < MAXLABELS; sp->succ[i++] = NULL);
        !           442:        sp->treecnt = 0;
        !           443:        sp->partial = _allocpartial();
        !           444:        return(sp);
        !           445: }
        !           446: 
        !           447: _freeskel(sp)
        !           448:        skeleton *sp;
        !           449: {
        !           450:        int i;
        !           451:        __match *mp;
        !           452:        if(sp==NULL)
        !           453:                return;
        !           454:        if(sp->leftchild)
        !           455:                _freeskel(sp->leftchild);
        !           456:        if(sp->sibling)
        !           457:                _freeskel(sp->sibling);
        !           458:        _freepartial (sp->partial);
        !           459:        for (i=0; i < MAXLABELS; i++)
        !           460:                if ((mp = sp->succ[i])!=NULL) _freematch (mp);
        !           461:        sp->sibling = sfreep;
        !           462:        sfreep = sp;
        !           463: }
        !           464: 
        !           465: _match()
        !           466: {
        !           467:        skeleton *sp;
        !           468:        sp = _allocskel();
        !           469:        sp->root = NULL;
        !           470:        _mpbtop = _mpblock;
        !           471:        _freeskel(_walk(sp, HANG));
        !           472: #ifdef CHECKMEM
        !           473:        if(f_matches+_count!=x_matches) {
        !           474:                printf(";#m %d %d %d\n", f_matches, _count, x_matches);
        !           475:                assert(0);
        !           476:        }
        !           477:        if(f_partials+pcount!=x_partials) {
        !           478:                printf(";#p %d %d %d\n", f_partials, pcount, x_partials);
        !           479:                assert(0);
        !           480:        }
        !           481: #endif
        !           482: }
        !           483: 
        !           484: NODEPTR
        !           485: _mtG(root,i)
        !           486:        NODEPTR root;
        !           487:        int i;
        !           488: {
        !           489:        int *p = &i;
        !           490:        while(*p!=-1)
        !           491:                root = mtGetNodes(root, *p++);
        !           492:        return(root);
        !           493: }
        !           494: 
        !           495: /* diagnostic routines */
        !           496: 
        !           497: _prskel (skp, lvl)
        !           498:        skeleton *skp; int lvl;
        !           499: {
        !           500:        int i; __match *mp;
        !           501:        __partial *pp;
        !           502:        if(skp==NULL) return;
        !           503:        for (i = lvl; i > 0; i--) { putchar (' '); putchar (' '); }
        !           504:        printf ("###\n");
        !           505:        for (i = lvl; i > 0; i--) { putchar (' '); putchar (' '); }
        !           506:        for (i = 0; i < MAXLABELS; i++)
        !           507:                if ((mp=skp->succ[i])!=NULL)
        !           508: #ifdef LINE_XREF
        !           509:                        printf ("[%d<%d> %d]", mp->tree,
        !           510:                                mtLine[mp->tree], mp->cost);
        !           511: #else
        !           512:                        printf ("[%d %d]", mp->tree, mp->cost);
        !           513: #endif
        !           514:        putchar('\n');
        !           515:        for (i = lvl; i > 0; i--) { putchar (' '); putchar (' '); }
        !           516:        for (i = 0, pp=skp->partial; i < skp->treecnt; i++, pp++)
        !           517: #ifdef LINE_XREF
        !           518:                        printf("(%d<%d> %x)", pp->treeno, mtLine[pp->treeno],
        !           519:                                pp->bits);
        !           520: #else
        !           521:                        printf ("(%d %x)", pp->treeno, pp->bits);
        !           522: #endif
        !           523:        putchar('\n');
        !           524:        fflush(stdout);
        !           525:        _prskel (skp->leftchild, lvl+2);
        !           526:        _prskel (skp->sibling, lvl);
        !           527: }

unix.superglobalmegacorp.com

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