Annotation of src/usr.bin/yacc/main.c, Revision 1.30
1.30 ! espie 1: /* $OpenBSD: main.c,v 1.29 2017/05/25 20:11:03 tedu Exp $ */
1.26 tedu 2: /* $NetBSD: main.c,v 1.5 1996/03/19 03:21:38 jtc Exp $ */
1.3 deraadt 3:
4: /*
5: * Copyright (c) 1989 The Regents of the University of California.
6: * All rights reserved.
7: *
8: * This code is derived from software contributed to Berkeley by
9: * Robert Paul Corbett.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
1.17 millert 19: * 3. Neither the name of the University nor the names of its contributors
1.3 deraadt 20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: */
1.1 deraadt 35:
1.4 deraadt 36: #include <sys/types.h>
1.6 tholo 37: #include <fcntl.h>
1.10 millert 38: #include <paths.h>
1.12 pvalchev 39: #include <signal.h>
1.4 deraadt 40: #include <stdlib.h>
1.12 pvalchev 41: #include <unistd.h>
1.1 deraadt 42: #include "defs.h"
43:
44: char dflag;
45: char lflag;
46: char rflag;
47: char tflag;
48: char vflag;
49:
50: char *symbol_prefix;
51: char *file_prefix = "y";
52:
53: int lineno;
54: int outline;
55:
1.2 niklas 56: int explicit_file_name;
57:
1.1 deraadt 58: char *action_file_name;
59: char *code_file_name;
60: char *defines_file_name;
61: char *input_file_name = "";
62: char *output_file_name;
63: char *text_file_name;
64: char *union_file_name;
65: char *verbose_file_name;
66:
1.26 tedu 67: FILE *action_file; /* a temp file, used to save actions associated */
68: /* with rules until the parser is written */
69: FILE *code_file; /* y.code.c (used when the -r option is specified) */
70: FILE *defines_file; /* y.tab.h */
71: FILE *input_file; /* the input file */
72: FILE *output_file; /* y.tab.c */
73: FILE *text_file; /* a temp file, used to save text until all */
74: /* symbols have been defined */
75: FILE *union_file; /* a temp file, used to save the union */
76: /* definition until all symbol have been */
77: /* defined */
78: FILE *verbose_file; /* y.output */
1.1 deraadt 79:
80: int nitems;
81: int nrules;
82: int nsyms;
83: int ntokens;
84: int nvars;
85:
1.26 tedu 86: int start_symbol;
87: char **symbol_name;
1.1 deraadt 88: short *symbol_value;
89: short *symbol_prec;
1.26 tedu 90: char *symbol_assoc;
1.1 deraadt 91:
92: short *ritem;
93: short *rlhs;
94: short *rrhs;
95: short *rprec;
1.26 tedu 96: char *rassoc;
1.1 deraadt 97: short **derives;
98: char *nullable;
99:
1.15 millert 100: void onintr(int);
101: void set_signals(void);
102: void usage(void);
103: void getargs(int, char *[]);
104: void create_file_names(void);
105: void open_files(void);
1.12 pvalchev 106:
1.13 deraadt 107: volatile sig_atomic_t sigdie;
108:
1.12 pvalchev 109: void
1.18 pvalchev 110: done(int k)
1.1 deraadt 111: {
1.26 tedu 112: if (action_file)
113: unlink(action_file_name);
114: if (text_file)
115: unlink(text_file_name);
116: if (union_file)
117: unlink(union_file_name);
118: if (sigdie)
119: _exit(k);
120: exit(k);
1.1 deraadt 121: }
122:
123:
124: void
1.29 tedu 125: onintr(__unused int signo)
1.1 deraadt 126: {
1.26 tedu 127: sigdie = 1;
128: done(1);
1.1 deraadt 129: }
130:
131:
1.12 pvalchev 132: void
1.18 pvalchev 133: set_signals(void)
1.1 deraadt 134: {
135: #ifdef SIGINT
1.26 tedu 136: if (signal(SIGINT, SIG_IGN) != SIG_IGN)
137: signal(SIGINT, onintr);
1.1 deraadt 138: #endif
139: #ifdef SIGTERM
1.26 tedu 140: if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
141: signal(SIGTERM, onintr);
1.1 deraadt 142: #endif
143: #ifdef SIGHUP
1.26 tedu 144: if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
145: signal(SIGHUP, onintr);
1.1 deraadt 146: #endif
147: }
148:
149:
1.12 pvalchev 150: void
1.18 pvalchev 151: usage(void)
1.1 deraadt 152: {
1.26 tedu 153: fprintf(stderr, "usage: %s [-dlrtv] [-b file_prefix] [-o output_file] [-p symbol_prefix] file\n", __progname);
154: exit(1);
1.1 deraadt 155: }
156:
157:
1.12 pvalchev 158: void
1.18 pvalchev 159: getargs(int argc, char *argv[])
1.1 deraadt 160: {
1.26 tedu 161: int ch;
1.1 deraadt 162:
1.26 tedu 163: while ((ch = getopt(argc, argv, "b:dlo:p:rtv")) != -1) {
164: switch (ch) {
165: case 'b':
166: file_prefix = optarg;
167: break;
168:
169: case 'd':
170: dflag = 1;
171: break;
172:
173: case 'l':
174: lflag = 1;
175: break;
176:
177: case 'o':
178: output_file_name = optarg;
179: explicit_file_name = 1;
180: break;
181:
182: case 'p':
183: symbol_prefix = optarg;
184: break;
185:
186: case 'r':
187: rflag = 1;
188: break;
189:
190: case 't':
191: tflag = 1;
192: break;
193:
194: case 'v':
195: vflag = 1;
196: break;
197:
198: default:
199: usage();
200: }
201: }
202: argc -= optind;
203: argv += optind;
1.1 deraadt 204:
1.26 tedu 205: if (argc != 1)
206: usage();
207: if (strcmp(*argv, "-") == 0)
208: input_file = stdin;
209: else
210: input_file_name = *argv;
1.1 deraadt 211: }
212:
213:
1.25 millert 214: void *
215: allocate(size_t n)
1.1 deraadt 216: {
1.26 tedu 217: void *v;
1.1 deraadt 218:
1.26 tedu 219: v = NULL;
220: if (n) {
221: v = calloc(1, n);
222: if (!v)
223: no_space();
224: }
225: return (v);
1.1 deraadt 226: }
227:
1.16 millert 228: #define TEMPNAME(s, c, d, l) \
229: (asprintf(&(s), "%.*s/yacc.%xXXXXXXXXXX", (int)(l), (d), (c)))
230:
1.12 pvalchev 231: void
1.18 pvalchev 232: create_file_names(void)
1.1 deraadt 233: {
1.26 tedu 234: size_t len;
235: char *tmpdir;
1.1 deraadt 236:
1.28 tedu 237: tmpdir = _PATH_TMP;
1.1 deraadt 238:
1.26 tedu 239: len = strlen(tmpdir);
240: if (tmpdir[len - 1] == '/')
241: len--;
242:
243: if (TEMPNAME(action_file_name, 'a', tmpdir, len) == -1 ||
244: TEMPNAME(text_file_name, 'r', tmpdir, len) == -1 ||
245: TEMPNAME(union_file_name, 'u', tmpdir, len) == -1)
246: no_space();
247:
248: if (output_file_name == NULL) {
249: if (asprintf(&output_file_name, "%s%s", file_prefix, OUTPUT_SUFFIX)
250: == -1)
251: no_space();
252: }
253: if (rflag) {
254: if (asprintf(&code_file_name, "%s%s", file_prefix, CODE_SUFFIX) == -1)
255: no_space();
256: } else
257: code_file_name = output_file_name;
258:
259: if (dflag) {
260: if (explicit_file_name) {
261: char *suffix;
262:
263: defines_file_name = strdup(output_file_name);
264: if (defines_file_name == 0)
265: no_space();
266:
267: /* does the output_file_name have a known suffix */
268: if ((suffix = strrchr(output_file_name, '.')) != 0 &&
269: (!strcmp(suffix, ".c") || /* good, old-fashioned C */
270: !strcmp(suffix, ".C") || /* C++, or C on Windows */
271: !strcmp(suffix, ".cc") || /* C++ */
272: !strcmp(suffix, ".cxx") || /* C++ */
273: !strcmp(suffix, ".cpp"))) {/* C++ (Windows) */
274: strncpy(defines_file_name, output_file_name,
275: suffix - output_file_name + 1);
276: defines_file_name[suffix - output_file_name + 1] = 'h';
277: defines_file_name[suffix - output_file_name + 2] = '\0';
278: } else {
279: fprintf(stderr, "%s: suffix of output file name %s"
280: " not recognized, no -d file generated.\n",
281: __progname, output_file_name);
282: dflag = 0;
283: free(defines_file_name);
284: defines_file_name = 0;
285: }
286: } else {
287: if (asprintf(&defines_file_name, "%s%s", file_prefix,
288: DEFINES_SUFFIX) == -1)
289: no_space();
290: }
1.2 niklas 291: }
1.26 tedu 292: if (vflag) {
293: if (asprintf(&verbose_file_name, "%s%s", file_prefix,
294: VERBOSE_SUFFIX) == -1)
295: no_space();
1.2 niklas 296: }
1.1 deraadt 297: }
298:
1.4 deraadt 299:
1.12 pvalchev 300: void
1.18 pvalchev 301: open_files(void)
1.1 deraadt 302: {
1.26 tedu 303: int fd;
1.4 deraadt 304:
1.26 tedu 305: create_file_names();
1.1 deraadt 306:
1.30 ! espie 307: if (input_file == NULL) {
1.26 tedu 308: input_file = fopen(input_file_name, "r");
1.30 ! espie 309: if (input_file == NULL)
1.26 tedu 310: open_error(input_file_name);
311: }
312: fd = mkstemp(action_file_name);
313: if (fd == -1 || (action_file = fdopen(fd, "w")) == NULL)
314: open_error(action_file_name);
315:
316: fd = mkstemp(text_file_name);
317: if (fd == -1 || (text_file = fdopen(fd, "w")) == NULL)
318: open_error(text_file_name);
319:
320: if (vflag) {
321: verbose_file = fopen(verbose_file_name, "w");
1.30 ! espie 322: if (verbose_file == NULL)
1.26 tedu 323: open_error(verbose_file_name);
324: }
325: if (dflag) {
326: defines_file = fopen(defines_file_name, "w");
327: if (defines_file == NULL)
328: open_write_error(defines_file_name);
329: fd = mkstemp(union_file_name);
330: if (fd == -1 || (union_file = fdopen(fd, "w")) == NULL)
331: open_error(union_file_name);
332: }
333: output_file = fopen(output_file_name, "w");
1.30 ! espie 334: if (output_file == NULL)
1.26 tedu 335: open_error(output_file_name);
336:
337: if (rflag) {
338: code_file = fopen(code_file_name, "w");
1.30 ! espie 339: if (code_file == NULL)
1.26 tedu 340: open_error(code_file_name);
341: } else
342: code_file = output_file;
1.1 deraadt 343: }
344:
345:
346: int
1.18 pvalchev 347: main(int argc, char *argv[])
1.1 deraadt 348: {
1.27 deraadt 349: if (pledge("stdio rpath wpath cpath", NULL) == -1)
350: fatal("pledge: invalid arguments");
351:
1.26 tedu 352: set_signals();
353: getargs(argc, argv);
354: open_files();
355: reader();
356: lr0();
357: lalr();
358: make_parser();
359: verbose();
360: output();
361: done(0);
362: /* NOTREACHED */
363: return (0);
1.1 deraadt 364: }