|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.