Annotation of src/usr.bin/yacc/main.c, Revision 1.11
1.11 ! deraadt 1: /* $OpenBSD: main.c,v 1.10 1999/08/04 18:31:26 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.
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.11 ! deraadt 50: static char rcsid[] = "$OpenBSD: main.c,v 1.10 1999/08/04 18:31:26 millert 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.4 deraadt 57: #include <stdlib.h>
1.1 deraadt 58: #include <signal.h>
59: #include "defs.h"
60:
61: char dflag;
62: char lflag;
63: char rflag;
64: char tflag;
65: char vflag;
66:
67: char *symbol_prefix;
68: char *file_prefix = "y";
1.10 millert 69: char *temp_form = "yacc.XXXXXXXXXXX";
1.1 deraadt 70:
71: int lineno;
72: int outline;
73:
1.2 niklas 74: int explicit_file_name;
75:
1.1 deraadt 76: char *action_file_name;
77: char *code_file_name;
78: char *defines_file_name;
79: char *input_file_name = "";
80: char *output_file_name;
81: char *text_file_name;
82: char *union_file_name;
83: char *verbose_file_name;
84:
85: FILE *action_file; /* a temp file, used to save actions associated */
86: /* with rules until the parser is written */
87: FILE *code_file; /* y.code.c (used when the -r option is specified) */
88: FILE *defines_file; /* y.tab.h */
89: FILE *input_file; /* the input file */
90: FILE *output_file; /* y.tab.c */
91: FILE *text_file; /* a temp file, used to save text until all */
92: /* symbols have been defined */
93: FILE *union_file; /* a temp file, used to save the union */
94: /* definition until all symbol have been */
95: /* defined */
96: FILE *verbose_file; /* y.output */
97:
98: int nitems;
99: int nrules;
100: int nsyms;
101: int ntokens;
102: int nvars;
103:
104: int start_symbol;
105: char **symbol_name;
106: short *symbol_value;
107: short *symbol_prec;
108: char *symbol_assoc;
109:
110: short *ritem;
111: short *rlhs;
112: short *rrhs;
113: short *rprec;
114: char *rassoc;
115: short **derives;
116: char *nullable;
117:
118: done(k)
119: int k;
120: {
121: if (action_file) { fclose(action_file); unlink(action_file_name); }
122: if (text_file) { fclose(text_file); unlink(text_file_name); }
123: if (union_file) { fclose(union_file); unlink(union_file_name); }
124: exit(k);
125: }
126:
127:
128: void
1.3 deraadt 129: onintr(signo)
130: int signo;
1.1 deraadt 131: {
1.11 ! deraadt 132: done(1); /* XXX signal race */
1.1 deraadt 133: }
134:
135:
136: set_signals()
137: {
138: #ifdef SIGINT
139: if (signal(SIGINT, SIG_IGN) != SIG_IGN)
140: signal(SIGINT, onintr);
141: #endif
142: #ifdef SIGTERM
143: if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
144: signal(SIGTERM, onintr);
145: #endif
146: #ifdef SIGHUP
147: if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
148: signal(SIGHUP, onintr);
149: #endif
150: }
151:
152:
153: usage()
154: {
1.10 millert 155: fprintf(stderr, "usage: %s [-dlrtv] [-b file_prefix] [-o outputfile] [-p symbol_prefix] filename\n", __progname);
1.1 deraadt 156: exit(1);
157: }
158:
159:
160: getargs(argc, argv)
161: int argc;
162: char *argv[];
163: {
164: register int i;
165: register char *s;
166:
167: for (i = 1; i < argc; ++i)
168: {
169: s = argv[i];
170: if (*s != '-') break;
171: switch (*++s)
172: {
173: case '\0':
174: input_file = stdin;
175: if (i + 1 < argc) usage();
176: return;
177:
178: case '-':
179: ++i;
180: goto no_more_options;
181:
182: case 'b':
183: if (*++s)
184: file_prefix = s;
185: else if (++i < argc)
186: file_prefix = argv[i];
187: else
188: usage();
189: continue;
190:
191: case 'd':
192: dflag = 1;
193: break;
194:
195: case 'l':
196: lflag = 1;
197: break;
198:
1.2 niklas 199: case 'o':
200: if (*++s)
201: output_file_name = s;
202: else if (++i < argc)
203: output_file_name = argv[i];
204: else
205: usage();
206: explicit_file_name = 1;
207: continue;
208:
1.1 deraadt 209: case 'p':
210: if (*++s)
211: symbol_prefix = s;
212: else if (++i < argc)
213: symbol_prefix = argv[i];
214: else
215: usage();
216: continue;
217:
218: case 'r':
219: rflag = 1;
220: break;
221:
222: case 't':
223: tflag = 1;
224: break;
225:
226: case 'v':
227: vflag = 1;
228: break;
229:
230: default:
231: usage();
232: }
233:
234: for (;;)
235: {
236: switch (*++s)
237: {
238: case '\0':
239: goto end_of_option;
240:
241: case 'd':
242: dflag = 1;
243: break;
244:
245: case 'l':
246: lflag = 1;
247: break;
248:
249: case 'r':
250: rflag = 1;
251: break;
252:
253: case 't':
254: tflag = 1;
255: break;
256:
257: case 'v':
258: vflag = 1;
259: break;
260:
261: default:
262: usage();
263: }
264: }
265: end_of_option:;
266: }
267:
268: no_more_options:;
269: if (i + 1 != argc) usage();
270: input_file_name = argv[i];
271: }
272:
273:
274: char *
275: allocate(n)
276: unsigned n;
277: {
278: register char *p;
279:
280: p = NULL;
281: if (n)
282: {
283: p = CALLOC(1, n);
284: if (!p) no_space();
285: }
286: return (p);
287: }
288:
289:
290: create_file_names()
291: {
292: int i, len;
293: char *tmpdir;
294:
1.10 millert 295: if (!(tmpdir = getenv("TMPDIR")))
296: tmpdir = _PATH_TMP;
1.1 deraadt 297:
298: len = strlen(tmpdir);
1.9 deraadt 299: i = len + strlen(temp_form) + 1;
1.1 deraadt 300: if (len && tmpdir[len-1] != '/')
301: ++i;
302:
303: action_file_name = MALLOC(i);
304: if (action_file_name == 0) no_space();
305: text_file_name = MALLOC(i);
306: if (text_file_name == 0) no_space();
307: union_file_name = MALLOC(i);
308: if (union_file_name == 0) no_space();
309:
310: strcpy(action_file_name, tmpdir);
311: strcpy(text_file_name, tmpdir);
312: strcpy(union_file_name, tmpdir);
313:
314: if (len && tmpdir[len - 1] != '/')
315: {
316: action_file_name[len] = '/';
317: text_file_name[len] = '/';
318: union_file_name[len] = '/';
319: ++len;
320: }
321:
322: strcpy(action_file_name + len, temp_form);
323: strcpy(text_file_name + len, temp_form);
324: strcpy(union_file_name + len, temp_form);
325:
326: action_file_name[len + 5] = 'a';
327: text_file_name[len + 5] = 't';
328: union_file_name[len + 5] = 'u';
329:
330: len = strlen(file_prefix);
331:
1.2 niklas 332: if (!output_file_name)
333: {
334: output_file_name = MALLOC(len + 7);
335: if (output_file_name == 0)
336: no_space();
337: strcpy(output_file_name, file_prefix);
338: strcpy(output_file_name + len, OUTPUT_SUFFIX);
339: }
1.1 deraadt 340:
341: if (rflag)
342: {
343: code_file_name = MALLOC(len + 8);
344: if (code_file_name == 0)
345: no_space();
346: strcpy(code_file_name, file_prefix);
347: strcpy(code_file_name + len, CODE_SUFFIX);
348: }
349: else
350: code_file_name = output_file_name;
351:
352: if (dflag)
353: {
1.2 niklas 354: if (explicit_file_name)
355: {
1.8 deraadt 356: char *suffix;
357:
358: defines_file_name = MALLOC(strlen(output_file_name)+1);
1.2 niklas 359: if (defines_file_name == 0)
360: no_space();
361: strcpy(defines_file_name, output_file_name);
1.8 deraadt 362:
363: /* does the output_file_name have a known suffix */
364: if ((suffix = strrchr(output_file_name, '.')) != 0 &&
365: (!strcmp(suffix, ".c") || /* good, old-fashioned C */
366: !strcmp(suffix, ".C") || /* C++, or C on Windows */
367: !strcmp(suffix, ".cc") || /* C++ */
368: !strcmp(suffix, ".cxx") || /* C++ */
369: !strcmp(suffix, ".cpp"))) /* C++ (Windows) */
370: {
371: strncpy(defines_file_name, output_file_name,
372: suffix - output_file_name + 1);
373: defines_file_name[suffix - output_file_name + 1] = 'h';
374: defines_file_name[suffix - output_file_name + 2] = '\0';
375: } else {
376: fprintf(stderr,"%s: suffix of output file name %s"
377: " not recognized, no -d file generated.\n",
1.10 millert 378: __progname, output_file_name);
1.8 deraadt 379: dflag = 0;
380: free(defines_file_name);
381: defines_file_name = 0;
382: }
1.2 niklas 383: }
384: else
385: {
386: defines_file_name = MALLOC(len + 7);
387: if (defines_file_name == 0)
388: no_space();
389: strcpy(defines_file_name, file_prefix);
390: strcpy(defines_file_name + len, DEFINES_SUFFIX);
391: }
1.1 deraadt 392: }
393:
394: if (vflag)
395: {
396: verbose_file_name = MALLOC(len + 8);
397: if (verbose_file_name == 0)
398: no_space();
399: strcpy(verbose_file_name, file_prefix);
400: strcpy(verbose_file_name + len, VERBOSE_SUFFIX);
401: }
402: }
403:
404:
1.4 deraadt 405: FILE *
406: fsopen(name, mode)
407: char *name;
408: char *mode;
409: {
410: FILE *fp = NULL;
411: int fd, mod = O_RDONLY;
412:
413: if (strchr(mode, 'w'))
414: mod = O_RDWR;
415: if ((fd = open(name, mod | O_EXCL|O_CREAT, 0666)) == -1 ||
416: (fp = fdopen(fd, mode)) == NULL) {
417: if (fd != -1)
418: close(fd);
419: }
420: return (fp);
421: }
422:
423:
1.1 deraadt 424: open_files()
425: {
1.4 deraadt 426: int fd;
427:
1.1 deraadt 428: create_file_names();
429:
430: if (input_file == 0)
431: {
432: input_file = fopen(input_file_name, "r");
433: if (input_file == 0)
434: open_error(input_file_name);
435: }
436:
1.10 millert 437: fd = mkstemp(action_file_name);
438: if (fd == -1 || (action_file = fdopen(fd, "w")) == NULL)
1.1 deraadt 439: open_error(action_file_name);
440:
1.10 millert 441: fd = mkstemp(text_file_name);
442: if (fd == -1 || (text_file = fdopen(fd, "w")) == NULL)
1.1 deraadt 443: open_error(text_file_name);
444:
445: if (vflag)
446: {
447: verbose_file = fopen(verbose_file_name, "w");
448: if (verbose_file == 0)
449: open_error(verbose_file_name);
450: }
451:
452: if (dflag)
453: {
454: defines_file = fopen(defines_file_name, "w");
455: if (defines_file == 0)
456: open_error(defines_file_name);
1.10 millert 457: fd = mkstemp(union_file_name);
458: if (fd == -1 || (union_file = fdopen(fd, "w")) == NULL)
1.1 deraadt 459: open_error(union_file_name);
460: }
461:
462: output_file = fopen(output_file_name, "w");
463: if (output_file == 0)
464: open_error(output_file_name);
465:
466: if (rflag)
467: {
468: code_file = fopen(code_file_name, "w");
469: if (code_file == 0)
470: open_error(code_file_name);
471: }
472: else
473: code_file = output_file;
474: }
475:
476:
477: int
478: main(argc, argv)
479: int argc;
480: char *argv[];
481: {
482: set_signals();
483: getargs(argc, argv);
484: open_files();
485: reader();
486: lr0();
487: lalr();
488: make_parser();
489: verbose();
490: output();
491: done(0);
492: /*NOTREACHED*/
493: }