Make sure to print a stack trace whenever an error signal is delivered
[oota-llvm.git] / utils / Burg / be.c
1 char rcsid_be[] = "$Id$";
2
3 #include <stdio.h>
4 #include <string.h>
5 #include "b.h"
6 #include "fe.h"
7
8 #define ERROR_VAL 0
9
10 FILE *outfile;
11 const char *prefix = "burm";
12
13 static void doKids ARGS((RuleAST));
14 static void doLabel ARGS((Operator));
15 static void doLayout ARGS((RuleAST));
16 static void doMakeTable ARGS((Operator));
17 static void doVector ARGS((RuleAST));
18 static void layoutNts ARGS((PatternAST));
19 static void makeIndex_Map ARGS((Dimension));
20 static void makePvector ARGS((void));
21 static void makeState ARGS((void));
22 static void printPatternAST ARGS((PatternAST));
23 static void printPatternAST_int ARGS((PatternAST));
24 static void setVectors ARGS((PatternAST));
25 static void trailing_zeroes ARGS((int));
26 static int seminal ARGS((int from, int to));
27 static void printRule ARGS((RuleAST, const char *));
28
29 static void
30 doLabel(op) Operator op;
31 {
32         fprintf(outfile, "\tcase %d:\n", op->num);
33
34         switch (op->arity) {
35         default:
36                 assert(0);
37                 break;
38         case 0:
39                 fprintf(outfile, "\t\treturn %d;\n", op->table->transition[0]->num);
40                 break;
41         case 1:
42                 if (op->table->rules) {
43                         fprintf(outfile, "\t\treturn %s_%s_transition[l];\n", prefix, op->name);
44                 } else {
45                         fprintf(outfile, "\t\treturn %d;\n", ERROR_VAL);
46                 }
47                 break;
48         case 2:
49                 if (op->table->rules) {
50                         fprintf(outfile, "\t\treturn %s_%s_transition[%s_%s_imap_1[l]][%s_%s_imap_2[r]];\n", prefix, op->name, prefix, op->name, prefix, op->name);
51                 } else {
52                         fprintf(outfile, "\t\treturn %d;\n", ERROR_VAL);
53                 }
54                 break;
55         }
56 }
57
58 int
59 opsOfArity(arity) int arity;
60 {
61         int c;
62         List l;
63
64         c = 0;
65         for (l = operators; l; l = l->next) {
66                 Operator op = (Operator) l->x;
67                 if (op->arity == arity) {
68                         fprintf(outfile, "\tcase %d:\n", op->num);
69                         c++;
70                 }
71         }
72         return c;
73 }
74
75 static void
76 trailing_zeroes(z) int z;
77 {
78         int i;
79
80         for (i = 0; i < z; i++) {
81                 fprintf(outfile, ", 0");
82         }
83 }
84
85 void
86 makeLabel()
87 {
88         int flag;
89
90         fprintf(outfile, "#ifdef __STDC__\n");
91         fprintf(outfile, "int %s_label(%s_NODEPTR_TYPE n) {\n", prefix, prefix);
92         fprintf(outfile, "#else\n");
93         fprintf(outfile, "int %s_label(n) %s_NODEPTR_TYPE n; {\n", prefix, prefix);
94         fprintf(outfile, "#endif\n");
95
96         fprintf(outfile, 
97         "\t%s_assert(n, %s_PANIC(\"NULL pointer passed to %s_label\\n\"));\n",
98                                 prefix, prefix, prefix);
99         fprintf(outfile, "\tswitch (%s_OP_LABEL(n)) {\n", prefix);
100         fprintf(outfile, "\tdefault: %s_PANIC(\"Bad op %%d in %s_label\\n\", %s_OP_LABEL(n)); abort(); return 0;\n", 
101                         prefix, prefix, prefix);
102
103         flag = opsOfArity(0);
104         if (flag > 0) {
105                 fprintf(outfile, "\t\treturn %s_STATE_LABEL(n) = %s_state(%s_OP_LABEL(n)",
106                                         prefix, prefix, prefix);
107                 trailing_zeroes(max_arity);
108                 fprintf(outfile, ");\n");
109         }
110         flag = opsOfArity(1);
111         if (flag > 0) {
112                 fprintf(outfile, "\t\treturn %s_STATE_LABEL(n) = %s_state(%s_OP_LABEL(n), %s_label(%s_LEFT_CHILD(n))",
113                                         prefix, prefix, prefix, prefix, prefix);
114                 trailing_zeroes(max_arity-1);
115                 fprintf(outfile, ");\n");
116         }
117         flag = opsOfArity(2);
118         if (flag > 0) {
119                 fprintf(outfile, "\t\treturn %s_STATE_LABEL(n) = %s_state(%s_OP_LABEL(n), %s_label(%s_LEFT_CHILD(n)), %s_label(%s_RIGHT_CHILD(n))",
120                                         prefix, prefix, prefix, prefix, prefix, prefix, prefix);
121                 trailing_zeroes(max_arity-2);
122                 fprintf(outfile, ");\n");
123
124         }
125         fprintf(outfile, "\t}\n");
126         fprintf(outfile, "}\n");
127 }
128
129 static void
130 makeState()
131 {
132         fprintf(outfile, "int %s_state(int op, int l, int r) {\n", prefix);
133         fprintf(outfile, 
134         "\t%s_assert(l >= 0 && l < %d, PANIC(\"Bad state %%d passed to %s_state\\n\", l));\n",
135                                 prefix, globalMap->count, prefix);
136         fprintf(outfile, 
137         "\t%s_assert(r >= 0 && r < %d, PANIC(\"Bad state %%d passed to %s_state\\n\", r));\n",
138                                 prefix, globalMap->count, prefix);
139         fprintf(outfile, "\tswitch (op) {\n");
140         fprintf(outfile, "\tdefault: %s_PANIC(\"Bad op %%d in %s_state\\n\", op); abort(); return 0;\n", prefix, prefix);
141
142         foreachList((ListFn) doLabel, operators);
143
144         fprintf(outfile, "\t}\n");
145         fprintf(outfile, "}\n");
146 }
147
148 static char cumBuf[4000];
149 static int vecIndex;
150 char vecBuf[4000];
151
152 static void
153 setVectors(ast) PatternAST ast;
154 {
155         char old[4000];
156
157         switch (ast->sym->tag) {
158         default:
159                 assert(0);
160                 break;
161         case NONTERMINAL:
162                 sprintf(old, "\t\tkids[%d] = %s;\n", vecIndex, vecBuf);
163                 strcat(cumBuf, old);
164                 vecIndex++;
165                 return;
166         case OPERATOR:
167                 switch (ast->sym->u.op->arity) {
168                 default:
169                         assert(0);
170                         break;
171                 case 0:
172                         return;
173                 case 1:
174                         strcpy(old, vecBuf);
175                         sprintf(vecBuf, "%s_LEFT_CHILD(%s)", prefix, old);
176                         setVectors((PatternAST) ast->children->x);
177                         strcpy(vecBuf, old);
178                         return;
179                 case 2:
180                         strcpy(old, vecBuf);
181                         sprintf(vecBuf, "%s_LEFT_CHILD(%s)", prefix, old);
182                         setVectors((PatternAST) ast->children->x);
183
184                         sprintf(vecBuf, "%s_RIGHT_CHILD(%s)", prefix, old);
185                         setVectors((PatternAST) ast->children->next->x);
186                         strcpy(vecBuf, old);
187                         return;
188                 }
189                 break;
190         }
191 }
192
193 #define MAX_VECTOR      10
194
195 void
196 makeRuleTable()
197 {
198         int s,nt;
199
200         fprintf(outfile, "static short %s_RuleNo[%d][%d] = {\n", prefix, globalMap->count, last_user_nonterminal-1);
201         for (s = 0; s < globalMap->count; s++) {
202                 Item_Set ts = globalMap->set[s];
203                 if (s > 0) {
204                         fprintf(outfile, ",\n");
205                 }
206                 fprintf(outfile, "/* state %d */\n", s);
207                 fprintf(outfile, "{");
208                 for (nt = 1; nt < last_user_nonterminal; nt++) {
209                         if (nt > 1) {
210                                 fprintf(outfile, ",");
211                                 if (nt % 10 == 1) {
212                                         fprintf(outfile, "\t/* state %d; Nonterminals %d-%d */\n", s, nt-10, nt-1);
213                                 }
214                         }
215                         if (ts->closed[nt].rule) {
216                                 ts->closed[nt].rule->used = 1;
217                                 fprintf(outfile, "%5d", ts->closed[nt].rule->erulenum);
218                         } else {
219                                 fprintf(outfile, "%5d", ERROR_VAL);
220                         }
221                 }
222                 fprintf(outfile, "}");
223         }
224         fprintf(outfile, "};\n");
225 }
226
227 static void
228 makeIndex_Map(d) Dimension d;
229 {
230         int s;
231
232         for (s = 0; s < globalMap->count; s++) {
233                 if (s > 0) {
234                         fprintf(outfile, ",");
235                         if (s % 10 == 0) {
236                                 fprintf(outfile, "\t/* %d-%d */\n", s-10, s-1);
237                         }
238                 }
239                 fprintf(outfile, "%5d", d->map->set[d->index_map.class[s]->num]->num);
240         }
241         fprintf(outfile, "};\n");
242 }
243
244 static void
245 doMakeTable(op) Operator op;
246 {
247         int s;
248         int i,j;
249         Dimension d;
250
251         switch (op->arity) {
252         default:
253                 assert(0);
254                 break;
255         case 0:
256                 return;
257         case 1:
258                 if (!op->table->rules) {
259                         return;
260                 }
261                 d = op->table->dimen[0];
262                 fprintf(outfile, "static short %s_%s_transition[%d] = {\n", prefix, op->name, globalMap->count);
263                 for (s = 0; s < globalMap->count; s++) {
264                         if (s > 0) {
265                                 fprintf(outfile, ", ");
266                                 if (s % 10 == 0) {
267                                         fprintf(outfile, "\t/* %d-%d */\n", s-10, s-1);
268                                 }
269                         }
270                         fprintf(outfile, "%5d", op->table->transition[d->map->set[d->index_map.class[s]->num]->num]->num);
271                 }
272                 fprintf(outfile, "};\n");
273                 break;
274         case 2:
275                 if (!op->table->rules) {
276                         return;
277                 }
278                 fprintf(outfile, "static short %s_%s_imap_1[%d] = {\n", prefix, op->name, globalMap->count);
279                 makeIndex_Map(op->table->dimen[0]);
280                 fprintf(outfile, "static short %s_%s_imap_2[%d] = {\n", prefix, op->name, globalMap->count);
281                 makeIndex_Map(op->table->dimen[1]);
282
283                 fprintf(outfile, "static short %s_%s_transition[%d][%d] = {", prefix, op->name,
284                                                 op->table->dimen[0]->map->count,
285                                                 op->table->dimen[1]->map->count);
286                 for (i = 0; i < op->table->dimen[0]->map->count; i++) {
287                         if (i > 0) {
288                                 fprintf(outfile, ",");
289                         }
290                         fprintf(outfile, "\n");
291                         fprintf(outfile, "{");
292                         for (j = 0; j < op->table->dimen[1]->map->count; j++) {
293                                 Item_Set *ts = transLval(op->table, i, j);
294                                 if (j > 0) {
295                                         fprintf(outfile, ",");
296                                 }
297                                 fprintf(outfile, "%5d", (*ts)->num);
298                         }
299                         fprintf(outfile, "}\t/* row %d */", i);
300                 }
301                 fprintf(outfile, "\n};\n");
302
303                 break;
304         }
305 }
306
307 void
308 makeTables()
309 {
310         foreachList((ListFn) doMakeTable, operators);
311 }
312
313 RuleAST *pVector;
314
315 void
316 makeLHSmap()
317 {
318         int i;
319
320         if (!pVector) {
321                 makePvector();
322         }
323
324         fprintf(outfile, "short %s_lhs[] = {\n", prefix);
325         for (i = 0; i <= max_erule_num; i++) {
326                 if (pVector[i]) {
327                         fprintf(outfile, "\t%s_%s_NT,\n", prefix, pVector[i]->lhs);
328                 } else {
329                         fprintf(outfile, "\t0,\n");
330                 }
331         }
332         fprintf(outfile, "};\n\n");
333 }
334
335 static int seminal(int from, int to)
336 {
337         return allpairs[from][to].rule ? allpairs[from][to].rule->erulenum : 0;
338
339         /*
340         int tmp, last;
341         tmp = 0;
342         for (;;) {
343                 last = tmp;
344                 tmp = allpairs[to][from].rule ? allpairs[to][from].rule->erulenum : 0;
345                 if (!tmp) {
346                         break;
347                 }
348                 assert(pVector[tmp]);
349                 to = pVector[tmp]->rule->pat->children[0]->num;
350         }
351         return last;
352         */
353 }
354
355 void
356 makeClosureArray()
357 {
358         int i, j;
359
360         if (!pVector) {
361                 makePvector();
362         }
363
364         fprintf(outfile, "short %s_closure[%d][%d] = {\n", prefix, last_user_nonterminal, last_user_nonterminal);
365         for (i = 0; i < last_user_nonterminal; i++) {
366                 fprintf(outfile, "\t{");
367                 for (j = 0; j < last_user_nonterminal; j++) {
368                         if (j > 0 && j%10 == 0) {
369                                 fprintf(outfile, "\n\t ");
370                         }
371                         fprintf(outfile, " %4d,", seminal(i,j));
372                 }
373                 fprintf(outfile, "},\n");
374         }
375         fprintf(outfile, "};\n");
376 }
377
378 void
379 makeCostVector(z,d) int z; DeltaCost d;
380 {
381         fprintf(outfile, "\t{");
382 #ifdef NOLEX
383         if (z) {
384                 fprintf(outfile, "%5d", d);
385         } else {
386                 fprintf(outfile, "%5d", 0);
387         }
388 #else
389         {
390         int j;
391         for (j = 0; j < DELTAWIDTH; j++) {
392                 if (j > 0) {
393                         fprintf(outfile, ",");
394                 }
395                 if (z) {
396                         fprintf(outfile, "%5d", d[j]);
397                 } else {
398                         fprintf(outfile, "%5d", 0);
399                 }
400         }
401         }
402 #endif /* NOLEX */
403         fprintf(outfile, "}");
404 }
405
406 void
407 makeCostArray()
408 {
409         int i;
410
411         if (!pVector) {
412                 makePvector();
413         }
414
415         fprintf(outfile, "short %s_cost[][%d] = {\n", prefix, DELTAWIDTH);
416         for (i = 0; i <= max_erule_num; i++) {
417                 makeCostVector(pVector[i] != 0, pVector[i] ? pVector[i]->rule->delta : 0);
418                 fprintf(outfile, ", /* ");
419                 printRule(pVector[i], "(none)");
420                 fprintf(outfile, " = %d */\n", i);
421         }
422         fprintf(outfile, "};\n");
423 }
424
425 void
426 makeStateStringArray()
427 {
428         int s;
429         int nt;
430         int states;
431         
432         states = globalMap->count;
433         fprintf(outfile, "\nconst char * %s_state_string[] = {\n", prefix);
434         fprintf(outfile, "\" not a state\", /* state 0 */\n");
435         for (s = 0; s < states-1; s++) {
436                 fprintf(outfile, "\t\"");
437                 printRepresentative(outfile, sortedStates[s]);
438                 fprintf(outfile, "\", /* state #%d */\n", s+1);
439         }
440         fprintf(outfile, "};\n");
441 }
442
443 void
444 makeDeltaCostArray()
445 {
446         int s;
447         int nt;
448         int states;
449         
450         states = globalMap->count;
451         fprintf(outfile, "\nshort %s_delta_cost[%d][%d][%d] = {\n", prefix, states, last_user_nonterminal, DELTAWIDTH);
452         fprintf(outfile, "{{0}}, /* state 0 */\n");
453         for (s = 0; s < states-1; s++) {
454                 fprintf(outfile, "{ /* state #%d: ", s+1);
455                 printRepresentative(outfile, sortedStates[s]);
456                 fprintf(outfile, " */\n");
457                 fprintf(outfile, "\t{0},\n");
458                 for (nt = 1; nt < last_user_nonterminal; nt++) {
459                         makeCostVector(1, sortedStates[s]->closed[nt].delta);
460                         fprintf(outfile, ", /* ");
461                         if (sortedStates[s]->closed[nt].rule) {
462                                 int erulenum = sortedStates[s]->closed[nt].rule->erulenum;
463                                 printRule(pVector[erulenum], "(none)");
464                                 fprintf(outfile, " = %d */", erulenum);
465                         } else {
466                                 fprintf(outfile, "(none) */");
467                         }
468                         fprintf(outfile, "\n");
469                 }
470                 fprintf(outfile, "},\n");
471         }
472         fprintf(outfile, "};\n");
473 }
474
475 static void
476 printPatternAST_int(p) PatternAST p;
477 {
478         List l;
479
480         if (p) {
481                 switch (p->sym->tag) {
482                 case NONTERMINAL:
483                         fprintf(outfile, "%5d,", -p->sym->u.nt->num);
484                         break;
485                 case OPERATOR:
486                         fprintf(outfile, "%5d,", p->sym->u.op->num);
487                         break;
488                 default:
489                         assert(0);
490                 }
491                 if (p->children) {
492                         for (l = p->children; l; l = l->next) {
493                                 PatternAST pat = (PatternAST) l->x;
494                                 printPatternAST_int(pat);
495                         }
496                 }
497         }
498 }
499
500 static void
501 printPatternAST(p) PatternAST p;
502 {
503         List l;
504
505         if (p) {
506                 fprintf(outfile, "%s", p->op);
507                 if (p->children) {
508                         fprintf(outfile, "(");
509                         for (l = p->children; l; l = l->next) {
510                                 PatternAST pat = (PatternAST) l->x;
511                                 if (l != p->children) {
512                                         fprintf(outfile, ", ");
513                                 }
514                                 printPatternAST(pat);
515                         }
516                         fprintf(outfile, ")");
517                 }
518         }
519 }
520
521 static void
522 layoutNts(ast) PatternAST ast;
523 {
524         char out[30];
525
526         switch (ast->sym->tag) {
527         default:
528                 assert(0);
529                 break;
530         case NONTERMINAL:
531                 sprintf(out, "%d, ", ast->sym->u.nt->num);
532                 strcat(cumBuf, out);
533                 return;
534         case OPERATOR:
535                 switch (ast->sym->u.op->arity) {
536                 default:
537                         assert(0);
538                         break;
539                 case 0:
540                         return;
541                 case 1:
542                         layoutNts((PatternAST) ast->children->x);
543                         return;
544                 case 2:
545                         layoutNts((PatternAST) ast->children->x);
546                         layoutNts((PatternAST) ast->children->next->x);
547                         return;
548                 }
549                 break;
550         }
551 }
552
553 static void
554 doVector(ast) RuleAST ast;
555 {
556         if (pVector[ast->rule->erulenum]) {
557                 fprintf(stderr, "ERROR: non-unique external rule number: (%d)\n", ast->rule->erulenum);
558                 exit(1);
559         }
560         pVector[ast->rule->erulenum] = ast;
561 }
562
563 static void
564 makePvector()
565 {
566         pVector = (RuleAST*) zalloc((max_erule_num+1) * sizeof(RuleAST));
567         foreachList((ListFn) doVector, ruleASTs);
568 }
569
570 static void
571 doLayout(ast) RuleAST ast;
572 {
573         sprintf(cumBuf, "{ ");
574         layoutNts(ast->pat);
575         strcat(cumBuf, "0 }");
576 }
577
578 void
579 makeNts()
580 {
581         int i;
582         int new;
583         StrTable nts;
584
585         nts = newStrTable();
586
587         if (!pVector) {
588                 makePvector();
589         }
590
591         for (i = 0; i <= max_erule_num; i++) {
592                 if (pVector[i]) {
593                         doLayout(pVector[i]);
594                         pVector[i]->nts = addString(nts, cumBuf, i, &new);
595                         if (new) {
596                                 char ename[50];
597
598                                 sprintf(ename, "%s_r%d_nts", prefix, i);
599                                 pVector[i]->nts->ename = (char*) zalloc(strlen(ename)+1);
600                                 strcpy(pVector[i]->nts->ename, ename);
601                                 fprintf(outfile, "static short %s[] =", ename);
602                                 fprintf(outfile, "%s;\n", cumBuf);
603                         }
604                 }
605         }
606
607         fprintf(outfile, "short *%s_nts[] = {\n", prefix);
608         for (i = 0; i <= max_erule_num; i++) {
609                 if (pVector[i]) {
610                         fprintf(outfile, "\t%s,\n", pVector[i]->nts->ename);
611                 } else {
612                         fprintf(outfile, "\t0,\n");
613                 }
614         }
615         fprintf(outfile, "};\n");
616 }
617
618 static void
619 printRule(RuleAST r, const char *d)
620 {
621         if (r) {
622                 fprintf(outfile, "%s: ", r->rule->lhs->name);
623                 printPatternAST(r->pat);
624         } else {
625                 fprintf(outfile, "%s", d);
626         }
627 }
628
629 void
630 makeRuleDescArray()
631 {
632         int i;
633
634         if (!pVector) {
635                 makePvector();
636         }
637
638         if (last_user_nonterminal != max_nonterminal) {
639                 /* not normal form */
640                 fprintf(outfile, "short %s_rule_descriptor_0[] = { 0, 0 };\n", prefix);
641         } else {
642                 fprintf(outfile, "short %s_rule_descriptor_0[] = { 0, 1 };\n", prefix);
643         }
644         for (i = 1; i <= max_erule_num; i++) {
645                 if (pVector[i]) {
646                         Operator o;
647                         NonTerminal t;
648
649                         fprintf(outfile, "short %s_rule_descriptor_%d[] = {", prefix, i);
650                         fprintf(outfile, "%5d,", -pVector[i]->rule->lhs->num);
651                         printPatternAST_int(pVector[i]->pat);
652                         fprintf(outfile, " };\n");
653                 }
654         }
655
656         fprintf(outfile, "/* %s_rule_descriptors[0][1] = 1 iff grammar is normal form. */\n", prefix);
657         fprintf(outfile, "short * %s_rule_descriptors[] = {\n", prefix);
658         fprintf(outfile, "\t%s_rule_descriptor_0,\n", prefix);
659         for (i = 1; i <= max_erule_num; i++) {
660                 if (pVector[i]) {
661                         fprintf(outfile, "\t%s_rule_descriptor_%d,\n", prefix, i);
662                 } else {
663                         fprintf(outfile, "\t%s_rule_descriptor_0,\n", prefix);
664                 }
665         }
666         fprintf(outfile, "};\n");
667 }
668
669
670 void
671 makeRuleDescArray2()
672 {
673         int i;
674
675         if (!pVector) {
676                 makePvector();
677         }
678
679         fprintf(outfile, "struct { int lhs, op, left, right; } %s_rule_struct[] = {\n", prefix);
680         if (last_user_nonterminal != max_nonterminal) {
681                 /* not normal form */
682                 fprintf(outfile, "\t{-1},");
683         } else {
684                 fprintf(outfile, "\t{0},");
685         }
686         fprintf(outfile, " /* 0 if normal form, -1 if not normal form */\n");
687         for (i = 1; i <= max_erule_num; i++) {
688                 fprintf(outfile, "\t");
689                 if (pVector[i]) {
690                         Operator o;
691                         NonTerminal t1, t2;
692
693                         fprintf(outfile, "{");
694                         fprintf(outfile, "%5d, %5d, %5d, %5d",
695                                 pVector[i]->rule->lhs->num,
696                                 (o = pVector[i]->rule->pat->op) ? o->num : 0,
697                                 (t1 = pVector[i]->rule->pat->children[0]) ? t1->num : 0,
698                                 (t2 = pVector[i]->rule->pat->children[1]) ? t2->num : 0
699                                 );
700                         fprintf(outfile, "} /* ");
701                         printRule(pVector[i], "0");
702                         fprintf(outfile, " = %d */", i);
703                 } else {
704                         fprintf(outfile, "{0}");
705                 }
706                 fprintf(outfile, ",\n");
707         }
708         fprintf(outfile, "};\n");
709 }
710
711 void
712 makeStringArray()
713 {
714         int i;
715
716         if (!pVector) {
717                 makePvector();
718         }
719
720         fprintf(outfile, "const char *%s_string[] = {\n", prefix);
721         for (i = 0; i <= max_erule_num; i++) {
722                 fprintf(outfile, "\t");
723                 if (pVector[i]) {
724                         fprintf(outfile, "\"");
725                         printRule(pVector[i], "0");
726                         fprintf(outfile, "\"");
727                 } else {
728                         fprintf(outfile, "0");
729                 }
730                 fprintf(outfile, ",\n");
731         }
732         fprintf(outfile, "};\n");
733         fprintf(outfile, "int %s_max_rule = %d;\n", prefix, max_erule_num);
734         fprintf(outfile, "#define %s_Max_rule %d\n", prefix, max_erule_num);
735 }
736
737 void
738 makeRule()
739 {
740         fprintf(outfile, "int %s_rule(int state, int goalnt) {\n", prefix);
741         fprintf(outfile, 
742         "\t%s_assert(state >= 0 && state < %d, PANIC(\"Bad state %%d passed to %s_rule\\n\", state));\n",
743                                 prefix, globalMap->count, prefix);
744         fprintf(outfile, 
745         "\t%s_assert(goalnt >= 1 && goalnt < %d, PANIC(\"Bad goalnt %%d passed to %s_rule\\n\", state));\n",
746                                 prefix, max_nonterminal, prefix);
747         fprintf(outfile, "\treturn %s_RuleNo[state][goalnt-1];\n", prefix);
748         fprintf(outfile, "};\n");
749 }
750
751 static StrTable kids;
752
753 static void
754 doKids(ast) RuleAST ast;
755 {
756         int new;
757
758         vecIndex = 0;
759         cumBuf[0] = 0;
760         strcpy(vecBuf, "p");
761         setVectors(ast->pat);
762
763         ast->kids = addString(kids, cumBuf, ast->rule->erulenum, &new);
764
765 }
766
767 void
768 makeKids()
769 {
770         List e;
771         IntList r;
772
773         kids = newStrTable();
774
775         fprintf(outfile, "#ifdef __STDC__\n");
776         fprintf(outfile, "%s_NODEPTR_TYPE * %s_kids(%s_NODEPTR_TYPE p, int rulenumber, %s_NODEPTR_TYPE *kids) {\n", prefix, prefix, prefix, prefix);
777         fprintf(outfile, "#else\n");
778         fprintf(outfile, "%s_NODEPTR_TYPE * %s_kids(p, rulenumber, kids) %s_NODEPTR_TYPE p; int rulenumber; %s_NODEPTR_TYPE *kids; {\n", prefix, prefix, prefix, prefix);
779         fprintf(outfile, "#endif\n");
780
781         fprintf(outfile, 
782         "\t%s_assert(p, %s_PANIC(\"NULL node pointer passed to %s_kids\\n\"));\n",
783                                 prefix, prefix, prefix);
784         fprintf(outfile, 
785         "\t%s_assert(kids, %s_PANIC(\"NULL kids pointer passed to %s_kids\\n\"));\n",
786                                 prefix, prefix, prefix);
787         fprintf(outfile, "\tswitch (rulenumber) {\n");
788         fprintf(outfile, "\tdefault:\n");
789         fprintf(outfile, "\t\t%s_PANIC(\"Unknown Rule %%d in %s_kids;\\n\", rulenumber);\n", prefix, prefix);
790         fprintf(outfile, "\t\tabort();\n");
791         fprintf(outfile, "\t\t/* NOTREACHED */\n");
792
793         foreachList((ListFn) doKids, ruleASTs);
794
795         for (e = kids->elems; e; e = e->next) {
796                 StrTableElement el = (StrTableElement) e->x;
797                 for (r = el->erulenos; r; r = r->next) {
798                         int i = r->x;
799                         fprintf(outfile, "\tcase %d:\n", i);
800                 }
801                 fprintf(outfile, "%s", el->str);
802                 fprintf(outfile, "\t\tbreak;\n");
803         }
804         fprintf(outfile, "\t}\n");
805         fprintf(outfile, "\treturn kids;\n");
806         fprintf(outfile, "}\n");
807 }
808
809 void
810 makeOpLabel()
811 {
812         fprintf(outfile, "#ifdef __STDC__\n");
813         fprintf(outfile, "int %s_op_label(%s_NODEPTR_TYPE p) {\n", prefix, prefix);
814         fprintf(outfile, "#else\n");
815         fprintf(outfile, "int %s_op_label(p) %s_NODEPTR_TYPE p; {\n", prefix, prefix);
816         fprintf(outfile, "#endif\n");
817         fprintf(outfile, 
818         "\t%s_assert(p, %s_PANIC(\"NULL pointer passed to %s_op_label\\n\"));\n",
819                                 prefix, prefix, prefix);
820         fprintf(outfile, "\treturn %s_OP_LABEL(p);\n", prefix);
821         fprintf(outfile, "}\n");
822 }
823
824 void
825 makeStateLabel()
826 {
827         fprintf(outfile, "#ifdef __STDC__\n");
828         fprintf(outfile, "int %s_state_label(%s_NODEPTR_TYPE p) {\n", prefix, prefix);
829         fprintf(outfile, "#else\n");
830         fprintf(outfile, "int %s_state_label(p) %s_NODEPTR_TYPE p; {\n", prefix, prefix);
831         fprintf(outfile, "#endif\n");
832
833         fprintf(outfile, 
834         "\t%s_assert(p, %s_PANIC(\"NULL pointer passed to %s_state_label\\n\"));\n",
835                                 prefix, prefix, prefix);
836         fprintf(outfile, "\treturn %s_STATE_LABEL(p);\n", prefix);
837         fprintf(outfile, "}\n");
838 }
839
840 void
841 makeChild()
842 {
843         fprintf(outfile, "#ifdef __STDC__\n");
844         fprintf(outfile, "%s_NODEPTR_TYPE %s_child(%s_NODEPTR_TYPE p, int index) {\n", prefix, prefix, prefix);
845         fprintf(outfile, "#else\n");
846         fprintf(outfile, "%s_NODEPTR_TYPE %s_child(p, index) %s_NODEPTR_TYPE p; int index; {\n", prefix, prefix, prefix);
847         fprintf(outfile, "#endif\n");
848
849         fprintf(outfile, 
850         "\t%s_assert(p, %s_PANIC(\"NULL pointer passed to %s_child\\n\"));\n",
851                                 prefix, prefix, prefix);
852         fprintf(outfile, "\tswitch (index) {\n");
853         fprintf(outfile, "\tcase 0:\n");
854         fprintf(outfile, "\t\treturn %s_LEFT_CHILD(p);\n", prefix);
855         fprintf(outfile, "\tcase 1:\n");
856         fprintf(outfile, "\t\treturn %s_RIGHT_CHILD(p);\n", prefix);
857         fprintf(outfile, "\t}\n");
858         fprintf(outfile, "\t%s_PANIC(\"Bad index %%d in %s_child;\\n\", index);\n", prefix, prefix);
859         fprintf(outfile, "\tabort();\n");
860         fprintf(outfile, "\treturn 0;\n");
861         fprintf(outfile, "}\n");
862 }
863
864 static Operator *opVector;
865 static int maxOperator;
866
867 void
868 makeOperatorVector()
869 {
870         List l;
871
872         maxOperator = 0;
873         for (l = operators; l; l = l->next) {
874                 Operator op = (Operator) l->x;
875                 if (op->num > maxOperator) {
876                         maxOperator = op->num;
877                 }
878         }
879         opVector = (Operator*) zalloc((maxOperator+1) * sizeof(*opVector));
880         for (l = operators; l; l = l->next) {
881                 Operator op = (Operator) l->x;
882                 if (opVector[op->num]) {
883                         fprintf(stderr, "ERROR: Non-unique external symbol number (%d)\n", op->num);
884                         exit(1);
885                 }
886                 opVector[op->num] = op;
887         }
888 }
889
890 void
891 makeOperators()
892 {
893         int i;
894
895         if (!opVector) {
896                 makeOperatorVector();
897         }
898         fprintf(outfile, "const char * %s_opname[] = {\n", prefix);
899         for (i = 0; i <= maxOperator; i++) {
900                 if (i > 0) {
901                         fprintf(outfile, ", /* %d */\n", i-1);
902                 }
903                 if (opVector[i]) {
904                         fprintf(outfile, "\t\"%s\"", opVector[i]->name);
905                 } else {
906                         fprintf(outfile, "\t0");
907                 }
908         }
909         fprintf(outfile, "\n};\n");
910         fprintf(outfile, "char %s_arity[] = {\n", prefix);
911         for (i = 0; i <= maxOperator; i++) {
912                 if (i > 0) {
913                         fprintf(outfile, ", /* %d */\n", i-1);
914                 }
915                 fprintf(outfile, "\t%d", opVector[i] ? opVector[i]->arity : -1);
916         }
917         fprintf(outfile, "\n};\n");
918         fprintf(outfile, "int %s_max_op = %d;\n", prefix, maxOperator);
919         fprintf(outfile, "int %s_max_state = %d;\n", prefix, globalMap->count-1);
920         fprintf(outfile, "#define %s_Max_state %d\n", prefix, globalMap->count-1);
921 }
922
923 void
924 makeDebug()
925 {
926         fprintf(outfile, "#ifdef DEBUG\n");
927         fprintf(outfile, "int %s_debug;\n", prefix);
928         fprintf(outfile, "#endif /* DEBUG */\n");
929 }
930
931 void
932 makeSimple()
933 {
934         makeRuleTable();
935         makeTables();
936         makeRule();
937         makeState();
938 }
939
940 void
941 startOptional()
942 {
943         fprintf(outfile, "#ifdef %s_STATE_LABEL\n", prefix);
944         fprintf(outfile, "#define %s_INCLUDE_EXTRA\n", prefix);
945         fprintf(outfile, "#else\n");
946         fprintf(outfile, "#ifdef STATE_LABEL\n");
947         fprintf(outfile, "#define %s_INCLUDE_EXTRA\n", prefix);
948         fprintf(outfile, "#define %s_STATE_LABEL \tSTATE_LABEL\n", prefix);
949         fprintf(outfile, "#define %s_NODEPTR_TYPE\tNODEPTR_TYPE\n", prefix);
950         fprintf(outfile, "#define %s_LEFT_CHILD  \tLEFT_CHILD\n", prefix);
951         fprintf(outfile, "#define %s_OP_LABEL    \tOP_LABEL\n", prefix);
952         fprintf(outfile, "#define %s_RIGHT_CHILD \tRIGHT_CHILD\n", prefix);
953         fprintf(outfile, "#endif /* STATE_LABEL */\n");
954         fprintf(outfile, "#endif /* %s_STATE_LABEL */\n\n", prefix);
955
956         fprintf(outfile, "#ifdef %s_INCLUDE_EXTRA\n\n", prefix);
957
958 }
959
960 void
961 makeNonterminals()
962 {
963         List l;
964
965         for (l = nonterminals; l; l = l->next) {
966                 NonTerminal nt = (NonTerminal) l->x;
967                 if (nt->num < last_user_nonterminal) {
968                         fprintf(outfile, "#define %s_%s_NT %d\n", prefix, nt->name, nt->num);
969                 }
970         }
971         fprintf(outfile, "#define %s_NT %d\n", prefix, last_user_nonterminal-1);
972 }
973
974 void
975 makeNonterminalArray()
976 {
977         int i;
978         List l;
979         NonTerminal *nta;
980
981         nta = (NonTerminal *) zalloc(sizeof(*nta) * last_user_nonterminal);
982
983         for (l = nonterminals; l; l = l->next) {
984                 NonTerminal nt = (NonTerminal) l->x;
985                 if (nt->num < last_user_nonterminal) {
986                         nta[nt->num] = nt;
987                 }
988         }
989
990         fprintf(outfile, "const char *%s_ntname[] = {\n", prefix);
991         fprintf(outfile, "\t\"Error: Nonterminals are > 0\",\n");
992         for (i = 1; i < last_user_nonterminal; i++) {
993                 fprintf(outfile, "\t\"%s\",\n", nta[i]->name);
994         }
995         fprintf(outfile, "\t0\n");
996         fprintf(outfile, "};\n\n");
997
998         zfree(nta);
999 }
1000
1001 void
1002 endOptional()
1003 {
1004         fprintf(outfile, "#endif /* %s_INCLUDE_EXTRA */\n", prefix);
1005 }
1006
1007 void
1008 startBurm()
1009 {
1010         fprintf(outfile, "#ifndef %s_PANIC\n", prefix);
1011         fprintf(outfile, "#define %s_PANIC\tPANIC\n", prefix);
1012         fprintf(outfile, "#endif /* %s_PANIC */\n", prefix);
1013         fprintf(outfile, "#ifdef __STDC__\n");
1014         fprintf(outfile, "extern void abort(void);\n");
1015         fprintf(outfile, "#else\n");
1016         fprintf(outfile, "extern void abort();\n");
1017         fprintf(outfile, "#endif\n");
1018         fprintf(outfile, "#ifdef NDEBUG\n");
1019         fprintf(outfile, "#define %s_assert(x,y)\t;\n", prefix);
1020         fprintf(outfile, "#else\n");
1021         fprintf(outfile, "#define %s_assert(x,y)\tif(!(x)) {y; abort();}\n", prefix);
1022         fprintf(outfile, "#endif\n");
1023 }
1024
1025 void
1026 reportDiagnostics()
1027 {
1028         List l;
1029
1030         for (l = operators; l; l = l->next) {
1031                 Operator op = (Operator) l->x;
1032                 if (!op->ref) {
1033                         fprintf(stderr, "warning: Unreferenced Operator: %s\n", op->name);
1034                 }
1035         }
1036         for (l = rules; l; l = l->next) {
1037                 Rule r = (Rule) l->x;
1038                 if (!r->used && r->num < max_ruleAST) {
1039                         fprintf(stderr, "warning: Unused Rule: #%d\n", r->erulenum);
1040                 }
1041         }
1042         if (!start->pmap) {
1043                 fprintf(stderr, "warning: Start Nonterminal (%s) does not appear on LHS.\n", start->name);
1044         }
1045
1046         fprintf(stderr, "start symbol = \"%s\"\n", start->name);
1047         fprintf(stderr, "# of states = %d\n", globalMap->count-1);
1048         fprintf(stderr, "# of nonterminals = %d\n", max_nonterminal-1);
1049         fprintf(stderr, "# of user nonterminals = %d\n", last_user_nonterminal-1);
1050         fprintf(stderr, "# of rules = %d\n", max_rule);
1051         fprintf(stderr, "# of user rules = %d\n", max_ruleAST);
1052 }