Annotation of src/usr.bin/yacc/main.c, Revision 1.23
1.23 ! deraadt 1: /* $OpenBSD: main.c,v 1.22 2009/05/01 10:41:05 chl Exp $ */
1.3 deraadt 2: /* $NetBSD: main.c,v 1.5 1996/03/19 03:21:38 jtc Exp $ */
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:
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 */
79:
80: int nitems;
81: int nrules;
82: int nsyms;
83: int ntokens;
84: int nvars;
85:
86: int start_symbol;
87: char **symbol_name;
88: short *symbol_value;
89: short *symbol_prec;
90: char *symbol_assoc;
91:
92: short *ritem;
93: short *rlhs;
94: short *rrhs;
95: short *rprec;
96: char *rassoc;
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.13 deraadt 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);
1.1 deraadt 120: exit(k);
121: }
122:
123:
124: void
1.18 pvalchev 125: onintr(int signo)
1.1 deraadt 126: {
1.13 deraadt 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
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:
1.12 pvalchev 150: void
1.18 pvalchev 151: usage(void)
1.1 deraadt 152: {
1.21 sobrado 153: fprintf(stderr, "usage: %s [-dlrtv] [-b file_prefix] [-o output_file] [-p symbol_prefix] file\n", __progname);
1.1 deraadt 154: exit(1);
155: }
156:
157:
1.12 pvalchev 158: void
1.18 pvalchev 159: getargs(int argc, char *argv[])
1.1 deraadt 160: {
1.19 robert 161: int ch;
1.1 deraadt 162:
1.19 robert 163: while ((ch = getopt(argc, argv, "b:dlo:p:rtv")) != -1)
1.1 deraadt 164: {
1.19 robert 165: switch (ch)
1.1 deraadt 166: {
167: case 'b':
1.19 robert 168: file_prefix = optarg;
169: break;
170:
1.1 deraadt 171: case 'd':
172: dflag = 1;
173: break;
174:
175: case 'l':
176: lflag = 1;
177: break;
178:
1.2 niklas 179: case 'o':
1.19 robert 180: output_file_name = optarg;
181: explicit_file_name = 1;
182: break;
183:
1.1 deraadt 184: case 'p':
1.19 robert 185: symbol_prefix = optarg;
186: break;
187:
1.1 deraadt 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: }
1.19 robert 204: argc -= optind;
205: argv += optind;
1.1 deraadt 206:
1.19 robert 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:
216: char *
1.18 pvalchev 217: allocate(unsigned int n)
1.1 deraadt 218: {
1.14 mpech 219: char *p;
1.1 deraadt 220:
221: p = NULL;
222: if (n)
223: {
224: p = CALLOC(1, n);
225: if (!p) no_space();
226: }
227: return (p);
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.16 millert 236: size_t len;
1.1 deraadt 237: char *tmpdir;
238:
1.16 millert 239: if ((tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0')
1.10 millert 240: tmpdir = _PATH_TMP;
1.1 deraadt 241:
242: len = strlen(tmpdir);
1.16 millert 243: if (tmpdir[len-1] == '/')
244: len--;
1.1 deraadt 245:
1.16 millert 246: if (TEMPNAME(action_file_name, 'a', tmpdir, len) == -1 ||
247: TEMPNAME(text_file_name, 'r', tmpdir, len) == -1 ||
248: TEMPNAME(union_file_name, 'u', tmpdir, len) == -1)
249: no_space();
1.1 deraadt 250:
1.16 millert 251: if (output_file_name == NULL)
1.2 niklas 252: {
1.16 millert 253: if (asprintf(&output_file_name, "%s%s", file_prefix, OUTPUT_SUFFIX)
254: == -1)
1.2 niklas 255: no_space();
256: }
1.1 deraadt 257:
1.16 millert 258: if (rflag) {
259: if (asprintf(&code_file_name, "%s%s", file_prefix, CODE_SUFFIX) == -1)
1.1 deraadt 260: no_space();
1.16 millert 261: } else
1.1 deraadt 262: code_file_name = output_file_name;
263:
264: if (dflag)
265: {
1.2 niklas 266: if (explicit_file_name)
267: {
1.8 deraadt 268: char *suffix;
269:
1.16 millert 270: defines_file_name = strdup(output_file_name);
1.2 niklas 271: if (defines_file_name == 0)
272: no_space();
1.8 deraadt 273:
274: /* does the output_file_name have a known suffix */
275: if ((suffix = strrchr(output_file_name, '.')) != 0 &&
276: (!strcmp(suffix, ".c") || /* good, old-fashioned C */
277: !strcmp(suffix, ".C") || /* C++, or C on Windows */
278: !strcmp(suffix, ".cc") || /* C++ */
279: !strcmp(suffix, ".cxx") || /* C++ */
280: !strcmp(suffix, ".cpp"))) /* C++ (Windows) */
281: {
282: strncpy(defines_file_name, output_file_name,
283: suffix - output_file_name + 1);
284: defines_file_name[suffix - output_file_name + 1] = 'h';
285: defines_file_name[suffix - output_file_name + 2] = '\0';
286: } else {
287: fprintf(stderr,"%s: suffix of output file name %s"
288: " not recognized, no -d file generated.\n",
1.10 millert 289: __progname, output_file_name);
1.8 deraadt 290: dflag = 0;
291: free(defines_file_name);
292: defines_file_name = 0;
293: }
1.2 niklas 294: }
295: else
296: {
1.16 millert 297: if (asprintf(&defines_file_name, "%s%s", file_prefix,
298: DEFINES_SUFFIX) == -1)
1.2 niklas 299: no_space();
300: }
1.1 deraadt 301: }
302:
303: if (vflag)
304: {
1.16 millert 305: if (asprintf(&verbose_file_name, "%s%s", file_prefix,
306: VERBOSE_SUFFIX) == -1)
1.1 deraadt 307: no_space();
308: }
309: }
310:
1.4 deraadt 311:
1.12 pvalchev 312: void
1.18 pvalchev 313: open_files(void)
1.1 deraadt 314: {
1.4 deraadt 315: int fd;
316:
1.1 deraadt 317: create_file_names();
318:
319: if (input_file == 0)
320: {
321: input_file = fopen(input_file_name, "r");
322: if (input_file == 0)
323: open_error(input_file_name);
324: }
325:
1.10 millert 326: fd = mkstemp(action_file_name);
327: if (fd == -1 || (action_file = fdopen(fd, "w")) == NULL)
1.1 deraadt 328: open_error(action_file_name);
329:
1.10 millert 330: fd = mkstemp(text_file_name);
331: if (fd == -1 || (text_file = fdopen(fd, "w")) == NULL)
1.1 deraadt 332: open_error(text_file_name);
333:
334: if (vflag)
335: {
336: verbose_file = fopen(verbose_file_name, "w");
337: if (verbose_file == 0)
338: open_error(verbose_file_name);
339: }
340:
341: if (dflag)
342: {
343: defines_file = fopen(defines_file_name, "w");
1.20 pvalchev 344: if (defines_file == NULL)
345: open_write_error(defines_file_name);
1.10 millert 346: fd = mkstemp(union_file_name);
347: if (fd == -1 || (union_file = fdopen(fd, "w")) == NULL)
1.1 deraadt 348: open_error(union_file_name);
349: }
350:
351: output_file = fopen(output_file_name, "w");
352: if (output_file == 0)
353: open_error(output_file_name);
354:
355: if (rflag)
356: {
357: code_file = fopen(code_file_name, "w");
358: if (code_file == 0)
359: open_error(code_file_name);
360: }
361: else
362: code_file = output_file;
363: }
364:
365:
366: int
1.18 pvalchev 367: main(int argc, char *argv[])
1.1 deraadt 368: {
369: set_signals();
370: getargs(argc, argv);
371: open_files();
372: reader();
373: lr0();
374: lalr();
375: make_parser();
376: verbose();
377: output();
378: done(0);
379: /*NOTREACHED*/
1.12 pvalchev 380: return (0);
1.1 deraadt 381: }