Updated from files in llvm/autoconf. This was done immediently following
[oota-llvm.git] / utils / Burg / plank.c
1 char rcsid_plank[] = "$Id$";
2
3 #include <stdio.h>
4 #include <string.h>
5 #include <stdlib.h>
6 #include "b.h"
7 #include "fe.h"
8
9 #define ERROR_VAL 0
10
11 int speedflag = 0;
12
13 Item_Set *sortedStates;
14 static struct stateMapTable smt;
15 int exceptionTolerance = 0;
16 static int plankSize = 32;
17
18 static Plank newPlank ARGS((void));
19 static PlankMap newPlankMap ARGS((int));
20 static StateMap newStateMap ARGS((void));
21 static Exception newException ARGS((int, int));
22 static void enterStateMap ARGS((PlankMap, short *, int, int *));
23 static List assemblePlanks ARGS((void));
24 static void assignRules ARGS((RuleAST));
25 static int stateCompare ARGS((Item_Set *, Item_Set *));
26 static int ruleCompare ARGS((RuleAST *, RuleAST *));
27 static void renumber ARGS((void));
28 static short * newVector ARGS((void));
29 static int width ARGS((int));
30 static PlankMap mapToPmap ARGS((Dimension));
31 static void doDimPmaps ARGS((Operator));
32 static void doNonTermPmaps ARGS((NonTerminal));
33 static void makePmaps ARGS((void));
34 static void outPlank ARGS((Plank));
35 static void purgePlanks ARGS((List));
36 static void inToEx ARGS((void));
37 static void makePlankRuleMacros ARGS((void));
38 static void makePlankRule ARGS((void));
39 static void exceptionSwitch ARGS((List, const char *, const char *, const char *, int, const char *));
40 static void doPlankLabel ARGS((Operator));
41 static void doPlankLabelSafely ARGS((Operator));
42 static void doPlankLabelMacrosSafely ARGS((Operator));
43 static void makePlankState ARGS((void));
44
45 static Plank
46 newPlank()
47 {
48         Plank p;
49         char buf[50];
50         static int num = 0;
51
52         p = (Plank) zalloc(sizeof(struct plank));
53         sprintf(buf, "%s_plank_%d", prefix, num++);
54         p->name = (char *) zalloc(strlen(buf)+1);
55         strcpy(p->name, buf);
56         return p;
57 }
58
59 static PlankMap
60 newPlankMap(offset) int offset;
61 {
62         PlankMap im;
63
64         im = (PlankMap) zalloc(sizeof(struct plankMap));
65         im->offset = offset;
66         return im;
67 }
68
69 static StateMap
70 newStateMap()
71 {
72         char buf[50];
73         static int num = 0;
74
75         StateMap sm;
76
77         sm = (StateMap) zalloc(sizeof(struct stateMap));
78         sprintf(buf, "f%d", num++);
79         sm->fieldname = (char *) zalloc(strlen(buf)+1);
80         strcpy(sm->fieldname, buf);
81         return sm;
82 }
83
84 static Exception
85 newException(index, value) int index; int value;
86 {
87         Exception e;
88
89         e = (Exception) zalloc(sizeof(struct except));
90         e->index = index;
91         e->value = value;
92         return e;
93 }
94
95 static void
96 enterStateMap(im, v, width, new) PlankMap im; short * v; int width; int *new;
97 {
98         int i;
99         StateMap sm;
100         List l;
101         int size;
102
103         assert(im);
104         assert(v);
105         assert(width > 0);
106         size = globalMap->count;
107
108         for (l = smt.maps; l; l = l->next) {
109                 int ecount;
110
111                 sm = (StateMap) l->x;
112                 ecount = 0;
113                 for (i = 0; i < size; i++) {
114                         if (v[i] != -1 && sm->value[i] != -1 && v[i] != sm->value[i]) {
115                                 if (++ecount > exceptionTolerance) {
116                                         goto again;
117                                 }
118                         }
119                 }
120                 for (i = 0; i < size; i++) {
121                         assert(v[i] >= 0);
122                         assert(sm->value[i] >= 0);
123                         if (v[i] == -1) {
124                                 continue;
125                         }
126                         if (sm->value[i] == -1) {
127                                 sm->value[i] = v[i];
128                         } else if (v[i] != sm->value[i]) {
129                                 im->exceptions = newList(newException(i,v[i]), im->exceptions);
130                         }
131                 }
132                 im->values = sm;
133                 if (width > sm->width) {
134                         sm->width = width;
135                 }
136                 *new = 0;
137                 return;
138         again: ;
139         }
140         sm = newStateMap();
141         im->values = sm;
142         sm->value = v;
143         sm->width = width;
144         *new = 1;
145         smt.maps = newList(sm, smt.maps);
146 }
147
148 static List
149 assemblePlanks()
150 {
151         List planks = 0;
152         Plank pl;
153         List p;
154         List s;
155
156         for (s = smt.maps; s; s = s->next) {
157                 StateMap sm = (StateMap) s->x;
158                 for (p = planks; p; p = p->next) {
159                         pl = (Plank) p->x;
160                         if (sm->width <= plankSize - pl->width) {
161                                 pl->width += sm->width;
162                                 pl->fields = newList(sm, pl->fields);
163                                 sm->plank = pl;
164                                 goto next;
165                         }
166                 }
167                 pl = newPlank();
168                 pl->width = sm->width;
169                 pl->fields = newList(sm, 0);
170                 sm->plank = pl;
171                 planks = appendList(pl, planks);
172         next: ;
173         }
174         return planks;
175 }
176
177 RuleAST *sortedRules;
178
179 static int count;
180
181 static void
182 assignRules(ast) RuleAST ast;
183 {
184         sortedRules[count++] = ast;
185 }
186
187 static int
188 stateCompare(s, t) Item_Set *s; Item_Set *t;
189 {
190         return strcmp((*s)->op->name, (*t)->op->name);
191 }
192
193 static int
194 ruleCompare(s, t) RuleAST *s; RuleAST *t;
195 {
196         return strcmp((*s)->lhs, (*t)->lhs);
197 }
198
199 void
200 dumpSortedStates()
201 {
202         int i;
203         
204         printf("dump Sorted States: ");
205         for (i = 0; i < globalMap->count; i++) {
206                 printf("%d ", sortedStates[i]->num);
207         }
208         printf("\n");
209 }
210
211 void
212 dumpSortedRules()
213 {
214         int i;
215         
216         printf("dump Sorted Rules: ");
217         for (i = 0; i < max_ruleAST; i++) {
218                 printf("%d ", sortedRules[i]->rule->erulenum);
219         }
220         printf("\n");
221 }
222
223 static void
224 renumber()
225 {
226         int i;
227         Operator previousOp;
228         NonTerminal previousLHS;
229         int base_counter;
230
231         sortedStates = (Item_Set*) zalloc(globalMap->count * sizeof(Item_Set));
232         for (i = 1; i < globalMap->count; i++) {
233                 sortedStates[i-1] = globalMap->set[i];
234         }
235         qsort(sortedStates, globalMap->count-1, sizeof(Item_Set), (int(*)(const void *, const void *))stateCompare);
236         previousOp = 0;
237         for (i = 0; i < globalMap->count-1; i++) {
238                 sortedStates[i]->newNum = i;
239                 sortedStates[i]->op->stateCount++;
240                 if (previousOp != sortedStates[i]->op) {
241                         sortedStates[i]->op->baseNum = i;
242                         previousOp = sortedStates[i]->op;
243                 }
244         }
245
246         sortedRules = (RuleAST*) zalloc(max_ruleAST * sizeof(RuleAST));
247         count = 0;
248         foreachList((ListFn) assignRules, ruleASTs);
249         qsort(sortedRules, max_ruleAST, sizeof(RuleAST), (int(*)(const void *, const void *))ruleCompare);
250         previousLHS = 0;
251         base_counter = 0;
252         for (i = 0; i < max_ruleAST; i++) {
253                 if (previousLHS != sortedRules[i]->rule->lhs) {
254                         sortedRules[i]->rule->lhs->baseNum = base_counter;
255                         previousLHS = sortedRules[i]->rule->lhs;
256                         base_counter++; /* make space for 0 */
257                 }
258                 sortedRules[i]->rule->newNum = base_counter;
259                 sortedRules[i]->rule->lhs->ruleCount++;
260                 sortedRules[i]->rule->lhs->sampleRule = sortedRules[i]->rule; /* kludge for diagnostics */
261                 base_counter++;
262         }
263 }
264
265 static short *
266 newVector()
267 {
268         short *p;
269         p = (short *) zalloc(globalMap->count* sizeof(short));
270         return p;
271 }
272
273 static int
274 width(v) int v;
275 {
276         int c;
277
278         for (c = 0; v; v >>= 1) {
279                 c++;
280         }
281         return c;
282
283 }
284
285 static PlankMap
286 mapToPmap(d) Dimension d;
287 {
288         PlankMap im;
289         short *v;
290         int i;
291         int new;
292
293         if (d->map->count == 1) {
294                 return 0;
295         }
296         assert(d->map->count > 1);
297         im = newPlankMap(0);
298         v = newVector();
299         for (i = 0; i < globalMap->count-1; i++) {
300                 int index = d->map->set[d->index_map.class[sortedStates[i]->num]->num]->num;
301                 assert(index >= 0);
302                 v[i+1] = index;
303         }
304         v[0] = 0;
305         enterStateMap(im, v, width(d->map->count), &new);
306         if (!new) {
307                 zfree(v);
308         }
309         return im;
310 }
311
312 static void
313 doDimPmaps(op) Operator op;
314 {
315         int i, j;
316         Dimension d;
317         short *v;
318         PlankMap im;
319         int new;
320
321         if (!op->table->rules) {
322                 return;
323         }
324         switch (op->arity) {
325         case 0:
326                 break;
327         case 1:
328                 d = op->table->dimen[0];
329                 if (d->map->count > 1) {
330                         v = newVector();
331                         im = newPlankMap(op->baseNum);
332                         for (i = 0; i < globalMap->count-1; i++) {
333                                 int index = d->map->set[d->index_map.class[sortedStates[i]->num]->num]->num;
334                                 if (index) {
335                                         Item_Set *ts = transLval(op->table, index, 0);
336                                         v[i+1] = (*ts)->newNum - op->baseNum+1;
337                                         assert(v[i+1] >= 0);
338                                 }
339                         }
340                         enterStateMap(im, v, width(d->map->count-1), &new);
341                         if (!new) {
342                                 zfree(v);
343                         }
344                         d->pmap = im;
345                 }
346                 break;
347         case 2:
348                 if (op->table->dimen[0]->map->count == 1 && op->table->dimen[1]->map->count == 1) {
349                         op->table->dimen[0]->pmap = 0;
350                         op->table->dimen[1]->pmap = 0;
351                 } else if (op->table->dimen[0]->map->count == 1) {
352                         v = newVector();
353                         im = newPlankMap(op->baseNum);
354                         d = op->table->dimen[1];
355                         for (i = 0; i < globalMap->count-1; i++) {
356                                 int index = d->map->set[d->index_map.class[sortedStates[i]->num]->num]->num;
357                                 if (index) {
358                                         Item_Set *ts = transLval(op->table, 1, index);
359                                         v[i+1] = (*ts)->newNum - op->baseNum+1;
360                                         assert(v[i+1] >= 0);
361                                 }
362                         }
363                         enterStateMap(im, v, width(d->map->count-1), &new);
364                         if (!new) {
365                                 zfree(v);
366                         }
367                         d->pmap = im;
368                 } else if (op->table->dimen[1]->map->count == 1) {
369                         v = newVector();
370                         im = newPlankMap(op->baseNum);
371                         d = op->table->dimen[0];
372                         for (i = 0; i < globalMap->count-1; i++) {
373                                 int index = d->map->set[d->index_map.class[sortedStates[i]->num]->num]->num;
374                                 if (index) {
375                                         Item_Set *ts = transLval(op->table, index, 1);
376                                         v[i +1] = (*ts)->newNum - op->baseNum +1;
377                                         assert(v[i +1] >= 0);
378                                 }
379                         }
380                         enterStateMap(im, v, width(d->map->count-1), &new);
381                         if (!new) {
382                                 zfree(v);
383                         }
384                         d->pmap = im;
385                 } else {
386                         op->table->dimen[0]->pmap = mapToPmap(op->table->dimen[0]);
387                         op->table->dimen[1]->pmap = mapToPmap(op->table->dimen[1]);
388                         /* output table */
389                         fprintf(outfile, "static unsigned %s %s_%s_transition[%d][%d] = {", 
390                                 op->stateCount <= 255 ? "char" : "short",
391                                 prefix,
392                                 op->name,
393                                 op->table->dimen[0]->map->count,
394                                 op->table->dimen[1]->map->count);
395                         for (i = 0; i < op->table->dimen[0]->map->count; i++) {
396                                 if (i > 0) {
397                                         fprintf(outfile, ",");
398                                 }
399                                 fprintf(outfile, "\n{");
400                                 for (j = 0; j < op->table->dimen[1]->map->count; j++) {
401                                         Item_Set *ts = transLval(op->table, i, j);
402                                         short diff;
403                                         if (j > 0) {
404                                                 fprintf(outfile, ",");
405                                                 if (j % 10 == 0) {
406                                                         fprintf(outfile, "\t/* row %d, cols %d-%d*/\n",
407                                                                 i,
408                                                                 j-10,
409                                                                 j-1);
410                                                 }
411                                         }
412                                         if ((*ts)->num > 0) {
413                                                 diff = (*ts)->newNum - op->baseNum +1;
414                                         } else {
415                                                 diff = 0;
416                                         }
417                                         fprintf(outfile, "%5d", diff);
418                                 }
419                                 fprintf(outfile, "}\t/* row %d */", i);
420                         }
421                         fprintf(outfile, "\n};\n");
422                 }
423                 break;
424         default:
425                 assert(0);
426         }
427 }
428
429 static NonTerminal *ntVector;
430
431 static void
432 doNonTermPmaps(n) NonTerminal n;
433 {
434         short *v;
435         PlankMap im;
436         int new;
437         int i;
438
439         ntVector[n->num] = n;
440         if (n->num >= last_user_nonterminal) {
441                 return;
442         }
443         if (n->ruleCount <= 0) {
444                 return;
445         }
446         im = newPlankMap(n->baseNum);
447         v = newVector();
448         for (i = 0; i < globalMap->count-1; i++) {
449                 Rule r = globalMap->set[sortedStates[i]->num]->closed[n->num].rule;
450                 if (r) {
451                         r->used = 1;
452                         v[i+1] = r->newNum - n->baseNum /*safely*/;
453                         assert(v[i+1] >= 0);
454                 }
455         }
456         enterStateMap(im, v, width(n->ruleCount+1), &new);
457         if (!new) {
458                 zfree(v);
459         }
460         n->pmap = im;
461 }
462
463 static void
464 makePmaps()
465 {
466         foreachList((ListFn) doDimPmaps, operators);
467         ntVector = (NonTerminal*) zalloc((max_nonterminal) * sizeof(NonTerminal));
468         foreachList((ListFn) doNonTermPmaps, nonterminals);
469 }
470
471 static void
472 outPlank(p) Plank p;
473 {
474         List f;
475         int i;
476
477         fprintf(outfile, "static struct {\n");
478
479         for (f = p->fields; f; f = f->next) {
480                 StateMap sm = (StateMap) f->x;
481                 fprintf(outfile, "\tunsigned int %s:%d;\n", sm->fieldname, sm->width);
482         }
483
484         fprintf(outfile, "} %s[] = {\n", p->name);
485
486         for (i = 0; i < globalMap->count; i++) {
487                 fprintf(outfile, "\t{");
488                 for (f = p->fields; f; f = f->next) {
489                         StateMap sm = (StateMap) f->x;
490                         fprintf(outfile, "%4d,", sm->value[i] == -1 ? ERROR_VAL : sm->value[i]);
491                 }
492                 fprintf(outfile, "},\t/* row %d */\n", i);
493         }
494
495         fprintf(outfile, "};\n");
496 }
497
498 static void
499 purgePlanks(planks) List planks;
500 {
501         List p;
502
503         for (p = planks; p; p = p->next) {
504                 Plank x = (Plank) p->x;
505                 outPlank(x);
506         }
507 }
508
509 static void
510 inToEx()
511 {
512         int i;
513         int counter;
514
515         fprintf(outfile, "static short %s_eruleMap[] = {\n", prefix);
516         counter = 0;
517         for (i = 0; i < max_ruleAST; i++) {
518                 if (counter > 0) {
519                         fprintf(outfile, ",");
520                         if (counter % 10 == 0) {
521                                 fprintf(outfile, "\t/* %d-%d */\n", counter-10, counter-1);
522                         }
523                 }
524                 if (counter < sortedRules[i]->rule->newNum) {
525                         assert(counter == sortedRules[i]->rule->newNum-1);
526                         fprintf(outfile, "%5d", 0);
527                         counter++;
528                         if (counter > 0) {
529                                 fprintf(outfile, ",");
530                                 if (counter % 10 == 0) {
531                                         fprintf(outfile, "\t/* %d-%d */\n", counter-10, counter-1);
532                                 }
533                         }
534                 }
535                 fprintf(outfile, "%5d", sortedRules[i]->rule->erulenum);
536                 counter++;
537         }
538         fprintf(outfile, "\n};\n");
539 }
540
541 static void
542 makePlankRuleMacros()
543 {
544         int i;
545
546         for (i = 1; i < last_user_nonterminal; i++) {
547                 List es;
548                 PlankMap im = ntVector[i]->pmap;
549                 fprintf(outfile, "#define %s_%s_rule(state)\t", prefix, ntVector[i]->name);
550                 if (im) {
551                         fprintf(outfile, "%s_eruleMap[", prefix);
552                         for (es = im->exceptions; es; es = es->next) {
553                                 Exception e = (Exception) es->x;
554                                 fprintf(outfile, "((state) == %d ? %d :", 
555                                                 e->index, e->value);
556                         }
557                         fprintf(outfile, "%s[state].%s", 
558                                 im->values->plank->name, 
559                                 im->values->fieldname);
560                         for (es = im->exceptions; es; es = es->next) {
561                                 fprintf(outfile, ")");
562                         }
563                         fprintf(outfile, " +%d]", im->offset);
564
565                 } else {
566                         /* nonterminal never appears on LHS. */
567                         assert(ntVector[i] ==  start);
568                         fprintf(outfile, "0");
569                 }
570                 fprintf(outfile, "\n");
571         }
572         fprintf(outfile, "\n");
573 }
574
575 static void
576 makePlankRule()
577 {
578         int i;
579
580         makePlankRuleMacros();
581
582         fprintf(outfile, "#ifdef __STDC__\n");
583         fprintf(outfile, "int %s_rule(int state, int goalnt) {\n", prefix);
584         fprintf(outfile, "#else\n");
585         fprintf(outfile, "int %s_rule(state, goalnt) int state; int goalnt; {\n", prefix);
586         fprintf(outfile, "#endif\n");
587
588         fprintf(outfile, 
589         "\t%s_assert(state >= 0 && state < %d, %s_PANIC(\"Bad state %%d passed to %s_rule\\n\", state));\n",
590                                 prefix, globalMap->count, prefix, prefix);
591         fprintf(outfile, "\tswitch(goalnt) {\n");
592
593         for (i = 1; i < last_user_nonterminal; i++) {
594                 fprintf(outfile, "\tcase %d:\n", i);
595                 fprintf(outfile, "\t\treturn %s_%s_rule(state);\n", prefix, ntVector[i]->name);
596         }
597         fprintf(outfile, "\tdefault:\n");
598         fprintf(outfile, "\t\t%s_PANIC(\"Unknown nonterminal %%d in %s_rule;\\n\", goalnt);\n", prefix, prefix);
599         fprintf(outfile, "\t\tabort();\n");
600         fprintf(outfile, "\t\treturn 0;\n");
601         fprintf(outfile, "\t}\n");
602         fprintf(outfile, "}\n");
603 }
604
605 static void
606 exceptionSwitch(es, sw, pre, post, offset, def) List es; const char *sw; const char *pre; const char *post; int offset; const char *def;
607 {
608         if (es) {
609                 fprintf(outfile, "\t\tswitch (%s) {\n", sw);
610                 for (; es; es = es->next) {
611                         Exception e = (Exception) es->x;
612                         fprintf(outfile, "\t\tcase %d: %s %d; %s\n", e->index, pre, e->value+offset, post);
613                 }
614                 if (def) {
615                         fprintf(outfile, "\t\tdefault: %s;\n", def);
616                 }
617                 fprintf(outfile, "\t\t}\n");
618         } else {
619                 if (def) {
620                         fprintf(outfile, "\t\t%s;\n", def);
621                 }
622         }
623 }
624
625 static void
626 doPlankLabel(op) Operator op;
627 {
628         PlankMap im0;
629         PlankMap im1;
630         char buf[100];
631
632         fprintf(outfile, "\tcase %d:\n", op->num);
633         switch (op->arity) {
634         case 0:
635                 fprintf(outfile, "\t\treturn %d;\n", op->table->transition[0]->newNum);
636                 break;
637         case 1:
638                 im0 = op->table->dimen[0]->pmap;
639                 if (im0) {
640                         exceptionSwitch(im0->exceptions, "l", "return ", "", im0->offset, 0);
641                         fprintf(outfile, "\t\treturn %s[l].%s + %d;\n", 
642                                 im0->values->plank->name, im0->values->fieldname, im0->offset);
643                 } else {
644                         Item_Set *ts = transLval(op->table, 1, 0);
645                         if (*ts) {
646                                 fprintf(outfile, "\t\treturn %d;\n", (*ts)->newNum);
647                         } else {
648                                 fprintf(outfile, "\t\treturn %d;\n", ERROR_VAL);
649                         }
650                 }
651                 break;
652         case 2:
653                 im0 = op->table->dimen[0]->pmap;
654                 im1 = op->table->dimen[1]->pmap;
655                 if (!im0 && !im1) {
656                         Item_Set *ts = transLval(op->table, 1, 1);
657                         if (*ts) {
658                                 fprintf(outfile, "\t\treturn %d;\n", (*ts)->newNum);
659                         } else {
660                                 fprintf(outfile, "\t\treturn %d;\n", ERROR_VAL);
661                         }
662                 } else if (!im0) {
663                         exceptionSwitch(im1->exceptions, "r", "return ", "", im1->offset, 0);
664                         fprintf(outfile, "\t\treturn %s[r].%s + %d;\n", 
665                                 im1->values->plank->name, im1->values->fieldname, im1->offset);
666                 } else if (!im1) {
667                         exceptionSwitch(im0->exceptions, "l", "return ", "", im0->offset, 0);
668                         fprintf(outfile, "\t\treturn %s[l].%s + %d;\n", 
669                                 im0->values->plank->name, im0->values->fieldname, im0->offset);
670                 } else {
671                         assert(im0->offset == 0);
672                         assert(im1->offset == 0);
673                         sprintf(buf, "l = %s[l].%s",
674                                 im0->values->plank->name, im0->values->fieldname);
675                         exceptionSwitch(im0->exceptions, "l", "l =", "break;", 0, buf);
676                         sprintf(buf, "r = %s[r].%s",
677                                 im1->values->plank->name, im1->values->fieldname);
678                         exceptionSwitch(im1->exceptions, "r", "r =", "break;", 0, buf);
679
680                         fprintf(outfile, "\t\treturn %s_%s_transition[l][r] + %d;\n", 
681                                 prefix,
682                                 op->name,
683                                 op->baseNum);
684                 }
685                 break;
686         default:
687                 assert(0);
688         }
689 }
690
691 static void
692 doPlankLabelMacrosSafely(op) Operator op;
693 {
694         PlankMap im0;
695         PlankMap im1;
696
697         switch (op->arity) {
698         case -1:
699                 fprintf(outfile, "#define %s_%s_state\t0\n", prefix, op->name);
700                 break;
701         case 0:
702                 fprintf(outfile, "#define %s_%s_state", prefix, op->name);
703                 fprintf(outfile, "\t%d\n", op->table->transition[0]->newNum+1);
704                 break;
705         case 1:
706                 fprintf(outfile, "#define %s_%s_state(l)", prefix, op->name);
707                 im0 = op->table->dimen[0]->pmap;
708                 if (im0) {
709                         if (im0->exceptions) {
710                                 List es = im0->exceptions;
711                                 assert(0);
712                                 fprintf(outfile, "\t\tswitch (l) {\n");
713                                 for (; es; es = es->next) {
714                                         Exception e = (Exception) es->x;
715                                         fprintf(outfile, "\t\tcase %d: return %d;\n", e->index, e->value ? e->value+im0->offset : 0);
716                                 }
717                                 fprintf(outfile, "\t\t}\n");
718                         }
719                         if (speedflag) {
720                                 fprintf(outfile, "\t( %s[l].%s + %d )\n",
721                                         im0->values->plank->name, im0->values->fieldname,
722                                         im0->offset);
723                         } else {
724                                 fprintf(outfile, "\t( (%s_TEMP = %s[l].%s) ? %s_TEMP + %d : 0 )\n",
725                                         prefix,
726                                         im0->values->plank->name, im0->values->fieldname,
727                                         prefix,
728                                         im0->offset);
729                         }
730                 } else {
731                         Item_Set *ts = transLval(op->table, 1, 0);
732                         if (*ts) {
733                                 fprintf(outfile, "\t%d\n", (*ts)->newNum+1);
734                         } else {
735                                 fprintf(outfile, "\t%d\n", 0);
736                         }
737                 }
738                 break;
739         case 2:
740                 fprintf(outfile, "#define %s_%s_state(l,r)", prefix, op->name);
741
742                 im0 = op->table->dimen[0]->pmap;
743                 im1 = op->table->dimen[1]->pmap;
744                 if (!im0 && !im1) {
745                         Item_Set *ts = transLval(op->table, 1, 1);
746                         assert(0);
747                         if (*ts) {
748                                 fprintf(outfile, "\t\treturn %d;\n", (*ts)->newNum+1);
749                         } else {
750                                 fprintf(outfile, "\t\treturn %d;\n", 0);
751                         }
752                 } else if (!im0) {
753                         assert(0);
754                         if (im1->exceptions) {
755                                 List es = im1->exceptions;
756                                 fprintf(outfile, "\t\tswitch (r) {\n");
757                                 for (; es; es = es->next) {
758                                         Exception e = (Exception) es->x;
759                                         fprintf(outfile, "\t\tcase %d: return %d;\n", e->index, e->value ? e->value+im1->offset : 0);
760                                 }
761                                 fprintf(outfile, "\t\t}\n");
762                         }
763                         fprintf(outfile, "\t\tstate = %s[r].%s; offset = %d;\n", 
764                                 im1->values->plank->name, im1->values->fieldname, im1->offset);
765                         fprintf(outfile, "\t\tbreak;\n");
766                 } else if (!im1) {
767                         assert(0);
768                         if (im0->exceptions) {
769                                 List es = im0->exceptions;
770                                 fprintf(outfile, "\t\tswitch (l) {\n");
771                                 for (; es; es = es->next) {
772                                         Exception e = (Exception) es->x;
773                                         fprintf(outfile, "\t\tcase %d: return %d;\n", e->index, e->value ? e->value+im0->offset : 0);
774                                 }
775                                 fprintf(outfile, "\t\t}\n");
776                         }
777                         fprintf(outfile, "\t\tstate = %s[l].%s; offset = %d;\n", 
778                                 im0->values->plank->name, im0->values->fieldname, im0->offset);
779                         fprintf(outfile, "\t\tbreak;\n");
780                 } else {
781                         assert(im0->offset == 0);
782                         assert(im1->offset == 0);
783                         /*
784                         sprintf(buf, "l = %s[l].%s",
785                                 im0->values->plank->name, im0->values->fieldname);
786                         exceptionSwitch(im0->exceptions, "l", "l =", "break;", 0, buf);
787                         sprintf(buf, "r = %s[r].%s",
788                                 im1->values->plank->name, im1->values->fieldname);
789                         exceptionSwitch(im1->exceptions, "r", "r =", "break;", 0, buf);
790
791                         fprintf(outfile, "\t\tstate = %s_%s_transition[l][r]; offset = %d;\n", 
792                                 prefix,
793                                 op->name,
794                                 op->baseNum);
795                         fprintf(outfile, "\t\tbreak;\n");
796                         */
797
798                         if (speedflag) {
799                                 fprintf(outfile, "\t( %s_%s_transition[%s[l].%s][%s[r].%s] + %d)\n",
800                                         prefix,
801                                         op->name,
802                                         im0->values->plank->name, im0->values->fieldname,
803                                         im1->values->plank->name, im1->values->fieldname,
804                                         op->baseNum);
805                         } else {
806                                 fprintf(outfile, "\t( (%s_TEMP = %s_%s_transition[%s[l].%s][%s[r].%s]) ? ",
807                                         prefix,
808                                         prefix,
809                                         op->name,
810                                         im0->values->plank->name, im0->values->fieldname,
811                                         im1->values->plank->name, im1->values->fieldname);
812                                 fprintf(outfile, "%s_TEMP + %d : 0 )\n",
813                                         prefix,
814                                         op->baseNum);
815                         }
816                 }
817                 break;
818         default:
819                 assert(0);
820         }
821 }
822 static void
823 doPlankLabelSafely(op) Operator op;
824 {
825         fprintf(outfile, "\tcase %d:\n", op->num);
826         switch (op->arity) {
827         case -1:
828                 fprintf(outfile, "\t\treturn 0;\n");
829                 break;
830         case 0:
831                 fprintf(outfile, "\t\treturn %s_%s_state;\n", prefix, op->name);
832                 break;
833         case 1:
834                 fprintf(outfile, "\t\treturn %s_%s_state(l);\n", prefix, op->name);
835                 break;
836         case 2:
837                 fprintf(outfile, "\t\treturn %s_%s_state(l,r);\n", prefix, op->name);
838                 break;
839         default:
840                 assert(0);
841         }
842 }
843
844 static void
845 makePlankState()
846 {
847         fprintf(outfile, "\n");
848         fprintf(outfile, "int %s_TEMP;\n", prefix);
849         foreachList((ListFn) doPlankLabelMacrosSafely, operators);
850         fprintf(outfile, "\n");
851
852         fprintf(outfile, "#ifdef __STDC__\n");
853         switch (max_arity) {
854         case -1:
855                 fprintf(stderr, "ERROR: no terminals in grammar.\n");
856                 exit(1);
857         case 0:
858                 fprintf(outfile, "int %s_state(int op) {\n", prefix);
859                 fprintf(outfile, "#else\n");
860                 fprintf(outfile, "int %s_state(op) int op; {\n", prefix);
861                 break;
862         case 1:
863                 fprintf(outfile, "int %s_state(int op, int l) {\n", prefix);
864                 fprintf(outfile, "#else\n");
865                 fprintf(outfile, "int %s_state(op, l) int op; int l; {\n", prefix);
866                 break;
867         case 2:
868                 fprintf(outfile, "int %s_state(int op, int l, int r) {\n", prefix);
869                 fprintf(outfile, "#else\n");
870                 fprintf(outfile, "int %s_state(op, l, r) int op; int l; int r; {\n", prefix);
871                 break;
872         default:
873                 assert(0);
874         }
875         fprintf(outfile, "#endif\n");
876
877         fprintf(outfile, "\tregister int %s_TEMP;\n", prefix);
878
879         fprintf(outfile, "#ifndef NDEBUG\n");
880
881         fprintf(outfile, "\tswitch (op) {\n");
882         opsOfArity(2);
883         if (max_arity >= 2) {
884                 fprintf(outfile, 
885                 "\t\t%s_assert(r >= 0 && r < %d, %s_PANIC(\"Bad state %%d passed to %s_state\\n\", r));\n",
886                                 prefix, globalMap->count, prefix, prefix);
887                 fprintf(outfile, "\t\t/*FALLTHROUGH*/\n");
888         }
889         opsOfArity(1);
890         if (max_arity > 1) {
891                 fprintf(outfile, 
892                 "\t\t%s_assert(l >= 0 && l < %d, %s_PANIC(\"Bad state %%d passed to %s_state\\n\", l));\n",
893                                 prefix, globalMap->count, prefix, prefix);
894                 fprintf(outfile, "\t\t/*FALLTHROUGH*/\n");
895         }
896         opsOfArity(0);
897         fprintf(outfile, "\t\tbreak;\n");
898         fprintf(outfile, "\t}\n");
899         fprintf(outfile, "#endif\n");
900
901         fprintf(outfile, "\tswitch (op) {\n");
902         fprintf(outfile,"\tdefault: %s_PANIC(\"Unknown op %%d in %s_state\\n\", op); abort(); return 0;\n",
903                 prefix, prefix);
904         foreachList((ListFn) doPlankLabelSafely, operators);
905         fprintf(outfile, "\t}\n");
906
907         fprintf(outfile, "}\n");
908 }
909
910 void
911 makePlanks()
912 {
913         List planks;
914         renumber();
915         makePmaps();
916         planks = assemblePlanks();
917         purgePlanks(planks);
918         inToEx();
919         makePlankRule();
920         makePlankState();
921 }