Imported Upstream version 20100216
[platform/upstream/byacc.git] / main.c
1 /* $Id: main.c,v 1.24 2010/02/17 00:43:08 tom Exp $ */
2
3 #include <signal.h>
4 #include <unistd.h>             /* for _exit() */
5
6 #include "defs.h"
7
8 char dflag;
9 char gflag;
10 char lflag;
11 char oflag;
12 char rflag;
13 char tflag;
14 char vflag;
15
16 const char *symbol_prefix;
17 const char *myname = "yacc";
18
19 int lineno;
20 int outline;
21
22 static char empty_string[] = "";
23 static char default_file_prefix[] = "y";
24
25 static char *file_prefix = default_file_prefix;
26
27 char *code_file_name;
28 char *defines_file_name;
29 char *input_file_name = empty_string;
30 char *output_file_name = 0;
31 char *verbose_file_name;
32 char *graph_file_name;
33
34 FILE *action_file;      /*  a temp file, used to save actions associated    */
35                         /*  with rules until the parser is written          */
36 FILE *code_file;        /*  y.code.c (used when the -r option is specified) */
37 FILE *defines_file;     /*  y.tab.h                                         */
38 FILE *input_file;       /*  the input file                                  */
39 FILE *output_file;      /*  y.tab.c                                         */
40 FILE *text_file;        /*  a temp file, used to save text until all        */
41                         /*  symbols have been defined                       */
42 FILE *union_file;       /*  a temp file, used to save the union             */
43                         /*  definition until all symbol have been           */
44                         /*  defined                                         */
45 FILE *verbose_file;     /*  y.output                                        */
46 FILE *graph_file;       /*  y.dot                                           */
47
48 int nitems;
49 int nrules;
50 int nsyms;
51 int ntokens;
52 int nvars;
53
54 Value_t start_symbol;
55 char **symbol_name;
56 char **symbol_pname;
57 Value_t *symbol_value;
58 short *symbol_prec;
59 char *symbol_assoc;
60
61 int pure_parser;
62 int exit_code;
63
64 Value_t *ritem;
65 Value_t *rlhs;
66 Value_t *rrhs;
67 Value_t *rprec;
68 Assoc_t *rassoc;
69 Value_t **derives;
70 char *nullable;
71
72 /*
73  * Since fclose() is called via the signal handler, it might die.  Don't loop
74  * if there is a problem closing a file.
75  */
76 #define DO_CLOSE(fp) \
77         if (fp != 0) { \
78             FILE *use = fp; \
79             fp = 0; \
80             fclose(use); \
81         }
82
83 static int got_intr = 0;
84
85 void
86 done(int k)
87 {
88     DO_CLOSE(input_file);
89     DO_CLOSE(output_file);
90
91     DO_CLOSE(action_file);
92     DO_CLOSE(defines_file);
93     DO_CLOSE(graph_file);
94     DO_CLOSE(text_file);
95     DO_CLOSE(union_file);
96     DO_CLOSE(verbose_file);
97
98     if (got_intr)
99         _exit(EXIT_FAILURE);
100
101 #ifdef NO_LEAKS
102     if (rflag)
103         DO_FREE(code_file_name);
104
105     if (dflag)
106         DO_FREE(defines_file_name);
107
108     if (oflag)
109         DO_FREE(output_file_name);
110
111     if (vflag)
112         DO_FREE(verbose_file_name);
113
114     if (gflag)
115         DO_FREE(graph_file_name);
116
117     lr0_leaks();
118     lalr_leaks();
119     mkpar_leaks();
120     output_leaks();
121     reader_leaks();
122 #endif
123
124     exit(k);
125 }
126
127 static void
128 onintr(int sig GCC_UNUSED)
129 {
130     got_intr = 1;
131     done(EXIT_FAILURE);
132 }
133
134 static void
135 set_signals(void)
136 {
137 #ifdef SIGINT
138     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
139         signal(SIGINT, onintr);
140 #endif
141 #ifdef SIGTERM
142     if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
143         signal(SIGTERM, onintr);
144 #endif
145 #ifdef SIGHUP
146     if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
147         signal(SIGHUP, onintr);
148 #endif
149 }
150
151 static void
152 usage(void)
153 {
154     static const char *msg[] =
155     {
156         ""
157         ,"Options:"
158         ,"  -b file_prefix        set filename prefix (default \"y.\")"
159         ,"  -d                    write definitions (y.tab.h)"
160         ,"  -g                    write a graphical description"
161         ,"  -l                    suppress #line directives"
162         ,"  -o output_file        (default \"y.tab.c\")"
163         ,"  -p symbol_prefix      set symbol prefix (default \"yy\")"
164         ,"  -r                    produce separate code and table files (y.code.c)"
165         ,"  -t                    add debugging support"
166         ,"  -v                    write description (y.output)"
167         ,"  -V                    show version information and exit"
168     };
169     unsigned n;
170
171     fflush(stdout);
172     fprintf(stderr, "Usage: %s [options] filename\n", myname);
173     for (n = 0; n < sizeof(msg) / sizeof(msg[0]); ++n)
174         fprintf(stderr, "%s\n", msg[n]);
175
176     exit(1);
177 }
178
179 static void
180 setflag(int ch)
181 {
182     switch (ch)
183     {
184     case 'd':
185         dflag = 1;
186         break;
187
188     case 'g':
189         gflag = 1;
190         break;
191
192     case 'l':
193         lflag = 1;
194         break;
195
196     case 'P':
197         pure_parser = 1;
198         break;
199
200     case 'r':
201         rflag = 1;
202         break;
203
204     case 't':
205         tflag = 1;
206         break;
207
208     case 'v':
209         vflag = 1;
210         break;
211
212     case 'V':
213         printf("%s - %s\n", myname, VERSION);
214         exit(EXIT_SUCCESS);
215
216     default:
217         usage();
218     }
219 }
220
221 static void
222 getargs(int argc, char *argv[])
223 {
224     int i;
225     char *s;
226     int ch;
227
228     if (argc > 0)
229         myname = argv[0];
230
231     for (i = 1; i < argc; ++i)
232     {
233         s = argv[i];
234         if (*s != '-')
235             break;
236         switch (ch = *++s)
237         {
238         case '\0':
239             input_file = stdin;
240             if (i + 1 < argc)
241                 usage();
242             return;
243
244         case '-':
245             ++i;
246             goto no_more_options;
247
248         case 'b':
249             if (*++s)
250                 file_prefix = s;
251             else if (++i < argc)
252                 file_prefix = argv[i];
253             else
254                 usage();
255             continue;
256
257         case 'o':
258             if (*++s)
259                 output_file_name = s;
260             else if (++i < argc)
261                 output_file_name = argv[i];
262             else
263                 usage();
264             continue;
265
266         case 'p':
267             if (*++s)
268                 symbol_prefix = s;
269             else if (++i < argc)
270                 symbol_prefix = argv[i];
271             else
272                 usage();
273             continue;
274
275         default:
276             setflag(ch);
277             break;
278         }
279
280         for (;;)
281         {
282             switch (ch = *++s)
283             {
284             case '\0':
285                 goto end_of_option;
286
287             default:
288                 setflag(ch);
289                 break;
290             }
291         }
292       end_of_option:;
293     }
294
295   no_more_options:;
296     if (i + 1 != argc)
297         usage();
298     input_file_name = argv[i];
299 }
300
301 char *
302 allocate(unsigned n)
303 {
304     char *p;
305
306     p = NULL;
307     if (n)
308     {
309         p = CALLOC(1, n);
310         if (!p)
311             no_space();
312     }
313     return (p);
314 }
315
316 #define CREATE_FILE_NAME(dest, suffix) \
317         dest = MALLOC(len + strlen(suffix) + 1); \
318         if (dest == 0) \
319             no_space(); \
320         strcpy(dest, file_prefix); \
321         strcpy(dest + len, suffix)
322
323 static void
324 create_file_names(void)
325 {
326     size_t len;
327     const char *defines_suffix;
328     char *prefix;
329
330     prefix = NULL;
331     defines_suffix = DEFINES_SUFFIX;
332
333     /* compute the file_prefix from the user provided output_file_name */
334     if (output_file_name != 0)
335     {
336         if (!(prefix = strstr(output_file_name, ".tab.c"))
337             && (prefix = strstr(output_file_name, ".c")))
338             defines_suffix = ".h";
339     }
340
341     if (prefix != NULL)
342     {
343         len = (size_t) (prefix - output_file_name);
344         file_prefix = (char *)MALLOC(len + 1);
345         if (file_prefix == 0)
346             no_space();
347         strncpy(file_prefix, output_file_name, len)[len] = 0;
348     }
349     else
350         len = strlen(file_prefix);
351
352     /* if "-o filename" was not given */
353     if (output_file_name == 0)
354     {
355         oflag = 1;
356         CREATE_FILE_NAME(output_file_name, OUTPUT_SUFFIX);
357     }
358
359     if (rflag)
360     {
361         CREATE_FILE_NAME(code_file_name, CODE_SUFFIX);
362     }
363     else
364         code_file_name = output_file_name;
365
366     if (dflag)
367     {
368         CREATE_FILE_NAME(defines_file_name, defines_suffix);
369     }
370
371     if (vflag)
372     {
373         CREATE_FILE_NAME(verbose_file_name, VERBOSE_SUFFIX);
374     }
375
376     if (gflag)
377     {
378         CREATE_FILE_NAME(graph_file_name, GRAPH_SUFFIX);
379     }
380
381     if (prefix != NULL)
382     {
383         FREE(file_prefix);
384     }
385 }
386
387 static void
388 open_files(void)
389 {
390     create_file_names();
391
392     if (input_file == 0)
393     {
394         input_file = fopen(input_file_name, "r");
395         if (input_file == 0)
396             open_error(input_file_name);
397     }
398
399     action_file = tmpfile();
400     if (action_file == 0)
401         open_error("action_file");
402
403     text_file = tmpfile();
404     if (text_file == 0)
405         open_error("text_file");
406
407     if (vflag)
408     {
409         verbose_file = fopen(verbose_file_name, "w");
410         if (verbose_file == 0)
411             open_error(verbose_file_name);
412     }
413
414     if (gflag)
415     {
416         graph_file = fopen(graph_file_name, "w");
417         if (graph_file == 0)
418             open_error(graph_file_name);
419         fprintf(graph_file, "digraph %s {\n", file_prefix);
420         fprintf(graph_file, "\tedge [fontsize=10];\n");
421         fprintf(graph_file, "\tnode [shape=box,fontsize=10];\n");
422         fprintf(graph_file, "\torientation=landscape;\n");
423         fprintf(graph_file, "\trankdir=LR;\n");
424         fprintf(graph_file, "\t/*\n");
425         fprintf(graph_file, "\tmargin=0.2;\n");
426         fprintf(graph_file, "\tpage=\"8.27,11.69\"; // for A4 printing\n");
427         fprintf(graph_file, "\tratio=auto;\n");
428         fprintf(graph_file, "\t*/\n");
429     }
430
431     if (dflag)
432     {
433         defines_file = fopen(defines_file_name, "w");
434         if (defines_file == 0)
435             open_error(defines_file_name);
436         union_file = tmpfile();
437         if (union_file == 0)
438             open_error("union_file");
439     }
440
441     output_file = fopen(output_file_name, "w");
442     if (output_file == 0)
443         open_error(output_file_name);
444
445     if (rflag)
446     {
447         code_file = fopen(code_file_name, "w");
448         if (code_file == 0)
449             open_error(code_file_name);
450     }
451     else
452         code_file = output_file;
453 }
454
455 int
456 main(int argc, char *argv[])
457 {
458     SRexpect = -1;
459     RRexpect = -1;
460     exit_code = EXIT_SUCCESS;
461
462     set_signals();
463     getargs(argc, argv);
464     open_files();
465     reader();
466     lr0();
467     lalr();
468     make_parser();
469     graph();
470     finalize_closure();
471     verbose();
472     output();
473     done(exit_code);
474     /*NOTREACHED */
475 }