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