xref: /openbsd-src/usr.bin/yacc/main.c (revision 3a3fbb3f2e2521ab7c4a56b7ff7462ebd9095ec5)
1 /*	$OpenBSD: main.c,v 1.14 2001/11/19 19:02:18 mpech Exp $	*/
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 
46 #ifndef lint
47 #if 0
48 static char sccsid[] = "@(#)main.c	5.5 (Berkeley) 5/24/93";
49 #else
50 static char rcsid[] = "$OpenBSD: main.c,v 1.14 2001/11/19 19:02:18 mpech Exp $";
51 #endif
52 #endif /* not lint */
53 
54 #include <sys/types.h>
55 #include <fcntl.h>
56 #include <paths.h>
57 #include <signal.h>
58 #include <stdlib.h>
59 #include <unistd.h>
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";
70 char *temp_form = "yacc.XXXXXXXXXXX";
71 
72 int lineno;
73 int outline;
74 
75 int explicit_file_name;
76 
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 
119 void onintr __P((int));
120 void set_signals __P((void));
121 void usage __P((void));
122 void getargs __P((int, char *[]));
123 void create_file_names __P((void));
124 void open_files __P((void));
125 
126 volatile sig_atomic_t sigdie;
127 
128 void
129 done(k)
130 int k;
131 {
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);
140     exit(k);
141 }
142 
143 
144 void
145 onintr(signo)
146 	int signo;
147 {
148     sigdie = 1;
149     done(1);
150 }
151 
152 
153 void
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 
171 void
172 usage()
173 {
174     fprintf(stderr, "usage: %s [-dlrtv] [-b file_prefix] [-o outputfile] [-p symbol_prefix] filename\n", __progname);
175     exit(1);
176 }
177 
178 
179 void
180 getargs(argc, argv)
181 int argc;
182 char *argv[];
183 {
184     int i;
185     char *s;
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 
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 
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 {
298     char *p;
299 
300     p = NULL;
301     if (n)
302     {
303 	p = CALLOC(1, n);
304 	if (!p) no_space();
305     }
306     return (p);
307 }
308 
309 void
310 create_file_names()
311 {
312     int i, len;
313     char *tmpdir;
314 
315     if (!(tmpdir = getenv("TMPDIR")))
316 	tmpdir = _PATH_TMP;
317 
318     len = strlen(tmpdir);
319     i = len + strlen(temp_form) + 1;
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 
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     }
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     {
374         if (explicit_file_name)
375 	{
376 	    char *suffix;
377 
378 	    defines_file_name = MALLOC(strlen(output_file_name)+1);
379 	    if (defines_file_name == 0)
380 	        no_space();
381 	    strcpy(defines_file_name, output_file_name);
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",
398                     __progname, output_file_name);
399                 dflag = 0;
400                 free(defines_file_name);
401                 defines_file_name = 0;
402             }
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 	}
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 
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 
443 void
444 open_files()
445 {
446     int fd;
447 
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 
457     fd = mkstemp(action_file_name);
458     if (fd == -1 || (action_file = fdopen(fd, "w")) == NULL)
459 	open_error(action_file_name);
460 
461     fd = mkstemp(text_file_name);
462     if (fd == -1 || (text_file = fdopen(fd, "w")) == NULL)
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);
477 	fd = mkstemp(union_file_name);
478 	if (fd == -1 || (union_file = fdopen(fd, "w")) == NULL)
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*/
513     return (0);
514 }
515