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