main.c revision 272769
1272769Sbapt/* $Id: main.c,v 1.54 2014/10/06 22:40:07 tom Exp $ */
2234949Sbapt
3234949Sbapt#include <signal.h>
4264803Sbapt#ifndef _WIN32
5234949Sbapt#include <unistd.h>		/* for _exit() */
6264803Sbapt#else
7264803Sbapt#include <stdlib.h>		/* for _exit() */
8264803Sbapt#endif
9234949Sbapt
10234949Sbapt#include "defs.h"
11234949Sbapt
12251143Sbapt#ifdef HAVE_MKSTEMP
13251143Sbapt# define USE_MKSTEMP 1
14251143Sbapt#elif defined(HAVE_FCNTL_H)
15251143Sbapt# define USE_MKSTEMP 1
16251143Sbapt# include <fcntl.h>		/* for open(), O_EXCL, etc. */
17234949Sbapt#else
18234949Sbapt# define USE_MKSTEMP 0
19234949Sbapt#endif
20234949Sbapt
21234949Sbapt#if USE_MKSTEMP
22234949Sbapt#include <sys/types.h>
23234949Sbapt#include <sys/stat.h>
24234949Sbapt
25234949Sbapttypedef struct _my_tmpfiles
26234949Sbapt{
27234949Sbapt    struct _my_tmpfiles *next;
28234949Sbapt    char *name;
29234949Sbapt}
30234949SbaptMY_TMPFILES;
31234949Sbapt
32234949Sbaptstatic MY_TMPFILES *my_tmpfiles;
33234949Sbapt#endif /* USE_MKSTEMP */
34234949Sbapt
35234949Sbaptchar dflag;
36234949Sbaptchar gflag;
37234949Sbaptchar iflag;
38234949Sbaptchar lflag;
39234949Sbaptstatic char oflag;
40234949Sbaptchar rflag;
41234949Sbaptchar sflag;
42234949Sbaptchar tflag;
43234949Sbaptchar vflag;
44234949Sbapt
45234949Sbaptconst char *symbol_prefix;
46234949Sbaptconst char *myname = "yacc";
47234949Sbapt
48234949Sbaptint lineno;
49234949Sbaptint outline;
50234949Sbapt
51234949Sbaptstatic char empty_string[] = "";
52234949Sbaptstatic char default_file_prefix[] = "y";
53234949Sbapt
54234949Sbaptstatic char *file_prefix = default_file_prefix;
55234949Sbapt
56234949Sbaptchar *code_file_name;
57234949Sbaptchar *input_file_name = empty_string;
58234949Sbaptchar *defines_file_name;
59234949Sbaptchar *externs_file_name;
60234949Sbapt
61234949Sbaptstatic char *graph_file_name;
62234949Sbaptstatic char *output_file_name;
63234949Sbaptstatic char *verbose_file_name;
64234949Sbapt
65234949SbaptFILE *action_file;	/*  a temp file, used to save actions associated    */
66234949Sbapt			/*  with rules until the parser is written          */
67234949SbaptFILE *code_file;	/*  y.code.c (used when the -r option is specified) */
68234949SbaptFILE *defines_file;	/*  y.tab.h                                         */
69234949SbaptFILE *externs_file;	/*  y.tab.i                                         */
70234949SbaptFILE *input_file;	/*  the input file                                  */
71234949SbaptFILE *output_file;	/*  y.tab.c                                         */
72234949SbaptFILE *text_file;	/*  a temp file, used to save text until all        */
73234949Sbapt			/*  symbols have been defined                       */
74234949SbaptFILE *union_file;	/*  a temp file, used to save the union             */
75234949Sbapt			/*  definition until all symbol have been           */
76234949Sbapt			/*  defined                                         */
77234949SbaptFILE *verbose_file;	/*  y.output                                        */
78234949SbaptFILE *graph_file;	/*  y.dot                                           */
79234949Sbapt
80264803SbaptValue_t nitems;
81264803SbaptValue_t nrules;
82264803SbaptValue_t nsyms;
83264803SbaptValue_t ntokens;
84264803SbaptValue_t nvars;
85234949Sbapt
86234949SbaptValue_t start_symbol;
87234949Sbaptchar **symbol_name;
88234949Sbaptchar **symbol_pname;
89234949SbaptValue_t *symbol_value;
90264803SbaptValue_t *symbol_prec;
91234949Sbaptchar *symbol_assoc;
92234949Sbapt
93234949Sbaptint pure_parser;
94260445Sbaptint token_table;
95264803Sbapt
96264803Sbapt#if defined(YYBTYACC)
97264803SbaptValue_t *symbol_pval;
98264803Sbaptchar **symbol_destructor;
99264803Sbaptchar **symbol_type_tag;
100264803Sbaptint locations = 0;	/* default to no position processing */
101264803Sbaptint backtrack = 0;	/* default is no backtracking */
102264803Sbapt#endif
103264803Sbapt
104234949Sbaptint exit_code;
105234949Sbapt
106234949SbaptValue_t *ritem;
107234949SbaptValue_t *rlhs;
108234949SbaptValue_t *rrhs;
109234949SbaptValue_t *rprec;
110234949SbaptAssoc_t *rassoc;
111234949SbaptValue_t **derives;
112234949Sbaptchar *nullable;
113234949Sbapt
114234949Sbapt/*
115234949Sbapt * Since fclose() is called via the signal handler, it might die.  Don't loop
116234949Sbapt * if there is a problem closing a file.
117234949Sbapt */
118234949Sbapt#define DO_CLOSE(fp) \
119234949Sbapt	if (fp != 0) { \
120234949Sbapt	    FILE *use = fp; \
121234949Sbapt	    fp = 0; \
122234949Sbapt	    fclose(use); \
123234949Sbapt	}
124234949Sbapt
125234949Sbaptstatic int got_intr = 0;
126234949Sbapt
127234949Sbaptvoid
128234949Sbaptdone(int k)
129234949Sbapt{
130234949Sbapt    DO_CLOSE(input_file);
131234949Sbapt    DO_CLOSE(output_file);
132264803Sbapt    if (iflag)
133264803Sbapt	DO_CLOSE(externs_file);
134264803Sbapt    if (rflag)
135264803Sbapt	DO_CLOSE(code_file);
136234949Sbapt
137234949Sbapt    DO_CLOSE(action_file);
138234949Sbapt    DO_CLOSE(defines_file);
139234949Sbapt    DO_CLOSE(graph_file);
140234949Sbapt    DO_CLOSE(text_file);
141234949Sbapt    DO_CLOSE(union_file);
142234949Sbapt    DO_CLOSE(verbose_file);
143234949Sbapt
144234949Sbapt    if (got_intr)
145234949Sbapt	_exit(EXIT_FAILURE);
146234949Sbapt
147234949Sbapt#ifdef NO_LEAKS
148234949Sbapt    if (rflag)
149234949Sbapt	DO_FREE(code_file_name);
150234949Sbapt
151234949Sbapt    if (dflag)
152234949Sbapt	DO_FREE(defines_file_name);
153234949Sbapt
154234949Sbapt    if (iflag)
155234949Sbapt	DO_FREE(externs_file_name);
156234949Sbapt
157234949Sbapt    if (oflag)
158234949Sbapt	DO_FREE(output_file_name);
159234949Sbapt
160234949Sbapt    if (vflag)
161234949Sbapt	DO_FREE(verbose_file_name);
162234949Sbapt
163234949Sbapt    if (gflag)
164234949Sbapt	DO_FREE(graph_file_name);
165234949Sbapt
166234949Sbapt    lr0_leaks();
167234949Sbapt    lalr_leaks();
168234949Sbapt    mkpar_leaks();
169266639Sbapt    mstring_leaks();
170234949Sbapt    output_leaks();
171234949Sbapt    reader_leaks();
172234949Sbapt#endif
173234949Sbapt
174234949Sbapt    exit(k);
175234949Sbapt}
176234949Sbapt
177234949Sbaptstatic void
178240517Sbaptonintr(int sig GCC_UNUSED)
179234949Sbapt{
180234949Sbapt    got_intr = 1;
181234949Sbapt    done(EXIT_FAILURE);
182234949Sbapt}
183234949Sbapt
184234949Sbaptstatic void
185234949Sbaptset_signals(void)
186234949Sbapt{
187234949Sbapt#ifdef SIGINT
188234949Sbapt    if (signal(SIGINT, SIG_IGN) != SIG_IGN)
189234949Sbapt	signal(SIGINT, onintr);
190234949Sbapt#endif
191234949Sbapt#ifdef SIGTERM
192234949Sbapt    if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
193234949Sbapt	signal(SIGTERM, onintr);
194234949Sbapt#endif
195234949Sbapt#ifdef SIGHUP
196234949Sbapt    if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
197234949Sbapt	signal(SIGHUP, onintr);
198234949Sbapt#endif
199234949Sbapt}
200234949Sbapt
201234949Sbaptstatic void
202234949Sbaptusage(void)
203234949Sbapt{
204234949Sbapt    static const char *msg[] =
205234949Sbapt    {
206234949Sbapt	""
207234949Sbapt	,"Options:"
208234949Sbapt	,"  -b file_prefix        set filename prefix (default \"y.\")"
209264803Sbapt	,"  -B                    create a backtracking parser"
210264803Sbapt	,"  -d                    write definitions (" DEFINES_SUFFIX ")"
211234949Sbapt	,"  -i                    write interface (y.tab.i)"
212234949Sbapt	,"  -g                    write a graphical description"
213234949Sbapt	,"  -l                    suppress #line directives"
214264803Sbapt	,"  -L                    enable position processing, e.g., \"%locations\""
215264803Sbapt	,"  -o output_file        (default \"" OUTPUT_SUFFIX "\")"
216234949Sbapt	,"  -p symbol_prefix      set symbol prefix (default \"yy\")"
217234949Sbapt	,"  -P                    create a reentrant parser, e.g., \"%pure-parser\""
218234949Sbapt	,"  -r                    produce separate code and table files (y.code.c)"
219234949Sbapt	,"  -s                    suppress #define's for quoted names in %token lines"
220234949Sbapt	,"  -t                    add debugging support"
221234949Sbapt	,"  -v                    write description (y.output)"
222234949Sbapt	,"  -V                    show version information and exit"
223234949Sbapt    };
224234949Sbapt    unsigned n;
225234949Sbapt
226234949Sbapt    fflush(stdout);
227234949Sbapt    fprintf(stderr, "Usage: %s [options] filename\n", myname);
228234949Sbapt    for (n = 0; n < sizeof(msg) / sizeof(msg[0]); ++n)
229234949Sbapt	fprintf(stderr, "%s\n", msg[n]);
230234949Sbapt
231234949Sbapt    exit(1);
232234949Sbapt}
233234949Sbapt
234234949Sbaptstatic void
235234949Sbaptsetflag(int ch)
236234949Sbapt{
237234949Sbapt    switch (ch)
238234949Sbapt    {
239264803Sbapt    case 'B':
240264803Sbapt#if defined(YYBTYACC)
241264803Sbapt	backtrack = 1;
242264803Sbapt#else
243264803Sbapt	unsupported_flag_warning("-B", "reconfigure with --enable-btyacc");
244264803Sbapt#endif
245264803Sbapt	break;
246264803Sbapt
247234949Sbapt    case 'd':
248234949Sbapt	dflag = 1;
249234949Sbapt	break;
250234949Sbapt
251234949Sbapt    case 'g':
252234949Sbapt	gflag = 1;
253234949Sbapt	break;
254234949Sbapt
255234949Sbapt    case 'i':
256234949Sbapt	iflag = 1;
257234949Sbapt	break;
258234949Sbapt
259234949Sbapt    case 'l':
260234949Sbapt	lflag = 1;
261234949Sbapt	break;
262234949Sbapt
263264803Sbapt    case 'L':
264264803Sbapt#if defined(YYBTYACC)
265264803Sbapt	locations = 1;
266264803Sbapt#else
267264803Sbapt	unsupported_flag_warning("-B", "reconfigure with --enable-btyacc");
268264803Sbapt#endif
269264803Sbapt	break;
270264803Sbapt
271234949Sbapt    case 'P':
272234949Sbapt	pure_parser = 1;
273234949Sbapt	break;
274234949Sbapt
275234949Sbapt    case 'r':
276234949Sbapt	rflag = 1;
277234949Sbapt	break;
278234949Sbapt
279234949Sbapt    case 's':
280234949Sbapt	sflag = 1;
281234949Sbapt	break;
282234949Sbapt
283234949Sbapt    case 't':
284234949Sbapt	tflag = 1;
285234949Sbapt	break;
286234949Sbapt
287234949Sbapt    case 'v':
288234949Sbapt	vflag = 1;
289234949Sbapt	break;
290234949Sbapt
291234949Sbapt    case 'V':
292234949Sbapt	printf("%s - %s\n", myname, VERSION);
293234949Sbapt	exit(EXIT_SUCCESS);
294234949Sbapt
295234949Sbapt    case 'y':
296234949Sbapt	/* noop for bison compatibility. byacc is already designed to be posix
297234949Sbapt	 * yacc compatible. */
298234949Sbapt	break;
299234949Sbapt
300234949Sbapt    default:
301234949Sbapt	usage();
302234949Sbapt    }
303234949Sbapt}
304234949Sbapt
305234949Sbaptstatic void
306234949Sbaptgetargs(int argc, char *argv[])
307234949Sbapt{
308234949Sbapt    int i;
309234949Sbapt    char *s;
310234949Sbapt    int ch;
311234949Sbapt
312234949Sbapt    if (argc > 0)
313234949Sbapt	myname = argv[0];
314234949Sbapt
315234949Sbapt    for (i = 1; i < argc; ++i)
316234949Sbapt    {
317234949Sbapt	s = argv[i];
318234949Sbapt	if (*s != '-')
319234949Sbapt	    break;
320234949Sbapt	switch (ch = *++s)
321234949Sbapt	{
322234949Sbapt	case '\0':
323234949Sbapt	    input_file = stdin;
324234949Sbapt	    if (i + 1 < argc)
325234949Sbapt		usage();
326234949Sbapt	    return;
327234949Sbapt
328234949Sbapt	case '-':
329234949Sbapt	    ++i;
330234949Sbapt	    goto no_more_options;
331234949Sbapt
332234949Sbapt	case 'b':
333234949Sbapt	    if (*++s)
334234949Sbapt		file_prefix = s;
335234949Sbapt	    else if (++i < argc)
336234949Sbapt		file_prefix = argv[i];
337234949Sbapt	    else
338234949Sbapt		usage();
339234949Sbapt	    continue;
340234949Sbapt
341234949Sbapt	case 'o':
342234949Sbapt	    if (*++s)
343234949Sbapt		output_file_name = s;
344234949Sbapt	    else if (++i < argc)
345234949Sbapt		output_file_name = argv[i];
346234949Sbapt	    else
347234949Sbapt		usage();
348234949Sbapt	    continue;
349234949Sbapt
350234949Sbapt	case 'p':
351234949Sbapt	    if (*++s)
352234949Sbapt		symbol_prefix = s;
353234949Sbapt	    else if (++i < argc)
354234949Sbapt		symbol_prefix = argv[i];
355234949Sbapt	    else
356234949Sbapt		usage();
357234949Sbapt	    continue;
358234949Sbapt
359234949Sbapt	default:
360234949Sbapt	    setflag(ch);
361234949Sbapt	    break;
362234949Sbapt	}
363234949Sbapt
364234949Sbapt	for (;;)
365234949Sbapt	{
366234949Sbapt	    switch (ch = *++s)
367234949Sbapt	    {
368234949Sbapt	    case '\0':
369234949Sbapt		goto end_of_option;
370234949Sbapt
371234949Sbapt	    default:
372234949Sbapt		setflag(ch);
373234949Sbapt		break;
374234949Sbapt	    }
375234949Sbapt	}
376234949Sbapt      end_of_option:;
377234949Sbapt    }
378234949Sbapt
379234949Sbapt  no_more_options:;
380234949Sbapt    if (i + 1 != argc)
381234949Sbapt	usage();
382234949Sbapt    input_file_name = argv[i];
383234949Sbapt}
384234949Sbapt
385234949Sbaptvoid *
386234949Sbaptallocate(size_t n)
387234949Sbapt{
388234949Sbapt    void *p;
389234949Sbapt
390234949Sbapt    p = NULL;
391234949Sbapt    if (n)
392234949Sbapt    {
393234949Sbapt	p = CALLOC(1, n);
394234949Sbapt	NO_SPACE(p);
395234949Sbapt    }
396234949Sbapt    return (p);
397234949Sbapt}
398234949Sbapt
399234949Sbapt#define CREATE_FILE_NAME(dest, suffix) \
400264803Sbapt	dest = alloc_file_name(len, suffix)
401234949Sbapt
402264803Sbaptstatic char *
403264803Sbaptalloc_file_name(size_t len, const char *suffix)
404264803Sbapt{
405264803Sbapt    char *result = TMALLOC(char, len + strlen(suffix) + 1);
406264803Sbapt    if (result == 0)
407264803Sbapt	no_space();
408264803Sbapt    strcpy(result, file_prefix);
409264803Sbapt    strcpy(result + len, suffix);
410264803Sbapt    return result;
411264803Sbapt}
412264803Sbapt
413234949Sbaptstatic void
414234949Sbaptcreate_file_names(void)
415234949Sbapt{
416234949Sbapt    size_t len;
417234949Sbapt    const char *defines_suffix;
418234949Sbapt    const char *externs_suffix;
419234949Sbapt    char *prefix;
420234949Sbapt
421234949Sbapt    prefix = NULL;
422234949Sbapt    defines_suffix = DEFINES_SUFFIX;
423234949Sbapt    externs_suffix = EXTERNS_SUFFIX;
424234949Sbapt
425234949Sbapt    /* compute the file_prefix from the user provided output_file_name */
426234949Sbapt    if (output_file_name != 0)
427234949Sbapt    {
428264803Sbapt	if (!(prefix = strstr(output_file_name, OUTPUT_SUFFIX))
429234949Sbapt	    && (prefix = strstr(output_file_name, ".c")))
430234949Sbapt	{
431234949Sbapt	    defines_suffix = ".h";
432234949Sbapt	    externs_suffix = ".i";
433234949Sbapt	}
434234949Sbapt    }
435234949Sbapt
436234949Sbapt    if (prefix != NULL)
437234949Sbapt    {
438234949Sbapt	len = (size_t) (prefix - output_file_name);
439240517Sbapt	file_prefix = TMALLOC(char, len + 1);
440234949Sbapt	NO_SPACE(file_prefix);
441234949Sbapt	strncpy(file_prefix, output_file_name, len)[len] = 0;
442234949Sbapt    }
443234949Sbapt    else
444234949Sbapt	len = strlen(file_prefix);
445234949Sbapt
446234949Sbapt    /* if "-o filename" was not given */
447234949Sbapt    if (output_file_name == 0)
448234949Sbapt    {
449234949Sbapt	oflag = 1;
450234949Sbapt	CREATE_FILE_NAME(output_file_name, OUTPUT_SUFFIX);
451234949Sbapt    }
452234949Sbapt
453234949Sbapt    if (rflag)
454234949Sbapt    {
455234949Sbapt	CREATE_FILE_NAME(code_file_name, CODE_SUFFIX);
456234949Sbapt    }
457234949Sbapt    else
458234949Sbapt	code_file_name = output_file_name;
459234949Sbapt
460234949Sbapt    if (dflag)
461234949Sbapt    {
462234949Sbapt	CREATE_FILE_NAME(defines_file_name, defines_suffix);
463234949Sbapt    }
464234949Sbapt
465234949Sbapt    if (iflag)
466234949Sbapt    {
467234949Sbapt	CREATE_FILE_NAME(externs_file_name, externs_suffix);
468234949Sbapt    }
469234949Sbapt
470234949Sbapt    if (vflag)
471234949Sbapt    {
472234949Sbapt	CREATE_FILE_NAME(verbose_file_name, VERBOSE_SUFFIX);
473234949Sbapt    }
474234949Sbapt
475234949Sbapt    if (gflag)
476234949Sbapt    {
477234949Sbapt	CREATE_FILE_NAME(graph_file_name, GRAPH_SUFFIX);
478234949Sbapt    }
479234949Sbapt
480234949Sbapt    if (prefix != NULL)
481234949Sbapt    {
482234949Sbapt	FREE(file_prefix);
483234949Sbapt    }
484234949Sbapt}
485234949Sbapt
486234949Sbapt#if USE_MKSTEMP
487234949Sbaptstatic void
488234949Sbaptclose_tmpfiles(void)
489234949Sbapt{
490234949Sbapt    while (my_tmpfiles != 0)
491234949Sbapt    {
492234949Sbapt	MY_TMPFILES *next = my_tmpfiles->next;
493234949Sbapt
494272655Sbapt	(void)chmod(my_tmpfiles->name, 0644);
495272655Sbapt	(void)unlink(my_tmpfiles->name);
496234949Sbapt
497234949Sbapt	free(my_tmpfiles->name);
498234949Sbapt	free(my_tmpfiles);
499234949Sbapt
500234949Sbapt	my_tmpfiles = next;
501234949Sbapt    }
502234949Sbapt}
503234949Sbapt
504234949Sbapt#ifndef HAVE_MKSTEMP
505234949Sbaptstatic int
506234949Sbaptmy_mkstemp(char *temp)
507234949Sbapt{
508234949Sbapt    int fd;
509234949Sbapt    char *dname;
510234949Sbapt    char *fname;
511234949Sbapt    char *name;
512234949Sbapt
513234949Sbapt    /*
514234949Sbapt     * Split-up to use tempnam, rather than tmpnam; the latter (like
515234949Sbapt     * mkstemp) is unusable on Windows.
516234949Sbapt     */
517234949Sbapt    if ((fname = strrchr(temp, '/')) != 0)
518234949Sbapt    {
519234949Sbapt	dname = strdup(temp);
520234949Sbapt	dname[++fname - temp] = '\0';
521234949Sbapt    }
522234949Sbapt    else
523234949Sbapt    {
524234949Sbapt	dname = 0;
525234949Sbapt	fname = temp;
526234949Sbapt    }
527234949Sbapt    if ((name = tempnam(dname, fname)) != 0)
528234949Sbapt    {
529234949Sbapt	fd = open(name, O_CREAT | O_EXCL | O_RDWR);
530234949Sbapt	strcpy(temp, name);
531234949Sbapt    }
532234949Sbapt    else
533234949Sbapt    {
534234949Sbapt	fd = -1;
535234949Sbapt    }
536234949Sbapt
537234949Sbapt    if (dname != 0)
538234949Sbapt	free(dname);
539234949Sbapt
540234949Sbapt    return fd;
541234949Sbapt}
542234949Sbapt#define mkstemp(s) my_mkstemp(s)
543234949Sbapt#endif
544234949Sbapt
545234949Sbapt#endif
546234949Sbapt
547234949Sbapt/*
548234949Sbapt * tmpfile() should be adequate, except that it may require special privileges
549234949Sbapt * to use, e.g., MinGW and Windows 7 where it tries to use the root directory.
550234949Sbapt */
551234949Sbaptstatic FILE *
552234949Sbaptopen_tmpfile(const char *label)
553234949Sbapt{
554234949Sbapt    FILE *result;
555234949Sbapt#if USE_MKSTEMP
556234949Sbapt    int fd;
557234949Sbapt    const char *tmpdir;
558234949Sbapt    char *name;
559234949Sbapt    const char *mark;
560234949Sbapt
561234949Sbapt    if ((tmpdir = getenv("TMPDIR")) == 0 || access(tmpdir, W_OK) != 0)
562234949Sbapt    {
563234949Sbapt#ifdef P_tmpdir
564234949Sbapt	tmpdir = P_tmpdir;
565234949Sbapt#else
566234949Sbapt	tmpdir = "/tmp";
567234949Sbapt#endif
568234949Sbapt	if (access(tmpdir, W_OK) != 0)
569234949Sbapt	    tmpdir = ".";
570234949Sbapt    }
571234949Sbapt
572234949Sbapt    name = malloc(strlen(tmpdir) + 10 + strlen(label));
573234949Sbapt
574234949Sbapt    result = 0;
575234949Sbapt    if (name != 0)
576234949Sbapt    {
577272769Sbapt	mode_t save_umask = umask(0177);
578272655Sbapt
579234949Sbapt	if ((mark = strrchr(label, '_')) == 0)
580234949Sbapt	    mark = label + strlen(label);
581234949Sbapt
582234949Sbapt	sprintf(name, "%s/%.*sXXXXXX", tmpdir, (int)(mark - label), label);
583234949Sbapt	fd = mkstemp(name);
584234949Sbapt	if (fd >= 0)
585234949Sbapt	{
586234949Sbapt	    result = fdopen(fd, "w+");
587234949Sbapt	    if (result != 0)
588234949Sbapt	    {
589234949Sbapt		MY_TMPFILES *item;
590234949Sbapt
591234949Sbapt		if (my_tmpfiles == 0)
592234949Sbapt		{
593234949Sbapt		    atexit(close_tmpfiles);
594234949Sbapt		}
595234949Sbapt
596234949Sbapt		item = NEW(MY_TMPFILES);
597234949Sbapt		NO_SPACE(item);
598234949Sbapt
599234949Sbapt		item->name = name;
600234949Sbapt		NO_SPACE(item->name);
601234949Sbapt
602234949Sbapt		item->next = my_tmpfiles;
603234949Sbapt		my_tmpfiles = item;
604234949Sbapt	    }
605234949Sbapt	}
606272655Sbapt	(void)umask(save_umask);
607234949Sbapt    }
608234949Sbapt#else
609234949Sbapt    result = tmpfile();
610234949Sbapt#endif
611234949Sbapt
612234949Sbapt    if (result == 0)
613234949Sbapt	open_error(label);
614234949Sbapt    return result;
615234949Sbapt}
616234949Sbapt
617234949Sbaptstatic void
618234949Sbaptopen_files(void)
619234949Sbapt{
620234949Sbapt    create_file_names();
621234949Sbapt
622234949Sbapt    if (input_file == 0)
623234949Sbapt    {
624234949Sbapt	input_file = fopen(input_file_name, "r");
625234949Sbapt	if (input_file == 0)
626234949Sbapt	    open_error(input_file_name);
627234949Sbapt    }
628234949Sbapt
629234949Sbapt    action_file = open_tmpfile("action_file");
630234949Sbapt    text_file = open_tmpfile("text_file");
631234949Sbapt
632234949Sbapt    if (vflag)
633234949Sbapt    {
634234949Sbapt	verbose_file = fopen(verbose_file_name, "w");
635234949Sbapt	if (verbose_file == 0)
636234949Sbapt	    open_error(verbose_file_name);
637234949Sbapt    }
638234949Sbapt
639234949Sbapt    if (gflag)
640234949Sbapt    {
641234949Sbapt	graph_file = fopen(graph_file_name, "w");
642234949Sbapt	if (graph_file == 0)
643234949Sbapt	    open_error(graph_file_name);
644234949Sbapt	fprintf(graph_file, "digraph %s {\n", file_prefix);
645234949Sbapt	fprintf(graph_file, "\tedge [fontsize=10];\n");
646234949Sbapt	fprintf(graph_file, "\tnode [shape=box,fontsize=10];\n");
647234949Sbapt	fprintf(graph_file, "\torientation=landscape;\n");
648234949Sbapt	fprintf(graph_file, "\trankdir=LR;\n");
649234949Sbapt	fprintf(graph_file, "\t/*\n");
650234949Sbapt	fprintf(graph_file, "\tmargin=0.2;\n");
651234949Sbapt	fprintf(graph_file, "\tpage=\"8.27,11.69\"; // for A4 printing\n");
652234949Sbapt	fprintf(graph_file, "\tratio=auto;\n");
653234949Sbapt	fprintf(graph_file, "\t*/\n");
654234949Sbapt    }
655234949Sbapt
656234949Sbapt    if (dflag)
657234949Sbapt    {
658234949Sbapt	defines_file = fopen(defines_file_name, "w");
659234949Sbapt	if (defines_file == 0)
660234949Sbapt	    open_error(defines_file_name);
661234949Sbapt	union_file = open_tmpfile("union_file");
662234949Sbapt    }
663234949Sbapt
664234949Sbapt    if (iflag)
665234949Sbapt    {
666234949Sbapt	externs_file = fopen(externs_file_name, "w");
667234949Sbapt	if (externs_file == 0)
668234949Sbapt	    open_error(externs_file_name);
669234949Sbapt    }
670234949Sbapt
671234949Sbapt    output_file = fopen(output_file_name, "w");
672234949Sbapt    if (output_file == 0)
673234949Sbapt	open_error(output_file_name);
674234949Sbapt
675234949Sbapt    if (rflag)
676234949Sbapt    {
677234949Sbapt	code_file = fopen(code_file_name, "w");
678234949Sbapt	if (code_file == 0)
679234949Sbapt	    open_error(code_file_name);
680234949Sbapt    }
681234949Sbapt    else
682234949Sbapt	code_file = output_file;
683234949Sbapt}
684234949Sbapt
685234949Sbaptint
686234949Sbaptmain(int argc, char *argv[])
687234949Sbapt{
688234949Sbapt    SRexpect = -1;
689234949Sbapt    RRexpect = -1;
690234949Sbapt    exit_code = EXIT_SUCCESS;
691234949Sbapt
692234949Sbapt    set_signals();
693234949Sbapt    getargs(argc, argv);
694234949Sbapt    open_files();
695234949Sbapt    reader();
696234949Sbapt    lr0();
697234949Sbapt    lalr();
698234949Sbapt    make_parser();
699234949Sbapt    graph();
700234949Sbapt    finalize_closure();
701234949Sbapt    verbose();
702234949Sbapt    output();
703234949Sbapt    done(exit_code);
704234949Sbapt    /*NOTREACHED */
705234949Sbapt}
706