111d4a34jkim/* $Id: main.c,v 1.60 2017/04/30 20:57:56 Julien.Ramseier Exp $ */
226a93febapt
326a93febapt#include <signal.h>
43c84e00bapt#ifndef _WIN32
526a93febapt#include <unistd.h>		/* for _exit() */
63c84e00bapt#else
73c84e00bapt#include <stdlib.h>		/* for _exit() */
83c84e00bapt#endif
926a93febapt
1026a93febapt#include "defs.h"
1126a93febapt
1295d4c53bapt#ifdef HAVE_MKSTEMP
1395d4c53bapt# define USE_MKSTEMP 1
1495d4c53bapt#elif defined(HAVE_FCNTL_H)
1595d4c53bapt# define USE_MKSTEMP 1
1695d4c53bapt# include <fcntl.h>		/* for open(), O_EXCL, etc. */
1726a93febapt#else
1826a93febapt# define USE_MKSTEMP 0
1926a93febapt#endif
2026a93febapt
2126a93febapt#if USE_MKSTEMP
2226a93febapt#include <sys/types.h>
2326a93febapt#include <sys/stat.h>
2426a93febapt
2526a93febapttypedef struct _my_tmpfiles
2626a93febapt{
2726a93febapt    struct _my_tmpfiles *next;
2826a93febapt    char *name;
2926a93febapt}
3026a93febaptMY_TMPFILES;
3126a93febapt
3226a93febaptstatic MY_TMPFILES *my_tmpfiles;
3326a93febapt#endif /* USE_MKSTEMP */
3426a93febapt
3526a93febaptchar dflag;
3626a93febaptchar gflag;
3726a93febaptchar iflag;
3826a93febaptchar lflag;
3926a93febaptstatic char oflag;
4026a93febaptchar rflag;
4126a93febaptchar sflag;
4226a93febaptchar tflag;
4326a93febaptchar vflag;
4426a93febapt
4526a93febaptconst char *symbol_prefix;
4626a93febaptconst char *myname = "yacc";
4726a93febapt
4826a93febaptint lineno;
4926a93febaptint outline;
5026a93febapt
5126a93febaptstatic char default_file_prefix[] = "y";
5226a93febapt
5326a93febaptstatic char *file_prefix = default_file_prefix;
5426a93febapt
5526a93febaptchar *code_file_name;
56e7d342bjkimchar *input_file_name;
57e7d342bjkimsize_t input_file_name_len = 0;
5826a93febaptchar *defines_file_name;
5926a93febaptchar *externs_file_name;
6026a93febapt
6126a93febaptstatic char *graph_file_name;
6226a93febaptstatic char *output_file_name;
6326a93febaptstatic char *verbose_file_name;
6426a93febapt
6526a93febaptFILE *action_file;	/*  a temp file, used to save actions associated    */
6626a93febapt			/*  with rules until the parser is written          */
6726a93febaptFILE *code_file;	/*  y.code.c (used when the -r option is specified) */
6826a93febaptFILE *defines_file;	/*  y.tab.h                                         */
6926a93febaptFILE *externs_file;	/*  y.tab.i                                         */
7026a93febaptFILE *input_file;	/*  the input file                                  */
7126a93febaptFILE *output_file;	/*  y.tab.c                                         */
7226a93febaptFILE *text_file;	/*  a temp file, used to save text until all        */
7326a93febapt			/*  symbols have been defined                       */
7426a93febaptFILE *union_file;	/*  a temp file, used to save the union             */
7526a93febapt			/*  definition until all symbol have been           */
7626a93febapt			/*  defined                                         */
7726a93febaptFILE *verbose_file;	/*  y.output                                        */
7826a93febaptFILE *graph_file;	/*  y.dot                                           */
7926a93febapt
803c84e00baptValue_t nitems;
813c84e00baptValue_t nrules;
823c84e00baptValue_t nsyms;
833c84e00baptValue_t ntokens;
843c84e00baptValue_t nvars;
8526a93febapt
8626a93febaptValue_t start_symbol;
8726a93febaptchar **symbol_name;
8826a93febaptchar **symbol_pname;
8926a93febaptValue_t *symbol_value;
903c84e00baptValue_t *symbol_prec;
9126a93febaptchar *symbol_assoc;
9226a93febapt
9326a93febaptint pure_parser;
94c2f7afcbaptint token_table;
95fe9f57ajkimint error_verbose;
963c84e00bapt
973c84e00bapt#if defined(YYBTYACC)
983c84e00baptValue_t *symbol_pval;
993c84e00baptchar **symbol_destructor;
1003c84e00baptchar **symbol_type_tag;
1013c84e00baptint locations = 0;	/* default to no position processing */
1023c84e00baptint backtrack = 0;	/* default is no backtracking */
103fe9f57ajkimchar *initial_action = NULL;
1043c84e00bapt#endif
1053c84e00bapt
10626a93febaptint exit_code;
10726a93febapt
10826a93febaptValue_t *ritem;
10926a93febaptValue_t *rlhs;
11026a93febaptValue_t *rrhs;
11126a93febaptValue_t *rprec;
11226a93febaptAssoc_t *rassoc;
11326a93febaptValue_t **derives;
11426a93febaptchar *nullable;
11526a93febapt
11626a93febapt/*
11726a93febapt * Since fclose() is called via the signal handler, it might die.  Don't loop
11826a93febapt * if there is a problem closing a file.
11926a93febapt */
12026a93febapt#define DO_CLOSE(fp) \
12126a93febapt	if (fp != 0) { \
12226a93febapt	    FILE *use = fp; \
12326a93febapt	    fp = 0; \
12426a93febapt	    fclose(use); \
12526a93febapt	}
12626a93febapt
12726a93febaptstatic int got_intr = 0;
12826a93febapt
12926a93febaptvoid
13026a93febaptdone(int k)
13126a93febapt{
13226a93febapt    DO_CLOSE(input_file);
13326a93febapt    DO_CLOSE(output_file);
1343c84e00bapt    if (iflag)
1353c84e00bapt	DO_CLOSE(externs_file);
1363c84e00bapt    if (rflag)
1373c84e00bapt	DO_CLOSE(code_file);
13826a93febapt
13926a93febapt    DO_CLOSE(action_file);
14026a93febapt    DO_CLOSE(defines_file);
14126a93febapt    DO_CLOSE(graph_file);
14226a93febapt    DO_CLOSE(text_file);
14326a93febapt    DO_CLOSE(union_file);
14426a93febapt    DO_CLOSE(verbose_file);
14526a93febapt
14626a93febapt    if (got_intr)
14726a93febapt	_exit(EXIT_FAILURE);
14826a93febapt
14926a93febapt#ifdef NO_LEAKS
15026a93febapt    if (rflag)
15126a93febapt	DO_FREE(code_file_name);
15226a93febapt
15326a93febapt    if (dflag)
15426a93febapt	DO_FREE(defines_file_name);
15526a93febapt
15626a93febapt    if (iflag)
15726a93febapt	DO_FREE(externs_file_name);
15826a93febapt
15926a93febapt    if (oflag)
16026a93febapt	DO_FREE(output_file_name);
16126a93febapt
16226a93febapt    if (vflag)
16326a93febapt	DO_FREE(verbose_file_name);
16426a93febapt
16526a93febapt    if (gflag)
16626a93febapt	DO_FREE(graph_file_name);
16726a93febapt
16826a93febapt    lr0_leaks();
16926a93febapt    lalr_leaks();
17026a93febapt    mkpar_leaks();
17108d24c3bapt    mstring_leaks();
17226a93febapt    output_leaks();
17326a93febapt    reader_leaks();
17426a93febapt#endif
17526a93febapt
17626a93febapt    exit(k);
17726a93febapt}
17826a93febapt
17926a93febaptstatic void
18026a93febaptonintr(int sig GCC_UNUSED)
18126a93febapt{
18226a93febapt    got_intr = 1;
18326a93febapt    done(EXIT_FAILURE);
18426a93febapt}
18526a93febapt
18626a93febaptstatic void
18726a93febaptset_signals(void)
18826a93febapt{
18926a93febapt#ifdef SIGINT
19026a93febapt    if (signal(SIGINT, SIG_IGN) != SIG_IGN)
19126a93febapt	signal(SIGINT, onintr);
19226a93febapt#endif
19326a93febapt#ifdef SIGTERM
19426a93febapt    if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
19526a93febapt	signal(SIGTERM, onintr);
19626a93febapt#endif
19726a93febapt#ifdef SIGHUP
19826a93febapt    if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
19926a93febapt	signal(SIGHUP, onintr);
20026a93febapt#endif
20126a93febapt}
20226a93febapt
20326a93febaptstatic void
20426a93febaptusage(void)
20526a93febapt{
20626a93febapt    static const char *msg[] =
20726a93febapt    {
20826a93febapt	""
20926a93febapt	,"Options:"
21026a93febapt	,"  -b file_prefix        set filename prefix (default \"y.\")"
2113c84e00bapt	,"  -B                    create a backtracking parser"
2123c84e00bapt	,"  -d                    write definitions (" DEFINES_SUFFIX ")"
21326a93febapt	,"  -i                    write interface (y.tab.i)"
21426a93febapt	,"  -g                    write a graphical description"
21526a93febapt	,"  -l                    suppress #line directives"
2163c84e00bapt	,"  -L                    enable position processing, e.g., \"%locations\""
2173c84e00bapt	,"  -o output_file        (default \"" OUTPUT_SUFFIX "\")"
21826a93febapt	,"  -p symbol_prefix      set symbol prefix (default \"yy\")"
21926a93febapt	,"  -P                    create a reentrant parser, e.g., \"%pure-parser\""
22026a93febapt	,"  -r                    produce separate code and table files (y.code.c)"
22126a93febapt	,"  -s                    suppress #define's for quoted names in %token lines"
22226a93febapt	,"  -t                    add debugging support"
22326a93febapt	,"  -v                    write description (y.output)"
22426a93febapt	,"  -V                    show version information and exit"
22526a93febapt    };
22626a93febapt    unsigned n;
22726a93febapt
22826a93febapt    fflush(stdout);
22926a93febapt    fprintf(stderr, "Usage: %s [options] filename\n", myname);
23026a93febapt    for (n = 0; n < sizeof(msg) / sizeof(msg[0]); ++n)
23126a93febapt	fprintf(stderr, "%s\n", msg[n]);
23226a93febapt
23326a93febapt    exit(1);
23426a93febapt}
23526a93febapt
23626a93febaptstatic void
23726a93febaptsetflag(int ch)
23826a93febapt{
23926a93febapt    switch (ch)
24026a93febapt    {
2413c84e00bapt    case 'B':
2423c84e00bapt#if defined(YYBTYACC)
2433c84e00bapt	backtrack = 1;
2443c84e00bapt#else
2453c84e00bapt	unsupported_flag_warning("-B", "reconfigure with --enable-btyacc");
2463c84e00bapt#endif
2473c84e00bapt	break;
2483c84e00bapt
24926a93febapt    case 'd':
25026a93febapt	dflag = 1;
25126a93febapt	break;
25226a93febapt
25326a93febapt    case 'g':
25426a93febapt	gflag = 1;
25526a93febapt	break;
25626a93febapt
25726a93febapt    case 'i':
25826a93febapt	iflag = 1;
25926a93febapt	break;
26026a93febapt
26126a93febapt    case 'l':
26226a93febapt	lflag = 1;
26326a93febapt	break;
26426a93febapt
2653c84e00bapt    case 'L':
2663c84e00bapt#if defined(YYBTYACC)
2673c84e00bapt	locations = 1;
2683c84e00bapt#else
26911d4a34jkim	unsupported_flag_warning("-L", "reconfigure with --enable-btyacc");
2703c84e00bapt#endif
2713c84e00bapt	break;
2723c84e00bapt
27326a93febapt    case 'P':
27426a93febapt	pure_parser = 1;
27526a93febapt	break;
27626a93febapt
27726a93febapt    case 'r':
27826a93febapt	rflag = 1;
27926a93febapt	break;
28026a93febapt
28126a93febapt    case 's':
28226a93febapt	sflag = 1;
28326a93febapt	break;
28426a93febapt
28526a93febapt    case 't':
28626a93febapt	tflag = 1;
28726a93febapt	break;
28826a93febapt
28926a93febapt    case 'v':
29026a93febapt	vflag = 1;
29126a93febapt	break;
29226a93febapt
29326a93febapt    case 'V':
29426a93febapt	printf("%s - %s\n", myname, VERSION);
29526a93febapt	exit(EXIT_SUCCESS);
29626a93febapt
29726a93febapt    case 'y':
29826a93febapt	/* noop for bison compatibility. byacc is already designed to be posix
29926a93febapt	 * yacc compatible. */
30026a93febapt	break;
30126a93febapt
30226a93febapt    default:
30326a93febapt	usage();
30426a93febapt    }
30526a93febapt}
30626a93febapt
30726a93febaptstatic void
30826a93febaptgetargs(int argc, char *argv[])
30926a93febapt{
31026a93febapt    int i;
31126a93febapt    char *s;
31226a93febapt    int ch;
31326a93febapt
31426a93febapt    if (argc > 0)
31526a93febapt	myname = argv[0];
31626a93febapt
31726a93febapt    for (i = 1; i < argc; ++i)
31826a93febapt    {
31926a93febapt	s = argv[i];
32026a93febapt	if (*s != '-')
32126a93febapt	    break;
32226a93febapt	switch (ch = *++s)
32326a93febapt	{
32426a93febapt	case '\0':
32526a93febapt	    input_file = stdin;
32626a93febapt	    if (i + 1 < argc)
32726a93febapt		usage();
32826a93febapt	    return;
32926a93febapt
33026a93febapt	case '-':
33126a93febapt	    ++i;
33226a93febapt	    goto no_more_options;
33326a93febapt
33426a93febapt	case 'b':
33526a93febapt	    if (*++s)
33626a93febapt		file_prefix = s;
33726a93febapt	    else if (++i < argc)
33826a93febapt		file_prefix = argv[i];
33926a93febapt	    else
34026a93febapt		usage();
34126a93febapt	    continue;
34226a93febapt
34326a93febapt	case 'o':
34426a93febapt	    if (*++s)
34526a93febapt		output_file_name = s;
34626a93febapt	    else if (++i < argc)
34726a93febapt		output_file_name = argv[i];
34826a93febapt	    else
34926a93febapt		usage();
35026a93febapt	    continue;
35126a93febapt
35226a93febapt	case 'p':
35326a93febapt	    if (*++s)
35426a93febapt		symbol_prefix = s;
35526a93febapt	    else if (++i < argc)
35626a93febapt		symbol_prefix = argv[i];
35726a93febapt	    else
35826a93febapt		usage();
35926a93febapt	    continue;
36026a93febapt
36126a93febapt	default:
36226a93febapt	    setflag(ch);
36326a93febapt	    break;
36426a93febapt	}
36526a93febapt
36626a93febapt	for (;;)
36726a93febapt	{
36826a93febapt	    switch (ch = *++s)
36926a93febapt	    {
37026a93febapt	    case '\0':
37126a93febapt		goto end_of_option;
37226a93febapt
37326a93febapt	    default:
37426a93febapt		setflag(ch);
37526a93febapt		break;
37626a93febapt	    }
37726a93febapt	}
37826a93febapt      end_of_option:;
37926a93febapt    }
38026a93febapt
38126a93febapt  no_more_options:;
38226a93febapt    if (i + 1 != argc)
38326a93febapt	usage();
384e7d342bjkim    input_file_name_len = strlen(argv[i]);
385e7d342bjkim    input_file_name = TMALLOC(char, input_file_name_len + 1);
386e7d342bjkim    NO_SPACE(input_file_name);
387e7d342bjkim    strcpy(input_file_name, argv[i]);
38826a93febapt}
38926a93febapt
39026a93febaptvoid *
39126a93febaptallocate(size_t n)
39226a93febapt{
39326a93febapt    void *p;
39426a93febapt
39526a93febapt    p = NULL;
39626a93febapt    if (n)
39726a93febapt    {
39826a93febapt	p = CALLOC(1, n);
39926a93febapt	NO_SPACE(p);
40026a93febapt    }
40126a93febapt    return (p);
40226a93febapt}
40326a93febapt
40426a93febapt#define CREATE_FILE_NAME(dest, suffix) \
4053c84e00bapt	dest = alloc_file_name(len, suffix)
4063c84e00bapt
4073c84e00baptstatic char *
4083c84e00baptalloc_file_name(size_t len, const char *suffix)
4093c84e00bapt{
4103c84e00bapt    char *result = TMALLOC(char, len + strlen(suffix) + 1);
4113c84e00bapt    if (result == 0)
4123c84e00bapt	no_space();
4133c84e00bapt    strcpy(result, file_prefix);
4143c84e00bapt    strcpy(result + len, suffix);
4153c84e00bapt    return result;
4163c84e00bapt}
41726a93febapt
41836f7fe3jkimstatic char *
41936f7fe3jkimfind_suffix(char *name, const char *suffix)
42036f7fe3jkim{
42136f7fe3jkim    size_t len = strlen(name);
42236f7fe3jkim    size_t slen = strlen(suffix);
42336f7fe3jkim    if (len >= slen)
42436f7fe3jkim    {
42536f7fe3jkim	name += len - slen;
42636f7fe3jkim	if (strcmp(name, suffix) == 0)
42736f7fe3jkim	    return name;
42836f7fe3jkim    }
42936f7fe3jkim    return NULL;
43036f7fe3jkim}
43136f7fe3jkim
43226a93febaptstatic void
43326a93febaptcreate_file_names(void)
43426a93febapt{
43526a93febapt    size_t len;
43626a93febapt    const char *defines_suffix;
43726a93febapt    const char *externs_suffix;
43836f7fe3jkim    char *suffix;
43926a93febapt
44036f7fe3jkim    suffix = NULL;
44126a93febapt    defines_suffix = DEFINES_SUFFIX;
44226a93febapt    externs_suffix = EXTERNS_SUFFIX;
44326a93febapt
44426a93febapt    /* compute the file_prefix from the user provided output_file_name */
44526a93febapt    if (output_file_name != 0)
44626a93febapt    {
44736f7fe3jkim	if (!(suffix = find_suffix(output_file_name, OUTPUT_SUFFIX))
44836f7fe3jkim	    && (suffix = find_suffix(output_file_name, ".c")))
44926a93febapt	{
45026a93febapt	    defines_suffix = ".h";
45126a93febapt	    externs_suffix = ".i";
45226a93febapt	}
45326a93febapt    }
45426a93febapt
45536f7fe3jkim    if (suffix != NULL)
45626a93febapt    {
45736f7fe3jkim	len = (size_t) (suffix - output_file_name);
45837c437fbapt	file_prefix = TMALLOC(char, len + 1);
45926a93febapt	NO_SPACE(file_prefix);
46026a93febapt	strncpy(file_prefix, output_file_name, len)[len] = 0;
46126a93febapt    }
46226a93febapt    else
46326a93febapt	len = strlen(file_prefix);
46426a93febapt
46526a93febapt    /* if "-o filename" was not given */
46626a93febapt    if (output_file_name == 0)
46726a93febapt    {
46826a93febapt	oflag = 1;
46926a93febapt	CREATE_FILE_NAME(output_file_name, OUTPUT_SUFFIX);
47026a93febapt    }
47126a93febapt
47226a93febapt    if (rflag)
47326a93febapt    {
47426a93febapt	CREATE_FILE_NAME(code_file_name, CODE_SUFFIX);
47526a93febapt    }
47626a93febapt    else
47726a93febapt	code_file_name = output_file_name;
47826a93febapt
47926a93febapt    if (dflag)
48026a93febapt    {
48126a93febapt	CREATE_FILE_NAME(defines_file_name, defines_suffix);
48226a93febapt    }
48326a93febapt
48426a93febapt    if (iflag)
48526a93febapt    {
48626a93febapt	CREATE_FILE_NAME(externs_file_name, externs_suffix);
48726a93febapt    }
48826a93febapt
48926a93febapt    if (vflag)
49026a93febapt    {
49126a93febapt	CREATE_FILE_NAME(verbose_file_name, VERBOSE_SUFFIX);
49226a93febapt    }
49326a93febapt
49426a93febapt    if (gflag)
49526a93febapt    {
49626a93febapt	CREATE_FILE_NAME(graph_file_name, GRAPH_SUFFIX);
49726a93febapt    }
49826a93febapt
49936f7fe3jkim    if (suffix != NULL)
50026a93febapt    {
50126a93febapt	FREE(file_prefix);
50226a93febapt    }
50326a93febapt}
50426a93febapt
50526a93febapt#if USE_MKSTEMP
50626a93febaptstatic void
50726a93febaptclose_tmpfiles(void)
50826a93febapt{
50926a93febapt    while (my_tmpfiles != 0)
51026a93febapt    {
51126a93febapt	MY_TMPFILES *next = my_tmpfiles->next;
51226a93febapt
5133090913bapt	(void)chmod(my_tmpfiles->name, 0644);
5143090913bapt	(void)unlink(my_tmpfiles->name);
51526a93febapt
51626a93febapt	free(my_tmpfiles->name);
51726a93febapt	free(my_tmpfiles);
51826a93febapt
51926a93febapt	my_tmpfiles = next;
52026a93febapt    }
52126a93febapt}
52226a93febapt
52326a93febapt#ifndef HAVE_MKSTEMP
52426a93febaptstatic int
52526a93febaptmy_mkstemp(char *temp)
52626a93febapt{
52726a93febapt    int fd;
52826a93febapt    char *dname;
52926a93febapt    char *fname;
53026a93febapt    char *name;
53126a93febapt
53226a93febapt    /*
53326a93febapt     * Split-up to use tempnam, rather than tmpnam; the latter (like
53426a93febapt     * mkstemp) is unusable on Windows.
53526a93febapt     */
53626a93febapt    if ((fname = strrchr(temp, '/')) != 0)
53726a93febapt    {
53826a93febapt	dname = strdup(temp);
53926a93febapt	dname[++fname - temp] = '\0';
54026a93febapt    }
54126a93febapt    else
54226a93febapt    {
54326a93febapt	dname = 0;
54426a93febapt	fname = temp;
54526a93febapt    }
54626a93febapt    if ((name = tempnam(dname, fname)) != 0)
54726a93febapt    {
54826a93febapt	fd = open(name, O_CREAT | O_EXCL | O_RDWR);
54926a93febapt	strcpy(temp, name);
55026a93febapt    }
55126a93febapt    else
55226a93febapt    {
55326a93febapt	fd = -1;
55426a93febapt    }
55526a93febapt
55626a93febapt    if (dname != 0)
55726a93febapt	free(dname);
55826a93febapt
55926a93febapt    return fd;
56026a93febapt}
56126a93febapt#define mkstemp(s) my_mkstemp(s)
56226a93febapt#endif
56326a93febapt
56426a93febapt#endif
56526a93febapt
56626a93febapt/*
56726a93febapt * tmpfile() should be adequate, except that it may require special privileges
56826a93febapt * to use, e.g., MinGW and Windows 7 where it tries to use the root directory.
56926a93febapt */
57026a93febaptstatic FILE *
57126a93febaptopen_tmpfile(const char *label)
57226a93febapt{
5730ea517cjkim#define MY_FMT "%s/%.*sXXXXXX"
57426a93febapt    FILE *result;
57526a93febapt#if USE_MKSTEMP
57626a93febapt    int fd;
57726a93febapt    const char *tmpdir;
57826a93febapt    char *name;
57926a93febapt    const char *mark;
58026a93febapt
58126a93febapt    if ((tmpdir = getenv("TMPDIR")) == 0 || access(tmpdir, W_OK) != 0)
58226a93febapt    {
58326a93febapt#ifdef P_tmpdir
58426a93febapt	tmpdir = P_tmpdir;
58526a93febapt#else
58626a93febapt	tmpdir = "/tmp";
58726a93febapt#endif
58826a93febapt	if (access(tmpdir, W_OK) != 0)
58926a93febapt	    tmpdir = ".";
59026a93febapt    }
59126a93febapt
5920ea517cjkim    /* The size of the format is guaranteed to be longer than the result from
5930ea517cjkim     * printing empty strings with it; this calculation accounts for the
5940ea517cjkim     * string-lengths as well.
5950ea517cjkim     */
5960ea517cjkim    name = malloc(strlen(tmpdir) + sizeof(MY_FMT) + strlen(label));
59726a93febapt
59826a93febapt    result = 0;
59926a93febapt    if (name != 0)
60026a93febapt    {
60186771febapt	mode_t save_umask = umask(0177);
6023090913bapt
60326a93febapt	if ((mark = strrchr(label, '_')) == 0)
60426a93febapt	    mark = label + strlen(label);
60526a93febapt
6060ea517cjkim	sprintf(name, MY_FMT, tmpdir, (int)(mark - label), label);
60726a93febapt	fd = mkstemp(name);
60826a93febapt	if (fd >= 0)
60926a93febapt	{
61026a93febapt	    result = fdopen(fd, "w+");
61126a93febapt	    if (result != 0)
61226a93febapt	    {
61326a93febapt		MY_TMPFILES *item;
61426a93febapt
61526a93febapt		if (my_tmpfiles == 0)
61626a93febapt		{
61726a93febapt		    atexit(close_tmpfiles);
61826a93febapt		}
61926a93febapt
62026a93febapt		item = NEW(MY_TMPFILES);
62126a93febapt		NO_SPACE(item);
62226a93febapt
62326a93febapt		item->name = name;
62426a93febapt		NO_SPACE(item->name);
62526a93febapt
62626a93febapt		item->next = my_tmpfiles;
62726a93febapt		my_tmpfiles = item;
62826a93febapt	    }
62926a93febapt	}
6303090913bapt	(void)umask(save_umask);
63126a93febapt    }
63226a93febapt#else
63326a93febapt    result = tmpfile();
63426a93febapt#endif
63526a93febapt
63626a93febapt    if (result == 0)
63726a93febapt	open_error(label);
63826a93febapt    return result;
6390ea517cjkim#undef MY_FMT
64026a93febapt}
64126a93febapt
64226a93febaptstatic void
64326a93febaptopen_files(void)
64426a93febapt{
64526a93febapt    create_file_names();
64626a93febapt
64726a93febapt    if (input_file == 0)
64826a93febapt    {
64926a93febapt	input_file = fopen(input_file_name, "r");
65026a93febapt	if (input_file == 0)
65126a93febapt	    open_error(input_file_name);
65226a93febapt    }
65326a93febapt
65426a93febapt    action_file = open_tmpfile("action_file");
65526a93febapt    text_file = open_tmpfile("text_file");
65626a93febapt
65726a93febapt    if (vflag)
65826a93febapt    {
65926a93febapt	verbose_file = fopen(verbose_file_name, "w");
66026a93febapt	if (verbose_file == 0)
66126a93febapt	    open_error(verbose_file_name);
66226a93febapt    }
66326a93febapt
66426a93febapt    if (gflag)
66526a93febapt    {
66626a93febapt	graph_file = fopen(graph_file_name, "w");
66726a93febapt	if (graph_file == 0)
66826a93febapt	    open_error(graph_file_name);
66926a93febapt	fprintf(graph_file, "digraph %s {\n", file_prefix);
67026a93febapt	fprintf(graph_file, "\tedge [fontsize=10];\n");
67126a93febapt	fprintf(graph_file, "\tnode [shape=box,fontsize=10];\n");
67226a93febapt	fprintf(graph_file, "\torientation=landscape;\n");
67326a93febapt	fprintf(graph_file, "\trankdir=LR;\n");
67426a93febapt	fprintf(graph_file, "\t/*\n");
67526a93febapt	fprintf(graph_file, "\tmargin=0.2;\n");
67626a93febapt	fprintf(graph_file, "\tpage=\"8.27,11.69\"; // for A4 printing\n");
67726a93febapt	fprintf(graph_file, "\tratio=auto;\n");
67826a93febapt	fprintf(graph_file, "\t*/\n");
67926a93febapt    }
68026a93febapt
68126a93febapt    if (dflag)
68226a93febapt    {
68326a93febapt	defines_file = fopen(defines_file_name, "w");
68426a93febapt	if (defines_file == 0)
68526a93febapt	    open_error(defines_file_name);
68626a93febapt	union_file = open_tmpfile("union_file");
68726a93febapt    }
68826a93febapt
68926a93febapt    if (iflag)
69026a93febapt    {
69126a93febapt	externs_file = fopen(externs_file_name, "w");
69226a93febapt	if (externs_file == 0)
69326a93febapt	    open_error(externs_file_name);
69426a93febapt    }
69526a93febapt
69626a93febapt    output_file = fopen(output_file_name, "w");
69726a93febapt    if (output_file == 0)
69826a93febapt	open_error(output_file_name);
69926a93febapt
70026a93febapt    if (rflag)
70126a93febapt    {
70226a93febapt	code_file = fopen(code_file_name, "w");
70326a93febapt	if (code_file == 0)
70426a93febapt	    open_error(code_file_name);
70526a93febapt    }
70626a93febapt    else
70726a93febapt	code_file = output_file;
70826a93febapt}
70926a93febapt
71026a93febaptint
71126a93febaptmain(int argc, char *argv[])
71226a93febapt{
71326a93febapt    SRexpect = -1;
71426a93febapt    RRexpect = -1;
71526a93febapt    exit_code = EXIT_SUCCESS;
71626a93febapt
71726a93febapt    set_signals();
71826a93febapt    getargs(argc, argv);
71926a93febapt    open_files();
72026a93febapt    reader();
72126a93febapt    lr0();
72226a93febapt    lalr();
72326a93febapt    make_parser();
72426a93febapt    graph();
72526a93febapt    finalize_closure();
72626a93febapt    verbose();
72726a93febapt    output();
72826a93febapt    done(exit_code);
72926a93febapt    /*NOTREACHED */
73026a93febapt}
731