Annotation of researchv10no/cmd/twig/rawwalker.ex, 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, qstate;
        !           229:        register __match *mp;
        !           230:        static short int quick[128][MAXLABELS];
        !           231:        static short int qtag[128][MAXLABELS];
        !           232: 
        !           233:         label = mtMap[np->tree];
        !           234: 
        !           235:        /*
        !           236:         * The following lines replace the line:
        !           237:         *
        !           238:         *      state = _machstep(ostate, NULL, MV_LABEL(label));
        !           239:         *
        !           240:         * Statistics show that a large percentage (approx 2/3) of calls to
        !           241:         * _machstep occur in this function.  The lines below attempt
        !           242:         * to reduce the number of these calls by using an unsophisticated
        !           243:         * but apparently adequate caching scheme.
        !           244:         */
        !           245:        qstate = ((ostate>>2)+2)&0177;
        !           246:        if(ostate != qtag[qstate][label]) {
        !           247:                state = _machstep(ostate, NULL, MV_LABEL(label));
        !           248:                quick[qstate][label] = state;
        !           249:                qtag[qstate][label] = ostate;
        !           250:        } else state = quick[qstate][label];
        !           251: 
        !           252:        /*
        !           253:         * this is a very poor substitute for good design of the DFA.
        !           254:         * What we need is a special case that allows any label to be accepted
        !           255:         * by the start state but we don't want the start state to recognize
        !           256:         * them after a failure.
        !           257:         */
        !           258:        if (ostate!=mtStart  && state==HANG) {
        !           259:                _freematch(np);
        !           260:                return;
        !           261:        }
        !           262: 
        !           263:        np->lleaves = _getleaves (np, sp);
        !           264:        np->skel = sp;
        !           265:         if((np->mode = mtEvalCost(np, np->lleaves, sp))==xABORT)
        !           266:        {
        !           267:                _freematch(np);
        !           268:                return;
        !           269:        }
        !           270: 
        !           271:        if ((mp = sp->succ[label])!=NULL) {
        !           272:                if (!COSTLESS (np->cost, mp->cost))
        !           273:                        { _freematch(np); return; }
        !           274:                else _freematch(mp);
        !           275:        }
        !           276:        if(COSTLESS(np->cost,sp->mincost)) {
        !           277:                if(np->mode==xREWRITE) {
        !           278:                        sp->mincost = np->cost; sp->winner = np; }
        !           279:                else { sp->mincost = INFINITY; sp->winner = NULL; }
        !           280:        }
        !           281:        sp->succ[label] = np;
        !           282:        _closure(state, ostate, sp);
        !           283: }
        !           284: 
        !           285: _closure(state, ostate, skp)
        !           286:        int state, ostate;
        !           287:        skeleton *skp;
        !           288: {
        !           289:        register struct ap { short int tree, depth; } *ap;
        !           290:        short int *sp = &mtTable[state];
        !           291:        register __match *mp;
        !           292: 
        !           293:        if(state==HANG || *sp!=ACCEPT) return(NULL);
        !           294: 
        !           295:        for(ap = (struct ap *) &mtAccept[*++sp]; ap->tree!=-1; ap++)
        !           296:                if (ap->depth==0) {
        !           297:                        mp = _allocmatch();     
        !           298:                        mp->tree = ap->tree;
        !           299:                        _addmatches (ostate, skp, mp);
        !           300:                } else {
        !           301:                        register __partial *pp, *lim = &skp->partial[skp->treecnt];
        !           302:                        for(pp=skp->partial; pp < lim; pp++)
        !           303:                                if(pp->treeno==ap->tree)
        !           304:                                        break;
        !           305:                        if(pp==lim) {
        !           306:                                skp->treecnt++;
        !           307:                                pp->treeno = ap->tree;
        !           308:                                pp->bits = (1<<(ap->depth));
        !           309:                        } else pp->bits |= (1<<(ap->depth));
        !           310:                }
        !           311: }
        !           312: 
        !           313: _merge (old, new)
        !           314:        skeleton *old, *new;
        !           315: {
        !           316:        register __partial *op = old->partial, *np = new->partial;
        !           317:        int nson = new->nson;
        !           318:        register __partial *lim = np + new->treecnt;
        !           319:        if (nson==1) {
        !           320:                old->treecnt = new->treecnt;
        !           321:                for(; np < lim; op++, np++) {
        !           322:                        op->treeno = np->treeno;
        !           323:                        op->bits = np->bits/2;
        !           324:                }
        !           325:        } else {
        !           326:                __partial *newer = _allocpartial();
        !           327:                register __partial *newerp = newer;
        !           328:                register int cnt;
        !           329:                lim = op+old->treecnt;
        !           330:                for(cnt=new->treecnt; cnt-- ; np++) {
        !           331:                        for(op = old->partial; op < lim; op++)
        !           332:                                if (op->treeno == np->treeno) {
        !           333:                                        newerp->treeno = op->treeno;
        !           334:                                        newerp++->bits = op->bits & (np->bits/2);
        !           335:                                        break;
        !           336:                                }
        !           337:                }
        !           338:                _freepartial(old->partial);
        !           339:                old->partial = newer;
        !           340:                old->treecnt = newerp-newer;
        !           341:        }
        !           342: }
        !           343:  
        !           344: /* Save and Allocate Matches */
        !           345: #define BLKF   100
        !           346: __match *freep = NULL;
        !           347: static int _count = 0;
        !           348: static __match *_blockp = NULL;
        !           349: #ifdef CHECKMEM
        !           350: int x_matches, f_matches;
        !           351: #endif
        !           352: 
        !           353: __match *
        !           354: _allocmatch()
        !           355: {
        !           356:        __match *mp;
        !           357: 
        !           358:        if(freep!=NULL) {
        !           359:                mp = freep;
        !           360:                freep = ((__match *)((struct freeb *) freep)->next);
        !           361: #ifdef CHECKMEM
        !           362:                f_matches--;
        !           363: #endif
        !           364:        } else {
        !           365:                if(_count==0) {
        !           366:                        _blockp = (__match *) malloc (BLKF*sizeof (__match));
        !           367:                        _count = BLKF;
        !           368: #ifdef CHECKMEM
        !           369:                        x_matches += BLKF;
        !           370: #endif
        !           371:                }
        !           372:                mp = _blockp++;
        !           373:                _count--;
        !           374:        }
        !           375:        return(mp);
        !           376: }
        !           377: 
        !           378: _freematch(mp)
        !           379:        __match *mp;
        !           380: {
        !           381:        ((struct freeb *) mp)->next = (struct freeb *) freep;
        !           382:        freep = mp;
        !           383: #ifdef CHECKMEM
        !           384:        f_matches++;
        !           385: #endif
        !           386: }
        !           387: 
        !           388: static __partial *pfreep = NULL;
        !           389: static int pcount = 0;
        !           390: static __partial *pblock = NULL;
        !           391: #ifdef CHECKMEM
        !           392: static int x_partials, f_partials;
        !           393: #endif
        !           394: 
        !           395: __partial *
        !           396: _allocpartial()
        !           397: {
        !           398:        __partial *pp;
        !           399:        if (pfreep!=NULL) {
        !           400:                pp = pfreep;
        !           401:                pfreep = *(__partial **) pp;
        !           402: #ifdef CHECKMEM
        !           403:                f_partials--;
        !           404: #endif
        !           405:        } else {
        !           406:                if (pcount==0) {
        !           407:                        pblock=(__partial *)malloc(BLKF*MAXTREES*sizeof(__partial));
        !           408:                        pcount = BLKF;
        !           409: #ifdef CHECKMEM
        !           410:                        x_partials += BLKF;
        !           411: #endif
        !           412:                }
        !           413:                pp = pblock;
        !           414:                pblock += MAXTREES;
        !           415:                pcount--;
        !           416:        }
        !           417:        return(pp);
        !           418: }
        !           419: 
        !           420: _freepartial(pp)
        !           421:        __partial *pp;
        !           422: {
        !           423:        * (__partial **)pp = pfreep;
        !           424:        pfreep = pp;
        !           425: #ifdef CHECKMEM
        !           426:        f_partials++;
        !           427: #endif
        !           428: }
        !           429: 
        !           430: 
        !           431: /* storage management */
        !           432: static skeleton *sfreep = NULL;
        !           433: static int scount = 0;
        !           434: static skeleton * sblock = NULL;
        !           435: 
        !           436: skeleton *
        !           437: _allocskel()
        !           438: {
        !           439:        skeleton *sp;
        !           440:        int i;
        !           441:        if(sfreep!=NULL) {
        !           442:                sp = sfreep;
        !           443:                sfreep = sp->sibling;
        !           444:        } else {
        !           445:                if(scount==0) {
        !           446:                        sblock = (skeleton *) malloc (BLKF * sizeof (skeleton));
        !           447:                        scount = BLKF;
        !           448:                }
        !           449:                sp = sblock++;
        !           450:                scount--;
        !           451:        }
        !           452:        sp->sibling = NULL; sp->leftchild = NULL;
        !           453:        for (i=0; i < MAXLABELS; sp->succ[i++] = NULL);
        !           454:        sp->treecnt = 0;
        !           455:        sp->partial = _allocpartial();
        !           456:        return(sp);
        !           457: }
        !           458: 
        !           459: _freeskel(sp)
        !           460:        skeleton *sp;
        !           461: {
        !           462:        int i;
        !           463:        __match *mp;
        !           464:        if(sp==NULL)
        !           465:                return;
        !           466:        if(sp->leftchild)
        !           467:                _freeskel(sp->leftchild);
        !           468:        if(sp->sibling)
        !           469:                _freeskel(sp->sibling);
        !           470:        _freepartial (sp->partial);
        !           471:        for (i=0; i < MAXLABELS; i++)
        !           472:                if ((mp = sp->succ[i])!=NULL) _freematch (mp);
        !           473:        sp->sibling = sfreep;
        !           474:        sfreep = sp;
        !           475: }
        !           476: 
        !           477: _match()
        !           478: {
        !           479:        skeleton *sp;
        !           480:        sp = _allocskel();
        !           481:        sp->root = NULL;
        !           482:        _mpbtop = _mpblock;
        !           483:        _freeskel(_walk(sp, HANG));
        !           484: #ifdef CHECKMEM
        !           485:        if(f_matches+_count!=x_matches) {
        !           486:                printf(";#m %d %d %d\n", f_matches, _count, x_matches);
        !           487:                assert(0);
        !           488:        }
        !           489:        if(f_partials+pcount!=x_partials) {
        !           490:                printf(";#p %d %d %d\n", f_partials, pcount, x_partials);
        !           491:                assert(0);
        !           492:        }
        !           493: #endif
        !           494: }
        !           495: 
        !           496: NODEPTR
        !           497: _mtG(root,i)
        !           498:        NODEPTR root;
        !           499:        int i;
        !           500: {
        !           501:        int *p = &i;
        !           502:        while(*p!=-1)
        !           503:                root = mtGetNodes(root, *p++);
        !           504:        return(root);
        !           505: }
        !           506: 
        !           507: /* diagnostic routines */
        !           508: 
        !           509: _prskel (skp, lvl)
        !           510:        skeleton *skp; int lvl;
        !           511: {
        !           512:        int i; __match *mp;
        !           513:        __partial *pp;
        !           514:        if(skp==NULL) return;
        !           515:        for (i = lvl; i > 0; i--) { putchar (' '); putchar (' '); }
        !           516:        printf ("###\n");
        !           517:        for (i = lvl; i > 0; i--) { putchar (' '); putchar (' '); }
        !           518:        for (i = 0; i < MAXLABELS; i++)
        !           519:                if ((mp=skp->succ[i])!=NULL)
        !           520: #ifdef LINE_XREF
        !           521:                        printf ("[%d<%d> %d]", mp->tree,
        !           522:                                mtLine[mp->tree], mp->cost);
        !           523: #else
        !           524:                        printf ("[%d %d]", mp->tree, mp->cost);
        !           525: #endif
        !           526:        putchar('\n');
        !           527:        for (i = lvl; i > 0; i--) { putchar (' '); putchar (' '); }
        !           528:        for (i = 0, pp=skp->partial; i < skp->treecnt; i++, pp++)
        !           529: #ifdef LINE_XREF
        !           530:                        printf("(%d<%d> %x)", pp->treeno, mtLine[pp->treeno],
        !           531:                                pp->bits);
        !           532: #else
        !           533:                        printf ("(%d %x)", pp->treeno, pp->bits);
        !           534: #endif
        !           535:        putchar('\n');
        !           536:        fflush(stdout);
        !           537:        _prskel (skp->leftchild, lvl+2);
        !           538:        _prskel (skp->sibling, lvl);
        !           539: }

unix.superglobalmegacorp.com

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