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