|
|
1.1 root 1: /*
2: * Symbol manipulation routines
3: */
4: #include "common.h"
5: #include "code.h"
6: #include "sym.h"
7: #include "machine.h"
8: #include "y.tab.h"
9: #include "mem.h"
10:
11: #define SAFE 1 /* generates code to do redundant checks */
12: #define MAXSYMS 100
13: #define MAX_UNIQUE 255
14:
15: static void AppendToList();
16: typedef
17: struct SymbolList {
18: SymbolEntry *first, *last;
19: int count;
20: }
21: SymbolList;
22:
23: /*
24: * The range of the unique numbers assigned to each type of
25: * symbol is [min,max)
26: */
27: struct ranges {
28: int min,max;
29: int limit;
30: } uniques[] = {
31: {0, 0, MAX_UNIQUE}, /* A_UNDEFINED -- not used */
32: {0, 0, MAX_NODE_VALUE}, /* A_NODE */
33: {0, 0, MAX_UNIQUE}, /* A_LABEL */
34: {0, 0, MAX_UNIQUE}, /* A_COST */
35: {0, 0, MAX_UNIQUE}, /* A_ACTION */
36: };
37:
38: int treeIndex = 0;
39:
40: static SymbolList lists[] = {
41: { NULL, NULL, 0}, /* A_UNDEFINED -- never used */
42: { NULL, NULL, 0}, /* A_NODE */
43: { NULL, NULL, 0}, /* A_LABEL */
44: { NULL, NULL, 0}, /* A_COST */
45: { NULL, NULL, 0}, /* A_ACTION */
46: { NULL, NULL, 0}, /* A_CONST */
47: };
48:
49: struct _mem sym_mem, lab_mem, tree_mem;
50: SymbolEntry *hash_table[HASHSIZE];
51: SymbolEntry *startSymbol;
52:
53: static int
54: RawHash(s)
55: register char *s;
56: {
57: register int sum = 0;
58: register int i = 0;
59: while(*s)
60: sum += (++i)*(0377&*s++);
61: return(sum);
62: }
63:
64:
65: /*
66: * Allocate a new symbol_entry structure for the given structure and
67: * return it. There is no check of whether the symbol is already defined or
68: * not. The caller is expected to fill in the uninitialized fields.
69: */
70: SymbolEntry *
71: SymbolAllocate(s)
72: char *s;
73: {
74: SymbolEntry *sp;
75: sp = (SymbolEntry *) mem_get(&sym_mem);
76: assert(sp!=NULL);
77:
78: #ifdef SAFE
79: assert (SymbolLookup(s) == NULL);
80: #endif
81:
82: sp->name = malloc(strlen(s)+1);
83: assert(sp->name!=NULL);
84: strcpy (sp->name, s);
85: sp->hash = RawHash(s);
86: sp->next = NULL;
87: sp->attr = A_UNDEFINED;
88: sp->unique = -1;
89: return(sp);
90: }
91:
92: void
93: SymbolFree (symp)
94: SymbolEntry *symp;
95: {
96: assert (symp->next == NULL);
97: free(symp);
98: }
99:
100: SymbolEntry *
101: SymbolLookup(s)
102: char *s;
103: {
104: int hash_value = RawHash(s);
105: register SymbolEntry * hp = hash_table[hash_value%HASHSIZE];
106:
107: while(hp!=NULL) {
108: if(hp->hash == hash_value &&
109: strcmp (s, hp->name)==0) break;
110: hp = hp->next;
111: }
112: return(hp);
113: }
114:
115: /*
116: * enter the symbol into the symbol table. It believes everything in the
117: * symp argument.
118: */
119: void
120: SymbolEnter (symp, attr)
121: SymbolEntry *symp;
122: byte attr;
123: {
124: struct symbol_entry *hp;
125:
126: #ifdef SAFE
127: assert (symp!=NULL);
128: assert (symp->hash == RawHash(symp->name));
129: assert (symp->attr == A_UNDEFINED);
130: #endif
131:
132: hp = hash_table[symp->hash%HASHSIZE];
133: symp->next = hp;
134: hash_table[symp->hash%HASHSIZE] = symp;
135: symp->attr = attr;
136: if (HAS_UNIQUE(attr)){
137: struct ranges *rp = &uniques[attr];
138: int new_unique;
139: if(symp->unique==-1)
140: symp->unique = new_unique = rp->max++;
141: else {
142: new_unique = symp->unique;
143: if(new_unique>=rp->max)
144: rp->max = new_unique+1;
145: else if(new_unique < rp->min)
146: rp->min = new_unique;
147: }
148: if(new_unique>rp->limit)
149: sem_error("number assigned to %s (%d) out of range",
150: symp->name, new_unique);
151: if(new_unique<0)
152: sem_error("number assigned to %s (%d) is negative",
153: symp->name, new_unique);
154: assert(rp->max>=rp->min);
155: }
156: if (HAS_LIST(attr)) {
157: AppendToList(&lists[attr], symp);
158: }
159: }
160:
161: static void
162: AppendToList(list, sp)
163: SymbolList *list;
164: SymbolEntry *sp;
165: {
166: sp->link = NULL;
167: if(list->first==NULL)
168: list->first = sp;
169: else (list->last)->link = sp;
170: list->last = sp;
171: list->count++;
172: }
173:
174: SymbolCheckNodeValues()
175: {
176: SymbolList *slist;
177: SymbolEntry **stab, **spp, *sp;
178: struct ranges *rp;
179: int i, range;
180:
181: rp = &uniques[A_NODE];
182: slist = &lists[A_NODE];
183: range = rp->max - rp->min + 1;
184: stab = (SymbolEntry **) malloc(range*sizeof(SymbolEntry *));
185:
186: for(i=range, spp = stab; i-->0; spp++) *spp = NULL;
187:
188: for(sp = slist->first; sp; sp = sp->link) {
189: SymbolEntry *sp2 = stab[sp->unique];
190: if(sp2==NULL)
191: stab[sp->unique] = sp;
192: else
193: sem_error("%s and %s have the same node value",
194: sp2->name, sp->name);
195: }
196: free(stab);
197: }
198:
199: SymbolEntry *
200: SymbolEnterKeyword(s, value)
201: char *s;
202: int value;
203: {
204: SymbolEntry *sp = SymbolAllocate(s);
205: sp->sd.keyword = value;
206: SymbolEnter (sp, A_KEYWORD);
207: return(sp);
208: }
209:
210: void
211: SymbolInit()
212: {
213: SymbolEntry *sp;
214:
215: mem_init(&sym_mem,sizeof(SymbolEntry));
216: mem_init(&lab_mem,sizeof(LabelData));
217: mem_init(&tree_mem,sizeof(struct treeassoc));
218: SymbolEnterKeyword ("node", K_NODE);
219: SymbolEnterKeyword ("label", K_LABEL);
220: SymbolEnterKeyword ("prologue", K_PROLOGUE);
221: SymbolEnterKeyword ("const", K_CONST);
222: SymbolEnterKeyword ("insert", K_INSERT);
223: SymbolEnterKeyword ("cost", K_COST);
224: SymbolEnterKeyword ("action", K_ACTION);
225: }
226:
227: void
228: SymbolMap(f)
229: int (*f)();
230: {
231: SymbolEntry **spp, *sp;
232: for(spp = hash_table; spp < &hash_table[HASHSIZE]; spp++)
233: for(sp= *spp; sp!=NULL; sp = sp->next)
234: f(sp);
235: };
236:
237: static int symcnt, labcnt, nodecnt;
238: static
239: sym_count(sp)
240: SymbolEntry *sp;
241: {
242: symcnt++;
243: switch(sp->attr) {
244: case A_LABEL: {
245: LabelData *lp;
246: for(lp = sp->sd.lp;lp!=NULL;lp=lp->next) {
247: labcnt++;
248: nodecnt += cntnodes(lp->tree);
249: }
250: } break;
251: }
252: }
253:
254: void
255: SymbolFinish()
256: {
257: if(DB_MEM&debug_flag) {
258: extern struct _mem node_mem;
259: int symout = mem_outstanding(&sym_mem);
260: int labout = mem_outstanding(&lab_mem);
261: int nodeout = mem_outstanding(&node_mem);
262: SymbolMap(sym_count);
263: fprintf(stderr,"symbols defined=%d out=%d\n",symcnt, symout);
264: fprintf(stderr,"labdata def=%d out=%d\n",labcnt,labout);
265: fprintf(stderr,"node def=%d out=%d\n",nodecnt,nodeout);
266: assert(symcnt==symout);
267: assert(labcnt==labout);
268: assert(nodecnt==nodeout);
269: }
270: }
271:
272: void
273: SymbolEnterList (symp, attr)
274: SymbolEntry *symp;
275: int attr;
276: {
277: /*
278: * enter in reverse order because the list was built in reverse
279: * order by the parser
280: */
281:
282: if(symp==NULL)
283: return;
284: SymbolEnterList(symp->next, attr);
285: if(symp->attr!=A_UNDEFINED)
286: sem_error ("multiple declaration ignored: %s", symp->name);
287: SymbolEnter (symp, attr);
288: }
289:
290: LabelData *
291: SymbolEnterTreeIntoLabel(symp, tree, costfunc, action, lineno)
292: SymbolEntry *symp, *action, *costfunc;
293: struct node *tree;
294: int lineno;
295: {
296: LabelData *tp = (LabelData *) mem_get(&lab_mem);
297: struct treeassoc *ap;
298:
299: if (symp==&ErrorSymbol) return(NULL);
300: #ifdef SAFE
301: assert (tp!=NULL);
302: assert (symp->attr==A_LABEL);
303: #endif
304:
305: tp->tree = tree;
306: tp->treeIndex = treeIndex++;
307: tp->lineno = lineno;
308: tp->next = symp->sd.lp;
309: tp->label = symp;
310: symp->sd.lp = tp;
311:
312: if (action!=NULL) {
313: ap = (struct treeassoc *) mem_get(&tree_mem);
314: ap->tree = tp->treeIndex;
315: ap->next = action->sd.ca.assoc;
316: action->sd.ca.assoc = ap;
317: }
318:
319: if (costfunc!=NULL) {
320: ap = (struct treeassoc *) mem_get(&tree_mem);
321: ap->tree = tp->treeIndex;
322: ap->next = costfunc->sd.ca.assoc;
323: costfunc->sd.ca.assoc = ap;
324: }
325: return(tp);
326: }
327:
328: static void
329: WriteSymbols(sp, mask)
330: SymbolEntry *sp;
331: int mask;
332: {
333: for(;sp!=NULL; sp = sp->link)
334: fprintf(symfile, "#define %s\t0%o\n", sp->name, sp->unique|mask);
335: }
336:
337: void
338: SymbolDump()
339: {
340: WriteSymbols(lists[A_NODE].first, M_NODE);
341: WriteSymbols(lists[A_LABEL].first, 0);
342: WriteSymbols(lists[A_CONST].first, 0);
343: fprintf(symfile, "#define MAXLABELS %d\n", uniques[A_LABEL].max);
344: fprintf(symfile, "#define MAXTREES %d\n", treeIndex);
345: fprintf(symfile, "#define MAXNDVAL %d\n", uniques[A_NODE].max);
346: }
347:
348: void
349: SymbolGenerateWalkerCode()
350: {
351: register SymbolEntry *pp;
352: int i;
353: extern int line_xref_flag;
354: struct treeassoc *tap;
355: register LabelData *lp;
356: register short int *mapTab;
357:
358: /*
359: * Write out the table of tree index to label correspondence
360: */
361: mapTab = (short int *) malloc (treeIndex * sizeof(short int));
362: for(pp=lists[A_LABEL].first; pp!=NULL; pp=pp->link) {
363: lp = pp->sd.lp;
364: if(lp==NULL)
365: sem_error2("%s undefined\n", pp->name);
366: for(;lp!=NULL;lp=lp->next)
367: mapTab[lp->treeIndex] = pp->unique;
368: }
369: fputs("short int mtMap[] = {\n", outfile);
370: for(i=0, oreset(); i < treeIndex;)
371: oputoct(mapTab[i++]);
372: fputs("};\n", outfile);
373:
374: /* generate tree to line index table */
375: if(line_xref_flag) {
376: for(pp=lists[A_LABEL].first; pp!=NULL; pp=pp->link) {
377: lp = pp->sd.lp;
378: for(;lp!=NULL;lp=lp->next)
379: mapTab[lp->treeIndex] = lp->lineno;
380: }
381: fputs("short int mtLine[] = {\n", outfile);
382: for(i=0, oreset(); i<treeIndex;)
383: oputint(mapTab[i++]);
384: fputs("};\n", outfile);
385: }
386: /*
387: * Generate path table
388: */
389: fputs ("short int mtPaths[] = {\n", outfile);
390: for(pp=lists[A_LABEL].first, oreset(); pp!=NULL; pp=pp->link) {
391: lp = pp->sd.lp;
392: if(lp==NULL)
393: sem_error2("%s undefined\n", pp->name);
394: do {
395: mapTab[lp->treeIndex] = ointcnt();
396: oputint (lp->tree->nlleaves);
397: SymbolWritePath (lp->tree);
398: oputint (eSTOP);
399: lp = lp->next;
400: } while (lp!=NULL);
401: }
402: fputs(" };\nshort int mtPathStart[] = {\n", outfile);
403: for(i=0, oreset(); i < treeIndex;)
404: oputint (mapTab[i++]);
405: fputs("};\n", outfile);
406:
407: /*
408: * Code to perform the action of the trees
409: */
410: fputs("NODEPTR\nmtAction (_t, _ll, _s)\n", outfile);
411: fputs("int _t; __match **_ll; skeleton *_s;\n", outfile);
412: fputs("{ NODEPTR root = _s->root;\n", outfile);
413: fputs("switch (_t) {\n", outfile);
414: for (pp=lists[A_ACTION].first; pp!=NULL; pp=pp->link) {
415: if ((tap=pp->sd.ca.assoc)==NULL) {
416: sem_error2 ("%s not used", pp->name);
417: continue;
418: }
419: for (; tap!=NULL; tap=tap->next)
420: fprintf (outfile, "case %d:", tap->tree);
421: fputs ("{\n", outfile);
422: CodeWrite (outfile, pp->sd.ca.code);
423: fputs("} break;\n", outfile);
424: }
425: fputs("} return(_s->root);}\n", outfile);
426:
427: fputs ("mtEvalCost(_m, _ll, _s)\n", outfile);
428: fputs ("__match **_ll; __match *_m; skeleton *_s;\n", outfile);
429: fputs ("{ NODEPTR root = _s->root;\n", outfile);
430: fputs ("COST cost; cost = DEFAULT_COST;\n", outfile);
431: fputs ("switch(_m->tree) {\n", outfile);
432: for(pp=lists[A_COST].first; pp!=NULL; pp=pp->link) {
433: if ((tap=pp->sd.ca.assoc)==NULL) {
434: sem_error2 ("%s not used", pp->name);
435: continue;
436: }
437: for (; tap!=NULL; tap=tap->next)
438: fprintf (outfile, "case %d:", tap->tree);
439: fputs ("{\n", outfile);
440: CodeWrite (outfile, pp->sd.ca.code);
441: fputs ("} break;\n", outfile);
442: }
443: fputs("}\n", outfile);
444: fputs("_m->cost = cost; return(xDEFER);}\n", outfile);
445:
446: }
447:
448: SymbolWritePath (root)
449: Node *root;
450: {
451: Node *np;
452: if(root->nlleaves==0)
453: return;
454: if((root->sym)->attr==A_LABEL) {
455: oputint (eEVAL); oputoct (MV_LABEL((root->sym)->unique));
456: return;
457: }
458: oputint (ePUSH);
459: for(np = root->children;;) {
460: if(np->nlleaves > 0)
461: SymbolWritePath (np);
462: if ((np = np->siblings) == NULL)
463: break;
464: oputint (eNEXT);
465: }
466: oputint (ePOP);
467: return;
468: }
469:
470: static int gensymndx = 0;
471:
472: char *
473: SymbolGenUnique()
474: {
475: static char name[7];
476: name[0] = '$';
477: sprintf (&name[1], "%05d", gensymndx++);
478: return (name);
479: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.