1268899Sbapt/* $Id: main.c,v 1.50 2014/04/22 23:34:47 tom Exp $ */
2234949Sbapt
3234949Sbapt#include <signal.h>
4268899Sbapt#ifndef _WIN32
5234949Sbapt#include <unistd.h>		/* for _exit() */
6268899Sbapt#else
7268899Sbapt#include <stdlib.h>		/* for _exit() */
8268899Sbapt#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
80268899SbaptValue_t nitems;
81268899SbaptValue_t nrules;
82268899SbaptValue_t nsyms;
83268899SbaptValue_t ntokens;
84268899SbaptValue_t nvars;
85234949Sbapt
86234949SbaptValue_t start_symbol;
87234949Sbaptchar **symbol_name;
88234949Sbaptchar **symbol_pname;
89234949SbaptValue_t *symbol_value;
90268899SbaptValue_t *symbol_prec;
91234949Sbaptchar *symbol_assoc;
92234949Sbapt
93234949Sbaptint pure_parser;
94268899Sbaptint token_table;
95268899Sbapt
96268899Sbapt#if defined(YYBTYACC)
97268899SbaptValue_t *symbol_pval;
98268899Sbaptchar **symbol_destructor;
99268899Sbaptchar **symbol_type_tag;
100268899Sbaptint locations = 0;	/* default to no position processing */
101268899Sbaptint backtrack = 0;	/* default is no backtracking */
102268899Sbapt#endif
103268899Sbapt
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);
132268899Sbapt    if (iflag)
133268899Sbapt	DO_CLOSE(externs_file);
134268899Sbapt    if (rflag)
135268899Sbapt	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();
169268899Sbapt    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.\")"
209268899Sbapt	,"  -B                    create a backtracking parser"
210268899Sbapt	,"  -d                    write definitions (" DEFINES_SUFFIX ")"
211268899Sbapt	,"  -D                    enable value stack memory reclamation"
212234949Sbapt	,"  -i                    write interface (y.tab.i)"
213234949Sbapt	,"  -g                    write a graphical description"
214234949Sbapt	,"  -l                    suppress #line directives"
215268899Sbapt	,"  -L                    enable position processing, e.g., \"%locations\""
216268899Sbapt	,"  -o output_file        (default \"" OUTPUT_SUFFIX "\")"
217234949Sbapt	,"  -p symbol_prefix      set symbol prefix (default \"yy\")"
218234949Sbapt	,"  -P                    create a reentrant parser, e.g., \"%pure-parser\""
219234949Sbapt	,"  -r                    produce separate code and table files (y.code.c)"
220234949Sbapt	,"  -s                    suppress #define's for quoted names in %token lines"
221234949Sbapt	,"  -t                    add debugging support"
222234949Sbapt	,"  -v                    write description (y.output)"
223234949Sbapt	,"  -V                    show version information and exit"
224234949Sbapt    };
225234949Sbapt    unsigned n;
226234949Sbapt
227234949Sbapt    fflush(stdout);
228234949Sbapt    fprintf(stderr, "Usage: %s [options] filename\n", myname);
229234949Sbapt    for (n = 0; n < sizeof(msg) / sizeof(msg[0]); ++n)
230234949Sbapt	fprintf(stderr, "%s\n", msg[n]);
231234949Sbapt
232234949Sbapt    exit(1);
233234949Sbapt}
234234949Sbapt
235234949Sbaptstatic void
236234949Sbaptsetflag(int ch)
237234949Sbapt{
238234949Sbapt    switch (ch)
239234949Sbapt    {
240268899Sbapt    case 'B':
241268899Sbapt#if defined(YYBTYACC)
242268899Sbapt	backtrack = 1;
243268899Sbapt#else
244268899Sbapt	unsupported_flag_warning("-B", "reconfigure with --enable-btyacc");
245268899Sbapt#endif
246268899Sbapt	break;
247268899Sbapt
248234949Sbapt    case 'd':
249234949Sbapt	dflag = 1;
250234949Sbapt	break;
251234949Sbapt
252234949Sbapt    case 'g':
253234949Sbapt	gflag = 1;
254234949Sbapt	break;
255234949Sbapt
256234949Sbapt    case 'i':
257234949Sbapt	iflag = 1;
258234949Sbapt	break;
259234949Sbapt
260234949Sbapt    case 'l':
261234949Sbapt	lflag = 1;
262234949Sbapt	break;
263234949Sbapt
264268899Sbapt    case 'L':
265268899Sbapt#if defined(YYBTYACC)
266268899Sbapt	locations = 1;
267268899Sbapt#else
268268899Sbapt	unsupported_flag_warning("-B", "reconfigure with --enable-btyacc");
269268899Sbapt#endif
270268899Sbapt	break;
271268899Sbapt
272234949Sbapt    case 'P':
273234949Sbapt	pure_parser = 1;
274234949Sbapt	break;
275234949Sbapt
276234949Sbapt    case 'r':
277234949Sbapt	rflag = 1;
278234949Sbapt	break;
279234949Sbapt
280234949Sbapt    case 's':
281234949Sbapt	sflag = 1;
282234949Sbapt	break;
283234949Sbapt
284234949Sbapt    case 't':
285234949Sbapt	tflag = 1;
286234949Sbapt	break;
287234949Sbapt
288234949Sbapt    case 'v':
289234949Sbapt	vflag = 1;
290234949Sbapt	break;
291234949Sbapt
292234949Sbapt    case 'V':
293234949Sbapt	printf("%s - %s\n", myname, VERSION);
294234949Sbapt	exit(EXIT_SUCCESS);
295234949Sbapt
296234949Sbapt    case 'y':
297234949Sbapt	/* noop for bison compatibility. byacc is already designed to be posix
298234949Sbapt	 * yacc compatible. */
299234949Sbapt	break;
300234949Sbapt
301234949Sbapt    default:
302234949Sbapt	usage();
303234949Sbapt    }
304234949Sbapt}
305234949Sbapt
306234949Sbaptstatic void
307234949Sbaptgetargs(int argc, char *argv[])
308234949Sbapt{
309234949Sbapt    int i;
310234949Sbapt    char *s;
311234949Sbapt    int ch;
312234949Sbapt
313234949Sbapt    if (argc > 0)
314234949Sbapt	myname = argv[0];
315234949Sbapt
316234949Sbapt    for (i = 1; i < argc; ++i)
317234949Sbapt    {
318234949Sbapt	s = argv[i];
319234949Sbapt	if (*s != '-')
320234949Sbapt	    break;
321234949Sbapt	switch (ch = *++s)
322234949Sbapt	{
323234949Sbapt	case '\0':
324234949Sbapt	    input_file = stdin;
325234949Sbapt	    if (i + 1 < argc)
326234949Sbapt		usage();
327234949Sbapt	    return;
328234949Sbapt
329234949Sbapt	case '-':
330234949Sbapt	    ++i;
331234949Sbapt	    goto no_more_options;
332234949Sbapt
333234949Sbapt	case 'b':
334234949Sbapt	    if (*++s)
335234949Sbapt		file_prefix = s;
336234949Sbapt	    else if (++i < argc)
337234949Sbapt		file_prefix = argv[i];
338234949Sbapt	    else
339234949Sbapt		usage();
340234949Sbapt	    continue;
341234949Sbapt
342234949Sbapt	case 'o':
343234949Sbapt	    if (*++s)
344234949Sbapt		output_file_name = s;
345234949Sbapt	    else if (++i < argc)
346234949Sbapt		output_file_name = argv[i];
347234949Sbapt	    else
348234949Sbapt		usage();
349234949Sbapt	    continue;
350234949Sbapt
351234949Sbapt	case 'p':
352234949Sbapt	    if (*++s)
353234949Sbapt		symbol_prefix = s;
354234949Sbapt	    else if (++i < argc)
355234949Sbapt		symbol_prefix = argv[i];
356234949Sbapt	    else
357234949Sbapt		usage();
358234949Sbapt	    continue;
359234949Sbapt
360234949Sbapt	default:
361234949Sbapt	    setflag(ch);
362234949Sbapt	    break;
363234949Sbapt	}
364234949Sbapt
365234949Sbapt	for (;;)
366234949Sbapt	{
367234949Sbapt	    switch (ch = *++s)
368234949Sbapt	    {
369234949Sbapt	    case '\0':
370234949Sbapt		goto end_of_option;
371234949Sbapt
372234949Sbapt	    default:
373234949Sbapt		setflag(ch);
374234949Sbapt		break;
375234949Sbapt	    }
376234949Sbapt	}
377234949Sbapt      end_of_option:;
378234949Sbapt    }
379234949Sbapt
380234949Sbapt  no_more_options:;
381234949Sbapt    if (i + 1 != argc)
382234949Sbapt	usage();
383234949Sbapt    input_file_name = argv[i];
384234949Sbapt}
385234949Sbapt
386234949Sbaptvoid *
387234949Sbaptallocate(size_t n)
388234949Sbapt{
389234949Sbapt    void *p;
390234949Sbapt
391234949Sbapt    p = NULL;
392234949Sbapt    if (n)
393234949Sbapt    {
394234949Sbapt	p = CALLOC(1, n);
395234949Sbapt	NO_SPACE(p);
396234949Sbapt    }
397234949Sbapt    return (p);
398234949Sbapt}
399234949Sbapt
400234949Sbapt#define CREATE_FILE_NAME(dest, suffix) \
401268899Sbapt	dest = alloc_file_name(len, suffix)
402234949Sbapt
403268899Sbaptstatic char *
404268899Sbaptalloc_file_name(size_t len, const char *suffix)
405268899Sbapt{
406268899Sbapt    char *result = TMALLOC(char, len + strlen(suffix) + 1);
407268899Sbapt    if (result == 0)
408268899Sbapt	no_space();
409268899Sbapt    strcpy(result, file_prefix);
410268899Sbapt    strcpy(result + len, suffix);
411268899Sbapt    return result;
412268899Sbapt}
413268899Sbapt
414234949Sbaptstatic void
415234949Sbaptcreate_file_names(void)
416234949Sbapt{
417234949Sbapt    size_t len;
418234949Sbapt    const char *defines_suffix;
419234949Sbapt    const char *externs_suffix;
420234949Sbapt    char *prefix;
421234949Sbapt
422234949Sbapt    prefix = NULL;
423234949Sbapt    defines_suffix = DEFINES_SUFFIX;
424234949Sbapt    externs_suffix = EXTERNS_SUFFIX;
425234949Sbapt
426234949Sbapt    /* compute the file_prefix from the user provided output_file_name */
427234949Sbapt    if (output_file_name != 0)
428234949Sbapt    {
429268899Sbapt	if (!(prefix = strstr(output_file_name, OUTPUT_SUFFIX))
430234949Sbapt	    && (prefix = strstr(output_file_name, ".c")))
431234949Sbapt	{
432234949Sbapt	    defines_suffix = ".h";
433234949Sbapt	    externs_suffix = ".i";
434234949Sbapt	}
435234949Sbapt    }
436234949Sbapt
437234949Sbapt    if (prefix != NULL)
438234949Sbapt    {
439234949Sbapt	len = (size_t) (prefix - output_file_name);
440240517Sbapt	file_prefix = TMALLOC(char, len + 1);
441234949Sbapt	NO_SPACE(file_prefix);
442234949Sbapt	strncpy(file_prefix, output_file_name, len)[len] = 0;
443234949Sbapt    }
444234949Sbapt    else
445234949Sbapt	len = strlen(file_prefix);
446234949Sbapt
447234949Sbapt    /* if "-o filename" was not given */
448234949Sbapt    if (output_file_name == 0)
449234949Sbapt    {
450234949Sbapt	oflag = 1;
451234949Sbapt	CREATE_FILE_NAME(output_file_name, OUTPUT_SUFFIX);
452234949Sbapt    }
453234949Sbapt
454234949Sbapt    if (rflag)
455234949Sbapt    {
456234949Sbapt	CREATE_FILE_NAME(code_file_name, CODE_SUFFIX);
457234949Sbapt    }
458234949Sbapt    else
459234949Sbapt	code_file_name = output_file_name;
460234949Sbapt
461234949Sbapt    if (dflag)
462234949Sbapt    {
463234949Sbapt	CREATE_FILE_NAME(defines_file_name, defines_suffix);
464234949Sbapt    }
465234949Sbapt
466234949Sbapt    if (iflag)
467234949Sbapt    {
468234949Sbapt	CREATE_FILE_NAME(externs_file_name, externs_suffix);
469234949Sbapt    }
470234949Sbapt
471234949Sbapt    if (vflag)
472234949Sbapt    {
473234949Sbapt	CREATE_FILE_NAME(verbose_file_name, VERBOSE_SUFFIX);
474234949Sbapt    }
475234949Sbapt
476234949Sbapt    if (gflag)
477234949Sbapt    {
478234949Sbapt	CREATE_FILE_NAME(graph_file_name, GRAPH_SUFFIX);
479234949Sbapt    }
480234949Sbapt
481234949Sbapt    if (prefix != NULL)
482234949Sbapt    {
483234949Sbapt	FREE(file_prefix);
484234949Sbapt    }
485234949Sbapt}
486234949Sbapt
487234949Sbapt#if USE_MKSTEMP
488234949Sbaptstatic void
489234949Sbaptclose_tmpfiles(void)
490234949Sbapt{
491234949Sbapt    while (my_tmpfiles != 0)
492234949Sbapt    {
493234949Sbapt	MY_TMPFILES *next = my_tmpfiles->next;
494234949Sbapt
495234949Sbapt	chmod(my_tmpfiles->name, 0644);
496234949Sbapt	unlink(my_tmpfiles->name);
497234949Sbapt
498234949Sbapt	free(my_tmpfiles->name);
499234949Sbapt	free(my_tmpfiles);
500234949Sbapt
501234949Sbapt	my_tmpfiles = next;
502234949Sbapt    }
503234949Sbapt}
504234949Sbapt
505234949Sbapt#ifndef HAVE_MKSTEMP
506234949Sbaptstatic int
507234949Sbaptmy_mkstemp(char *temp)
508234949Sbapt{
509234949Sbapt    int fd;
510234949Sbapt    char *dname;
511234949Sbapt    char *fname;
512234949Sbapt    char *name;
513234949Sbapt
514234949Sbapt    /*
515234949Sbapt     * Split-up to use tempnam, rather than tmpnam; the latter (like
516234949Sbapt     * mkstemp) is unusable on Windows.
517234949Sbapt     */
518234949Sbapt    if ((fname = strrchr(temp, '/')) != 0)
519234949Sbapt    {
520234949Sbapt	dname = strdup(temp);
521234949Sbapt	dname[++fname - temp] = '\0';
522234949Sbapt    }
523234949Sbapt    else
524234949Sbapt    {
525234949Sbapt	dname = 0;
526234949Sbapt	fname = temp;
527234949Sbapt    }
528234949Sbapt    if ((name = tempnam(dname, fname)) != 0)
529234949Sbapt    {
530234949Sbapt	fd = open(name, O_CREAT | O_EXCL | O_RDWR);
531234949Sbapt	strcpy(temp, name);
532234949Sbapt    }
533234949Sbapt    else
534234949Sbapt    {
535234949Sbapt	fd = -1;
536234949Sbapt    }
537234949Sbapt
538234949Sbapt    if (dname != 0)
539234949Sbapt	free(dname);
540234949Sbapt
541234949Sbapt    return fd;
542234949Sbapt}
543234949Sbapt#define mkstemp(s) my_mkstemp(s)
544234949Sbapt#endif
545234949Sbapt
546234949Sbapt#endif
547234949Sbapt
548234949Sbapt/*
549234949Sbapt * tmpfile() should be adequate, except that it may require special privileges
550234949Sbapt * to use, e.g., MinGW and Windows 7 where it tries to use the root directory.
551234949Sbapt */
552234949Sbaptstatic FILE *
553234949Sbaptopen_tmpfile(const char *label)
554234949Sbapt{
555234949Sbapt    FILE *result;
556234949Sbapt#if USE_MKSTEMP
557234949Sbapt    int fd;
558234949Sbapt    const char *tmpdir;
559234949Sbapt    char *name;
560234949Sbapt    const char *mark;
561234949Sbapt
562234949Sbapt    if ((tmpdir = getenv("TMPDIR")) == 0 || access(tmpdir, W_OK) != 0)
563234949Sbapt    {
564234949Sbapt#ifdef P_tmpdir
565234949Sbapt	tmpdir = P_tmpdir;
566234949Sbapt#else
567234949Sbapt	tmpdir = "/tmp";
568234949Sbapt#endif
569234949Sbapt	if (access(tmpdir, W_OK) != 0)
570234949Sbapt	    tmpdir = ".";
571234949Sbapt    }
572234949Sbapt
573234949Sbapt    name = malloc(strlen(tmpdir) + 10 + strlen(label));
574234949Sbapt
575234949Sbapt    result = 0;
576234949Sbapt    if (name != 0)
577234949Sbapt    {
578234949Sbapt	if ((mark = strrchr(label, '_')) == 0)
579234949Sbapt	    mark = label + strlen(label);
580234949Sbapt
581234949Sbapt	sprintf(name, "%s/%.*sXXXXXX", tmpdir, (int)(mark - label), label);
582234949Sbapt	fd = mkstemp(name);
583234949Sbapt	if (fd >= 0)
584234949Sbapt	{
585234949Sbapt	    result = fdopen(fd, "w+");
586234949Sbapt	    if (result != 0)
587234949Sbapt	    {
588234949Sbapt		MY_TMPFILES *item;
589234949Sbapt
590234949Sbapt		if (my_tmpfiles == 0)
591234949Sbapt		{
592234949Sbapt		    atexit(close_tmpfiles);
593234949Sbapt		}
594234949Sbapt
595234949Sbapt		item = NEW(MY_TMPFILES);
596234949Sbapt		NO_SPACE(item);
597234949Sbapt
598234949Sbapt		item->name = name;
599234949Sbapt		NO_SPACE(item->name);
600234949Sbapt
601234949Sbapt		item->next = my_tmpfiles;
602234949Sbapt		my_tmpfiles = item;
603234949Sbapt	    }
604234949Sbapt	}
605234949Sbapt    }
606234949Sbapt#else
607234949Sbapt    result = tmpfile();
608234949Sbapt#endif
609234949Sbapt
610234949Sbapt    if (result == 0)
611234949Sbapt	open_error(label);
612234949Sbapt    return result;
613234949Sbapt}
614234949Sbapt
615234949Sbaptstatic void
616234949Sbaptopen_files(void)
617234949Sbapt{
618234949Sbapt    create_file_names();
619234949Sbapt
620234949Sbapt    if (input_file == 0)
621234949Sbapt    {
622234949Sbapt	input_file = fopen(input_file_name, "r");
623234949Sbapt	if (input_file == 0)
624234949Sbapt	    open_error(input_file_name);
625234949Sbapt    }
626234949Sbapt
627234949Sbapt    action_file = open_tmpfile("action_file");
628234949Sbapt    text_file = open_tmpfile("text_file");
629234949Sbapt
630234949Sbapt    if (vflag)
631234949Sbapt    {
632234949Sbapt	verbose_file = fopen(verbose_file_name, "w");
633234949Sbapt	if (verbose_file == 0)
634234949Sbapt	    open_error(verbose_file_name);
635234949Sbapt    }
636234949Sbapt
637234949Sbapt    if (gflag)
638234949Sbapt    {
639234949Sbapt	graph_file = fopen(graph_file_name, "w");
640234949Sbapt	if (graph_file == 0)
641234949Sbapt	    open_error(graph_file_name);
642234949Sbapt	fprintf(graph_file, "digraph %s {\n", file_prefix);
643234949Sbapt	fprintf(graph_file, "\tedge [fontsize=10];\n");
644234949Sbapt	fprintf(graph_file, "\tnode [shape=box,fontsize=10];\n");
645234949Sbapt	fprintf(graph_file, "\torientation=landscape;\n");
646234949Sbapt	fprintf(graph_file, "\trankdir=LR;\n");
647234949Sbapt	fprintf(graph_file, "\t/*\n");
648234949Sbapt	fprintf(graph_file, "\tmargin=0.2;\n");
649234949Sbapt	fprintf(graph_file, "\tpage=\"8.27,11.69\"; // for A4 printing\n");
650234949Sbapt	fprintf(graph_file, "\tratio=auto;\n");
651234949Sbapt	fprintf(graph_file, "\t*/\n");
652234949Sbapt    }
653234949Sbapt
654234949Sbapt    if (dflag)
655234949Sbapt    {
656234949Sbapt	defines_file = fopen(defines_file_name, "w");
657234949Sbapt	if (defines_file == 0)
658234949Sbapt	    open_error(defines_file_name);
659234949Sbapt	union_file = open_tmpfile("union_file");
660234949Sbapt    }
661234949Sbapt
662234949Sbapt    if (iflag)
663234949Sbapt    {
664234949Sbapt	externs_file = fopen(externs_file_name, "w");
665234949Sbapt	if (externs_file == 0)
666234949Sbapt	    open_error(externs_file_name);
667234949Sbapt    }
668234949Sbapt
669234949Sbapt    output_file = fopen(output_file_name, "w");
670234949Sbapt    if (output_file == 0)
671234949Sbapt	open_error(output_file_name);
672234949Sbapt
673234949Sbapt    if (rflag)
674234949Sbapt    {
675234949Sbapt	code_file = fopen(code_file_name, "w");
676234949Sbapt	if (code_file == 0)
677234949Sbapt	    open_error(code_file_name);
678234949Sbapt    }
679234949Sbapt    else
680234949Sbapt	code_file = output_file;
681234949Sbapt}
682234949Sbapt
683234949Sbaptint
684234949Sbaptmain(int argc, char *argv[])
685234949Sbapt{
686234949Sbapt    SRexpect = -1;
687234949Sbapt    RRexpect = -1;
688234949Sbapt    exit_code = EXIT_SUCCESS;
689234949Sbapt
690234949Sbapt    set_signals();
691234949Sbapt    getargs(argc, argv);
692234949Sbapt    open_files();
693234949Sbapt    reader();
694234949Sbapt    lr0();
695234949Sbapt    lalr();
696234949Sbapt    make_parser();
697234949Sbapt    graph();
698234949Sbapt    finalize_closure();
699234949Sbapt    verbose();
700234949Sbapt    output();
701234949Sbapt    done(exit_code);
702234949Sbapt    /*NOTREACHED */
703234949Sbapt}
704