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