Annotation of researchv10no/cmd/twig/machine.c, revision 1.1.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.