main.c revision 126623
11590Srgrimes/*
21590Srgrimes * Copyright (c) 1989 The Regents of the University of California.
31590Srgrimes * All rights reserved.
41590Srgrimes *
51590Srgrimes * This code is derived from software contributed to Berkeley by
61590Srgrimes * Robert Paul Corbett.
71590Srgrimes *
81590Srgrimes * Redistribution and use in source and binary forms, with or without
91590Srgrimes * modification, are permitted provided that the following conditions
101590Srgrimes * are met:
111590Srgrimes * 1. Redistributions of source code must retain the above copyright
121590Srgrimes *    notice, this list of conditions and the following disclaimer.
131590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141590Srgrimes *    notice, this list of conditions and the following disclaimer in the
151590Srgrimes *    documentation and/or other materials provided with the distribution.
161590Srgrimes * 3. All advertising materials mentioning features or use of this software
171590Srgrimes *    must display the following acknowledgement:
181590Srgrimes *	This product includes software developed by the University of
191590Srgrimes *	California, Berkeley and its contributors.
201590Srgrimes * 4. Neither the name of the University nor the names of its contributors
211590Srgrimes *    may be used to endorse or promote products derived from this software
221590Srgrimes *    without specific prior written permission.
231590Srgrimes *
241590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
251590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
261590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
271590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
281590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
291590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
301590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
311590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
321590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
331590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
341590Srgrimes * SUCH DAMAGE.
351590Srgrimes */
361590Srgrimes
3787628Sdwmalone#if 0
3887628Sdwmalone#ifndef lint
3987628Sdwmalonestatic char sccsid[] = "@(#)main.c	5.5 (Berkeley) 5/24/93";
4087628Sdwmalone#endif
4187628Sdwmalone#endif
4287628Sdwmalone
4387234Smarkm#include <sys/cdefs.h>
4487234Smarkm__FBSDID("$FreeBSD: head/usr.bin/yacc/main.c 126623 2004-03-05 01:52:09Z wes $");
4587234Smarkm
4693831Sobrien#include <paths.h>
471590Srgrimes#include <signal.h>
4821622Ssteve#include <stdlib.h>
4921622Ssteve#include <string.h>
5021622Ssteve#include <unistd.h>
511590Srgrimes#include "defs.h"
521590Srgrimes
531590Srgrimeschar dflag;
541590Srgrimeschar lflag;
551590Srgrimeschar rflag;
561590Srgrimeschar tflag;
571590Srgrimeschar vflag;
581590Srgrimes
5987171Smarkmconst char *symbol_prefix;
6087171Smarkmconst char *file_prefix = "y";
6187171Smarkmchar temp_form[] = "yacc.XXXXXXXXXXX";
621590Srgrimes
631590Srgrimesint lineno;
641590Srgrimesint outline;
651590Srgrimes
661590Srgrimeschar *action_file_name;
671590Srgrimeschar *code_file_name;
681590Srgrimeschar *defines_file_name;
6987171Smarkmconst char *input_file_name = "";
701590Srgrimeschar *output_file_name;
711590Srgrimeschar *text_file_name;
721590Srgrimeschar *union_file_name;
731590Srgrimeschar *verbose_file_name;
741590Srgrimes
751590SrgrimesFILE *action_file;	/*  a temp file, used to save actions associated    */
761590Srgrimes			/*  with rules until the parser is written	    */
771590SrgrimesFILE *code_file;	/*  y.code.c (used when the -r option is specified) */
781590SrgrimesFILE *defines_file;	/*  y.tab.h					    */
791590SrgrimesFILE *input_file;	/*  the input file				    */
801590SrgrimesFILE *output_file;	/*  y.tab.c					    */
811590SrgrimesFILE *text_file;	/*  a temp file, used to save text until all	    */
821590Srgrimes			/*  symbols have been defined			    */
831590SrgrimesFILE *union_file;	/*  a temp file, used to save the union		    */
841590Srgrimes			/*  definition until all symbol have been	    */
851590Srgrimes			/*  defined					    */
861590SrgrimesFILE *verbose_file;	/*  y.output					    */
871590Srgrimes
881590Srgrimesint nitems;
891590Srgrimesint nrules;
901590Srgrimesint nsyms;
911590Srgrimesint ntokens;
921590Srgrimesint nvars;
931590Srgrimes
941590Srgrimesint   start_symbol;
951590Srgrimeschar  **symbol_name;
961590Srgrimesshort *symbol_value;
971590Srgrimesshort *symbol_prec;
981590Srgrimeschar  *symbol_assoc;
991590Srgrimes
1001590Srgrimesshort *ritem;
1011590Srgrimesshort *rlhs;
1021590Srgrimesshort *rrhs;
1031590Srgrimesshort *rprec;
1041590Srgrimeschar  *rassoc;
1051590Srgrimesshort **derives;
1061590Srgrimeschar *nullable;
1071590Srgrimes
10892922Simpstatic void create_file_names(void);
10992922Simpstatic void getargs(int, char **);
11092922Simpstatic void onintr(int);
11192922Simpstatic void open_files(void);
11292922Simpstatic void set_signals(void);
11392922Simpstatic void usage(void);
1141590Srgrimes
11593831Sobrienvolatile sig_atomic_t sigdie;
1161590Srgrimes
11793831Sobrien__dead2 void
1181590Srgrimesdone(k)
1191590Srgrimesint k;
1201590Srgrimes{
1211590Srgrimes    if (action_file) { fclose(action_file); unlink(action_file_name); }
1221590Srgrimes    if (text_file) { fclose(text_file); unlink(text_file_name); }
1231590Srgrimes    if (union_file) { fclose(union_file); unlink(union_file_name); }
12493831Sobrien    if (sigdie) { _exit(k); }
1251590Srgrimes    exit(k);
1261590Srgrimes}
1271590Srgrimes
1281590Srgrimes
12921622Sstevestatic void
1301590Srgrimesonintr(signo)
13187171Smarkm	int signo __unused;
1321590Srgrimes{
13393831Sobrien    sigdie = 1;
1341590Srgrimes    done(1);
1351590Srgrimes}
1361590Srgrimes
1371590Srgrimes
13821622Sstevestatic void
1391590Srgrimesset_signals()
1401590Srgrimes{
1411590Srgrimes#ifdef SIGINT
1421590Srgrimes    if (signal(SIGINT, SIG_IGN) != SIG_IGN)
1431590Srgrimes	signal(SIGINT, onintr);
1441590Srgrimes#endif
1451590Srgrimes#ifdef SIGTERM
1461590Srgrimes    if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
1471590Srgrimes	signal(SIGTERM, onintr);
1481590Srgrimes#endif
1491590Srgrimes#ifdef SIGHUP
1501590Srgrimes    if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
1511590Srgrimes	signal(SIGHUP, onintr);
1521590Srgrimes#endif
1531590Srgrimes}
1541590Srgrimes
1551590Srgrimes
15621622Sstevestatic void
1571590Srgrimesusage()
1581590Srgrimes{
15928856Scharnier    fprintf(stderr, "%s\n%s\n",
16028856Scharnier		"usage: yacc [-dlrtv] [-b file_prefix] [-o output_filename]",
16128856Scharnier		"            [-p symbol_prefix] filename");
1621590Srgrimes    exit(1);
1631590Srgrimes}
1641590Srgrimes
1651590Srgrimes
16621622Sstevestatic void
1671590Srgrimesgetargs(argc, argv)
1681590Srgrimesint argc;
1691590Srgrimeschar *argv[];
1701590Srgrimes{
171126623Swes    int ch;
1721590Srgrimes
173126623Swes    while ((ch = getopt(argc, argv, "b:dlo:p:rtv")) != -1)
1741590Srgrimes    {
175126623Swes	switch (ch)
1761590Srgrimes	{
1771590Srgrimes	case 'b':
178126623Swes	    file_prefix = optarg;
179126623Swes	    break;
1801590Srgrimes
1811590Srgrimes	case 'd':
1821590Srgrimes	    dflag = 1;
1831590Srgrimes	    break;
1841590Srgrimes
1851590Srgrimes	case 'l':
1861590Srgrimes	    lflag = 1;
1871590Srgrimes	    break;
1881590Srgrimes
18922776Ssteve	case 'o':
190126623Swes	    output_file_name = optarg;
191126623Swes	    break;
19222776Ssteve
1931590Srgrimes	case 'p':
194126623Swes	    symbol_prefix = optarg;
195126623Swes	    break;
1961590Srgrimes
1971590Srgrimes	case 'r':
1981590Srgrimes	    rflag = 1;
1991590Srgrimes	    break;
2001590Srgrimes
2011590Srgrimes	case 't':
2021590Srgrimes	    tflag = 1;
2031590Srgrimes	    break;
2041590Srgrimes
2051590Srgrimes	case 'v':
2061590Srgrimes	    vflag = 1;
2071590Srgrimes	    break;
2081590Srgrimes
2091590Srgrimes	default:
2101590Srgrimes	    usage();
2111590Srgrimes	}
2121590Srgrimes    }
2131590Srgrimes
214126623Swes    if (optind + 1 != argc)
215126623Swes	usage();
216126623Swes    if (strcmp(argv[optind], "-") == 0)
217126623Swes	input_file = stdin;
218126623Swes    else
219126623Swes	input_file_name = argv[optind];
2201590Srgrimes}
2211590Srgrimes
2221590Srgrimes
2231590Srgrimeschar *
2241590Srgrimesallocate(n)
2251590Srgrimesunsigned n;
2261590Srgrimes{
22787171Smarkm    char *p;
2281590Srgrimes
2291590Srgrimes    p = NULL;
2301590Srgrimes    if (n)
2311590Srgrimes    {
2321590Srgrimes	p = CALLOC(1, n);
2331590Srgrimes	if (!p) no_space();
2341590Srgrimes    }
2351590Srgrimes    return (p);
2361590Srgrimes}
2371590Srgrimes
2381590Srgrimes
23921622Sstevestatic void
2401590Srgrimescreate_file_names()
2411590Srgrimes{
2421590Srgrimes    int i, len;
24387171Smarkm    const char *tmpdir;
2441590Srgrimes
24593831Sobrien    if (!(tmpdir = getenv("TMPDIR")))
24693831Sobrien	tmpdir = _PATH_TMP;
2471590Srgrimes
2481590Srgrimes    len = strlen(tmpdir);
24993831Sobrien    i = len + strlen(temp_form) + 1;
2501590Srgrimes    if (len && tmpdir[len-1] != '/')
2511590Srgrimes	++i;
2521590Srgrimes
2531590Srgrimes    action_file_name = MALLOC(i);
2541590Srgrimes    if (action_file_name == 0) no_space();
2551590Srgrimes    text_file_name = MALLOC(i);
2561590Srgrimes    if (text_file_name == 0) no_space();
2571590Srgrimes    union_file_name = MALLOC(i);
2581590Srgrimes    if (union_file_name == 0) no_space();
2591590Srgrimes
2601590Srgrimes    strcpy(action_file_name, tmpdir);
2611590Srgrimes    strcpy(text_file_name, tmpdir);
2621590Srgrimes    strcpy(union_file_name, tmpdir);
2631590Srgrimes
2641590Srgrimes    if (len && tmpdir[len - 1] != '/')
2651590Srgrimes    {
2661590Srgrimes	action_file_name[len] = '/';
2671590Srgrimes	text_file_name[len] = '/';
2681590Srgrimes	union_file_name[len] = '/';
2691590Srgrimes	++len;
2701590Srgrimes    }
2711590Srgrimes
2721590Srgrimes    strcpy(action_file_name + len, temp_form);
2731590Srgrimes    strcpy(text_file_name + len, temp_form);
2741590Srgrimes    strcpy(union_file_name + len, temp_form);
2751590Srgrimes
2761590Srgrimes    action_file_name[len + 5] = 'a';
2771590Srgrimes    text_file_name[len + 5] = 't';
2781590Srgrimes    union_file_name[len + 5] = 'u';
2791590Srgrimes
28022776Ssteve    if (output_file_name != 0)
28122776Ssteve    {
28222776Ssteve	file_prefix = output_file_name;
28322776Ssteve	len = strlen(file_prefix);
28422776Ssteve    }
28522776Ssteve    else
28622776Ssteve    {
28722776Ssteve	len = strlen(file_prefix);
28822776Ssteve	output_file_name = MALLOC(len + 7);
28922776Ssteve	if (output_file_name == 0)
29022776Ssteve	    no_space();
29122776Ssteve	strcpy(output_file_name, file_prefix);
29222776Ssteve	strcpy(output_file_name + len, OUTPUT_SUFFIX);
29322776Ssteve    }
2941590Srgrimes
2951590Srgrimes    if (rflag)
2961590Srgrimes    {
2971590Srgrimes	code_file_name = MALLOC(len + 8);
2981590Srgrimes	if (code_file_name == 0)
2991590Srgrimes	    no_space();
3001590Srgrimes	strcpy(code_file_name, file_prefix);
30122776Ssteve	if (file_prefix == output_file_name)
30222776Ssteve	{
30322776Ssteve	    /*
30422776Ssteve	     * XXX ".tab.c" here is OUTPUT_SUFFIX, but since its length is
30522776Ssteve	     * in various magic numbers, don't bother using the macro.
30622776Ssteve	     */
30722776Ssteve	    if (len >= 6 && strcmp(code_file_name + len - 6, ".tab.c") == 0)
30822776Ssteve		strcpy(code_file_name + len - 6, CODE_SUFFIX);
30922776Ssteve	    else if (len >= 2 && strcmp(code_file_name + len - 2, ".c") == 0)
31022776Ssteve		strcpy(code_file_name + len - 2, CODE_SUFFIX);
31122776Ssteve	    else
31222776Ssteve		strcpy(code_file_name + len, CODE_SUFFIX);
31322776Ssteve	}
31422776Ssteve	else
31522776Ssteve	    strcpy(code_file_name + len, CODE_SUFFIX);
3161590Srgrimes    }
3171590Srgrimes    else
3181590Srgrimes	code_file_name = output_file_name;
3191590Srgrimes
3201590Srgrimes    if (dflag)
3211590Srgrimes    {
3221590Srgrimes	defines_file_name = MALLOC(len + 7);
3231590Srgrimes	if (defines_file_name == 0)
3241590Srgrimes	    no_space();
3251590Srgrimes	strcpy(defines_file_name, file_prefix);
32622776Ssteve	if (file_prefix == output_file_name)
32722776Ssteve	{
32822776Ssteve#define BISON_DEFINES_SUFFIX  ".h"
32922776Ssteve	    if (len >= 2 && strcmp(defines_file_name + len - 2, ".c") == 0)
33022776Ssteve		strcpy(defines_file_name + len - 2, BISON_DEFINES_SUFFIX);
33122776Ssteve	    else
33222776Ssteve		strcpy(defines_file_name + len, BISON_DEFINES_SUFFIX);
33322776Ssteve	}
33422776Ssteve	else
33522776Ssteve	    strcpy(defines_file_name + len, DEFINES_SUFFIX);
3361590Srgrimes    }
3371590Srgrimes
3381590Srgrimes    if (vflag)
3391590Srgrimes    {
3401590Srgrimes	verbose_file_name = MALLOC(len + 8);
3411590Srgrimes	if (verbose_file_name == 0)
3421590Srgrimes	    no_space();
3431590Srgrimes	strcpy(verbose_file_name, file_prefix);
34422776Ssteve	if (file_prefix == output_file_name)
34522776Ssteve	{
34622776Ssteve	    if (len >= 6 && strcmp(verbose_file_name + len - 6, ".tab.c") == 0)
34722776Ssteve		strcpy(verbose_file_name + len - 6, VERBOSE_SUFFIX);
34822776Ssteve	    else if (len >= 2 && strcmp(verbose_file_name + len - 2, ".c") == 0)
34922776Ssteve		strcpy(verbose_file_name + len - 2, VERBOSE_SUFFIX);
35022776Ssteve	    else
35122776Ssteve		strcpy(verbose_file_name + len, VERBOSE_SUFFIX);
35222776Ssteve	}
35322776Ssteve	else
35422776Ssteve	    strcpy(verbose_file_name + len, VERBOSE_SUFFIX);
3551590Srgrimes    }
3561590Srgrimes}
3571590Srgrimes
3581590Srgrimes
35921622Sstevestatic void
3601590Srgrimesopen_files()
3611590Srgrimes{
36236790Simp    int fd;
36336790Simp
3641590Srgrimes    create_file_names();
3651590Srgrimes
3661590Srgrimes    if (input_file == 0)
3671590Srgrimes    {
3681590Srgrimes	input_file = fopen(input_file_name, "r");
3691590Srgrimes	if (input_file == 0)
3701590Srgrimes	    open_error(input_file_name);
3711590Srgrimes    }
3721590Srgrimes
37336790Simp    fd = mkstemp(action_file_name);
37436790Simp    if (fd < 0 || (action_file = fdopen(fd, "w")) == NULL) {
37536790Simp        if (fd >= 0)
37636790Simp	    close(fd);
3771590Srgrimes	open_error(action_file_name);
37836790Simp    }
37936790Simp    fd = mkstemp(text_file_name);
38036790Simp    if (fd < 0 || (text_file = fdopen(fd, "w")) == NULL) {
38136790Simp        if (fd >= 0)
38236790Simp	    close(fd);
38336790Simp	open_error(text_file_name);
38436790Simp    }
38536790Simp    fd = mkstemp(union_file_name);
38636790Simp    if (fd < 0 || (union_file = fdopen(fd, "w")) == NULL) {
38736790Simp        if (fd >= 0)
38836790Simp	    close(fd);
38936790Simp	open_error(union_file_name);
39036790Simp    }
3911590Srgrimes
3921590Srgrimes    text_file = fopen(text_file_name, "w");
3931590Srgrimes    if (text_file == 0)
3941590Srgrimes	open_error(text_file_name);
3951590Srgrimes
3961590Srgrimes    if (vflag)
3971590Srgrimes    {
3981590Srgrimes	verbose_file = fopen(verbose_file_name, "w");
3991590Srgrimes	if (verbose_file == 0)
4001590Srgrimes	    open_error(verbose_file_name);
4011590Srgrimes    }
4021590Srgrimes
4031590Srgrimes    if (dflag)
4041590Srgrimes    {
4051590Srgrimes	defines_file = fopen(defines_file_name, "w");
4061590Srgrimes	if (defines_file == 0)
4071590Srgrimes	    open_error(defines_file_name);
4081590Srgrimes	union_file = fopen(union_file_name, "w");
4091590Srgrimes	if (union_file ==  0)
4101590Srgrimes	    open_error(union_file_name);
4111590Srgrimes    }
4121590Srgrimes
4131590Srgrimes    output_file = fopen(output_file_name, "w");
4141590Srgrimes    if (output_file == 0)
4151590Srgrimes	open_error(output_file_name);
4161590Srgrimes
4171590Srgrimes    if (rflag)
4181590Srgrimes    {
4191590Srgrimes	code_file = fopen(code_file_name, "w");
4201590Srgrimes	if (code_file == 0)
4211590Srgrimes	    open_error(code_file_name);
4221590Srgrimes    }
4231590Srgrimes    else
4241590Srgrimes	code_file = output_file;
4251590Srgrimes}
4261590Srgrimes
4271590Srgrimes
4281590Srgrimesint
42993832Sobrienmain(int argc, char *argv[])
4301590Srgrimes{
4311590Srgrimes    set_signals();
4321590Srgrimes    getargs(argc, argv);
4331590Srgrimes    open_files();
4341590Srgrimes    reader();
4351590Srgrimes    lr0();
4361590Srgrimes    lalr();
4371590Srgrimes    make_parser();
4381590Srgrimes    verbose();
4391590Srgrimes    output();
4401590Srgrimes    done(0);
4411590Srgrimes    /*NOTREACHED*/
44221622Ssteve    return (0);
4431590Srgrimes}
444