Initial import of binutils 2.22 on the new vendor branch
[dragonfly.git] / usr.bin / yacc / main.c
1 /*
2  * Copyright (c) 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Robert Paul Corbett.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by the University of
19  *      California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  * @(#) Copyright (c) 1989 The Regents of the University of California. All rights reserved.
37  * @(#)main.c   5.5 (Berkeley) 5/24/93
38  * $FreeBSD: src/usr.bin/yacc/main.c,v 1.12 2000/01/10 20:26:24 kris Exp $
39  * $DragonFly: src/usr.bin/yacc/main.c,v 1.6 2006/01/22 13:38:50 swildner Exp $
40  */
41
42 #include <signal.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <unistd.h>
46 #include "defs.h"
47
48 char dflag;
49 char lflag;
50 char rflag;
51 char tflag;
52 char vflag;
53
54 const char *symbol_prefix;
55 const char *file_prefix = "y";
56 const char *temp_form = "yacc.XXXXXXXXXXX";
57
58 int lineno;
59 int outline;
60
61 char *action_file_name;
62 char *code_file_name;
63 char *defines_file_name;
64 const char *input_file_name = "";
65 char *output_file_name;
66 char *text_file_name;
67 char *union_file_name;
68 char *verbose_file_name;
69
70 FILE *action_file;      /*  a temp file, used to save actions associated    */
71                         /*  with rules until the parser is written          */
72 FILE *code_file;        /*  y.code.c (used when the -r option is specified) */
73 FILE *defines_file;     /*  y.tab.h                                         */
74 FILE *input_file;       /*  the input file                                  */
75 FILE *output_file;      /*  y.tab.c                                         */
76 FILE *text_file;        /*  a temp file, used to save text until all        */
77                         /*  symbols have been defined                       */
78 FILE *union_file;       /*  a temp file, used to save the union             */
79                         /*  definition until all symbol have been           */
80                         /*  defined                                         */
81 FILE *verbose_file;     /*  y.output                                        */
82
83 int nitems;
84 int nrules;
85 int nsyms;
86 int ntokens;
87 int nvars;
88
89 int   start_symbol;
90 char  **symbol_name;
91 short *symbol_value;
92 short *symbol_prec;
93 char  *symbol_assoc;
94
95 short *ritem;
96 short *rlhs;
97 short *rrhs;
98 short *rprec;
99 char  *rassoc;
100 short **derives;
101 char *nullable;
102
103 static void cleanup(void);
104 static void create_file_names(void);
105 static void getargs(int, char **);
106 static void onintr(int);
107 static void open_files(void);
108 static void set_signals(void);
109 static void usage(void);
110
111
112 static void
113 cleanup(void)
114 {
115     if (action_file) { fclose(action_file); unlink(action_file_name); }
116     if (text_file) { fclose(text_file); unlink(text_file_name); }
117     if (union_file) { fclose(union_file); unlink(union_file_name); }
118 }
119
120
121 static void
122 onintr(int signo __unused)
123 {
124     if (action_file)
125         unlink(action_file_name);
126     if (text_file)
127         unlink(text_file_name);
128     if (union_file)
129         unlink(union_file_name);
130     _exit(1);
131 }
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
152 static void
153 usage(void)
154 {
155     fprintf(stderr, "%s\n%s\n",
156                 "usage: yacc [-dlrtv] [-b file_prefix] [-o output_filename]",
157                 "            [-p symbol_prefix] filename");
158     exit(1);
159 }
160
161
162 static void
163 getargs(int argc, char **argv)
164 {
165     int i;
166     char *s;
167
168     for (i = 1; i < argc; ++i)
169     {
170         s = argv[i];
171         if (*s != '-') break;
172         switch (*++s)
173         {
174         case '\0':
175             input_file = stdin;
176             if (i + 1 < argc) usage();
177             return;
178
179         case '-':
180             ++i;
181             goto no_more_options;
182
183         case 'b':
184             if (*++s)
185                  file_prefix = s;
186             else if (++i < argc)
187                 file_prefix = argv[i];
188             else
189                 usage();
190             continue;
191
192         case 'd':
193             dflag = 1;
194             break;
195
196         case 'l':
197             lflag = 1;
198             break;
199
200         case 'o':
201             if (*++s)
202                 output_file_name = s;
203             else if (++i < argc)
204                 output_file_name = argv[i];
205             else
206                 usage();
207             continue;
208
209         case 'p':
210             if (*++s)
211                 symbol_prefix = s;
212             else if (++i < argc)
213                 symbol_prefix = argv[i];
214             else
215                 usage();
216             continue;
217
218         case 'r':
219             rflag = 1;
220             break;
221
222         case 't':
223             tflag = 1;
224             break;
225
226         case 'v':
227             vflag = 1;
228             break;
229
230         default:
231             usage();
232         }
233
234         for (;;)
235         {
236             switch (*++s)
237             {
238             case '\0':
239                 goto end_of_option;
240
241             case 'd':
242                 dflag = 1;
243                 break;
244
245             case 'l':
246                 lflag = 1;
247                 break;
248
249             case 'r':
250                 rflag = 1;
251                 break;
252
253             case 't':
254                 tflag = 1;
255                 break;
256
257             case 'v':
258                 vflag = 1;
259                 break;
260
261             default:
262                 usage();
263             }
264         }
265 end_of_option:;
266     }
267
268 no_more_options:;
269     if (i + 1 != argc) usage();
270     input_file_name = argv[i];
271 }
272
273
274 char *
275 allocate(unsigned n)
276 {
277     char *p;
278
279     p = NULL;
280     if (n)
281     {
282         p = CALLOC(1, n);
283         if (!p) no_space();
284     }
285     return (p);
286 }
287
288
289 static void
290 create_file_names(void)
291 {
292     int i, len;
293     const char *tmpdir;
294
295     tmpdir = getenv("TMPDIR");
296     if (tmpdir == 0) tmpdir = "/tmp";
297
298     len = strlen(tmpdir);
299     i = len + 17;
300     if (len && tmpdir[len-1] != '/')
301         ++i;
302
303     action_file_name = MALLOC(i);
304     if (action_file_name == 0) no_space();
305     text_file_name = MALLOC(i);
306     if (text_file_name == 0) no_space();
307     union_file_name = MALLOC(i);
308     if (union_file_name == 0) no_space();
309
310     strcpy(action_file_name, tmpdir);
311     strcpy(text_file_name, tmpdir);
312     strcpy(union_file_name, tmpdir);
313
314     if (len && tmpdir[len - 1] != '/')
315     {
316         action_file_name[len] = '/';
317         text_file_name[len] = '/';
318         union_file_name[len] = '/';
319         ++len;
320     }
321
322     strcpy(action_file_name + len, temp_form);
323     strcpy(text_file_name + len, temp_form);
324     strcpy(union_file_name + len, temp_form);
325
326     action_file_name[len + 5] = 'a';
327     text_file_name[len + 5] = 't';
328     union_file_name[len + 5] = 'u';
329
330     if (output_file_name != 0)
331     {
332         file_prefix = output_file_name;
333         len = strlen(file_prefix);
334     }
335     else
336     {
337         len = strlen(file_prefix);
338         output_file_name = MALLOC(len + 7);
339         if (output_file_name == 0)
340             no_space();
341         strcpy(output_file_name, file_prefix);
342         strcpy(output_file_name + len, OUTPUT_SUFFIX);
343     }
344
345     if (rflag)
346     {
347         code_file_name = MALLOC(len + 8);
348         if (code_file_name == 0)
349             no_space();
350         strcpy(code_file_name, file_prefix);
351         if (file_prefix == output_file_name)
352         {
353             /*
354              * XXX ".tab.c" here is OUTPUT_SUFFIX, but since its length is
355              * in various magic numbers, don't bother using the macro.
356              */
357             if (len >= 6 && strcmp(code_file_name + len - 6, ".tab.c") == 0)
358                 strcpy(code_file_name + len - 6, CODE_SUFFIX);
359             else if (len >= 2 && strcmp(code_file_name + len - 2, ".c") == 0)
360                 strcpy(code_file_name + len - 2, CODE_SUFFIX);
361             else
362                 strcpy(code_file_name + len, CODE_SUFFIX);
363         }
364         else
365             strcpy(code_file_name + len, CODE_SUFFIX);
366     }
367     else
368         code_file_name = output_file_name;
369
370     if (dflag)
371     {
372         defines_file_name = MALLOC(len + 7);
373         if (defines_file_name == 0)
374             no_space();
375         strcpy(defines_file_name, file_prefix);
376         if (file_prefix == output_file_name)
377         {
378 #define BISON_DEFINES_SUFFIX  ".h"
379             if (len >= 2 && strcmp(defines_file_name + len - 2, ".c") == 0)
380                 strcpy(defines_file_name + len - 2, BISON_DEFINES_SUFFIX);
381             else
382                 strcpy(defines_file_name + len, BISON_DEFINES_SUFFIX);
383         }
384         else
385             strcpy(defines_file_name + len, DEFINES_SUFFIX);
386     }
387
388     if (vflag)
389     {
390         verbose_file_name = MALLOC(len + 8);
391         if (verbose_file_name == 0)
392             no_space();
393         strcpy(verbose_file_name, file_prefix);
394         if (file_prefix == output_file_name)
395         {
396             if (len >= 6 && strcmp(verbose_file_name + len - 6, ".tab.c") == 0)
397                 strcpy(verbose_file_name + len - 6, VERBOSE_SUFFIX);
398             else if (len >= 2 && strcmp(verbose_file_name + len - 2, ".c") == 0)
399                 strcpy(verbose_file_name + len - 2, VERBOSE_SUFFIX);
400             else
401                 strcpy(verbose_file_name + len, VERBOSE_SUFFIX);
402         }
403         else
404             strcpy(verbose_file_name + len, VERBOSE_SUFFIX);
405     }
406 }
407
408
409 static void
410 open_files(void)
411 {
412     int fd;
413
414     create_file_names();
415
416     if (input_file == 0)
417     {
418         input_file = fopen(input_file_name, "r");
419         if (input_file == 0)
420             open_error(input_file_name);
421     }
422
423     fd = mkstemp(action_file_name);
424     if (fd < 0 || (action_file = fdopen(fd, "w")) == NULL) {
425         if (fd >= 0)
426             close(fd);
427         open_error(action_file_name);
428     }
429     fd = mkstemp(text_file_name);
430     if (fd < 0 || (text_file = fdopen(fd, "w")) == NULL) {
431         if (fd >= 0)
432             close(fd);
433         open_error(text_file_name);
434     }
435     fd = mkstemp(union_file_name);
436     if (fd < 0 || (union_file = fdopen(fd, "w")) == NULL) {
437         if (fd >= 0)
438             close(fd);
439         open_error(union_file_name);
440     }
441
442     text_file = fopen(text_file_name, "w");
443     if (text_file == 0)
444         open_error(text_file_name);
445
446     if (vflag)
447     {
448         verbose_file = fopen(verbose_file_name, "w");
449         if (verbose_file == 0)
450             open_error(verbose_file_name);
451     }
452
453     if (dflag)
454     {
455         defines_file = fopen(defines_file_name, "w");
456         if (defines_file == 0)
457             open_error(defines_file_name);
458         union_file = fopen(union_file_name, "w");
459         if (union_file ==  0)
460             open_error(union_file_name);
461     }
462
463     output_file = fopen(output_file_name, "w");
464     if (output_file == 0)
465         open_error(output_file_name);
466
467     if (rflag)
468     {
469         code_file = fopen(code_file_name, "w");
470         if (code_file == 0)
471             open_error(code_file_name);
472     }
473     else
474         code_file = output_file;
475 }
476
477
478 int
479 main(int argc, char **argv)
480 {
481     atexit(cleanup);
482     set_signals();
483     getargs(argc, argv);
484     open_files();
485     reader();
486     lr0();
487     lalr();
488     make_parser();
489     verbose();
490     output();
491     exit(0);
492     /*NOTREACHED*/
493 }