|
|
1.1 ! root 1: /* ! 2: * The machine is laid out as a sequence of integers in the walker. ! 3: * The form described above is only used inside the preprocessor. ! 4: * Each machine state is one of the following sequence: ! 5: * ! 6: * TABLE <value_1><index_1>...<value_n><index_n> -1 [FAIL <fail_index>] -1 ! 7: * or ! 8: * TABLE2 <value_1><index_1>...<value_n><index_n> -1 [FAIL <fail_index>] -1 ! 9: * or ! 10: * ACCEPT <accept table index> -1 ! 11: * ! 12: * The accept table is in the form: ! 13: * ! 14: * <tree index_1> ...<tree_index_m> -1 ! 15: * ! 16: */ ! 17: /* Keutzer - all "short int"'s have been changed to "short" for ! 18: portability to UTS. */ ! 19: #include "symbols.h" ! 20: /* Keutzer 1/88- _mtG now uses varargs for portability to SUN4 etc.*/ ! 21: #include <varargs.h> ! 22: ! 23: #ifndef FILE ! 24: #include <stdio.h> ! 25: #endif ! 26: #include <assert.h> ! 27: ! 28: /* These constants must be the same as the ones in machine.c */ ! 29: #define FASTLIM 0 ! 30: #define TABLE 1 ! 31: #define FAIL 2 ! 32: #define ACCEPT 3 ! 33: #define TABLE2 4 ! 34: #define EOT -1 ! 35: ! 36: /* special machine state */ ! 37: #define HANG -1 ! 38: ! 39: /* used by the evaluator to interpret path table */ ! 40: #define eSTOP 0 ! 41: #define ePOP -1 ! 42: #define eEVAL -2 ! 43: #define eNEXT -3 ! 44: #define ePUSH -4 ! 45: ! 46: /* Tags that indicate the type of a value */ ! 47: #define M_BRANCH 010000 ! 48: #define M_NODE 0 ! 49: #define M_LABEL 01000 ! 50: #define MAX_NODE_VALUE 00777 ! 51: #define MTAG_SHIFT 9 ! 52: #define M_DETAG(x) ((x)&~(M_BRANCH|M_LABEL|M_NODE)) ! 53: ! 54: /* predicates to tell whether a value x is of type NODE, BRANCH, or LABEL */ ! 55: #define MI_NODE(x) (((x)&(M_BRANCH|M_LABEL))==0) ! 56: #define MI_DEFINED(x) ((x)!=-1) ! 57: #define MI_LABEL(x) (((x)&M_LABEL)!=0) ! 58: #define MI_BRANCH(x) (((x)&M_BRANCH)!=0) ! 59: ! 60: /* build a tagged value */ ! 61: #define MV_NODE(x) (x) ! 62: #define MV_BRANCH(x) ((x)|M_BRANCH) ! 63: #define MV_LABEL(x) ((x)|M_LABEL) ! 64: ! 65: /* limits */ ! 66: /* ! 67: * The depth of a pattern must be 7 or less. Otherwise the type of he ! 68: * partial mask in skeleton must be changed ! 69: */ ! 70: #define MAXDEPTH 7 ! 71: ! 72: /* modes */ ! 73: #define xTOPDOWN 3 ! 74: #define xABORT 2 ! 75: #define xREWRITE 1 ! 76: #define xDEFER 0 ! 77: ! 78: /* macros */ ! 79: #define tDO(m) _do((m)->skel, (m), 1) ! 80: #define REWRITE return(_m->cost = cost, xREWRITE) ! 81: #define TOPDOWN return(_m->cost = cost, xTOPDOWN) ! 82: #define ABORT return(xABORT) ! 83: ! 84: /* ! 85: * REORDER macro allows a knowledgeable user to change the order ! 86: * of evaluation of the leaves. ! 87: */ ! 88: #ifndef REORDER ! 89: #define REORDER(list) _evalleaves(list) ! 90: #endif ! 91: #define EVAL REORDER(_ll) ! 92: ! 93: #define mpush(s,m) (m)->next = s, s = m ! 94: ! 95: /* skeleton structure */ ! 96: typedef struct skeleton skeleton; ! 97: typedef struct __match __match; ! 98: typedef struct __partial __partial; ! 99: typedef struct __hshcls __hshcls; /* a hashed closure entry */ ! 100: typedef int labelset; /* a bit vector of labels */ ! 101: ! 102: struct __partial { ! 103: unsigned char treeno; ! 104: char bits; ! 105: }; ! 106: ! 107: struct __hshcls { ! 108: __hshcls *next; ! 109: labelset labels; ! 110: int treecnt; /* number of partial matches */ ! 111: __partial partial[MAXTREES]; ! 112: }; ! 113: ! 114: struct skeleton { ! 115: skeleton *sibling; ! 116: skeleton *leftchild; /* leftmost child */ ! 117: skeleton *rightchild; /* rightmost child */ ! 118: NODEPTR root; ! 119: NODEPTR parent; /* our parent */ ! 120: int nson; ! 121: int treecnt; ! 122: __match *succ[MAXLABELS]; ! 123: __partial *partial; ! 124: __match *winner; ! 125: COST mincost; ! 126: }; ! 127: ! 128: struct __match { ! 129: __match **lleaves; /* labelled leaves */ ! 130: skeleton *skel; /* back pointer to associated skeleton node */ ! 131: COST cost; ! 132: short tree; ! 133: short mode; ! 134: }; ! 135: ! 136: struct freeb { ! 137: struct freeb *next; ! 138: }; ! 139: ! 140: struct _mem { ! 141: struct _mem *next; ! 142: int size; /* size of individual elements in bytes */ ! 143: int blkf; /* blocking factor */ ! 144: int bsize; /* block size */ ! 145: char *block; /* block */ ! 146: int cnt; /* count of free elem in block */ ! 147: char *freelist; /* free list */ ! 148: int totelem; /* total number elements we have */ ! 149: int freecnt; /* number of times mem_free was called */ ! 150: }; ! 151: ! 152: /* turn this flag on if your machine has a fast byte string zero operation */ ! 153: /*#define BZERO 1*/ ! 154: int mtDebug = 0; ! 155: int treedebug = 0; ! 156: extern int _machstep(); ! 157: extern short mtStart; ! 158: extern short mtTable[], mtAccept[], mtMap[], mtPaths[], mtPathStart[]; ! 159: #ifdef LINE_XREF ! 160: extern short mtLine[]; ! 161: #endif ! 162: ! 163: #ifndef MPBSIZE ! 164: #define MPBSIZE 8000 ! 165: #endif ! 166: ! 167: #ifdef ADDCOST ! 168: #define DEFAULT_COST sumleaves(_ll) ! 169: COST sumleaves(list) __match **list; ! 170: {COST cost; ! 171: cost=ZEROCOST; ! 172: for(; *list; list++) ! 173: {ADDCOST((cost),(*list)->cost); ! 174: } ! 175: return cost; ! 176: } ! 177: #endif ! 178: ! 179: extern NODEPTR mtGetNodes(), mtAction(); ! 180: extern skeleton *_allocskel(); ! 181: extern __match *_allocmatch(); ! 182: extern __partial *_allocpartial(); ! 183: ! 184: __match *_mpblock[MPBSIZE], **_mpbtop; ! 185: ! 186: __match ** ! 187: _getleaves (mp, skp) ! 188: register __match *mp; register skeleton *skp; ! 189: { ! 190: skeleton *stack[MAXDEPTH]; ! 191: skeleton **stp = stack; ! 192: register short *sip = &mtPaths[mtPathStart[mp->tree]]; ! 193: register __match **mmp = _mpbtop; ! 194: __match **mmp2 = mmp; ! 195: if((_mpbtop += *sip++ + 1) > &_mpblock[MPBSIZE]) { ! 196: printf("Tree too large: make MPBSIZE larger.\n\ ! 197: (i.e. cc -c -DMPBSIZE=%d walker.c)\n",MPBSIZE*2); ! 198: assert(0); ! 199: } ! 200: ! 201: for(;;) ! 202: switch(*sip++) { ! 203: case ePUSH: ! 204: *stp++ = skp; ! 205: skp = skp->leftchild; ! 206: break; ! 207: ! 208: case eNEXT: ! 209: skp = skp->sibling; ! 210: break; ! 211: ! 212: case eEVAL: ! 213: if ((mp = skp->succ[M_DETAG(*sip++)])==NULL) abort(); ! 214: *mmp++ = mp; ! 215: break; ! 216: ! 217: case ePOP: ! 218: skp = *--stp; ! 219: break; ! 220: ! 221: case eSTOP: ! 222: *mmp = NULL; ! 223: return (mmp2); ! 224: } ! 225: } ! 226: ! 227: _evalleaves (mpp) ! 228: register __match **mpp; ! 229: { ! 230: for (; *mpp!=NULL; mpp++) { ! 231: register __match *mp = *mpp; ! 232: _do (mp->skel, mp, 1); ! 233: } ! 234: } ! 235: ! 236: ! 237: _do(sp, winner, evalall) ! 238: skeleton *sp; register __match *winner; int evalall; ! 239: { ! 240: register __match **mpp; ! 241: register skeleton *skel = winner->skel; ! 242: if(winner==NULL) { ! 243: _nowin(sp); ! 244: return; ! 245: } ! 246: if(winner->mode==xDEFER || (evalall && winner->mode!=xTOPDOWN)) ! 247: REORDER(winner->lleaves); ! 248: mtSetNodes (skel->parent, skel->nson, ! 249: skel->root=mtAction (winner->tree, winner->lleaves, sp)); ! 250: } ! 251: ! 252: skeleton * ! 253: _walk(sp, ostate) ! 254: register skeleton *sp; ! 255: int ostate; ! 256: { ! 257: int state, nstate, nson; ! 258: register __partial *pp; ! 259: register __match *mp, *mp2; ! 260: register skeleton *nsp, *lastchild = NULL; ! 261: NODEPTR son, root; ! 262: ! 263: root = sp->root; ! 264: nson = 1; sp->mincost = INFINITY; ! 265: state = _machstep (ostate, root, mtValue(root)); ! 266: ! 267: while((son = mtGetNodes(root, nson))!=NULL) { ! 268: nstate = _machstep (state, NULL, MV_BRANCH(nson)); ! 269: nsp = _allocskel(); ! 270: nsp->root = son; ! 271: nsp->parent = root; ! 272: nsp->nson = nson; ! 273: _walk(nsp, nstate); ! 274: if(COSTLESS(nsp->mincost,INFINITY)) { ! 275: assert (nsp->winner->mode==xREWRITE); ! 276: _do(nsp, nsp->winner, 0); ! 277: _freeskel(nsp); ! 278: continue; ! 279: } ! 280: _merge (sp, nsp); ! 281: if (lastchild==NULL) sp->leftchild = nsp; ! 282: else lastchild->sibling = nsp; ! 283: lastchild = nsp; ! 284: nson++; ! 285: } ! 286: ! 287: for (pp = sp->partial; pp < &sp->partial[sp->treecnt]; pp++) ! 288: if (pp->bits&01==1) { ! 289: mp = _allocmatch(); ! 290: mp->tree = pp->treeno; ! 291: _addmatches (ostate, sp, mp); ! 292: } ! 293: if(son==NULL && nson==1) ! 294: _closure (state, ostate, sp); ! 295: ! 296: sp->rightchild = lastchild; ! 297: if (root==NULL) { ! 298: COST c; __match *win; int i; nsp = sp->leftchild; ! 299: c = INFINITY; ! 300: win = NULL; ! 301: for (i = 0; i < MAXLABELS; i++) { ! 302: mp = nsp->succ[i]; ! 303: if (mp!=NULL && COSTLESS (mp->cost, c)) ! 304: { c = mp->cost; win = mp; } ! 305: } ! 306: _do (nsp, win, 0); ! 307: } ! 308: return(sp); ! 309: } ! 310: ! 311: /* ! 312: * Convert the start state which has a large branching factor into ! 313: * a index table. This must be called before the matcher is used. ! 314: */ ! 315: static short _nodetab[MAXNDVAL], _labeltab[MAXLABELS]; ! 316: _matchinit() ! 317: { ! 318: short *sp; ! 319: /* Keutzer - this syntax doesn't work on UTS ! 320: struct pair { short val, where } *pp; ! 321: */ ! 322: struct pair { short val; short where; } *pp; ! 323: for (sp=_nodetab; sp < &_nodetab[MAXNDVAL]; sp++) *sp = HANG; ! 324: for (sp=_labeltab; sp < &_labeltab[MAXLABELS]; sp++) *sp = HANG; ! 325: sp = &mtTable[mtStart]; ! 326: assert (*sp==TABLE); ! 327: for (pp = (struct pair *) ++sp; pp->val!=EOF; pp++) { ! 328: if (MI_NODE(pp->val)) ! 329: _nodetab[M_DETAG(pp->val)] = pp->where; ! 330: else if (MI_LABEL(pp->val)) ! 331: _labeltab[M_DETAG(pp->val)] = pp->where; ! 332: } ! 333: } ! 334: ! 335: int ! 336: _machstep(state, root, input) ! 337: short state, input; ! 338: NODEPTR root; ! 339: { ! 340: register short *stp = &mtTable[state]; ! 341: int start = 0; ! 342: if (state==HANG) ! 343: return (input==(MV_BRANCH(1)) ? mtStart : HANG); ! 344: rescan: ! 345: if (stp==&mtTable[mtStart]) { ! 346: if (MI_NODE(input)) return(_nodetab[M_DETAG(input)]); ! 347: if (MI_LABEL(input)) return(_labeltab[M_DETAG(input)]); ! 348: } ! 349: ! 350: for(;;) { ! 351: if(*stp==ACCEPT) stp += 2; ! 352: ! 353: if(*stp==TABLE) { ! 354: stp++; ! 355: while(*stp!=EOT) { ! 356: if(input==*stp) { ! 357: return(*++stp); ! 358: } ! 359: stp += 2; ! 360: } ! 361: stp++; ! 362: } ! 363: if(*stp!=FAIL) { ! 364: if (start) return (HANG); ! 365: else { stp = &mtTable[mtStart]; start = 1; goto rescan;} ! 366: } else { ! 367: stp++; ! 368: stp = &mtTable[*stp]; ! 369: goto rescan; ! 370: } ! 371: } ! 372: } ! 373: ! 374: _addmatches(ostate, sp, np) ! 375: int ostate; ! 376: register skeleton *sp; ! 377: register __match *np; ! 378: { ! 379: int label; ! 380: int state; ! 381: register __match *mp; ! 382: ! 383: label = mtMap[np->tree]; ! 384: ! 385: /* ! 386: * this is a very poor substitute for good design of the DFA. ! 387: * What we need is a special case that allows any label to be accepted ! 388: * by the start state but we don't want the start state to recognize ! 389: * them after a failure. ! 390: */ ! 391: state = _machstep(ostate, NULL, MV_LABEL(label)); ! 392: if (ostate!=mtStart && state==HANG) { ! 393: _freematch(np); ! 394: return; ! 395: } ! 396: ! 397: np->lleaves = _getleaves (np, sp); ! 398: np->skel = sp; ! 399: if((np->mode = mtEvalCost(np, np->lleaves, sp))==xABORT) ! 400: { ! 401: _freematch(np); ! 402: return; ! 403: } ! 404: ! 405: /* ! 406: if(np->mode==xREWRITE && COSTLESS(np->cost, sp->mincost)) { ! 407: sp->mincost = np->cost; ! 408: sp->winner = np; ! 409: } ! 410: */ ! 411: if ((mp = sp->succ[label])!=NULL) { ! 412: if (!COSTLESS (np->cost, mp->cost)) ! 413: { _freematch(np); return; } ! 414: else _freematch(mp); ! 415: } ! 416: if(COSTLESS(np->cost,sp->mincost)) { ! 417: if(np->mode==xREWRITE) { ! 418: sp->mincost = np->cost; sp->winner = np; } ! 419: else { sp->mincost = INFINITY; sp->winner = NULL; } ! 420: } ! 421: sp->succ[label] = np; ! 422: _closure(state, ostate, sp); ! 423: } ! 424: ! 425: _closure(state, ostate, skp) ! 426: int state, ostate; ! 427: skeleton *skp; ! 428: { ! 429: register struct ap { short tree, depth; } *ap; ! 430: short *sp = &mtTable[state]; ! 431: register __match *mp; ! 432: ! 433: if(state==HANG || *sp!=ACCEPT) return(NULL); ! 434: ! 435: for(ap = (struct ap *) &mtAccept[*++sp]; ap->tree!=-1; ap++) ! 436: if (ap->depth==0) { ! 437: mp = _allocmatch(); ! 438: mp->tree = ap->tree; ! 439: _addmatches (ostate, skp, mp); ! 440: } else { ! 441: register __partial *pp, *lim = &skp->partial[skp->treecnt]; ! 442: for(pp=skp->partial; pp < lim; pp++) ! 443: if(pp->treeno==ap->tree) ! 444: break; ! 445: if(pp==lim) { ! 446: skp->treecnt++; ! 447: pp->treeno = ap->tree; ! 448: pp->bits = (1<<(ap->depth)); ! 449: } else pp->bits |= (1<<(ap->depth)); ! 450: } ! 451: } ! 452: ! 453: _merge (old, new) ! 454: skeleton *old, *new; ! 455: { ! 456: register __partial *op = old->partial, *np = new->partial; ! 457: int nson = new->nson; ! 458: register __partial *lim = np + new->treecnt; ! 459: if (nson==1) { ! 460: old->treecnt = new->treecnt; ! 461: for(; np < lim; op++, np++) { ! 462: op->treeno = np->treeno; ! 463: op->bits = np->bits/2; ! 464: } ! 465: } else { ! 466: __partial *newer = _allocpartial(); ! 467: register __partial *newerp = newer; ! 468: register int cnt; ! 469: lim = op+old->treecnt; ! 470: for(cnt=new->treecnt; cnt-- ; np++) { ! 471: for(op = old->partial; op < lim; op++) ! 472: if (op->treeno == np->treeno) { ! 473: newerp->treeno = op->treeno; ! 474: newerp++->bits = op->bits & (np->bits/2); ! 475: break; ! 476: } ! 477: } ! 478: _freepartial(old->partial); ! 479: old->partial = newer; ! 480: old->treecnt = newerp-newer; ! 481: } ! 482: } ! 483: ! 484: /* Save and Allocate Matches */ ! 485: #define BLKF 100 ! 486: __match *freep = NULL; ! 487: static int _count = 0; ! 488: static __match *_blockp = NULL; ! 489: #ifdef CHECKMEM ! 490: int x_matches, f_matches; ! 491: #endif ! 492: ! 493: __match * ! 494: _allocmatch() ! 495: { ! 496: __match *mp; ! 497: ! 498: if(freep!=NULL) { ! 499: mp = freep; ! 500: freep = ((__match *)((struct freeb *) freep)->next); ! 501: #ifdef CHECKMEM ! 502: f_matches--; ! 503: #endif ! 504: } else { ! 505: if(_count==0) { ! 506: _blockp = (__match *) malloc (BLKF*sizeof (__match)); ! 507: _count = BLKF; ! 508: #ifdef CHECKMEM ! 509: x_matches += BLKF; ! 510: #endif ! 511: } ! 512: mp = _blockp++; ! 513: _count--; ! 514: } ! 515: return(mp); ! 516: } ! 517: ! 518: _freematch(mp) ! 519: __match *mp; ! 520: { ! 521: ((struct freeb *) mp)->next = (struct freeb *) freep; ! 522: freep = mp; ! 523: #ifdef CHECKMEM ! 524: f_matches++; ! 525: #endif ! 526: } ! 527: ! 528: static __partial *pfreep = NULL; ! 529: static int pcount = 0; ! 530: static __partial *pblock = NULL; ! 531: #ifdef CHECKMEM ! 532: static int x_partials, f_partials; ! 533: #endif ! 534: ! 535: __partial * ! 536: _allocpartial() ! 537: { ! 538: __partial *pp; ! 539: if (pfreep!=NULL) { ! 540: pp = pfreep; ! 541: pfreep = *(__partial **) pp; ! 542: #ifdef CHECKMEM ! 543: f_partials--; ! 544: #endif ! 545: } else { ! 546: if (pcount==0) { ! 547: pblock=(__partial *)malloc(BLKF*MAXTREES*sizeof(__partial)); ! 548: pcount = BLKF; ! 549: #ifdef CHECKMEM ! 550: x_partials += BLKF; ! 551: #endif ! 552: } ! 553: pp = pblock; ! 554: pblock += MAXTREES; ! 555: pcount--; ! 556: } ! 557: return(pp); ! 558: } ! 559: ! 560: _freepartial(pp) ! 561: __partial *pp; ! 562: { ! 563: * (__partial **)pp = pfreep; ! 564: pfreep = pp; ! 565: #ifdef CHECKMEM ! 566: f_partials++; ! 567: #endif ! 568: } ! 569: ! 570: ! 571: /* storage management */ ! 572: static skeleton *sfreep = NULL; ! 573: static int scount = 0; ! 574: static skeleton * sblock = NULL; ! 575: ! 576: skeleton * ! 577: _allocskel() ! 578: { ! 579: skeleton *sp; ! 580: int i; ! 581: if(sfreep!=NULL) { ! 582: sp = sfreep; ! 583: sfreep = sp->sibling; ! 584: } else { ! 585: if(scount==0) { ! 586: sblock = (skeleton *) malloc (BLKF * sizeof (skeleton)); ! 587: scount = BLKF; ! 588: } ! 589: sp = sblock++; ! 590: scount--; ! 591: } ! 592: sp->sibling = NULL; sp->leftchild = NULL; ! 593: for (i=0; i < MAXLABELS; sp->succ[i++] = NULL); ! 594: sp->treecnt = 0; ! 595: sp->partial = _allocpartial(); ! 596: return(sp); ! 597: } ! 598: ! 599: _freeskel(sp) ! 600: skeleton *sp; ! 601: { ! 602: int i; ! 603: __match *mp; ! 604: if(sp==NULL) return; ! 605: _freeskel (sp->leftchild); ! 606: _freeskel (sp->sibling); ! 607: _freepartial (sp->partial); ! 608: for (i=0; i < MAXLABELS; i++) ! 609: if ((mp = sp->succ[i])!=NULL) _freematch (mp); ! 610: sp->sibling = sfreep; ! 611: sfreep = sp; ! 612: } ! 613: ! 614: _match() ! 615: { ! 616: skeleton *sp; ! 617: sp = _allocskel(); ! 618: sp->root = NULL; ! 619: _mpbtop = _mpblock; ! 620: _freeskel(_walk(sp, HANG)); ! 621: #ifdef CHECKMEM ! 622: if(f_matches+_count!=x_matches) { ! 623: printf(";#m %d %d %d\n", f_matches, _count, x_matches); ! 624: assert(0); ! 625: } ! 626: if(f_partials+pcount!=x_partials) { ! 627: printf(";#p %d %d %d\n", f_partials, pcount, x_partials); ! 628: assert(0); ! 629: } ! 630: #endif ! 631: } ! 632: ! 633: /* Keutzer 1/88- _mtG now uses varargs for portability to SUN4 etc.*/ ! 634: NODEPTR _mtG(va_alist) ! 635: va_dcl ! 636: { ! 637: NODEPTR root; ! 638: int i=0; ! 639: va_list p_var; ! 640: va_start(p_var); ! 641: root = va_arg(p_var,NODEPTR); ! 642: while( (i = va_arg(p_var,int)) != -1){ ! 643: root = mtGetNodes(root, i); ! 644: } ! 645: va_end(p_var); ! 646: return(root); ! 647: } ! 648: ! 649: /* diagnostic routines */ ! 650: #ifdef NOMARK ! 651: markIfNoMatch(skp,mark) ! 652: skeleton *skp; ! 653: int mark; ! 654: {} ! 655: #else ! 656: markIfNoMatch(skp,mark) skeleton *skp; int mark; ! 657: {skeleton *child; int i; int found=0; ! 658: for(i=0; i<MAXLABELS; i++) ! 659: if (skp->succ[i]) found=1; ! 660: if (!found) skp->root->mark=mark; ! 661: for(child=skp->leftchild; child; child=child->sibling) ! 662: markIfNoMatch(child,mark); ! 663: } ! 664: #endif ! 665: ! 666: _nowin(skp) skeleton *skp; ! 667: { ! 668: markIfNoMatch(skp,1); ! 669: printf("# No match was found for the nodes printed in lowercase\n"); ! 670: printTree(skp->root); ! 671: markIfNoMatch(skp,0); ! 672: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.