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