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