1 /* $OpenBSD: main.c,v 1.12 2001/07/16 06:29:44 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. 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.12 2001/07/16 06:29:44 pvalchev 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, register char *[])); 123 void create_file_names __P((void)); 124 void open_files __P((void)); 125 126 void 127 done(k) 128 int k; 129 { 130 if (action_file) { fclose(action_file); unlink(action_file_name); } 131 if (text_file) { fclose(text_file); unlink(text_file_name); } 132 if (union_file) { fclose(union_file); unlink(union_file_name); } 133 exit(k); 134 } 135 136 137 void 138 onintr(signo) 139 int signo; 140 { 141 done(1); /* XXX signal race */ 142 } 143 144 145 void 146 set_signals() 147 { 148 #ifdef SIGINT 149 if (signal(SIGINT, SIG_IGN) != SIG_IGN) 150 signal(SIGINT, onintr); 151 #endif 152 #ifdef SIGTERM 153 if (signal(SIGTERM, SIG_IGN) != SIG_IGN) 154 signal(SIGTERM, onintr); 155 #endif 156 #ifdef SIGHUP 157 if (signal(SIGHUP, SIG_IGN) != SIG_IGN) 158 signal(SIGHUP, onintr); 159 #endif 160 } 161 162 163 void 164 usage() 165 { 166 fprintf(stderr, "usage: %s [-dlrtv] [-b file_prefix] [-o outputfile] [-p symbol_prefix] filename\n", __progname); 167 exit(1); 168 } 169 170 171 void 172 getargs(argc, argv) 173 int argc; 174 char *argv[]; 175 { 176 register int i; 177 register char *s; 178 179 for (i = 1; i < argc; ++i) 180 { 181 s = argv[i]; 182 if (*s != '-') break; 183 switch (*++s) 184 { 185 case '\0': 186 input_file = stdin; 187 if (i + 1 < argc) usage(); 188 return; 189 190 case '-': 191 ++i; 192 goto no_more_options; 193 194 case 'b': 195 if (*++s) 196 file_prefix = s; 197 else if (++i < argc) 198 file_prefix = argv[i]; 199 else 200 usage(); 201 continue; 202 203 case 'd': 204 dflag = 1; 205 break; 206 207 case 'l': 208 lflag = 1; 209 break; 210 211 case 'o': 212 if (*++s) 213 output_file_name = s; 214 else if (++i < argc) 215 output_file_name = argv[i]; 216 else 217 usage(); 218 explicit_file_name = 1; 219 continue; 220 221 case 'p': 222 if (*++s) 223 symbol_prefix = s; 224 else if (++i < argc) 225 symbol_prefix = argv[i]; 226 else 227 usage(); 228 continue; 229 230 case 'r': 231 rflag = 1; 232 break; 233 234 case 't': 235 tflag = 1; 236 break; 237 238 case 'v': 239 vflag = 1; 240 break; 241 242 default: 243 usage(); 244 } 245 246 for (;;) 247 { 248 switch (*++s) 249 { 250 case '\0': 251 goto end_of_option; 252 253 case 'd': 254 dflag = 1; 255 break; 256 257 case 'l': 258 lflag = 1; 259 break; 260 261 case 'r': 262 rflag = 1; 263 break; 264 265 case 't': 266 tflag = 1; 267 break; 268 269 case 'v': 270 vflag = 1; 271 break; 272 273 default: 274 usage(); 275 } 276 } 277 end_of_option:; 278 } 279 280 no_more_options:; 281 if (i + 1 != argc) usage(); 282 input_file_name = argv[i]; 283 } 284 285 286 char * 287 allocate(n) 288 unsigned n; 289 { 290 register char *p; 291 292 p = NULL; 293 if (n) 294 { 295 p = CALLOC(1, n); 296 if (!p) no_space(); 297 } 298 return (p); 299 } 300 301 void 302 create_file_names() 303 { 304 int i, len; 305 char *tmpdir; 306 307 if (!(tmpdir = getenv("TMPDIR"))) 308 tmpdir = _PATH_TMP; 309 310 len = strlen(tmpdir); 311 i = len + strlen(temp_form) + 1; 312 if (len && tmpdir[len-1] != '/') 313 ++i; 314 315 action_file_name = MALLOC(i); 316 if (action_file_name == 0) no_space(); 317 text_file_name = MALLOC(i); 318 if (text_file_name == 0) no_space(); 319 union_file_name = MALLOC(i); 320 if (union_file_name == 0) no_space(); 321 322 strcpy(action_file_name, tmpdir); 323 strcpy(text_file_name, tmpdir); 324 strcpy(union_file_name, tmpdir); 325 326 if (len && tmpdir[len - 1] != '/') 327 { 328 action_file_name[len] = '/'; 329 text_file_name[len] = '/'; 330 union_file_name[len] = '/'; 331 ++len; 332 } 333 334 strcpy(action_file_name + len, temp_form); 335 strcpy(text_file_name + len, temp_form); 336 strcpy(union_file_name + len, temp_form); 337 338 action_file_name[len + 5] = 'a'; 339 text_file_name[len + 5] = 't'; 340 union_file_name[len + 5] = 'u'; 341 342 len = strlen(file_prefix); 343 344 if (!output_file_name) 345 { 346 output_file_name = MALLOC(len + 7); 347 if (output_file_name == 0) 348 no_space(); 349 strcpy(output_file_name, file_prefix); 350 strcpy(output_file_name + len, OUTPUT_SUFFIX); 351 } 352 353 if (rflag) 354 { 355 code_file_name = MALLOC(len + 8); 356 if (code_file_name == 0) 357 no_space(); 358 strcpy(code_file_name, file_prefix); 359 strcpy(code_file_name + len, CODE_SUFFIX); 360 } 361 else 362 code_file_name = output_file_name; 363 364 if (dflag) 365 { 366 if (explicit_file_name) 367 { 368 char *suffix; 369 370 defines_file_name = MALLOC(strlen(output_file_name)+1); 371 if (defines_file_name == 0) 372 no_space(); 373 strcpy(defines_file_name, output_file_name); 374 375 /* does the output_file_name have a known suffix */ 376 if ((suffix = strrchr(output_file_name, '.')) != 0 && 377 (!strcmp(suffix, ".c") || /* good, old-fashioned C */ 378 !strcmp(suffix, ".C") || /* C++, or C on Windows */ 379 !strcmp(suffix, ".cc") || /* C++ */ 380 !strcmp(suffix, ".cxx") || /* C++ */ 381 !strcmp(suffix, ".cpp"))) /* C++ (Windows) */ 382 { 383 strncpy(defines_file_name, output_file_name, 384 suffix - output_file_name + 1); 385 defines_file_name[suffix - output_file_name + 1] = 'h'; 386 defines_file_name[suffix - output_file_name + 2] = '\0'; 387 } else { 388 fprintf(stderr,"%s: suffix of output file name %s" 389 " not recognized, no -d file generated.\n", 390 __progname, output_file_name); 391 dflag = 0; 392 free(defines_file_name); 393 defines_file_name = 0; 394 } 395 } 396 else 397 { 398 defines_file_name = MALLOC(len + 7); 399 if (defines_file_name == 0) 400 no_space(); 401 strcpy(defines_file_name, file_prefix); 402 strcpy(defines_file_name + len, DEFINES_SUFFIX); 403 } 404 } 405 406 if (vflag) 407 { 408 verbose_file_name = MALLOC(len + 8); 409 if (verbose_file_name == 0) 410 no_space(); 411 strcpy(verbose_file_name, file_prefix); 412 strcpy(verbose_file_name + len, VERBOSE_SUFFIX); 413 } 414 } 415 416 417 FILE * 418 fsopen(name, mode) 419 char *name; 420 char *mode; 421 { 422 FILE *fp = NULL; 423 int fd, mod = O_RDONLY; 424 425 if (strchr(mode, 'w')) 426 mod = O_RDWR; 427 if ((fd = open(name, mod | O_EXCL|O_CREAT, 0666)) == -1 || 428 (fp = fdopen(fd, mode)) == NULL) { 429 if (fd != -1) 430 close(fd); 431 } 432 return (fp); 433 } 434 435 void 436 open_files() 437 { 438 int fd; 439 440 create_file_names(); 441 442 if (input_file == 0) 443 { 444 input_file = fopen(input_file_name, "r"); 445 if (input_file == 0) 446 open_error(input_file_name); 447 } 448 449 fd = mkstemp(action_file_name); 450 if (fd == -1 || (action_file = fdopen(fd, "w")) == NULL) 451 open_error(action_file_name); 452 453 fd = mkstemp(text_file_name); 454 if (fd == -1 || (text_file = fdopen(fd, "w")) == NULL) 455 open_error(text_file_name); 456 457 if (vflag) 458 { 459 verbose_file = fopen(verbose_file_name, "w"); 460 if (verbose_file == 0) 461 open_error(verbose_file_name); 462 } 463 464 if (dflag) 465 { 466 defines_file = fopen(defines_file_name, "w"); 467 if (defines_file == 0) 468 open_error(defines_file_name); 469 fd = mkstemp(union_file_name); 470 if (fd == -1 || (union_file = fdopen(fd, "w")) == NULL) 471 open_error(union_file_name); 472 } 473 474 output_file = fopen(output_file_name, "w"); 475 if (output_file == 0) 476 open_error(output_file_name); 477 478 if (rflag) 479 { 480 code_file = fopen(code_file_name, "w"); 481 if (code_file == 0) 482 open_error(code_file_name); 483 } 484 else 485 code_file = output_file; 486 } 487 488 489 int 490 main(argc, argv) 491 int argc; 492 char *argv[]; 493 { 494 set_signals(); 495 getargs(argc, argv); 496 open_files(); 497 reader(); 498 lr0(); 499 lalr(); 500 make_parser(); 501 verbose(); 502 output(); 503 done(0); 504 /*NOTREACHED*/ 505 return (0); 506 } 507