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