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