Annotation of src/usr.bin/yacc/main.c, Revision 1.15
1.15 ! millert 1: /* $OpenBSD: main.c,v 1.14 2001/11/19 19:02:18 mpech 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.
19: * 3. All advertising materials mentioning features or use of this software
20: * must display the following acknowledgement:
21: * This product includes software developed by the University of
22: * California, Berkeley and its contributors.
23: * 4. Neither the name of the University nor the names of its contributors
24: * may be used to endorse or promote products derived from this software
25: * without specific prior written permission.
26: *
27: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37: * SUCH DAMAGE.
38: */
39:
40: #ifndef lint
41: char copyright[] =
42: "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
43: All rights reserved.\n";
44: #endif /* not lint */
45:
1.1 deraadt 46: #ifndef lint
1.3 deraadt 47: #if 0
48: static char sccsid[] = "@(#)main.c 5.5 (Berkeley) 5/24/93";
49: #else
1.15 ! millert 50: static char rcsid[] = "$OpenBSD: main.c,v 1.14 2001/11/19 19:02:18 mpech Exp $";
1.3 deraadt 51: #endif
1.1 deraadt 52: #endif /* not lint */
53:
1.4 deraadt 54: #include <sys/types.h>
1.6 tholo 55: #include <fcntl.h>
1.10 millert 56: #include <paths.h>
1.12 pvalchev 57: #include <signal.h>
1.4 deraadt 58: #include <stdlib.h>
1.12 pvalchev 59: #include <unistd.h>
1.1 deraadt 60: #include "defs.h"
61:
62: char dflag;
63: char lflag;
64: char rflag;
65: char tflag;
66: char vflag;
67:
68: char *symbol_prefix;
69: char *file_prefix = "y";
1.10 millert 70: char *temp_form = "yacc.XXXXXXXXXXX";
1.1 deraadt 71:
72: int lineno;
73: int outline;
74:
1.2 niklas 75: int explicit_file_name;
76:
1.1 deraadt 77: char *action_file_name;
78: char *code_file_name;
79: char *defines_file_name;
80: char *input_file_name = "";
81: char *output_file_name;
82: char *text_file_name;
83: char *union_file_name;
84: char *verbose_file_name;
85:
86: FILE *action_file; /* a temp file, used to save actions associated */
87: /* with rules until the parser is written */
88: FILE *code_file; /* y.code.c (used when the -r option is specified) */
89: FILE *defines_file; /* y.tab.h */
90: FILE *input_file; /* the input file */
91: FILE *output_file; /* y.tab.c */
92: FILE *text_file; /* a temp file, used to save text until all */
93: /* symbols have been defined */
94: FILE *union_file; /* a temp file, used to save the union */
95: /* definition until all symbol have been */
96: /* defined */
97: FILE *verbose_file; /* y.output */
98:
99: int nitems;
100: int nrules;
101: int nsyms;
102: int ntokens;
103: int nvars;
104:
105: int start_symbol;
106: char **symbol_name;
107: short *symbol_value;
108: short *symbol_prec;
109: char *symbol_assoc;
110:
111: short *ritem;
112: short *rlhs;
113: short *rrhs;
114: short *rprec;
115: char *rassoc;
116: short **derives;
117: char *nullable;
118:
1.15 ! millert 119: void onintr(int);
! 120: void set_signals(void);
! 121: void usage(void);
! 122: void getargs(int, char *[]);
! 123: void create_file_names(void);
! 124: void open_files(void);
1.12 pvalchev 125:
1.13 deraadt 126: volatile sig_atomic_t sigdie;
127:
1.12 pvalchev 128: void
1.1 deraadt 129: done(k)
130: int k;
131: {
1.13 deraadt 132: if (action_file)
133: unlink(action_file_name);
134: if (text_file)
135: unlink(text_file_name);
136: if (union_file)
137: unlink(union_file_name);
138: if (sigdie)
139: _exit(k);
1.1 deraadt 140: exit(k);
141: }
142:
143:
144: void
1.3 deraadt 145: onintr(signo)
146: int signo;
1.1 deraadt 147: {
1.13 deraadt 148: sigdie = 1;
149: done(1);
1.1 deraadt 150: }
151:
152:
1.12 pvalchev 153: void
1.1 deraadt 154: set_signals()
155: {
156: #ifdef SIGINT
157: if (signal(SIGINT, SIG_IGN) != SIG_IGN)
158: signal(SIGINT, onintr);
159: #endif
160: #ifdef SIGTERM
161: if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
162: signal(SIGTERM, onintr);
163: #endif
164: #ifdef SIGHUP
165: if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
166: signal(SIGHUP, onintr);
167: #endif
168: }
169:
170:
1.12 pvalchev 171: void
1.1 deraadt 172: usage()
173: {
1.10 millert 174: fprintf(stderr, "usage: %s [-dlrtv] [-b file_prefix] [-o outputfile] [-p symbol_prefix] filename\n", __progname);
1.1 deraadt 175: exit(1);
176: }
177:
178:
1.12 pvalchev 179: void
1.1 deraadt 180: getargs(argc, argv)
181: int argc;
182: char *argv[];
183: {
1.14 mpech 184: int i;
185: char *s;
1.1 deraadt 186:
187: for (i = 1; i < argc; ++i)
188: {
189: s = argv[i];
190: if (*s != '-') break;
191: switch (*++s)
192: {
193: case '\0':
194: input_file = stdin;
195: if (i + 1 < argc) usage();
196: return;
197:
198: case '-':
199: ++i;
200: goto no_more_options;
201:
202: case 'b':
203: if (*++s)
204: file_prefix = s;
205: else if (++i < argc)
206: file_prefix = argv[i];
207: else
208: usage();
209: continue;
210:
211: case 'd':
212: dflag = 1;
213: break;
214:
215: case 'l':
216: lflag = 1;
217: break;
218:
1.2 niklas 219: case 'o':
220: if (*++s)
221: output_file_name = s;
222: else if (++i < argc)
223: output_file_name = argv[i];
224: else
225: usage();
226: explicit_file_name = 1;
227: continue;
228:
1.1 deraadt 229: case 'p':
230: if (*++s)
231: symbol_prefix = s;
232: else if (++i < argc)
233: symbol_prefix = argv[i];
234: else
235: usage();
236: continue;
237:
238: case 'r':
239: rflag = 1;
240: break;
241:
242: case 't':
243: tflag = 1;
244: break;
245:
246: case 'v':
247: vflag = 1;
248: break;
249:
250: default:
251: usage();
252: }
253:
254: for (;;)
255: {
256: switch (*++s)
257: {
258: case '\0':
259: goto end_of_option;
260:
261: case 'd':
262: dflag = 1;
263: break;
264:
265: case 'l':
266: lflag = 1;
267: break;
268:
269: case 'r':
270: rflag = 1;
271: break;
272:
273: case 't':
274: tflag = 1;
275: break;
276:
277: case 'v':
278: vflag = 1;
279: break;
280:
281: default:
282: usage();
283: }
284: }
285: end_of_option:;
286: }
287:
288: no_more_options:;
289: if (i + 1 != argc) usage();
290: input_file_name = argv[i];
291: }
292:
293:
294: char *
295: allocate(n)
296: unsigned n;
297: {
1.14 mpech 298: char *p;
1.1 deraadt 299:
300: p = NULL;
301: if (n)
302: {
303: p = CALLOC(1, n);
304: if (!p) no_space();
305: }
306: return (p);
307: }
308:
1.12 pvalchev 309: void
1.1 deraadt 310: create_file_names()
311: {
312: int i, len;
313: char *tmpdir;
314:
1.10 millert 315: if (!(tmpdir = getenv("TMPDIR")))
316: tmpdir = _PATH_TMP;
1.1 deraadt 317:
318: len = strlen(tmpdir);
1.9 deraadt 319: i = len + strlen(temp_form) + 1;
1.1 deraadt 320: if (len && tmpdir[len-1] != '/')
321: ++i;
322:
323: action_file_name = MALLOC(i);
324: if (action_file_name == 0) no_space();
325: text_file_name = MALLOC(i);
326: if (text_file_name == 0) no_space();
327: union_file_name = MALLOC(i);
328: if (union_file_name == 0) no_space();
329:
330: strcpy(action_file_name, tmpdir);
331: strcpy(text_file_name, tmpdir);
332: strcpy(union_file_name, tmpdir);
333:
334: if (len && tmpdir[len - 1] != '/')
335: {
336: action_file_name[len] = '/';
337: text_file_name[len] = '/';
338: union_file_name[len] = '/';
339: ++len;
340: }
341:
342: strcpy(action_file_name + len, temp_form);
343: strcpy(text_file_name + len, temp_form);
344: strcpy(union_file_name + len, temp_form);
345:
346: action_file_name[len + 5] = 'a';
347: text_file_name[len + 5] = 't';
348: union_file_name[len + 5] = 'u';
349:
350: len = strlen(file_prefix);
351:
1.2 niklas 352: if (!output_file_name)
353: {
354: output_file_name = MALLOC(len + 7);
355: if (output_file_name == 0)
356: no_space();
357: strcpy(output_file_name, file_prefix);
358: strcpy(output_file_name + len, OUTPUT_SUFFIX);
359: }
1.1 deraadt 360:
361: if (rflag)
362: {
363: code_file_name = MALLOC(len + 8);
364: if (code_file_name == 0)
365: no_space();
366: strcpy(code_file_name, file_prefix);
367: strcpy(code_file_name + len, CODE_SUFFIX);
368: }
369: else
370: code_file_name = output_file_name;
371:
372: if (dflag)
373: {
1.2 niklas 374: if (explicit_file_name)
375: {
1.8 deraadt 376: char *suffix;
377:
378: defines_file_name = MALLOC(strlen(output_file_name)+1);
1.2 niklas 379: if (defines_file_name == 0)
380: no_space();
381: strcpy(defines_file_name, output_file_name);
1.8 deraadt 382:
383: /* does the output_file_name have a known suffix */
384: if ((suffix = strrchr(output_file_name, '.')) != 0 &&
385: (!strcmp(suffix, ".c") || /* good, old-fashioned C */
386: !strcmp(suffix, ".C") || /* C++, or C on Windows */
387: !strcmp(suffix, ".cc") || /* C++ */
388: !strcmp(suffix, ".cxx") || /* C++ */
389: !strcmp(suffix, ".cpp"))) /* C++ (Windows) */
390: {
391: strncpy(defines_file_name, output_file_name,
392: suffix - output_file_name + 1);
393: defines_file_name[suffix - output_file_name + 1] = 'h';
394: defines_file_name[suffix - output_file_name + 2] = '\0';
395: } else {
396: fprintf(stderr,"%s: suffix of output file name %s"
397: " not recognized, no -d file generated.\n",
1.10 millert 398: __progname, output_file_name);
1.8 deraadt 399: dflag = 0;
400: free(defines_file_name);
401: defines_file_name = 0;
402: }
1.2 niklas 403: }
404: else
405: {
406: defines_file_name = MALLOC(len + 7);
407: if (defines_file_name == 0)
408: no_space();
409: strcpy(defines_file_name, file_prefix);
410: strcpy(defines_file_name + len, DEFINES_SUFFIX);
411: }
1.1 deraadt 412: }
413:
414: if (vflag)
415: {
416: verbose_file_name = MALLOC(len + 8);
417: if (verbose_file_name == 0)
418: no_space();
419: strcpy(verbose_file_name, file_prefix);
420: strcpy(verbose_file_name + len, VERBOSE_SUFFIX);
421: }
422: }
423:
424:
1.4 deraadt 425: FILE *
426: fsopen(name, mode)
427: char *name;
428: char *mode;
429: {
430: FILE *fp = NULL;
431: int fd, mod = O_RDONLY;
432:
433: if (strchr(mode, 'w'))
434: mod = O_RDWR;
435: if ((fd = open(name, mod | O_EXCL|O_CREAT, 0666)) == -1 ||
436: (fp = fdopen(fd, mode)) == NULL) {
437: if (fd != -1)
438: close(fd);
439: }
440: return (fp);
441: }
442:
1.12 pvalchev 443: void
1.1 deraadt 444: open_files()
445: {
1.4 deraadt 446: int fd;
447:
1.1 deraadt 448: create_file_names();
449:
450: if (input_file == 0)
451: {
452: input_file = fopen(input_file_name, "r");
453: if (input_file == 0)
454: open_error(input_file_name);
455: }
456:
1.10 millert 457: fd = mkstemp(action_file_name);
458: if (fd == -1 || (action_file = fdopen(fd, "w")) == NULL)
1.1 deraadt 459: open_error(action_file_name);
460:
1.10 millert 461: fd = mkstemp(text_file_name);
462: if (fd == -1 || (text_file = fdopen(fd, "w")) == NULL)
1.1 deraadt 463: open_error(text_file_name);
464:
465: if (vflag)
466: {
467: verbose_file = fopen(verbose_file_name, "w");
468: if (verbose_file == 0)
469: open_error(verbose_file_name);
470: }
471:
472: if (dflag)
473: {
474: defines_file = fopen(defines_file_name, "w");
475: if (defines_file == 0)
476: open_error(defines_file_name);
1.10 millert 477: fd = mkstemp(union_file_name);
478: if (fd == -1 || (union_file = fdopen(fd, "w")) == NULL)
1.1 deraadt 479: open_error(union_file_name);
480: }
481:
482: output_file = fopen(output_file_name, "w");
483: if (output_file == 0)
484: open_error(output_file_name);
485:
486: if (rflag)
487: {
488: code_file = fopen(code_file_name, "w");
489: if (code_file == 0)
490: open_error(code_file_name);
491: }
492: else
493: code_file = output_file;
494: }
495:
496:
497: int
498: main(argc, argv)
499: int argc;
500: char *argv[];
501: {
502: set_signals();
503: getargs(argc, argv);
504: open_files();
505: reader();
506: lr0();
507: lalr();
508: make_parser();
509: verbose();
510: output();
511: done(0);
512: /*NOTREACHED*/
1.12 pvalchev 513: return (0);
1.1 deraadt 514: }