* monoburg.c (create_term): bug fix: g_strdup strings from the parser
[mono.git] / mono / monoburg / monoburg.c
1 /*
2  * monoburg.c: an iburg like code generator generator
3  *
4  * Author:
5  *   Dietmar Maurer (dietmar@ximian.com)
6  *
7  * (C) 2001 Ximian, Inc.
8  */
9
10 #include <stdio.h>
11
12 #include "monoburg.h"
13
14 extern void yyparse (void);
15
16 static GHashTable *term_hash;
17 static GList *term_list;
18 static GHashTable *nonterm_hash;
19 static GList *nonterm_list;
20 static GList *rule_list;
21
22 FILE *inputfd;
23 FILE *outputfd;
24 static FILE *deffd;
25
26 static void output (char *fmt, ...) 
27 {
28         va_list ap;
29
30         va_start(ap, fmt);
31         vfprintf (outputfd, fmt, ap);
32         va_end (ap);
33 }
34
35 void     
36 create_rule (char *id, Tree *tree, char *code, char *cost, char *cfunc)
37 {
38         Rule *rule = g_new0 (Rule, 1);
39
40         if (!cfunc && !cost)
41                 cost = "0";
42
43         rule->lhs = nonterm (id);
44         rule->tree = tree;
45         rule_list = g_list_append (rule_list, rule);
46         rule->cost = g_strdup (cost);
47         rule->cfunc = g_strdup (cfunc);
48         rule->code = g_strdup (code);
49
50         if (cfunc) {
51                 if (cost)
52                         yyerror ("duplicated costs (constant costs and cost function)");
53                 else 
54                         rule->cost = g_strdup_printf ("mono_burg_cost_%d (tree)",
55                                                       g_list_length (rule_list));
56         }
57
58         rule->lhs->rules = g_list_append (rule->lhs->rules, rule);
59
60         if (tree->op)
61                 tree->op->rules = g_list_append (tree->op->rules, rule);
62         else 
63                 tree->nonterm->chain = g_list_append (tree->nonterm->chain, rule);
64 }
65
66 Tree *
67 create_tree (char *id, Tree *left, Tree *right)
68 {
69         int arity = (left != NULL) + (right != NULL);
70         Term *term = g_hash_table_lookup (term_hash, id);
71         Tree *tree = g_new0 (Tree, 1);
72         
73         if (term) {
74                 if (term->arity == -1)
75                         term->arity = arity;
76
77                 if (term->arity != arity)
78                         yyerror ("changed arity of terminal %s from %d to %d",
79                                  id, term->arity, arity);
80
81                 tree->op = term;
82                 tree->left = left;
83                 tree->right = right;
84         } else {
85                 tree->nonterm = nonterm (id);
86         }
87
88         return tree;
89 }
90
91 static void
92 check_term_num (char *key, Term *value, int num)
93 {
94         if (num != -1 && value->number == num)
95                 yyerror ("duplicate terminal id \"%s\"", key);
96 }
97  
98 void  
99 create_term (char *id, int num)
100 {
101         Term *term;
102
103         if (nonterm_list)
104                 yyerror ("terminal definition after nonterminal definition");
105
106         if (num < -1)
107                 yyerror ("invalid terminal number %d", num);
108
109         if (!term_hash) 
110                 term_hash = g_hash_table_new (g_str_hash , g_str_equal);
111
112         g_hash_table_foreach (term_hash, (GHFunc) check_term_num, (gpointer) num);
113
114         term = g_new0 (Term, 1);
115
116         term->name = g_strdup (id);
117         term->number = num;
118         term->arity = -1;
119
120         term_list = g_list_append (term_list, term);
121
122         g_hash_table_insert (term_hash, term->name, term);
123 }
124
125 NonTerm *
126 nonterm (char *id)
127 {
128         NonTerm *nterm;
129
130         if (!nonterm_hash) 
131                 nonterm_hash = g_hash_table_new (g_str_hash , g_str_equal);
132
133         if ((nterm = g_hash_table_lookup (nonterm_hash, id)))
134                 return nterm;
135
136         nterm = g_new0 (NonTerm, 1);
137
138         nterm->name = g_strdup (id);
139         nonterm_list = g_list_append (nonterm_list, nterm);
140         nterm->number = g_list_length (nonterm_list);
141         
142         g_hash_table_insert (nonterm_hash, nterm->name, nterm);
143
144         return nterm;
145 }
146
147 void
148 start_nonterm (char *id)
149 {
150         static gboolean start_def;
151         
152         if (start_def)
153                 yyerror ("start symbol redeclared");
154         
155         start_def = TRUE;
156         nonterm (id); 
157 }
158
159 static void
160 emit_tree_string (Tree *tree)
161 {
162         if (tree->op) {
163                 output ("%s", tree->op->name);
164                 if (tree->op->arity) {
165                         output ("(");
166                         emit_tree_string (tree->left);
167                         if (tree->right) {
168                                 output (", ");
169                                 emit_tree_string (tree->right);
170                         }
171                         output (")");
172                 }
173         } else 
174                 output ("%s", tree->nonterm->name);
175 }
176
177 static void
178 emit_rule_string (Rule *rule, char *fill)
179 {
180         output ("%s/* ", fill);
181         
182         output ("%s: ", rule->lhs->name);
183
184         emit_tree_string (rule->tree);
185
186         output (" */\n");
187 }
188
189 static int
190 next_term_num ()
191 {
192         GList *l = term_list;
193         int i = 1;
194
195         while (l) {
196                 Term *t = (Term *)l->data;
197                 if (t->number == i) {
198                         l = term_list;
199                         i++;
200                 } else
201                         l = l->next;
202         }
203         return i;
204 }
205
206 static int
207 term_compare_func (Term *t1, Term *t2)
208 {
209         return t1->number - t2->number;
210 }
211
212 static void
213 emit_header ()
214 {
215         GList *l;
216
217         output ("#include <glib.h>\n");
218         output ("\n");
219
220         output ("#ifndef MBTREE_TYPE\n#error MBTREE_TYPE undefined\n#endif\n");
221         output ("#ifndef MBTREE_OP\n#define MBTREE_OP(t) ((t)->op)\n#endif\n");
222         output ("#ifndef MBTREE_LEFT\n#define MBTREE_LEFT(t) ((t)->left)\n#endif\n");
223         output ("#ifndef MBTREE_RIGHT\n#define MBTREE_RIGHT(t) ((t)->right)\n#endif\n");
224         output ("#ifndef MBTREE_STATE\n#define MBTREE_STATE(t) ((t)->state)\n#endif\n");
225         output ("#ifndef MBCGEN_TYPE\n#define MBCGEN_TYPE int\n#endif\n");
226
227         output ("\n");
228         output ("#define MBMAXCOST 32768\n");
229
230         output ("\n");
231         output ("#define MBCOND(x) if (!(x)) return MBMAXCOST;\n");
232
233         output ("\n");
234
235         for (l = term_list; l; l = l->next) {
236                 Term *t = (Term *)l->data;
237                 if (t->number == -1)
238                         t->number = next_term_num ();
239         }
240         term_list = g_list_sort (term_list, (GCompareFunc)term_compare_func);
241
242         for (l = term_list; l; l = l->next) {
243                 Term *t = (Term *)l->data;
244                 if (t->number == -1)
245                         t->number = next_term_num ();
246                 
247                 output ("#define MB_TERM_%s\t %d\n", t->name, t->number);
248
249         }
250         output ("\n");
251
252 }
253
254 static void
255 emit_nonterm ()
256 {
257         GList *l;
258
259         for (l = nonterm_list; l; l = l->next) {
260                 NonTerm *n = (NonTerm *)l->data;
261                 output ("#define MB_NTERM_%s\t%d\n", n->name, n->number);
262         }
263         output ("#define MB_MAX_NTERMS\t%d\n", g_list_length (nonterm_list));
264         output ("\n");
265 }
266
267 static void
268 emit_state ()
269 {
270         GList *l;
271         int i, j;
272
273         output ("typedef struct _MBState MBState;\n");
274         output ("struct _MBState {\n");
275         output ("\tint\t\t op;\n");
276         output ("\tMBState\t\t*left, *right;\n");
277         output ("\tguint16\t\tcost[%d];\n", g_list_length (nonterm_list) + 1);
278
279         for (l = nonterm_list; l; l = l->next) {
280                 NonTerm *n = (NonTerm *)l->data;
281                 g_assert (g_list_length (n->rules) < 256);
282                 i = g_list_length (n->rules);
283                 j = 1;
284                 while (i >>= 1)
285                         j++;
286                 output ("\tunsigned int\t rule_%s:%d;\n",  n->name, j); 
287         }
288         output ("};\n\n");
289 }
290
291 static void
292 emit_decoders ()
293 {
294         GList *l;
295         GList *rl;
296
297         for (l = nonterm_list; l; l = l->next) {
298                 NonTerm *n = (NonTerm *)l->data;
299                 output ("int mono_burg_decode_%s[] = {\n", n->name);
300                 output ("\t0,\n");
301                 for (rl = n->rules; rl; rl = rl->next) {
302                         Rule *rule = (Rule *)rl->data;
303                         output ("\t%d,\n", g_list_index (rule_list, rule) + 1);
304                 }
305                 
306                 output ("};\n\n");
307         }
308 }
309
310 static void
311 emit_tree_match (char *st, Tree *t)
312 {
313         char *tn;
314
315         output ("\t\t\t%sop == %d /* %s */", st, t->op->number, t->op->name);
316         
317         if (t->left && t->left->op) {
318                 tn = g_strconcat (st, "left->", NULL);
319                 output (" &&\n");
320                 emit_tree_match (tn, t->left);
321                 g_free (tn);
322         }
323
324         if (t->right && t->right->op) {
325                 tn = g_strconcat (st, "right->", NULL);
326                 output (" &&\n");
327                 emit_tree_match (tn, t->right);
328                 g_free (tn);
329         }
330 }
331
332 static void
333 emit_rule_match (Rule *rule)
334 {
335         Tree *t = rule->tree; 
336
337         if ((t->left && t->left->op) || 
338             (t->right && t->right->op)) {       
339                 output ("\t\tif (\n");
340                 emit_tree_match ("p->", t);
341                 output ("\n\t\t)\n");
342         }
343 }
344
345 static void
346 emit_costs (char *st, Tree *t)
347 {
348         char *tn;
349
350         if (t->op) {
351
352                 if (t->left) {
353                         tn = g_strconcat (st, "left->", NULL);
354                         emit_costs (tn, t->left);
355                         g_free (tn);
356                 }
357
358                 if (t->right) {
359                         tn = g_strconcat (st, "right->", NULL);
360                         emit_costs (tn, t->right);
361                 }
362         } else
363                 output ("%scost[MB_NTERM_%s] + ", st, t->nonterm->name);
364 }
365
366 static void
367 emit_cond_assign (Rule *rule, char *cost, char *fill)
368 {
369         char *rc;
370
371         if (cost)
372                 rc = g_strconcat ("c + ", cost, NULL);
373         else
374                 rc = g_strdup ("c");
375
376
377         output ("%sif (%s < p->cost[MB_NTERM_%s]) {\n", fill, rc, rule->lhs->name);
378
379         output ("%s\tp->cost[MB_NTERM_%s] = %s;\n", fill, rule->lhs->name, rc);
380
381         output ("%s\tp->rule_%s = %d;\n", fill, rule->lhs->name, 
382                 g_list_index (rule->lhs->rules, rule) + 1);
383
384         if (rule->lhs->chain)
385                 output ("%s\tclosure_%s (p, %s);\n", fill, rule->lhs->name, rc); 
386
387         output ("%s}\n", fill);
388
389         g_free (rc);
390         
391 }
392
393 static void
394 emit_label_func ()
395 {
396         GList *l;
397         int i;
398
399         output ("static MBState *\n");
400         output ("mono_burg_label_priv (MBTREE_TYPE *tree) {\n");
401
402         output ("\tint arity;\n");
403         output ("\tint c;\n");
404         output ("\tMBState *p, *left, *right;\n\n");
405
406         output ("\tswitch (mono_burg_arity [MBTREE_OP(tree)]) {\n");
407         output ("\tcase 0:\n");
408         output ("\t\tleft = NULL;\n");
409         output ("\t\tright = NULL;\n");
410         output ("\t\tbreak;\n");
411         output ("\tcase 1:\n");
412         output ("\t\tleft = mono_burg_label_priv (MBTREE_LEFT(tree));\n");
413         output ("\t\tright = NULL;\n");
414         output ("\t\tbreak;\n");
415         output ("\tcase 2:\n");
416         output ("\t\tleft = mono_burg_label_priv (MBTREE_LEFT(tree));\n");
417         output ("\t\tright = mono_burg_label_priv (MBTREE_RIGHT(tree));\n");
418         output ("\t}\n\n");
419
420         output ("\tarity = (left != NULL) + (right != NULL);\n");
421         output ("\tg_assert (arity == mono_burg_arity [MBTREE_OP(tree)]);\n\n");
422
423         output ("\tp = g_new0 (MBState, 1);\n");
424         output ("\tp->op = MBTREE_OP(tree);\n");
425         output ("\tp->left = left;\n");
426         output ("\tp->right = right;\n");
427         
428         for (l = nonterm_list, i = 0; l; l = l->next) {
429                 output ("\tp->cost [%d] = 32767;\n", ++i);
430         }
431         output ("\n");
432
433         output ("\tswitch (MBTREE_OP(tree)) {\n");
434         for (l = term_list; l; l = l->next) {
435                 Term *t = (Term *)l->data;
436                 GList *rl;
437                 output ("\tcase %d: /* %s */\n", t->number, t->name);
438
439                 for (rl = t->rules; rl; rl = rl->next) {
440                         Rule *rule = (Rule *)rl->data; 
441                         Tree *t = rule->tree;
442
443                         emit_rule_string (rule, "\t\t");
444
445                         emit_rule_match (rule);
446                         
447                         output ("\t\t{\n");
448
449                         output ("\t\t\tc = ");
450                         
451                         emit_costs ("", t);
452         
453                         output ("%s;\n", rule->cost);
454
455                         emit_cond_assign (rule, NULL, "\t\t\t");
456
457                         output ("\t\t}\n");
458                 }
459
460                 output ("\t\tbreak;\n");
461         }
462         
463         output ("\tdefault:\n");
464         output ("\t\tg_error (\"unknown operator\");\n");
465         output ("\t}\n\n");
466
467         output ("\tMBTREE_STATE(tree) = p;\n");
468
469         output ("\treturn p;\n");
470
471         output ("}\n\n");
472
473         output ("MBState *\n");
474         output ("mono_burg_label (MBTREE_TYPE *tree)\n{\n");
475         output ("\tMBState *p = mono_burg_label_priv (tree);\n");
476         output ("\treturn p->rule_%s ? p : NULL;\n", ((NonTerm *)nonterm_list->data)->name);
477         output ("}\n\n");
478 }
479
480 static char *
481 compute_kids (char *ts, Tree *tree, int *n)
482 {
483         char *res;
484
485         if (tree->nonterm) {
486                 return g_strdup_printf ("\t\tkids[%d] = %s;\n", (*n)++, ts);
487         } else if (tree->op && tree->op->arity) {
488                 char *res2 = NULL;
489
490                 res = compute_kids (g_strdup_printf ("MBTREE_LEFT(%s)", ts), 
491                                     tree->left, n);
492                 if (tree->op->arity == 2)
493                         res2 = compute_kids (g_strdup_printf ("MBTREE_RIGHT(%s)", ts), 
494                                              tree->right, n);
495                 return g_strconcat (res, res2, NULL);
496         }
497         return "";
498 }
499
500 static void
501 emit_kids ()
502 {
503         GList *l, *nl;
504         int i, j, c, n, *si;
505         char **sa;
506
507         output ("int\n");
508         output ("mono_burg_rule (MBState *state, int goal)\n{\n");
509
510         output ("\tg_return_val_if_fail (state != NULL, 0);\n"); 
511         output ("\tg_return_val_if_fail (goal > 0, 0);\n\n");
512
513         output ("\tswitch (goal) {\n");
514
515         for (nl = nonterm_list; nl; nl = nl->next) {
516                 NonTerm *n = (NonTerm *)nl->data;
517                 output ("\tcase MB_NTERM_%s:\n", n->name);
518                 output ("\t\treturn mono_burg_decode_%s [state->rule_%s];\n",
519                         n->name, n->name);
520         }
521
522         output ("\tdefault: g_assert_not_reached ();\n");
523         output ("\t}\n");
524         output ("\treturn 0;\n");
525         output ("}\n\n");
526
527
528         output ("MBTREE_TYPE **\n");
529         output ("mono_burg_kids (MBTREE_TYPE *tree, int rulenr, MBTREE_TYPE *kids [])\n{\n");
530         output ("\tg_return_val_if_fail (tree != NULL, NULL);\n");
531         output ("\tg_return_val_if_fail (MBTREE_STATE(tree) != NULL, NULL);\n");
532         output ("\tg_return_val_if_fail (kids != NULL, NULL);\n\n");
533
534         output ("\tswitch (rulenr) {\n");
535
536         n = g_list_length (rule_list);
537         sa = g_new0 (char *, n);
538         si = g_new0 (int, n);
539
540         /* compress the case statement */
541         for (l = rule_list, i = 0, c = 0; l; l = l->next) {
542                 Rule *rule = (Rule *)l->data;
543                 int kn = 0;
544                 char *k;
545
546                 k = compute_kids ("tree", rule->tree, &kn);
547                 for (j = 0; j < c; j++)
548                         if (!strcmp (sa [j], k))
549                                 break;
550
551                 si [i++] = j;
552                 if (j == c)
553                         sa [c++] = k;
554         }
555
556         for (i = 0; i < c; i++) {
557                 for (l = rule_list, j = 0; l; l = l->next, j++)
558                         if (i == si [j])
559                                 output ("\tcase %d:\n", j + 1);
560                 output ("%s", sa [i]);
561                 output ("\t\tbreak;\n");
562         }
563
564         output ("\tdefault:\n\t\tg_assert_not_reached ();\n");
565         output ("\t}\n");
566         output ("\treturn kids;\n");
567         output ("}\n\n");
568
569 }
570
571 static void
572 emit_emitter_func ()
573 {
574         GList *l;
575         int i;
576
577         for (l =  rule_list, i = 0; l; l = l->next) {
578                 Rule *rule = (Rule *)l->data;
579                 
580                 if (rule->code) {
581                         output ("static void ");
582
583                         emit_rule_string (rule, "");
584
585                         output ("mono_burg_emit_%d (MBTREE_TYPE *tree, MBCGEN_TYPE *s)\n", i);
586                         output ("{\n");
587                         output ("%s\n", rule->code);
588                         output ("}\n\n");
589                 }
590                 i++;
591         }
592
593         output ("MBEmitFunc mono_burg_func [] = {\n");
594         output ("\tNULL,\n");
595         for (l =  rule_list, i = 0; l; l = l->next) {
596                 Rule *rule = (Rule *)l->data;
597                 if (rule->code)
598                         output ("\tmono_burg_emit_%d,\n", i);
599                 else
600                         output ("\tNULL,\n");
601                 i++;
602         }
603         output ("};\n\n");
604 }
605
606 static void
607 emit_cost_func ()
608 {
609         GList *l;
610         int i;
611
612         for (l =  rule_list, i = 0; l; l = l->next) {
613                 Rule *rule = (Rule *)l->data;
614                 
615                 if (rule->cfunc) {
616                         output ("static guint16\n");
617
618                         emit_rule_string (rule, "");
619
620                         output ("mono_burg_cost_%d (MBTREE_TYPE *tree)\n", i + 1);
621                         output ("{\n");
622                         output ("%s\n", rule->cfunc);
623                         output ("}\n\n");
624                 }
625                 i++;
626         }
627 }
628
629 static void
630 emit_closure ()
631 {
632         GList *l, *rl;
633
634         for (l = nonterm_list; l; l = l->next) {
635                 NonTerm *n = (NonTerm *)l->data;
636                 
637                 if (n->chain)
638                         output ("static void closure_%s (MBState *p, int c);\n", n->name);
639         }
640
641         output ("\n");
642
643         for (l = nonterm_list; l; l = l->next) {
644                 NonTerm *n = (NonTerm *)l->data;
645                 
646                 if (n->chain) {
647                         output ("static void\n");
648                         output ("closure_%s (MBState *p, int c)\n{\n", n->name);
649                         for (rl = n->chain; rl; rl = rl->next) {
650                                 Rule *rule = (Rule *)rl->data;
651                                 
652                                 emit_rule_string (rule, "\t");
653                                 emit_cond_assign (rule, rule->cost, "\t");
654                         }
655                         output ("}\n\n");
656                 }
657         }
658 }
659
660 static char *
661 compute_nonterms (Tree *tree)
662 {
663         if (!tree)
664                 return "";
665
666         if (tree->nonterm) {
667                 return g_strdup_printf ("MB_NTERM_%s, ", tree->nonterm->name);
668         } else {
669                 return g_strconcat (compute_nonterms (tree->left),
670                                     compute_nonterms (tree->right), NULL);
671         } 
672 }
673
674 static void
675 emit_vardefs ()
676 {
677         GList *l;
678         int i, j, c, n, *si;
679         char **sa;
680
681         output ("guint8 mono_burg_arity [] = {\n"); 
682         for (l = term_list, i = 0; l; l = l->next) {
683                 Term *t = (Term *)l->data;
684
685                 while (i < t->number) {
686                         output ("\t0,\n");
687                         i++;
688                 }
689                 
690                 output ("\t%d, /* %s */\n", t->arity, t->name);
691
692                 i++;
693         }
694         output ("};\n\n");
695
696         output ("char *mono_burg_term_string [] = {\n");
697         output ("\tNULL,\n");
698         for (l = term_list, i = 0; l; l = l->next) {
699                 Term *t = (Term *)l->data;
700                 output ("\t\"%s\",\n", t->name);
701         }
702         output ("};\n\n");
703
704         output ("char *mono_burg_rule_string [] = {\n");
705         output ("\tNULL,\n");
706         for (l = rule_list, i = 0; l; l = l->next) {
707                 Rule *rule = (Rule *)l->data;
708                 output ("\t\"%s: ", rule->lhs->name);
709                 emit_tree_string (rule->tree);
710                 output ("\",\n");
711         }
712         output ("};\n\n");
713
714         n = g_list_length (rule_list);
715         sa = g_new0 (char *, n);
716         si = g_new0 (int, n);
717
718         /* compress the _nts array */
719         for (l = rule_list, i = 0, c = 0; l; l = l->next) {
720                 Rule *rule = (Rule *)l->data;
721                 char *s = compute_nonterms (rule->tree);
722
723                 for (j = 0; j < c; j++)
724                         if (!strcmp (sa [j], s))
725                                 break;
726
727                 si [i++] = j;
728                 if (j == c) {
729                         output ("static guint16 mono_burg_nts_%d [] = { %s0 };\n", c, s);
730                         sa [c++] = s;
731                 }
732         }       
733         output ("\n");
734
735         output ("guint16 *mono_burg_nts [] = {\n");
736         output ("\t0,\n");
737         for (l = rule_list, i = 0; l; l = l->next) {
738                 Rule *rule = (Rule *)l->data;
739                 output ("\tmono_burg_nts_%d, ", si [i++]);
740                 emit_rule_string (rule, "");
741         }
742         output ("};\n\n");
743 }
744
745 static void
746 emit_prototypes ()
747 {
748         output ("typedef void (*MBEmitFunc) (MBTREE_TYPE *tree, MBCGEN_TYPE *s);\n\n");
749
750         output ("extern char *mono_burg_term_string [];\n");
751         output ("extern char *mono_burg_rule_string [];\n");
752         output ("extern guint16 *mono_burg_nts [];\n");
753         output ("extern MBEmitFunc mono_burg_func [];\n");
754
755         output ("MBState *mono_burg_label (MBTREE_TYPE *tree);\n");
756         output ("int mono_burg_rule (MBState *state, int goal);\n");
757         output ("MBTREE_TYPE **mono_burg_kids (MBTREE_TYPE *tree, int rulenr, MBTREE_TYPE *kids []);\n");
758
759         output ("\n");
760 }
761
762 static void check_reach (NonTerm *n);
763
764 static void
765 mark_reached (Tree *tree)
766 {
767         if (tree->nonterm && !tree->nonterm->reached)
768                 check_reach (tree->nonterm);
769         if (tree->left)
770                 mark_reached (tree->left);
771         if (tree->right)
772                 mark_reached (tree->right);
773 }
774
775 static void
776 check_reach (NonTerm *n)
777 {
778         GList *l;
779
780         n->reached = 1;
781         for (l = n->rules; l; l = l->next) {
782                 Rule *rule = (Rule *)l->data;
783                 mark_reached (rule->tree);
784         }
785 }
786
787 static void
788 check_result ()
789 {
790         GList *l;
791
792         for (l = term_list; l; l = l->next) {
793                 Term *term = (Term *)l->data;
794                 if (term->arity == -1)
795                         g_warning ("unused terminal \"%s\"",term->name);
796         } 
797
798         check_reach (((NonTerm *)nonterm_list->data));
799
800         for (l = nonterm_list; l; l = l->next) {
801                 NonTerm *n = (NonTerm *)l->data;
802                 if (!n->reached)
803                         g_error ("unreachable nonterm \"%s\"", n->name);
804         }
805 }
806
807 static void
808 usage ()
809 {
810         fprintf (stderr,
811                  "Usage is: monoburg [-d file] [file] \n");
812         exit (1);
813 }
814
815 int
816 main (int argc, char *argv [])
817 {
818         char *deffile = NULL;
819         char *infile = NULL;
820         int i;
821
822         for (i = 1; i < argc; i++){
823                 if (argv [i][0] == '-'){
824                         if (argv [i][1] == 'h') {
825                                 usage ();
826                         } else if (argv [i][1] == 'd') {
827                                 deffile = argv [++i];
828                         } else {
829                                 usage ();
830                         }
831                 } else {
832                         if (infile)
833                                 usage ();
834                         else
835                                 infile = argv [i];
836                 }
837         }
838
839         if (deffile) {
840                 if (!(deffd = fopen (deffile, "w"))) {
841                         perror ("cant open header output file");
842                         exit (-1);
843                 }
844                 outputfd = deffd;
845                 output ("#ifndef _MONO_BURG_DEFS_\n");
846                 output ("#define _MONO_BURG_DEFS_\n\n");
847         } else 
848                 outputfd = stdout;
849
850
851         if (infile) {
852                 if (!(inputfd = fopen (infile, "r"))) {
853                         perror ("cant open input file");
854                         exit (-1);
855                 }
856         } else {
857                 inputfd = stdin;
858         }
859
860         yyparse ();
861
862         check_result ();
863
864         if (!nonterm_list)
865                 g_error ("no start symbol found");
866
867         emit_header ();
868         emit_nonterm ();
869         emit_state ();
870         emit_prototypes ();
871
872         if (deffd) {
873                 output ("#endif /* _MONO_BURG_DEFS_ */\n");
874                 fclose (deffd);
875                 outputfd = stdout;
876
877                 output ("#include \"%s\"\n\n", deffile);
878         }
879         
880         emit_vardefs ();
881         emit_cost_func ();
882         emit_emitter_func ();
883         emit_decoders ();
884
885         emit_closure ();
886         emit_label_func ();
887
888         emit_kids ();
889
890         yyparsetail ();
891
892         if (infile)
893                 fclose (inputfd);
894
895
896         return 0;
897 }