Annotation of researchv10no/cmd/twig/machine.c, revision 1.1

1.1     ! root        1: #include "common.h"
        !             2: #include "code.h"
        !             3: #include "sym.h"
        !             4: #include "machine.h"
        !             5: 
        !             6: int gen_table2;                /* generate type two tables */
        !             7: struct machine_node *machine = NULL;
        !             8: static int depth;
        !             9: 
        !            10: static struct machine_node *
        !            11: get_state()
        !            12: {
        !            13:        struct machine_node *mp = (struct machine_node *)
        !            14:                                malloc (sizeof (struct machine_node));
        !            15:        assert (mp!=NULL);
        !            16:        mp->inp.value = -1;
        !            17:        mp->nst = NULL;
        !            18:        mp->link = NULL;
        !            19:        mp->fail = NULL;
        !            20:        mp->match = NULL;
        !            21:        return(mp);
        !            22: }
        !            23: 
        !            24: add_match(s, tp, depth)
        !            25:        struct machine_node *s;
        !            26:        LabelData *tp;
        !            27:        int depth;
        !            28: {
        !            29:        struct match *mp = (struct match *) malloc (sizeof (struct match));
        !            30: 
        !            31:        assert (mp!=NULL);
        !            32:        mp->next = s->match;
        !            33:        mp->depth = depth;
        !            34:        mp->tree = tp;
        !            35:        s->match = mp;
        !            36: }
        !            37:        
        !            38: /*
        !            39:  * Build a trie from the path strings.  Failure transition are added later.
        !            40:  */
        !            41: cgotofn(tp)
        !            42:        LabelData *tp;
        !            43: {
        !            44:        struct machine_input inp;
        !            45:        int ret;
        !            46:        register struct machine_node *s;
        !            47:        register int quit = 0;
        !            48: 
        !            49:        if (machine==NULL) {
        !            50:                /* first time thru */
        !            51:                machine = get_state();
        !            52:        }
        !            53:        s = machine;
        !            54:        depth = -1;
        !            55: 
        !            56:        assert (tp->tree!=NULL);
        !            57:        path_setup (tp->tree);
        !            58: 
        !            59:        for(;;) {
        !            60:                ret = path_getsym(&inp);
        !            61: 
        !            62:                /* no more paths */
        !            63:                if (ret == EOF)
        !            64:                        break;
        !            65: 
        !            66:                if (ret == NULL) {
        !            67:                        /*
        !            68:                         * the end of the path.  Add a match to the
        !            69:                         * accepting state.
        !            70:                         */
        !            71:                        assert ((depth&01)==0); /* make sure it's even */
        !            72:                        add_match(s, tp, depth >> 1);
        !            73:                        s = machine;
        !            74:                        depth = -1;
        !            75:                        ntrees++;
        !            76:                        continue;
        !            77:                }
        !            78: 
        !            79:                while (!MI_EQUAL(s->inp, inp)) {
        !            80:                        if (!MI_DEFINED(s->inp.value) || s->link == NULL) {
        !            81:                                if (MI_DEFINED(s->inp.value)) {
        !            82:                                        /*
        !            83:                                         * The trie must be split here
        !            84:                                         */
        !            85:                                        s->link = get_state();
        !            86:                                        s = s->link;
        !            87:                                }
        !            88:                                /*
        !            89:                                 * Fill in the state
        !            90:                                 */
        !            91:                                s->inp = inp;
        !            92:                                s->nst = get_state();
        !            93:                                s = s->nst;
        !            94:                                depth++;
        !            95:                                break;
        !            96:                        } else s = s->link;
        !            97:                }
        !            98:                if (MI_EQUAL(s->inp, inp)) {
        !            99:                        s = s->nst;
        !           100:                        depth++;
        !           101:                }
        !           102:        }
        !           103: }
        !           104: 
        !           105: /* print out the machine for debugging */
        !           106: machine_print(mp)
        !           107:        struct machine_node *mp;
        !           108: {
        !           109:        register struct machine_node *mp2;
        !           110:        struct machine_node *fail;
        !           111:        struct match *match, *p;
        !           112: 
        !           113:        if (mp==NULL)
        !           114:                return;
        !           115:        printf("%x %d:", mp, mp->index);
        !           116:        if((fail = mp->fail))
        !           117:                printf("\tfail %x", fail);
        !           118:        if((match = mp->match)) {
        !           119:                printf("\taccept ");
        !           120:                for(p = match; p!=NULL; p = p->next) {
        !           121:                        LabelData *tp = p->tree;
        !           122:                        printf("%s ", (tp->label)->name);
        !           123:                }
        !           124:        }
        !           125:        putchar('\n');
        !           126:        for(mp2=mp; mp2!=NULL; mp2 = mp2->link) {
        !           127:                if (MI_DEFINED(mp2->inp.value)) {
        !           128:                        if (MI_BRANCH(mp->inp.value))
        !           129:                                printf(" %d -> ", mp2->inp.value);
        !           130:                        else
        !           131:                                printf(" [%s] -> ", (mp2->inp.sym)->name);
        !           132:                        printf("%x", mp2->nst);
        !           133:                }
        !           134:                assert(mp2->fail==fail);
        !           135:                assert(mp2->match==match);
        !           136:        }
        !           137:        if(MI_DEFINED(mp->inp.value))
        !           138:                putchar('\n');
        !           139:        for (mp2 = mp; mp2!=NULL; mp2=mp2->link) {
        !           140:                machine_print(mp2->nst);
        !           141:        }
        !           142: }
        !           143: 
        !           144: /*
        !           145:  * This routine augments the machine with failure transition.
        !           146:  * The trie is examined in breadth first order.
        !           147:  *     See Aho, Corasick Comm ACM 18:6 for details
        !           148:  */
        !           149: cfail()
        !           150: {
        !           151:        struct machine_node **stack, **stack2;
        !           152:        struct machine_node **stackTop, **stack2Top, **temp;
        !           153:        int stackCnt, stack2Cnt;
        !           154:        struct machine_node *state;
        !           155:        struct machine_input sym;
        !           156:        register struct machine_node *s, *q;
        !           157: 
        !           158:        /* allocate stacks */
        !           159:        stackTop = stack = (struct machine_node **) malloc
        !           160:                                (ntrees*sizeof (struct machine_node *));
        !           161:        stack2 = stack2Top = (struct machine_node **) malloc
        !           162:                                (ntrees*sizeof (struct machine_node *));
        !           163:        stackCnt = stack2Cnt = 0;
        !           164:        s = machine;
        !           165:        do {
        !           166:                if (MI_DEFINED(s->inp.value)) {
        !           167:                        assert(++stackCnt <= ntrees);
        !           168:                        *stackTop++ = s->nst;
        !           169:                }
        !           170:                s = s->link;
        !           171:        } while (s != NULL);
        !           172: 
        !           173:        for(;;) {
        !           174:                if (stackCnt == 0) {
        !           175:                        /* swap stacks */
        !           176:                        if (stack2Cnt == 0)
        !           177:                                break;
        !           178:                        stackCnt = stack2Cnt; stack2Cnt = 0;
        !           179:                        stackTop = stack2Top;
        !           180:                        temp = stack; stack = stack2; stack2 = temp;
        !           181:                        stack2Top = stack2;
        !           182:                }
        !           183:                stackCnt--;
        !           184:                s = *--stackTop;
        !           185:                do {
        !           186:                        int startstate = 0;
        !           187:                        sym = s->inp;
        !           188:                        if (MI_DEFINED(sym.value)) {    /* g(s,c) != 0 */
        !           189:                            assert (++stack2Cnt <= ntrees);
        !           190:                            *stack2Top++ = (q=s->nst);
        !           191:                            state = s->fail;    /* state = f(s) */
        !           192:                            for(;;) {
        !           193:                                if (state == 0) {
        !           194:                                        state = machine;
        !           195:                                        startstate++;
        !           196:                                }
        !           197:                                if (MI_EQUAL(state->inp, sym)) {
        !           198:                                    struct match *mp = NULL;
        !           199: 
        !           200:                                    /* append any accepting matches */
        !           201:                                    for(mp=(state->nst)->match;mp;mp=mp->next)
        !           202:                                        add_match(q,mp->tree, mp->depth);
        !           203:                                    mp = q->match;
        !           204: 
        !           205:                                    do {
        !           206:                                        /* f(q) = g(state,sym)
        !           207:                                         * for all q links */
        !           208:                                        q->fail = state->nst;
        !           209:                                        q->match = mp;
        !           210:                                    } while ((q = q->link) != 0);
        !           211:                                    break;
        !           212:                                }
        !           213:                                else if (state->link != 0)
        !           214:                                    state = state->link;
        !           215:                                else {
        !           216:                                        state = state->fail;
        !           217:                                        if (state==NULL&&startstate)
        !           218:                                                break;
        !           219:                                }
        !           220:                            }
        !           221:                        }
        !           222:                        s = s->link;
        !           223:                } while (s!=NULL);
        !           224:        }
        !           225: }
        !           226: 
        !           227: /*
        !           228:  * Called from the YACC rule pattern_spec
        !           229:  */
        !           230: void
        !           231: machine_build()
        !           232: {
        !           233:        cfail();
        !           234:        (void) MachineNumber(machine, 0);
        !           235:        if(debug_flag&DB_MACH) {
        !           236:                fputs("\n-------\n", stderr);
        !           237:                machine_print(machine);
        !           238:        }
        !           239: }
        !           240: 
        !           241: struct match *acceptTable[MAXACCEPTS];
        !           242: struct match **acceptTableTop = acceptTable;
        !           243: static short int *arityTable;
        !           244: int nextAcceptIndex = 0;
        !           245: 
        !           246: /*
        !           247:  * This is the first pass of the process to generate the
        !           248:  * flattened machine used in the walker.  Called from machine_build
        !           249:  */
        !           250: int
        !           251: MachineNumber(mach, index)
        !           252:        struct machine_node *mach;
        !           253:        int index;
        !           254: {
        !           255:        struct machine_node *mp;
        !           256: 
        !           257:        for(mp=mach; mp!=NULL; mp = mp->link)
        !           258:                if(MI_DEFINED(mp->inp.value))
        !           259:                        index = MachineNumber(mp->nst, index);
        !           260: 
        !           261:        mach->index = index;
        !           262:        if (mach->match!=NULL) index += 2;
        !           263:        if(mach->link!=NULL || mach->nst!=NULL) {
        !           264:                index += 2;
        !           265:                for(mp = mach; mp!=NULL; mp = mp->link)
        !           266:                        if(mp->nst!=NULL) 
        !           267:                                index += 2;
        !           268:        }
        !           269: 
        !           270:        if (mach->fail!=NULL)
        !           271:                index += 2;
        !           272:        index++;
        !           273:        return(index);
        !           274: }
        !           275: 
        !           276: /*
        !           277:  * Build the flattened out machine used in the walker.
        !           278:  * See machine.h for description
        !           279:  */
        !           280: MachineGen()
        !           281: {
        !           282:        struct match **atp, *ap;
        !           283:        short int *sp;
        !           284: 
        !           285:        oreset();
        !           286:        fputs("short int mtTable[] = {\n", outfile);
        !           287:        machineGen2(machine);
        !           288:        fputs("};\n", outfile);
        !           289: 
        !           290:        fputs("short int mtAccept[] = {\n", outfile);
        !           291: 
        !           292:        oreset();
        !           293:        for(atp = acceptTable; atp < acceptTableTop; atp++) {
        !           294:                for(ap = *atp; ap!=NULL; ap = ap->next) {
        !           295:                        register LabelData *tree = ap->tree;
        !           296: 
        !           297:                        /* if you change any of the code below you must change
        !           298:                         * the increment added to nextAcceptIndex in
        !           299:                         * machineGen2
        !           300:                         */
        !           301:                        oputint(tree->treeIndex);
        !           302:                        oputint(ap->depth);
        !           303:                }
        !           304:                oputint(-1);
        !           305:        }
        !           306:        fprintf(outfile, "};\nshort int mtStart = %d;\n", machine->index);
        !           307: }
        !           308:                 
        !           309: machineGen2(mach)
        !           310:        struct machine_node *mach;
        !           311: {
        !           312:        struct machine_node *mp;
        !           313:        struct match *ap;
        !           314: 
        !           315:        if (mach==NULL)
        !           316:                return;
        !           317: 
        !           318:        for(mp=mach; mp!=NULL; mp = mp->link)
        !           319:                if(MI_DEFINED(mp->inp.value))
        !           320:                        machineGen2(mp->nst);
        !           321: 
        !           322:        assert(mach->index == ointcnt());
        !           323:        if (mach->match!=NULL) {
        !           324:                *acceptTableTop++ = mach->match;
        !           325:                oputint(ACCEPT); oputint(nextAcceptIndex);
        !           326:                for(ap = mach->match; ap!=NULL; ap = ap->next)
        !           327:                        nextAcceptIndex += 2;
        !           328:                nextAcceptIndex++;
        !           329:        }
        !           330:        if(mach->link!=NULL || mach->nst!=NULL) {
        !           331:                if(MI_BRANCH(mp->inp.value)&&gen_table2) {
        !           332:                        oputint (TABLE2);
        !           333:                        for(mp = mach; mp!=NULL; mp = mp->link) {
        !           334:                                if(mp->nst!=NULL) {
        !           335:                                        oputoct(mp->inp.value);
        !           336:                                        oputint((mp->nst)->index);
        !           337:                                }
        !           338:                        }
        !           339:                } else {
        !           340:                        oputint (TABLE);
        !           341:                        for(mp = mach; mp!=NULL; mp = mp->link) {
        !           342:                                if(mp->nst!=NULL) {
        !           343:                                        oputoct(mp->inp.value);
        !           344:                                        oputint((mp->nst)->index);
        !           345:                                }
        !           346:                        }
        !           347:                }
        !           348:                oputint(-1);
        !           349:        }
        !           350: 
        !           351:        /* A failure transition or a -1 terminate every state */
        !           352:        if (mach->fail!=NULL) {
        !           353:                oputint(FAIL); oputint((mach->fail)->index);
        !           354:        }
        !           355:        oputint(-1);
        !           356: }

unix.superglobalmegacorp.com

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