|
|
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.