Initial import from FreeBSD RELENG_4:
[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
37 #ifndef lint
38 static char const copyright[] =
39 "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
40  All rights reserved.\n";
41 #endif /* not lint */
42
43 #ifndef lint
44 #if 0
45 static char const sccsid[] = "@(#)main.c        5.5 (Berkeley) 5/24/93";
46 #endif
47 static const char rcsid[] =
48   "$FreeBSD: src/usr.bin/yacc/main.c,v 1.12 2000/01/10 20:26:24 kris Exp $";
49 #endif /* not lint */
50
51 #include <signal.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include <unistd.h>
55 #include "defs.h"
56
57 char dflag;
58 char lflag;
59 char rflag;
60 char tflag;
61 char vflag;
62
63 char *symbol_prefix;
64 char *file_prefix = "y";
65 char *temp_form = "yacc.XXXXXXXXXXX";
66
67 int lineno;
68 int outline;
69
70 char *action_file_name;
71 char *code_file_name;
72 char *defines_file_name;
73 char *input_file_name = "";
74 char *output_file_name;
75 char *text_file_name;
76 char *union_file_name;
77 char *verbose_file_name;
78
79 FILE *action_file;      /*  a temp file, used to save actions associated    */
80                         /*  with rules until the parser is written          */
81 FILE *code_file;        /*  y.code.c (used when the -r option is specified) */
82 FILE *defines_file;     /*  y.tab.h                                         */
83 FILE *input_file;       /*  the input file                                  */
84 FILE *output_file;      /*  y.tab.c                                         */
85 FILE *text_file;        /*  a temp file, used to save text until all        */
86                         /*  symbols have been defined                       */
87 FILE *union_file;       /*  a temp file, used to save the union             */
88                         /*  definition until all symbol have been           */
89                         /*  defined                                         */
90 FILE *verbose_file;     /*  y.output                                        */
91
92 int nitems;
93 int nrules;
94 int nsyms;
95 int ntokens;
96 int nvars;
97
98 int   start_symbol;
99 char  **symbol_name;
100 short *symbol_value;
101 short *symbol_prec;
102 char  *symbol_assoc;
103
104 short *ritem;
105 short *rlhs;
106 short *rrhs;
107 short *rprec;
108 char  *rassoc;
109 short **derives;
110 char *nullable;
111
112 static void create_file_names __P((void));
113 static void getargs __P((int, char **));
114 static void onintr __P((int));
115 static void open_files __P((void));
116 static void set_signals __P((void));
117 static void usage __P((void));
118
119
120 void
121 done(k)
122 int k;
123 {
124     if (action_file) { fclose(action_file); unlink(action_file_name); }
125     if (text_file) { fclose(text_file); unlink(text_file_name); }
126     if (union_file) { fclose(union_file); unlink(union_file_name); }
127     exit(k);
128 }
129
130
131 static void
132 onintr(signo)
133         int signo;
134 {
135     done(1);
136 }
137
138
139 static void
140 set_signals()
141 {
142 #ifdef SIGINT
143     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
144         signal(SIGINT, onintr);
145 #endif
146 #ifdef SIGTERM
147     if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
148         signal(SIGTERM, onintr);
149 #endif
150 #ifdef SIGHUP
151     if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
152         signal(SIGHUP, onintr);
153 #endif
154 }
155
156
157 static void
158 usage()
159 {
160     fprintf(stderr, "%s\n%s\n",
161                 "usage: yacc [-dlrtv] [-b file_prefix] [-o output_filename]",
162                 "            [-p symbol_prefix] filename");
163     exit(1);
164 }
165
166
167 static void
168 getargs(argc, argv)
169 int argc;
170 char *argv[];
171 {
172     register int i;
173     register char *s;
174
175     for (i = 1; i < argc; ++i)
176     {
177         s = argv[i];
178         if (*s != '-') break;
179         switch (*++s)
180         {
181         case '\0':
182             input_file = stdin;
183             if (i + 1 < argc) usage();
184             return;
185
186         case '-':
187             ++i;
188             goto no_more_options;
189
190         case 'b':
191             if (*++s)
192                  file_prefix = s;
193             else if (++i < argc)
194                 file_prefix = argv[i];
195             else
196                 usage();
197             continue;
198
199         case 'd':
200             dflag = 1;
201             break;
202
203         case 'l':
204             lflag = 1;
205             break;
206
207         case 'o':
208             if (*++s)
209                 output_file_name = s;
210             else if (++i < argc)
211                 output_file_name = argv[i];
212             else
213                 usage();
214             continue;
215
216         case 'p':
217             if (*++s)
218                 symbol_prefix = s;
219             else if (++i < argc)
220                 symbol_prefix = argv[i];
221             else
222                 usage();
223             continue;
224
225         case 'r':
226             rflag = 1;
227             break;
228
229         case 't':
230             tflag = 1;
231             break;
232
233         case 'v':
234             vflag = 1;
235             break;
236
237         default:
238             usage();
239         }
240
241         for (;;)
242         {
243             switch (*++s)
244             {
245             case '\0':
246                 goto end_of_option;
247
248             case 'd':
249                 dflag = 1;
250                 break;
251
252             case 'l':
253                 lflag = 1;
254                 break;
255
256             case 'r':
257                 rflag = 1;
258                 break;
259
260             case 't':
261                 tflag = 1;
262                 break;
263
264             case 'v':
265                 vflag = 1;
266                 break;
267
268             default:
269                 usage();
270             }
271         }
272 end_of_option:;
273     }
274
275 no_more_options:;
276     if (i + 1 != argc) usage();
277     input_file_name = argv[i];
278 }
279
280
281 char *
282 allocate(n)
283 unsigned n;
284 {
285     register char *p;
286
287     p = NULL;
288     if (n)
289     {
290         p = CALLOC(1, n);
291         if (!p) no_space();
292     }
293     return (p);
294 }
295
296
297 static void
298 create_file_names()
299 {
300     int i, len;
301     char *tmpdir;
302
303     tmpdir = getenv("TMPDIR");
304     if (tmpdir == 0) tmpdir = "/tmp";
305
306     len = strlen(tmpdir);
307     i = len + 17;
308     if (len && tmpdir[len-1] != '/')
309         ++i;
310
311     action_file_name = MALLOC(i);
312     if (action_file_name == 0) no_space();
313     text_file_name = MALLOC(i);
314     if (text_file_name == 0) no_space();
315     union_file_name = MALLOC(i);
316     if (union_file_name == 0) no_space();
317
318     strcpy(action_file_name, tmpdir);
319     strcpy(text_file_name, tmpdir);
320     strcpy(union_file_name, tmpdir);
321
322     if (len && tmpdir[len - 1] != '/')
323     {
324         action_file_name[len] = '/';
325         text_file_name[len] = '/';
326         union_file_name[len] = '/';
327         ++len;
328     }
329
330     strcpy(action_file_name + len, temp_form);
331     strcpy(text_file_name + len, temp_form);
332     strcpy(union_file_name + len, temp_form);
333
334     action_file_name[len + 5] = 'a';
335     text_file_name[len + 5] = 't';
336     union_file_name[len + 5] = 'u';
337
338     if (output_file_name != 0)
339     {
340         file_prefix = output_file_name;
341         len = strlen(file_prefix);
342     }
343     else
344     {
345         len = strlen(file_prefix);
346         output_file_name = MALLOC(len + 7);
347         if (output_file_name == 0)
348             no_space();
349         strcpy(output_file_name, file_prefix);
350         strcpy(output_file_name + len, OUTPUT_SUFFIX);
351     }
352
353     if (rflag)
354     {
355         code_file_name = MALLOC(len + 8);
356         if (code_file_name == 0)
357             no_space();
358         strcpy(code_file_name, file_prefix);
359         if (file_prefix == output_file_name)
360         {
361             /*
362              * XXX ".tab.c" here is OUTPUT_SUFFIX, but since its length is
363              * in various magic numbers, don't bother using the macro.
364              */
365             if (len >= 6 && strcmp(code_file_name + len - 6, ".tab.c") == 0)
366                 strcpy(code_file_name + len - 6, CODE_SUFFIX);
367             else if (len >= 2 && strcmp(code_file_name + len - 2, ".c") == 0)
368                 strcpy(code_file_name + len - 2, CODE_SUFFIX);
369             else
370                 strcpy(code_file_name + len, CODE_SUFFIX);
371         }
372         else
373             strcpy(code_file_name + len, CODE_SUFFIX);
374     }
375     else
376         code_file_name = output_file_name;
377
378     if (dflag)
379     {
380         defines_file_name = MALLOC(len + 7);
381         if (defines_file_name == 0)
382             no_space();
383         strcpy(defines_file_name, file_prefix);
384         if (file_prefix == output_file_name)
385         {
386 #define BISON_DEFINES_SUFFIX  ".h"
387             if (len >= 2 && strcmp(defines_file_name + len - 2, ".c") == 0)
388                 strcpy(defines_file_name + len - 2, BISON_DEFINES_SUFFIX);
389             else
390                 strcpy(defines_file_name + len, BISON_DEFINES_SUFFIX);
391         }
392         else
393             strcpy(defines_file_name + len, DEFINES_SUFFIX);
394     }
395
396     if (vflag)
397     {
398         verbose_file_name = MALLOC(len + 8);
399         if (verbose_file_name == 0)
400             no_space();
401         strcpy(verbose_file_name, file_prefix);
402         if (file_prefix == output_file_name)
403         {
404             if (len >= 6 && strcmp(verbose_file_name + len - 6, ".tab.c") == 0)
405                 strcpy(verbose_file_name + len - 6, VERBOSE_SUFFIX);
406             else if (len >= 2 && strcmp(verbose_file_name + len - 2, ".c") == 0)
407                 strcpy(verbose_file_name + len - 2, VERBOSE_SUFFIX);
408             else
409                 strcpy(verbose_file_name + len, VERBOSE_SUFFIX);
410         }
411         else
412             strcpy(verbose_file_name + len, VERBOSE_SUFFIX);
413     }
414 }
415
416
417 static void
418 open_files()
419 {
420     int fd;
421
422     create_file_names();
423
424     if (input_file == 0)
425     {
426         input_file = fopen(input_file_name, "r");
427         if (input_file == 0)
428             open_error(input_file_name);
429     }
430
431     fd = mkstemp(action_file_name);
432     if (fd < 0 || (action_file = fdopen(fd, "w")) == NULL) {
433         if (fd >= 0)
434             close(fd);
435         open_error(action_file_name);
436     }
437     fd = mkstemp(text_file_name);
438     if (fd < 0 || (text_file = fdopen(fd, "w")) == NULL) {
439         if (fd >= 0)
440             close(fd);
441         open_error(text_file_name);
442     }
443     fd = mkstemp(union_file_name);
444     if (fd < 0 || (union_file = fdopen(fd, "w")) == NULL) {
445         if (fd >= 0)
446             close(fd);
447         open_error(union_file_name);
448     }
449
450     text_file = fopen(text_file_name, "w");
451     if (text_file == 0)
452         open_error(text_file_name);
453
454     if (vflag)
455     {
456         verbose_file = fopen(verbose_file_name, "w");
457         if (verbose_file == 0)
458             open_error(verbose_file_name);
459     }
460
461     if (dflag)
462     {
463         defines_file = fopen(defines_file_name, "w");
464         if (defines_file == 0)
465             open_error(defines_file_name);
466         union_file = fopen(union_file_name, "w");
467         if (union_file ==  0)
468             open_error(union_file_name);
469     }
470
471     output_file = fopen(output_file_name, "w");
472     if (output_file == 0)
473         open_error(output_file_name);
474
475     if (rflag)
476     {
477         code_file = fopen(code_file_name, "w");
478         if (code_file == 0)
479             open_error(code_file_name);
480     }
481     else
482         code_file = output_file;
483 }
484
485
486 int
487 main(argc, argv)
488 int argc;
489 char *argv[];
490 {
491     set_signals();
492     getargs(argc, argv);
493     open_files();
494     reader();
495     lr0();
496     lalr();
497     make_parser();
498     verbose();
499     output();
500     done(0);
501     /*NOTREACHED*/
502     return (0);
503 }