Annotation of src/usr.bin/yacc/main.c, Revision 1.21
1.21 ! sobrado 1: /* $OpenBSD: main.c,v 1.20 2005/06/08 03:18:59 pvalchev 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.21 ! sobrado 46: static char rcsid[] = "$OpenBSD: main.c,v 1.20 2005/06/08 03:18:59 pvalchev 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:
325:
1.4 deraadt 326: FILE *
1.18 pvalchev 327: fsopen(char *name, char *mode)
1.4 deraadt 328: {
329: FILE *fp = NULL;
330: int fd, mod = O_RDONLY;
331:
332: if (strchr(mode, 'w'))
333: mod = O_RDWR;
334: if ((fd = open(name, mod | O_EXCL|O_CREAT, 0666)) == -1 ||
335: (fp = fdopen(fd, mode)) == NULL) {
336: if (fd != -1)
337: close(fd);
338: }
339: return (fp);
340: }
341:
1.12 pvalchev 342: void
1.18 pvalchev 343: open_files(void)
1.1 deraadt 344: {
1.4 deraadt 345: int fd;
346:
1.1 deraadt 347: create_file_names();
348:
349: if (input_file == 0)
350: {
351: input_file = fopen(input_file_name, "r");
352: if (input_file == 0)
353: open_error(input_file_name);
354: }
355:
1.10 millert 356: fd = mkstemp(action_file_name);
357: if (fd == -1 || (action_file = fdopen(fd, "w")) == NULL)
1.1 deraadt 358: open_error(action_file_name);
359:
1.10 millert 360: fd = mkstemp(text_file_name);
361: if (fd == -1 || (text_file = fdopen(fd, "w")) == NULL)
1.1 deraadt 362: open_error(text_file_name);
363:
364: if (vflag)
365: {
366: verbose_file = fopen(verbose_file_name, "w");
367: if (verbose_file == 0)
368: open_error(verbose_file_name);
369: }
370:
371: if (dflag)
372: {
373: defines_file = fopen(defines_file_name, "w");
1.20 pvalchev 374: if (defines_file == NULL)
375: open_write_error(defines_file_name);
1.10 millert 376: fd = mkstemp(union_file_name);
377: if (fd == -1 || (union_file = fdopen(fd, "w")) == NULL)
1.1 deraadt 378: open_error(union_file_name);
379: }
380:
381: output_file = fopen(output_file_name, "w");
382: if (output_file == 0)
383: open_error(output_file_name);
384:
385: if (rflag)
386: {
387: code_file = fopen(code_file_name, "w");
388: if (code_file == 0)
389: open_error(code_file_name);
390: }
391: else
392: code_file = output_file;
393: }
394:
395:
396: int
1.18 pvalchev 397: main(int argc, char *argv[])
1.1 deraadt 398: {
399: set_signals();
400: getargs(argc, argv);
401: open_files();
402: reader();
403: lr0();
404: lalr();
405: make_parser();
406: verbose();
407: output();
408: done(0);
409: /*NOTREACHED*/
1.12 pvalchev 410: return (0);
1.1 deraadt 411: }