K&R style function removal. Update functions to ANSI style.
[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.3 2003/10/04 20:36:55 hmp 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 char *symbol_prefix;
55 char *file_prefix = "y";
56 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 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 create_file_names(void);
104 static void getargs(int, char **);
105 static void onintr(int);
106 static void open_files(void);
107 static void set_signals(void);
108 static void usage(void);
109
110
111 void
112 done(int k)
113 {
114     if (action_file) { fclose(action_file); unlink(action_file_name); }
115     if (text_file) { fclose(text_file); unlink(text_file_name); }
116     if (union_file) { fclose(union_file); unlink(union_file_name); }
117     exit(k);
118 }
119
120
121 static void
122 onintr(int signo)
123 {
124     done(1);
125 }
126
127
128 static void
129 set_signals(void)
130 {
131 #ifdef SIGINT
132     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
133         signal(SIGINT, onintr);
134 #endif
135 #ifdef SIGTERM
136     if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
137         signal(SIGTERM, onintr);
138 #endif
139 #ifdef SIGHUP
140     if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
141         signal(SIGHUP, onintr);
142 #endif
143 }
144
145
146 static void
147 usage(void)
148 {
149     fprintf(stderr, "%s\n%s\n",
150                 "usage: yacc [-dlrtv] [-b file_prefix] [-o output_filename]",
151                 "            [-p symbol_prefix] filename");
152     exit(1);
153 }
154
155
156 static void
157 getargs(int argc, char **argv)
158 {
159     register int i;
160     register char *s;
161
162     for (i = 1; i < argc; ++i)
163     {
164         s = argv[i];
165         if (*s != '-') break;
166         switch (*++s)
167         {
168         case '\0':
169             input_file = stdin;
170             if (i + 1 < argc) usage();
171             return;
172
173         case '-':
174             ++i;
175             goto no_more_options;
176
177         case 'b':
178             if (*++s)
179                  file_prefix = s;
180             else if (++i < argc)
181                 file_prefix = argv[i];
182             else
183                 usage();
184             continue;
185
186         case 'd':
187             dflag = 1;
188             break;
189
190         case 'l':
191             lflag = 1;
192             break;
193
194         case 'o':
195             if (*++s)
196                 output_file_name = s;
197             else if (++i < argc)
198                 output_file_name = argv[i];
199             else
200                 usage();
201             continue;
202
203         case 'p':
204             if (*++s)
205                 symbol_prefix = s;
206             else if (++i < argc)
207                 symbol_prefix = argv[i];
208             else
209                 usage();
210             continue;
211
212         case 'r':
213             rflag = 1;
214             break;
215
216         case 't':
217             tflag = 1;
218             break;
219
220         case 'v':
221             vflag = 1;
222             break;
223
224         default:
225             usage();
226         }
227
228         for (;;)
229         {
230             switch (*++s)
231             {
232             case '\0':
233                 goto end_of_option;
234
235             case 'd':
236                 dflag = 1;
237                 break;
238
239             case 'l':
240                 lflag = 1;
241                 break;
242
243             case 'r':
244                 rflag = 1;
245                 break;
246
247             case 't':
248                 tflag = 1;
249                 break;
250
251             case 'v':
252                 vflag = 1;
253                 break;
254
255             default:
256                 usage();
257             }
258         }
259 end_of_option:;
260     }
261
262 no_more_options:;
263     if (i + 1 != argc) usage();
264     input_file_name = argv[i];
265 }
266
267
268 char *
269 allocate(unsigned n)
270 {
271     register char *p;
272
273     p = NULL;
274     if (n)
275     {
276         p = CALLOC(1, n);
277         if (!p) no_space();
278     }
279     return (p);
280 }
281
282
283 static void
284 create_file_names(void)
285 {
286     int i, len;
287     char *tmpdir;
288
289     tmpdir = getenv("TMPDIR");
290     if (tmpdir == 0) tmpdir = "/tmp";
291
292     len = strlen(tmpdir);
293     i = len + 17;
294     if (len && tmpdir[len-1] != '/')
295         ++i;
296
297     action_file_name = MALLOC(i);
298     if (action_file_name == 0) no_space();
299     text_file_name = MALLOC(i);
300     if (text_file_name == 0) no_space();
301     union_file_name = MALLOC(i);
302     if (union_file_name == 0) no_space();
303
304     strcpy(action_file_name, tmpdir);
305     strcpy(text_file_name, tmpdir);
306     strcpy(union_file_name, tmpdir);
307
308     if (len && tmpdir[len - 1] != '/')
309     {
310         action_file_name[len] = '/';
311         text_file_name[len] = '/';
312         union_file_name[len] = '/';
313         ++len;
314     }
315
316     strcpy(action_file_name + len, temp_form);
317     strcpy(text_file_name + len, temp_form);
318     strcpy(union_file_name + len, temp_form);
319
320     action_file_name[len + 5] = 'a';
321     text_file_name[len + 5] = 't';
322     union_file_name[len + 5] = 'u';
323
324     if (output_file_name != 0)
325     {
326         file_prefix = output_file_name;
327         len = strlen(file_prefix);
328     }
329     else
330     {
331         len = strlen(file_prefix);
332         output_file_name = MALLOC(len + 7);
333         if (output_file_name == 0)
334             no_space();
335         strcpy(output_file_name, file_prefix);
336         strcpy(output_file_name + len, OUTPUT_SUFFIX);
337     }
338
339     if (rflag)
340     {
341         code_file_name = MALLOC(len + 8);
342         if (code_file_name == 0)
343             no_space();
344         strcpy(code_file_name, file_prefix);
345         if (file_prefix == output_file_name)
346         {
347             /*
348              * XXX ".tab.c" here is OUTPUT_SUFFIX, but since its length is
349              * in various magic numbers, don't bother using the macro.
350              */
351             if (len >= 6 && strcmp(code_file_name + len - 6, ".tab.c") == 0)
352                 strcpy(code_file_name + len - 6, CODE_SUFFIX);
353             else if (len >= 2 && strcmp(code_file_name + len - 2, ".c") == 0)
354                 strcpy(code_file_name + len - 2, CODE_SUFFIX);
355             else
356                 strcpy(code_file_name + len, CODE_SUFFIX);
357         }
358         else
359             strcpy(code_file_name + len, CODE_SUFFIX);
360     }
361     else
362         code_file_name = output_file_name;
363
364     if (dflag)
365     {
366         defines_file_name = MALLOC(len + 7);
367         if (defines_file_name == 0)
368             no_space();
369         strcpy(defines_file_name, file_prefix);
370         if (file_prefix == output_file_name)
371         {
372 #define BISON_DEFINES_SUFFIX  ".h"
373             if (len >= 2 && strcmp(defines_file_name + len - 2, ".c") == 0)
374                 strcpy(defines_file_name + len - 2, BISON_DEFINES_SUFFIX);
375             else
376                 strcpy(defines_file_name + len, BISON_DEFINES_SUFFIX);
377         }
378         else
379             strcpy(defines_file_name + len, DEFINES_SUFFIX);
380     }
381
382     if (vflag)
383     {
384         verbose_file_name = MALLOC(len + 8);
385         if (verbose_file_name == 0)
386             no_space();
387         strcpy(verbose_file_name, file_prefix);
388         if (file_prefix == output_file_name)
389         {
390             if (len >= 6 && strcmp(verbose_file_name + len - 6, ".tab.c") == 0)
391                 strcpy(verbose_file_name + len - 6, VERBOSE_SUFFIX);
392             else if (len >= 2 && strcmp(verbose_file_name + len - 2, ".c") == 0)
393                 strcpy(verbose_file_name + len - 2, VERBOSE_SUFFIX);
394             else
395                 strcpy(verbose_file_name + len, VERBOSE_SUFFIX);
396         }
397         else
398             strcpy(verbose_file_name + len, VERBOSE_SUFFIX);
399     }
400 }
401
402
403 static void
404 open_files(void)
405 {
406     int fd;
407
408     create_file_names();
409
410     if (input_file == 0)
411     {
412         input_file = fopen(input_file_name, "r");
413         if (input_file == 0)
414             open_error(input_file_name);
415     }
416
417     fd = mkstemp(action_file_name);
418     if (fd < 0 || (action_file = fdopen(fd, "w")) == NULL) {
419         if (fd >= 0)
420             close(fd);
421         open_error(action_file_name);
422     }
423     fd = mkstemp(text_file_name);
424     if (fd < 0 || (text_file = fdopen(fd, "w")) == NULL) {
425         if (fd >= 0)
426             close(fd);
427         open_error(text_file_name);
428     }
429     fd = mkstemp(union_file_name);
430     if (fd < 0 || (union_file = fdopen(fd, "w")) == NULL) {
431         if (fd >= 0)
432             close(fd);
433         open_error(union_file_name);
434     }
435
436     text_file = fopen(text_file_name, "w");
437     if (text_file == 0)
438         open_error(text_file_name);
439
440     if (vflag)
441     {
442         verbose_file = fopen(verbose_file_name, "w");
443         if (verbose_file == 0)
444             open_error(verbose_file_name);
445     }
446
447     if (dflag)
448     {
449         defines_file = fopen(defines_file_name, "w");
450         if (defines_file == 0)
451             open_error(defines_file_name);
452         union_file = fopen(union_file_name, "w");
453         if (union_file ==  0)
454             open_error(union_file_name);
455     }
456
457     output_file = fopen(output_file_name, "w");
458     if (output_file == 0)
459         open_error(output_file_name);
460
461     if (rflag)
462     {
463         code_file = fopen(code_file_name, "w");
464         if (code_file == 0)
465             open_error(code_file_name);
466     }
467     else
468         code_file = output_file;
469 }
470
471
472 int
473 main(int argc, char **argv)
474 {
475     set_signals();
476     getargs(argc, argv);
477     open_files();
478     reader();
479     lr0();
480     lalr();
481     make_parser();
482     verbose();
483     output();
484     done(0);
485     /*NOTREACHED*/
486     return (0);
487 }