main.c revision 93831
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>
4487517Simp#ifdef __FBSDID
4587234Smarkm__FBSDID("$FreeBSD: head/usr.bin/yacc/main.c 93831 2002-04-04 22:15:13Z obrien $");
4687517Simp#endif
4787234Smarkm
4893831Sobrien#include <paths.h>
491590Srgrimes#include <signal.h>
5021622Ssteve#include <stdlib.h>
5121622Ssteve#include <string.h>
5221622Ssteve#include <unistd.h>
531590Srgrimes#include "defs.h"
541590Srgrimes
551590Srgrimeschar dflag;
561590Srgrimeschar lflag;
571590Srgrimeschar rflag;
581590Srgrimeschar tflag;
591590Srgrimeschar vflag;
601590Srgrimes
6187171Smarkmconst char *symbol_prefix;
6287171Smarkmconst char *file_prefix = "y";
6387171Smarkmchar temp_form[] = "yacc.XXXXXXXXXXX";
641590Srgrimes
651590Srgrimesint lineno;
661590Srgrimesint outline;
671590Srgrimes
681590Srgrimeschar *action_file_name;
691590Srgrimeschar *code_file_name;
701590Srgrimeschar *defines_file_name;
7187171Smarkmconst char *input_file_name = "";
721590Srgrimeschar *output_file_name;
731590Srgrimeschar *text_file_name;
741590Srgrimeschar *union_file_name;
751590Srgrimeschar *verbose_file_name;
761590Srgrimes
771590SrgrimesFILE *action_file;	/*  a temp file, used to save actions associated    */
781590Srgrimes			/*  with rules until the parser is written	    */
791590SrgrimesFILE *code_file;	/*  y.code.c (used when the -r option is specified) */
801590SrgrimesFILE *defines_file;	/*  y.tab.h					    */
811590SrgrimesFILE *input_file;	/*  the input file				    */
821590SrgrimesFILE *output_file;	/*  y.tab.c					    */
831590SrgrimesFILE *text_file;	/*  a temp file, used to save text until all	    */
841590Srgrimes			/*  symbols have been defined			    */
851590SrgrimesFILE *union_file;	/*  a temp file, used to save the union		    */
861590Srgrimes			/*  definition until all symbol have been	    */
871590Srgrimes			/*  defined					    */
881590SrgrimesFILE *verbose_file;	/*  y.output					    */
891590Srgrimes
901590Srgrimesint nitems;
911590Srgrimesint nrules;
921590Srgrimesint nsyms;
931590Srgrimesint ntokens;
941590Srgrimesint nvars;
951590Srgrimes
961590Srgrimesint   start_symbol;
971590Srgrimeschar  **symbol_name;
981590Srgrimesshort *symbol_value;
991590Srgrimesshort *symbol_prec;
1001590Srgrimeschar  *symbol_assoc;
1011590Srgrimes
1021590Srgrimesshort *ritem;
1031590Srgrimesshort *rlhs;
1041590Srgrimesshort *rrhs;
1051590Srgrimesshort *rprec;
1061590Srgrimeschar  *rassoc;
1071590Srgrimesshort **derives;
1081590Srgrimeschar *nullable;
1091590Srgrimes
11092922Simpstatic void create_file_names(void);
11192922Simpstatic void getargs(int, char **);
11292922Simpstatic void onintr(int);
11392922Simpstatic void open_files(void);
11492922Simpstatic void set_signals(void);
11592922Simpstatic void usage(void);
1161590Srgrimes
11793831Sobrienvolatile sig_atomic_t sigdie;
1181590Srgrimes
11993831Sobrien__dead2 void
1201590Srgrimesdone(k)
1211590Srgrimesint k;
1221590Srgrimes{
1231590Srgrimes    if (action_file) { fclose(action_file); unlink(action_file_name); }
1241590Srgrimes    if (text_file) { fclose(text_file); unlink(text_file_name); }
1251590Srgrimes    if (union_file) { fclose(union_file); unlink(union_file_name); }
12693831Sobrien    if (sigdie) { _exit(k); }
1271590Srgrimes    exit(k);
1281590Srgrimes}
1291590Srgrimes
1301590Srgrimes
13121622Sstevestatic void
1321590Srgrimesonintr(signo)
13387171Smarkm	int signo __unused;
1341590Srgrimes{
13593831Sobrien    sigdie = 1;
1361590Srgrimes    done(1);
1371590Srgrimes}
1381590Srgrimes
1391590Srgrimes
14021622Sstevestatic void
1411590Srgrimesset_signals()
1421590Srgrimes{
1431590Srgrimes#ifdef SIGINT
1441590Srgrimes    if (signal(SIGINT, SIG_IGN) != SIG_IGN)
1451590Srgrimes	signal(SIGINT, onintr);
1461590Srgrimes#endif
1471590Srgrimes#ifdef SIGTERM
1481590Srgrimes    if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
1491590Srgrimes	signal(SIGTERM, onintr);
1501590Srgrimes#endif
1511590Srgrimes#ifdef SIGHUP
1521590Srgrimes    if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
1531590Srgrimes	signal(SIGHUP, onintr);
1541590Srgrimes#endif
1551590Srgrimes}
1561590Srgrimes
1571590Srgrimes
15821622Sstevestatic void
1591590Srgrimesusage()
1601590Srgrimes{
16128856Scharnier    fprintf(stderr, "%s\n%s\n",
16228856Scharnier		"usage: yacc [-dlrtv] [-b file_prefix] [-o output_filename]",
16328856Scharnier		"            [-p symbol_prefix] filename");
1641590Srgrimes    exit(1);
1651590Srgrimes}
1661590Srgrimes
1671590Srgrimes
16821622Sstevestatic void
1691590Srgrimesgetargs(argc, argv)
1701590Srgrimesint argc;
1711590Srgrimeschar *argv[];
1721590Srgrimes{
17387171Smarkm    int i;
17487171Smarkm    char *s;
1751590Srgrimes
1761590Srgrimes    for (i = 1; i < argc; ++i)
1771590Srgrimes    {
1781590Srgrimes	s = argv[i];
1791590Srgrimes	if (*s != '-') break;
1801590Srgrimes	switch (*++s)
1811590Srgrimes	{
1821590Srgrimes	case '\0':
1831590Srgrimes	    input_file = stdin;
1841590Srgrimes	    if (i + 1 < argc) usage();
1851590Srgrimes	    return;
1861590Srgrimes
1871590Srgrimes	case '-':
1881590Srgrimes	    ++i;
1891590Srgrimes	    goto no_more_options;
1901590Srgrimes
1911590Srgrimes	case 'b':
1921590Srgrimes	    if (*++s)
1931590Srgrimes		 file_prefix = s;
1941590Srgrimes	    else if (++i < argc)
1951590Srgrimes		file_prefix = argv[i];
1961590Srgrimes	    else
1971590Srgrimes		usage();
1981590Srgrimes	    continue;
1991590Srgrimes
2001590Srgrimes	case 'd':
2011590Srgrimes	    dflag = 1;
2021590Srgrimes	    break;
2031590Srgrimes
2041590Srgrimes	case 'l':
2051590Srgrimes	    lflag = 1;
2061590Srgrimes	    break;
2071590Srgrimes
20822776Ssteve	case 'o':
20922776Ssteve	    if (*++s)
21022776Ssteve		output_file_name = s;
21122776Ssteve	    else if (++i < argc)
21222776Ssteve		output_file_name = argv[i];
21322776Ssteve	    else
21422776Ssteve		usage();
21522776Ssteve	    continue;
21622776Ssteve
2171590Srgrimes	case 'p':
2181590Srgrimes	    if (*++s)
2191590Srgrimes		symbol_prefix = s;
2201590Srgrimes	    else if (++i < argc)
2211590Srgrimes		symbol_prefix = argv[i];
2221590Srgrimes	    else
2231590Srgrimes		usage();
2241590Srgrimes	    continue;
2251590Srgrimes
2261590Srgrimes	case 'r':
2271590Srgrimes	    rflag = 1;
2281590Srgrimes	    break;
2291590Srgrimes
2301590Srgrimes	case 't':
2311590Srgrimes	    tflag = 1;
2321590Srgrimes	    break;
2331590Srgrimes
2341590Srgrimes	case 'v':
2351590Srgrimes	    vflag = 1;
2361590Srgrimes	    break;
2371590Srgrimes
2381590Srgrimes	default:
2391590Srgrimes	    usage();
2401590Srgrimes	}
2411590Srgrimes
2421590Srgrimes	for (;;)
2431590Srgrimes	{
2441590Srgrimes	    switch (*++s)
2451590Srgrimes	    {
2461590Srgrimes	    case '\0':
2471590Srgrimes		goto end_of_option;
2481590Srgrimes
2491590Srgrimes	    case 'd':
2501590Srgrimes		dflag = 1;
2511590Srgrimes		break;
2521590Srgrimes
2531590Srgrimes	    case 'l':
2541590Srgrimes		lflag = 1;
2551590Srgrimes		break;
2561590Srgrimes
2571590Srgrimes	    case 'r':
2581590Srgrimes		rflag = 1;
2591590Srgrimes		break;
2601590Srgrimes
2611590Srgrimes	    case 't':
2621590Srgrimes		tflag = 1;
2631590Srgrimes		break;
2641590Srgrimes
2651590Srgrimes	    case 'v':
2661590Srgrimes		vflag = 1;
2671590Srgrimes		break;
2681590Srgrimes
2691590Srgrimes	    default:
2701590Srgrimes		usage();
2711590Srgrimes	    }
2721590Srgrimes	}
2731590Srgrimesend_of_option:;
2741590Srgrimes    }
2751590Srgrimes
2761590Srgrimesno_more_options:;
2771590Srgrimes    if (i + 1 != argc) usage();
2781590Srgrimes    input_file_name = argv[i];
2791590Srgrimes}
2801590Srgrimes
2811590Srgrimes
2821590Srgrimeschar *
2831590Srgrimesallocate(n)
2841590Srgrimesunsigned n;
2851590Srgrimes{
28687171Smarkm    char *p;
2871590Srgrimes
2881590Srgrimes    p = NULL;
2891590Srgrimes    if (n)
2901590Srgrimes    {
2911590Srgrimes	p = CALLOC(1, n);
2921590Srgrimes	if (!p) no_space();
2931590Srgrimes    }
2941590Srgrimes    return (p);
2951590Srgrimes}
2961590Srgrimes
2971590Srgrimes
29821622Sstevestatic void
2991590Srgrimescreate_file_names()
3001590Srgrimes{
3011590Srgrimes    int i, len;
30287171Smarkm    const char *tmpdir;
3031590Srgrimes
30493831Sobrien    if (!(tmpdir = getenv("TMPDIR")))
30593831Sobrien	tmpdir = _PATH_TMP;
3061590Srgrimes
3071590Srgrimes    len = strlen(tmpdir);
30893831Sobrien    i = len + strlen(temp_form) + 1;
3091590Srgrimes    if (len && tmpdir[len-1] != '/')
3101590Srgrimes	++i;
3111590Srgrimes
3121590Srgrimes    action_file_name = MALLOC(i);
3131590Srgrimes    if (action_file_name == 0) no_space();
3141590Srgrimes    text_file_name = MALLOC(i);
3151590Srgrimes    if (text_file_name == 0) no_space();
3161590Srgrimes    union_file_name = MALLOC(i);
3171590Srgrimes    if (union_file_name == 0) no_space();
3181590Srgrimes
3191590Srgrimes    strcpy(action_file_name, tmpdir);
3201590Srgrimes    strcpy(text_file_name, tmpdir);
3211590Srgrimes    strcpy(union_file_name, tmpdir);
3221590Srgrimes
3231590Srgrimes    if (len && tmpdir[len - 1] != '/')
3241590Srgrimes    {
3251590Srgrimes	action_file_name[len] = '/';
3261590Srgrimes	text_file_name[len] = '/';
3271590Srgrimes	union_file_name[len] = '/';
3281590Srgrimes	++len;
3291590Srgrimes    }
3301590Srgrimes
3311590Srgrimes    strcpy(action_file_name + len, temp_form);
3321590Srgrimes    strcpy(text_file_name + len, temp_form);
3331590Srgrimes    strcpy(union_file_name + len, temp_form);
3341590Srgrimes
3351590Srgrimes    action_file_name[len + 5] = 'a';
3361590Srgrimes    text_file_name[len + 5] = 't';
3371590Srgrimes    union_file_name[len + 5] = 'u';
3381590Srgrimes
33922776Ssteve    if (output_file_name != 0)
34022776Ssteve    {
34122776Ssteve	file_prefix = output_file_name;
34222776Ssteve	len = strlen(file_prefix);
34322776Ssteve    }
34422776Ssteve    else
34522776Ssteve    {
34622776Ssteve	len = strlen(file_prefix);
34722776Ssteve	output_file_name = MALLOC(len + 7);
34822776Ssteve	if (output_file_name == 0)
34922776Ssteve	    no_space();
35022776Ssteve	strcpy(output_file_name, file_prefix);
35122776Ssteve	strcpy(output_file_name + len, OUTPUT_SUFFIX);
35222776Ssteve    }
3531590Srgrimes
3541590Srgrimes    if (rflag)
3551590Srgrimes    {
3561590Srgrimes	code_file_name = MALLOC(len + 8);
3571590Srgrimes	if (code_file_name == 0)
3581590Srgrimes	    no_space();
3591590Srgrimes	strcpy(code_file_name, file_prefix);
36022776Ssteve	if (file_prefix == output_file_name)
36122776Ssteve	{
36222776Ssteve	    /*
36322776Ssteve	     * XXX ".tab.c" here is OUTPUT_SUFFIX, but since its length is
36422776Ssteve	     * in various magic numbers, don't bother using the macro.
36522776Ssteve	     */
36622776Ssteve	    if (len >= 6 && strcmp(code_file_name + len - 6, ".tab.c") == 0)
36722776Ssteve		strcpy(code_file_name + len - 6, CODE_SUFFIX);
36822776Ssteve	    else if (len >= 2 && strcmp(code_file_name + len - 2, ".c") == 0)
36922776Ssteve		strcpy(code_file_name + len - 2, CODE_SUFFIX);
37022776Ssteve	    else
37122776Ssteve		strcpy(code_file_name + len, CODE_SUFFIX);
37222776Ssteve	}
37322776Ssteve	else
37422776Ssteve	    strcpy(code_file_name + len, CODE_SUFFIX);
3751590Srgrimes    }
3761590Srgrimes    else
3771590Srgrimes	code_file_name = output_file_name;
3781590Srgrimes
3791590Srgrimes    if (dflag)
3801590Srgrimes    {
3811590Srgrimes	defines_file_name = MALLOC(len + 7);
3821590Srgrimes	if (defines_file_name == 0)
3831590Srgrimes	    no_space();
3841590Srgrimes	strcpy(defines_file_name, file_prefix);
38522776Ssteve	if (file_prefix == output_file_name)
38622776Ssteve	{
38722776Ssteve#define BISON_DEFINES_SUFFIX  ".h"
38822776Ssteve	    if (len >= 2 && strcmp(defines_file_name + len - 2, ".c") == 0)
38922776Ssteve		strcpy(defines_file_name + len - 2, BISON_DEFINES_SUFFIX);
39022776Ssteve	    else
39122776Ssteve		strcpy(defines_file_name + len, BISON_DEFINES_SUFFIX);
39222776Ssteve	}
39322776Ssteve	else
39422776Ssteve	    strcpy(defines_file_name + len, DEFINES_SUFFIX);
3951590Srgrimes    }
3961590Srgrimes
3971590Srgrimes    if (vflag)
3981590Srgrimes    {
3991590Srgrimes	verbose_file_name = MALLOC(len + 8);
4001590Srgrimes	if (verbose_file_name == 0)
4011590Srgrimes	    no_space();
4021590Srgrimes	strcpy(verbose_file_name, file_prefix);
40322776Ssteve	if (file_prefix == output_file_name)
40422776Ssteve	{
40522776Ssteve	    if (len >= 6 && strcmp(verbose_file_name + len - 6, ".tab.c") == 0)
40622776Ssteve		strcpy(verbose_file_name + len - 6, VERBOSE_SUFFIX);
40722776Ssteve	    else if (len >= 2 && strcmp(verbose_file_name + len - 2, ".c") == 0)
40822776Ssteve		strcpy(verbose_file_name + len - 2, VERBOSE_SUFFIX);
40922776Ssteve	    else
41022776Ssteve		strcpy(verbose_file_name + len, VERBOSE_SUFFIX);
41122776Ssteve	}
41222776Ssteve	else
41322776Ssteve	    strcpy(verbose_file_name + len, VERBOSE_SUFFIX);
4141590Srgrimes    }
4151590Srgrimes}
4161590Srgrimes
4171590Srgrimes
41821622Sstevestatic void
4191590Srgrimesopen_files()
4201590Srgrimes{
42136790Simp    int fd;
42236790Simp
4231590Srgrimes    create_file_names();
4241590Srgrimes
4251590Srgrimes    if (input_file == 0)
4261590Srgrimes    {
4271590Srgrimes	input_file = fopen(input_file_name, "r");
4281590Srgrimes	if (input_file == 0)
4291590Srgrimes	    open_error(input_file_name);
4301590Srgrimes    }
4311590Srgrimes
43236790Simp    fd = mkstemp(action_file_name);
43336790Simp    if (fd < 0 || (action_file = fdopen(fd, "w")) == NULL) {
43436790Simp        if (fd >= 0)
43536790Simp	    close(fd);
4361590Srgrimes	open_error(action_file_name);
43736790Simp    }
43836790Simp    fd = mkstemp(text_file_name);
43936790Simp    if (fd < 0 || (text_file = fdopen(fd, "w")) == NULL) {
44036790Simp        if (fd >= 0)
44136790Simp	    close(fd);
44236790Simp	open_error(text_file_name);
44336790Simp    }
44436790Simp    fd = mkstemp(union_file_name);
44536790Simp    if (fd < 0 || (union_file = fdopen(fd, "w")) == NULL) {
44636790Simp        if (fd >= 0)
44736790Simp	    close(fd);
44836790Simp	open_error(union_file_name);
44936790Simp    }
4501590Srgrimes
4511590Srgrimes    text_file = fopen(text_file_name, "w");
4521590Srgrimes    if (text_file == 0)
4531590Srgrimes	open_error(text_file_name);
4541590Srgrimes
4551590Srgrimes    if (vflag)
4561590Srgrimes    {
4571590Srgrimes	verbose_file = fopen(verbose_file_name, "w");
4581590Srgrimes	if (verbose_file == 0)
4591590Srgrimes	    open_error(verbose_file_name);
4601590Srgrimes    }
4611590Srgrimes
4621590Srgrimes    if (dflag)
4631590Srgrimes    {
4641590Srgrimes	defines_file = fopen(defines_file_name, "w");
4651590Srgrimes	if (defines_file == 0)
4661590Srgrimes	    open_error(defines_file_name);
4671590Srgrimes	union_file = fopen(union_file_name, "w");
4681590Srgrimes	if (union_file ==  0)
4691590Srgrimes	    open_error(union_file_name);
4701590Srgrimes    }
4711590Srgrimes
4721590Srgrimes    output_file = fopen(output_file_name, "w");
4731590Srgrimes    if (output_file == 0)
4741590Srgrimes	open_error(output_file_name);
4751590Srgrimes
4761590Srgrimes    if (rflag)
4771590Srgrimes    {
4781590Srgrimes	code_file = fopen(code_file_name, "w");
4791590Srgrimes	if (code_file == 0)
4801590Srgrimes	    open_error(code_file_name);
4811590Srgrimes    }
4821590Srgrimes    else
4831590Srgrimes	code_file = output_file;
4841590Srgrimes}
4851590Srgrimes
4861590Srgrimes
4871590Srgrimesint
4881590Srgrimesmain(argc, argv)
4891590Srgrimesint argc;
4901590Srgrimeschar *argv[];
4911590Srgrimes{
4921590Srgrimes    set_signals();
4931590Srgrimes    getargs(argc, argv);
4941590Srgrimes    open_files();
4951590Srgrimes    reader();
4961590Srgrimes    lr0();
4971590Srgrimes    lalr();
4981590Srgrimes    make_parser();
4991590Srgrimes    verbose();
5001590Srgrimes    output();
5011590Srgrimes    done(0);
5021590Srgrimes    /*NOTREACHED*/
50321622Ssteve    return (0);
5041590Srgrimes}
505