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 * 4. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #if 0
34 #ifndef lint
35 static char sccsid[] = "@(#)main.c 5.5 (Berkeley) 5/24/93";
36 #endif
37 #endif
38
39 #include <sys/cdefs.h>
40 __FBSDID("$FreeBSD: stable/9/usr.bin/yacc/main.c 216370 2010-12-11 08:32:16Z joel $");
41
42 #include <paths.h>
43 #include <signal.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <unistd.h>
47 #include "defs.h"
48
49 char dflag;
50 char lflag;
51 char rflag;
52 char tflag;
53 char vflag;
54
55 const char *symbol_prefix;
56 const char *file_prefix = "y";
57 char temp_form[] = "yacc.XXXXXXXXXXX";
58
59 int lineno;
60 int outline;
61
62 char *action_file_name;
63 char *code_file_name;
64 char *defines_file_name;
65 const char *input_file_name = "";
66 char *output_file_name;
67 char *text_file_name;
68 char *union_file_name;
69 char *verbose_file_name;
70
71 FILE *action_file; /* a temp file, used to save actions associated */
72 /* with rules until the parser is written */
73 FILE *code_file; /* y.code.c (used when the -r option is specified) */
74 FILE *defines_file; /* y.tab.h */
75 FILE *input_file; /* the input file */
76 FILE *output_file; /* y.tab.c */
77 FILE *text_file; /* a temp file, used to save text until all */
78 /* symbols have been defined */
79 FILE *union_file; /* a temp file, used to save the union */
80 /* definition until all symbol have been */
81 /* defined */
82 FILE *verbose_file; /* y.output */
83
84 int nitems;
85 int nrules;
86 int nsyms;
87 int ntokens;
88 int nvars;
89
90 int start_symbol;
91 char **symbol_name;
92 short *symbol_value;
93 short *symbol_prec;
94 char *symbol_assoc;
95
96 short *ritem;
97 short *rlhs;
98 short *rrhs;
99 short *rprec;
100 char *rassoc;
101 short **derives;
102 char *nullable;
103
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 volatile sig_atomic_t sigdie;
112
113 __dead2 void
done(int k)114 done(int k)
115 {
116 if (action_file) { fclose(action_file); unlink(action_file_name); }
117 if (text_file) { fclose(text_file); unlink(text_file_name); }
118 if (union_file) { fclose(union_file); unlink(union_file_name); }
119 if (sigdie) { _exit(k); }
120 exit(k);
121 }
122
123
124 static void
onintr(int signo __unused)125 onintr(int signo __unused)
126 {
127 sigdie = 1;
128 done(1);
129 }
130
131
132 static void
set_signals(void)133 set_signals(void)
134 {
135 #ifdef SIGINT
136 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
137 signal(SIGINT, onintr);
138 #endif
139 #ifdef SIGTERM
140 if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
141 signal(SIGTERM, onintr);
142 #endif
143 #ifdef SIGHUP
144 if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
145 signal(SIGHUP, onintr);
146 #endif
147 }
148
149
150 static void
usage(void)151 usage(void)
152 {
153 fprintf(stderr, "%s\n%s\n",
154 "usage: yacc [-dlrtv] [-b file_prefix] [-o output_filename]",
155 " [-p symbol_prefix] filename");
156 exit(1);
157 }
158
159
160 static void
getargs(int argc,char * argv[])161 getargs(int argc, char *argv[])
162 {
163 int ch;
164
165 while ((ch = getopt(argc, argv, "b:dlo:p:rtvy")) != -1)
166 {
167 switch (ch)
168 {
169 case 'b':
170 file_prefix = optarg;
171 break;
172
173 case 'd':
174 dflag = 1;
175 break;
176
177 case 'l':
178 lflag = 1;
179 break;
180
181 case 'o':
182 output_file_name = optarg;
183 break;
184
185 case 'p':
186 symbol_prefix = optarg;
187 break;
188
189 case 'r':
190 rflag = 1;
191 break;
192
193 case 't':
194 tflag = 1;
195 break;
196
197 case 'v':
198 vflag = 1;
199 break;
200
201 case 'y':
202 /* for bison compatibility -- byacc is already POSIX compatible */
203 break;
204
205 default:
206 usage();
207 }
208 }
209
210 if (optind + 1 != argc)
211 usage();
212 if (strcmp(argv[optind], "-") == 0)
213 input_file = stdin;
214 else
215 input_file_name = argv[optind];
216 }
217
218
219 void *
allocate(size_t n)220 allocate(size_t n)
221 {
222 void *p;
223
224 p = NULL;
225 if (n)
226 {
227 p = calloc(1, n);
228 if (!p) no_space();
229 }
230 return (p);
231 }
232
233
234 static void
create_file_names(void)235 create_file_names(void)
236 {
237 int i, len;
238 const char *tmpdir;
239
240 if (!(tmpdir = getenv("TMPDIR")))
241 tmpdir = _PATH_TMP;
242
243 len = strlen(tmpdir);
244 i = len + strlen(temp_form) + 1;
245 if (len && tmpdir[len-1] != '/')
246 ++i;
247
248 action_file_name = malloc(i);
249 if (action_file_name == 0) no_space();
250 text_file_name = malloc(i);
251 if (text_file_name == 0) no_space();
252 union_file_name = malloc(i);
253 if (union_file_name == 0) no_space();
254
255 strcpy(action_file_name, tmpdir);
256 strcpy(text_file_name, tmpdir);
257 strcpy(union_file_name, tmpdir);
258
259 if (len && tmpdir[len - 1] != '/')
260 {
261 action_file_name[len] = '/';
262 text_file_name[len] = '/';
263 union_file_name[len] = '/';
264 ++len;
265 }
266
267 strcpy(action_file_name + len, temp_form);
268 strcpy(text_file_name + len, temp_form);
269 strcpy(union_file_name + len, temp_form);
270
271 action_file_name[len + 5] = 'a';
272 text_file_name[len + 5] = 't';
273 union_file_name[len + 5] = 'u';
274
275 if (output_file_name != 0)
276 {
277 file_prefix = output_file_name;
278 len = strlen(file_prefix);
279 }
280 else
281 {
282 len = strlen(file_prefix);
283 output_file_name = malloc(len + 7);
284 if (output_file_name == 0)
285 no_space();
286 strcpy(output_file_name, file_prefix);
287 strcpy(output_file_name + len, OUTPUT_SUFFIX);
288 }
289
290 if (rflag)
291 {
292 code_file_name = malloc(len + 8);
293 if (code_file_name == 0)
294 no_space();
295 strcpy(code_file_name, file_prefix);
296 if (file_prefix == output_file_name)
297 {
298 /*
299 * XXX ".tab.c" here is OUTPUT_SUFFIX, but since its length is
300 * in various magic numbers, don't bother using the macro.
301 */
302 if (len >= 6 && strcmp(code_file_name + len - 6, ".tab.c") == 0)
303 strcpy(code_file_name + len - 6, CODE_SUFFIX);
304 else if (len >= 2 && strcmp(code_file_name + len - 2, ".c") == 0)
305 strcpy(code_file_name + len - 2, CODE_SUFFIX);
306 else
307 strcpy(code_file_name + len, CODE_SUFFIX);
308 }
309 else
310 strcpy(code_file_name + len, CODE_SUFFIX);
311 }
312 else
313 code_file_name = output_file_name;
314
315 if (dflag)
316 {
317 defines_file_name = malloc(len + 7);
318 if (defines_file_name == 0)
319 no_space();
320 strcpy(defines_file_name, file_prefix);
321 if (file_prefix == output_file_name)
322 {
323 #define BISON_DEFINES_SUFFIX ".h"
324 if (len >= 2 && strcmp(defines_file_name + len - 2, ".c") == 0)
325 strcpy(defines_file_name + len - 2, BISON_DEFINES_SUFFIX);
326 else
327 strcpy(defines_file_name + len, BISON_DEFINES_SUFFIX);
328 }
329 else
330 strcpy(defines_file_name + len, DEFINES_SUFFIX);
331 }
332
333 if (vflag)
334 {
335 verbose_file_name = malloc(len + 8);
336 if (verbose_file_name == 0)
337 no_space();
338 strcpy(verbose_file_name, file_prefix);
339 if (file_prefix == output_file_name)
340 {
341 if (len >= 6 && strcmp(verbose_file_name + len - 6, ".tab.c") == 0)
342 strcpy(verbose_file_name + len - 6, VERBOSE_SUFFIX);
343 else if (len >= 2 && strcmp(verbose_file_name + len - 2, ".c") == 0)
344 strcpy(verbose_file_name + len - 2, VERBOSE_SUFFIX);
345 else
346 strcpy(verbose_file_name + len, VERBOSE_SUFFIX);
347 }
348 else
349 strcpy(verbose_file_name + len, VERBOSE_SUFFIX);
350 }
351 }
352
353
354 static void
open_files(void)355 open_files(void)
356 {
357 int fd;
358
359 create_file_names();
360
361 if (input_file == 0)
362 {
363 input_file = fopen(input_file_name, "r");
364 if (input_file == 0)
365 open_error(input_file_name);
366 }
367
368 fd = mkstemp(action_file_name);
369 if (fd < 0 || (action_file = fdopen(fd, "w")) == NULL) {
370 if (fd >= 0)
371 close(fd);
372 open_error(action_file_name);
373 }
374 fd = mkstemp(text_file_name);
375 if (fd < 0 || (text_file = fdopen(fd, "w")) == NULL) {
376 if (fd >= 0)
377 close(fd);
378 open_error(text_file_name);
379 }
380 fd = mkstemp(union_file_name);
381 if (fd < 0 || (union_file = fdopen(fd, "w")) == NULL) {
382 if (fd >= 0)
383 close(fd);
384 open_error(union_file_name);
385 }
386
387 text_file = fopen(text_file_name, "w");
388 if (text_file == 0)
389 open_error(text_file_name);
390
391 if (vflag)
392 {
393 verbose_file = fopen(verbose_file_name, "w");
394 if (verbose_file == 0)
395 open_error(verbose_file_name);
396 }
397
398 if (dflag)
399 {
400 defines_file = fopen(defines_file_name, "w");
401 if (defines_file == 0)
402 open_error(defines_file_name);
403 union_file = fopen(union_file_name, "w");
404 if (union_file == 0)
405 open_error(union_file_name);
406 }
407
408 output_file = fopen(output_file_name, "w");
409 if (output_file == 0)
410 open_error(output_file_name);
411
412 if (rflag)
413 {
414 code_file = fopen(code_file_name, "w");
415 if (code_file == 0)
416 open_error(code_file_name);
417 }
418 else
419 code_file = output_file;
420 }
421
422
423 int
main(int argc,char * argv[])424 main(int argc, char *argv[])
425 {
426 set_signals();
427 getargs(argc, argv);
428 open_files();
429 reader();
430 lr0();
431 lalr();
432 make_parser();
433 verbose();
434 output();
435 done(0);
436 /*NOTREACHED*/
437 return (0);
438 }
439