blob: 1ce006dd01996bdb7a931bf761f4df98c6493712 [file] [log] [blame]
Chris Lattnerf5bd1b72003-10-05 19:27:59 +00001char 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
11int speedflag = 0;
12
13Item_Set *sortedStates;
14static struct stateMapTable smt;
15int exceptionTolerance = 0;
16static int plankSize = 32;
17
18static Plank newPlank ARGS((void));
19static PlankMap newPlankMap ARGS((int));
20static StateMap newStateMap ARGS((void));
21static Exception newException ARGS((int, int));
22static void enterStateMap ARGS((PlankMap, short *, int, int *));
23static List assemblePlanks ARGS((void));
24static void assignRules ARGS((RuleAST));
25static int stateCompare ARGS((Item_Set *, Item_Set *));
26static int ruleCompare ARGS((RuleAST *, RuleAST *));
27static void renumber ARGS((void));
28static short * newVector ARGS((void));
29static int width ARGS((int));
30static PlankMap mapToPmap ARGS((Dimension));
31static void doDimPmaps ARGS((Operator));
32static void doNonTermPmaps ARGS((NonTerminal));
33static void makePmaps ARGS((void));
34static void outPlank ARGS((Plank));
35static void purgePlanks ARGS((List));
36static void inToEx ARGS((void));
37static void makePlankRuleMacros ARGS((void));
38static void makePlankRule ARGS((void));
39static void exceptionSwitch ARGS((List, const char *, const char *, const char *, int, const char *));
40static void doPlankLabel ARGS((Operator));
41static void doPlankLabelSafely ARGS((Operator));
42static void doPlankLabelMacrosSafely ARGS((Operator));
43static void makePlankState ARGS((void));
44
45static Plank
46newPlank()
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
59static PlankMap
60newPlankMap(offset) int offset;
61{
62 PlankMap im;
63
64 im = (PlankMap) zalloc(sizeof(struct plankMap));
65 im->offset = offset;
66 return im;
67}
68
69static StateMap
70newStateMap()
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
84static Exception
85newException(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
95static void
96enterStateMap(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
148static List
149assemblePlanks()
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
177RuleAST *sortedRules;
178
179static int count;
180
181static void
182assignRules(ast) RuleAST ast;
183{
184 sortedRules[count++] = ast;
185}
186
187static int
188stateCompare(s, t) Item_Set *s; Item_Set *t;
189{
190 return strcmp((*s)->op->name, (*t)->op->name);
191}
192
193static int
194ruleCompare(s, t) RuleAST *s; RuleAST *t;
195{
196 return strcmp((*s)->lhs, (*t)->lhs);
197}
198
199void
200dumpSortedStates()
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
211void
212dumpSortedRules()
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
223static void
224renumber()
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
265static short *
266newVector()
267{
268 short *p;
269 p = (short *) zalloc(globalMap->count* sizeof(short));
270 return p;
271}
272
273static int
274width(v) int v;
275{
276 int c;
277
278 for (c = 0; v; v >>= 1) {
279 c++;
280 }
281 return c;
282
283}
284
285static PlankMap
286mapToPmap(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
312static void
313doDimPmaps(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
429static NonTerminal *ntVector;
430
431static void
432doNonTermPmaps(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
463static void
464makePmaps()
465{
466 foreachList((ListFn) doDimPmaps, operators);
467 ntVector = (NonTerminal*) zalloc((max_nonterminal) * sizeof(NonTerminal));
468 foreachList((ListFn) doNonTermPmaps, nonterminals);
469}
470
471static void
472outPlank(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
498static void
499purgePlanks(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
509static void
510inToEx()
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
541static void
542makePlankRuleMacros()
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
575static void
576makePlankRule()
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
605static void
606exceptionSwitch(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
625static void
626doPlankLabel(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
691static void
692doPlankLabelMacrosSafely(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}
822static void
823doPlankLabelSafely(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
844static void
845makePlankState()
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
910void
911makePlanks()
912{
913 List planks;
914 renumber();
915 makePmaps();
916 planks = assemblePlanks();
917 purgePlanks(planks);
918 inToEx();
919 makePlankRule();
920 makePlankState();
921}