|
|
1.1 ! root 1: # To unbundle, sh this file ! 2: echo README 1>&2 ! 3: sed 's/.//' >README <<'//GO.SYSIN DD README' ! 4: -Installation Procedure ! 5: ----------------------- ! 6: -To install twig, you must decide in which directories to place: ! 7: - ! 8: -(1) the twig compiler binary, and ! 9: -(2) the twig template files. ! 10: - ! 11: -Once you have made these two decisions, you should edit the makefile and ! 12: -set the variable INSTALL to the value of (1), and the variable TEMPLATES to ! 13: -(2). The definitions of INSTALL and TEMPLATES should be near the beginning ! 14: -of the makefile. The installation can then be completed by typing: ! 15: - ! 16: - make install ! 17: - ! 18: -Once a user has written a twig specification, the command twig is used to ! 19: -compile it. The compilation creates two files called walker.c, ! 20: -containing several subroutines, and symbols.h, containing definitions. ! 21: -Walker.c is compiled and linked with the rest of the user program, and ! 22: -tree matching occurs when the user's program calls a subroutine called _match. ! 23: -More details about twig specifications, and how to interface to the ! 24: -subroutines in walker.c is given in the ``Twig Reference Manual'', AT&T Bell ! 25: -Laboratories, Computing Science Technical Report #120. ! 26: - ! 27: -Addendum to the ``Twig Reference Manual'' ! 28: ------------------------------------------ ! 29: - ! 30: -1. In a node declaration, the user can override the automatic numbering ! 31: - of a node id by expliciting assigning a number using the ``= int'' ! 32: - construct. However, the user must then assign a number to all ! 33: - of the node ids. In other words, the user must either assign ! 34: - numbers to each of the node ids, or to none of them. The ids must ! 35: - have unique numbers. ! 36: - ! 37: -2. The default action of executing the labelled leaves from ! 38: - right to left is inadequate. ``Execution,'' as used here, is in ! 39: - the sense as described in the ``Twig Reference Manual.'' Although ! 40: - one could simulate any execution order by using a top-down rule, and ! 41: - explicitly requesting the execution of labelled leaves with the tDO ! 42: - macro, it is tedious to do so. For example, implementing a Sethi-Ullman ! 43: - style register allocator in such a fashion is extremely awkward. ! 44: - To alleviate this tedium, reordering scheme has been proposed, and ! 45: - implemented by Andrew Appel of Princeton University. It is included ! 46: - in this version of twig. ! 47: - ! 48: - A function, ``_do'' performs the execution of the matches. This ! 49: - function is part of the walker.c file generated by twig. In versions ! 50: - of the walker without reordering, _do performs the call: ! 51: - ! 52: - _evalleaves(winner->lleaves); ! 53: - ! 54: - where winner->lleaves are the labelled leaves of the winning match. ! 55: - Lleaves has type ``__match *[], '' and is a NULL terminated sequence ! 56: - of matches for the labelled leaves in left to right order. Calling ! 57: - tDO with an element of lleaves executes the match associated with ! 58: - the labelled leaf. ! 59: - ! 60: - Reordering is accomplished by changing the call to _evalleaves with ! 61: - the statement: ! 62: - ! 63: - REORDER(winner->lleaves); ! 64: - ! 65: - REORDER is a macro, or function defined by the user that may execute ! 66: - the leaves in any order. If the user does not define REORDER then ! 67: - twig will generate a default, which is to call _evalleaves. ! 68: - ! 69: - For example, if the user wishes to execute the leaves in the order of ! 70: - decreasing cost, the following definition could be used. ! 71: - ! 72: - prologue { ! 73: - ... ! 74: - #define REORDER(list) reorder(list) ! 75: - ... ! 76: - } ! 77: - ! 78: - ... ! 79: - ! 80: - insert { ! 81: - ! 82: - reorder(list) ! 83: - __match **list; ! 84: - { ! 85: - int i, j, n; ! 86: - __match *index[16]; ! 87: - ! 88: - /* copy list into index */ ! 89: - for(n=0; list[n]; n++) index[n] = list[n]; ! 90: - ! 91: - /* insertion sort */ ! 92: - for(j=0;j<n;j++) ! 93: - for(i=j; i>0; i--) ! 94: - if(index[i]->cost > index[i-1]->cost) { ! 95: - /* swap them */ ! 96: - __match *temp = index[i]; ! 97: - index[i] = index[i-1]; index[i-1] = p; ! 98: - } ! 99: - ! 100: - /* now execute */ ! 101: - for(j=0;j<n;j++) ! 102: - tDO(index[j]); ! 103: - } ! 104: - ! 105: - } ! 106: - ! 107: - ! 108: -3. In a top-down rule, there is often a desire to execute all the ! 109: - labelled leaves after performing some preparatory actions. This ! 110: - could be done by saying ! 111: - ! 112: - tDO($%1$); tDO($%2$); ... ! 113: - ! 114: - However, the short hand notation, ``EVAL;'' provides the same function. ! 115: - ! 116: -4. In the previous version of twig, Walker.c had a reference to ! 117: - walker.h. Hence the user had to compile walker.c with the command: ! 118: - ! 119: - cc -Iinclude_dir -c walker.c ! 120: - ! 121: - where include_dir was the directory containing walker.h. ! 122: - The reference to walker.h has been eliminated by inserting walker.h ! 123: - into all the template files that could generate walker.c. ! 124: - Therefore the new compile command is: ! 125: - ! 126: - cc -c walker.c ! 127: - ! 128: -5. Twig assigns numbers to the node symbols, which are used to identify ! 129: - nodes to the tree matcher. In the previous version of twig, the ! 130: - tree matcher actually recognized ``M_NODE|number'' as the value ! 131: - assigned to the node symbol rather than just plain ``number.'' ! 132: - This was completely undocumented. The current version fixed the ! 133: - tree matcher to recognize ``number'' as the correct value associated ! 134: - with a node symbol. ! 135: - ! 136: -6. Twig now uses dynamic initialization of costs rather than static ! 137: - initialization. This permits the user to declare COST as structure. ! 138: - ! 139: -7. Many cost metrics used in twig programs are additive. That is, ! 140: - the cost of a match is some constant cost plus the sum of the ! 141: - costs of the matches at the labelled leaves. The macros ZEROCOST, and ! 142: - ADDCOST provide an easy way to implement this. For example, if costs ! 143: - are integers, then the definition ! 144: - ! 145: - #define ZEROCOST 1 ! 146: - #define ADDCOST(accum,y) (accum) += (y) ! 147: - ! 148: - would cause twig to generate, for rules without a cost part, code that ! 149: - calculate the default cost as one plus the sum of the costs of the ! 150: - matches at the labelled leaves. ! 151: - ! 152: - ZEROCOST, and ADDCOST must both be defined, if the above facility is ! 153: - to be used. DEFAULT_COST must not be defined when ADDCOST is defined. ! 154: - ! 155: -8. Changes made by Keutzer (allegra!keutzer) and Appel (research!appel) ! 156: - ! 157: - modifications by keutzer: ! 158: - ! 159: - char c ->int c ! 160: - all over lex.c ! 161: - ! 162: - varargs added in _mtG in walker.c ! 163: - may be too expensive for some people. ! 164: - code is not portable to a SUN4 without it however. ! 165: - ! 166: - "short int"'s were changed to "short"'s for UTS compatability. ! 167: - ! 168: - The NODE struct pointed to by a NODEPTR now needs a "mark" field. ! 169: - ! 170: - A printTree(NODEPTR n) routine must also be supplied by the user. ! 171: - ! 172: - If you were using the values of nodes in your symbols.h file ! 173: - then the command ! 174: - cc -g -c -DDUMPNAMES sym.c ! 175: - should be used to compile sym.c. ! 176: //GO.SYSIN DD README ! 177: echo code.c 1>&2 ! 178: sed 's/.//' >code.c <<'//GO.SYSIN DD code.c' ! 179: -#include "common.h" ! 180: -#include "code.h" ! 181: -#define BLOCKSIZE 10 ! 182: - ! 183: -Code *cdfreep = NULL; ! 184: - ! 185: -Code * ! 186: -CodeGetBlock() ! 187: -{ ! 188: - static int count = 0; ! 189: - static Code *blockp = NULL; ! 190: - Code *cp; ! 191: - ! 192: - if(cdfreep!=NULL) { ! 193: - cp = cdfreep; ! 194: - cdfreep = cdfreep->prev; ! 195: - } else { ! 196: - if(count==0) { ! 197: - blockp = (Code *) malloc (BLOCKSIZE*sizeof(Code)); ! 198: - count = BLOCKSIZE; ! 199: - } ! 200: - cp = blockp++; ! 201: - count--; ! 202: - } ! 203: - cp->prev = NULL; ! 204: - cp->firstFree = cp->segment; ! 205: - return(cp); ! 206: -} ! 207: - ! 208: -void ! 209: -CodeFreeBlock(cd) ! 210: - Code *cd; ! 211: -{ ! 212: - if (cd!=NULL) { ! 213: - cd->prev = cdfreep; ! 214: - cdfreep = cd; ! 215: - } ! 216: -} ! 217: - ! 218: -Code * ! 219: -CodeStoreChar(cd, c) ! 220: - Code *cd; ! 221: - char c; ! 222: -{ ! 223: - if(cd->firstFree - cd->segment >= CSEGSIZE) { ! 224: - Code *ncd = CodeGetBlock(); ! 225: - ncd->prev = cd; ! 226: - cd = ncd; ! 227: - } ! 228: - *cd->firstFree = c; ! 229: - cd->firstFree++; ! 230: - return(cd); ! 231: -} ! 232: - ! 233: -Code * ! 234: -CodeStoreString(cd, s) ! 235: - Code *cd; ! 236: - char *s; ! 237: -{ ! 238: - while(*s!='\0') cd = CodeStoreChar(cd, *s++); ! 239: - return(cd); ! 240: -} ! 241: - ! 242: -Code * ! 243: -CodeAppend(cd1, cd2) ! 244: - Code *cd1, *cd2; ! 245: -{ ! 246: - if(cd2==NULL) return(cd1); ! 247: - cd2->prev = CodeAppend(cd1, cd2->prev); ! 248: - return(cd2); ! 249: -} ! 250: - ! 251: -void ! 252: -CodeWrite(f, cd) ! 253: - FILE *f; ! 254: - Code *cd; ! 255: -{ ! 256: - register char *cp; ! 257: - ! 258: - if (cd != NULL) ! 259: - {CodeWrite(outfile, cd->prev); ! 260: - for(cp=cd->segment; cp < cd->firstFree; cp++) ! 261: - putc(*cp, f); ! 262: - } ! 263: -} ! 264: - ! 265: -Code * ! 266: -CodeMarkLine(cd,lineno) ! 267: - Code *cd; ! 268: - int lineno; ! 269: -{ ! 270: - char buf[100]; ! 271: - sprintf(buf,"\n# line %d \"%s\"\n", lineno, inFileName); ! 272: - return(CodeStoreString(cd,buf)); ! 273: -} ! 274: //GO.SYSIN DD code.c ! 275: echo code.h 1>&2 ! 276: sed 's/.//' >code.h <<'//GO.SYSIN DD code.h' ! 277: -#define CSEGSIZE 512-2*sizeof(int) ! 278: - ! 279: -typedef struct Code { ! 280: - struct Code *prev; ! 281: - char *firstFree; ! 282: - char segment[CSEGSIZE]; ! 283: - } Code; ! 284: - ! 285: -extern Code *CodeStoreChar(); ! 286: -extern Code *CodeGetBlock(); ! 287: -extern Code *CodeAppend(); ! 288: -extern Code *CodeStoreString(), *CodeMarkLine(); ! 289: //GO.SYSIN DD code.h ! 290: echo common.h 1>&2 ! 291: sed 's/.//' >common.h <<'//GO.SYSIN DD common.h' ! 292: -#include <stdio.h> ! 293: -#include <assert.h> ! 294: - ! 295: -#define MAXIDSIZE 100 ! 296: -#define HASHSIZE 1181 ! 297: -#define MAXPATH 32 ! 298: -#define MAXBRANCH 10 ! 299: -#define MAXACCEPTS 100 ! 300: -#define MAXSTATES 200 ! 301: -/* type definitions */ ! 302: -typedef char byte; ! 303: - ! 304: -/* forward and external type defs */ ! 305: -extern struct node *GetNode(); ! 306: -extern struct edges *GetEdge(); ! 307: -extern struct augmented_edges *GetAugEdges(); ! 308: -extern char *malloc(); ! 309: -extern char *strrchr(); ! 310: -extern FILE *outfile; ! 311: -extern FILE *symfile; ! 312: - ! 313: -extern int debug_flag; ! 314: -# define DB_LEX 1 /* print out lexical analyser debugging info */ ! 315: -# define DB_MACH 2 /* print out machine information */ ! 316: -# define DB_SYM 4 /* print out symbol debugging info */ ! 317: -# define DB_TREE 8 /* print out trees */ ! 318: -# define DB_MEM 16 /* check memory usage */ ! 319: -extern int tflag; /* generate tables only */ ! 320: -extern int ntrees; ! 321: -extern int unique; ! 322: - ! 323: -/* tree definitions */ ! 324: -typedef struct node Node; ! 325: -typedef struct symbol_entry SymbolEntry; ! 326: - ! 327: -/* Nodes provide the backbone for the trees built by the parser */ ! 328: -struct node { ! 329: - SymbolEntry *sym; ! 330: - int nlleaves; /* count of the labelled leaves */ ! 331: - Node *children; ! 332: - Node *siblings; ! 333: -}; ! 334: - ! 335: -extern Node *TreeBuild(); ! 336: - ! 337: -/* path defintions */ ! 338: -extern void path_setup(); ! 339: - ! 340: -/* lexical analyser */ ! 341: -extern int yyline; ! 342: -extern char *inFileName; ! 343: -extern char token_buffer[MAXIDSIZE+1]; ! 344: - ! 345: -extern void LexInit(); ! 346: -extern yylex(); ! 347: //GO.SYSIN DD common.h ! 348: echo doc 1>&2 ! 349: sed 's/.//' >doc <<'//GO.SYSIN DD doc' ! 350: //GO.SYSIN DD doc ! 351: echo examples 1>&2 ! 352: sed 's/.//' >examples <<'//GO.SYSIN DD examples' ! 353: //GO.SYSIN DD examples ! 354: echo io.c 1>&2 ! 355: sed 's/.//' >io.c <<'//GO.SYSIN DD io.c' ! 356: -#include "common.h" ! 357: -#define MAXINTONLINE 10 ! 358: -static int intcnt, intonline, firstint; ! 359: - ! 360: -oreset() ! 361: -{ ! 362: - intcnt = 0; ! 363: - intonline = 0; ! 364: - firstint = 1; ! 365: -} ! 366: - ! 367: -ointcnt() { return(intcnt); } ! 368: - ! 369: -oputint(i) ! 370: -{ ! 371: - if(!firstint) putc(',', outfile); ! 372: - else firstint = 0; ! 373: - fprintf(outfile, "%d", i); ! 374: - intonline++; ! 375: - intcnt++; ! 376: - if(intonline >= MAXINTONLINE) { putc('\n', outfile); intonline = 0; } ! 377: -} ! 378: - ! 379: -oputoct(i) ! 380: -{ ! 381: - if(!firstint) putc(',', outfile); ! 382: - else firstint = 0; ! 383: - fprintf(outfile, "0%o", i); ! 384: - intonline++; ! 385: - intcnt++; ! 386: - if(intonline >= MAXINTONLINE) { putc('\n', outfile); intonline = 0; } ! 387: -} ! 388: //GO.SYSIN DD io.c ! 389: echo lex.c 1>&2 ! 390: sed 's/.//' >lex.c <<'//GO.SYSIN DD lex.c' ! 391: -#include <ctype.h> ! 392: -#include "common.h" ! 393: -#include "code.h" ! 394: -#include "sym.h" ! 395: -#include "y.tab.h" ! 396: - ! 397: -int yyline = 1; ! 398: -char token_buffer[MAXIDSIZE+1]; ! 399: -extern YYSTYPE yylval; ! 400: -static void ScanCodeBlock(); ! 401: -static void ScanComment(); ! 402: -static Code *curCdBlock; ! 403: -static char get(); ! 404: - ! 405: -yylex() ! 406: -{ ! 407: - register c; ! 408: - register char *cp; ! 409: - int in_ident = 0; ! 410: - yylval.y_nodep = (struct node *) NULL; ! 411: - cp = token_buffer; ! 412: - while((c=getchar())!=EOF) { ! 413: - switch(c) { ! 414: - case ' ': case '\t': case '\f': ! 415: - continue; ! 416: - case '@': case '[': case ']': case ';': case ':': ! 417: - case '(': case ')': case ',': case '=': ! 418: - case '*': ! 419: - if(debug_flag&DB_LEX) { ! 420: - putc(c,stderr); ! 421: - putc('\n', stderr); ! 422: - } ! 423: - *cp++ = c; ! 424: - *cp = '\0'; ! 425: - return(c); ! 426: - ! 427: - case '{': ! 428: - ScanCodeBlock(); ! 429: - yylval.y_code = curCdBlock; ! 430: - curCdBlock = NULL; ! 431: - *cp++ = '{'; *cp++ = '}'; ! 432: - return(CBLOCK); ! 433: - ! 434: - case '\n': ! 435: - yyline++; ! 436: - continue; ! 437: - case '/': ! 438: - if ((c=getchar())=='*') { ! 439: - ScanComment(get); ! 440: - continue; ! 441: - } else { ! 442: - ungetc(c, stdin); ! 443: - c = '/'; ! 444: - } ! 445: - /* FALL THRU */ ! 446: - ! 447: - default: ! 448: - if (isdigit(c)) { ! 449: - int errs = 0; ! 450: - do { ! 451: - if(cp > &token_buffer[MAXIDSIZE]) { ! 452: - token_buffer[MAXIDSIZE] = '\0'; ! 453: - yyerror("number too long"); ! 454: - errs++; ! 455: - } else *cp++ = c; ! 456: - c = getchar(); ! 457: - } while (isdigit(c)); ! 458: - if(isalpha(c)) ! 459: - yyerror2("illegal digit '%c'", c); ! 460: - ungetc(c, stdin); ! 461: - if(errs) ! 462: - return(ERROR); ! 463: - yylval.y_int = atoi(token_buffer); ! 464: - return(NUMBER); ! 465: - } ! 466: - if (isalpha(c)) { ! 467: - SymbolEntry *sp; ! 468: - int errs = 0; ! 469: - do { ! 470: - if(cp > &token_buffer[MAXIDSIZE]) { ! 471: - token_buffer[MAXIDSIZE] = '\0'; ! 472: - yyerror("ID too long"); ! 473: - errs++; ! 474: - } else *cp++ = c; ! 475: - c = getchar(); ! 476: - } while (isalpha(c)||isdigit(c)||c=='_'); ! 477: - ungetc(c, stdin); ! 478: - if(errs) ! 479: - return(ERROR); ! 480: - *cp = '\0'; ! 481: - ! 482: - sp = SymbolLookup (token_buffer); ! 483: - if (sp==NULL) { ! 484: - /* undefined */ ! 485: - yylval.y_symp = SymbolAllocate(token_buffer); ! 486: - } else { ! 487: - /* already defined */ ! 488: - if (sp->attr == A_KEYWORD) ! 489: - return (sp->sd.keyword); ! 490: - yylval.y_symp = sp; ! 491: - } ! 492: - if(debug_flag&DB_LEX) ! 493: - fprintf(stderr, "ID\n"); ! 494: - return(ID); ! 495: - } ! 496: - yyerror2("illegal character (\\%03o)", c); ! 497: - } ! 498: - } ! 499: - strcpy(token_buffer, "EOF"); ! 500: - return(0); ! 501: -} ! 502: - ! 503: -void ! 504: -LexInit() ! 505: -{ ! 506: -} ! 507: - ! 508: -lexCleanup() ! 509: -{ ! 510: -} ! 511: - ! 512: -/* ! 513: - * Beware: ungets of the characters from these routines may screw up the ! 514: - * line count ! 515: - */ ! 516: -static char ! 517: -getput() ! 518: -{ ! 519: - /* keutzer ! 520: - char c; ! 521: - */ ! 522: - int c; ! 523: - c = getchar(); ! 524: - if(c=='\n') yyline++; ! 525: - if(c!=EOF) ! 526: - curCdBlock = CodeStoreChar(curCdBlock, c); ! 527: - return(c); ! 528: -} ! 529: - ! 530: -static char ! 531: -get() ! 532: -{ ! 533: - /* keutzer ! 534: - char c; ! 535: - */ ! 536: - int c; ! 537: - c = getchar(); ! 538: - if(c=='\n') yyline++; ! 539: - return(c); ! 540: -} ! 541: - ! 542: -extern int nerrors; ! 543: - ! 544: -static void ! 545: -ScanComment(rdfunc) ! 546: - char (*rdfunc)(); ! 547: -{ ! 548: - int startline = yyline; ! 549: - /* keutzer ! 550: - char c; ! 551: - */ ! 552: - int c; ! 553: - int saw_star = 0; ! 554: - while ((c=rdfunc())!=EOF) { ! 555: - if (c=='*') ! 556: - saw_star++; ! 557: - else if(c=='/' && saw_star) { ! 558: - return; ! 559: - } else saw_star = 0; ! 560: - } ! 561: - yyerror2("unexpected EOF in comment beginning on line %d", startline); ! 562: - nerrors++; ! 563: - cleanup(1); ! 564: -} ! 565: - ! 566: -static ! 567: -ScanString(rdfunc) ! 568: - char (*rdfunc)(); ! 569: -{ ! 570: - int startline = yyline; ! 571: - /* keutzer ! 572: - char c; ! 573: - */ ! 574: - int c; ! 575: - int saw_backsl = 0; ! 576: - ! 577: - while((c=rdfunc())!=EOF) { ! 578: - if (c=='"' && !saw_backsl) ! 579: - return; ! 580: - if (c=='\\' && !saw_backsl) { ! 581: - saw_backsl = 1; ! 582: - continue; ! 583: - } ! 584: - saw_backsl = 0; ! 585: - } ! 586: - /* fall thru due to EOF */ ! 587: - yyerror2("unexpected EOF in string beginning on line %d", startline); ! 588: - nerrors++; ! 589: - cleanup(1); ! 590: -} ! 591: - ! 592: -static ! 593: -ScanChar() ! 594: -{ ! 595: - int startline = yyline; ! 596: - /* keutzer ! 597: - char c; ! 598: - */ ! 599: - int c; ! 600: - int saw_backsl = 0; ! 601: - ! 602: - while((c=getput(stdin))!=EOF) { ! 603: - if (c=='\'' && !saw_backsl) ! 604: - return; ! 605: - if (c=='\\' && !saw_backsl) { ! 606: - saw_backsl = 1; ! 607: - continue; ! 608: - } ! 609: - saw_backsl = 0; ! 610: - } ! 611: - /* fall thru due to EOF */ ! 612: - yyerror2("unexpected EOF in character constant beginning on line %d", ! 613: - startline); ! 614: - nerrors++; ! 615: - cleanup(1); ! 616: -} ! 617: - ! 618: -static void ! 619: -ScanTreeReference() ! 620: -{ ! 621: - ! 622: - /* keutzer ! 623: - char c; ! 624: - */ ! 625: - int c; ! 626: - c = getchar(); ! 627: - if(c=='%') { ! 628: - curCdBlock = CodeStoreString (curCdBlock, "_ll[("); ! 629: - while ((c=getchar())!=EOF && c!='$') { ! 630: - if(!isdigit(c)) { ! 631: - yyerror("unclosed $ reference"); ! 632: - ungetc(c,stdin); ! 633: - break; ! 634: - } ! 635: - curCdBlock = CodeStoreChar(curCdBlock, c); ! 636: - } ! 637: - curCdBlock = CodeStoreString (curCdBlock, ")-1]"); ! 638: - return; ! 639: - } ! 640: - else if(c=='$') { ! 641: - curCdBlock = CodeStoreString(curCdBlock, "root"); ! 642: - return; ! 643: - } else curCdBlock = CodeStoreString(curCdBlock, "_mtG(root,"); ! 644: - do { ! 645: - if(!isdigit(c) && c!='.') { ! 646: - yyerror("unclosed $ reference"); ! 647: - ungetc(c,stdin); ! 648: - break; ! 649: - } ! 650: - curCdBlock = CodeStoreChar(curCdBlock, c=='.' ? ',' : c); ! 651: - } while((c=getchar())!=EOF && c!='$'); ! 652: - curCdBlock = CodeStoreString(curCdBlock, ", -1)"); ! 653: -} ! 654: - ! 655: -static void ! 656: -ScanCodeBlock() ! 657: -{ ! 658: - int startline = yyline; ! 659: - /* keutzer ! 660: - char c; ! 661: - */ ! 662: - int c; ! 663: - if(curCdBlock==NULL) { ! 664: - curCdBlock = CodeGetBlock(); ! 665: - curCdBlock = CodeMarkLine(curCdBlock,yyline); ! 666: - } ! 667: - while((c=getc(stdin))!=EOF) { ! 668: - if (c=='}') ! 669: - return; ! 670: - else if (c=='$') ScanTreeReference(); ! 671: - else curCdBlock = CodeStoreChar(curCdBlock, c); ! 672: - if (c=='\n') yyline++; ! 673: - if (c=='"') ScanString(getput); ! 674: - else if (c=='\'') ScanChar(); ! 675: - else if (c=='/') { ! 676: - if ((c=getc(stdin))=='*') { ! 677: - curCdBlock = CodeStoreChar(curCdBlock, '*'); ! 678: - ScanComment(getput); ! 679: - } ! 680: - else ungetc(c, stdin); ! 681: - } ! 682: - else if (c=='{') { ! 683: - ScanCodeBlock(); ! 684: - curCdBlock = CodeStoreChar (curCdBlock, '}'); ! 685: - } ! 686: - } ! 687: - yyerror2("{ on line %d has no closing }", startline); ! 688: - nerrors++; ! 689: -} ! 690: //GO.SYSIN DD lex.c ! 691: echo machcomm.h 1>&2 ! 692: sed 's/.//' >machcomm.h <<'//GO.SYSIN DD machcomm.h' ! 693: -/* ! 694: - * The machine is laid out as a sequence of integers in the walker. ! 695: - * The form described above is only used inside the preprocessor. ! 696: - * Each machine state is one of the following sequence: ! 697: - * ! 698: - * TABLE <value_1><index_1>...<value_n><index_n> -1 [FAIL <fail_index>] -1 ! 699: - * or ! 700: - * TABLE2 <value_1><index_1>...<value_n><index_n> -1 [FAIL <fail_index>] -1 ! 701: - * or ! 702: - * ACCEPT <accept table index> -1 ! 703: - * ! 704: - * The accept table is in the form: ! 705: - * ! 706: - * <tree index_1> ...<tree_index_m> -1 ! 707: - * ! 708: - */ ! 709: - ! 710: -#define FASTLIM 0 ! 711: -#define TABLE 1 ! 712: -#define FAIL 2 ! 713: -#define ACCEPT 3 ! 714: -#define TABLE2 4 ! 715: -#define EOT -1 ! 716: - ! 717: -/* special machine state */ ! 718: -#define HANG -1 ! 719: - ! 720: -/* used by the evaluator to interpret path table */ ! 721: -#define eSTOP 0 ! 722: -#define ePOP -1 ! 723: -#define eEVAL -2 ! 724: -#define eNEXT -3 ! 725: -#define ePUSH -4 ! 726: - ! 727: -/* Tags that indicate the type of a value */ ! 728: -#define M_BRANCH 010000 ! 729: -#define M_NODE 0 ! 730: -#define M_LABEL 01000 ! 731: -#define MAX_NODE_VALUE 00777 ! 732: -#define MTAG_SHIFT 9 ! 733: -#define M_DETAG(x) ((x)&~(M_BRANCH|M_LABEL|M_NODE)) ! 734: - ! 735: -/* predicates to tell whether a value x is of type NODE, BRANCH, or LABEL */ ! 736: -#define MI_NODE(x) (((x)&(M_BRANCH|M_LABEL))==0) ! 737: -#define MI_DEFINED(x) ((x)!=-1) ! 738: -#define MI_LABEL(x) (((x)&M_LABEL)!=0) ! 739: -#define MI_BRANCH(x) (((x)&M_BRANCH)!=0) ! 740: - ! 741: -/* build a tagged value */ ! 742: -#define MV_NODE(x) (x) ! 743: -#define MV_BRANCH(x) ((x)|M_BRANCH) ! 744: -#define MV_LABEL(x) ((x)|M_LABEL) ! 745: - ! 746: //GO.SYSIN DD machcomm.h ! 747: echo machine.c 1>&2 ! 748: sed 's/.//' >machine.c <<'//GO.SYSIN DD machine.c' ! 749: -#include "common.h" ! 750: -#include "code.h" ! 751: -#include "sym.h" ! 752: -#include "machine.h" ! 753: - ! 754: -int gen_table2; /* generate type two tables */ ! 755: -struct machine_node *machine = NULL; ! 756: -static int depth; ! 757: - ! 758: -static struct machine_node * ! 759: -get_state() ! 760: -{ ! 761: - struct machine_node *mp = (struct machine_node *) ! 762: - malloc (sizeof (struct machine_node)); ! 763: - assert (mp!=NULL); ! 764: - mp->inp.value = -1; ! 765: - mp->nst = NULL; ! 766: - mp->link = NULL; ! 767: - mp->fail = NULL; ! 768: - mp->match = NULL; ! 769: - return(mp); ! 770: -} ! 771: - ! 772: -add_match(s, tp, depth) ! 773: - struct machine_node *s; ! 774: - LabelData *tp; ! 775: - int depth; ! 776: -{ ! 777: - struct match *mp = (struct match *) malloc (sizeof (struct match)); ! 778: - ! 779: - assert (mp!=NULL); ! 780: - mp->next = s->match; ! 781: - mp->depth = depth; ! 782: - mp->tree = tp; ! 783: - s->match = mp; ! 784: -} ! 785: - ! 786: -/* ! 787: - * Build a trie from the path strings. Failure transition are added later. ! 788: - */ ! 789: -cgotofn(tp) ! 790: - LabelData *tp; ! 791: -{ ! 792: - struct machine_input inp; ! 793: - int ret; ! 794: - register struct machine_node *s; ! 795: - register int quit = 0; ! 796: - ! 797: - if (machine==NULL) { ! 798: - /* first time thru */ ! 799: - machine = get_state(); ! 800: - } ! 801: - s = machine; ! 802: - depth = -1; ! 803: - ! 804: - assert (tp->tree!=NULL); ! 805: - path_setup (tp->tree); ! 806: - ! 807: - for(;;) { ! 808: - ret = path_getsym(&inp); ! 809: - ! 810: - /* no more paths */ ! 811: - if (ret == EOF) ! 812: - break; ! 813: - ! 814: - if (ret == NULL) { ! 815: - /* ! 816: - * the end of the path. Add a match to the ! 817: - * accepting state. ! 818: - */ ! 819: - assert ((depth&01)==0); /* make sure it's even */ ! 820: - add_match(s, tp, depth >> 1); ! 821: - s = machine; ! 822: - depth = -1; ! 823: - ntrees++; ! 824: - continue; ! 825: - } ! 826: - ! 827: - while (!MI_EQUAL(s->inp, inp)) { ! 828: - if (!MI_DEFINED(s->inp.value) || s->link == NULL) { ! 829: - if (MI_DEFINED(s->inp.value)) { ! 830: - /* ! 831: - * The trie must be split here ! 832: - */ ! 833: - s->link = get_state(); ! 834: - s = s->link; ! 835: - } ! 836: - /* ! 837: - * Fill in the state ! 838: - */ ! 839: - s->inp = inp; ! 840: - s->nst = get_state(); ! 841: - s = s->nst; ! 842: - depth++; ! 843: - break; ! 844: - } else s = s->link; ! 845: - } ! 846: - if (MI_EQUAL(s->inp, inp)) { ! 847: - s = s->nst; ! 848: - depth++; ! 849: - } ! 850: - } ! 851: -} ! 852: - ! 853: -/* print out the machine for debugging */ ! 854: -machine_print(mp) ! 855: - struct machine_node *mp; ! 856: -{ ! 857: - register struct machine_node *mp2; ! 858: - struct machine_node *fail; ! 859: - struct match *match, *p; ! 860: - ! 861: - if (mp==NULL) ! 862: - return; ! 863: - printf("%x %d:", mp, mp->index); ! 864: - if((fail = mp->fail)) ! 865: - printf("\tfail %x", fail); ! 866: - if((match = mp->match)) { ! 867: - printf("\taccept "); ! 868: - for(p = match; p!=NULL; p = p->next) { ! 869: - LabelData *tp = p->tree; ! 870: - printf("%s ", (tp->label)->name); ! 871: - } ! 872: - } ! 873: - putchar('\n'); ! 874: - for(mp2=mp; mp2!=NULL; mp2 = mp2->link) { ! 875: - if (MI_DEFINED(mp2->inp.value)) { ! 876: - if (MI_BRANCH(mp->inp.value)) ! 877: - printf(" %d -> ", mp2->inp.value); ! 878: - else ! 879: - printf(" [%s] -> ", (mp2->inp.sym)->name); ! 880: - printf("%x", mp2->nst); ! 881: - } ! 882: - assert(mp2->fail==fail); ! 883: - assert(mp2->match==match); ! 884: - } ! 885: - if(MI_DEFINED(mp->inp.value)) ! 886: - putchar('\n'); ! 887: - for (mp2 = mp; mp2!=NULL; mp2=mp2->link) { ! 888: - machine_print(mp2->nst); ! 889: - } ! 890: -} ! 891: - ! 892: -/* ! 893: - * This routine augments the machine with failure transition. ! 894: - * The trie is examined in breadth first order. ! 895: - * See Aho, Corasick Comm ACM 18:6 for details ! 896: - */ ! 897: -cfail() ! 898: -{ ! 899: - struct machine_node **stack, **stack2; ! 900: - struct machine_node **stackTop, **stack2Top, **temp; ! 901: - int stackCnt, stack2Cnt; ! 902: - struct machine_node *state; ! 903: - struct machine_input sym; ! 904: - register struct machine_node *s, *q; ! 905: - ! 906: - /* allocate stacks */ ! 907: - stackTop = stack = (struct machine_node **) malloc ! 908: - (ntrees*sizeof (struct machine_node *)); ! 909: - stack2 = stack2Top = (struct machine_node **) malloc ! 910: - (ntrees*sizeof (struct machine_node *)); ! 911: - stackCnt = stack2Cnt = 0; ! 912: - s = machine; ! 913: - do { ! 914: - if (MI_DEFINED(s->inp.value)) { ! 915: - assert(++stackCnt <= ntrees); ! 916: - *stackTop++ = s->nst; ! 917: - } ! 918: - s = s->link; ! 919: - } while (s != NULL); ! 920: - ! 921: - for(;;) { ! 922: - if (stackCnt == 0) { ! 923: - /* swap stacks */ ! 924: - if (stack2Cnt == 0) ! 925: - break; ! 926: - stackCnt = stack2Cnt; stack2Cnt = 0; ! 927: - stackTop = stack2Top; ! 928: - temp = stack; stack = stack2; stack2 = temp; ! 929: - stack2Top = stack2; ! 930: - } ! 931: - stackCnt--; ! 932: - s = *--stackTop; ! 933: - do { ! 934: - int startstate = 0; ! 935: - sym = s->inp; ! 936: - if (MI_DEFINED(sym.value)) { /* g(s,c) != 0 */ ! 937: - assert (++stack2Cnt <= ntrees); ! 938: - *stack2Top++ = (q=s->nst); ! 939: - state = s->fail; /* state = f(s) */ ! 940: - for(;;) { ! 941: - if (state == 0) { ! 942: - state = machine; ! 943: - startstate++; ! 944: - } ! 945: - if (MI_EQUAL(state->inp, sym)) { ! 946: - struct match *mp = NULL; ! 947: - ! 948: - /* append any accepting matches */ ! 949: - for(mp=(state->nst)->match;mp;mp=mp->next) ! 950: - add_match(q,mp->tree, mp->depth); ! 951: - mp = q->match; ! 952: - ! 953: - do { ! 954: - /* f(q) = g(state,sym) ! 955: - * for all q links */ ! 956: - q->fail = state->nst; ! 957: - q->match = mp; ! 958: - } while ((q = q->link) != 0); ! 959: - break; ! 960: - } ! 961: - else if (state->link != 0) ! 962: - state = state->link; ! 963: - else { ! 964: - state = state->fail; ! 965: - if (state==NULL&&startstate) ! 966: - break; ! 967: - } ! 968: - } ! 969: - } ! 970: - s = s->link; ! 971: - } while (s!=NULL); ! 972: - } ! 973: -} ! 974: - ! 975: -/* ! 976: - * Called from the YACC rule pattern_spec ! 977: - */ ! 978: -void ! 979: -machine_build() ! 980: -{ ! 981: - cfail(); ! 982: - (void) MachineNumber(machine, 0); ! 983: - if(debug_flag&DB_MACH) { ! 984: - fputs("\n-------\n", stderr); ! 985: - machine_print(machine); ! 986: - } ! 987: -} ! 988: - ! 989: -struct match *acceptTable[MAXACCEPTS]; ! 990: -struct match **acceptTableTop = acceptTable; ! 991: -static short int *arityTable; ! 992: -int nextAcceptIndex = 0; ! 993: - ! 994: -/* ! 995: - * This is the first pass of the process to generate the ! 996: - * flattened machine used in the walker. Called from machine_build ! 997: - */ ! 998: -int ! 999: -MachineNumber(mach, index) ! 1000: - struct machine_node *mach; ! 1001: - int index; ! 1002: -{ ! 1003: - struct machine_node *mp; ! 1004: - ! 1005: - for(mp=mach; mp!=NULL; mp = mp->link) ! 1006: - if(MI_DEFINED(mp->inp.value)) ! 1007: - index = MachineNumber(mp->nst, index); ! 1008: - ! 1009: - mach->index = index; ! 1010: - if (mach->match!=NULL) index += 2; ! 1011: - if(mach->link!=NULL || mach->nst!=NULL) { ! 1012: - index += 2; ! 1013: - for(mp = mach; mp!=NULL; mp = mp->link) ! 1014: - if(mp->nst!=NULL) ! 1015: - index += 2; ! 1016: - } ! 1017: - ! 1018: - if (mach->fail!=NULL) ! 1019: - index += 2; ! 1020: - index++; ! 1021: - return(index); ! 1022: -} ! 1023: - ! 1024: -/* ! 1025: - * Build the flattened out machine used in the walker. ! 1026: - * See machine.h for description ! 1027: - */ ! 1028: -MachineGen() ! 1029: -{ ! 1030: - struct match **atp, *ap; ! 1031: - short int *sp; ! 1032: - ! 1033: - oreset(); ! 1034: - fputs("short int mtTable[] = {\n", outfile); ! 1035: - machineGen2(machine); ! 1036: - fputs("};\n", outfile); ! 1037: - ! 1038: - fputs("short int mtAccept[] = {\n", outfile); ! 1039: - ! 1040: - oreset(); ! 1041: - for(atp = acceptTable; atp < acceptTableTop; atp++) { ! 1042: - for(ap = *atp; ap!=NULL; ap = ap->next) { ! 1043: - register LabelData *tree = ap->tree; ! 1044: - ! 1045: - /* if you change any of the code below you must change ! 1046: - * the increment added to nextAcceptIndex in ! 1047: - * machineGen2 ! 1048: - */ ! 1049: - oputint(tree->treeIndex); ! 1050: - oputint(ap->depth); ! 1051: - } ! 1052: - oputint(-1); ! 1053: - } ! 1054: - fprintf(outfile, "};\nshort int mtStart = %d;\n", machine->index); ! 1055: -} ! 1056: - ! 1057: -machineGen2(mach) ! 1058: - struct machine_node *mach; ! 1059: -{ ! 1060: - struct machine_node *mp; ! 1061: - struct match *ap; ! 1062: - ! 1063: - if (mach==NULL) ! 1064: - return; ! 1065: - ! 1066: - for(mp=mach; mp!=NULL; mp = mp->link) ! 1067: - if(MI_DEFINED(mp->inp.value)) ! 1068: - machineGen2(mp->nst); ! 1069: - ! 1070: - assert(mach->index == ointcnt()); ! 1071: - if (mach->match!=NULL) { ! 1072: - *acceptTableTop++ = mach->match; ! 1073: - oputint(ACCEPT); oputint(nextAcceptIndex); ! 1074: - for(ap = mach->match; ap!=NULL; ap = ap->next) ! 1075: - nextAcceptIndex += 2; ! 1076: - nextAcceptIndex++; ! 1077: - } ! 1078: - if(mach->link!=NULL || mach->nst!=NULL) { ! 1079: - if(MI_BRANCH(mp->inp.value)&&gen_table2) { ! 1080: - oputint (TABLE2); ! 1081: - for(mp = mach; mp!=NULL; mp = mp->link) { ! 1082: - if(mp->nst!=NULL) { ! 1083: - oputoct(mp->inp.value); ! 1084: - oputint((mp->nst)->index); ! 1085: - } ! 1086: - } ! 1087: - } else { ! 1088: - oputint (TABLE); ! 1089: - for(mp = mach; mp!=NULL; mp = mp->link) { ! 1090: - if(mp->nst!=NULL) { ! 1091: - oputoct(mp->inp.value); ! 1092: - oputint((mp->nst)->index); ! 1093: - } ! 1094: - } ! 1095: - } ! 1096: - oputint(-1); ! 1097: - } ! 1098: - ! 1099: - /* A failure transition or a -1 terminate every state */ ! 1100: - if (mach->fail!=NULL) { ! 1101: - oputint(FAIL); oputint((mach->fail)->index); ! 1102: - } ! 1103: - oputint(-1); ! 1104: -} ! 1105: //GO.SYSIN DD machine.c ! 1106: echo machine.h 1>&2 ! 1107: sed 's/.//' >machine.h <<'//GO.SYSIN DD machine.h' ! 1108: -/* ! 1109: - * The machine used here is the same as the one used in fgrep. ! 1110: - * Logically, it is a trie of all the strings to be recognized. ! 1111: - * In this case, the strings are the paths of tree patterns. ! 1112: - * The nodes of the trie are the states of the machine and leaves ! 1113: - * are accepting states. The trie is augmented by failure transitions. ! 1114: - * ! 1115: - * Each machine state is a linked list of machine_node's and referred to ! 1116: - * by pointing to the head of the list. The machine_node represents a ! 1117: - * transition. The nst field points to the next state when the current ! 1118: - * input is MI_EQUAL to the inp field. If the input is not MI_EQUAL to any ! 1119: - * of the inp fields in the list, the next state is the one that fail ! 1120: - * points to. The fail field must be the same for all machine_node's in ! 1121: - * a state. Accepting states have inp.value equal to -1, and the match ! 1122: - * field points to a list of match structures. The match structures record ! 1123: - * which trees have been partially matched. ! 1124: - * ! 1125: - * The index is used by the machine generator to convert the machine into ! 1126: - * a list of integers. ! 1127: - * ! 1128: - * Further details about the data structure and algorithms can be ! 1129: - * found in: ! 1130: - * Knuth, Morris, Pratt in SIAM J Computing 6:3 ! 1131: - * Aho, Corasick in Comm ACM 18:6 ! 1132: - * Hoffman, O'Donnell in JACM 29:1 ! 1133: - */ ! 1134: -struct machine_input { ! 1135: - short value; ! 1136: - struct symbol_entry *sym; ! 1137: -}; ! 1138: -#define MI_EQUAL(x,y) ((x).value==(y).value) ! 1139: - ! 1140: -#include "machcomm.h" ! 1141: - ! 1142: -extern int path_getsym(); ! 1143: - ! 1144: -struct machine_node { ! 1145: - struct machine_input inp; ! 1146: - struct machine_node *nst; ! 1147: - struct machine_node *link; ! 1148: - struct machine_node *fail; ! 1149: - struct match *match; ! 1150: - short int index; ! 1151: -}; ! 1152: - ! 1153: -struct match { ! 1154: - struct match *next; ! 1155: - short int depth; ! 1156: - LabelData *tree; ! 1157: -}; ! 1158: - ! 1159: -extern struct machine_node *machine; ! 1160: - ! 1161: -extern void machine_build(); ! 1162: //GO.SYSIN DD machine.h ! 1163: echo makefile 1>&2 ! 1164: sed 's/.//' >makefile <<'//GO.SYSIN DD makefile' ! 1165: -# ! 1166: -CC= cc ! 1167: -INSTALL= /usr/bin ! 1168: -TEMPLATES = /usr/lib/twig ! 1169: -SRCS= twig.y sym.c path.c machine.c trees.c lex.c code.c io.c mem.c ! 1170: -OBJS= y.tab.o sym.o path.o machine.o trees.o lex.o code.o io.o mem.o ! 1171: -HDRS= common.h code.h sym.h machine.h mem.h ! 1172: -PREFIX= \"$(TEMPLATES)/walker\" ! 1173: - ! 1174: -all: twig ! 1175: - ! 1176: -install: twig ! 1177: - mv twig $(INSTALL) ! 1178: - mv walker.c1 $(TEMPLATES) ! 1179: - ! 1180: -kindling: ! 1181: - bundle README makefile *.y *.c *.h rawwalker.* >kindling ! 1182: - ! 1183: -sym.h: code.h ! 1184: -machine.h: machcomm.h ! 1185: - touch machine.h ! 1186: - ! 1187: -machine.o: common.h sym.h machine.h machine.c ! 1188: - $(CC) -g -c machine.c ! 1189: - ! 1190: -path.o: common.h sym.h path.c ! 1191: - $(CC) -g -c path.c ! 1192: - ! 1193: -y.tab.h: common.h sym.h twig.y ! 1194: - yacc -d twig.y ! 1195: - ! 1196: -y.tab.c: y.tab.h common.h sym.h twig.y ! 1197: -y.tab.o: y.tab.c ! 1198: - $(CC) -DPREFIX_BASE=$(PREFIX) -g -c y.tab.c ! 1199: - ! 1200: -sym.o: common.h sym.h y.tab.h sym.c ! 1201: - $(CC) -g -c sym.c ! 1202: - ! 1203: -trees.o: common.h sym.h ! 1204: - $(CC) -g -c trees.c ! 1205: - ! 1206: -lex.o: common.h sym.h y.tab.h lex.c ! 1207: - $(CC) -g -c lex.c ! 1208: - ! 1209: -code.o: common.h code.h ! 1210: - $(CC) -g -c code.c ! 1211: - ! 1212: -io.o: common.h io.c ! 1213: - $(CC) -g -c io.c ! 1214: - ! 1215: -mem.o: common.h mem.c ! 1216: - $(CC) -g -c mem.c ! 1217: - ! 1218: -twig: $(OBJS) ! 1219: - $(CC) -g -o twig $(OBJS) ! 1220: - ! 1221: -# generate walker from templates ! 1222: -walker.c1: machcomm.h walker.h rawwalker.c1 ! 1223: - cat machcomm.h walker.h rawwalker.c1 >walker.c1 ! 1224: - ! 1225: -walker.ex: machcomm.h walker.h rawwalker.ex ! 1226: - cat machcomm.h walker.h rawwalker.ex >walker.ex ! 1227: - ! 1228: -# at bell labs only ! 1229: -print: ! 1230: - pr makefile $(HDRS) $(SRCS) | 4can ! 1231: -bell_print: ! 1232: - pp makefile $(HDRS) $(SRCS) | dcan ! 1233: - ! 1234: -# at stanford only ! 1235: -enscript: ! 1236: - enscript -Pbt -2r makefile $(HDRS) $(SRCS) ! 1237: - ! 1238: //GO.SYSIN DD makefile ! 1239: echo mem.c 1>&2 ! 1240: sed 's/.//' >mem.c <<'//GO.SYSIN DD mem.c' ! 1241: -#include <stdio.h> ! 1242: -#include <assert.h> ! 1243: -#include "mem.h" ! 1244: - ! 1245: -#define BLKF 100 ! 1246: - ! 1247: -static struct _mem *mlist; ! 1248: - ! 1249: -static void ! 1250: -zap(cp,size) ! 1251: - char *cp; ! 1252: - int size; ! 1253: -{ ! 1254: - for(;size>0;size--) { ! 1255: - *cp = 0xff; ! 1256: - } ! 1257: -} ! 1258: -void ! 1259: -mem_init(mp, size) ! 1260: - struct _mem *mp; ! 1261: - int size; ! 1262: -{ ! 1263: - int i, s; ! 1264: - assert(size>=4); ! 1265: - mp->size = s = size; ! 1266: - s *= BLKF; ! 1267: - for (i=1; i < s; i <<= 1); ! 1268: - mp->bsize = i; ! 1269: - mp->blkf = mp->bsize/size; ! 1270: - mp->cnt = 0; ! 1271: - mp->freelist = NULL; ! 1272: - mp->totelem = 0; ! 1273: - mp->freecnt = 0; ! 1274: - mp->next = mlist; ! 1275: - mlist = mp; ! 1276: -}; ! 1277: - ! 1278: -char * ! 1279: -mem_get(mp) ! 1280: - struct _mem *mp; ! 1281: -{ ! 1282: - char *cp; ! 1283: - if (mp->freelist!=NULL) { ! 1284: - cp = mp->freelist; ! 1285: - mp->freelist = *(char **) cp; ! 1286: - mp->freecnt--; ! 1287: - zap(cp,mp->size); ! 1288: - return(cp); ! 1289: - } else if (mp->cnt==0) { ! 1290: - mp->block = (char *)malloc(mp->bsize); ! 1291: - mp->cnt = mp->blkf; ! 1292: - mp->totelem += mp->blkf; ! 1293: - } ! 1294: - mp->cnt--; ! 1295: - cp = mp->block; ! 1296: - mp->block += mp->size; ! 1297: - zap(cp,mp->size); ! 1298: - return(cp); ! 1299: -} ! 1300: - ! 1301: -mem_free(mp, cp) ! 1302: - struct _mem *mp; ! 1303: - char *cp;{ ! 1304: - *(char **)cp = mp->freelist; ! 1305: - mp->freelist = cp; ! 1306: - mp->freecnt++; ! 1307: -} ! 1308: - ! 1309: -mem_outstanding(mp) ! 1310: - struct _mem *mp; ! 1311: -{ ! 1312: - /* returns elements that are outstanding..i.e. asked for ! 1313: - * but haven't yet been returned ! 1314: - */ ! 1315: - return(mp->totelem - (mp->cnt+mp->freecnt)); ! 1316: -} ! 1317: - ! 1318: -mem_epilogue() ! 1319: -{ ! 1320: - struct _mem *mp; ! 1321: - /* ! 1322: - * if the following assertion fails then one of the following ! 1323: - * has happened: ! 1324: - * 1) somebody forgot to free something or ! 1325: - * 2) there is leakage. ! 1326: - */ ! 1327: - for(mp=mlist; mp!=NULL; mp = mp->next) { ! 1328: - assert(mem_outstanding(mp)==0); ! 1329: - } ! 1330: -} ! 1331: //GO.SYSIN DD mem.c ! 1332: echo mem.h 1>&2 ! 1333: sed 's/.//' >mem.h <<'//GO.SYSIN DD mem.h' ! 1334: -struct _mem { ! 1335: - struct _mem *next; ! 1336: - int size; /* size of individual elements in bytes */ ! 1337: - int blkf; /* blocking factor */ ! 1338: - int bsize; /* block size */ ! 1339: - char *block; /* block */ ! 1340: - int cnt; /* count of free elem in block */ ! 1341: - char *freelist; /* free list */ ! 1342: - int totelem; /* total number elements we have */ ! 1343: - int freecnt; /* number of times mem_free was called */ ! 1344: -}; ! 1345: //GO.SYSIN DD mem.h ! 1346: echo path.c 1>&2 ! 1347: sed 's/.//' >path.c <<'//GO.SYSIN DD path.c' ! 1348: -#include <stdio.h> ! 1349: -#include "common.h" ! 1350: -#include "code.h" ! 1351: -#include "sym.h" ! 1352: -#include "machine.h" ! 1353: - ! 1354: -/* ! 1355: - * Routines to enumerate paths of a tree. Firt call path_setup to ! 1356: - * initialize the internal data structure. Each component of the ! 1357: - * path may be consecutively retrieved by calling path_getsym. ! 1358: - */ ! 1359: - ! 1360: -/* ! 1361: - * For trees, a path is defined to be the sequence of nodes and edges ! 1362: - * from the root to a leaf. A path is represented here as a list of ! 1363: - * path components. Each component is represented by the following ! 1364: - * strucutre and may either be a pointer to a node or an integer. ! 1365: - * If the integer is i then the next component is the ith child of the ! 1366: - * previous component in the list. For example, "a 3 b 1 c" is a path ! 1367: - * for the tree "a(x,y,b(c,k))". The tag field indicates whether the ! 1368: - * component is a node or a branch. ! 1369: - * When the component represents a node then the node field points ! 1370: - * the corresponding Node structure. When the component is a branch then ! 1371: - * branch is the index of the current branch followed (1 is leftmost...) ! 1372: - * and node is a list of all unexamined children. ! 1373: - */ ! 1374: -struct path { ! 1375: - int tag; ! 1376: -#define P_NODE 0 ! 1377: -#define P_BRANCH 1 ! 1378: - int branch; ! 1379: - Node *node; ! 1380: -}; ! 1381: - ! 1382: -/* ! 1383: - * The path component list is stored in the path array. Path_length ! 1384: - * is the length of the path. Path_ptr points to the first unread ! 1385: - * component of the path component list. (see path_getsym ! 1386: - * and path_build for details) ! 1387: - */ ! 1388: -struct path path[2*MAXPATH]; ! 1389: -static int path_length; ! 1390: -static struct path *path_ptr = NULL; ! 1391: - ! 1392: -/* ! 1393: - * Given a tree, path_setup updates the path array with the leftmost ! 1394: - * of a subtree starting at root. The leftmost path is produced by ! 1395: - * following the leftmost branch of every encountered interior node ! 1396: - * starting at the root. Note that this routine can be used to layout ! 1397: - * the leftmost branch of a subtree into part of the path array and for ! 1398: - * initializing the path array with the leftmost path of the whole tree. ! 1399: - */ ! 1400: -void ! 1401: -path_setup(root) ! 1402: - Node *root; ! 1403: -{ ! 1404: - for(;;) { ! 1405: - register struct path *pp = &path[path_length++]; ! 1406: - Node *ep; ! 1407: - assert (root!=NULL); ! 1408: - ! 1409: - /* Place node in the component list */ ! 1410: - pp->tag = P_NODE; ! 1411: - pp->node = root; ! 1412: - ! 1413: - /* If leaf encountered exit */ ! 1414: - if ((ep=root->children)==NULL) ! 1415: - break; ! 1416: - ! 1417: - /* ! 1418: - * Mark that the left branch (i.e. 1st in our numbering ! 1419: - * scheme) was followed. ! 1420: - */ ! 1421: - pp = &path[path_length++]; ! 1422: - pp->tag = P_BRANCH; ! 1423: - pp->branch = 1; ! 1424: - pp->node = ep->siblings; ! 1425: - root = ep; ! 1426: - } ! 1427: - path_ptr = path; ! 1428: -} ! 1429: - ! 1430: -/* ! 1431: - * Path_build generates the next path of the tree and returns 0 if ! 1432: - * there are no more paths. Each path can be associated ! 1433: - * with exactly one leaf. Hence the ordering of paths generated by ! 1434: - * this routine is the same as a left to right ordering of the leaves. ! 1435: - */ ! 1436: -path_build() ! 1437: -{ ! 1438: - Node *np, *ep; ! 1439: - struct path *pp = &path[path_length-1]; ! 1440: - ! 1441: - /* ! 1442: - * Assert that the end of the last path was indeed ! 1443: - * a leaf. ! 1444: - */ ! 1445: - assert (pp->tag == P_NODE); ! 1446: - assert ((pp->node)->children == NULL); ! 1447: - ! 1448: - /* ! 1449: - * back up until we find a node that still has children ! 1450: - */ ! 1451: - pp--; ! 1452: - while (pp >= &path[1] && pp->node==NULL) pp -= 2; ! 1453: - ! 1454: - /* ! 1455: - * If we hit the beginning of the path array, there are ! 1456: - * no more leaves and hence no more paths. ! 1457: - */ ! 1458: - if (pp < &path[1]) { ! 1459: - /* reset path_length */ ! 1460: - path_length = 0; ! 1461: - return(0); ! 1462: - } ! 1463: - ! 1464: - /* ! 1465: - * append the new leftmost branch onto the rest of ! 1466: - * the path component list. ! 1467: - */ ! 1468: - pp->branch++; ! 1469: - np = pp->node; ! 1470: - pp->node = np->siblings; ! 1471: - path_length = pp-path+1; ! 1472: - path_setup(np); ! 1473: - return(1); ! 1474: -} ! 1475: - ! 1476: -/* ! 1477: - * Get the next component in the path component list. ! 1478: - * When the end of a path is reached, NULL is returned and ! 1479: - * the next call will retrieve the first component of the next path. ! 1480: - * EOF is returned if there are no more paths. ! 1481: - * A return value of 1 indicates that the value returned in mi is ! 1482: - * valid. ! 1483: - */ ! 1484: -int ! 1485: -path_getsym(mi) ! 1486: - register struct machine_input *mi; ! 1487: -{ ! 1488: - if(path_ptr > &path[path_length]) { ! 1489: - /* ! 1490: - * When the end of that path is passed, generate the ! 1491: - * next path. ! 1492: - */ ! 1493: - if(!path_build()) ! 1494: - return(EOF); ! 1495: - path_ptr = path; ! 1496: - } ! 1497: - if (path_ptr == &path[path_length]) { ! 1498: - /* ! 1499: - * Path_ptr just encountered the end of ! 1500: - * the path, return a marker value ! 1501: - * to notify caller. ! 1502: - */ ! 1503: - mi->value = 0; ! 1504: - path_ptr++; ! 1505: - return(NULL); ! 1506: - } else if (path_ptr->tag != P_BRANCH) { ! 1507: - /* ! 1508: - * Translate the right machine input value ! 1509: - */ ! 1510: - mi->sym = (path_ptr->node)->sym; ! 1511: - switch((mi->sym)->attr) { ! 1512: - ! 1513: - case A_NODE: ! 1514: - mi->value = MV_NODE((mi->sym)->unique); ! 1515: - break; ! 1516: - ! 1517: - case A_LABEL: ! 1518: - mi->value = MV_LABEL((mi->sym)->unique); ! 1519: - break; ! 1520: - ! 1521: - default: ! 1522: - assert(0); ! 1523: - } ! 1524: - } else { ! 1525: - mi->value = MV_BRANCH(path_ptr->branch); ! 1526: - } ! 1527: - path_ptr++; ! 1528: - return(1); ! 1529: -} ! 1530: - ! 1531: -/* ! 1532: - * Prints out path for debugging ! 1533: - */ ! 1534: -void ! 1535: -prpath() ! 1536: -{ ! 1537: - register int i; ! 1538: - for(i=0; i < path_length; i++) { ! 1539: - struct path *pp = &path[i]; ! 1540: - if (pp->tag==P_NODE) { ! 1541: - struct node *np = pp->node; ! 1542: - printf("[%s]", (np->sym)->name); ! 1543: - } else { ! 1544: - assert (pp->tag == P_BRANCH); ! 1545: - printf("%d", pp->branch); ! 1546: - } ! 1547: - } ! 1548: - putchar('\n'); ! 1549: - ! 1550: -} ! 1551: //GO.SYSIN DD path.c ! 1552: echo rawwalker.c1 1>&2 ! 1553: sed 's/.//' >rawwalker.c1 <<'//GO.SYSIN DD rawwalker.c1' ! 1554: -/* ! 1555: - * See Aho, Corasick Comm ACM 18:6, and Hoffman and O'Donell JACM 29:1 ! 1556: - * for detail of the matching algorithm ! 1557: - */ ! 1558: - ! 1559: -/* turn this flag on if your machine has a fast byte string zero operation */ ! 1560: -/*#define BZERO 1*/ ! 1561: -int mtDebug = 0; ! 1562: -int treedebug = 0; ! 1563: -extern int _machstep(); ! 1564: -extern short int mtStart; ! 1565: -extern short int mtTable[], mtAccept[], mtMap[], mtPaths[], mtPathStart[]; ! 1566: -#ifdef LINE_XREF ! 1567: - extern short int mtLine[]; ! 1568: -#endif ! 1569: -extern NODEPTR mtGetNodes(), mtAction(); ! 1570: -extern skeleton *_allocskel(); ! 1571: -extern __match *_allocmatch(); ! 1572: -extern __partial *_allocpartial(); ! 1573: - ! 1574: -#define MPBLOCKSIZ 3000 ! 1575: -__match *_mpblock[MPBLOCKSIZ], **_mpbtop; ! 1576: - ! 1577: -/* ! 1578: - * See sym.h in the preprocessor for details ! 1579: - * Basically used to support eh $%n$ construct. ! 1580: - */ ! 1581: -__match ** ! 1582: -_getleaves (mp, skp) ! 1583: - register __match *mp; register skeleton *skp; ! 1584: -{ ! 1585: - skeleton *stack[MAXDEPTH]; ! 1586: - skeleton **stp = stack; ! 1587: - register short int *sip = &mtPaths[mtPathStart[mp->tree]]; ! 1588: - register __match **mmp = _mpbtop; ! 1589: - __match **mmp2 = mmp; ! 1590: - if((_mpbtop += *sip++ + 1) > &_mpblock[MPBLOCKSIZ]) { ! 1591: - printf ("ich: %d\n", _mpbtop-_mpblock); ! 1592: - assert(0); ! 1593: - } ! 1594: - ! 1595: - for(;;) ! 1596: - switch(*sip++) { ! 1597: - case ePUSH: ! 1598: - *stp++ = skp; ! 1599: - skp = skp->leftchild; ! 1600: - break; ! 1601: - ! 1602: - case eNEXT: ! 1603: - skp = skp->sibling; ! 1604: - break; ! 1605: - ! 1606: - case eEVAL: ! 1607: - if ((mp = skp->succ[M_DETAG(*sip++)])==NULL) abort(); ! 1608: - *mmp++ = mp; ! 1609: - break; ! 1610: - ! 1611: - case ePOP: ! 1612: - skp = *--stp; ! 1613: - break; ! 1614: - ! 1615: - case eSTOP: ! 1616: - *mmp = NULL; ! 1617: - return (mmp2); ! 1618: - } ! 1619: -} ! 1620: - ! 1621: -_evalleaves (mpp) ! 1622: - register __match **mpp; ! 1623: -{ ! 1624: - for (; *mpp!=NULL; mpp++) { ! 1625: - register __match *mp = *mpp; ! 1626: - _do (mp->skel, mp, 1); ! 1627: - } ! 1628: -} ! 1629: - ! 1630: - ! 1631: -_do(sp, winner, evalall) ! 1632: - skeleton *sp; register __match *winner; int evalall; ! 1633: -{ ! 1634: - register __match **mpp; ! 1635: - register skeleton *skel = winner->skel; ! 1636: - if(winner==NULL) { ! 1637: - _prskel(sp, 0); ! 1638: - puts ("no winner"); ! 1639: - return; ! 1640: - } ! 1641: - if(winner->mode==xDEFER || (evalall && winner->mode!=xTOPDOWN)) ! 1642: - REORDER (winner->lleaves); ! 1643: - mtSetNodes (skel->parent, skel->nson, ! 1644: - skel->root=mtAction (winner->tree, winner->lleaves, sp)); ! 1645: -} ! 1646: - ! 1647: -skeleton * ! 1648: -_walk(sp, ostate) ! 1649: - register skeleton *sp; ! 1650: - int ostate; ! 1651: -{ ! 1652: - int state, nstate, nson; ! 1653: - register __partial *pp; ! 1654: - register __match *mp, *mp2; ! 1655: - register skeleton *nsp, *lastchild = NULL; ! 1656: - NODEPTR son, root; ! 1657: - ! 1658: - root = sp->root; ! 1659: - nson = 1; sp->mincost = INFINITY; ! 1660: - state = _machstep (ostate, root, mtValue(root)); ! 1661: - ! 1662: - while((son = mtGetNodes(root, nson))!=NULL) { ! 1663: - nstate = _machstep (state, NULL, MV_BRANCH(nson)); ! 1664: - nsp = _allocskel(); ! 1665: - nsp->root = son; ! 1666: - nsp->parent = root; ! 1667: - nsp->nson = nson; ! 1668: - _walk(nsp, nstate); ! 1669: - if(COSTLESS(nsp->mincost, INFINITY)) { ! 1670: - assert (nsp->winner->mode==xREWRITE); ! 1671: - if (mtDebug || treedebug) { ! 1672: - printf ("rewrite\n"); ! 1673: - _prskel (nsp, 0); ! 1674: - } ! 1675: - _do(nsp, nsp->winner, 0); ! 1676: - _freeskel(nsp); ! 1677: - continue; ! 1678: - } ! 1679: - _merge (sp, nsp); ! 1680: - if (lastchild==NULL) sp->leftchild = nsp; ! 1681: - else lastchild->sibling = nsp; ! 1682: - lastchild = nsp; ! 1683: - nson++; ! 1684: - } ! 1685: - ! 1686: - for (pp = sp->partial; pp < &sp->partial[sp->treecnt]; pp++) ! 1687: - if (pp->bits&01==1) { ! 1688: - mp = _allocmatch(); ! 1689: - mp->tree = pp->treeno; ! 1690: - _addmatches (ostate, sp, mp); ! 1691: - } ! 1692: - if(son==NULL && nson==1) ! 1693: - _closure (state, ostate, sp); ! 1694: - ! 1695: - sp->rightchild = lastchild; ! 1696: - if (root==NULL) { ! 1697: - COST c; __match *win; int i; nsp = sp->leftchild; ! 1698: - c = INFINITY; ! 1699: - win = NULL; ! 1700: - for (i = 0; i < MAXLABELS; i++) { ! 1701: - mp = nsp->succ[i]; ! 1702: - if (mp!=NULL && COSTLESS (mp->cost, c)) ! 1703: - { c = mp->cost; win = mp; } ! 1704: - } ! 1705: - if (mtDebug || treedebug) ! 1706: - _prskel (nsp, 0); ! 1707: - _do (nsp, win, 0); ! 1708: - } ! 1709: - if (mtDebug) ! 1710: - _prskel (sp, 0); ! 1711: - return(sp); ! 1712: -} ! 1713: - ! 1714: -static short int _nodetab[MAXNDVAL], _labeltab[MAXLABELS]; ! 1715: - ! 1716: -/* ! 1717: - * Convert the start state which has a large branching factor into ! 1718: - * a index table. This must be called before the matcher is used. ! 1719: - */ ! 1720: -_matchinit() ! 1721: -{ ! 1722: - short int *sp; ! 1723: - struct pair { short int val, where } *pp; ! 1724: - for (sp=_nodetab; sp < &_nodetab[MAXNDVAL]; sp++) *sp = HANG; ! 1725: - for (sp=_labeltab; sp < &_labeltab[MAXLABELS]; sp++) *sp = HANG; ! 1726: - sp = &mtTable[mtStart]; ! 1727: - assert (*sp==TABLE); ! 1728: - for (pp = (struct pair *) ++sp; pp->val!=EOF; pp++) { ! 1729: - if (MI_NODE(pp->val)) ! 1730: - _nodetab[M_DETAG(pp->val)] = pp->where; ! 1731: - else if (MI_LABEL(pp->val)) ! 1732: - _labeltab[M_DETAG(pp->val)] = pp->where; ! 1733: - } ! 1734: -} ! 1735: - ! 1736: -int ! 1737: -_machstep(state, root, input) ! 1738: - short int state, input; ! 1739: - NODEPTR root; ! 1740: -{ ! 1741: - register short int *stp = &mtTable[state]; ! 1742: - int start = 0; ! 1743: - if (state==HANG) ! 1744: - return (input==(MV_BRANCH(1)) ? mtStart : HANG); ! 1745: -rescan: ! 1746: - if (stp==&mtTable[mtStart]) { ! 1747: - if (MI_NODE(input)) return(_nodetab[M_DETAG(input)]); ! 1748: - if (MI_LABEL(input)) return(_labeltab[M_DETAG(input)]); ! 1749: - } ! 1750: - ! 1751: - for(;;) { ! 1752: - if(*stp==ACCEPT) stp += 2; ! 1753: - ! 1754: - if(*stp==TABLE) { ! 1755: - stp++; ! 1756: - while(*stp!=EOT) { ! 1757: - if(input==*stp) { ! 1758: - return(*++stp); ! 1759: - } ! 1760: - stp += 2; ! 1761: - } ! 1762: - stp++; ! 1763: - } ! 1764: - if(*stp!=FAIL) { ! 1765: - if (start) return (HANG); ! 1766: - else { stp = &mtTable[mtStart]; start = 1; goto rescan;} ! 1767: - } else { ! 1768: - stp++; ! 1769: - stp = &mtTable[*stp]; ! 1770: - goto rescan; ! 1771: - } ! 1772: - } ! 1773: -} ! 1774: - ! 1775: -_addmatches(ostate, sp, np) ! 1776: - int ostate; ! 1777: - register skeleton *sp; ! 1778: - register __match *np; ! 1779: -{ ! 1780: - int label; ! 1781: - int state; ! 1782: - register __match *mp; ! 1783: - ! 1784: - label = mtMap[np->tree]; ! 1785: - ! 1786: - /* ! 1787: - * this is a very poor substitute for good design of the DFA. ! 1788: - * What we need is a special case that allows any label to be accepted ! 1789: - * by the start state but we don't want the start state to recognize ! 1790: - * them after a failure. ! 1791: - */ ! 1792: - state = _machstep(ostate, NULL, MV_LABEL(label)); ! 1793: - if (ostate!=mtStart && state==HANG) { ! 1794: - _freematch(np); ! 1795: - return; ! 1796: - } ! 1797: - ! 1798: - np->lleaves = _getleaves (np, sp); ! 1799: - np->skel = sp; ! 1800: - if((np->mode = mtEvalCost(np, np->lleaves, sp))==xABORT) ! 1801: - { ! 1802: - _freematch(np); ! 1803: - return; ! 1804: - } ! 1805: - ! 1806: -/* ! 1807: - if(np->mode==xREWRITE && COSTLESS(np->cost, sp->mincost)) { ! 1808: - sp->mincost = np->cost; ! 1809: - sp->winner = np; ! 1810: - } ! 1811: -*/ ! 1812: - if ((mp = sp->succ[label])!=NULL) { ! 1813: - if (!COSTLESS (np->cost, mp->cost)) ! 1814: - { _freematch(np); return; } ! 1815: - else _freematch(mp); ! 1816: - } ! 1817: - if(COSTLESS(np->cost,sp->mincost)) { ! 1818: - if(np->mode==xREWRITE) { ! 1819: - sp->mincost = np->cost; sp->winner = np; } ! 1820: - else { sp->mincost = INFINITY; sp->winner = NULL; } ! 1821: - } ! 1822: - sp->succ[label] = np; ! 1823: - _closure(state, ostate, sp); ! 1824: -} ! 1825: - ! 1826: -_closure(state, ostate, skp) ! 1827: - int state, ostate; ! 1828: - skeleton *skp; ! 1829: -{ ! 1830: - register struct ap { short int tree, depth; } *ap; ! 1831: - short int *sp = &mtTable[state]; ! 1832: - register __match *mp; ! 1833: - ! 1834: - if(state==HANG || *sp!=ACCEPT) return(NULL); ! 1835: - ! 1836: - for(ap = (struct ap *) &mtAccept[*++sp]; ap->tree!=-1; ap++) ! 1837: - if (ap->depth==0) { ! 1838: - mp = _allocmatch(); ! 1839: - mp->tree = ap->tree; ! 1840: - _addmatches (ostate, skp, mp); ! 1841: - } else { ! 1842: - register __partial *pp, *lim = &skp->partial[skp->treecnt]; ! 1843: - for(pp=skp->partial; pp < lim; pp++) ! 1844: - if(pp->treeno==ap->tree) ! 1845: - break; ! 1846: - if(pp==lim) { ! 1847: - skp->treecnt++; ! 1848: - pp->treeno = ap->tree; ! 1849: - pp->bits = (1<<(ap->depth)); ! 1850: - } else pp->bits |= (1<<(ap->depth)); ! 1851: - } ! 1852: -} ! 1853: - ! 1854: -_merge (old, new) ! 1855: - skeleton *old, *new; ! 1856: -{ ! 1857: - register __partial *op = old->partial, *np = new->partial; ! 1858: - int nson = new->nson; ! 1859: - register __partial *lim = np + new->treecnt; ! 1860: - if (nson==1) { ! 1861: - old->treecnt = new->treecnt; ! 1862: - for(; np < lim; op++, np++) { ! 1863: - op->treeno = np->treeno; ! 1864: - op->bits = np->bits/2; ! 1865: - } ! 1866: - } else { ! 1867: - __partial *newer = _allocpartial(); ! 1868: - register __partial *newerp = newer; ! 1869: - register int cnt; ! 1870: - lim = op+old->treecnt; ! 1871: - for(cnt=new->treecnt; cnt-- ; np++) { ! 1872: - for(op = old->partial; op < lim; op++) ! 1873: - if (op->treeno == np->treeno) { ! 1874: - newerp->treeno = op->treeno; ! 1875: - newerp++->bits = op->bits & (np->bits/2); ! 1876: - break; ! 1877: - } ! 1878: - } ! 1879: - _freepartial(old->partial); ! 1880: - old->partial = newer; ! 1881: - old->treecnt = newerp-newer; ! 1882: - } ! 1883: -} ! 1884: - ! 1885: -/* Save and Allocate Matches */ ! 1886: -#define BLKF 100 ! 1887: -__match *freep = NULL; ! 1888: -static int _count = 0; ! 1889: -static __match *_blockp = NULL; ! 1890: -#ifdef CHECKMEM ! 1891: -int x_matches, f_matches; ! 1892: -#endif ! 1893: - ! 1894: -__match * ! 1895: -_allocmatch() ! 1896: -{ ! 1897: - __match *mp; ! 1898: - ! 1899: - if(freep!=NULL) { ! 1900: - mp = freep; ! 1901: - freep = ((__match *)((struct freeb *) freep)->next); ! 1902: -#ifdef CHECKMEM ! 1903: - f_matches--; ! 1904: -#endif ! 1905: - } else { ! 1906: - if(_count==0) { ! 1907: - _blockp = (__match *) malloc (BLKF*sizeof (__match)); ! 1908: - _count = BLKF; ! 1909: -#ifdef CHECKMEM ! 1910: - x_matches += BLKF; ! 1911: -#endif ! 1912: - } ! 1913: - mp = _blockp++; ! 1914: - _count--; ! 1915: - } ! 1916: - return(mp); ! 1917: -} ! 1918: - ! 1919: -_freematch(mp) ! 1920: - __match *mp; ! 1921: -{ ! 1922: - ((struct freeb *) mp)->next = (struct freeb *) freep; ! 1923: - freep = mp; ! 1924: -#ifdef CHECKMEM ! 1925: - f_matches++; ! 1926: -#endif ! 1927: -} ! 1928: - ! 1929: -static __partial *pfreep = NULL; ! 1930: -static int pcount = 0; ! 1931: -static __partial *pblock = NULL; ! 1932: -#ifdef CHECKMEM ! 1933: -static int x_partials, f_partials; ! 1934: -#endif ! 1935: - ! 1936: -__partial * ! 1937: -_allocpartial() ! 1938: -{ ! 1939: - __partial *pp; ! 1940: - if (pfreep!=NULL) { ! 1941: - pp = pfreep; ! 1942: - pfreep = *(__partial **) pp; ! 1943: -#ifdef CHECKMEM ! 1944: - f_partials--; ! 1945: -#endif ! 1946: - } else { ! 1947: - if (pcount==0) { ! 1948: - pblock=(__partial *)malloc(BLKF*MAXTREES*sizeof(__partial)); ! 1949: - pcount = BLKF; ! 1950: -#ifdef CHECKMEM ! 1951: - x_partials += BLKF; ! 1952: -#endif ! 1953: - } ! 1954: - pp = pblock; ! 1955: - pblock += MAXTREES; ! 1956: - pcount--; ! 1957: - } ! 1958: - return(pp); ! 1959: -} ! 1960: - ! 1961: -_freepartial(pp) ! 1962: - __partial *pp; ! 1963: -{ ! 1964: - * (__partial **)pp = pfreep; ! 1965: - pfreep = pp; ! 1966: -#ifdef CHECKMEM ! 1967: - f_partials++; ! 1968: -#endif ! 1969: -} ! 1970: - ! 1971: - ! 1972: -/* storage management */ ! 1973: -static skeleton *sfreep = NULL; ! 1974: -static int scount = 0; ! 1975: -static skeleton * sblock = NULL; ! 1976: - ! 1977: -skeleton * ! 1978: -_allocskel() ! 1979: -{ ! 1980: - skeleton *sp; ! 1981: - int i; ! 1982: - if(sfreep!=NULL) { ! 1983: - sp = sfreep; ! 1984: - sfreep = sp->sibling; ! 1985: - } else { ! 1986: - if(scount==0) { ! 1987: - sblock = (skeleton *) malloc (BLKF * sizeof (skeleton)); ! 1988: - scount = BLKF; ! 1989: - } ! 1990: - sp = sblock++; ! 1991: - scount--; ! 1992: - } ! 1993: - sp->sibling = NULL; sp->leftchild = NULL; ! 1994: - for (i=0; i < MAXLABELS; sp->succ[i++] = NULL); ! 1995: - sp->treecnt = 0; ! 1996: - sp->partial = _allocpartial(); ! 1997: - return(sp); ! 1998: -} ! 1999: - ! 2000: -_freeskel(sp) ! 2001: - skeleton *sp; ! 2002: -{ ! 2003: - int i; ! 2004: - __match *mp; ! 2005: - if(sp==NULL) ! 2006: - return; ! 2007: - if(sp->leftchild) ! 2008: - _freeskel(sp->leftchild); ! 2009: - if(sp->sibling) ! 2010: - _freeskel(sp->sibling); ! 2011: - _freepartial (sp->partial); ! 2012: - for (i=0; i < MAXLABELS; i++) ! 2013: - if ((mp = sp->succ[i])!=NULL) _freematch (mp); ! 2014: - sp->sibling = sfreep; ! 2015: - sfreep = sp; ! 2016: -} ! 2017: - ! 2018: -_match() ! 2019: -{ ! 2020: - skeleton *sp; ! 2021: - sp = _allocskel(); ! 2022: - sp->root = NULL; ! 2023: - _mpbtop = _mpblock; ! 2024: - _freeskel(_walk(sp, HANG)); ! 2025: -#ifdef CHECKMEM ! 2026: - if(f_matches+_count!=x_matches) { ! 2027: - printf(";#m %d %d %d\n", f_matches, _count, x_matches); ! 2028: - assert(0); ! 2029: - } ! 2030: - if(f_partials+pcount!=x_partials) { ! 2031: - printf(";#p %d %d %d\n", f_partials, pcount, x_partials); ! 2032: - assert(0); ! 2033: - } ! 2034: -#endif ! 2035: -} ! 2036: - ! 2037: -NODEPTR ! 2038: -_mtG(root,i) ! 2039: - NODEPTR root; ! 2040: - int i; ! 2041: -{ ! 2042: - int *p = &i; ! 2043: - while(*p!=-1) ! 2044: - root = mtGetNodes(root, *p++); ! 2045: - return(root); ! 2046: -} ! 2047: - ! 2048: -/* diagnostic routines */ ! 2049: - ! 2050: -_prskel (skp, lvl) ! 2051: - skeleton *skp; int lvl; ! 2052: -{ ! 2053: - int i; __match *mp; ! 2054: - __partial *pp; ! 2055: - if(skp==NULL) return; ! 2056: - for (i = lvl; i > 0; i--) { putchar (' '); putchar (' '); } ! 2057: - printf ("###\n"); ! 2058: - for (i = lvl; i > 0; i--) { putchar (' '); putchar (' '); } ! 2059: - for (i = 0; i < MAXLABELS; i++) ! 2060: - if ((mp=skp->succ[i])!=NULL) ! 2061: -#ifdef LINE_XREF ! 2062: - printf ("[%d<%d> %d]", mp->tree, ! 2063: - mtLine[mp->tree], mp->cost); ! 2064: -#else ! 2065: - printf ("[%d %d]", mp->tree, mp->cost); ! 2066: -#endif ! 2067: - putchar('\n'); ! 2068: - for (i = lvl; i > 0; i--) { putchar (' '); putchar (' '); } ! 2069: - for (i = 0, pp=skp->partial; i < skp->treecnt; i++, pp++) ! 2070: -#ifdef LINE_XREF ! 2071: - printf("(%d<%d> %x)", pp->treeno, mtLine[pp->treeno], ! 2072: - pp->bits); ! 2073: -#else ! 2074: - printf ("(%d %x)", pp->treeno, pp->bits); ! 2075: -#endif ! 2076: - putchar('\n'); ! 2077: - fflush(stdout); ! 2078: - _prskel (skp->leftchild, lvl+2); ! 2079: - _prskel (skp->sibling, lvl); ! 2080: -} ! 2081: //GO.SYSIN DD rawwalker.c1 ! 2082: echo rawwalker.ex 1>&2 ! 2083: sed 's/.//' >rawwalker.ex <<'//GO.SYSIN DD rawwalker.ex' ! 2084: -/* ! 2085: - * See Aho, Corasick Comm ACM 18:6, and Hoffman and O'Donell JACM 29:1 ! 2086: - * for detail of the matching algorithm ! 2087: - */ ! 2088: - ! 2089: -/* turn this flag on if your machine has a fast byte string zero operation */ ! 2090: -/*#define BZERO 1*/ ! 2091: -int mtDebug = 0; ! 2092: -int treedebug = 0; ! 2093: -extern int _machstep(); ! 2094: -extern short int mtStart; ! 2095: -extern short int mtTable[], mtAccept[], mtMap[], mtPaths[], mtPathStart[]; ! 2096: -#ifdef LINE_XREF ! 2097: - extern short int mtLine[]; ! 2098: -#endif ! 2099: -extern NODEPTR mtGetNodes(), mtAction(); ! 2100: -extern skeleton *_allocskel(); ! 2101: -extern __match *_allocmatch(); ! 2102: -extern __partial *_allocpartial(); ! 2103: - ! 2104: -#define MPBLOCKSIZ 3000 ! 2105: -__match *_mpblock[MPBLOCKSIZ], **_mpbtop; ! 2106: - ! 2107: -/* ! 2108: - * See sym.h in the preprocessor for details ! 2109: - * Basically used to support eh $%n$ construct. ! 2110: - */ ! 2111: -__match ** ! 2112: -_getleaves (mp, skp) ! 2113: - register __match *mp; register skeleton *skp; ! 2114: -{ ! 2115: - skeleton *stack[MAXDEPTH]; ! 2116: - skeleton **stp = stack; ! 2117: - register short int *sip = &mtPaths[mtPathStart[mp->tree]]; ! 2118: - register __match **mmp = _mpbtop; ! 2119: - __match **mmp2 = mmp; ! 2120: - if((_mpbtop += *sip++ + 1) > &_mpblock[MPBLOCKSIZ]) { ! 2121: - printf ("ich: %d\n", _mpbtop-_mpblock); ! 2122: - assert(0); ! 2123: - } ! 2124: - ! 2125: - for(;;) ! 2126: - switch(*sip++) { ! 2127: - case ePUSH: ! 2128: - *stp++ = skp; ! 2129: - skp = skp->leftchild; ! 2130: - break; ! 2131: - ! 2132: - case eNEXT: ! 2133: - skp = skp->sibling; ! 2134: - break; ! 2135: - ! 2136: - case eEVAL: ! 2137: - if ((mp = skp->succ[M_DETAG(*sip++)])==NULL) abort(); ! 2138: - *mmp++ = mp; ! 2139: - break; ! 2140: - ! 2141: - case ePOP: ! 2142: - skp = *--stp; ! 2143: - break; ! 2144: - ! 2145: - case eSTOP: ! 2146: - *mmp = NULL; ! 2147: - return (mmp2); ! 2148: - } ! 2149: -} ! 2150: - ! 2151: -_evalleaves (mpp) ! 2152: - register __match **mpp; ! 2153: -{ ! 2154: - for (; *mpp!=NULL; mpp++) { ! 2155: - register __match *mp = *mpp; ! 2156: - _do (mp->skel, mp, 1); ! 2157: - } ! 2158: -} ! 2159: - ! 2160: - ! 2161: -_do(sp, winner, evalall) ! 2162: - skeleton *sp; register __match *winner; int evalall; ! 2163: -{ ! 2164: - register __match **mpp; ! 2165: - register skeleton *skel = winner->skel; ! 2166: - if(winner==NULL) { ! 2167: - _prskel(sp, 0); ! 2168: - puts ("no winner"); ! 2169: - return; ! 2170: - } ! 2171: - if(winner->mode==xDEFER || (evalall && winner->mode!=xTOPDOWN)) ! 2172: - REORDER (winner->lleaves); ! 2173: - mtSetNodes (skel->parent, skel->nson, ! 2174: - skel->root=mtAction (winner->tree, winner->lleaves, sp)); ! 2175: -} ! 2176: - ! 2177: -skeleton * ! 2178: -_walk(sp, ostate) ! 2179: - register skeleton *sp; ! 2180: - int ostate; ! 2181: -{ ! 2182: - int state, nstate, nson; ! 2183: - register __partial *pp; ! 2184: - register __match *mp, *mp2; ! 2185: - register skeleton *nsp, *lastchild = NULL; ! 2186: - NODEPTR son, root; ! 2187: - ! 2188: - root = sp->root; ! 2189: - nson = 1; sp->mincost = INFINITY; ! 2190: - state = _machstep (ostate, root, mtValue(root)); ! 2191: - ! 2192: - while((son = mtGetNodes(root, nson))!=NULL) { ! 2193: - nstate = _machstep (state, NULL, MV_BRANCH(nson)); ! 2194: - nsp = _allocskel(); ! 2195: - nsp->root = son; ! 2196: - nsp->parent = root; ! 2197: - nsp->nson = nson; ! 2198: - _walk(nsp, nstate); ! 2199: - if(COSTLESS(nsp->mincost, INFINITY)) { ! 2200: - assert (nsp->winner->mode==xREWRITE); ! 2201: - if (mtDebug || treedebug) { ! 2202: - printf ("rewrite\n"); ! 2203: - _prskel (nsp, 0); ! 2204: - } ! 2205: - _do(nsp, nsp->winner, 0); ! 2206: - _freeskel(nsp); ! 2207: - continue; ! 2208: - } ! 2209: - _merge (sp, nsp); ! 2210: - if (lastchild==NULL) sp->leftchild = nsp; ! 2211: - else lastchild->sibling = nsp; ! 2212: - lastchild = nsp; ! 2213: - nson++; ! 2214: - } ! 2215: - ! 2216: - for (pp = sp->partial; pp < &sp->partial[sp->treecnt]; pp++) ! 2217: - if (pp->bits&01==1) { ! 2218: - mp = _allocmatch(); ! 2219: - mp->tree = pp->treeno; ! 2220: - _addmatches (ostate, sp, mp); ! 2221: - } ! 2222: - if(son==NULL && nson==1) ! 2223: - _closure (state, ostate, sp); ! 2224: - ! 2225: - sp->rightchild = lastchild; ! 2226: - if (root==NULL) { ! 2227: - COST c; __match *win; int i; nsp = sp->leftchild; ! 2228: - c = INFINITY; ! 2229: - win = NULL; ! 2230: - for (i = 0; i < MAXLABELS; i++) { ! 2231: - mp = nsp->succ[i]; ! 2232: - if (mp!=NULL && COSTLESS (mp->cost, c)) ! 2233: - { c = mp->cost; win = mp; } ! 2234: - } ! 2235: - if (mtDebug || treedebug) ! 2236: - _prskel (nsp, 0); ! 2237: - _do (nsp, win, 0); ! 2238: - } ! 2239: - if (mtDebug) ! 2240: - _prskel (sp, 0); ! 2241: - return(sp); ! 2242: -} ! 2243: - ! 2244: -static short int _nodetab[MAXNDVAL], _labeltab[MAXLABELS]; ! 2245: - ! 2246: -/* ! 2247: - * Convert the start state which has a large branching factor into ! 2248: - * a index table. This must be called before the matcher is used. ! 2249: - */ ! 2250: -_matchinit() ! 2251: -{ ! 2252: - short int *sp; ! 2253: - struct pair { short int val, where } *pp; ! 2254: - for (sp=_nodetab; sp < &_nodetab[MAXNDVAL]; sp++) *sp = HANG; ! 2255: - for (sp=_labeltab; sp < &_labeltab[MAXLABELS]; sp++) *sp = HANG; ! 2256: - sp = &mtTable[mtStart]; ! 2257: - assert (*sp==TABLE); ! 2258: - for (pp = (struct pair *) ++sp; pp->val!=EOF; pp++) { ! 2259: - if (MI_NODE(pp->val)) ! 2260: - _nodetab[M_DETAG(pp->val)] = pp->where; ! 2261: - else if (MI_LABEL(pp->val)) ! 2262: - _labeltab[M_DETAG(pp->val)] = pp->where; ! 2263: - } ! 2264: -} ! 2265: - ! 2266: -int ! 2267: -_machstep(state, root, input) ! 2268: - short int state, input; ! 2269: - NODEPTR root; ! 2270: -{ ! 2271: - register short int *stp = &mtTable[state]; ! 2272: - int start = 0; ! 2273: - if (state==HANG) ! 2274: - return (input==(MV_BRANCH(1)) ? mtStart : HANG); ! 2275: -rescan: ! 2276: - if (stp==&mtTable[mtStart]) { ! 2277: - if (MI_NODE(input)) return(_nodetab[M_DETAG(input)]); ! 2278: - if (MI_LABEL(input)) return(_labeltab[M_DETAG(input)]); ! 2279: - } ! 2280: - ! 2281: - for(;;) { ! 2282: - if(*stp==ACCEPT) stp += 2; ! 2283: - ! 2284: - if(*stp==TABLE) { ! 2285: - stp++; ! 2286: - while(*stp!=EOT) { ! 2287: - if(input==*stp) { ! 2288: - return(*++stp); ! 2289: - } ! 2290: - stp += 2; ! 2291: - } ! 2292: - stp++; ! 2293: - } ! 2294: - if(*stp!=FAIL) { ! 2295: - if (start) return (HANG); ! 2296: - else { stp = &mtTable[mtStart]; start = 1; goto rescan;} ! 2297: - } else { ! 2298: - stp++; ! 2299: - stp = &mtTable[*stp]; ! 2300: - goto rescan; ! 2301: - } ! 2302: - } ! 2303: -} ! 2304: - ! 2305: -_addmatches(ostate, sp, np) ! 2306: - int ostate; ! 2307: - register skeleton *sp; ! 2308: - register __match *np; ! 2309: -{ ! 2310: - int label; ! 2311: - int state, qstate; ! 2312: - register __match *mp; ! 2313: - static short int quick[128][MAXLABELS]; ! 2314: - static short int qtag[128][MAXLABELS]; ! 2315: - ! 2316: - label = mtMap[np->tree]; ! 2317: - ! 2318: - /* ! 2319: - * The following lines replace the line: ! 2320: - * ! 2321: - * state = _machstep(ostate, NULL, MV_LABEL(label)); ! 2322: - * ! 2323: - * Statistics show that a large percentage (approx 2/3) of calls to ! 2324: - * _machstep occur in this function. The lines below attempt ! 2325: - * to reduce the number of these calls by using an unsophisticated ! 2326: - * but apparently adequate caching scheme. ! 2327: - */ ! 2328: - qstate = ((ostate>>2)+2)&0177; ! 2329: - if(ostate != qtag[qstate][label]) { ! 2330: - state = _machstep(ostate, NULL, MV_LABEL(label)); ! 2331: - quick[qstate][label] = state; ! 2332: - qtag[qstate][label] = ostate; ! 2333: - } else state = quick[qstate][label]; ! 2334: - ! 2335: - /* ! 2336: - * this is a very poor substitute for good design of the DFA. ! 2337: - * What we need is a special case that allows any label to be accepted ! 2338: - * by the start state but we don't want the start state to recognize ! 2339: - * them after a failure. ! 2340: - */ ! 2341: - if (ostate!=mtStart && state==HANG) { ! 2342: - _freematch(np); ! 2343: - return; ! 2344: - } ! 2345: - ! 2346: - np->lleaves = _getleaves (np, sp); ! 2347: - np->skel = sp; ! 2348: - if((np->mode = mtEvalCost(np, np->lleaves, sp))==xABORT) ! 2349: - { ! 2350: - _freematch(np); ! 2351: - return; ! 2352: - } ! 2353: - ! 2354: - if ((mp = sp->succ[label])!=NULL) { ! 2355: - if (!COSTLESS (np->cost, mp->cost)) ! 2356: - { _freematch(np); return; } ! 2357: - else _freematch(mp); ! 2358: - } ! 2359: - if(COSTLESS(np->cost,sp->mincost)) { ! 2360: - if(np->mode==xREWRITE) { ! 2361: - sp->mincost = np->cost; sp->winner = np; } ! 2362: - else { sp->mincost = INFINITY; sp->winner = NULL; } ! 2363: - } ! 2364: - sp->succ[label] = np; ! 2365: - _closure(state, ostate, sp); ! 2366: -} ! 2367: - ! 2368: -_closure(state, ostate, skp) ! 2369: - int state, ostate; ! 2370: - skeleton *skp; ! 2371: -{ ! 2372: - register struct ap { short int tree, depth; } *ap; ! 2373: - short int *sp = &mtTable[state]; ! 2374: - register __match *mp; ! 2375: - ! 2376: - if(state==HANG || *sp!=ACCEPT) return(NULL); ! 2377: - ! 2378: - for(ap = (struct ap *) &mtAccept[*++sp]; ap->tree!=-1; ap++) ! 2379: - if (ap->depth==0) { ! 2380: - mp = _allocmatch(); ! 2381: - mp->tree = ap->tree; ! 2382: - _addmatches (ostate, skp, mp); ! 2383: - } else { ! 2384: - register __partial *pp, *lim = &skp->partial[skp->treecnt]; ! 2385: - for(pp=skp->partial; pp < lim; pp++) ! 2386: - if(pp->treeno==ap->tree) ! 2387: - break; ! 2388: - if(pp==lim) { ! 2389: - skp->treecnt++; ! 2390: - pp->treeno = ap->tree; ! 2391: - pp->bits = (1<<(ap->depth)); ! 2392: - } else pp->bits |= (1<<(ap->depth)); ! 2393: - } ! 2394: -} ! 2395: - ! 2396: -_merge (old, new) ! 2397: - skeleton *old, *new; ! 2398: -{ ! 2399: - register __partial *op = old->partial, *np = new->partial; ! 2400: - int nson = new->nson; ! 2401: - register __partial *lim = np + new->treecnt; ! 2402: - if (nson==1) { ! 2403: - old->treecnt = new->treecnt; ! 2404: - for(; np < lim; op++, np++) { ! 2405: - op->treeno = np->treeno; ! 2406: - op->bits = np->bits/2; ! 2407: - } ! 2408: - } else { ! 2409: - __partial *newer = _allocpartial(); ! 2410: - register __partial *newerp = newer; ! 2411: - register int cnt; ! 2412: - lim = op+old->treecnt; ! 2413: - for(cnt=new->treecnt; cnt-- ; np++) { ! 2414: - for(op = old->partial; op < lim; op++) ! 2415: - if (op->treeno == np->treeno) { ! 2416: - newerp->treeno = op->treeno; ! 2417: - newerp++->bits = op->bits & (np->bits/2); ! 2418: - break; ! 2419: - } ! 2420: - } ! 2421: - _freepartial(old->partial); ! 2422: - old->partial = newer; ! 2423: - old->treecnt = newerp-newer; ! 2424: - } ! 2425: -} ! 2426: - ! 2427: -/* Save and Allocate Matches */ ! 2428: -#define BLKF 100 ! 2429: -__match *freep = NULL; ! 2430: -static int _count = 0; ! 2431: -static __match *_blockp = NULL; ! 2432: -#ifdef CHECKMEM ! 2433: -int x_matches, f_matches; ! 2434: -#endif ! 2435: - ! 2436: -__match * ! 2437: -_allocmatch() ! 2438: -{ ! 2439: - __match *mp; ! 2440: - ! 2441: - if(freep!=NULL) { ! 2442: - mp = freep; ! 2443: - freep = ((__match *)((struct freeb *) freep)->next); ! 2444: -#ifdef CHECKMEM ! 2445: - f_matches--; ! 2446: -#endif ! 2447: - } else { ! 2448: - if(_count==0) { ! 2449: - _blockp = (__match *) malloc (BLKF*sizeof (__match)); ! 2450: - _count = BLKF; ! 2451: -#ifdef CHECKMEM ! 2452: - x_matches += BLKF; ! 2453: -#endif ! 2454: - } ! 2455: - mp = _blockp++; ! 2456: - _count--; ! 2457: - } ! 2458: - return(mp); ! 2459: -} ! 2460: - ! 2461: -_freematch(mp) ! 2462: - __match *mp; ! 2463: -{ ! 2464: - ((struct freeb *) mp)->next = (struct freeb *) freep; ! 2465: - freep = mp; ! 2466: -#ifdef CHECKMEM ! 2467: - f_matches++; ! 2468: -#endif ! 2469: -} ! 2470: - ! 2471: -static __partial *pfreep = NULL; ! 2472: -static int pcount = 0; ! 2473: -static __partial *pblock = NULL; ! 2474: -#ifdef CHECKMEM ! 2475: -static int x_partials, f_partials; ! 2476: -#endif ! 2477: - ! 2478: -__partial * ! 2479: -_allocpartial() ! 2480: -{ ! 2481: - __partial *pp; ! 2482: - if (pfreep!=NULL) { ! 2483: - pp = pfreep; ! 2484: - pfreep = *(__partial **) pp; ! 2485: -#ifdef CHECKMEM ! 2486: - f_partials--; ! 2487: -#endif ! 2488: - } else { ! 2489: - if (pcount==0) { ! 2490: - pblock=(__partial *)malloc(BLKF*MAXTREES*sizeof(__partial)); ! 2491: - pcount = BLKF; ! 2492: -#ifdef CHECKMEM ! 2493: - x_partials += BLKF; ! 2494: -#endif ! 2495: - } ! 2496: - pp = pblock; ! 2497: - pblock += MAXTREES; ! 2498: - pcount--; ! 2499: - } ! 2500: - return(pp); ! 2501: -} ! 2502: - ! 2503: -_freepartial(pp) ! 2504: - __partial *pp; ! 2505: -{ ! 2506: - * (__partial **)pp = pfreep; ! 2507: - pfreep = pp; ! 2508: -#ifdef CHECKMEM ! 2509: - f_partials++; ! 2510: -#endif ! 2511: -} ! 2512: - ! 2513: - ! 2514: -/* storage management */ ! 2515: -static skeleton *sfreep = NULL; ! 2516: -static int scount = 0; ! 2517: -static skeleton * sblock = NULL; ! 2518: - ! 2519: -skeleton * ! 2520: -_allocskel() ! 2521: -{ ! 2522: - skeleton *sp; ! 2523: - int i; ! 2524: - if(sfreep!=NULL) { ! 2525: - sp = sfreep; ! 2526: - sfreep = sp->sibling; ! 2527: - } else { ! 2528: - if(scount==0) { ! 2529: - sblock = (skeleton *) malloc (BLKF * sizeof (skeleton)); ! 2530: - scount = BLKF; ! 2531: - } ! 2532: - sp = sblock++; ! 2533: - scount--; ! 2534: - } ! 2535: - sp->sibling = NULL; sp->leftchild = NULL; ! 2536: - for (i=0; i < MAXLABELS; sp->succ[i++] = NULL); ! 2537: - sp->treecnt = 0; ! 2538: - sp->partial = _allocpartial(); ! 2539: - return(sp); ! 2540: -} ! 2541: - ! 2542: -_freeskel(sp) ! 2543: - skeleton *sp; ! 2544: -{ ! 2545: - int i; ! 2546: - __match *mp; ! 2547: - if(sp==NULL) ! 2548: - return; ! 2549: - if(sp->leftchild) ! 2550: - _freeskel(sp->leftchild); ! 2551: - if(sp->sibling) ! 2552: - _freeskel(sp->sibling); ! 2553: - _freepartial (sp->partial); ! 2554: - for (i=0; i < MAXLABELS; i++) ! 2555: - if ((mp = sp->succ[i])!=NULL) _freematch (mp); ! 2556: - sp->sibling = sfreep; ! 2557: - sfreep = sp; ! 2558: -} ! 2559: - ! 2560: -_match() ! 2561: -{ ! 2562: - skeleton *sp; ! 2563: - sp = _allocskel(); ! 2564: - sp->root = NULL; ! 2565: - _mpbtop = _mpblock; ! 2566: - _freeskel(_walk(sp, HANG)); ! 2567: -#ifdef CHECKMEM ! 2568: - if(f_matches+_count!=x_matches) { ! 2569: - printf(";#m %d %d %d\n", f_matches, _count, x_matches); ! 2570: - assert(0); ! 2571: - } ! 2572: - if(f_partials+pcount!=x_partials) { ! 2573: - printf(";#p %d %d %d\n", f_partials, pcount, x_partials); ! 2574: - assert(0); ! 2575: - } ! 2576: -#endif ! 2577: -} ! 2578: - ! 2579: -NODEPTR ! 2580: -_mtG(root,i) ! 2581: - NODEPTR root; ! 2582: - int i; ! 2583: -{ ! 2584: - int *p = &i; ! 2585: - while(*p!=-1) ! 2586: - root = mtGetNodes(root, *p++); ! 2587: - return(root); ! 2588: -} ! 2589: - ! 2590: -/* diagnostic routines */ ! 2591: - ! 2592: -_prskel (skp, lvl) ! 2593: - skeleton *skp; int lvl; ! 2594: -{ ! 2595: - int i; __match *mp; ! 2596: - __partial *pp; ! 2597: - if(skp==NULL) return; ! 2598: - for (i = lvl; i > 0; i--) { putchar (' '); putchar (' '); } ! 2599: - printf ("###\n"); ! 2600: - for (i = lvl; i > 0; i--) { putchar (' '); putchar (' '); } ! 2601: - for (i = 0; i < MAXLABELS; i++) ! 2602: - if ((mp=skp->succ[i])!=NULL) ! 2603: -#ifdef LINE_XREF ! 2604: - printf ("[%d<%d> %d]", mp->tree, ! 2605: - mtLine[mp->tree], mp->cost); ! 2606: -#else ! 2607: - printf ("[%d %d]", mp->tree, mp->cost); ! 2608: -#endif ! 2609: - putchar('\n'); ! 2610: - for (i = lvl; i > 0; i--) { putchar (' '); putchar (' '); } ! 2611: - for (i = 0, pp=skp->partial; i < skp->treecnt; i++, pp++) ! 2612: -#ifdef LINE_XREF ! 2613: - printf("(%d<%d> %x)", pp->treeno, mtLine[pp->treeno], ! 2614: - pp->bits); ! 2615: -#else ! 2616: - printf ("(%d %x)", pp->treeno, pp->bits); ! 2617: -#endif ! 2618: - putchar('\n'); ! 2619: - fflush(stdout); ! 2620: - _prskel (skp->leftchild, lvl+2); ! 2621: - _prskel (skp->sibling, lvl); ! 2622: -} ! 2623: //GO.SYSIN DD rawwalker.ex ! 2624: echo sym.c 1>&2 ! 2625: sed 's/.//' >sym.c <<'//GO.SYSIN DD sym.c' ! 2626: -/* ! 2627: - * Symbol manipulation routines ! 2628: - */ ! 2629: -#include "common.h" ! 2630: -#include "code.h" ! 2631: -#include "sym.h" ! 2632: -#include "machine.h" ! 2633: -#include "y.tab.h" ! 2634: -#include "mem.h" ! 2635: - ! 2636: -#define SAFE 1 /* generates code to do redundant checks */ ! 2637: -#define MAXSYMS 100 ! 2638: -#define MAX_UNIQUE 255 ! 2639: - ! 2640: -static void AppendToList(); ! 2641: -typedef ! 2642: - struct SymbolList { ! 2643: - SymbolEntry *first, *last; ! 2644: - int count; ! 2645: - } ! 2646: - SymbolList; ! 2647: - ! 2648: -/* ! 2649: - * The range of the unique numbers assigned to each type of ! 2650: - * symbol is [min,max) ! 2651: - */ ! 2652: -struct ranges { ! 2653: - int min,max; ! 2654: - int limit; ! 2655: -} uniques[] = { ! 2656: - {0, 0, MAX_UNIQUE}, /* A_UNDEFINED -- not used */ ! 2657: - {0, 0, MAX_NODE_VALUE}, /* A_NODE */ ! 2658: - {0, 0, MAX_UNIQUE}, /* A_LABEL */ ! 2659: - {0, 0, MAX_UNIQUE}, /* A_COST */ ! 2660: - {0, 0, MAX_UNIQUE}, /* A_ACTION */ ! 2661: -}; ! 2662: - ! 2663: -int treeIndex = 0; ! 2664: - ! 2665: -static SymbolList lists[] = { ! 2666: - { NULL, NULL, 0}, /* A_UNDEFINED -- never used */ ! 2667: - { NULL, NULL, 0}, /* A_NODE */ ! 2668: - { NULL, NULL, 0}, /* A_LABEL */ ! 2669: - { NULL, NULL, 0}, /* A_COST */ ! 2670: - { NULL, NULL, 0}, /* A_ACTION */ ! 2671: - { NULL, NULL, 0}, /* A_CONST */ ! 2672: -}; ! 2673: - ! 2674: -struct _mem sym_mem, lab_mem, tree_mem; ! 2675: -SymbolEntry *hash_table[HASHSIZE]; ! 2676: -SymbolEntry *startSymbol; ! 2677: - ! 2678: -static int ! 2679: -RawHash(s) ! 2680: - register char *s; ! 2681: -{ ! 2682: - register int sum = 0; ! 2683: - register int i = 0; ! 2684: - while(*s) ! 2685: - sum += (++i)*(0377&*s++); ! 2686: - return(sum); ! 2687: -} ! 2688: - ! 2689: - ! 2690: -/* ! 2691: - * Allocate a new symbol_entry structure for the given structure and ! 2692: - * return it. There is no check of whether the symbol is already defined or ! 2693: - * not. The caller is expected to fill in the uninitialized fields. ! 2694: - */ ! 2695: -SymbolEntry * ! 2696: -SymbolAllocate(s) ! 2697: - char *s; ! 2698: -{ ! 2699: - SymbolEntry *sp; ! 2700: - sp = (SymbolEntry *) mem_get(&sym_mem); ! 2701: - assert(sp!=NULL); ! 2702: - ! 2703: -#ifdef SAFE ! 2704: - assert (SymbolLookup(s) == NULL); ! 2705: -#endif ! 2706: - ! 2707: - sp->name = malloc(strlen(s)+1); ! 2708: - assert(sp->name!=NULL); ! 2709: - strcpy (sp->name, s); ! 2710: - sp->hash = RawHash(s); ! 2711: - sp->next = NULL; ! 2712: - sp->attr = A_UNDEFINED; ! 2713: - sp->unique = -1; ! 2714: - return(sp); ! 2715: -} ! 2716: - ! 2717: -void ! 2718: -SymbolFree (symp) ! 2719: - SymbolEntry *symp; ! 2720: -{ ! 2721: - assert (symp->next == NULL); ! 2722: - free(symp); ! 2723: -} ! 2724: - ! 2725: -SymbolEntry * ! 2726: -SymbolLookup(s) ! 2727: - char *s; ! 2728: -{ ! 2729: - int hash_value = RawHash(s); ! 2730: - register SymbolEntry * hp = hash_table[hash_value%HASHSIZE]; ! 2731: - ! 2732: - while(hp!=NULL) { ! 2733: - if(hp->hash == hash_value && ! 2734: - strcmp (s, hp->name)==0) break; ! 2735: - hp = hp->next; ! 2736: - } ! 2737: - return(hp); ! 2738: -} ! 2739: - ! 2740: -/* ! 2741: - * enter the symbol into the symbol table. It believes everything in the ! 2742: - * symp argument. ! 2743: - */ ! 2744: -void ! 2745: -SymbolEnter (symp, attr) ! 2746: - SymbolEntry *symp; ! 2747: - byte attr; ! 2748: -{ ! 2749: - struct symbol_entry *hp; ! 2750: - ! 2751: -#ifdef SAFE ! 2752: - assert (symp!=NULL); ! 2753: - assert (symp->hash == RawHash(symp->name)); ! 2754: - assert (symp->attr == A_UNDEFINED); ! 2755: -#endif ! 2756: - ! 2757: - hp = hash_table[symp->hash%HASHSIZE]; ! 2758: - symp->next = hp; ! 2759: - hash_table[symp->hash%HASHSIZE] = symp; ! 2760: - symp->attr = attr; ! 2761: - if (HAS_UNIQUE(attr)){ ! 2762: - struct ranges *rp = &uniques[attr]; ! 2763: - int new_unique; ! 2764: - if(symp->unique==-1) ! 2765: - symp->unique = new_unique = rp->max++; ! 2766: - else { ! 2767: - new_unique = symp->unique; ! 2768: - if(new_unique>=rp->max) ! 2769: - rp->max = new_unique+1; ! 2770: - else if(new_unique < rp->min) ! 2771: - rp->min = new_unique; ! 2772: - } ! 2773: - if(new_unique>rp->limit) ! 2774: - sem_error("number assigned to %s (%d) out of range", ! 2775: - symp->name, new_unique); ! 2776: - if(new_unique<0) ! 2777: - sem_error("number assigned to %s (%d) is negative", ! 2778: - symp->name, new_unique); ! 2779: - assert(rp->max>=rp->min); ! 2780: - } ! 2781: - if (HAS_LIST(attr)) { ! 2782: - AppendToList(&lists[attr], symp); ! 2783: - } ! 2784: -} ! 2785: - ! 2786: -static void ! 2787: -AppendToList(list, sp) ! 2788: - SymbolList *list; ! 2789: - SymbolEntry *sp; ! 2790: -{ ! 2791: - sp->link = NULL; ! 2792: - if(list->first==NULL) ! 2793: - list->first = sp; ! 2794: - else (list->last)->link = sp; ! 2795: - list->last = sp; ! 2796: - list->count++; ! 2797: -} ! 2798: - ! 2799: -SymbolCheckNodeValues() ! 2800: -{ ! 2801: - SymbolList *slist; ! 2802: - SymbolEntry **stab, **spp, *sp; ! 2803: - struct ranges *rp; ! 2804: - int i, range; ! 2805: - ! 2806: - rp = &uniques[A_NODE]; ! 2807: - slist = &lists[A_NODE]; ! 2808: - range = rp->max - rp->min + 1; ! 2809: - stab = (SymbolEntry **) malloc(range*sizeof(SymbolEntry *)); ! 2810: - ! 2811: - for(i=range, spp = stab; i-->0; spp++) *spp = NULL; ! 2812: - ! 2813: - for(sp = slist->first; sp; sp = sp->link) { ! 2814: - SymbolEntry *sp2 = stab[sp->unique]; ! 2815: - if(sp2==NULL) ! 2816: - stab[sp->unique] = sp; ! 2817: - else ! 2818: - sem_error("%s and %s have the same node value", ! 2819: - sp2->name, sp->name); ! 2820: - } ! 2821: - free(stab); ! 2822: -} ! 2823: - ! 2824: -SymbolEntry * ! 2825: -SymbolEnterKeyword(s, value) ! 2826: - char *s; ! 2827: - int value; ! 2828: -{ ! 2829: - SymbolEntry *sp = SymbolAllocate(s); ! 2830: - sp->sd.keyword = value; ! 2831: - SymbolEnter (sp, A_KEYWORD); ! 2832: - return(sp); ! 2833: -} ! 2834: - ! 2835: -void ! 2836: -SymbolInit() ! 2837: -{ ! 2838: - SymbolEntry *sp; ! 2839: - ! 2840: - mem_init(&sym_mem,sizeof(SymbolEntry)); ! 2841: - mem_init(&lab_mem,sizeof(LabelData)); ! 2842: - mem_init(&tree_mem,sizeof(struct treeassoc)); ! 2843: - SymbolEnterKeyword ("node", K_NODE); ! 2844: - SymbolEnterKeyword ("label", K_LABEL); ! 2845: - SymbolEnterKeyword ("prologue", K_PROLOGUE); ! 2846: - SymbolEnterKeyword ("const", K_CONST); ! 2847: - SymbolEnterKeyword ("insert", K_INSERT); ! 2848: - SymbolEnterKeyword ("cost", K_COST); ! 2849: - SymbolEnterKeyword ("action", K_ACTION); ! 2850: -} ! 2851: - ! 2852: -void ! 2853: -SymbolMap(f) ! 2854: - int (*f)(); ! 2855: -{ ! 2856: - SymbolEntry **spp, *sp; ! 2857: - for(spp = hash_table; spp < &hash_table[HASHSIZE]; spp++) ! 2858: - for(sp= *spp; sp!=NULL; sp = sp->next) ! 2859: - f(sp); ! 2860: -}; ! 2861: - ! 2862: -static int symcnt, labcnt, nodecnt; ! 2863: -static ! 2864: -sym_count(sp) ! 2865: - SymbolEntry *sp; ! 2866: -{ ! 2867: - symcnt++; ! 2868: - switch(sp->attr) { ! 2869: - case A_LABEL: { ! 2870: - LabelData *lp; ! 2871: - for(lp = sp->sd.lp;lp!=NULL;lp=lp->next) { ! 2872: - labcnt++; ! 2873: - nodecnt += cntnodes(lp->tree); ! 2874: - } ! 2875: - } break; ! 2876: - } ! 2877: -} ! 2878: - ! 2879: -void ! 2880: -SymbolFinish() ! 2881: -{ ! 2882: - if(DB_MEM&debug_flag) { ! 2883: - extern struct _mem node_mem; ! 2884: - int symout = mem_outstanding(&sym_mem); ! 2885: - int labout = mem_outstanding(&lab_mem); ! 2886: - int nodeout = mem_outstanding(&node_mem); ! 2887: - SymbolMap(sym_count); ! 2888: - fprintf(stderr,"symbols defined=%d out=%d\n",symcnt, symout); ! 2889: - fprintf(stderr,"labdata def=%d out=%d\n",labcnt,labout); ! 2890: - fprintf(stderr,"node def=%d out=%d\n",nodecnt,nodeout); ! 2891: - assert(symcnt==symout); ! 2892: - assert(labcnt==labout); ! 2893: - assert(nodecnt==nodeout); ! 2894: - } ! 2895: -} ! 2896: - ! 2897: -void ! 2898: -SymbolEnterList (symp, attr) ! 2899: - SymbolEntry *symp; ! 2900: - int attr; ! 2901: -{ ! 2902: - /* ! 2903: - * enter in reverse order because the list was built in reverse ! 2904: - * order by the parser ! 2905: - */ ! 2906: - ! 2907: - if(symp==NULL) ! 2908: - return; ! 2909: - SymbolEnterList(symp->next, attr); ! 2910: - if(symp->attr!=A_UNDEFINED) ! 2911: - sem_error ("multiple declaration ignored: %s", symp->name); ! 2912: - SymbolEnter (symp, attr); ! 2913: -} ! 2914: - ! 2915: -LabelData * ! 2916: -SymbolEnterTreeIntoLabel(symp, tree, costfunc, action, lineno) ! 2917: - SymbolEntry *symp, *action, *costfunc; ! 2918: - struct node *tree; ! 2919: - int lineno; ! 2920: -{ ! 2921: - LabelData *tp = (LabelData *) mem_get(&lab_mem); ! 2922: - struct treeassoc *ap; ! 2923: - ! 2924: - if (symp==&ErrorSymbol) return(NULL); ! 2925: -#ifdef SAFE ! 2926: - assert (tp!=NULL); ! 2927: - assert (symp->attr==A_LABEL); ! 2928: -#endif ! 2929: - ! 2930: - tp->tree = tree; ! 2931: - tp->treeIndex = treeIndex++; ! 2932: - tp->lineno = lineno; ! 2933: - tp->next = symp->sd.lp; ! 2934: - tp->label = symp; ! 2935: - symp->sd.lp = tp; ! 2936: - ! 2937: - if (action!=NULL) { ! 2938: - ap = (struct treeassoc *) mem_get(&tree_mem); ! 2939: - ap->tree = tp->treeIndex; ! 2940: - ap->next = action->sd.ca.assoc; ! 2941: - action->sd.ca.assoc = ap; ! 2942: - } ! 2943: - ! 2944: - if (costfunc!=NULL) { ! 2945: - ap = (struct treeassoc *) mem_get(&tree_mem); ! 2946: - ap->tree = tp->treeIndex; ! 2947: - ap->next = costfunc->sd.ca.assoc; ! 2948: - costfunc->sd.ca.assoc = ap; ! 2949: - } ! 2950: - return(tp); ! 2951: -} ! 2952: - ! 2953: -static void ! 2954: -WriteSymbols(sp, mask) ! 2955: - SymbolEntry *sp; ! 2956: - int mask; ! 2957: -{ ! 2958: - for(;sp!=NULL; sp = sp->link) ! 2959: - fprintf(symfile, "#define %s\t0%o\n", sp->name, sp->unique|mask); ! 2960: -} ! 2961: - ! 2962: -void ! 2963: -SymbolDump() ! 2964: -{ ! 2965: - WriteSymbols(lists[A_NODE].first, M_NODE); ! 2966: - WriteSymbols(lists[A_LABEL].first, 0); ! 2967: - WriteSymbols(lists[A_CONST].first, 0); ! 2968: - fprintf(symfile, "#define MAXLABELS %d\n", uniques[A_LABEL].max); ! 2969: - fprintf(symfile, "#define MAXTREES %d\n", treeIndex); ! 2970: - fprintf(symfile, "#define MAXNDVAL %d\n", uniques[A_NODE].max); ! 2971: -} ! 2972: - ! 2973: -void ! 2974: -SymbolGenerateWalkerCode() ! 2975: -{ ! 2976: - register SymbolEntry *pp; ! 2977: - int i; ! 2978: - extern int line_xref_flag; ! 2979: - struct treeassoc *tap; ! 2980: - register LabelData *lp; ! 2981: - register short int *mapTab; ! 2982: - ! 2983: - /* ! 2984: - * Write out the table of tree index to label correspondence ! 2985: - */ ! 2986: - mapTab = (short int *) malloc (treeIndex * sizeof(short int)); ! 2987: - for(pp=lists[A_LABEL].first; pp!=NULL; pp=pp->link) { ! 2988: - lp = pp->sd.lp; ! 2989: - if(lp==NULL) ! 2990: - sem_error2("%s undefined\n", pp->name); ! 2991: - for(;lp!=NULL;lp=lp->next) ! 2992: - mapTab[lp->treeIndex] = pp->unique; ! 2993: - } ! 2994: - fputs("short int mtMap[] = {\n", outfile); ! 2995: - for(i=0, oreset(); i < treeIndex;) ! 2996: - oputoct(mapTab[i++]); ! 2997: - fputs("};\n", outfile); ! 2998: - ! 2999: - /* generate tree to line index table */ ! 3000: - if(line_xref_flag) { ! 3001: - for(pp=lists[A_LABEL].first; pp!=NULL; pp=pp->link) { ! 3002: - lp = pp->sd.lp; ! 3003: - for(;lp!=NULL;lp=lp->next) ! 3004: - mapTab[lp->treeIndex] = lp->lineno; ! 3005: - } ! 3006: - fputs("short int mtLine[] = {\n", outfile); ! 3007: - for(i=0, oreset(); i<treeIndex;) ! 3008: - oputint(mapTab[i++]); ! 3009: - fputs("};\n", outfile); ! 3010: - } ! 3011: - /* ! 3012: - * Generate path table ! 3013: - */ ! 3014: - fputs ("short int mtPaths[] = {\n", outfile); ! 3015: - for(pp=lists[A_LABEL].first, oreset(); pp!=NULL; pp=pp->link) { ! 3016: - lp = pp->sd.lp; ! 3017: - if(lp==NULL) ! 3018: - sem_error2("%s undefined\n", pp->name); ! 3019: - do { ! 3020: - mapTab[lp->treeIndex] = ointcnt(); ! 3021: - oputint (lp->tree->nlleaves); ! 3022: - SymbolWritePath (lp->tree); ! 3023: - oputint (eSTOP); ! 3024: - lp = lp->next; ! 3025: - } while (lp!=NULL); ! 3026: - } ! 3027: - fputs(" };\nshort int mtPathStart[] = {\n", outfile); ! 3028: - for(i=0, oreset(); i < treeIndex;) ! 3029: - oputint (mapTab[i++]); ! 3030: - fputs("};\n", outfile); ! 3031: - ! 3032: - /* ! 3033: - * Code to perform the action of the trees ! 3034: - */ ! 3035: - fputs("NODEPTR\nmtAction (_t, _ll, _s)\n", outfile); ! 3036: - fputs("int _t; __match **_ll; skeleton *_s;\n", outfile); ! 3037: - fputs("{ NODEPTR root = _s->root;\n", outfile); ! 3038: - fputs("switch (_t) {\n", outfile); ! 3039: - for (pp=lists[A_ACTION].first; pp!=NULL; pp=pp->link) { ! 3040: - if ((tap=pp->sd.ca.assoc)==NULL) { ! 3041: - sem_error2 ("%s not used", pp->name); ! 3042: - continue; ! 3043: - } ! 3044: - for (; tap!=NULL; tap=tap->next) ! 3045: - fprintf (outfile, "case %d:", tap->tree); ! 3046: - fputs ("{\n", outfile); ! 3047: - CodeWrite (outfile, pp->sd.ca.code); ! 3048: - fputs("} break;\n", outfile); ! 3049: - } ! 3050: - fputs("} return(_s->root);}\n", outfile); ! 3051: - ! 3052: - fputs ("mtEvalCost(_m, _ll, _s)\n", outfile); ! 3053: - fputs ("__match **_ll; __match *_m; skeleton *_s;\n", outfile); ! 3054: - fputs ("{ NODEPTR root = _s->root;\n", outfile); ! 3055: - fputs ("COST cost; cost = DEFAULT_COST;\n", outfile); ! 3056: - fputs ("switch(_m->tree) {\n", outfile); ! 3057: - for(pp=lists[A_COST].first; pp!=NULL; pp=pp->link) { ! 3058: - if ((tap=pp->sd.ca.assoc)==NULL) { ! 3059: - sem_error2 ("%s not used", pp->name); ! 3060: - continue; ! 3061: - } ! 3062: - for (; tap!=NULL; tap=tap->next) ! 3063: - fprintf (outfile, "case %d:", tap->tree); ! 3064: - fputs ("{\n", outfile); ! 3065: - CodeWrite (outfile, pp->sd.ca.code); ! 3066: - fputs ("} break;\n", outfile); ! 3067: - } ! 3068: - fputs("}\n", outfile); ! 3069: - fputs("_m->cost = cost; return(xDEFER);}\n", outfile); ! 3070: - ! 3071: -} ! 3072: - ! 3073: -SymbolWritePath (root) ! 3074: - Node *root; ! 3075: -{ ! 3076: - Node *np; ! 3077: - if(root->nlleaves==0) ! 3078: - return; ! 3079: - if((root->sym)->attr==A_LABEL) { ! 3080: - oputint (eEVAL); oputoct (MV_LABEL((root->sym)->unique)); ! 3081: - return; ! 3082: - } ! 3083: - oputint (ePUSH); ! 3084: - for(np = root->children;;) { ! 3085: - if(np->nlleaves > 0) ! 3086: - SymbolWritePath (np); ! 3087: - if ((np = np->siblings) == NULL) ! 3088: - break; ! 3089: - oputint (eNEXT); ! 3090: - } ! 3091: - oputint (ePOP); ! 3092: - return; ! 3093: -} ! 3094: - ! 3095: -static int gensymndx = 0; ! 3096: - ! 3097: -char * ! 3098: -SymbolGenUnique() ! 3099: -{ ! 3100: - static char name[7]; ! 3101: - name[0] = '$'; ! 3102: - sprintf (&name[1], "%05d", gensymndx++); ! 3103: - return (name); ! 3104: -} ! 3105: //GO.SYSIN DD sym.c ! 3106: echo sym.h 1>&2 ! 3107: sed 's/.//' >sym.h <<'//GO.SYSIN DD sym.h' ! 3108: -/* symbol table definitions */ ! 3109: -extern int symbol_undefined; ! 3110: - ! 3111: -/* ! 3112: - * A LabelData structures are associated with label symbols. They ! 3113: - * indicate that a tree is labelled with the symbol ! 3114: - */ ! 3115: -typedef struct LabelData LabelData; ! 3116: - ! 3117: -struct LabelData { ! 3118: - Node *tree; ! 3119: - int treeIndex; ! 3120: - int lineno; ! 3121: - SymbolEntry *label; /* back pointer */ ! 3122: - LabelData *next; ! 3123: -}; ! 3124: - ! 3125: -struct treeassoc { ! 3126: - int tree; ! 3127: - struct treeassoc *next; ! 3128: -}; ! 3129: - ! 3130: -struct symbol_entry { ! 3131: - int hash; ! 3132: - char *name; ! 3133: - short attr; ! 3134: -# define A_UNDEFINED 0 ! 3135: -# define A_NODE 1 ! 3136: -# define A_LABEL 2 ! 3137: -# define A_COST 3 ! 3138: -# define A_ACTION 4 ! 3139: -# define MAXCHAINS A_CONST ! 3140: -# define HAS_UNIQUE(x) (x<MAXCHAINS) ! 3141: -# define A_CONST 5 ! 3142: -# define HAS_LIST(x) (x<=A_CONST) ! 3143: -# define A_ERROR 10 ! 3144: -# define A_KEYWORD 11 ! 3145: - short unique; ! 3146: - struct symbol_entry *link; ! 3147: - struct symbol_entry *next; ! 3148: - union { ! 3149: - int keyword; ! 3150: - int cvalue; /* a constant's value */ ! 3151: - int arity; /* information stored for A_NODE type */ ! 3152: - LabelData *lp; ! 3153: - struct { ! 3154: - int arity; ! 3155: - Code *code; ! 3156: - } predData; ! 3157: - struct { ! 3158: - struct treeassoc *assoc; ! 3159: - Code *code; ! 3160: - } ca; /* data for cost/action symbols */ ! 3161: - } sd; ! 3162: -}; ! 3163: - ! 3164: -extern void SymbolInit(); ! 3165: -extern void SymbolEnter(); ! 3166: -extern SymbolEntry *SymbolLookup(); ! 3167: -extern SymbolEntry *SymbolAllocate(); ! 3168: -extern void SymbolFree(); ! 3169: -extern void SymbolEnterList(); ! 3170: -extern char *SymbolGenUnique(); ! 3171: - ! 3172: -extern SymbolEntry ErrorSymbol; ! 3173: - ! 3174: -/* ! 3175: - * In order for the walker to access the labelled leaves of a pattern, ! 3176: - * a table (mistakenly) called the path table is generated (see sym.c). ! 3177: - * This table contains the following possible values: ! 3178: - * ! 3179: - * ePush follow the children link in the walker skeleton. ! 3180: - * ePop Pop up to parent. ! 3181: - * eNext follow the siblings link. ! 3182: - * eEval <arg> The current node is a labelled leaf whose label id ! 3183: - * is the integer <arg>. ! 3184: - * eStop All done. stop! ! 3185: - * ! 3186: - * The table is interpreted by the _getleaves routine in the walker. ! 3187: - */ ! 3188: -#define eSTOP 0 ! 3189: -#define ePOP -1 ! 3190: -#define eEVAL -2 ! 3191: -#define eNEXT -3 ! 3192: -#define ePUSH -4 ! 3193: //GO.SYSIN DD sym.h ! 3194: echo trees.c 1>&2 ! 3195: sed 's/.//' >trees.c <<'//GO.SYSIN DD trees.c' ! 3196: -#include "common.h" ! 3197: -#include "code.h" ! 3198: -#include "sym.h" ! 3199: -#include "mem.h" ! 3200: - ! 3201: -struct _mem node_mem; ! 3202: - ! 3203: -void ! 3204: -TreeFree(root) ! 3205: - Node *root; ! 3206: -{ ! 3207: - if(root==NULL) return; ! 3208: - TreeFree(root->children); ! 3209: - TreeFree(root->siblings); ! 3210: - free(root); ! 3211: -} ! 3212: - ! 3213: -void ! 3214: -TreePrint(tree, flag) ! 3215: - Node *tree; ! 3216: - int flag; ! 3217: -{ ! 3218: - if(tree==NULL) ! 3219: - return; ! 3220: - printf("%s", (tree->sym)->name); ! 3221: - putchar('('); ! 3222: - TreePrint(tree->children, 0); ! 3223: - putchar(')'); ! 3224: - if(tree->siblings!=NULL) { ! 3225: - putchar(','); ! 3226: - TreePrint(tree->siblings, 0); ! 3227: - } ! 3228: - if(flag) putchar('\n'); ! 3229: -} ! 3230: - ! 3231: -Node * ! 3232: -rev (sl, nl, nlleaves) ! 3233: - Node *sl, *nl; ! 3234: - int *nlleaves; ! 3235: -{ ! 3236: - Node *sl2; ! 3237: - if(sl==NULL) ! 3238: - return(nl); ! 3239: - sl2 = sl->siblings; ! 3240: - sl->siblings = nl; ! 3241: - *nlleaves += sl->nlleaves; ! 3242: - return (rev (sl2, sl, nlleaves)); ! 3243: -} ! 3244: - ! 3245: -Node * ! 3246: -TreeBuild (symp, children) ! 3247: - SymbolEntry *symp; ! 3248: - Node *children; ! 3249: -{ ! 3250: - Node *np = (struct node *) mem_get(&node_mem); ! 3251: - np->sym = symp; ! 3252: - np->nlleaves = symp->attr==A_LABEL ? 1 : 0; ! 3253: - np->children = rev (children, NULL, &np->nlleaves); ! 3254: - return(np); ! 3255: -} ! 3256: - ! 3257: -TreeInit() ! 3258: -{ ! 3259: - mem_init(&node_mem, sizeof(struct node)); ! 3260: -} ! 3261: - ! 3262: -cntnodes(np) ! 3263: - Node *np; ! 3264: -{ ! 3265: - if(np==NULL) return(0); ! 3266: - else return(1+cntnodes(np->children)+cntnodes(np->siblings)); ! 3267: -} ! 3268: //GO.SYSIN DD trees.c ! 3269: echo twig.y 1>&2 ! 3270: sed 's/.//' >twig.y <<'//GO.SYSIN DD twig.y' ! 3271: -%term ERROR ! 3272: -%{ ! 3273: -#include "common.h" ! 3274: -#include "code.h" ! 3275: -#include "sym.h" ! 3276: -#define UNDEFINED -1 ! 3277: -#define GIVENUP -2 ! 3278: - ! 3279: -int debug_flag = 0; ! 3280: -int Dflag = 0; ! 3281: -int tflag = 0; ! 3282: -int line_xref_flag = 0; ! 3283: -int ntrees = 0; ! 3284: -int nerrors = 0; ! 3285: -int fatalerrors = 0; ! 3286: -int tree_lineno; ! 3287: -FILE *outfile; ! 3288: -FILE *symfile; ! 3289: -Code *epilogue; ! 3290: - ! 3291: -SymbolEntry ErrorSymbol; ! 3292: -%} ! 3293: -%union { ! 3294: - Node *y_nodep; ! 3295: - SymbolEntry *y_symp; ! 3296: - Code *y_code; ! 3297: - int y_int; ! 3298: -} ! 3299: -%start pattern_spec ! 3300: -%term K_NODE K_LABEL K_PROLOGUE K_CONST K_INSERT ! 3301: -%term K_COST K_ACTION ! 3302: -%token <y_symp> ID ! 3303: -%token <y_int> NUMBER ! 3304: -%token <y_code> CBLOCK ! 3305: -%type <y_nodep> tree tree_list ! 3306: -%type <y_symp> id_list label assoc_list assoc assoc_list2 assoc2 ! 3307: -%type <y_symp> const_list const_def ! 3308: -%type <y_int> arity_spec constant ! 3309: -%type <y_symp> action cost ! 3310: -%% ! 3311: - ! 3312: -pattern_spec: declarations patternsOrInserts = ! 3313: - { if (nerrors==0) machine_build(); }; ! 3314: - ! 3315: -declarations: declarations decl ! 3316: - | decl; ! 3317: - ! 3318: -decl: K_NODE assoc_list ';' = { SymbolEnterList ($2, A_NODE); } ! 3319: - ! 3320: - | K_NODE assoc_list2 ';' ! 3321: - = { ! 3322: - SymbolEnterList($2, A_NODE); ! 3323: - SymbolCheckNodeValues(); ! 3324: - } ! 3325: - ! 3326: - | K_CONST const_list ';' = { SymbolEnterList ($2, A_CONST); } ! 3327: - ! 3328: - | K_LABEL id_list ';' = { SymbolEnterList ($2, A_LABEL); } ! 3329: - ! 3330: - | K_PROLOGUE CBLOCK ';' = { CodeWrite(outfile, $2); CodeFreeBlock($2); } ! 3331: - ! 3332: - | K_COST ID CBLOCK ';' ! 3333: - = { $2->sd.ca.code = $3; $2->sd.ca.assoc = NULL; ! 3334: - SymbolEnter ($2, A_COST); } ! 3335: - ! 3336: - | K_ACTION ID CBLOCK ';' ! 3337: - = { $2->sd.ca.code = $3; $2->sd.ca.assoc = NULL; ! 3338: - SymbolEnter ($2, A_ACTION); } ! 3339: - ! 3340: - | K_PROLOGUE error ';' ! 3341: - | K_ACTION error ';' ! 3342: - | K_COST error ';' ! 3343: - ; ! 3344: - ! 3345: -/* ! 3346: - * The rule id_list, assoc_list, and const_list build lists of identifiers. ! 3347: - * The field "next" is used as a link. This field is also used by the symbol ! 3348: - * table manager and thus the next field may not be used unless the identifiers ! 3349: - * have not already been defined. ! 3350: - */ ! 3351: - ! 3352: -id_list: ! 3353: - id_list ID = { ! 3354: - if(CheckIsUndefined($2)) { ! 3355: - $2->next = $1; ! 3356: - $$ = $2; ! 3357: - } else $$ = $1; ! 3358: - } ! 3359: - | ID { if(CheckIsUndefined($1)) $$ = $1; else $$ = NULL; } ! 3360: - | id_list error; ! 3361: - ! 3362: -/* ! 3363: - * Assoc_list2 allows user assignment of node values ! 3364: - */ ! 3365: -assoc_list2: ! 3366: - assoc_list2 assoc2 ! 3367: - = { ! 3368: - if($2->attr==A_ERROR) ! 3369: - $$ = $1; ! 3370: - else { $2->next = $1; $$ = $2; } ! 3371: - } ! 3372: - | assoc2 { $$ = $1->attr==A_ERROR ? NULL : $1; } ! 3373: - | assoc_list2 error; ! 3374: - ! 3375: -assoc_list: ! 3376: - assoc_list assoc = { ! 3377: - if($2->attr==A_ERROR) $$ = $1; ! 3378: - else { $2->next = $1; $$ = $2; } ! 3379: - } ! 3380: - | assoc { $$ = $1->attr==A_ERROR ? NULL : $1; } ! 3381: - | assoc_list error; ! 3382: - ! 3383: -assoc: ID arity_spec ! 3384: - = { ! 3385: - if (CheckIsUndefined($1)) { ! 3386: - $1->sd.arity = $2; $$ = $1; ! 3387: - } else $$ = &ErrorSymbol; ! 3388: - }; ! 3389: - ! 3390: -assoc2: ! 3391: - ID arity_spec '=' constant { ! 3392: - if(CheckIsUndefined($1)) { ! 3393: - $1->unique = $4; $1->sd.arity = $2; ! 3394: - $$ = $1; ! 3395: - } else $$ = &ErrorSymbol; ! 3396: - }; ! 3397: - ! 3398: -arity_spec: ! 3399: - '(' constant ')' = { $$ = $2; }; ! 3400: - | '(' '*' ')' = { $$=GIVENUP; }; ! 3401: - | = { $$ = UNDEFINED; }; ! 3402: - ! 3403: -const_list: ! 3404: - const_list const_def = { ! 3405: - if ($2->attr==A_ERROR) $$ = $1; ! 3406: - else { $2->next = $1; $$ = $2; } ! 3407: - } ! 3408: - | const_def { $$ = $1->attr==A_ERROR ? NULL : $1; } ! 3409: - | const_list error; ! 3410: - ! 3411: -const_def: ! 3412: - ID '=' constant = { ! 3413: - if(CheckIsUndefined($1)) { ! 3414: - $1->sd.cvalue = $3; $$ = $1; ! 3415: - } else $$ = &ErrorSymbol; ! 3416: - }; ! 3417: - ! 3418: -constant: ! 3419: - NUMBER ! 3420: - | ID = { ! 3421: - if(!CheckIsDefined($1)) $$ = UNDEFINED; ! 3422: - else if($1->attr!=A_CONST) { ! 3423: - sem_error("non-constant id used"); ! 3424: - $$ = -1; ! 3425: - } else $$ = $1->sd.cvalue; ! 3426: - }; ! 3427: - ! 3428: -patternsOrInserts: patternsOrInserts pattern ! 3429: - | patternsOrInserts insert ! 3430: - | insert ! 3431: - | pattern ! 3432: - ; ! 3433: - ! 3434: -insert: K_INSERT CBLOCK ';' = { epilogue = CodeAppend(epilogue, $2); } ! 3435: - | K_INSERT error ';' ! 3436: - ; ! 3437: - ! 3438: -pattern: ! 3439: - label ':' tree cost action ';' = { ! 3440: - if ($1->attr==A_ERROR) { ! 3441: - error(0, "\"label: tree\" pair ignored"); ! 3442: - TreeFree($3); ! 3443: - } else { ! 3444: - if(nerrors==0) ! 3445: - cgotofn(SymbolEnterTreeIntoLabel($1, ! 3446: - $3, $4, $5, tree_lineno)); ! 3447: - if(debug_flag&DB_TREE) ! 3448: - TreePrint($3, 1); ! 3449: - } ! 3450: - } ! 3451: - | error ';' ; ! 3452: - ! 3453: -action: '=' CBLOCK { SymbolEntry *sp = SymbolAllocate (SymbolGenUnique()); ! 3454: - sp->sd.ca.code = $2; sp->sd.ca.assoc = NULL; ! 3455: - SymbolEnter(sp, A_ACTION); $$ = sp; } ! 3456: - | '=' ID { if(CheckIsDefined($2)) { ! 3457: - if ($2->attr!=A_ACTION) { ! 3458: - sem_error ("non action id: %s", $2->name); ! 3459: - $$ = &ErrorSymbol; ! 3460: - } else $$ = $2; ! 3461: - } else $$ = &ErrorSymbol; } ! 3462: - | { $$ = NULL;}; ! 3463: - ! 3464: -cost: CBLOCK { SymbolEntry *sp = SymbolAllocate (SymbolGenUnique()); ! 3465: - sp->sd.ca.code = $1; sp->sd.ca.assoc = NULL; ! 3466: - SymbolEnter (sp, A_COST); $$ = sp; ! 3467: - } ! 3468: - | ID { if (CheckIsDefined($1)) { ! 3469: - if ($1->attr!=A_COST) { ! 3470: - sem_error ("non cost id: %s", $1->name); ! 3471: - $$ = &ErrorSymbol; ! 3472: - } else $$ = $1; ! 3473: - } else $$ = &ErrorSymbol; } ! 3474: - | { $$ = NULL; }; ! 3475: - ! 3476: -/* labels play the same role that non-terminals do in YACC */ ! 3477: -label: ID = { ! 3478: - tree_lineno = yyline; /* record line no */ ! 3479: - if(!CheckIsDefined($1)) ! 3480: - $1->attr = A_ERROR; ! 3481: - else if(!is_label($1)) { ! 3482: - sem_error("non label id: %s", $1->name); ! 3483: - $1->attr = A_ERROR; ! 3484: - } ! 3485: - $$ = $1; ! 3486: - }; ! 3487: - ! 3488: -tree: ID {CheckIsNodeOrPred($1);} '(' tree_list ')' ! 3489: - = { ! 3490: - int count; ! 3491: - Node *ap; ! 3492: - /* check the arity of the node */ ! 3493: - for(count=0, ap = $4; ap!=NULL; ap=ap->siblings) count++; ! 3494: - switch($1->attr) { ! 3495: - case A_NODE: ! 3496: - set_arity($1, &$1->sd.arity, count); ! 3497: - break; ! 3498: - } ! 3499: - ! 3500: - $$ = TreeBuild ($1, $4); ! 3501: - } ! 3502: - | ID ! 3503: - = { ! 3504: - CheckIsDefined($1); ! 3505: - switch ($1->attr) { ! 3506: - case A_NODE: ! 3507: - set_arity($1, &$1->sd.arity, 0); ! 3508: - break; ! 3509: - } ! 3510: - $$ = TreeBuild ($1, NULL); ! 3511: - }; ! 3512: - ! 3513: -tree_list: tree_list ',' tree = { ! 3514: - /* ! 3515: - * build sibling list in reverse order TreeBuild will ! 3516: - * put it right later. ! 3517: - */ ! 3518: - $3->siblings = $1; ! 3519: - $$ = $3; ! 3520: - } ! 3521: - | tree = { $1->siblings = NULL; $$ = $1; } ! 3522: - | error { $$ = NULL; }; ! 3523: - | tree_list error; ! 3524: - ! 3525: -%% ! 3526: - ! 3527: -extern char *process_suffix(); ! 3528: - ! 3529: -set_arity(symp, arityp, count) ! 3530: - SymbolEntry *symp; ! 3531: - int *arityp; ! 3532: - int count; ! 3533: -{ ! 3534: - if(*arityp!=GIVENUP) { ! 3535: - if (*arityp==UNDEFINED) ! 3536: - *arityp = count; ! 3537: - else if (*arityp!=count) { ! 3538: - sem_error("inconsistent arity for %s", symp->name); ! 3539: - *arityp = GIVENUP; ! 3540: - } ! 3541: - } ! 3542: -} ! 3543: - ! 3544: -is_node(symp) ! 3545: - SymbolEntry *symp; ! 3546: -{ return(symp->attr==A_NODE); } ! 3547: - ! 3548: -is_label(symp) ! 3549: - SymbolEntry *symp; ! 3550: -{ return(symp->attr==A_LABEL); } ! 3551: - ! 3552: -CheckIsNodeOrPred (symp) ! 3553: - SymbolEntry *symp; ! 3554: -{ ! 3555: - if (symp->attr==A_ERROR) ! 3556: - return; ! 3557: - if (symp->attr!=A_NODE) ! 3558: - sem_error ("non-node identifier %s", symp->name); ! 3559: -} ! 3560: - ! 3561: -CheckIsUndefined(symp) ! 3562: - SymbolEntry *symp; ! 3563: -{ ! 3564: - if (symp->attr==A_ERROR) ! 3565: - return(0); ! 3566: - if (symp->attr!=A_UNDEFINED) { ! 3567: - sem_error ("multiple declaration: %s", symp->name); ! 3568: - return(0); ! 3569: - } else return(1); ! 3570: -} ! 3571: - ! 3572: -CheckIsDefined(symp) ! 3573: - SymbolEntry *symp; ! 3574: -{ ! 3575: - if (symp->attr==A_ERROR) ! 3576: - return(0); ! 3577: - if (symp->attr==A_UNDEFINED) { ! 3578: - sem_error ("undefined identifier: %s", symp->name); ! 3579: - symp->attr=A_ERROR; ! 3580: - return(0); ! 3581: - } else return(1); ! 3582: -} ! 3583: - ! 3584: - ! 3585: - ! 3586: -/*VARARGS*/ ! 3587: -yyerror(fmt, s1, s2, s3) ! 3588: - char *fmt, *s1, *s2, *s3; ! 3589: -{ ! 3590: - fprintf(stderr, "line %d: ", yyline); ! 3591: - fprintf(stderr, fmt, s1, s2, s3); ! 3592: - if (token_buffer[0]!=0) ! 3593: - fprintf(stderr, " at \"%s\"\n", token_buffer); ! 3594: -} ! 3595: - ! 3596: -/*VARARGS*/ ! 3597: -yyerror2 (fmt, s1, s2, s3) ! 3598: - char *fmt, *s1, *s2, *s3; ! 3599: -{ ! 3600: - fprintf(stderr, "line %d: ", yyline); ! 3601: - fprintf(stderr, fmt, s1, s2, s3); ! 3602: - putchar('\n'); ! 3603: -} ! 3604: - ! 3605: -char *cmdnam; ! 3606: -char *inFileName; ! 3607: -char *outFileName; ! 3608: -char prefixFile[100]; ! 3609: -static char usage[] = "usage: mt [-d] file"; ! 3610: -#define USAGE error(1, usage) ! 3611: -char *prefix_base = PREFIX_BASE; ! 3612: -char *suffix = "c1"; ! 3613: - ! 3614: -main(argc, argv) ! 3615: - int argc; ! 3616: - char **argv; ! 3617: -{ ! 3618: - int i; ! 3619: - char *cp; ! 3620: - ! 3621: -#ifndef PREFIX_BASE ! 3622: - error(1,"PREFIX_BASE has not been defined; recompile twig"); ! 3623: -#endif ! 3624: - ! 3625: - cmdnam = argv[0]; ! 3626: - argv++; ! 3627: - inFileName = NULL; ! 3628: - ! 3629: - while(--argc > 0) { ! 3630: - if (*argv[0]=='-') ! 3631: - switch(argv[0][1]) { ! 3632: - /* to see what each of these flags mean... ! 3633: - * see common.h */ ! 3634: - case 'd': { ! 3635: - char *cp; ! 3636: - for(cp = &argv[0][2]; *cp!='\0'; cp++) ! 3637: - switch(*cp) { ! 3638: - case 'l': debug_flag |= DB_LEX; break; ! 3639: - case 'm': debug_flag |= DB_MACH; break; ! 3640: - case 's': debug_flag |= DB_SYM; break; ! 3641: - case 't': debug_flag |= DB_TREE; break; ! 3642: - case 'M': debug_flag |= DB_MEM; break; ! 3643: - } ! 3644: - } ! 3645: - break; ! 3646: - case 'D': Dflag++; break; ! 3647: - case 't': tflag++; break; ! 3648: - case 'w': suffix = process_suffix(&argv[0][2]); break; ! 3649: - case 'l': prefix_base = &argv[0][2]; break; ! 3650: - case 'x': line_xref_flag++; break; ! 3651: - default: ! 3652: - USAGE; ! 3653: - } ! 3654: - else inFileName = argv[0]; ! 3655: - argv++; ! 3656: - } ! 3657: - if(inFileName==NULL) ! 3658: - USAGE; ! 3659: - ! 3660: - if(freopen(inFileName, "r", stdin)==NULL) ! 3661: - error(1, "can't open %s", inFileName); ! 3662: - if((cp=strrchr(inFileName, '.'))!=NULL && strcmp(cp,".mt")==0) { ! 3663: - if ((outfile = fopen("walker.c" , "w"))==NULL) ! 3664: - error(1, "can't write %s", outFileName); ! 3665: - if ((symfile = fopen("symbols.h", "w"))==NULL) ! 3666: - error(1, "can't write %s", outFileName); ! 3667: - } else error(1, "input file must have suffix .mt"); ! 3668: - ! 3669: - ErrorSymbol.attr = A_LABEL; ! 3670: - TreeInit(); ! 3671: - SymbolInit(); ! 3672: - LexInit(); ! 3673: - yyparse(); ! 3674: - ! 3675: - SymbolDump(); ! 3676: - if(nerrors == 0) { ! 3677: - if(!tflag) { ! 3678: - FILE *prefix; ! 3679: - char c; ! 3680: - sprintf(prefixFile, "%s.%s", prefix_base, suffix); ! 3681: - prefix = fopen(prefixFile, "r"); ! 3682: - assert(prefix!=NULL); ! 3683: - if(Dflag) ! 3684: - fputs("#define DEBUG 1\n", outfile); ! 3685: - if(line_xref_flag) ! 3686: - fputs("#define LINE_XREF 1\n", outfile); ! 3687: - fprintf(outfile,"# line 1 \"%s\"\n", prefixFile); ! 3688: - while((c=getc(prefix))!=EOF) putc(c, outfile); ! 3689: - } ! 3690: - MachineGen(); ! 3691: - SymbolGenerateWalkerCode(); ! 3692: - CodeWrite(outfile, epilogue); ! 3693: - CodeFreeBlock(epilogue); ! 3694: - } ! 3695: - ! 3696: - /* cleanup */ ! 3697: - cleanup(0); ! 3698: -} ! 3699: - ! 3700: -cleanup(retcode) ! 3701: - int retcode; ! 3702: -{ ! 3703: - lexCleanup(); ! 3704: - if(retcode==0) { ! 3705: - SymbolFinish(); ! 3706: - } ! 3707: - exit(retcode); ! 3708: -} ! 3709: - ! 3710: -/*VARARGS*/ ! 3711: -error(rc, fmt, a1, a2, a3) ! 3712: - int rc; ! 3713: - char *fmt, *a1, *a2, *a3; ! 3714: -{ ! 3715: - fprintf(stderr, "%s: ", cmdnam); ! 3716: - fprintf(stderr, fmt, a1, a2, a3); ! 3717: - putc ('\n', stderr); ! 3718: - if(rc) ! 3719: - exit (rc); ! 3720: -} ! 3721: - ! 3722: -/*VARARGS*/ ! 3723: -sem_error (fmt, a1, a2, a3) ! 3724: - char *fmt, *a1, *a2, *a3; ! 3725: -{ ! 3726: - fprintf (stderr, "line %d: ", yyline); ! 3727: - sem_error2(fmt, a1, a2, a3); ! 3728: - nerrors++; ! 3729: - fatalerrors++; ! 3730: -} ! 3731: - ! 3732: -/*VARARGS*/ ! 3733: -sem_error2(fmt, a1, a2, a3) ! 3734: - char *fmt, *a1, *a2, *a3; ! 3735: -{ ! 3736: - fprintf (stderr, fmt, a1, a2, a3); ! 3737: - putc('\n', stderr); ! 3738: - nerrors++; ! 3739: -} ! 3740: - ! 3741: -char * ! 3742: -process_suffix(suf) ! 3743: - char *suf; ! 3744: -{ ! 3745: - extern int gen_table2; ! 3746: - if(strcmp(suf,"exper")==0) { ! 3747: - /* experimental walker */ ! 3748: - /* expect this to change alot */ ! 3749: - gen_table2++; ! 3750: - } ! 3751: - return(suf); ! 3752: -} ! 3753: //GO.SYSIN DD twig.y ! 3754: echo walker.c1 1>&2 ! 3755: sed 's/.//' >walker.c1 <<'//GO.SYSIN DD walker.c1' ! 3756: -/* ! 3757: - * The machine is laid out as a sequence of integers in the walker. ! 3758: - * The form described above is only used inside the preprocessor. ! 3759: - * Each machine state is one of the following sequence: ! 3760: - * ! 3761: - * TABLE <value_1><index_1>...<value_n><index_n> -1 [FAIL <fail_index>] -1 ! 3762: - * or ! 3763: - * TABLE2 <value_1><index_1>...<value_n><index_n> -1 [FAIL <fail_index>] -1 ! 3764: - * or ! 3765: - * ACCEPT <accept table index> -1 ! 3766: - * ! 3767: - * The accept table is in the form: ! 3768: - * ! 3769: - * <tree index_1> ...<tree_index_m> -1 ! 3770: - * ! 3771: - */ ! 3772: -/* Keutzer - all "short int"'s have been changed to "short" for ! 3773: - portability to UTS. */ ! 3774: -#include "symbols.h" ! 3775: -/* Keutzer 1/88- _mtG now uses varargs for portability to SUN4 etc.*/ ! 3776: -#include <varargs.h> ! 3777: - ! 3778: -#ifndef FILE ! 3779: -#include <stdio.h> ! 3780: -#endif ! 3781: -#include <assert.h> ! 3782: - ! 3783: -/* These constants must be the same as the ones in machine.c */ ! 3784: -#define FASTLIM 0 ! 3785: -#define TABLE 1 ! 3786: -#define FAIL 2 ! 3787: -#define ACCEPT 3 ! 3788: -#define TABLE2 4 ! 3789: -#define EOT -1 ! 3790: - ! 3791: -/* special machine state */ ! 3792: -#define HANG -1 ! 3793: - ! 3794: -/* used by the evaluator to interpret path table */ ! 3795: -#define eSTOP 0 ! 3796: -#define ePOP -1 ! 3797: -#define eEVAL -2 ! 3798: -#define eNEXT -3 ! 3799: -#define ePUSH -4 ! 3800: - ! 3801: -/* Tags that indicate the type of a value */ ! 3802: -#define M_BRANCH 010000 ! 3803: -#define M_NODE 0 ! 3804: -#define M_LABEL 01000 ! 3805: -#define MAX_NODE_VALUE 00777 ! 3806: -#define MTAG_SHIFT 9 ! 3807: -#define M_DETAG(x) ((x)&~(M_BRANCH|M_LABEL|M_NODE)) ! 3808: - ! 3809: -/* predicates to tell whether a value x is of type NODE, BRANCH, or LABEL */ ! 3810: -#define MI_NODE(x) (((x)&(M_BRANCH|M_LABEL))==0) ! 3811: -#define MI_DEFINED(x) ((x)!=-1) ! 3812: -#define MI_LABEL(x) (((x)&M_LABEL)!=0) ! 3813: -#define MI_BRANCH(x) (((x)&M_BRANCH)!=0) ! 3814: - ! 3815: -/* build a tagged value */ ! 3816: -#define MV_NODE(x) (x) ! 3817: -#define MV_BRANCH(x) ((x)|M_BRANCH) ! 3818: -#define MV_LABEL(x) ((x)|M_LABEL) ! 3819: - ! 3820: -/* limits */ ! 3821: -/* ! 3822: - * The depth of a pattern must be 7 or less. Otherwise the type of he ! 3823: - * partial mask in skeleton must be changed ! 3824: - */ ! 3825: -#define MAXDEPTH 7 ! 3826: - ! 3827: -/* modes */ ! 3828: -#define xTOPDOWN 3 ! 3829: -#define xABORT 2 ! 3830: -#define xREWRITE 1 ! 3831: -#define xDEFER 0 ! 3832: - ! 3833: -/* macros */ ! 3834: -#define tDO(m) _do((m)->skel, (m), 1) ! 3835: -#define REWRITE return(_m->cost = cost, xREWRITE) ! 3836: -#define TOPDOWN return(_m->cost = cost, xTOPDOWN) ! 3837: -#define ABORT return(xABORT) ! 3838: - ! 3839: -/* ! 3840: - * REORDER macro allows a knowledgeable user to change the order ! 3841: - * of evaluation of the leaves. ! 3842: - */ ! 3843: -#ifndef REORDER ! 3844: -#define REORDER(list) _evalleaves(list) ! 3845: -#endif ! 3846: -#define EVAL REORDER(_ll) ! 3847: - ! 3848: -#define mpush(s,m) (m)->next = s, s = m ! 3849: - ! 3850: -/* skeleton structure */ ! 3851: -typedef struct skeleton skeleton; ! 3852: -typedef struct __match __match; ! 3853: -typedef struct __partial __partial; ! 3854: -typedef struct __hshcls __hshcls; /* a hashed closure entry */ ! 3855: -typedef int labelset; /* a bit vector of labels */ ! 3856: - ! 3857: -struct __partial { ! 3858: - unsigned char treeno; ! 3859: - char bits; ! 3860: -}; ! 3861: - ! 3862: -struct __hshcls { ! 3863: - __hshcls *next; ! 3864: - labelset labels; ! 3865: - int treecnt; /* number of partial matches */ ! 3866: - __partial partial[MAXTREES]; ! 3867: -}; ! 3868: - ! 3869: -struct skeleton { ! 3870: - skeleton *sibling; ! 3871: - skeleton *leftchild; /* leftmost child */ ! 3872: - skeleton *rightchild; /* rightmost child */ ! 3873: - NODEPTR root; ! 3874: - NODEPTR parent; /* our parent */ ! 3875: - int nson; ! 3876: - int treecnt; ! 3877: - __match *succ[MAXLABELS]; ! 3878: - __partial *partial; ! 3879: - __match *winner; ! 3880: - COST mincost; ! 3881: -}; ! 3882: - ! 3883: -struct __match { ! 3884: - __match **lleaves; /* labelled leaves */ ! 3885: - skeleton *skel; /* back pointer to associated skeleton node */ ! 3886: - COST cost; ! 3887: - short tree; ! 3888: - short mode; ! 3889: -}; ! 3890: - ! 3891: -struct freeb { ! 3892: - struct freeb *next; ! 3893: -}; ! 3894: - ! 3895: -struct _mem { ! 3896: - struct _mem *next; ! 3897: - int size; /* size of individual elements in bytes */ ! 3898: - int blkf; /* blocking factor */ ! 3899: - int bsize; /* block size */ ! 3900: - char *block; /* block */ ! 3901: - int cnt; /* count of free elem in block */ ! 3902: - char *freelist; /* free list */ ! 3903: - int totelem; /* total number elements we have */ ! 3904: - int freecnt; /* number of times mem_free was called */ ! 3905: -}; ! 3906: - ! 3907: -/* turn this flag on if your machine has a fast byte string zero operation */ ! 3908: -/*#define BZERO 1*/ ! 3909: -int mtDebug = 0; ! 3910: -int treedebug = 0; ! 3911: -extern int _machstep(); ! 3912: -extern short mtStart; ! 3913: -extern short mtTable[], mtAccept[], mtMap[], mtPaths[], mtPathStart[]; ! 3914: -#ifdef LINE_XREF ! 3915: - extern short mtLine[]; ! 3916: -#endif ! 3917: - ! 3918: -#ifndef MPBSIZE ! 3919: -#define MPBSIZE 8000 ! 3920: -#endif ! 3921: - ! 3922: -#ifdef ADDCOST ! 3923: -#define DEFAULT_COST sumleaves(_ll) ! 3924: -COST sumleaves(list) __match **list; ! 3925: -{COST cost; ! 3926: - cost=ZEROCOST; ! 3927: - for(; *list; list++) ! 3928: - {ADDCOST((cost),(*list)->cost); ! 3929: - } ! 3930: - return cost; ! 3931: -} ! 3932: -#endif ! 3933: - ! 3934: -extern NODEPTR mtGetNodes(), mtAction(); ! 3935: -extern skeleton *_allocskel(); ! 3936: -extern __match *_allocmatch(); ! 3937: -extern __partial *_allocpartial(); ! 3938: - ! 3939: -__match *_mpblock[MPBSIZE], **_mpbtop; ! 3940: - ! 3941: -__match ** ! 3942: -_getleaves (mp, skp) ! 3943: - register __match *mp; register skeleton *skp; ! 3944: -{ ! 3945: - skeleton *stack[MAXDEPTH]; ! 3946: - skeleton **stp = stack; ! 3947: - register short *sip = &mtPaths[mtPathStart[mp->tree]]; ! 3948: - register __match **mmp = _mpbtop; ! 3949: - __match **mmp2 = mmp; ! 3950: - if((_mpbtop += *sip++ + 1) > &_mpblock[MPBSIZE]) { ! 3951: - printf("Tree too large: make MPBSIZE larger.\n\ ! 3952: -(i.e. cc -c -DMPBSIZE=%d walker.c)\n",MPBSIZE*2); ! 3953: - assert(0); ! 3954: - } ! 3955: - ! 3956: - for(;;) ! 3957: - switch(*sip++) { ! 3958: - case ePUSH: ! 3959: - *stp++ = skp; ! 3960: - skp = skp->leftchild; ! 3961: - break; ! 3962: - ! 3963: - case eNEXT: ! 3964: - skp = skp->sibling; ! 3965: - break; ! 3966: - ! 3967: - case eEVAL: ! 3968: - if ((mp = skp->succ[M_DETAG(*sip++)])==NULL) abort(); ! 3969: - *mmp++ = mp; ! 3970: - break; ! 3971: - ! 3972: - case ePOP: ! 3973: - skp = *--stp; ! 3974: - break; ! 3975: - ! 3976: - case eSTOP: ! 3977: - *mmp = NULL; ! 3978: - return (mmp2); ! 3979: - } ! 3980: -} ! 3981: - ! 3982: -_evalleaves (mpp) ! 3983: - register __match **mpp; ! 3984: -{ ! 3985: - for (; *mpp!=NULL; mpp++) { ! 3986: - register __match *mp = *mpp; ! 3987: - _do (mp->skel, mp, 1); ! 3988: - } ! 3989: -} ! 3990: - ! 3991: - ! 3992: -_do(sp, winner, evalall) ! 3993: - skeleton *sp; register __match *winner; int evalall; ! 3994: -{ ! 3995: - register __match **mpp; ! 3996: - register skeleton *skel = winner->skel; ! 3997: - if(winner==NULL) { ! 3998: - _nowin(sp); ! 3999: - return; ! 4000: - } ! 4001: - if(winner->mode==xDEFER || (evalall && winner->mode!=xTOPDOWN)) ! 4002: - REORDER(winner->lleaves); ! 4003: - mtSetNodes (skel->parent, skel->nson, ! 4004: - skel->root=mtAction (winner->tree, winner->lleaves, sp)); ! 4005: -} ! 4006: - ! 4007: -skeleton * ! 4008: -_walk(sp, ostate) ! 4009: - register skeleton *sp; ! 4010: - int ostate; ! 4011: -{ ! 4012: - int state, nstate, nson; ! 4013: - register __partial *pp; ! 4014: - register __match *mp, *mp2; ! 4015: - register skeleton *nsp, *lastchild = NULL; ! 4016: - NODEPTR son, root; ! 4017: - ! 4018: - root = sp->root; ! 4019: - nson = 1; sp->mincost = INFINITY; ! 4020: - state = _machstep (ostate, root, mtValue(root)); ! 4021: - ! 4022: - while((son = mtGetNodes(root, nson))!=NULL) { ! 4023: - nstate = _machstep (state, NULL, MV_BRANCH(nson)); ! 4024: - nsp = _allocskel(); ! 4025: - nsp->root = son; ! 4026: - nsp->parent = root; ! 4027: - nsp->nson = nson; ! 4028: - _walk(nsp, nstate); ! 4029: - if(COSTLESS(nsp->mincost,INFINITY)) { ! 4030: - assert (nsp->winner->mode==xREWRITE); ! 4031: - _do(nsp, nsp->winner, 0); ! 4032: - _freeskel(nsp); ! 4033: - continue; ! 4034: - } ! 4035: - _merge (sp, nsp); ! 4036: - if (lastchild==NULL) sp->leftchild = nsp; ! 4037: - else lastchild->sibling = nsp; ! 4038: - lastchild = nsp; ! 4039: - nson++; ! 4040: - } ! 4041: - ! 4042: - for (pp = sp->partial; pp < &sp->partial[sp->treecnt]; pp++) ! 4043: - if (pp->bits&01==1) { ! 4044: - mp = _allocmatch(); ! 4045: - mp->tree = pp->treeno; ! 4046: - _addmatches (ostate, sp, mp); ! 4047: - } ! 4048: - if(son==NULL && nson==1) ! 4049: - _closure (state, ostate, sp); ! 4050: - ! 4051: - sp->rightchild = lastchild; ! 4052: - if (root==NULL) { ! 4053: - COST c; __match *win; int i; nsp = sp->leftchild; ! 4054: - c = INFINITY; ! 4055: - win = NULL; ! 4056: - for (i = 0; i < MAXLABELS; i++) { ! 4057: - mp = nsp->succ[i]; ! 4058: - if (mp!=NULL && COSTLESS (mp->cost, c)) ! 4059: - { c = mp->cost; win = mp; } ! 4060: - } ! 4061: - _do (nsp, win, 0); ! 4062: - } ! 4063: - return(sp); ! 4064: -} ! 4065: - ! 4066: -/* ! 4067: - * Convert the start state which has a large branching factor into ! 4068: - * a index table. This must be called before the matcher is used. ! 4069: - */ ! 4070: -static short _nodetab[MAXNDVAL], _labeltab[MAXLABELS]; ! 4071: -_matchinit() ! 4072: -{ ! 4073: - short *sp; ! 4074: -/* Keutzer - this syntax doesn't work on UTS ! 4075: - struct pair { short val, where } *pp; ! 4076: -*/ ! 4077: - struct pair { short val; short where; } *pp; ! 4078: - for (sp=_nodetab; sp < &_nodetab[MAXNDVAL]; sp++) *sp = HANG; ! 4079: - for (sp=_labeltab; sp < &_labeltab[MAXLABELS]; sp++) *sp = HANG; ! 4080: - sp = &mtTable[mtStart]; ! 4081: - assert (*sp==TABLE); ! 4082: - for (pp = (struct pair *) ++sp; pp->val!=EOF; pp++) { ! 4083: - if (MI_NODE(pp->val)) ! 4084: - _nodetab[M_DETAG(pp->val)] = pp->where; ! 4085: - else if (MI_LABEL(pp->val)) ! 4086: - _labeltab[M_DETAG(pp->val)] = pp->where; ! 4087: - } ! 4088: -} ! 4089: - ! 4090: -int ! 4091: -_machstep(state, root, input) ! 4092: - short state, input; ! 4093: - NODEPTR root; ! 4094: -{ ! 4095: - register short *stp = &mtTable[state]; ! 4096: - int start = 0; ! 4097: - if (state==HANG) ! 4098: - return (input==(MV_BRANCH(1)) ? mtStart : HANG); ! 4099: -rescan: ! 4100: - if (stp==&mtTable[mtStart]) { ! 4101: - if (MI_NODE(input)) return(_nodetab[M_DETAG(input)]); ! 4102: - if (MI_LABEL(input)) return(_labeltab[M_DETAG(input)]); ! 4103: - } ! 4104: - ! 4105: - for(;;) { ! 4106: - if(*stp==ACCEPT) stp += 2; ! 4107: - ! 4108: - if(*stp==TABLE) { ! 4109: - stp++; ! 4110: - while(*stp!=EOT) { ! 4111: - if(input==*stp) { ! 4112: - return(*++stp); ! 4113: - } ! 4114: - stp += 2; ! 4115: - } ! 4116: - stp++; ! 4117: - } ! 4118: - if(*stp!=FAIL) { ! 4119: - if (start) return (HANG); ! 4120: - else { stp = &mtTable[mtStart]; start = 1; goto rescan;} ! 4121: - } else { ! 4122: - stp++; ! 4123: - stp = &mtTable[*stp]; ! 4124: - goto rescan; ! 4125: - } ! 4126: - } ! 4127: -} ! 4128: - ! 4129: -_addmatches(ostate, sp, np) ! 4130: - int ostate; ! 4131: - register skeleton *sp; ! 4132: - register __match *np; ! 4133: -{ ! 4134: - int label; ! 4135: - int state; ! 4136: - register __match *mp; ! 4137: - ! 4138: - label = mtMap[np->tree]; ! 4139: - ! 4140: - /* ! 4141: - * this is a very poor substitute for good design of the DFA. ! 4142: - * What we need is a special case that allows any label to be accepted ! 4143: - * by the start state but we don't want the start state to recognize ! 4144: - * them after a failure. ! 4145: - */ ! 4146: - state = _machstep(ostate, NULL, MV_LABEL(label)); ! 4147: - if (ostate!=mtStart && state==HANG) { ! 4148: - _freematch(np); ! 4149: - return; ! 4150: - } ! 4151: - ! 4152: - np->lleaves = _getleaves (np, sp); ! 4153: - np->skel = sp; ! 4154: - if((np->mode = mtEvalCost(np, np->lleaves, sp))==xABORT) ! 4155: - { ! 4156: - _freematch(np); ! 4157: - return; ! 4158: - } ! 4159: - ! 4160: -/* ! 4161: - if(np->mode==xREWRITE && COSTLESS(np->cost, sp->mincost)) { ! 4162: - sp->mincost = np->cost; ! 4163: - sp->winner = np; ! 4164: - } ! 4165: -*/ ! 4166: - if ((mp = sp->succ[label])!=NULL) { ! 4167: - if (!COSTLESS (np->cost, mp->cost)) ! 4168: - { _freematch(np); return; } ! 4169: - else _freematch(mp); ! 4170: - } ! 4171: - if(COSTLESS(np->cost,sp->mincost)) { ! 4172: - if(np->mode==xREWRITE) { ! 4173: - sp->mincost = np->cost; sp->winner = np; } ! 4174: - else { sp->mincost = INFINITY; sp->winner = NULL; } ! 4175: - } ! 4176: - sp->succ[label] = np; ! 4177: - _closure(state, ostate, sp); ! 4178: -} ! 4179: - ! 4180: -_closure(state, ostate, skp) ! 4181: - int state, ostate; ! 4182: - skeleton *skp; ! 4183: -{ ! 4184: - register struct ap { short tree, depth; } *ap; ! 4185: - short *sp = &mtTable[state]; ! 4186: - register __match *mp; ! 4187: - ! 4188: - if(state==HANG || *sp!=ACCEPT) return(NULL); ! 4189: - ! 4190: - for(ap = (struct ap *) &mtAccept[*++sp]; ap->tree!=-1; ap++) ! 4191: - if (ap->depth==0) { ! 4192: - mp = _allocmatch(); ! 4193: - mp->tree = ap->tree; ! 4194: - _addmatches (ostate, skp, mp); ! 4195: - } else { ! 4196: - register __partial *pp, *lim = &skp->partial[skp->treecnt]; ! 4197: - for(pp=skp->partial; pp < lim; pp++) ! 4198: - if(pp->treeno==ap->tree) ! 4199: - break; ! 4200: - if(pp==lim) { ! 4201: - skp->treecnt++; ! 4202: - pp->treeno = ap->tree; ! 4203: - pp->bits = (1<<(ap->depth)); ! 4204: - } else pp->bits |= (1<<(ap->depth)); ! 4205: - } ! 4206: -} ! 4207: - ! 4208: -_merge (old, new) ! 4209: - skeleton *old, *new; ! 4210: -{ ! 4211: - register __partial *op = old->partial, *np = new->partial; ! 4212: - int nson = new->nson; ! 4213: - register __partial *lim = np + new->treecnt; ! 4214: - if (nson==1) { ! 4215: - old->treecnt = new->treecnt; ! 4216: - for(; np < lim; op++, np++) { ! 4217: - op->treeno = np->treeno; ! 4218: - op->bits = np->bits/2; ! 4219: - } ! 4220: - } else { ! 4221: - __partial *newer = _allocpartial(); ! 4222: - register __partial *newerp = newer; ! 4223: - register int cnt; ! 4224: - lim = op+old->treecnt; ! 4225: - for(cnt=new->treecnt; cnt-- ; np++) { ! 4226: - for(op = old->partial; op < lim; op++) ! 4227: - if (op->treeno == np->treeno) { ! 4228: - newerp->treeno = op->treeno; ! 4229: - newerp++->bits = op->bits & (np->bits/2); ! 4230: - break; ! 4231: - } ! 4232: - } ! 4233: - _freepartial(old->partial); ! 4234: - old->partial = newer; ! 4235: - old->treecnt = newerp-newer; ! 4236: - } ! 4237: -} ! 4238: - ! 4239: -/* Save and Allocate Matches */ ! 4240: -#define BLKF 100 ! 4241: -__match *freep = NULL; ! 4242: -static int _count = 0; ! 4243: -static __match *_blockp = NULL; ! 4244: -#ifdef CHECKMEM ! 4245: -int x_matches, f_matches; ! 4246: -#endif ! 4247: - ! 4248: -__match * ! 4249: -_allocmatch() ! 4250: -{ ! 4251: - __match *mp; ! 4252: - ! 4253: - if(freep!=NULL) { ! 4254: - mp = freep; ! 4255: - freep = ((__match *)((struct freeb *) freep)->next); ! 4256: -#ifdef CHECKMEM ! 4257: - f_matches--; ! 4258: -#endif ! 4259: - } else { ! 4260: - if(_count==0) { ! 4261: - _blockp = (__match *) malloc (BLKF*sizeof (__match)); ! 4262: - _count = BLKF; ! 4263: -#ifdef CHECKMEM ! 4264: - x_matches += BLKF; ! 4265: -#endif ! 4266: - } ! 4267: - mp = _blockp++; ! 4268: - _count--; ! 4269: - } ! 4270: - return(mp); ! 4271: -} ! 4272: - ! 4273: -_freematch(mp) ! 4274: - __match *mp; ! 4275: -{ ! 4276: - ((struct freeb *) mp)->next = (struct freeb *) freep; ! 4277: - freep = mp; ! 4278: -#ifdef CHECKMEM ! 4279: - f_matches++; ! 4280: -#endif ! 4281: -} ! 4282: - ! 4283: -static __partial *pfreep = NULL; ! 4284: -static int pcount = 0; ! 4285: -static __partial *pblock = NULL; ! 4286: -#ifdef CHECKMEM ! 4287: -static int x_partials, f_partials; ! 4288: -#endif ! 4289: - ! 4290: -__partial * ! 4291: -_allocpartial() ! 4292: -{ ! 4293: - __partial *pp; ! 4294: - if (pfreep!=NULL) { ! 4295: - pp = pfreep; ! 4296: - pfreep = *(__partial **) pp; ! 4297: -#ifdef CHECKMEM ! 4298: - f_partials--; ! 4299: -#endif ! 4300: - } else { ! 4301: - if (pcount==0) { ! 4302: - pblock=(__partial *)malloc(BLKF*MAXTREES*sizeof(__partial)); ! 4303: - pcount = BLKF; ! 4304: -#ifdef CHECKMEM ! 4305: - x_partials += BLKF; ! 4306: -#endif ! 4307: - } ! 4308: - pp = pblock; ! 4309: - pblock += MAXTREES; ! 4310: - pcount--; ! 4311: - } ! 4312: - return(pp); ! 4313: -} ! 4314: - ! 4315: -_freepartial(pp) ! 4316: - __partial *pp; ! 4317: -{ ! 4318: - * (__partial **)pp = pfreep; ! 4319: - pfreep = pp; ! 4320: -#ifdef CHECKMEM ! 4321: - f_partials++; ! 4322: -#endif ! 4323: -} ! 4324: - ! 4325: - ! 4326: -/* storage management */ ! 4327: -static skeleton *sfreep = NULL; ! 4328: -static int scount = 0; ! 4329: -static skeleton * sblock = NULL; ! 4330: - ! 4331: -skeleton * ! 4332: -_allocskel() ! 4333: -{ ! 4334: - skeleton *sp; ! 4335: - int i; ! 4336: - if(sfreep!=NULL) { ! 4337: - sp = sfreep; ! 4338: - sfreep = sp->sibling; ! 4339: - } else { ! 4340: - if(scount==0) { ! 4341: - sblock = (skeleton *) malloc (BLKF * sizeof (skeleton)); ! 4342: - scount = BLKF; ! 4343: - } ! 4344: - sp = sblock++; ! 4345: - scount--; ! 4346: - } ! 4347: - sp->sibling = NULL; sp->leftchild = NULL; ! 4348: - for (i=0; i < MAXLABELS; sp->succ[i++] = NULL); ! 4349: - sp->treecnt = 0; ! 4350: - sp->partial = _allocpartial(); ! 4351: - return(sp); ! 4352: -} ! 4353: - ! 4354: -_freeskel(sp) ! 4355: - skeleton *sp; ! 4356: -{ ! 4357: - int i; ! 4358: - __match *mp; ! 4359: - if(sp==NULL) return; ! 4360: - _freeskel (sp->leftchild); ! 4361: - _freeskel (sp->sibling); ! 4362: - _freepartial (sp->partial); ! 4363: - for (i=0; i < MAXLABELS; i++) ! 4364: - if ((mp = sp->succ[i])!=NULL) _freematch (mp); ! 4365: - sp->sibling = sfreep; ! 4366: - sfreep = sp; ! 4367: -} ! 4368: - ! 4369: -_match() ! 4370: -{ ! 4371: - skeleton *sp; ! 4372: - sp = _allocskel(); ! 4373: - sp->root = NULL; ! 4374: - _mpbtop = _mpblock; ! 4375: - _freeskel(_walk(sp, HANG)); ! 4376: -#ifdef CHECKMEM ! 4377: - if(f_matches+_count!=x_matches) { ! 4378: - printf(";#m %d %d %d\n", f_matches, _count, x_matches); ! 4379: - assert(0); ! 4380: - } ! 4381: - if(f_partials+pcount!=x_partials) { ! 4382: - printf(";#p %d %d %d\n", f_partials, pcount, x_partials); ! 4383: - assert(0); ! 4384: - } ! 4385: -#endif ! 4386: -} ! 4387: - ! 4388: -/* Keutzer 1/88- _mtG now uses varargs for portability to SUN4 etc.*/ ! 4389: -NODEPTR _mtG(va_alist) ! 4390: -va_dcl ! 4391: -{ ! 4392: - NODEPTR root; ! 4393: - int i=0; ! 4394: - va_list p_var; ! 4395: - va_start(p_var); ! 4396: - root = va_arg(p_var,NODEPTR); ! 4397: - while( (i = va_arg(p_var,int)) != -1){ ! 4398: - root = mtGetNodes(root, i); ! 4399: - } ! 4400: - va_end(p_var); ! 4401: - return(root); ! 4402: -} ! 4403: - ! 4404: -/* diagnostic routines */ ! 4405: -#ifdef NOMARK ! 4406: -markIfNoMatch(skp,mark) ! 4407: - skeleton *skp; ! 4408: - int mark; ! 4409: -{} ! 4410: -#else ! 4411: -markIfNoMatch(skp,mark) skeleton *skp; int mark; ! 4412: -{skeleton *child; int i; int found=0; ! 4413: - for(i=0; i<MAXLABELS; i++) ! 4414: - if (skp->succ[i]) found=1; ! 4415: - if (!found) skp->root->mark=mark; ! 4416: - for(child=skp->leftchild; child; child=child->sibling) ! 4417: - markIfNoMatch(child,mark); ! 4418: -} ! 4419: -#endif ! 4420: - ! 4421: -_nowin(skp) skeleton *skp; ! 4422: -{ ! 4423: - markIfNoMatch(skp,1); ! 4424: - printf("# No match was found for the nodes printed in lowercase\n"); ! 4425: - printTree(skp->root); ! 4426: - markIfNoMatch(skp,0); ! 4427: -} ! 4428: //GO.SYSIN DD walker.c1 ! 4429: echo y.tab.c 1>&2 ! 4430: sed 's/.//' >y.tab.c <<'//GO.SYSIN DD y.tab.c' ! 4431: -# define ERROR 257 ! 4432: - ! 4433: -# line 3 "twig.y" ! 4434: -#include "common.h" ! 4435: -#include "code.h" ! 4436: -#include "sym.h" ! 4437: -#define UNDEFINED -1 ! 4438: -#define GIVENUP -2 ! 4439: - ! 4440: -int debug_flag = 0; ! 4441: -int Dflag = 0; ! 4442: -int tflag = 0; ! 4443: -int line_xref_flag = 0; ! 4444: -int ntrees = 0; ! 4445: -int nerrors = 0; ! 4446: -int fatalerrors = 0; ! 4447: -int tree_lineno; ! 4448: -FILE *outfile; ! 4449: -FILE *symfile; ! 4450: -Code *epilogue; ! 4451: - ! 4452: -SymbolEntry ErrorSymbol; ! 4453: - ! 4454: -# line 23 "twig.y" ! 4455: -typedef union { ! 4456: - Node *y_nodep; ! 4457: - SymbolEntry *y_symp; ! 4458: - Code *y_code; ! 4459: - int y_int; ! 4460: -} YYSTYPE; ! 4461: -# define K_NODE 258 ! 4462: -# define K_LABEL 259 ! 4463: -# define K_PROLOGUE 260 ! 4464: -# define K_CONST 261 ! 4465: -# define K_INSERT 262 ! 4466: -# define K_COST 263 ! 4467: -# define K_ACTION 264 ! 4468: -# define ID 265 ! 4469: -# define NUMBER 266 ! 4470: -# define CBLOCK 267 ! 4471: -#define yyclearin yychar = -1 ! 4472: -#define yyerrok yyerrflag = 0 ! 4473: -extern int yychar; ! 4474: -extern short yyerrflag; ! 4475: -#ifndef YYMAXDEPTH ! 4476: -#define YYMAXDEPTH 150 ! 4477: -#endif ! 4478: -YYSTYPE yylval, yyval; ! 4479: -# define YYERRCODE 256 ! 4480: - ! 4481: -# line 255 "twig.y" ! 4482: - ! 4483: - ! 4484: -extern char *process_suffix(); ! 4485: - ! 4486: -set_arity(symp, arityp, count) ! 4487: - SymbolEntry *symp; ! 4488: - int *arityp; ! 4489: - int count; ! 4490: -{ ! 4491: - if(*arityp!=GIVENUP) { ! 4492: - if (*arityp==UNDEFINED) ! 4493: - *arityp = count; ! 4494: - else if (*arityp!=count) { ! 4495: - sem_error("inconsistent arity for %s", symp->name); ! 4496: - *arityp = GIVENUP; ! 4497: - } ! 4498: - } ! 4499: -} ! 4500: - ! 4501: -is_node(symp) ! 4502: - SymbolEntry *symp; ! 4503: -{ return(symp->attr==A_NODE); } ! 4504: - ! 4505: -is_label(symp) ! 4506: - SymbolEntry *symp; ! 4507: -{ return(symp->attr==A_LABEL); } ! 4508: - ! 4509: -CheckIsNodeOrPred (symp) ! 4510: - SymbolEntry *symp; ! 4511: -{ ! 4512: - if (symp->attr==A_ERROR) ! 4513: - return; ! 4514: - if (symp->attr!=A_NODE) ! 4515: - sem_error ("non-node identifier %s", symp->name); ! 4516: -} ! 4517: - ! 4518: -CheckIsUndefined(symp) ! 4519: - SymbolEntry *symp; ! 4520: -{ ! 4521: - if (symp->attr==A_ERROR) ! 4522: - return(0); ! 4523: - if (symp->attr!=A_UNDEFINED) { ! 4524: - sem_error ("multiple declaration: %s", symp->name); ! 4525: - return(0); ! 4526: - } else return(1); ! 4527: -} ! 4528: - ! 4529: -CheckIsDefined(symp) ! 4530: - SymbolEntry *symp; ! 4531: -{ ! 4532: - if (symp->attr==A_ERROR) ! 4533: - return(0); ! 4534: - if (symp->attr==A_UNDEFINED) { ! 4535: - sem_error ("undefined identifier: %s", symp->name); ! 4536: - symp->attr=A_ERROR; ! 4537: - return(0); ! 4538: - } else return(1); ! 4539: -} ! 4540: - ! 4541: - ! 4542: - ! 4543: -/*VARARGS*/ ! 4544: -yyerror(fmt, s1, s2, s3) ! 4545: - char *fmt, *s1, *s2, *s3; ! 4546: -{ ! 4547: - fprintf(stderr, "line %d: ", yyline); ! 4548: - fprintf(stderr, fmt, s1, s2, s3); ! 4549: - if (token_buffer[0]!=0) ! 4550: - fprintf(stderr, " at \"%s\"\n", token_buffer); ! 4551: -} ! 4552: - ! 4553: -/*VARARGS*/ ! 4554: -yyerror2 (fmt, s1, s2, s3) ! 4555: - char *fmt, *s1, *s2, *s3; ! 4556: -{ ! 4557: - fprintf(stderr, "line %d: ", yyline); ! 4558: - fprintf(stderr, fmt, s1, s2, s3); ! 4559: - putchar('\n'); ! 4560: -} ! 4561: - ! 4562: -char *cmdnam; ! 4563: -char *inFileName; ! 4564: -char *outFileName; ! 4565: -char prefixFile[100]; ! 4566: -static char usage[] = "usage: mt [-d] file"; ! 4567: -#define USAGE error(1, usage) ! 4568: -char *prefix_base = PREFIX_BASE; ! 4569: -char *suffix = "c1"; ! 4570: - ! 4571: -main(argc, argv) ! 4572: - int argc; ! 4573: - char **argv; ! 4574: -{ ! 4575: - int i; ! 4576: - char *cp; ! 4577: - ! 4578: -#ifndef PREFIX_BASE ! 4579: - error(1,"PREFIX_BASE has not been defined; recompile twig"); ! 4580: -#endif ! 4581: - ! 4582: - cmdnam = argv[0]; ! 4583: - argv++; ! 4584: - inFileName = NULL; ! 4585: - ! 4586: - while(--argc > 0) { ! 4587: - if (*argv[0]=='-') ! 4588: - switch(argv[0][1]) { ! 4589: - /* to see what each of these flags mean... ! 4590: - * see common.h */ ! 4591: - case 'd': { ! 4592: - char *cp; ! 4593: - for(cp = &argv[0][2]; *cp!='\0'; cp++) ! 4594: - switch(*cp) { ! 4595: - case 'l': debug_flag |= DB_LEX; break; ! 4596: - case 'm': debug_flag |= DB_MACH; break; ! 4597: - case 's': debug_flag |= DB_SYM; break; ! 4598: - case 't': debug_flag |= DB_TREE; break; ! 4599: - case 'M': debug_flag |= DB_MEM; break; ! 4600: - } ! 4601: - } ! 4602: - break; ! 4603: - case 'D': Dflag++; break; ! 4604: - case 't': tflag++; break; ! 4605: - case 'w': suffix = process_suffix(&argv[0][2]); break; ! 4606: - case 'l': prefix_base = &argv[0][2]; break; ! 4607: - case 'x': line_xref_flag++; break; ! 4608: - default: ! 4609: - USAGE; ! 4610: - } ! 4611: - else inFileName = argv[0]; ! 4612: - argv++; ! 4613: - } ! 4614: - if(inFileName==NULL) ! 4615: - USAGE; ! 4616: - ! 4617: - if(freopen(inFileName, "r", stdin)==NULL) ! 4618: - error(1, "can't open %s", inFileName); ! 4619: - if((cp=strrchr(inFileName, '.'))!=NULL && strcmp(cp,".mt")==0) { ! 4620: - if ((outfile = fopen("walker.c" , "w"))==NULL) ! 4621: - error(1, "can't write %s", outFileName); ! 4622: - if ((symfile = fopen("symbols.h", "w"))==NULL) ! 4623: - error(1, "can't write %s", outFileName); ! 4624: - } else error(1, "input file must have suffix .mt"); ! 4625: - ! 4626: - ErrorSymbol.attr = A_LABEL; ! 4627: - TreeInit(); ! 4628: - SymbolInit(); ! 4629: - LexInit(); ! 4630: - yyparse(); ! 4631: - ! 4632: - SymbolDump(); ! 4633: - if(nerrors == 0) { ! 4634: - if(!tflag) { ! 4635: - FILE *prefix; ! 4636: - char c; ! 4637: - sprintf(prefixFile, "%s.%s", prefix_base, suffix); ! 4638: - prefix = fopen(prefixFile, "r"); ! 4639: - assert(prefix!=NULL); ! 4640: - if(Dflag) ! 4641: - fputs("#define DEBUG 1\n", outfile); ! 4642: - if(line_xref_flag) ! 4643: - fputs("#define LINE_XREF 1\n", outfile); ! 4644: - fprintf(outfile,"# line 1 \"%s\"\n", prefixFile); ! 4645: - while((c=getc(prefix))!=EOF) putc(c, outfile); ! 4646: - } ! 4647: - MachineGen(); ! 4648: - SymbolGenerateWalkerCode(); ! 4649: - CodeWrite(outfile, epilogue); ! 4650: - CodeFreeBlock(epilogue); ! 4651: - } ! 4652: - ! 4653: - /* cleanup */ ! 4654: - cleanup(0); ! 4655: -} ! 4656: - ! 4657: -cleanup(retcode) ! 4658: - int retcode; ! 4659: -{ ! 4660: - lexCleanup(); ! 4661: - if(retcode==0) { ! 4662: - SymbolFinish(); ! 4663: - } ! 4664: - exit(retcode); ! 4665: -} ! 4666: - ! 4667: -/*VARARGS*/ ! 4668: -error(rc, fmt, a1, a2, a3) ! 4669: - int rc; ! 4670: - char *fmt, *a1, *a2, *a3; ! 4671: -{ ! 4672: - fprintf(stderr, "%s: ", cmdnam); ! 4673: - fprintf(stderr, fmt, a1, a2, a3); ! 4674: - putc ('\n', stderr); ! 4675: - if(rc) ! 4676: - exit (rc); ! 4677: -} ! 4678: - ! 4679: -/*VARARGS*/ ! 4680: -sem_error (fmt, a1, a2, a3) ! 4681: - char *fmt, *a1, *a2, *a3; ! 4682: -{ ! 4683: - fprintf (stderr, "line %d: ", yyline); ! 4684: - sem_error2(fmt, a1, a2, a3); ! 4685: - nerrors++; ! 4686: - fatalerrors++; ! 4687: -} ! 4688: - ! 4689: -/*VARARGS*/ ! 4690: -sem_error2(fmt, a1, a2, a3) ! 4691: - char *fmt, *a1, *a2, *a3; ! 4692: -{ ! 4693: - fprintf (stderr, fmt, a1, a2, a3); ! 4694: - putc('\n', stderr); ! 4695: - nerrors++; ! 4696: -} ! 4697: - ! 4698: -char * ! 4699: -process_suffix(suf) ! 4700: - char *suf; ! 4701: -{ ! 4702: - extern int gen_table2; ! 4703: - if(strcmp(suf,"exper")==0) { ! 4704: - /* experimental walker */ ! 4705: - /* expect this to change alot */ ! 4706: - gen_table2++; ! 4707: - } ! 4708: - return(suf); ! 4709: -} ! 4710: -short yyexca[] ={ ! 4711: --1, 1, ! 4712: - 0, -1, ! 4713: - -2, 0, ! 4714: --1, 10, ! 4715: - 0, 1, ! 4716: - -2, 0, ! 4717: --1, 66, ! 4718: - 40, 49, ! 4719: - -2, 51, ! 4720: - }; ! 4721: -# define YYNPROD 56 ! 4722: -# define YYLAST 261 ! 4723: -short yyact[]={ ! 4724: - ! 4725: - 16, 71, 4, 6, 7, 5, 14, 8, 9, 17, ! 4726: - 4, 6, 7, 5, 37, 8, 9, 29, 89, 79, ! 4727: - 88, 78, 73, 72, 54, 36, 61, 59, 28, 50, ! 4728: - 44, 40, 16, 92, 33, 31, 66, 27, 14, 25, ! 4729: - 22, 17, 66, 32, 30, 93, 65, 70, 94, 85, ! 4730: - 69, 53, 87, 76, 75, 64, 63, 62, 60, 58, ! 4731: - 57, 39, 48, 38, 83, 82, 86, 49, 24, 21, ! 4732: - 12, 20, 13, 3, 80, 10, 11, 2, 77, 84, ! 4733: - 23, 35, 19, 34, 18, 15, 26, 90, 1, 45, ! 4734: - 41, 0, 51, 0, 0, 0, 0, 0, 0, 0, ! 4735: - 0, 74, 0, 0, 0, 0, 67, 0, 0, 0, ! 4736: - 68, 0, 0, 0, 0, 0, 0, 81, 0, 0, ! 4737: - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 4738: - 0, 0, 0, 91, 0, 0, 0, 0, 0, 0, ! 4739: - 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, ! 4740: - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 4741: - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 4742: - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 4743: - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 4744: - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 4745: - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 4746: - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 4747: - 0, 56, 0, 0, 73, 72, 52, 46, 42, 0, ! 4748: - 55, 0, 0, 0, 0, 25, 47, 43, 0, 0, ! 4749: - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 4750: - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ! 4751: - 95 }; ! 4752: -short yypact[]={ ! 4753: - ! 4754: --248,-1000,-256,-1000,-225,-226,-228,-239,-221,-222, ! 4755: --224,-1000,-1000,-1000,-242, 5, 2,-1000, -28, -29, ! 4756: --1000,-1000, 27, -30,-1000, -10, -35,-1000, 1, 0, ! 4757: --240, -1,-241, -2,-1000,-1000, -3, -4,-229,-1000, ! 4758: --1000,-1000,-1000, 27,-1000,-1000,-1000, 27, -11, -41, ! 4759: --1000,-1000,-1000,-243,-1000,-1000,-1000,-1000,-1000, -5, ! 4760: --1000, -6,-1000,-1000,-1000,-246,-1000,-1000, -11,-243, ! 4761: - 24, 23,-1000,-1000,-1000,-1000,-1000, -12,-1000,-1000, ! 4762: - 26,-1000,-1000,-1000, -7,-247,-223,-1000,-1000,-1000, ! 4763: - 4,-1000,-1000,-1000,-229,-1000,-1000 }; ! 4764: -short yypgo[]={ ! 4765: - ! 4766: - 0, 88, 46, 87, 86, 85, 84, 71, 82, 69, ! 4767: - 80, 68, 62, 47, 79, 78, 77, 75, 73, 72, ! 4768: - 70, 74 }; ! 4769: -short yyr1[]={ ! 4770: - ! 4771: - 0, 1, 16, 16, 18, 18, 18, 18, 18, 18, ! 4772: - 18, 18, 18, 18, 4, 4, 4, 8, 8, 8, ! 4773: - 6, 6, 6, 7, 9, 12, 12, 12, 10, 10, ! 4774: - 10, 11, 13, 13, 17, 17, 17, 17, 20, 20, ! 4775: - 19, 19, 14, 14, 14, 15, 15, 15, 5, 21, ! 4776: - 2, 2, 3, 3, 3, 3 }; ! 4777: -short yyr2[]={ ! 4778: - ! 4779: - 0, 2, 2, 1, 3, 3, 3, 3, 3, 4, ! 4780: - 4, 3, 3, 3, 2, 1, 2, 2, 1, 2, ! 4781: - 2, 1, 2, 2, 4, 3, 3, 0, 2, 1, ! 4782: - 2, 3, 1, 1, 2, 2, 1, 1, 3, 3, ! 4783: - 6, 2, 2, 2, 0, 1, 1, 0, 1, 0, ! 4784: - 5, 1, 3, 1, 1, 2 }; ! 4785: -short yychk[]={ ! 4786: - ! 4787: --1000, -1, -16, -18, 258, 261, 259, 260, 263, 264, ! 4788: - -17, -18, -20, -19, 262, -5, 256, 265, -6, -8, ! 4789: - -7, -9, 265, -10, -11, 265, -4, 265, 267, 256, ! 4790: - 265, 256, 265, 256, -19, -20, 267, 256, 58, 59, ! 4791: - 59, -7, 256, 265, 59, -9, 256, 265, -12, 40, ! 4792: - 59, -11, 256, 61, 59, 265, 256, 59, 59, 267, ! 4793: - 59, 267, 59, 59, 59, -2, 265, -12, -12, 61, ! 4794: - -13, 42, 266, 265, -13, 59, 59, -15, 267, 265, ! 4795: - -21, -13, 41, 41, -14, 61, 40, 59, 267, 265, ! 4796: - -3, -2, 256, 41, 44, 256, -2 }; ! 4797: -short yydef[]={ ! 4798: - ! 4799: - 0, -2, 0, 3, 0, 0, 0, 0, 0, 0, ! 4800: - -2, 2, 36, 37, 0, 0, 0, 48, 0, 0, ! 4801: - 21, 18, 27, 0, 29, 0, 0, 15, 0, 0, ! 4802: - 0, 0, 0, 0, 34, 35, 0, 0, 0, 41, ! 4803: - 4, 20, 22, 27, 5, 17, 19, 27, 23, 0, ! 4804: - 6, 28, 30, 0, 7, 14, 16, 8, 11, 0, ! 4805: - 13, 0, 12, 38, 39, 47, -2, 23, 0, 0, ! 4806: - 0, 0, 32, 33, 31, 9, 10, 44, 45, 46, ! 4807: - 0, 24, 25, 26, 0, 0, 0, 40, 42, 43, ! 4808: - 0, 53, 54, 50, 0, 55, 52 }; ! 4809: -# ifdef YYDEBUG ! 4810: -# include "y.debug" ! 4811: -# endif ! 4812: - ! 4813: -# define YYFLAG -1000 ! 4814: -# define YYERROR goto yyerrlab ! 4815: -# define YYACCEPT return(0) ! 4816: -# define YYABORT return(1) ! 4817: - ! 4818: -/* parser for yacc output */ ! 4819: - ! 4820: -#ifdef YYDEBUG ! 4821: -int yydebug = 0; /* 1 for debugging */ ! 4822: -#endif ! 4823: -YYSTYPE yyv[YYMAXDEPTH]; /* where the values are stored */ ! 4824: -int yychar = -1; /* current input token number */ ! 4825: -int yynerrs = 0; /* number of errors */ ! 4826: -short yyerrflag = 0; /* error recovery flag */ ! 4827: - ! 4828: -yyparse() ! 4829: -{ short yys[YYMAXDEPTH]; ! 4830: - int yyj, yym; ! 4831: - register YYSTYPE *yypvt; ! 4832: - register int yystate, yyn; ! 4833: - register short *yyps; ! 4834: - register YYSTYPE *yypv; ! 4835: - register short *yyxi; ! 4836: - ! 4837: - yystate = 0; ! 4838: - yychar = -1; ! 4839: - yynerrs = 0; ! 4840: - yyerrflag = 0; ! 4841: - yyps= &yys[-1]; ! 4842: - yypv= &yyv[-1]; ! 4843: - ! 4844: -yystack: /* put a state and value onto the stack */ ! 4845: -#ifdef YYDEBUG ! 4846: - if(yydebug >= 3) ! 4847: - if(yychar < 0 || yytoknames[yychar] == 0) ! 4848: - printf("char %d in %s", yychar, yystates[yystate]); ! 4849: - else ! 4850: - printf("%s in %s", yytoknames[yychar], yystates[yystate]); ! 4851: -#endif ! 4852: - if( ++yyps >= &yys[YYMAXDEPTH] ) { ! 4853: - yyerror( "yacc stack overflow" ); ! 4854: - return(1); ! 4855: - } ! 4856: - *yyps = yystate; ! 4857: - ++yypv; ! 4858: - *yypv = yyval; ! 4859: -yynewstate: ! 4860: - yyn = yypact[yystate]; ! 4861: - if(yyn <= YYFLAG) goto yydefault; /* simple state */ ! 4862: - if(yychar<0) { ! 4863: - yychar = yylex(); ! 4864: -#ifdef YYDEBUG ! 4865: - if(yydebug >= 2) { ! 4866: - if(yychar <= 0) ! 4867: - printf("lex EOF\n"); ! 4868: - else if(yytoknames[yychar]) ! 4869: - printf("lex %s\n", yytoknames[yychar]); ! 4870: - else ! 4871: - printf("lex (%c)\n", yychar); ! 4872: - } ! 4873: -#endif ! 4874: - if(yychar < 0) ! 4875: - yychar = 0; ! 4876: - } ! 4877: - if((yyn += yychar) < 0 || yyn >= YYLAST) ! 4878: - goto yydefault; ! 4879: - if( yychk[ yyn=yyact[ yyn ] ] == yychar ){ /* valid shift */ ! 4880: - yychar = -1; ! 4881: - yyval = yylval; ! 4882: - yystate = yyn; ! 4883: - if( yyerrflag > 0 ) --yyerrflag; ! 4884: - goto yystack; ! 4885: - } ! 4886: -yydefault: ! 4887: - /* default state action */ ! 4888: - if( (yyn=yydef[yystate]) == -2 ) { ! 4889: - if(yychar < 0) { ! 4890: - yychar = yylex(); ! 4891: -#ifdef YYDEBUG ! 4892: - if(yydebug >= 2) ! 4893: - if(yychar < 0) ! 4894: - printf("lex EOF\n"); ! 4895: - else ! 4896: - printf("lex %s\n", yytoknames[yychar]); ! 4897: -#endif ! 4898: - if(yychar < 0) ! 4899: - yychar = 0; ! 4900: - } ! 4901: - /* look through exception table */ ! 4902: - for(yyxi=yyexca; (*yyxi!= (-1)) || (yyxi[1]!=yystate); ! 4903: - yyxi += 2 ) ; /* VOID */ ! 4904: - while( *(yyxi+=2) >= 0 ){ ! 4905: - if( *yyxi == yychar ) break; ! 4906: - } ! 4907: - if( (yyn = yyxi[1]) < 0 ) return(0); /* accept */ ! 4908: - } ! 4909: - if( yyn == 0 ){ /* error */ ! 4910: - /* error ... attempt to resume parsing */ ! 4911: - switch( yyerrflag ){ ! 4912: - case 0: /* brand new error */ ! 4913: -#ifdef YYDEBUG ! 4914: - yyerror("syntax error\n%s", yystates[yystate]); ! 4915: - if(yytoknames[yychar]) ! 4916: - yyerror("saw %s\n", yytoknames[yychar]); ! 4917: - else if(yychar >= ' ' && yychar < '\177') ! 4918: - yyerror("saw `%c'\n", yychar); ! 4919: - else if(yychar == 0) ! 4920: - yyerror("saw EOF\n"); ! 4921: - else ! 4922: - yyerror("saw char 0%o\n", yychar); ! 4923: -#else ! 4924: - yyerror( "syntax error" ); ! 4925: -#endif ! 4926: -yyerrlab: ! 4927: - ++yynerrs; ! 4928: - case 1: ! 4929: - case 2: /* incompletely recovered error ... try again */ ! 4930: - yyerrflag = 3; ! 4931: - /* find a state where "error" is a legal shift action */ ! 4932: - while ( yyps >= yys ) { ! 4933: - yyn = yypact[*yyps] + YYERRCODE; ! 4934: - if( yyn>= 0 && yyn < YYLAST && yychk[yyact[yyn]] == YYERRCODE ){ ! 4935: - yystate = yyact[yyn]; /* simulate a shift of "error" */ ! 4936: - goto yystack; ! 4937: - } ! 4938: - yyn = yypact[*yyps]; ! 4939: - /* the current yyps has no shift onn "error", pop stack */ ! 4940: -#ifdef YYDEBUG ! 4941: - if( yydebug ) printf( "error recovery pops state %d, uncovers %d\n", *yyps, yyps[-1] ); ! 4942: -#endif ! 4943: - --yyps; ! 4944: - --yypv; ! 4945: - } ! 4946: - /* there is no state on the stack with an error shift ... abort */ ! 4947: -yyabort: ! 4948: - return(1); ! 4949: - case 3: /* no shift yet; clobber input char */ ! 4950: -#ifdef YYDEBUG ! 4951: - if( yydebug ) { ! 4952: - printf("error recovery discards "); ! 4953: - if(yytoknames[yychar]) ! 4954: - printf("%s\n", yytoknames[yychar]); ! 4955: - else if(yychar >= ' ' && yychar < '\177') ! 4956: - printf("`%c'\n", yychar); ! 4957: - else if(yychar == 0) ! 4958: - printf("EOF\n"); ! 4959: - else ! 4960: - printf("char 0%o\n", yychar); ! 4961: - } ! 4962: -#endif ! 4963: - if( yychar == 0 ) goto yyabort; /* don't discard EOF, quit */ ! 4964: - yychar = -1; ! 4965: - goto yynewstate; /* try again in the same state */ ! 4966: - } ! 4967: - } ! 4968: - /* reduction by production yyn */ ! 4969: -#ifdef YYDEBUG ! 4970: - if(yydebug) { char *s; ! 4971: - printf("reduce %d in:\n\t", yyn); ! 4972: - for(s = yystates[yystate]; *s; s++) { ! 4973: - putchar(*s); ! 4974: - if(*s == '\n' && *(s+1)) ! 4975: - putchar('\t'); ! 4976: - } ! 4977: - } ! 4978: -#endif ! 4979: - yyps -= yyr2[yyn]; ! 4980: - yypvt = yypv; ! 4981: - yypv -= yyr2[yyn]; ! 4982: - yyval = yypv[1]; ! 4983: - yym=yyn; ! 4984: - /* consult goto table to find next state */ ! 4985: - yyn = yyr1[yyn]; ! 4986: - yyj = yypgo[yyn] + *yyps + 1; ! 4987: - if( yyj>=YYLAST || yychk[ yystate = yyact[yyj] ] != -yyn ) yystate = yyact[yypgo[yyn]]; ! 4988: - switch(yym){ ! 4989: - ! 4990: -case 1: ! 4991: -# line 42 "twig.y" ! 4992: - ! 4993: - { if (nerrors==0) machine_build(); } break; ! 4994: -case 4: ! 4995: -# line 48 "twig.y" ! 4996: - { SymbolEnterList (yypvt[-1].y_symp, A_NODE); } break; ! 4997: -case 5: ! 4998: -# line 51 "twig.y" ! 4999: - { ! 5000: - SymbolEnterList(yypvt[-1].y_symp, A_NODE); ! 5001: - SymbolCheckNodeValues(); ! 5002: - } break; ! 5003: -case 6: ! 5004: -# line 56 "twig.y" ! 5005: - { SymbolEnterList (yypvt[-1].y_symp, A_CONST); } break; ! 5006: -case 7: ! 5007: -# line 58 "twig.y" ! 5008: - { SymbolEnterList (yypvt[-1].y_symp, A_LABEL); } break; ! 5009: -case 8: ! 5010: -# line 60 "twig.y" ! 5011: - { CodeWrite(outfile, yypvt[-1].y_code); CodeFreeBlock(yypvt[-1].y_code); } break; ! 5012: -case 9: ! 5013: -# line 63 "twig.y" ! 5014: - { yypvt[-2].y_symp->sd.ca.code = yypvt[-1].y_code; yypvt[-2].y_symp->sd.ca.assoc = NULL; ! 5015: - SymbolEnter (yypvt[-2].y_symp, A_COST); } break; ! 5016: -case 10: ! 5017: -# line 67 "twig.y" ! 5018: - { yypvt[-2].y_symp->sd.ca.code = yypvt[-1].y_code; yypvt[-2].y_symp->sd.ca.assoc = NULL; ! 5019: - SymbolEnter (yypvt[-2].y_symp, A_ACTION); } break; ! 5020: -case 14: ! 5021: -# line 83 "twig.y" ! 5022: - { ! 5023: - if(CheckIsUndefined(yypvt[-0].y_symp)) { ! 5024: - yypvt[-0].y_symp->next = yypvt[-1].y_symp; ! 5025: - yyval.y_symp = yypvt[-0].y_symp; ! 5026: - } else yyval.y_symp = yypvt[-1].y_symp; ! 5027: - } break; ! 5028: -case 15: ! 5029: -# line 89 "twig.y" ! 5030: -{ if(CheckIsUndefined(yypvt[-0].y_symp)) yyval.y_symp = yypvt[-0].y_symp; else yyval.y_symp = NULL; } break; ! 5031: -case 17: ! 5032: -# line 97 "twig.y" ! 5033: - { ! 5034: - if(yypvt[-0].y_symp->attr==A_ERROR) ! 5035: - yyval.y_symp = yypvt[-1].y_symp; ! 5036: - else { yypvt[-0].y_symp->next = yypvt[-1].y_symp; yyval.y_symp = yypvt[-0].y_symp; } ! 5037: - } break; ! 5038: -case 18: ! 5039: -# line 102 "twig.y" ! 5040: -{ yyval.y_symp = yypvt[-0].y_symp->attr==A_ERROR ? NULL : yypvt[-0].y_symp; } break; ! 5041: -case 20: ! 5042: -# line 106 "twig.y" ! 5043: - { ! 5044: - if(yypvt[-0].y_symp->attr==A_ERROR) yyval.y_symp = yypvt[-1].y_symp; ! 5045: - else { yypvt[-0].y_symp->next = yypvt[-1].y_symp; yyval.y_symp = yypvt[-0].y_symp; } ! 5046: - } break; ! 5047: -case 21: ! 5048: -# line 110 "twig.y" ! 5049: -{ yyval.y_symp = yypvt[-0].y_symp->attr==A_ERROR ? NULL : yypvt[-0].y_symp; } break; ! 5050: -case 23: ! 5051: -# line 114 "twig.y" ! 5052: - { ! 5053: - if (CheckIsUndefined(yypvt[-1].y_symp)) { ! 5054: - yypvt[-1].y_symp->sd.arity = yypvt[-0].y_int; yyval.y_symp = yypvt[-1].y_symp; ! 5055: - } else yyval.y_symp = &ErrorSymbol; ! 5056: - } break; ! 5057: -case 24: ! 5058: -# line 121 "twig.y" ! 5059: -{ ! 5060: - if(CheckIsUndefined(yypvt[-3].y_symp)) { ! 5061: - yypvt[-3].y_symp->unique = yypvt[-0].y_int; yypvt[-3].y_symp->sd.arity = yypvt[-2].y_int; ! 5062: - yyval.y_symp = yypvt[-3].y_symp; ! 5063: - } else yyval.y_symp = &ErrorSymbol; ! 5064: - } break; ! 5065: -case 25: ! 5066: -# line 129 "twig.y" ! 5067: - { yyval.y_int = yypvt[-1].y_int; } break; ! 5068: -case 26: ! 5069: -# line 130 "twig.y" ! 5070: - { yyval.y_int=GIVENUP; } break; ! 5071: -case 27: ! 5072: -# line 131 "twig.y" ! 5073: - { yyval.y_int = UNDEFINED; } break; ! 5074: -case 28: ! 5075: -# line 134 "twig.y" ! 5076: - { ! 5077: - if (yypvt[-0].y_symp->attr==A_ERROR) yyval.y_symp = yypvt[-1].y_symp; ! 5078: - else { yypvt[-0].y_symp->next = yypvt[-1].y_symp; yyval.y_symp = yypvt[-0].y_symp; } ! 5079: - } break; ! 5080: -case 29: ! 5081: -# line 138 "twig.y" ! 5082: -{ yyval.y_symp = yypvt[-0].y_symp->attr==A_ERROR ? NULL : yypvt[-0].y_symp; } break; ! 5083: -case 31: ! 5084: -# line 142 "twig.y" ! 5085: - { ! 5086: - if(CheckIsUndefined(yypvt[-2].y_symp)) { ! 5087: - yypvt[-2].y_symp->sd.cvalue = yypvt[-0].y_int; yyval.y_symp = yypvt[-2].y_symp; ! 5088: - } else yyval.y_symp = &ErrorSymbol; ! 5089: - } break; ! 5090: -case 33: ! 5091: -# line 150 "twig.y" ! 5092: - { ! 5093: - if(!CheckIsDefined(yypvt[-0].y_symp)) yyval.y_int = UNDEFINED; ! 5094: - else if(yypvt[-0].y_symp->attr!=A_CONST) { ! 5095: - sem_error("non-constant id used"); ! 5096: - yyval.y_int = -1; ! 5097: - } else yyval.y_int = yypvt[-0].y_symp->sd.cvalue; ! 5098: - } break; ! 5099: -case 38: ! 5100: -# line 164 "twig.y" ! 5101: - { epilogue = CodeAppend(epilogue, yypvt[-1].y_code); } break; ! 5102: -case 40: ! 5103: -# line 169 "twig.y" ! 5104: - { ! 5105: - if (yypvt[-5].y_symp->attr==A_ERROR) { ! 5106: - error(0, "\"label: tree\" pair ignored"); ! 5107: - TreeFree(yypvt[-3].y_nodep); ! 5108: - } else { ! 5109: - if(nerrors==0) ! 5110: - cgotofn(SymbolEnterTreeIntoLabel(yypvt[-5].y_symp, ! 5111: - yypvt[-3].y_nodep, yypvt[-2].y_symp, yypvt[-1].y_symp, tree_lineno)); ! 5112: - if(debug_flag&DB_TREE) ! 5113: - TreePrint(yypvt[-3].y_nodep, 1); ! 5114: - } ! 5115: - } break; ! 5116: -case 42: ! 5117: -# line 183 "twig.y" ! 5118: -{ SymbolEntry *sp = SymbolAllocate (SymbolGenUnique()); ! 5119: - sp->sd.ca.code = yypvt[-0].y_code; sp->sd.ca.assoc = NULL; ! 5120: - SymbolEnter(sp, A_ACTION); yyval.y_symp = sp; } break; ! 5121: -case 43: ! 5122: -# line 186 "twig.y" ! 5123: -{ if(CheckIsDefined(yypvt[-0].y_symp)) { ! 5124: - if (yypvt[-0].y_symp->attr!=A_ACTION) { ! 5125: - sem_error ("non action id: %s", yypvt[-0].y_symp->name); ! 5126: - yyval.y_symp = &ErrorSymbol; ! 5127: - } else yyval.y_symp = yypvt[-0].y_symp; ! 5128: - } else yyval.y_symp = &ErrorSymbol; } break; ! 5129: -case 44: ! 5130: -# line 192 "twig.y" ! 5131: -{ yyval.y_symp = NULL;} break; ! 5132: -case 45: ! 5133: -# line 194 "twig.y" ! 5134: -{ SymbolEntry *sp = SymbolAllocate (SymbolGenUnique()); ! 5135: - sp->sd.ca.code = yypvt[-0].y_code; sp->sd.ca.assoc = NULL; ! 5136: - SymbolEnter (sp, A_COST); yyval.y_symp = sp; ! 5137: - } break; ! 5138: -case 46: ! 5139: -# line 198 "twig.y" ! 5140: -{ if (CheckIsDefined(yypvt[-0].y_symp)) { ! 5141: - if (yypvt[-0].y_symp->attr!=A_COST) { ! 5142: - sem_error ("non cost id: %s", yypvt[-0].y_symp->name); ! 5143: - yyval.y_symp = &ErrorSymbol; ! 5144: - } else yyval.y_symp = yypvt[-0].y_symp; ! 5145: - } else yyval.y_symp = &ErrorSymbol; } break; ! 5146: -case 47: ! 5147: -# line 204 "twig.y" ! 5148: -{ yyval.y_symp = NULL; } break; ! 5149: -case 48: ! 5150: -# line 207 "twig.y" ! 5151: - { ! 5152: - tree_lineno = yyline; /* record line no */ ! 5153: - if(!CheckIsDefined(yypvt[-0].y_symp)) ! 5154: - yypvt[-0].y_symp->attr = A_ERROR; ! 5155: - else if(!is_label(yypvt[-0].y_symp)) { ! 5156: - sem_error("non label id: %s", yypvt[-0].y_symp->name); ! 5157: - yypvt[-0].y_symp->attr = A_ERROR; ! 5158: - } ! 5159: - yyval.y_symp = yypvt[-0].y_symp; ! 5160: - } break; ! 5161: -case 49: ! 5162: -# line 218 "twig.y" ! 5163: -{CheckIsNodeOrPred(yypvt[-0].y_symp);} break; ! 5164: -case 50: ! 5165: -# line 219 "twig.y" ! 5166: - { ! 5167: - int count; ! 5168: - Node *ap; ! 5169: - /* check the arity of the node */ ! 5170: - for(count=0, ap = yypvt[-1].y_nodep; ap!=NULL; ap=ap->siblings) count++; ! 5171: - switch(yypvt[-4].y_symp->attr) { ! 5172: - case A_NODE: ! 5173: - set_arity(yypvt[-4].y_symp, &yypvt[-4].y_symp->sd.arity, count); ! 5174: - break; ! 5175: - } ! 5176: - ! 5177: - yyval.y_nodep = TreeBuild (yypvt[-4].y_symp, yypvt[-1].y_nodep); ! 5178: - } break; ! 5179: -case 51: ! 5180: -# line 233 "twig.y" ! 5181: - { ! 5182: - CheckIsDefined(yypvt[-0].y_symp); ! 5183: - switch (yypvt[-0].y_symp->attr) { ! 5184: - case A_NODE: ! 5185: - set_arity(yypvt[-0].y_symp, &yypvt[-0].y_symp->sd.arity, 0); ! 5186: - break; ! 5187: - } ! 5188: - yyval.y_nodep = TreeBuild (yypvt[-0].y_symp, NULL); ! 5189: - } break; ! 5190: -case 52: ! 5191: -# line 243 "twig.y" ! 5192: - { ! 5193: - /* ! 5194: - * build sibling list in reverse order TreeBuild will ! 5195: - * put it right later. ! 5196: - */ ! 5197: - yypvt[-0].y_nodep->siblings = yypvt[-2].y_nodep; ! 5198: - yyval.y_nodep = yypvt[-0].y_nodep; ! 5199: - } break; ! 5200: -case 53: ! 5201: -# line 251 "twig.y" ! 5202: - { yypvt[-0].y_nodep->siblings = NULL; yyval.y_nodep = yypvt[-0].y_nodep; } break; ! 5203: -case 54: ! 5204: -# line 252 "twig.y" ! 5205: -{ yyval.y_nodep = NULL; } break; ! 5206: - } ! 5207: - goto yystack; /* stack new state and value */ ! 5208: -} ! 5209: //GO.SYSIN DD y.tab.c ! 5210: echo y.tab.h 1>&2 ! 5211: sed 's/.//' >y.tab.h <<'//GO.SYSIN DD y.tab.h' ! 5212: -# define ERROR 257 ! 5213: - ! 5214: -typedef union { ! 5215: - Node *y_nodep; ! 5216: - SymbolEntry *y_symp; ! 5217: - Code *y_code; ! 5218: - int y_int; ! 5219: -} YYSTYPE; ! 5220: -extern YYSTYPE yylval; ! 5221: -# define K_NODE 258 ! 5222: -# define K_LABEL 259 ! 5223: -# define K_PROLOGUE 260 ! 5224: -# define K_CONST 261 ! 5225: -# define K_INSERT 262 ! 5226: -# define K_COST 263 ! 5227: -# define K_ACTION 264 ! 5228: -# define ID 265 ! 5229: -# define NUMBER 266 ! 5230: -# define CBLOCK 267 ! 5231: //GO.SYSIN DD y.tab.h
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.