Annotation of src/usr.bin/yacc/main.c, Revision 1.17
1.17 ! millert 1: /* $OpenBSD: main.c,v 1.16 2003/04/16 17:43:37 millert 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.17 ! millert 46: static char rcsid[] = "$OpenBSD: main.c,v 1.16 2003/04/16 17:43:37 millert 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.1 deraadt 124: done(k)
125: int k;
126: {
1.13 deraadt 127: if (action_file)
128: unlink(action_file_name);
129: if (text_file)
130: unlink(text_file_name);
131: if (union_file)
132: unlink(union_file_name);
133: if (sigdie)
134: _exit(k);
1.1 deraadt 135: exit(k);
136: }
137:
138:
139: void
1.3 deraadt 140: onintr(signo)
141: int signo;
1.1 deraadt 142: {
1.13 deraadt 143: sigdie = 1;
144: done(1);
1.1 deraadt 145: }
146:
147:
1.12 pvalchev 148: void
1.1 deraadt 149: set_signals()
150: {
151: #ifdef SIGINT
152: if (signal(SIGINT, SIG_IGN) != SIG_IGN)
153: signal(SIGINT, onintr);
154: #endif
155: #ifdef SIGTERM
156: if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
157: signal(SIGTERM, onintr);
158: #endif
159: #ifdef SIGHUP
160: if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
161: signal(SIGHUP, onintr);
162: #endif
163: }
164:
165:
1.12 pvalchev 166: void
1.1 deraadt 167: usage()
168: {
1.10 millert 169: fprintf(stderr, "usage: %s [-dlrtv] [-b file_prefix] [-o outputfile] [-p symbol_prefix] filename\n", __progname);
1.1 deraadt 170: exit(1);
171: }
172:
173:
1.12 pvalchev 174: void
1.1 deraadt 175: getargs(argc, argv)
176: int argc;
177: char *argv[];
178: {
1.14 mpech 179: int i;
180: char *s;
1.1 deraadt 181:
182: for (i = 1; i < argc; ++i)
183: {
184: s = argv[i];
185: if (*s != '-') break;
186: switch (*++s)
187: {
188: case '\0':
189: input_file = stdin;
190: if (i + 1 < argc) usage();
191: return;
192:
193: case '-':
194: ++i;
195: goto no_more_options;
196:
197: case 'b':
198: if (*++s)
199: file_prefix = s;
200: else if (++i < argc)
201: file_prefix = argv[i];
202: else
203: usage();
204: continue;
205:
206: case 'd':
207: dflag = 1;
208: break;
209:
210: case 'l':
211: lflag = 1;
212: break;
213:
1.2 niklas 214: case 'o':
215: if (*++s)
216: output_file_name = s;
217: else if (++i < argc)
218: output_file_name = argv[i];
219: else
220: usage();
221: explicit_file_name = 1;
222: continue;
223:
1.1 deraadt 224: case 'p':
225: if (*++s)
226: symbol_prefix = s;
227: else if (++i < argc)
228: symbol_prefix = argv[i];
229: else
230: usage();
231: continue;
232:
233: case 'r':
234: rflag = 1;
235: break;
236:
237: case 't':
238: tflag = 1;
239: break;
240:
241: case 'v':
242: vflag = 1;
243: break;
244:
245: default:
246: usage();
247: }
248:
249: for (;;)
250: {
251: switch (*++s)
252: {
253: case '\0':
254: goto end_of_option;
255:
256: case 'd':
257: dflag = 1;
258: break;
259:
260: case 'l':
261: lflag = 1;
262: break;
263:
264: case 'r':
265: rflag = 1;
266: break;
267:
268: case 't':
269: tflag = 1;
270: break;
271:
272: case 'v':
273: vflag = 1;
274: break;
275:
276: default:
277: usage();
278: }
279: }
280: end_of_option:;
281: }
282:
283: no_more_options:;
284: if (i + 1 != argc) usage();
285: input_file_name = argv[i];
286: }
287:
288:
289: char *
290: allocate(n)
291: unsigned n;
292: {
1.14 mpech 293: char *p;
1.1 deraadt 294:
295: p = NULL;
296: if (n)
297: {
298: p = CALLOC(1, n);
299: if (!p) no_space();
300: }
301: return (p);
302: }
303:
1.16 millert 304: #define TEMPNAME(s, c, d, l) \
305: (asprintf(&(s), "%.*s/yacc.%xXXXXXXXXXX", (int)(l), (d), (c)))
306:
1.12 pvalchev 307: void
1.1 deraadt 308: create_file_names()
309: {
1.16 millert 310: size_t len;
1.1 deraadt 311: char *tmpdir;
312:
1.16 millert 313: if ((tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0')
1.10 millert 314: tmpdir = _PATH_TMP;
1.1 deraadt 315:
316: len = strlen(tmpdir);
1.16 millert 317: if (tmpdir[len-1] == '/')
318: len--;
1.1 deraadt 319:
1.16 millert 320: if (TEMPNAME(action_file_name, 'a', tmpdir, len) == -1 ||
321: TEMPNAME(text_file_name, 'r', tmpdir, len) == -1 ||
322: TEMPNAME(union_file_name, 'u', tmpdir, len) == -1)
323: no_space();
1.1 deraadt 324:
1.16 millert 325: if (output_file_name == NULL)
1.2 niklas 326: {
1.16 millert 327: if (asprintf(&output_file_name, "%s%s", file_prefix, OUTPUT_SUFFIX)
328: == -1)
1.2 niklas 329: no_space();
330: }
1.1 deraadt 331:
1.16 millert 332: if (rflag) {
333: if (asprintf(&code_file_name, "%s%s", file_prefix, CODE_SUFFIX) == -1)
1.1 deraadt 334: no_space();
1.16 millert 335: } else
1.1 deraadt 336: code_file_name = output_file_name;
337:
338: if (dflag)
339: {
1.2 niklas 340: if (explicit_file_name)
341: {
1.8 deraadt 342: char *suffix;
343:
1.16 millert 344: defines_file_name = strdup(output_file_name);
1.2 niklas 345: if (defines_file_name == 0)
346: no_space();
1.8 deraadt 347:
348: /* does the output_file_name have a known suffix */
349: if ((suffix = strrchr(output_file_name, '.')) != 0 &&
350: (!strcmp(suffix, ".c") || /* good, old-fashioned C */
351: !strcmp(suffix, ".C") || /* C++, or C on Windows */
352: !strcmp(suffix, ".cc") || /* C++ */
353: !strcmp(suffix, ".cxx") || /* C++ */
354: !strcmp(suffix, ".cpp"))) /* C++ (Windows) */
355: {
356: strncpy(defines_file_name, output_file_name,
357: suffix - output_file_name + 1);
358: defines_file_name[suffix - output_file_name + 1] = 'h';
359: defines_file_name[suffix - output_file_name + 2] = '\0';
360: } else {
361: fprintf(stderr,"%s: suffix of output file name %s"
362: " not recognized, no -d file generated.\n",
1.10 millert 363: __progname, output_file_name);
1.8 deraadt 364: dflag = 0;
365: free(defines_file_name);
366: defines_file_name = 0;
367: }
1.2 niklas 368: }
369: else
370: {
1.16 millert 371: if (asprintf(&defines_file_name, "%s%s", file_prefix,
372: DEFINES_SUFFIX) == -1)
1.2 niklas 373: no_space();
374: }
1.1 deraadt 375: }
376:
377: if (vflag)
378: {
1.16 millert 379: if (asprintf(&verbose_file_name, "%s%s", file_prefix,
380: VERBOSE_SUFFIX) == -1)
1.1 deraadt 381: no_space();
382: }
383: }
384:
385:
1.4 deraadt 386: FILE *
387: fsopen(name, mode)
388: char *name;
389: char *mode;
390: {
391: FILE *fp = NULL;
392: int fd, mod = O_RDONLY;
393:
394: if (strchr(mode, 'w'))
395: mod = O_RDWR;
396: if ((fd = open(name, mod | O_EXCL|O_CREAT, 0666)) == -1 ||
397: (fp = fdopen(fd, mode)) == NULL) {
398: if (fd != -1)
399: close(fd);
400: }
401: return (fp);
402: }
403:
1.12 pvalchev 404: void
1.1 deraadt 405: open_files()
406: {
1.4 deraadt 407: int fd;
408:
1.1 deraadt 409: create_file_names();
410:
411: if (input_file == 0)
412: {
413: input_file = fopen(input_file_name, "r");
414: if (input_file == 0)
415: open_error(input_file_name);
416: }
417:
1.10 millert 418: fd = mkstemp(action_file_name);
419: if (fd == -1 || (action_file = fdopen(fd, "w")) == NULL)
1.1 deraadt 420: open_error(action_file_name);
421:
1.10 millert 422: fd = mkstemp(text_file_name);
423: if (fd == -1 || (text_file = fdopen(fd, "w")) == NULL)
1.1 deraadt 424: open_error(text_file_name);
425:
426: if (vflag)
427: {
428: verbose_file = fopen(verbose_file_name, "w");
429: if (verbose_file == 0)
430: open_error(verbose_file_name);
431: }
432:
433: if (dflag)
434: {
435: defines_file = fopen(defines_file_name, "w");
436: if (defines_file == 0)
437: open_error(defines_file_name);
1.10 millert 438: fd = mkstemp(union_file_name);
439: if (fd == -1 || (union_file = fdopen(fd, "w")) == NULL)
1.1 deraadt 440: open_error(union_file_name);
441: }
442:
443: output_file = fopen(output_file_name, "w");
444: if (output_file == 0)
445: open_error(output_file_name);
446:
447: if (rflag)
448: {
449: code_file = fopen(code_file_name, "w");
450: if (code_file == 0)
451: open_error(code_file_name);
452: }
453: else
454: code_file = output_file;
455: }
456:
457:
458: int
459: main(argc, argv)
460: int argc;
461: char *argv[];
462: {
463: set_signals();
464: getargs(argc, argv);
465: open_files();
466: reader();
467: lr0();
468: lalr();
469: make_parser();
470: verbose();
471: output();
472: done(0);
473: /*NOTREACHED*/
1.12 pvalchev 474: return (0);
1.1 deraadt 475: }