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 * 4. Neither the name of the University nor the names of its contributors
171590Srgrimes *    may be used to endorse or promote products derived from this software
181590Srgrimes *    without specific prior written permission.
191590Srgrimes *
201590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
211590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
221590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
231590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
241590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
251590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
261590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
271590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
281590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
291590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
301590Srgrimes * SUCH DAMAGE.
311590Srgrimes */
321590Srgrimes
3387628Sdwmalone#if 0
3487628Sdwmalone#ifndef lint
3587628Sdwmalonestatic char sccsid[] = "@(#)main.c	5.5 (Berkeley) 5/24/93";
3687628Sdwmalone#endif
3787628Sdwmalone#endif
3887628Sdwmalone
3987234Smarkm#include <sys/cdefs.h>
4087234Smarkm__FBSDID("$FreeBSD$");
4187234Smarkm
4293831Sobrien#include <paths.h>
431590Srgrimes#include <signal.h>
4421622Ssteve#include <stdlib.h>
4521622Ssteve#include <string.h>
4621622Ssteve#include <unistd.h>
471590Srgrimes#include "defs.h"
481590Srgrimes
491590Srgrimeschar dflag;
501590Srgrimeschar lflag;
511590Srgrimeschar rflag;
521590Srgrimeschar tflag;
531590Srgrimeschar vflag;
541590Srgrimes
5587171Smarkmconst char *symbol_prefix;
5687171Smarkmconst char *file_prefix = "y";
5787171Smarkmchar temp_form[] = "yacc.XXXXXXXXXXX";
581590Srgrimes
591590Srgrimesint lineno;
601590Srgrimesint outline;
611590Srgrimes
621590Srgrimeschar *action_file_name;
631590Srgrimeschar *code_file_name;
641590Srgrimeschar *defines_file_name;
6587171Smarkmconst char *input_file_name = "";
661590Srgrimeschar *output_file_name;
671590Srgrimeschar *text_file_name;
681590Srgrimeschar *union_file_name;
691590Srgrimeschar *verbose_file_name;
701590Srgrimes
711590SrgrimesFILE *action_file;	/*  a temp file, used to save actions associated    */
721590Srgrimes			/*  with rules until the parser is written	    */
731590SrgrimesFILE *code_file;	/*  y.code.c (used when the -r option is specified) */
741590SrgrimesFILE *defines_file;	/*  y.tab.h					    */
751590SrgrimesFILE *input_file;	/*  the input file				    */
761590SrgrimesFILE *output_file;	/*  y.tab.c					    */
771590SrgrimesFILE *text_file;	/*  a temp file, used to save text until all	    */
781590Srgrimes			/*  symbols have been defined			    */
791590SrgrimesFILE *union_file;	/*  a temp file, used to save the union		    */
801590Srgrimes			/*  definition until all symbol have been	    */
811590Srgrimes			/*  defined					    */
821590SrgrimesFILE *verbose_file;	/*  y.output					    */
831590Srgrimes
841590Srgrimesint nitems;
851590Srgrimesint nrules;
861590Srgrimesint nsyms;
871590Srgrimesint ntokens;
881590Srgrimesint nvars;
891590Srgrimes
901590Srgrimesint   start_symbol;
911590Srgrimeschar  **symbol_name;
921590Srgrimesshort *symbol_value;
931590Srgrimesshort *symbol_prec;
941590Srgrimeschar  *symbol_assoc;
951590Srgrimes
961590Srgrimesshort *ritem;
971590Srgrimesshort *rlhs;
981590Srgrimesshort *rrhs;
991590Srgrimesshort *rprec;
1001590Srgrimeschar  *rassoc;
1011590Srgrimesshort **derives;
1021590Srgrimeschar *nullable;
1031590Srgrimes
10492922Simpstatic void create_file_names(void);
10592922Simpstatic void getargs(int, char **);
10692922Simpstatic void onintr(int);
10792922Simpstatic void open_files(void);
10892922Simpstatic void set_signals(void);
10992922Simpstatic void usage(void);
1101590Srgrimes
11193831Sobrienvolatile sig_atomic_t sigdie;
1121590Srgrimes
11393831Sobrien__dead2 void
114214959Sobriendone(int k)
1151590Srgrimes{
1161590Srgrimes    if (action_file) { fclose(action_file); unlink(action_file_name); }
1171590Srgrimes    if (text_file) { fclose(text_file); unlink(text_file_name); }
1181590Srgrimes    if (union_file) { fclose(union_file); unlink(union_file_name); }
11993831Sobrien    if (sigdie) { _exit(k); }
1201590Srgrimes    exit(k);
1211590Srgrimes}
1221590Srgrimes
1231590Srgrimes
12421622Sstevestatic void
125214959Sobrienonintr(int signo __unused)
1261590Srgrimes{
12793831Sobrien    sigdie = 1;
1281590Srgrimes    done(1);
1291590Srgrimes}
1301590Srgrimes
1311590Srgrimes
13221622Sstevestatic void
133214959Sobrienset_signals(void)
1341590Srgrimes{
1351590Srgrimes#ifdef SIGINT
1361590Srgrimes    if (signal(SIGINT, SIG_IGN) != SIG_IGN)
1371590Srgrimes	signal(SIGINT, onintr);
1381590Srgrimes#endif
1391590Srgrimes#ifdef SIGTERM
1401590Srgrimes    if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
1411590Srgrimes	signal(SIGTERM, onintr);
1421590Srgrimes#endif
1431590Srgrimes#ifdef SIGHUP
1441590Srgrimes    if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
1451590Srgrimes	signal(SIGHUP, onintr);
1461590Srgrimes#endif
1471590Srgrimes}
1481590Srgrimes
1491590Srgrimes
15021622Sstevestatic void
151214959Sobrienusage(void)
1521590Srgrimes{
15328856Scharnier    fprintf(stderr, "%s\n%s\n",
15428856Scharnier		"usage: yacc [-dlrtv] [-b file_prefix] [-o output_filename]",
15528856Scharnier		"            [-p symbol_prefix] filename");
1561590Srgrimes    exit(1);
1571590Srgrimes}
1581590Srgrimes
1591590Srgrimes
16021622Sstevestatic void
161214959Sobriengetargs(int argc, char *argv[])
1621590Srgrimes{
163126623Swes    int ch;
1641590Srgrimes
165214964Sobrien    while ((ch = getopt(argc, argv, "b:dlo:p:rtvy")) != -1)
1661590Srgrimes    {
167126623Swes	switch (ch)
1681590Srgrimes	{
1691590Srgrimes	case 'b':
170126623Swes	    file_prefix = optarg;
171126623Swes	    break;
1721590Srgrimes
1731590Srgrimes	case 'd':
1741590Srgrimes	    dflag = 1;
1751590Srgrimes	    break;
1761590Srgrimes
1771590Srgrimes	case 'l':
1781590Srgrimes	    lflag = 1;
1791590Srgrimes	    break;
1801590Srgrimes
18122776Ssteve	case 'o':
182126623Swes	    output_file_name = optarg;
183126623Swes	    break;
18422776Ssteve
1851590Srgrimes	case 'p':
186126623Swes	    symbol_prefix = optarg;
187126623Swes	    break;
1881590Srgrimes
1891590Srgrimes	case 'r':
1901590Srgrimes	    rflag = 1;
1911590Srgrimes	    break;
1921590Srgrimes
1931590Srgrimes	case 't':
1941590Srgrimes	    tflag = 1;
1951590Srgrimes	    break;
1961590Srgrimes
1971590Srgrimes	case 'v':
1981590Srgrimes	    vflag = 1;
1991590Srgrimes	    break;
2001590Srgrimes
201214964Sobrien	case 'y':
202214964Sobrien	    /* for bison compatibility -- byacc is already POSIX compatible */
203214964Sobrien	    break;
204214964Sobrien
2051590Srgrimes	default:
2061590Srgrimes	    usage();
2071590Srgrimes	}
2081590Srgrimes    }
2091590Srgrimes
210126623Swes    if (optind + 1 != argc)
211126623Swes	usage();
212126623Swes    if (strcmp(argv[optind], "-") == 0)
213126623Swes	input_file = stdin;
214126623Swes    else
215126623Swes	input_file_name = argv[optind];
2161590Srgrimes}
2171590Srgrimes
2181590Srgrimes
219214961Sobrienvoid *
220214961Sobrienallocate(size_t n)
2211590Srgrimes{
222214961Sobrien    void *p;
2231590Srgrimes
2241590Srgrimes    p = NULL;
2251590Srgrimes    if (n)
2261590Srgrimes    {
227214961Sobrien	p = calloc(1, n);
2281590Srgrimes	if (!p) no_space();
2291590Srgrimes    }
2301590Srgrimes    return (p);
2311590Srgrimes}
2321590Srgrimes
2331590Srgrimes
23421622Sstevestatic void
235214959Sobriencreate_file_names(void)
2361590Srgrimes{
2371590Srgrimes    int i, len;
23887171Smarkm    const char *tmpdir;
2391590Srgrimes
24093831Sobrien    if (!(tmpdir = getenv("TMPDIR")))
24193831Sobrien	tmpdir = _PATH_TMP;
2421590Srgrimes
2431590Srgrimes    len = strlen(tmpdir);
24493831Sobrien    i = len + strlen(temp_form) + 1;
2451590Srgrimes    if (len && tmpdir[len-1] != '/')
2461590Srgrimes	++i;
2471590Srgrimes
248214961Sobrien    action_file_name = malloc(i);
2491590Srgrimes    if (action_file_name == 0) no_space();
250214961Sobrien    text_file_name = malloc(i);
2511590Srgrimes    if (text_file_name == 0) no_space();
252214961Sobrien    union_file_name = malloc(i);
2531590Srgrimes    if (union_file_name == 0) no_space();
2541590Srgrimes
2551590Srgrimes    strcpy(action_file_name, tmpdir);
2561590Srgrimes    strcpy(text_file_name, tmpdir);
2571590Srgrimes    strcpy(union_file_name, tmpdir);
2581590Srgrimes
2591590Srgrimes    if (len && tmpdir[len - 1] != '/')
2601590Srgrimes    {
2611590Srgrimes	action_file_name[len] = '/';
2621590Srgrimes	text_file_name[len] = '/';
2631590Srgrimes	union_file_name[len] = '/';
2641590Srgrimes	++len;
2651590Srgrimes    }
2661590Srgrimes
2671590Srgrimes    strcpy(action_file_name + len, temp_form);
2681590Srgrimes    strcpy(text_file_name + len, temp_form);
2691590Srgrimes    strcpy(union_file_name + len, temp_form);
2701590Srgrimes
2711590Srgrimes    action_file_name[len + 5] = 'a';
2721590Srgrimes    text_file_name[len + 5] = 't';
2731590Srgrimes    union_file_name[len + 5] = 'u';
2741590Srgrimes
27522776Ssteve    if (output_file_name != 0)
27622776Ssteve    {
27722776Ssteve	file_prefix = output_file_name;
27822776Ssteve	len = strlen(file_prefix);
27922776Ssteve    }
28022776Ssteve    else
28122776Ssteve    {
28222776Ssteve	len = strlen(file_prefix);
283214961Sobrien	output_file_name = malloc(len + 7);
28422776Ssteve	if (output_file_name == 0)
28522776Ssteve	    no_space();
28622776Ssteve	strcpy(output_file_name, file_prefix);
28722776Ssteve	strcpy(output_file_name + len, OUTPUT_SUFFIX);
28822776Ssteve    }
2891590Srgrimes
2901590Srgrimes    if (rflag)
2911590Srgrimes    {
292214961Sobrien	code_file_name = malloc(len + 8);
2931590Srgrimes	if (code_file_name == 0)
2941590Srgrimes	    no_space();
2951590Srgrimes	strcpy(code_file_name, file_prefix);
29622776Ssteve	if (file_prefix == output_file_name)
29722776Ssteve	{
29822776Ssteve	    /*
29922776Ssteve	     * XXX ".tab.c" here is OUTPUT_SUFFIX, but since its length is
30022776Ssteve	     * in various magic numbers, don't bother using the macro.
30122776Ssteve	     */
30222776Ssteve	    if (len >= 6 && strcmp(code_file_name + len - 6, ".tab.c") == 0)
30322776Ssteve		strcpy(code_file_name + len - 6, CODE_SUFFIX);
30422776Ssteve	    else if (len >= 2 && strcmp(code_file_name + len - 2, ".c") == 0)
30522776Ssteve		strcpy(code_file_name + len - 2, CODE_SUFFIX);
30622776Ssteve	    else
30722776Ssteve		strcpy(code_file_name + len, CODE_SUFFIX);
30822776Ssteve	}
30922776Ssteve	else
31022776Ssteve	    strcpy(code_file_name + len, CODE_SUFFIX);
3111590Srgrimes    }
3121590Srgrimes    else
3131590Srgrimes	code_file_name = output_file_name;
3141590Srgrimes
3151590Srgrimes    if (dflag)
3161590Srgrimes    {
317214961Sobrien	defines_file_name = malloc(len + 7);
3181590Srgrimes	if (defines_file_name == 0)
3191590Srgrimes	    no_space();
3201590Srgrimes	strcpy(defines_file_name, file_prefix);
32122776Ssteve	if (file_prefix == output_file_name)
32222776Ssteve	{
32322776Ssteve#define BISON_DEFINES_SUFFIX  ".h"
32422776Ssteve	    if (len >= 2 && strcmp(defines_file_name + len - 2, ".c") == 0)
32522776Ssteve		strcpy(defines_file_name + len - 2, BISON_DEFINES_SUFFIX);
32622776Ssteve	    else
32722776Ssteve		strcpy(defines_file_name + len, BISON_DEFINES_SUFFIX);
32822776Ssteve	}
32922776Ssteve	else
33022776Ssteve	    strcpy(defines_file_name + len, DEFINES_SUFFIX);
3311590Srgrimes    }
3321590Srgrimes
3331590Srgrimes    if (vflag)
3341590Srgrimes    {
335214961Sobrien	verbose_file_name = malloc(len + 8);
3361590Srgrimes	if (verbose_file_name == 0)
3371590Srgrimes	    no_space();
3381590Srgrimes	strcpy(verbose_file_name, file_prefix);
33922776Ssteve	if (file_prefix == output_file_name)
34022776Ssteve	{
34122776Ssteve	    if (len >= 6 && strcmp(verbose_file_name + len - 6, ".tab.c") == 0)
34222776Ssteve		strcpy(verbose_file_name + len - 6, VERBOSE_SUFFIX);
34322776Ssteve	    else if (len >= 2 && strcmp(verbose_file_name + len - 2, ".c") == 0)
34422776Ssteve		strcpy(verbose_file_name + len - 2, VERBOSE_SUFFIX);
34522776Ssteve	    else
34622776Ssteve		strcpy(verbose_file_name + len, VERBOSE_SUFFIX);
34722776Ssteve	}
34822776Ssteve	else
34922776Ssteve	    strcpy(verbose_file_name + len, VERBOSE_SUFFIX);
3501590Srgrimes    }
3511590Srgrimes}
3521590Srgrimes
3531590Srgrimes
35421622Sstevestatic void
355214959Sobrienopen_files(void)
3561590Srgrimes{
35736790Simp    int fd;
35836790Simp
3591590Srgrimes    create_file_names();
3601590Srgrimes
3611590Srgrimes    if (input_file == 0)
3621590Srgrimes    {
3631590Srgrimes	input_file = fopen(input_file_name, "r");
3641590Srgrimes	if (input_file == 0)
3651590Srgrimes	    open_error(input_file_name);
3661590Srgrimes    }
3671590Srgrimes
36836790Simp    fd = mkstemp(action_file_name);
36936790Simp    if (fd < 0 || (action_file = fdopen(fd, "w")) == NULL) {
37036790Simp        if (fd >= 0)
37136790Simp	    close(fd);
3721590Srgrimes	open_error(action_file_name);
37336790Simp    }
37436790Simp    fd = mkstemp(text_file_name);
37536790Simp    if (fd < 0 || (text_file = fdopen(fd, "w")) == NULL) {
37636790Simp        if (fd >= 0)
37736790Simp	    close(fd);
37836790Simp	open_error(text_file_name);
37936790Simp    }
38036790Simp    fd = mkstemp(union_file_name);
38136790Simp    if (fd < 0 || (union_file = fdopen(fd, "w")) == NULL) {
38236790Simp        if (fd >= 0)
38336790Simp	    close(fd);
38436790Simp	open_error(union_file_name);
38536790Simp    }
3861590Srgrimes
3871590Srgrimes    text_file = fopen(text_file_name, "w");
3881590Srgrimes    if (text_file == 0)
3891590Srgrimes	open_error(text_file_name);
3901590Srgrimes
3911590Srgrimes    if (vflag)
3921590Srgrimes    {
3931590Srgrimes	verbose_file = fopen(verbose_file_name, "w");
3941590Srgrimes	if (verbose_file == 0)
3951590Srgrimes	    open_error(verbose_file_name);
3961590Srgrimes    }
3971590Srgrimes
3981590Srgrimes    if (dflag)
3991590Srgrimes    {
4001590Srgrimes	defines_file = fopen(defines_file_name, "w");
4011590Srgrimes	if (defines_file == 0)
4021590Srgrimes	    open_error(defines_file_name);
4031590Srgrimes	union_file = fopen(union_file_name, "w");
4041590Srgrimes	if (union_file ==  0)
4051590Srgrimes	    open_error(union_file_name);
4061590Srgrimes    }
4071590Srgrimes
4081590Srgrimes    output_file = fopen(output_file_name, "w");
4091590Srgrimes    if (output_file == 0)
4101590Srgrimes	open_error(output_file_name);
4111590Srgrimes
4121590Srgrimes    if (rflag)
4131590Srgrimes    {
4141590Srgrimes	code_file = fopen(code_file_name, "w");
4151590Srgrimes	if (code_file == 0)
4161590Srgrimes	    open_error(code_file_name);
4171590Srgrimes    }
4181590Srgrimes    else
4191590Srgrimes	code_file = output_file;
4201590Srgrimes}
4211590Srgrimes
4221590Srgrimes
4231590Srgrimesint
42493832Sobrienmain(int argc, char *argv[])
4251590Srgrimes{
4261590Srgrimes    set_signals();
4271590Srgrimes    getargs(argc, argv);
4281590Srgrimes    open_files();
4291590Srgrimes    reader();
4301590Srgrimes    lr0();
4311590Srgrimes    lalr();
4321590Srgrimes    make_parser();
4331590Srgrimes    verbose();
4341590Srgrimes    output();
4351590Srgrimes    done(0);
4361590Srgrimes    /*NOTREACHED*/
43721622Ssteve    return (0);
4381590Srgrimes}
439