Annotation of src/usr.bin/yacc/main.c, Revision 1.31
1.31 ! espie 1: /* $OpenBSD: main.c,v 1.30 2020/05/21 16:13:23 espie 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.31 ! espie 106: void cleanup_temp_files(void);
1.13 deraadt 107:
1.12 pvalchev 108: void
1.31 ! espie 109: cleanup_temp_files()
1.1 deraadt 110: {
1.26 tedu 111: if (action_file)
112: unlink(action_file_name);
113: if (text_file)
114: unlink(text_file_name);
115: if (union_file)
116: unlink(union_file_name);
1.31 ! espie 117: }
! 118:
! 119: void
! 120: done(int k)
! 121: {
! 122: cleanup_temp_files();
1.26 tedu 123: exit(k);
1.1 deraadt 124: }
125:
126: void
1.29 tedu 127: onintr(__unused int signo)
1.1 deraadt 128: {
1.31 ! espie 129: cleanup_temp_files();
! 130: _exit(1);
1.1 deraadt 131: }
132:
133:
1.12 pvalchev 134: void
1.18 pvalchev 135: set_signals(void)
1.1 deraadt 136: {
137: #ifdef SIGINT
1.26 tedu 138: if (signal(SIGINT, SIG_IGN) != SIG_IGN)
139: signal(SIGINT, onintr);
1.1 deraadt 140: #endif
141: #ifdef SIGTERM
1.26 tedu 142: if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
143: signal(SIGTERM, onintr);
1.1 deraadt 144: #endif
145: #ifdef SIGHUP
1.26 tedu 146: if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
147: signal(SIGHUP, onintr);
1.1 deraadt 148: #endif
149: }
150:
151:
1.12 pvalchev 152: void
1.18 pvalchev 153: usage(void)
1.1 deraadt 154: {
1.26 tedu 155: fprintf(stderr, "usage: %s [-dlrtv] [-b file_prefix] [-o output_file] [-p symbol_prefix] file\n", __progname);
156: exit(1);
1.1 deraadt 157: }
158:
159:
1.12 pvalchev 160: void
1.18 pvalchev 161: getargs(int argc, char *argv[])
1.1 deraadt 162: {
1.26 tedu 163: int ch;
1.1 deraadt 164:
1.26 tedu 165: while ((ch = getopt(argc, argv, "b:dlo:p:rtv")) != -1) {
166: switch (ch) {
167: case 'b':
168: file_prefix = optarg;
169: break;
170:
171: case 'd':
172: dflag = 1;
173: break;
174:
175: case 'l':
176: lflag = 1;
177: break;
178:
179: case 'o':
180: output_file_name = optarg;
181: explicit_file_name = 1;
182: break;
183:
184: case 'p':
185: symbol_prefix = optarg;
186: break;
187:
188: case 'r':
189: rflag = 1;
190: break;
191:
192: case 't':
193: tflag = 1;
194: break;
195:
196: case 'v':
197: vflag = 1;
198: break;
199:
200: default:
201: usage();
202: }
203: }
204: argc -= optind;
205: argv += optind;
1.1 deraadt 206:
1.26 tedu 207: if (argc != 1)
208: usage();
209: if (strcmp(*argv, "-") == 0)
210: input_file = stdin;
211: else
212: input_file_name = *argv;
1.1 deraadt 213: }
214:
215:
1.25 millert 216: void *
217: allocate(size_t n)
1.1 deraadt 218: {
1.26 tedu 219: void *v;
1.1 deraadt 220:
1.26 tedu 221: v = NULL;
222: if (n) {
223: v = calloc(1, n);
224: if (!v)
225: no_space();
226: }
227: return (v);
1.1 deraadt 228: }
229:
1.16 millert 230: #define TEMPNAME(s, c, d, l) \
231: (asprintf(&(s), "%.*s/yacc.%xXXXXXXXXXX", (int)(l), (d), (c)))
232:
1.12 pvalchev 233: void
1.18 pvalchev 234: create_file_names(void)
1.1 deraadt 235: {
1.26 tedu 236: size_t len;
237: char *tmpdir;
1.1 deraadt 238:
1.28 tedu 239: tmpdir = _PATH_TMP;
1.1 deraadt 240:
1.26 tedu 241: len = strlen(tmpdir);
242: if (tmpdir[len - 1] == '/')
243: len--;
244:
245: if (TEMPNAME(action_file_name, 'a', tmpdir, len) == -1 ||
246: TEMPNAME(text_file_name, 'r', tmpdir, len) == -1 ||
247: TEMPNAME(union_file_name, 'u', tmpdir, len) == -1)
248: no_space();
249:
250: if (output_file_name == NULL) {
251: if (asprintf(&output_file_name, "%s%s", file_prefix, OUTPUT_SUFFIX)
252: == -1)
253: no_space();
254: }
255: if (rflag) {
256: if (asprintf(&code_file_name, "%s%s", file_prefix, CODE_SUFFIX) == -1)
257: no_space();
258: } else
259: code_file_name = output_file_name;
260:
261: if (dflag) {
262: if (explicit_file_name) {
263: char *suffix;
264:
265: defines_file_name = strdup(output_file_name);
266: if (defines_file_name == 0)
267: no_space();
268:
269: /* does the output_file_name have a known suffix */
270: if ((suffix = strrchr(output_file_name, '.')) != 0 &&
271: (!strcmp(suffix, ".c") || /* good, old-fashioned C */
272: !strcmp(suffix, ".C") || /* C++, or C on Windows */
273: !strcmp(suffix, ".cc") || /* C++ */
274: !strcmp(suffix, ".cxx") || /* C++ */
275: !strcmp(suffix, ".cpp"))) {/* C++ (Windows) */
276: strncpy(defines_file_name, output_file_name,
277: suffix - output_file_name + 1);
278: defines_file_name[suffix - output_file_name + 1] = 'h';
279: defines_file_name[suffix - output_file_name + 2] = '\0';
280: } else {
281: fprintf(stderr, "%s: suffix of output file name %s"
282: " not recognized, no -d file generated.\n",
283: __progname, output_file_name);
284: dflag = 0;
285: free(defines_file_name);
286: defines_file_name = 0;
287: }
288: } else {
289: if (asprintf(&defines_file_name, "%s%s", file_prefix,
290: DEFINES_SUFFIX) == -1)
291: no_space();
292: }
1.2 niklas 293: }
1.26 tedu 294: if (vflag) {
295: if (asprintf(&verbose_file_name, "%s%s", file_prefix,
296: VERBOSE_SUFFIX) == -1)
297: no_space();
1.2 niklas 298: }
1.1 deraadt 299: }
300:
1.4 deraadt 301:
1.12 pvalchev 302: void
1.18 pvalchev 303: open_files(void)
1.1 deraadt 304: {
1.26 tedu 305: int fd;
1.4 deraadt 306:
1.26 tedu 307: create_file_names();
1.1 deraadt 308:
1.30 espie 309: if (input_file == NULL) {
1.26 tedu 310: input_file = fopen(input_file_name, "r");
1.30 espie 311: if (input_file == NULL)
1.26 tedu 312: open_error(input_file_name);
313: }
314: fd = mkstemp(action_file_name);
315: if (fd == -1 || (action_file = fdopen(fd, "w")) == NULL)
316: open_error(action_file_name);
317:
318: fd = mkstemp(text_file_name);
319: if (fd == -1 || (text_file = fdopen(fd, "w")) == NULL)
320: open_error(text_file_name);
321:
322: if (vflag) {
323: verbose_file = fopen(verbose_file_name, "w");
1.30 espie 324: if (verbose_file == NULL)
1.26 tedu 325: open_error(verbose_file_name);
326: }
327: if (dflag) {
328: defines_file = fopen(defines_file_name, "w");
329: if (defines_file == NULL)
330: open_write_error(defines_file_name);
331: fd = mkstemp(union_file_name);
332: if (fd == -1 || (union_file = fdopen(fd, "w")) == NULL)
333: open_error(union_file_name);
334: }
335: output_file = fopen(output_file_name, "w");
1.30 espie 336: if (output_file == NULL)
1.26 tedu 337: open_error(output_file_name);
338:
339: if (rflag) {
340: code_file = fopen(code_file_name, "w");
1.30 espie 341: if (code_file == NULL)
1.26 tedu 342: open_error(code_file_name);
343: } else
344: code_file = output_file;
1.1 deraadt 345: }
346:
347:
348: int
1.18 pvalchev 349: main(int argc, char *argv[])
1.1 deraadt 350: {
1.27 deraadt 351: if (pledge("stdio rpath wpath cpath", NULL) == -1)
352: fatal("pledge: invalid arguments");
353:
1.26 tedu 354: set_signals();
355: getargs(argc, argv);
356: open_files();
357: reader();
358: lr0();
359: lalr();
360: make_parser();
361: verbose();
362: output();
363: done(0);
364: /* NOTREACHED */
365: return (0);
1.1 deraadt 366: }