1 /* $OpenBSD: main.c,v 1.18 2003/06/19 16:34:53 pvalchev Exp $ */ 2 /* $NetBSD: main.c,v 1.5 1996/03/19 03:21:38 jtc Exp $ */ 3 4 /* 5 * Copyright (c) 1989 The Regents of the University of California. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Robert Paul Corbett. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #ifndef lint 37 char copyright[] = 38 "@(#) Copyright (c) 1989 The Regents of the University of California.\n\ 39 All rights reserved.\n"; 40 #endif /* not lint */ 41 42 #ifndef lint 43 #if 0 44 static char sccsid[] = "@(#)main.c 5.5 (Berkeley) 5/24/93"; 45 #else 46 static char rcsid[] = "$OpenBSD: main.c,v 1.18 2003/06/19 16:34:53 pvalchev Exp $"; 47 #endif 48 #endif /* not lint */ 49 50 #include <sys/types.h> 51 #include <fcntl.h> 52 #include <paths.h> 53 #include <signal.h> 54 #include <stdlib.h> 55 #include <unistd.h> 56 #include "defs.h" 57 58 char dflag; 59 char lflag; 60 char rflag; 61 char tflag; 62 char vflag; 63 64 char *symbol_prefix; 65 char *file_prefix = "y"; 66 67 int lineno; 68 int outline; 69 70 int explicit_file_name; 71 72 char *action_file_name; 73 char *code_file_name; 74 char *defines_file_name; 75 char *input_file_name = ""; 76 char *output_file_name; 77 char *text_file_name; 78 char *union_file_name; 79 char *verbose_file_name; 80 81 FILE *action_file; /* a temp file, used to save actions associated */ 82 /* with rules until the parser is written */ 83 FILE *code_file; /* y.code.c (used when the -r option is specified) */ 84 FILE *defines_file; /* y.tab.h */ 85 FILE *input_file; /* the input file */ 86 FILE *output_file; /* y.tab.c */ 87 FILE *text_file; /* a temp file, used to save text until all */ 88 /* symbols have been defined */ 89 FILE *union_file; /* a temp file, used to save the union */ 90 /* definition until all symbol have been */ 91 /* defined */ 92 FILE *verbose_file; /* y.output */ 93 94 int nitems; 95 int nrules; 96 int nsyms; 97 int ntokens; 98 int nvars; 99 100 int start_symbol; 101 char **symbol_name; 102 short *symbol_value; 103 short *symbol_prec; 104 char *symbol_assoc; 105 106 short *ritem; 107 short *rlhs; 108 short *rrhs; 109 short *rprec; 110 char *rassoc; 111 short **derives; 112 char *nullable; 113 114 void onintr(int); 115 void set_signals(void); 116 void usage(void); 117 void getargs(int, char *[]); 118 void create_file_names(void); 119 void open_files(void); 120 121 volatile sig_atomic_t sigdie; 122 123 void 124 done(int k) 125 { 126 if (action_file) 127 unlink(action_file_name); 128 if (text_file) 129 unlink(text_file_name); 130 if (union_file) 131 unlink(union_file_name); 132 if (sigdie) 133 _exit(k); 134 exit(k); 135 } 136 137 138 void 139 onintr(int signo) 140 { 141 sigdie = 1; 142 done(1); 143 } 144 145 146 void 147 set_signals(void) 148 { 149 #ifdef SIGINT 150 if (signal(SIGINT, SIG_IGN) != SIG_IGN) 151 signal(SIGINT, onintr); 152 #endif 153 #ifdef SIGTERM 154 if (signal(SIGTERM, SIG_IGN) != SIG_IGN) 155 signal(SIGTERM, onintr); 156 #endif 157 #ifdef SIGHUP 158 if (signal(SIGHUP, SIG_IGN) != SIG_IGN) 159 signal(SIGHUP, onintr); 160 #endif 161 } 162 163 164 void 165 usage(void) 166 { 167 fprintf(stderr, "usage: %s [-dlrtv] [-b file_prefix] [-o outputfile] [-p symbol_prefix] filename\n", __progname); 168 exit(1); 169 } 170 171 172 void 173 getargs(int argc, char *argv[]) 174 { 175 int i; 176 char *s; 177 178 for (i = 1; i < argc; ++i) 179 { 180 s = argv[i]; 181 if (*s != '-') break; 182 switch (*++s) 183 { 184 case '\0': 185 input_file = stdin; 186 if (i + 1 < argc) usage(); 187 return; 188 189 case '-': 190 ++i; 191 goto no_more_options; 192 193 case 'b': 194 if (*++s) 195 file_prefix = s; 196 else if (++i < argc) 197 file_prefix = argv[i]; 198 else 199 usage(); 200 continue; 201 202 case 'd': 203 dflag = 1; 204 break; 205 206 case 'l': 207 lflag = 1; 208 break; 209 210 case 'o': 211 if (*++s) 212 output_file_name = s; 213 else if (++i < argc) 214 output_file_name = argv[i]; 215 else 216 usage(); 217 explicit_file_name = 1; 218 continue; 219 220 case 'p': 221 if (*++s) 222 symbol_prefix = s; 223 else if (++i < argc) 224 symbol_prefix = argv[i]; 225 else 226 usage(); 227 continue; 228 229 case 'r': 230 rflag = 1; 231 break; 232 233 case 't': 234 tflag = 1; 235 break; 236 237 case 'v': 238 vflag = 1; 239 break; 240 241 default: 242 usage(); 243 } 244 245 for (;;) 246 { 247 switch (*++s) 248 { 249 case '\0': 250 goto end_of_option; 251 252 case 'd': 253 dflag = 1; 254 break; 255 256 case 'l': 257 lflag = 1; 258 break; 259 260 case 'r': 261 rflag = 1; 262 break; 263 264 case 't': 265 tflag = 1; 266 break; 267 268 case 'v': 269 vflag = 1; 270 break; 271 272 default: 273 usage(); 274 } 275 } 276 end_of_option:; 277 } 278 279 no_more_options:; 280 if (i + 1 != argc) usage(); 281 input_file_name = argv[i]; 282 } 283 284 285 char * 286 allocate(unsigned int n) 287 { 288 char *p; 289 290 p = NULL; 291 if (n) 292 { 293 p = CALLOC(1, n); 294 if (!p) no_space(); 295 } 296 return (p); 297 } 298 299 #define TEMPNAME(s, c, d, l) \ 300 (asprintf(&(s), "%.*s/yacc.%xXXXXXXXXXX", (int)(l), (d), (c))) 301 302 void 303 create_file_names(void) 304 { 305 size_t len; 306 char *tmpdir; 307 308 if ((tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0') 309 tmpdir = _PATH_TMP; 310 311 len = strlen(tmpdir); 312 if (tmpdir[len-1] == '/') 313 len--; 314 315 if (TEMPNAME(action_file_name, 'a', tmpdir, len) == -1 || 316 TEMPNAME(text_file_name, 'r', tmpdir, len) == -1 || 317 TEMPNAME(union_file_name, 'u', tmpdir, len) == -1) 318 no_space(); 319 320 if (output_file_name == NULL) 321 { 322 if (asprintf(&output_file_name, "%s%s", file_prefix, OUTPUT_SUFFIX) 323 == -1) 324 no_space(); 325 } 326 327 if (rflag) { 328 if (asprintf(&code_file_name, "%s%s", file_prefix, CODE_SUFFIX) == -1) 329 no_space(); 330 } else 331 code_file_name = output_file_name; 332 333 if (dflag) 334 { 335 if (explicit_file_name) 336 { 337 char *suffix; 338 339 defines_file_name = strdup(output_file_name); 340 if (defines_file_name == 0) 341 no_space(); 342 343 /* does the output_file_name have a known suffix */ 344 if ((suffix = strrchr(output_file_name, '.')) != 0 && 345 (!strcmp(suffix, ".c") || /* good, old-fashioned C */ 346 !strcmp(suffix, ".C") || /* C++, or C on Windows */ 347 !strcmp(suffix, ".cc") || /* C++ */ 348 !strcmp(suffix, ".cxx") || /* C++ */ 349 !strcmp(suffix, ".cpp"))) /* C++ (Windows) */ 350 { 351 strncpy(defines_file_name, output_file_name, 352 suffix - output_file_name + 1); 353 defines_file_name[suffix - output_file_name + 1] = 'h'; 354 defines_file_name[suffix - output_file_name + 2] = '\0'; 355 } else { 356 fprintf(stderr,"%s: suffix of output file name %s" 357 " not recognized, no -d file generated.\n", 358 __progname, output_file_name); 359 dflag = 0; 360 free(defines_file_name); 361 defines_file_name = 0; 362 } 363 } 364 else 365 { 366 if (asprintf(&defines_file_name, "%s%s", file_prefix, 367 DEFINES_SUFFIX) == -1) 368 no_space(); 369 } 370 } 371 372 if (vflag) 373 { 374 if (asprintf(&verbose_file_name, "%s%s", file_prefix, 375 VERBOSE_SUFFIX) == -1) 376 no_space(); 377 } 378 } 379 380 381 FILE * 382 fsopen(char *name, char *mode) 383 { 384 FILE *fp = NULL; 385 int fd, mod = O_RDONLY; 386 387 if (strchr(mode, 'w')) 388 mod = O_RDWR; 389 if ((fd = open(name, mod | O_EXCL|O_CREAT, 0666)) == -1 || 390 (fp = fdopen(fd, mode)) == NULL) { 391 if (fd != -1) 392 close(fd); 393 } 394 return (fp); 395 } 396 397 void 398 open_files(void) 399 { 400 int fd; 401 402 create_file_names(); 403 404 if (input_file == 0) 405 { 406 input_file = fopen(input_file_name, "r"); 407 if (input_file == 0) 408 open_error(input_file_name); 409 } 410 411 fd = mkstemp(action_file_name); 412 if (fd == -1 || (action_file = fdopen(fd, "w")) == NULL) 413 open_error(action_file_name); 414 415 fd = mkstemp(text_file_name); 416 if (fd == -1 || (text_file = fdopen(fd, "w")) == NULL) 417 open_error(text_file_name); 418 419 if (vflag) 420 { 421 verbose_file = fopen(verbose_file_name, "w"); 422 if (verbose_file == 0) 423 open_error(verbose_file_name); 424 } 425 426 if (dflag) 427 { 428 defines_file = fopen(defines_file_name, "w"); 429 if (defines_file == 0) 430 open_error(defines_file_name); 431 fd = mkstemp(union_file_name); 432 if (fd == -1 || (union_file = fdopen(fd, "w")) == NULL) 433 open_error(union_file_name); 434 } 435 436 output_file = fopen(output_file_name, "w"); 437 if (output_file == 0) 438 open_error(output_file_name); 439 440 if (rflag) 441 { 442 code_file = fopen(code_file_name, "w"); 443 if (code_file == 0) 444 open_error(code_file_name); 445 } 446 else 447 code_file = output_file; 448 } 449 450 451 int 452 main(int argc, char *argv[]) 453 { 454 set_signals(); 455 getargs(argc, argv); 456 open_files(); 457 reader(); 458 lr0(); 459 lalr(); 460 make_parser(); 461 verbose(); 462 output(); 463 done(0); 464 /*NOTREACHED*/ 465 return (0); 466 } 467