1319349Sjkim/* $Id: main.c,v 1.59 2017/02/02 00:44:38 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 default_file_prefix[] = "y"; 52234949Sbapt 53234949Sbaptstatic char *file_prefix = default_file_prefix; 54234949Sbapt 55234949Sbaptchar *code_file_name; 56319349Sjkimchar *input_file_name; 57319349Sjkimsize_t input_file_name_len = 0; 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; 95319297Sdelphijint error_verbose; 96264803Sbapt 97264803Sbapt#if defined(YYBTYACC) 98264803SbaptValue_t *symbol_pval; 99264803Sbaptchar **symbol_destructor; 100264803Sbaptchar **symbol_type_tag; 101264803Sbaptint locations = 0; /* default to no position processing */ 102264803Sbaptint backtrack = 0; /* default is no backtracking */ 103319297Sdelphijchar *initial_action = NULL; 104264803Sbapt#endif 105264803Sbapt 106234949Sbaptint exit_code; 107234949Sbapt 108234949SbaptValue_t *ritem; 109234949SbaptValue_t *rlhs; 110234949SbaptValue_t *rrhs; 111234949SbaptValue_t *rprec; 112234949SbaptAssoc_t *rassoc; 113234949SbaptValue_t **derives; 114234949Sbaptchar *nullable; 115234949Sbapt 116234949Sbapt/* 117234949Sbapt * Since fclose() is called via the signal handler, it might die. Don't loop 118234949Sbapt * if there is a problem closing a file. 119234949Sbapt */ 120234949Sbapt#define DO_CLOSE(fp) \ 121234949Sbapt if (fp != 0) { \ 122234949Sbapt FILE *use = fp; \ 123234949Sbapt fp = 0; \ 124234949Sbapt fclose(use); \ 125234949Sbapt } 126234949Sbapt 127234949Sbaptstatic int got_intr = 0; 128234949Sbapt 129234949Sbaptvoid 130234949Sbaptdone(int k) 131234949Sbapt{ 132234949Sbapt DO_CLOSE(input_file); 133234949Sbapt DO_CLOSE(output_file); 134264803Sbapt if (iflag) 135264803Sbapt DO_CLOSE(externs_file); 136264803Sbapt if (rflag) 137264803Sbapt DO_CLOSE(code_file); 138234949Sbapt 139234949Sbapt DO_CLOSE(action_file); 140234949Sbapt DO_CLOSE(defines_file); 141234949Sbapt DO_CLOSE(graph_file); 142234949Sbapt DO_CLOSE(text_file); 143234949Sbapt DO_CLOSE(union_file); 144234949Sbapt DO_CLOSE(verbose_file); 145234949Sbapt 146234949Sbapt if (got_intr) 147234949Sbapt _exit(EXIT_FAILURE); 148234949Sbapt 149234949Sbapt#ifdef NO_LEAKS 150234949Sbapt if (rflag) 151234949Sbapt DO_FREE(code_file_name); 152234949Sbapt 153234949Sbapt if (dflag) 154234949Sbapt DO_FREE(defines_file_name); 155234949Sbapt 156234949Sbapt if (iflag) 157234949Sbapt DO_FREE(externs_file_name); 158234949Sbapt 159234949Sbapt if (oflag) 160234949Sbapt DO_FREE(output_file_name); 161234949Sbapt 162234949Sbapt if (vflag) 163234949Sbapt DO_FREE(verbose_file_name); 164234949Sbapt 165234949Sbapt if (gflag) 166234949Sbapt DO_FREE(graph_file_name); 167234949Sbapt 168234949Sbapt lr0_leaks(); 169234949Sbapt lalr_leaks(); 170234949Sbapt mkpar_leaks(); 171266639Sbapt mstring_leaks(); 172234949Sbapt output_leaks(); 173234949Sbapt reader_leaks(); 174234949Sbapt#endif 175234949Sbapt 176234949Sbapt exit(k); 177234949Sbapt} 178234949Sbapt 179234949Sbaptstatic void 180240517Sbaptonintr(int sig GCC_UNUSED) 181234949Sbapt{ 182234949Sbapt got_intr = 1; 183234949Sbapt done(EXIT_FAILURE); 184234949Sbapt} 185234949Sbapt 186234949Sbaptstatic void 187234949Sbaptset_signals(void) 188234949Sbapt{ 189234949Sbapt#ifdef SIGINT 190234949Sbapt if (signal(SIGINT, SIG_IGN) != SIG_IGN) 191234949Sbapt signal(SIGINT, onintr); 192234949Sbapt#endif 193234949Sbapt#ifdef SIGTERM 194234949Sbapt if (signal(SIGTERM, SIG_IGN) != SIG_IGN) 195234949Sbapt signal(SIGTERM, onintr); 196234949Sbapt#endif 197234949Sbapt#ifdef SIGHUP 198234949Sbapt if (signal(SIGHUP, SIG_IGN) != SIG_IGN) 199234949Sbapt signal(SIGHUP, onintr); 200234949Sbapt#endif 201234949Sbapt} 202234949Sbapt 203234949Sbaptstatic void 204234949Sbaptusage(void) 205234949Sbapt{ 206234949Sbapt static const char *msg[] = 207234949Sbapt { 208234949Sbapt "" 209234949Sbapt ,"Options:" 210234949Sbapt ," -b file_prefix set filename prefix (default \"y.\")" 211264803Sbapt ," -B create a backtracking parser" 212264803Sbapt ," -d write definitions (" DEFINES_SUFFIX ")" 213234949Sbapt ," -i write interface (y.tab.i)" 214234949Sbapt ," -g write a graphical description" 215234949Sbapt ," -l suppress #line directives" 216264803Sbapt ," -L enable position processing, e.g., \"%locations\"" 217264803Sbapt ," -o output_file (default \"" OUTPUT_SUFFIX "\")" 218234949Sbapt ," -p symbol_prefix set symbol prefix (default \"yy\")" 219234949Sbapt ," -P create a reentrant parser, e.g., \"%pure-parser\"" 220234949Sbapt ," -r produce separate code and table files (y.code.c)" 221234949Sbapt ," -s suppress #define's for quoted names in %token lines" 222234949Sbapt ," -t add debugging support" 223234949Sbapt ," -v write description (y.output)" 224234949Sbapt ," -V show version information and exit" 225234949Sbapt }; 226234949Sbapt unsigned n; 227234949Sbapt 228234949Sbapt fflush(stdout); 229234949Sbapt fprintf(stderr, "Usage: %s [options] filename\n", myname); 230234949Sbapt for (n = 0; n < sizeof(msg) / sizeof(msg[0]); ++n) 231234949Sbapt fprintf(stderr, "%s\n", msg[n]); 232234949Sbapt 233234949Sbapt exit(1); 234234949Sbapt} 235234949Sbapt 236234949Sbaptstatic void 237234949Sbaptsetflag(int ch) 238234949Sbapt{ 239234949Sbapt switch (ch) 240234949Sbapt { 241264803Sbapt case 'B': 242264803Sbapt#if defined(YYBTYACC) 243264803Sbapt backtrack = 1; 244264803Sbapt#else 245264803Sbapt unsupported_flag_warning("-B", "reconfigure with --enable-btyacc"); 246264803Sbapt#endif 247264803Sbapt break; 248264803Sbapt 249234949Sbapt case 'd': 250234949Sbapt dflag = 1; 251234949Sbapt break; 252234949Sbapt 253234949Sbapt case 'g': 254234949Sbapt gflag = 1; 255234949Sbapt break; 256234949Sbapt 257234949Sbapt case 'i': 258234949Sbapt iflag = 1; 259234949Sbapt break; 260234949Sbapt 261234949Sbapt case 'l': 262234949Sbapt lflag = 1; 263234949Sbapt break; 264234949Sbapt 265264803Sbapt case 'L': 266264803Sbapt#if defined(YYBTYACC) 267264803Sbapt locations = 1; 268264803Sbapt#else 269264803Sbapt unsupported_flag_warning("-B", "reconfigure with --enable-btyacc"); 270264803Sbapt#endif 271264803Sbapt break; 272264803Sbapt 273234949Sbapt case 'P': 274234949Sbapt pure_parser = 1; 275234949Sbapt break; 276234949Sbapt 277234949Sbapt case 'r': 278234949Sbapt rflag = 1; 279234949Sbapt break; 280234949Sbapt 281234949Sbapt case 's': 282234949Sbapt sflag = 1; 283234949Sbapt break; 284234949Sbapt 285234949Sbapt case 't': 286234949Sbapt tflag = 1; 287234949Sbapt break; 288234949Sbapt 289234949Sbapt case 'v': 290234949Sbapt vflag = 1; 291234949Sbapt break; 292234949Sbapt 293234949Sbapt case 'V': 294234949Sbapt printf("%s - %s\n", myname, VERSION); 295234949Sbapt exit(EXIT_SUCCESS); 296234949Sbapt 297234949Sbapt case 'y': 298234949Sbapt /* noop for bison compatibility. byacc is already designed to be posix 299234949Sbapt * yacc compatible. */ 300234949Sbapt break; 301234949Sbapt 302234949Sbapt default: 303234949Sbapt usage(); 304234949Sbapt } 305234949Sbapt} 306234949Sbapt 307234949Sbaptstatic void 308234949Sbaptgetargs(int argc, char *argv[]) 309234949Sbapt{ 310234949Sbapt int i; 311234949Sbapt char *s; 312234949Sbapt int ch; 313234949Sbapt 314234949Sbapt if (argc > 0) 315234949Sbapt myname = argv[0]; 316234949Sbapt 317234949Sbapt for (i = 1; i < argc; ++i) 318234949Sbapt { 319234949Sbapt s = argv[i]; 320234949Sbapt if (*s != '-') 321234949Sbapt break; 322234949Sbapt switch (ch = *++s) 323234949Sbapt { 324234949Sbapt case '\0': 325234949Sbapt input_file = stdin; 326234949Sbapt if (i + 1 < argc) 327234949Sbapt usage(); 328234949Sbapt return; 329234949Sbapt 330234949Sbapt case '-': 331234949Sbapt ++i; 332234949Sbapt goto no_more_options; 333234949Sbapt 334234949Sbapt case 'b': 335234949Sbapt if (*++s) 336234949Sbapt file_prefix = s; 337234949Sbapt else if (++i < argc) 338234949Sbapt file_prefix = argv[i]; 339234949Sbapt else 340234949Sbapt usage(); 341234949Sbapt continue; 342234949Sbapt 343234949Sbapt case 'o': 344234949Sbapt if (*++s) 345234949Sbapt output_file_name = s; 346234949Sbapt else if (++i < argc) 347234949Sbapt output_file_name = argv[i]; 348234949Sbapt else 349234949Sbapt usage(); 350234949Sbapt continue; 351234949Sbapt 352234949Sbapt case 'p': 353234949Sbapt if (*++s) 354234949Sbapt symbol_prefix = s; 355234949Sbapt else if (++i < argc) 356234949Sbapt symbol_prefix = argv[i]; 357234949Sbapt else 358234949Sbapt usage(); 359234949Sbapt continue; 360234949Sbapt 361234949Sbapt default: 362234949Sbapt setflag(ch); 363234949Sbapt break; 364234949Sbapt } 365234949Sbapt 366234949Sbapt for (;;) 367234949Sbapt { 368234949Sbapt switch (ch = *++s) 369234949Sbapt { 370234949Sbapt case '\0': 371234949Sbapt goto end_of_option; 372234949Sbapt 373234949Sbapt default: 374234949Sbapt setflag(ch); 375234949Sbapt break; 376234949Sbapt } 377234949Sbapt } 378234949Sbapt end_of_option:; 379234949Sbapt } 380234949Sbapt 381234949Sbapt no_more_options:; 382234949Sbapt if (i + 1 != argc) 383234949Sbapt usage(); 384319349Sjkim input_file_name_len = strlen(argv[i]); 385319349Sjkim input_file_name = TMALLOC(char, input_file_name_len + 1); 386319349Sjkim NO_SPACE(input_file_name); 387319349Sjkim strcpy(input_file_name, argv[i]); 388234949Sbapt} 389234949Sbapt 390234949Sbaptvoid * 391234949Sbaptallocate(size_t n) 392234949Sbapt{ 393234949Sbapt void *p; 394234949Sbapt 395234949Sbapt p = NULL; 396234949Sbapt if (n) 397234949Sbapt { 398234949Sbapt p = CALLOC(1, n); 399234949Sbapt NO_SPACE(p); 400234949Sbapt } 401234949Sbapt return (p); 402234949Sbapt} 403234949Sbapt 404234949Sbapt#define CREATE_FILE_NAME(dest, suffix) \ 405264803Sbapt dest = alloc_file_name(len, suffix) 406234949Sbapt 407264803Sbaptstatic char * 408264803Sbaptalloc_file_name(size_t len, const char *suffix) 409264803Sbapt{ 410264803Sbapt char *result = TMALLOC(char, len + strlen(suffix) + 1); 411264803Sbapt if (result == 0) 412264803Sbapt no_space(); 413264803Sbapt strcpy(result, file_prefix); 414264803Sbapt strcpy(result + len, suffix); 415264803Sbapt return result; 416264803Sbapt} 417264803Sbapt 418297276Sjkimstatic char * 419297276Sjkimfind_suffix(char *name, const char *suffix) 420297276Sjkim{ 421297276Sjkim size_t len = strlen(name); 422297276Sjkim size_t slen = strlen(suffix); 423297276Sjkim if (len >= slen) 424297276Sjkim { 425297276Sjkim name += len - slen; 426297276Sjkim if (strcmp(name, suffix) == 0) 427297276Sjkim return name; 428297276Sjkim } 429297276Sjkim return NULL; 430297276Sjkim} 431297276Sjkim 432234949Sbaptstatic void 433234949Sbaptcreate_file_names(void) 434234949Sbapt{ 435234949Sbapt size_t len; 436234949Sbapt const char *defines_suffix; 437234949Sbapt const char *externs_suffix; 438297276Sjkim char *suffix; 439234949Sbapt 440297276Sjkim suffix = NULL; 441234949Sbapt defines_suffix = DEFINES_SUFFIX; 442234949Sbapt externs_suffix = EXTERNS_SUFFIX; 443234949Sbapt 444234949Sbapt /* compute the file_prefix from the user provided output_file_name */ 445234949Sbapt if (output_file_name != 0) 446234949Sbapt { 447297276Sjkim if (!(suffix = find_suffix(output_file_name, OUTPUT_SUFFIX)) 448297276Sjkim && (suffix = find_suffix(output_file_name, ".c"))) 449234949Sbapt { 450234949Sbapt defines_suffix = ".h"; 451234949Sbapt externs_suffix = ".i"; 452234949Sbapt } 453234949Sbapt } 454234949Sbapt 455297276Sjkim if (suffix != NULL) 456234949Sbapt { 457297276Sjkim len = (size_t) (suffix - output_file_name); 458240517Sbapt file_prefix = TMALLOC(char, len + 1); 459234949Sbapt NO_SPACE(file_prefix); 460234949Sbapt strncpy(file_prefix, output_file_name, len)[len] = 0; 461234949Sbapt } 462234949Sbapt else 463234949Sbapt len = strlen(file_prefix); 464234949Sbapt 465234949Sbapt /* if "-o filename" was not given */ 466234949Sbapt if (output_file_name == 0) 467234949Sbapt { 468234949Sbapt oflag = 1; 469234949Sbapt CREATE_FILE_NAME(output_file_name, OUTPUT_SUFFIX); 470234949Sbapt } 471234949Sbapt 472234949Sbapt if (rflag) 473234949Sbapt { 474234949Sbapt CREATE_FILE_NAME(code_file_name, CODE_SUFFIX); 475234949Sbapt } 476234949Sbapt else 477234949Sbapt code_file_name = output_file_name; 478234949Sbapt 479234949Sbapt if (dflag) 480234949Sbapt { 481234949Sbapt CREATE_FILE_NAME(defines_file_name, defines_suffix); 482234949Sbapt } 483234949Sbapt 484234949Sbapt if (iflag) 485234949Sbapt { 486234949Sbapt CREATE_FILE_NAME(externs_file_name, externs_suffix); 487234949Sbapt } 488234949Sbapt 489234949Sbapt if (vflag) 490234949Sbapt { 491234949Sbapt CREATE_FILE_NAME(verbose_file_name, VERBOSE_SUFFIX); 492234949Sbapt } 493234949Sbapt 494234949Sbapt if (gflag) 495234949Sbapt { 496234949Sbapt CREATE_FILE_NAME(graph_file_name, GRAPH_SUFFIX); 497234949Sbapt } 498234949Sbapt 499297276Sjkim if (suffix != NULL) 500234949Sbapt { 501234949Sbapt FREE(file_prefix); 502234949Sbapt } 503234949Sbapt} 504234949Sbapt 505234949Sbapt#if USE_MKSTEMP 506234949Sbaptstatic void 507234949Sbaptclose_tmpfiles(void) 508234949Sbapt{ 509234949Sbapt while (my_tmpfiles != 0) 510234949Sbapt { 511234949Sbapt MY_TMPFILES *next = my_tmpfiles->next; 512234949Sbapt 513272655Sbapt (void)chmod(my_tmpfiles->name, 0644); 514272655Sbapt (void)unlink(my_tmpfiles->name); 515234949Sbapt 516234949Sbapt free(my_tmpfiles->name); 517234949Sbapt free(my_tmpfiles); 518234949Sbapt 519234949Sbapt my_tmpfiles = next; 520234949Sbapt } 521234949Sbapt} 522234949Sbapt 523234949Sbapt#ifndef HAVE_MKSTEMP 524234949Sbaptstatic int 525234949Sbaptmy_mkstemp(char *temp) 526234949Sbapt{ 527234949Sbapt int fd; 528234949Sbapt char *dname; 529234949Sbapt char *fname; 530234949Sbapt char *name; 531234949Sbapt 532234949Sbapt /* 533234949Sbapt * Split-up to use tempnam, rather than tmpnam; the latter (like 534234949Sbapt * mkstemp) is unusable on Windows. 535234949Sbapt */ 536234949Sbapt if ((fname = strrchr(temp, '/')) != 0) 537234949Sbapt { 538234949Sbapt dname = strdup(temp); 539234949Sbapt dname[++fname - temp] = '\0'; 540234949Sbapt } 541234949Sbapt else 542234949Sbapt { 543234949Sbapt dname = 0; 544234949Sbapt fname = temp; 545234949Sbapt } 546234949Sbapt if ((name = tempnam(dname, fname)) != 0) 547234949Sbapt { 548234949Sbapt fd = open(name, O_CREAT | O_EXCL | O_RDWR); 549234949Sbapt strcpy(temp, name); 550234949Sbapt } 551234949Sbapt else 552234949Sbapt { 553234949Sbapt fd = -1; 554234949Sbapt } 555234949Sbapt 556234949Sbapt if (dname != 0) 557234949Sbapt free(dname); 558234949Sbapt 559234949Sbapt return fd; 560234949Sbapt} 561234949Sbapt#define mkstemp(s) my_mkstemp(s) 562234949Sbapt#endif 563234949Sbapt 564234949Sbapt#endif 565234949Sbapt 566234949Sbapt/* 567234949Sbapt * tmpfile() should be adequate, except that it may require special privileges 568234949Sbapt * to use, e.g., MinGW and Windows 7 where it tries to use the root directory. 569234949Sbapt */ 570234949Sbaptstatic FILE * 571234949Sbaptopen_tmpfile(const char *label) 572234949Sbapt{ 573296240Sjkim#define MY_FMT "%s/%.*sXXXXXX" 574234949Sbapt FILE *result; 575234949Sbapt#if USE_MKSTEMP 576234949Sbapt int fd; 577234949Sbapt const char *tmpdir; 578234949Sbapt char *name; 579234949Sbapt const char *mark; 580234949Sbapt 581234949Sbapt if ((tmpdir = getenv("TMPDIR")) == 0 || access(tmpdir, W_OK) != 0) 582234949Sbapt { 583234949Sbapt#ifdef P_tmpdir 584234949Sbapt tmpdir = P_tmpdir; 585234949Sbapt#else 586234949Sbapt tmpdir = "/tmp"; 587234949Sbapt#endif 588234949Sbapt if (access(tmpdir, W_OK) != 0) 589234949Sbapt tmpdir = "."; 590234949Sbapt } 591234949Sbapt 592296240Sjkim /* The size of the format is guaranteed to be longer than the result from 593296240Sjkim * printing empty strings with it; this calculation accounts for the 594296240Sjkim * string-lengths as well. 595296240Sjkim */ 596296240Sjkim name = malloc(strlen(tmpdir) + sizeof(MY_FMT) + strlen(label)); 597234949Sbapt 598234949Sbapt result = 0; 599234949Sbapt if (name != 0) 600234949Sbapt { 601272769Sbapt mode_t save_umask = umask(0177); 602272655Sbapt 603234949Sbapt if ((mark = strrchr(label, '_')) == 0) 604234949Sbapt mark = label + strlen(label); 605234949Sbapt 606296240Sjkim sprintf(name, MY_FMT, tmpdir, (int)(mark - label), label); 607234949Sbapt fd = mkstemp(name); 608234949Sbapt if (fd >= 0) 609234949Sbapt { 610234949Sbapt result = fdopen(fd, "w+"); 611234949Sbapt if (result != 0) 612234949Sbapt { 613234949Sbapt MY_TMPFILES *item; 614234949Sbapt 615234949Sbapt if (my_tmpfiles == 0) 616234949Sbapt { 617234949Sbapt atexit(close_tmpfiles); 618234949Sbapt } 619234949Sbapt 620234949Sbapt item = NEW(MY_TMPFILES); 621234949Sbapt NO_SPACE(item); 622234949Sbapt 623234949Sbapt item->name = name; 624234949Sbapt NO_SPACE(item->name); 625234949Sbapt 626234949Sbapt item->next = my_tmpfiles; 627234949Sbapt my_tmpfiles = item; 628234949Sbapt } 629234949Sbapt } 630272655Sbapt (void)umask(save_umask); 631234949Sbapt } 632234949Sbapt#else 633234949Sbapt result = tmpfile(); 634234949Sbapt#endif 635234949Sbapt 636234949Sbapt if (result == 0) 637234949Sbapt open_error(label); 638234949Sbapt return result; 639296240Sjkim#undef MY_FMT 640234949Sbapt} 641234949Sbapt 642234949Sbaptstatic void 643234949Sbaptopen_files(void) 644234949Sbapt{ 645234949Sbapt create_file_names(); 646234949Sbapt 647234949Sbapt if (input_file == 0) 648234949Sbapt { 649234949Sbapt input_file = fopen(input_file_name, "r"); 650234949Sbapt if (input_file == 0) 651234949Sbapt open_error(input_file_name); 652234949Sbapt } 653234949Sbapt 654234949Sbapt action_file = open_tmpfile("action_file"); 655234949Sbapt text_file = open_tmpfile("text_file"); 656234949Sbapt 657234949Sbapt if (vflag) 658234949Sbapt { 659234949Sbapt verbose_file = fopen(verbose_file_name, "w"); 660234949Sbapt if (verbose_file == 0) 661234949Sbapt open_error(verbose_file_name); 662234949Sbapt } 663234949Sbapt 664234949Sbapt if (gflag) 665234949Sbapt { 666234949Sbapt graph_file = fopen(graph_file_name, "w"); 667234949Sbapt if (graph_file == 0) 668234949Sbapt open_error(graph_file_name); 669234949Sbapt fprintf(graph_file, "digraph %s {\n", file_prefix); 670234949Sbapt fprintf(graph_file, "\tedge [fontsize=10];\n"); 671234949Sbapt fprintf(graph_file, "\tnode [shape=box,fontsize=10];\n"); 672234949Sbapt fprintf(graph_file, "\torientation=landscape;\n"); 673234949Sbapt fprintf(graph_file, "\trankdir=LR;\n"); 674234949Sbapt fprintf(graph_file, "\t/*\n"); 675234949Sbapt fprintf(graph_file, "\tmargin=0.2;\n"); 676234949Sbapt fprintf(graph_file, "\tpage=\"8.27,11.69\"; // for A4 printing\n"); 677234949Sbapt fprintf(graph_file, "\tratio=auto;\n"); 678234949Sbapt fprintf(graph_file, "\t*/\n"); 679234949Sbapt } 680234949Sbapt 681234949Sbapt if (dflag) 682234949Sbapt { 683234949Sbapt defines_file = fopen(defines_file_name, "w"); 684234949Sbapt if (defines_file == 0) 685234949Sbapt open_error(defines_file_name); 686234949Sbapt union_file = open_tmpfile("union_file"); 687234949Sbapt } 688234949Sbapt 689234949Sbapt if (iflag) 690234949Sbapt { 691234949Sbapt externs_file = fopen(externs_file_name, "w"); 692234949Sbapt if (externs_file == 0) 693234949Sbapt open_error(externs_file_name); 694234949Sbapt } 695234949Sbapt 696234949Sbapt output_file = fopen(output_file_name, "w"); 697234949Sbapt if (output_file == 0) 698234949Sbapt open_error(output_file_name); 699234949Sbapt 700234949Sbapt if (rflag) 701234949Sbapt { 702234949Sbapt code_file = fopen(code_file_name, "w"); 703234949Sbapt if (code_file == 0) 704234949Sbapt open_error(code_file_name); 705234949Sbapt } 706234949Sbapt else 707234949Sbapt code_file = output_file; 708234949Sbapt} 709234949Sbapt 710234949Sbaptint 711234949Sbaptmain(int argc, char *argv[]) 712234949Sbapt{ 713234949Sbapt SRexpect = -1; 714234949Sbapt RRexpect = -1; 715234949Sbapt exit_code = EXIT_SUCCESS; 716234949Sbapt 717234949Sbapt set_signals(); 718234949Sbapt getargs(argc, argv); 719234949Sbapt open_files(); 720234949Sbapt reader(); 721234949Sbapt lr0(); 722234949Sbapt lalr(); 723234949Sbapt make_parser(); 724234949Sbapt graph(); 725234949Sbapt finalize_closure(); 726234949Sbapt verbose(); 727234949Sbapt output(); 728234949Sbapt done(exit_code); 729234949Sbapt /*NOTREACHED */ 730234949Sbapt} 731