Annotation of src/usr.bin/yacc/main.c, Revision 1.22
1.22 ! chl 1: /* $OpenBSD: main.c,v 1.21 2008/05/17 23:31:52 sobrado 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: */
35:
36: #ifndef lint
37: char copyright[] =
38: "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
39: All rights reserved.\n";
40: #endif /* not lint */
41:
1.1 deraadt 42: #ifndef lint
1.3 deraadt 43: #if 0
44: static char sccsid[] = "@(#)main.c 5.5 (Berkeley) 5/24/93";
45: #else
1.22 ! chl 46: static char rcsid[] = "$OpenBSD: main.c,v 1.21 2008/05/17 23:31:52 sobrado Exp $";
1.3 deraadt 47: #endif
1.1 deraadt 48: #endif /* not lint */
49:
1.4 deraadt 50: #include <sys/types.h>
1.6 tholo 51: #include <fcntl.h>
1.10 millert 52: #include <paths.h>
1.12 pvalchev 53: #include <signal.h>
1.4 deraadt 54: #include <stdlib.h>
1.12 pvalchev 55: #include <unistd.h>
1.1 deraadt 56: #include "defs.h"
57:
58: char dflag;
59: char lflag;
60: char rflag;
61: char tflag;
62: char vflag;
63:
64: char *symbol_prefix;
65: char *file_prefix = "y";
66:
67: int lineno;
68: int outline;
69:
1.2 niklas 70: int explicit_file_name;
71:
1.1 deraadt 72: char *action_file_name;
73: char *code_file_name;
74: char *defines_file_name;
75: char *input_file_name = "";
76: char *output_file_name;
77: char *text_file_name;
78: char *union_file_name;
79: char *verbose_file_name;
80:
81: FILE *action_file; /* a temp file, used to save actions associated */
82: /* with rules until the parser is written */
83: FILE *code_file; /* y.code.c (used when the -r option is specified) */
84: FILE *defines_file; /* y.tab.h */
85: FILE *input_file; /* the input file */
86: FILE *output_file; /* y.tab.c */
87: FILE *text_file; /* a temp file, used to save text until all */
88: /* symbols have been defined */
89: FILE *union_file; /* a temp file, used to save the union */
90: /* definition until all symbol have been */
91: /* defined */
92: FILE *verbose_file; /* y.output */
93:
94: int nitems;
95: int nrules;
96: int nsyms;
97: int ntokens;
98: int nvars;
99:
100: int start_symbol;
101: char **symbol_name;
102: short *symbol_value;
103: short *symbol_prec;
104: char *symbol_assoc;
105:
106: short *ritem;
107: short *rlhs;
108: short *rrhs;
109: short *rprec;
110: char *rassoc;
111: short **derives;
112: char *nullable;
113:
1.15 millert 114: void onintr(int);
115: void set_signals(void);
116: void usage(void);
117: void getargs(int, char *[]);
118: void create_file_names(void);
119: void open_files(void);
1.12 pvalchev 120:
1.13 deraadt 121: volatile sig_atomic_t sigdie;
122:
1.12 pvalchev 123: void
1.18 pvalchev 124: done(int k)
1.1 deraadt 125: {
1.13 deraadt 126: if (action_file)
127: unlink(action_file_name);
128: if (text_file)
129: unlink(text_file_name);
130: if (union_file)
131: unlink(union_file_name);
132: if (sigdie)
133: _exit(k);
1.1 deraadt 134: exit(k);
135: }
136:
137:
138: void
1.18 pvalchev 139: onintr(int signo)
1.1 deraadt 140: {
1.13 deraadt 141: sigdie = 1;
142: done(1);
1.1 deraadt 143: }
144:
145:
1.12 pvalchev 146: void
1.18 pvalchev 147: set_signals(void)
1.1 deraadt 148: {
149: #ifdef SIGINT
150: if (signal(SIGINT, SIG_IGN) != SIG_IGN)
151: signal(SIGINT, onintr);
152: #endif
153: #ifdef SIGTERM
154: if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
155: signal(SIGTERM, onintr);
156: #endif
157: #ifdef SIGHUP
158: if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
159: signal(SIGHUP, onintr);
160: #endif
161: }
162:
163:
1.12 pvalchev 164: void
1.18 pvalchev 165: usage(void)
1.1 deraadt 166: {
1.21 sobrado 167: fprintf(stderr, "usage: %s [-dlrtv] [-b file_prefix] [-o output_file] [-p symbol_prefix] file\n", __progname);
1.1 deraadt 168: exit(1);
169: }
170:
171:
1.12 pvalchev 172: void
1.18 pvalchev 173: getargs(int argc, char *argv[])
1.1 deraadt 174: {
1.19 robert 175: int ch;
1.1 deraadt 176:
1.19 robert 177: while ((ch = getopt(argc, argv, "b:dlo:p:rtv")) != -1)
1.1 deraadt 178: {
1.19 robert 179: switch (ch)
1.1 deraadt 180: {
181: case 'b':
1.19 robert 182: file_prefix = optarg;
183: break;
184:
1.1 deraadt 185: case 'd':
186: dflag = 1;
187: break;
188:
189: case 'l':
190: lflag = 1;
191: break;
192:
1.2 niklas 193: case 'o':
1.19 robert 194: output_file_name = optarg;
195: explicit_file_name = 1;
196: break;
197:
1.1 deraadt 198: case 'p':
1.19 robert 199: symbol_prefix = optarg;
200: break;
201:
1.1 deraadt 202: case 'r':
203: rflag = 1;
204: break;
205:
206: case 't':
207: tflag = 1;
208: break;
209:
210: case 'v':
211: vflag = 1;
212: break;
213:
214: default:
215: usage();
216: }
217: }
1.19 robert 218: argc -= optind;
219: argv += optind;
1.1 deraadt 220:
1.19 robert 221: if (argc != 1)
222: usage();
223: if (strcmp(*argv, "-") == 0)
224: input_file = stdin;
225: else
226: input_file_name = *argv;
1.1 deraadt 227: }
228:
229:
230: char *
1.18 pvalchev 231: allocate(unsigned int n)
1.1 deraadt 232: {
1.14 mpech 233: char *p;
1.1 deraadt 234:
235: p = NULL;
236: if (n)
237: {
238: p = CALLOC(1, n);
239: if (!p) no_space();
240: }
241: return (p);
242: }
243:
1.16 millert 244: #define TEMPNAME(s, c, d, l) \
245: (asprintf(&(s), "%.*s/yacc.%xXXXXXXXXXX", (int)(l), (d), (c)))
246:
1.12 pvalchev 247: void
1.18 pvalchev 248: create_file_names(void)
1.1 deraadt 249: {
1.16 millert 250: size_t len;
1.1 deraadt 251: char *tmpdir;
252:
1.16 millert 253: if ((tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0')
1.10 millert 254: tmpdir = _PATH_TMP;
1.1 deraadt 255:
256: len = strlen(tmpdir);
1.16 millert 257: if (tmpdir[len-1] == '/')
258: len--;
1.1 deraadt 259:
1.16 millert 260: if (TEMPNAME(action_file_name, 'a', tmpdir, len) == -1 ||
261: TEMPNAME(text_file_name, 'r', tmpdir, len) == -1 ||
262: TEMPNAME(union_file_name, 'u', tmpdir, len) == -1)
263: no_space();
1.1 deraadt 264:
1.16 millert 265: if (output_file_name == NULL)
1.2 niklas 266: {
1.16 millert 267: if (asprintf(&output_file_name, "%s%s", file_prefix, OUTPUT_SUFFIX)
268: == -1)
1.2 niklas 269: no_space();
270: }
1.1 deraadt 271:
1.16 millert 272: if (rflag) {
273: if (asprintf(&code_file_name, "%s%s", file_prefix, CODE_SUFFIX) == -1)
1.1 deraadt 274: no_space();
1.16 millert 275: } else
1.1 deraadt 276: code_file_name = output_file_name;
277:
278: if (dflag)
279: {
1.2 niklas 280: if (explicit_file_name)
281: {
1.8 deraadt 282: char *suffix;
283:
1.16 millert 284: defines_file_name = strdup(output_file_name);
1.2 niklas 285: if (defines_file_name == 0)
286: no_space();
1.8 deraadt 287:
288: /* does the output_file_name have a known suffix */
289: if ((suffix = strrchr(output_file_name, '.')) != 0 &&
290: (!strcmp(suffix, ".c") || /* good, old-fashioned C */
291: !strcmp(suffix, ".C") || /* C++, or C on Windows */
292: !strcmp(suffix, ".cc") || /* C++ */
293: !strcmp(suffix, ".cxx") || /* C++ */
294: !strcmp(suffix, ".cpp"))) /* C++ (Windows) */
295: {
296: strncpy(defines_file_name, output_file_name,
297: suffix - output_file_name + 1);
298: defines_file_name[suffix - output_file_name + 1] = 'h';
299: defines_file_name[suffix - output_file_name + 2] = '\0';
300: } else {
301: fprintf(stderr,"%s: suffix of output file name %s"
302: " not recognized, no -d file generated.\n",
1.10 millert 303: __progname, output_file_name);
1.8 deraadt 304: dflag = 0;
305: free(defines_file_name);
306: defines_file_name = 0;
307: }
1.2 niklas 308: }
309: else
310: {
1.16 millert 311: if (asprintf(&defines_file_name, "%s%s", file_prefix,
312: DEFINES_SUFFIX) == -1)
1.2 niklas 313: no_space();
314: }
1.1 deraadt 315: }
316:
317: if (vflag)
318: {
1.16 millert 319: if (asprintf(&verbose_file_name, "%s%s", file_prefix,
320: VERBOSE_SUFFIX) == -1)
1.1 deraadt 321: no_space();
322: }
323: }
324:
1.4 deraadt 325:
1.12 pvalchev 326: void
1.18 pvalchev 327: open_files(void)
1.1 deraadt 328: {
1.4 deraadt 329: int fd;
330:
1.1 deraadt 331: create_file_names();
332:
333: if (input_file == 0)
334: {
335: input_file = fopen(input_file_name, "r");
336: if (input_file == 0)
337: open_error(input_file_name);
338: }
339:
1.10 millert 340: fd = mkstemp(action_file_name);
341: if (fd == -1 || (action_file = fdopen(fd, "w")) == NULL)
1.1 deraadt 342: open_error(action_file_name);
343:
1.10 millert 344: fd = mkstemp(text_file_name);
345: if (fd == -1 || (text_file = fdopen(fd, "w")) == NULL)
1.1 deraadt 346: open_error(text_file_name);
347:
348: if (vflag)
349: {
350: verbose_file = fopen(verbose_file_name, "w");
351: if (verbose_file == 0)
352: open_error(verbose_file_name);
353: }
354:
355: if (dflag)
356: {
357: defines_file = fopen(defines_file_name, "w");
1.20 pvalchev 358: if (defines_file == NULL)
359: open_write_error(defines_file_name);
1.10 millert 360: fd = mkstemp(union_file_name);
361: if (fd == -1 || (union_file = fdopen(fd, "w")) == NULL)
1.1 deraadt 362: open_error(union_file_name);
363: }
364:
365: output_file = fopen(output_file_name, "w");
366: if (output_file == 0)
367: open_error(output_file_name);
368:
369: if (rflag)
370: {
371: code_file = fopen(code_file_name, "w");
372: if (code_file == 0)
373: open_error(code_file_name);
374: }
375: else
376: code_file = output_file;
377: }
378:
379:
380: int
1.18 pvalchev 381: main(int argc, char *argv[])
1.1 deraadt 382: {
383: set_signals();
384: getargs(argc, argv);
385: open_files();
386: reader();
387: lr0();
388: lalr();
389: make_parser();
390: verbose();
391: output();
392: done(0);
393: /*NOTREACHED*/
1.12 pvalchev 394: return (0);
1.1 deraadt 395: }