main.c revision 234949
1234949Sbapt/* $Id: main.c,v 1.38 2012/01/14 01:01:15 tom Exp $ */
2234949Sbapt
3234949Sbapt#include <signal.h>
4234949Sbapt#include <unistd.h>		/* for _exit() */
5234949Sbapt
6234949Sbapt#include "defs.h"
7234949Sbapt
8234949Sbapt#if defined(HAVE_ATEXIT)
9234949Sbapt# ifdef HAVE_MKSTEMP
10234949Sbapt#  define USE_MKSTEMP 1
11234949Sbapt# elif defined(HAVE_FCNTL_H)
12234949Sbapt#  define USE_MKSTEMP 1
13234949Sbapt#  include <fcntl.h>		/* for open(), O_EXCL, etc. */
14234949Sbapt# else
15234949Sbapt#  define USE_MKSTEMP 0
16234949Sbapt# endif
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
80234949Sbaptint nitems;
81234949Sbaptint nrules;
82234949Sbaptint nsyms;
83234949Sbaptint ntokens;
84234949Sbaptint nvars;
85234949Sbapt
86234949SbaptValue_t start_symbol;
87234949Sbaptchar **symbol_name;
88234949Sbaptchar **symbol_pname;
89234949SbaptValue_t *symbol_value;
90234949Sbaptshort *symbol_prec;
91234949Sbaptchar *symbol_assoc;
92234949Sbapt
93234949Sbaptint pure_parser;
94234949Sbaptint exit_code;
95234949Sbapt
96234949SbaptValue_t *ritem;
97234949SbaptValue_t *rlhs;
98234949SbaptValue_t *rrhs;
99234949SbaptValue_t *rprec;
100234949SbaptAssoc_t *rassoc;
101234949SbaptValue_t **derives;
102234949Sbaptchar *nullable;
103234949Sbapt
104234949Sbapt/*
105234949Sbapt * Since fclose() is called via the signal handler, it might die.  Don't loop
106234949Sbapt * if there is a problem closing a file.
107234949Sbapt */
108234949Sbapt#define DO_CLOSE(fp) \
109234949Sbapt	if (fp != 0) { \
110234949Sbapt	    FILE *use = fp; \
111234949Sbapt	    fp = 0; \
112234949Sbapt	    fclose(use); \
113234949Sbapt	}
114234949Sbapt
115234949Sbaptstatic int got_intr = 0;
116234949Sbapt
117234949Sbaptvoid
118234949Sbaptdone(int k)
119234949Sbapt{
120234949Sbapt    DO_CLOSE(input_file);
121234949Sbapt    DO_CLOSE(output_file);
122234949Sbapt
123234949Sbapt    DO_CLOSE(action_file);
124234949Sbapt    DO_CLOSE(defines_file);
125234949Sbapt    DO_CLOSE(graph_file);
126234949Sbapt    DO_CLOSE(text_file);
127234949Sbapt    DO_CLOSE(union_file);
128234949Sbapt    DO_CLOSE(verbose_file);
129234949Sbapt
130234949Sbapt    if (got_intr)
131234949Sbapt	_exit(EXIT_FAILURE);
132234949Sbapt
133234949Sbapt#ifdef NO_LEAKS
134234949Sbapt    if (rflag)
135234949Sbapt	DO_FREE(code_file_name);
136234949Sbapt
137234949Sbapt    if (dflag)
138234949Sbapt	DO_FREE(defines_file_name);
139234949Sbapt
140234949Sbapt    if (iflag)
141234949Sbapt	DO_FREE(externs_file_name);
142234949Sbapt
143234949Sbapt    if (oflag)
144234949Sbapt	DO_FREE(output_file_name);
145234949Sbapt
146234949Sbapt    if (vflag)
147234949Sbapt	DO_FREE(verbose_file_name);
148234949Sbapt
149234949Sbapt    if (gflag)
150234949Sbapt	DO_FREE(graph_file_name);
151234949Sbapt
152234949Sbapt    lr0_leaks();
153234949Sbapt    lalr_leaks();
154234949Sbapt    mkpar_leaks();
155234949Sbapt    output_leaks();
156234949Sbapt    reader_leaks();
157234949Sbapt#endif
158234949Sbapt
159234949Sbapt    if (rflag)
160234949Sbapt	DO_CLOSE(code_file);
161234949Sbapt
162234949Sbapt    exit(k);
163234949Sbapt}
164234949Sbapt
165234949Sbaptstatic void
166234949Sbaptonintr(int sig GCC_UNUSED)
167234949Sbapt{
168234949Sbapt    got_intr = 1;
169234949Sbapt    done(EXIT_FAILURE);
170234949Sbapt}
171234949Sbapt
172234949Sbaptstatic void
173234949Sbaptset_signals(void)
174234949Sbapt{
175234949Sbapt#ifdef SIGINT
176234949Sbapt    if (signal(SIGINT, SIG_IGN) != SIG_IGN)
177234949Sbapt	signal(SIGINT, onintr);
178234949Sbapt#endif
179234949Sbapt#ifdef SIGTERM
180234949Sbapt    if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
181234949Sbapt	signal(SIGTERM, onintr);
182234949Sbapt#endif
183234949Sbapt#ifdef SIGHUP
184234949Sbapt    if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
185234949Sbapt	signal(SIGHUP, onintr);
186234949Sbapt#endif
187234949Sbapt}
188234949Sbapt
189234949Sbaptstatic void
190234949Sbaptusage(void)
191234949Sbapt{
192234949Sbapt    static const char *msg[] =
193234949Sbapt    {
194234949Sbapt	""
195234949Sbapt	,"Options:"
196234949Sbapt	,"  -b file_prefix        set filename prefix (default \"y.\")"
197234949Sbapt	,"  -d                    write definitions (y.tab.h)"
198234949Sbapt	,"  -i                    write interface (y.tab.i)"
199234949Sbapt	,"  -g                    write a graphical description"
200234949Sbapt	,"  -l                    suppress #line directives"
201234949Sbapt	,"  -o output_file        (default \"y.tab.c\")"
202234949Sbapt	,"  -p symbol_prefix      set symbol prefix (default \"yy\")"
203234949Sbapt	,"  -P                    create a reentrant parser, e.g., \"%pure-parser\""
204234949Sbapt	,"  -r                    produce separate code and table files (y.code.c)"
205234949Sbapt	,"  -s                    suppress #define's for quoted names in %token lines"
206234949Sbapt	,"  -t                    add debugging support"
207234949Sbapt	,"  -v                    write description (y.output)"
208234949Sbapt	,"  -V                    show version information and exit"
209234949Sbapt    };
210234949Sbapt    unsigned n;
211234949Sbapt
212234949Sbapt    fflush(stdout);
213234949Sbapt    fprintf(stderr, "Usage: %s [options] filename\n", myname);
214234949Sbapt    for (n = 0; n < sizeof(msg) / sizeof(msg[0]); ++n)
215234949Sbapt	fprintf(stderr, "%s\n", msg[n]);
216234949Sbapt
217234949Sbapt    exit(1);
218234949Sbapt}
219234949Sbapt
220234949Sbaptstatic void
221234949Sbaptsetflag(int ch)
222234949Sbapt{
223234949Sbapt    switch (ch)
224234949Sbapt    {
225234949Sbapt    case 'd':
226234949Sbapt	dflag = 1;
227234949Sbapt	break;
228234949Sbapt
229234949Sbapt    case 'g':
230234949Sbapt	gflag = 1;
231234949Sbapt	break;
232234949Sbapt
233234949Sbapt    case 'i':
234234949Sbapt	iflag = 1;
235234949Sbapt	break;
236234949Sbapt
237234949Sbapt    case 'l':
238234949Sbapt	lflag = 1;
239234949Sbapt	break;
240234949Sbapt
241234949Sbapt    case 'P':
242234949Sbapt	pure_parser = 1;
243234949Sbapt	break;
244234949Sbapt
245234949Sbapt    case 'r':
246234949Sbapt	rflag = 1;
247234949Sbapt	break;
248234949Sbapt
249234949Sbapt    case 's':
250234949Sbapt	sflag = 1;
251234949Sbapt	break;
252234949Sbapt
253234949Sbapt    case 't':
254234949Sbapt	tflag = 1;
255234949Sbapt	break;
256234949Sbapt
257234949Sbapt    case 'v':
258234949Sbapt	vflag = 1;
259234949Sbapt	break;
260234949Sbapt
261234949Sbapt    case 'V':
262234949Sbapt	printf("%s - %s\n", myname, VERSION);
263234949Sbapt	exit(EXIT_SUCCESS);
264234949Sbapt
265234949Sbapt    case 'y':
266234949Sbapt	/* noop for bison compatibility. byacc is already designed to be posix
267234949Sbapt	 * yacc compatible. */
268234949Sbapt	break;
269234949Sbapt
270234949Sbapt    default:
271234949Sbapt	usage();
272234949Sbapt    }
273234949Sbapt}
274234949Sbapt
275234949Sbaptstatic void
276234949Sbaptgetargs(int argc, char *argv[])
277234949Sbapt{
278234949Sbapt    int i;
279234949Sbapt    char *s;
280234949Sbapt    int ch;
281234949Sbapt
282234949Sbapt    if (argc > 0)
283234949Sbapt	myname = argv[0];
284234949Sbapt
285234949Sbapt    for (i = 1; i < argc; ++i)
286234949Sbapt    {
287234949Sbapt	s = argv[i];
288234949Sbapt	if (*s != '-')
289234949Sbapt	    break;
290234949Sbapt	switch (ch = *++s)
291234949Sbapt	{
292234949Sbapt	case '\0':
293234949Sbapt	    input_file = stdin;
294234949Sbapt	    if (i + 1 < argc)
295234949Sbapt		usage();
296234949Sbapt	    return;
297234949Sbapt
298234949Sbapt	case '-':
299234949Sbapt	    ++i;
300234949Sbapt	    goto no_more_options;
301234949Sbapt
302234949Sbapt	case 'b':
303234949Sbapt	    if (*++s)
304234949Sbapt		file_prefix = s;
305234949Sbapt	    else if (++i < argc)
306234949Sbapt		file_prefix = argv[i];
307234949Sbapt	    else
308234949Sbapt		usage();
309234949Sbapt	    continue;
310234949Sbapt
311234949Sbapt	case 'o':
312234949Sbapt	    if (*++s)
313234949Sbapt		output_file_name = s;
314234949Sbapt	    else if (++i < argc)
315234949Sbapt		output_file_name = argv[i];
316234949Sbapt	    else
317234949Sbapt		usage();
318234949Sbapt	    continue;
319234949Sbapt
320234949Sbapt	case 'p':
321234949Sbapt	    if (*++s)
322234949Sbapt		symbol_prefix = s;
323234949Sbapt	    else if (++i < argc)
324234949Sbapt		symbol_prefix = argv[i];
325234949Sbapt	    else
326234949Sbapt		usage();
327234949Sbapt	    continue;
328234949Sbapt
329234949Sbapt	default:
330234949Sbapt	    setflag(ch);
331234949Sbapt	    break;
332234949Sbapt	}
333234949Sbapt
334234949Sbapt	for (;;)
335234949Sbapt	{
336234949Sbapt	    switch (ch = *++s)
337234949Sbapt	    {
338234949Sbapt	    case '\0':
339234949Sbapt		goto end_of_option;
340234949Sbapt
341234949Sbapt	    default:
342234949Sbapt		setflag(ch);
343234949Sbapt		break;
344234949Sbapt	    }
345234949Sbapt	}
346234949Sbapt      end_of_option:;
347234949Sbapt    }
348234949Sbapt
349234949Sbapt  no_more_options:;
350234949Sbapt    if (i + 1 != argc)
351234949Sbapt	usage();
352234949Sbapt    input_file_name = argv[i];
353234949Sbapt}
354234949Sbapt
355234949Sbaptvoid *
356234949Sbaptallocate(size_t n)
357234949Sbapt{
358234949Sbapt    void *p;
359234949Sbapt
360234949Sbapt    p = NULL;
361234949Sbapt    if (n)
362234949Sbapt    {
363234949Sbapt	p = CALLOC(1, n);
364234949Sbapt	NO_SPACE(p);
365234949Sbapt    }
366234949Sbapt    return (p);
367234949Sbapt}
368234949Sbapt
369234949Sbapt#define CREATE_FILE_NAME(dest, suffix) \
370234949Sbapt	dest = MALLOC(len + strlen(suffix) + 1); \
371234949Sbapt	NO_SPACE(dest); \
372234949Sbapt	strcpy(dest, file_prefix); \
373234949Sbapt	strcpy(dest + len, suffix)
374234949Sbapt
375234949Sbaptstatic void
376234949Sbaptcreate_file_names(void)
377234949Sbapt{
378234949Sbapt    size_t len;
379234949Sbapt    const char *defines_suffix;
380234949Sbapt    const char *externs_suffix;
381234949Sbapt    char *prefix;
382234949Sbapt
383234949Sbapt    prefix = NULL;
384234949Sbapt    defines_suffix = DEFINES_SUFFIX;
385234949Sbapt    externs_suffix = EXTERNS_SUFFIX;
386234949Sbapt
387234949Sbapt    /* compute the file_prefix from the user provided output_file_name */
388234949Sbapt    if (output_file_name != 0)
389234949Sbapt    {
390234949Sbapt	if (!(prefix = strstr(output_file_name, ".tab.c"))
391234949Sbapt	    && (prefix = strstr(output_file_name, ".c")))
392234949Sbapt	{
393234949Sbapt	    defines_suffix = ".h";
394234949Sbapt	    externs_suffix = ".i";
395234949Sbapt	}
396234949Sbapt    }
397234949Sbapt
398234949Sbapt    if (prefix != NULL)
399234949Sbapt    {
400234949Sbapt	len = (size_t) (prefix - output_file_name);
401234949Sbapt	file_prefix = (char *)MALLOC(len + 1);
402234949Sbapt	NO_SPACE(file_prefix);
403234949Sbapt	strncpy(file_prefix, output_file_name, len)[len] = 0;
404234949Sbapt    }
405234949Sbapt    else
406234949Sbapt	len = strlen(file_prefix);
407234949Sbapt
408234949Sbapt    /* if "-o filename" was not given */
409234949Sbapt    if (output_file_name == 0)
410234949Sbapt    {
411234949Sbapt	oflag = 1;
412234949Sbapt	CREATE_FILE_NAME(output_file_name, OUTPUT_SUFFIX);
413234949Sbapt    }
414234949Sbapt
415234949Sbapt    if (rflag)
416234949Sbapt    {
417234949Sbapt	CREATE_FILE_NAME(code_file_name, CODE_SUFFIX);
418234949Sbapt    }
419234949Sbapt    else
420234949Sbapt	code_file_name = output_file_name;
421234949Sbapt
422234949Sbapt    if (dflag)
423234949Sbapt    {
424234949Sbapt	CREATE_FILE_NAME(defines_file_name, defines_suffix);
425234949Sbapt    }
426234949Sbapt
427234949Sbapt    if (iflag)
428234949Sbapt    {
429234949Sbapt	CREATE_FILE_NAME(externs_file_name, externs_suffix);
430234949Sbapt    }
431234949Sbapt
432234949Sbapt    if (vflag)
433234949Sbapt    {
434234949Sbapt	CREATE_FILE_NAME(verbose_file_name, VERBOSE_SUFFIX);
435234949Sbapt    }
436234949Sbapt
437234949Sbapt    if (gflag)
438234949Sbapt    {
439234949Sbapt	CREATE_FILE_NAME(graph_file_name, GRAPH_SUFFIX);
440234949Sbapt    }
441234949Sbapt
442234949Sbapt    if (prefix != NULL)
443234949Sbapt    {
444234949Sbapt	FREE(file_prefix);
445234949Sbapt    }
446234949Sbapt}
447234949Sbapt
448234949Sbapt#if USE_MKSTEMP
449234949Sbaptstatic void
450234949Sbaptclose_tmpfiles(void)
451234949Sbapt{
452234949Sbapt    while (my_tmpfiles != 0)
453234949Sbapt    {
454234949Sbapt	MY_TMPFILES *next = my_tmpfiles->next;
455234949Sbapt
456234949Sbapt	chmod(my_tmpfiles->name, 0644);
457234949Sbapt	unlink(my_tmpfiles->name);
458234949Sbapt
459234949Sbapt	free(my_tmpfiles->name);
460234949Sbapt	free(my_tmpfiles);
461234949Sbapt
462234949Sbapt	my_tmpfiles = next;
463234949Sbapt    }
464234949Sbapt}
465234949Sbapt
466234949Sbapt#ifndef HAVE_MKSTEMP
467234949Sbaptstatic int
468234949Sbaptmy_mkstemp(char *temp)
469234949Sbapt{
470234949Sbapt    int fd;
471234949Sbapt    char *dname;
472234949Sbapt    char *fname;
473234949Sbapt    char *name;
474234949Sbapt
475234949Sbapt    /*
476234949Sbapt     * Split-up to use tempnam, rather than tmpnam; the latter (like
477234949Sbapt     * mkstemp) is unusable on Windows.
478234949Sbapt     */
479234949Sbapt    if ((fname = strrchr(temp, '/')) != 0)
480234949Sbapt    {
481234949Sbapt	dname = strdup(temp);
482234949Sbapt	dname[++fname - temp] = '\0';
483234949Sbapt    }
484234949Sbapt    else
485234949Sbapt    {
486234949Sbapt	dname = 0;
487234949Sbapt	fname = temp;
488234949Sbapt    }
489234949Sbapt    if ((name = tempnam(dname, fname)) != 0)
490234949Sbapt    {
491234949Sbapt	fd = open(name, O_CREAT | O_EXCL | O_RDWR);
492234949Sbapt	strcpy(temp, name);
493234949Sbapt    }
494234949Sbapt    else
495234949Sbapt    {
496234949Sbapt	fd = -1;
497234949Sbapt    }
498234949Sbapt
499234949Sbapt    if (dname != 0)
500234949Sbapt	free(dname);
501234949Sbapt
502234949Sbapt    return fd;
503234949Sbapt}
504234949Sbapt#define mkstemp(s) my_mkstemp(s)
505234949Sbapt#endif
506234949Sbapt
507234949Sbapt#endif
508234949Sbapt
509234949Sbapt/*
510234949Sbapt * tmpfile() should be adequate, except that it may require special privileges
511234949Sbapt * to use, e.g., MinGW and Windows 7 where it tries to use the root directory.
512234949Sbapt */
513234949Sbaptstatic FILE *
514234949Sbaptopen_tmpfile(const char *label)
515234949Sbapt{
516234949Sbapt    FILE *result;
517234949Sbapt#if USE_MKSTEMP
518234949Sbapt    int fd;
519234949Sbapt    const char *tmpdir;
520234949Sbapt    char *name;
521234949Sbapt    const char *mark;
522234949Sbapt
523234949Sbapt    if ((tmpdir = getenv("TMPDIR")) == 0 || access(tmpdir, W_OK) != 0)
524234949Sbapt    {
525234949Sbapt#ifdef P_tmpdir
526234949Sbapt	tmpdir = P_tmpdir;
527234949Sbapt#else
528234949Sbapt	tmpdir = "/tmp";
529234949Sbapt#endif
530234949Sbapt	if (access(tmpdir, W_OK) != 0)
531234949Sbapt	    tmpdir = ".";
532234949Sbapt    }
533234949Sbapt
534234949Sbapt    name = malloc(strlen(tmpdir) + 10 + strlen(label));
535234949Sbapt
536234949Sbapt    result = 0;
537234949Sbapt    if (name != 0)
538234949Sbapt    {
539234949Sbapt	if ((mark = strrchr(label, '_')) == 0)
540234949Sbapt	    mark = label + strlen(label);
541234949Sbapt
542234949Sbapt	sprintf(name, "%s/%.*sXXXXXX", tmpdir, (int)(mark - label), label);
543234949Sbapt	fd = mkstemp(name);
544234949Sbapt	if (fd >= 0)
545234949Sbapt	{
546234949Sbapt	    result = fdopen(fd, "w+");
547234949Sbapt	    if (result != 0)
548234949Sbapt	    {
549234949Sbapt		MY_TMPFILES *item;
550234949Sbapt
551234949Sbapt		if (my_tmpfiles == 0)
552234949Sbapt		{
553234949Sbapt		    atexit(close_tmpfiles);
554234949Sbapt		}
555234949Sbapt
556234949Sbapt		item = NEW(MY_TMPFILES);
557234949Sbapt		NO_SPACE(item);
558234949Sbapt
559234949Sbapt		item->name = name;
560234949Sbapt		NO_SPACE(item->name);
561234949Sbapt
562234949Sbapt		item->next = my_tmpfiles;
563234949Sbapt		my_tmpfiles = item;
564234949Sbapt	    }
565234949Sbapt	}
566234949Sbapt    }
567234949Sbapt#else
568234949Sbapt    result = tmpfile();
569234949Sbapt#endif
570234949Sbapt
571234949Sbapt    if (result == 0)
572234949Sbapt	open_error(label);
573234949Sbapt    return result;
574234949Sbapt}
575234949Sbapt
576234949Sbaptstatic void
577234949Sbaptopen_files(void)
578234949Sbapt{
579234949Sbapt    create_file_names();
580234949Sbapt
581234949Sbapt    if (input_file == 0)
582234949Sbapt    {
583234949Sbapt	input_file = fopen(input_file_name, "r");
584234949Sbapt	if (input_file == 0)
585234949Sbapt	    open_error(input_file_name);
586234949Sbapt    }
587234949Sbapt
588234949Sbapt    action_file = open_tmpfile("action_file");
589234949Sbapt    text_file = open_tmpfile("text_file");
590234949Sbapt
591234949Sbapt    if (vflag)
592234949Sbapt    {
593234949Sbapt	verbose_file = fopen(verbose_file_name, "w");
594234949Sbapt	if (verbose_file == 0)
595234949Sbapt	    open_error(verbose_file_name);
596234949Sbapt    }
597234949Sbapt
598234949Sbapt    if (gflag)
599234949Sbapt    {
600234949Sbapt	graph_file = fopen(graph_file_name, "w");
601234949Sbapt	if (graph_file == 0)
602234949Sbapt	    open_error(graph_file_name);
603234949Sbapt	fprintf(graph_file, "digraph %s {\n", file_prefix);
604234949Sbapt	fprintf(graph_file, "\tedge [fontsize=10];\n");
605234949Sbapt	fprintf(graph_file, "\tnode [shape=box,fontsize=10];\n");
606234949Sbapt	fprintf(graph_file, "\torientation=landscape;\n");
607234949Sbapt	fprintf(graph_file, "\trankdir=LR;\n");
608234949Sbapt	fprintf(graph_file, "\t/*\n");
609234949Sbapt	fprintf(graph_file, "\tmargin=0.2;\n");
610234949Sbapt	fprintf(graph_file, "\tpage=\"8.27,11.69\"; // for A4 printing\n");
611234949Sbapt	fprintf(graph_file, "\tratio=auto;\n");
612234949Sbapt	fprintf(graph_file, "\t*/\n");
613234949Sbapt    }
614234949Sbapt
615234949Sbapt    if (dflag)
616234949Sbapt    {
617234949Sbapt	defines_file = fopen(defines_file_name, "w");
618234949Sbapt	if (defines_file == 0)
619234949Sbapt	    open_error(defines_file_name);
620234949Sbapt	union_file = open_tmpfile("union_file");
621234949Sbapt    }
622234949Sbapt
623234949Sbapt    if (iflag)
624234949Sbapt    {
625234949Sbapt	externs_file = fopen(externs_file_name, "w");
626234949Sbapt	if (externs_file == 0)
627234949Sbapt	    open_error(externs_file_name);
628234949Sbapt    }
629234949Sbapt
630234949Sbapt    output_file = fopen(output_file_name, "w");
631234949Sbapt    if (output_file == 0)
632234949Sbapt	open_error(output_file_name);
633234949Sbapt
634234949Sbapt    if (rflag)
635234949Sbapt    {
636234949Sbapt	code_file = fopen(code_file_name, "w");
637234949Sbapt	if (code_file == 0)
638234949Sbapt	    open_error(code_file_name);
639234949Sbapt    }
640234949Sbapt    else
641234949Sbapt	code_file = output_file;
642234949Sbapt}
643234949Sbapt
644234949Sbaptint
645234949Sbaptmain(int argc, char *argv[])
646234949Sbapt{
647234949Sbapt    SRexpect = -1;
648234949Sbapt    RRexpect = -1;
649234949Sbapt    exit_code = EXIT_SUCCESS;
650234949Sbapt
651234949Sbapt    set_signals();
652234949Sbapt    getargs(argc, argv);
653234949Sbapt    open_files();
654234949Sbapt    reader();
655234949Sbapt    lr0();
656234949Sbapt    lalr();
657234949Sbapt    make_parser();
658234949Sbapt    graph();
659234949Sbapt    finalize_closure();
660234949Sbapt    verbose();
661234949Sbapt    output();
662234949Sbapt    done(exit_code);
663234949Sbapt    /*NOTREACHED */
664234949Sbapt}
665