main.c revision 126623
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__FBSDID("$FreeBSD: head/usr.bin/yacc/main.c 126623 2004-03-05 01:52:09Z wes $"); 45 46#include <paths.h> 47#include <signal.h> 48#include <stdlib.h> 49#include <string.h> 50#include <unistd.h> 51#include "defs.h" 52 53char dflag; 54char lflag; 55char rflag; 56char tflag; 57char vflag; 58 59const char *symbol_prefix; 60const char *file_prefix = "y"; 61char temp_form[] = "yacc.XXXXXXXXXXX"; 62 63int lineno; 64int outline; 65 66char *action_file_name; 67char *code_file_name; 68char *defines_file_name; 69const char *input_file_name = ""; 70char *output_file_name; 71char *text_file_name; 72char *union_file_name; 73char *verbose_file_name; 74 75FILE *action_file; /* a temp file, used to save actions associated */ 76 /* with rules until the parser is written */ 77FILE *code_file; /* y.code.c (used when the -r option is specified) */ 78FILE *defines_file; /* y.tab.h */ 79FILE *input_file; /* the input file */ 80FILE *output_file; /* y.tab.c */ 81FILE *text_file; /* a temp file, used to save text until all */ 82 /* symbols have been defined */ 83FILE *union_file; /* a temp file, used to save the union */ 84 /* definition until all symbol have been */ 85 /* defined */ 86FILE *verbose_file; /* y.output */ 87 88int nitems; 89int nrules; 90int nsyms; 91int ntokens; 92int nvars; 93 94int start_symbol; 95char **symbol_name; 96short *symbol_value; 97short *symbol_prec; 98char *symbol_assoc; 99 100short *ritem; 101short *rlhs; 102short *rrhs; 103short *rprec; 104char *rassoc; 105short **derives; 106char *nullable; 107 108static void create_file_names(void); 109static void getargs(int, char **); 110static void onintr(int); 111static void open_files(void); 112static void set_signals(void); 113static void usage(void); 114 115volatile sig_atomic_t sigdie; 116 117__dead2 void 118done(k) 119int k; 120{ 121 if (action_file) { fclose(action_file); unlink(action_file_name); } 122 if (text_file) { fclose(text_file); unlink(text_file_name); } 123 if (union_file) { fclose(union_file); unlink(union_file_name); } 124 if (sigdie) { _exit(k); } 125 exit(k); 126} 127 128 129static void 130onintr(signo) 131 int signo __unused; 132{ 133 sigdie = 1; 134 done(1); 135} 136 137 138static void 139set_signals() 140{ 141#ifdef SIGINT 142 if (signal(SIGINT, SIG_IGN) != SIG_IGN) 143 signal(SIGINT, onintr); 144#endif 145#ifdef SIGTERM 146 if (signal(SIGTERM, SIG_IGN) != SIG_IGN) 147 signal(SIGTERM, onintr); 148#endif 149#ifdef SIGHUP 150 if (signal(SIGHUP, SIG_IGN) != SIG_IGN) 151 signal(SIGHUP, onintr); 152#endif 153} 154 155 156static void 157usage() 158{ 159 fprintf(stderr, "%s\n%s\n", 160 "usage: yacc [-dlrtv] [-b file_prefix] [-o output_filename]", 161 " [-p symbol_prefix] filename"); 162 exit(1); 163} 164 165 166static void 167getargs(argc, argv) 168int argc; 169char *argv[]; 170{ 171 int ch; 172 173 while ((ch = getopt(argc, argv, "b:dlo:p:rtv")) != -1) 174 { 175 switch (ch) 176 { 177 case 'b': 178 file_prefix = optarg; 179 break; 180 181 case 'd': 182 dflag = 1; 183 break; 184 185 case 'l': 186 lflag = 1; 187 break; 188 189 case 'o': 190 output_file_name = optarg; 191 break; 192 193 case 'p': 194 symbol_prefix = optarg; 195 break; 196 197 case 'r': 198 rflag = 1; 199 break; 200 201 case 't': 202 tflag = 1; 203 break; 204 205 case 'v': 206 vflag = 1; 207 break; 208 209 default: 210 usage(); 211 } 212 } 213 214 if (optind + 1 != argc) 215 usage(); 216 if (strcmp(argv[optind], "-") == 0) 217 input_file = stdin; 218 else 219 input_file_name = argv[optind]; 220} 221 222 223char * 224allocate(n) 225unsigned n; 226{ 227 char *p; 228 229 p = NULL; 230 if (n) 231 { 232 p = CALLOC(1, n); 233 if (!p) no_space(); 234 } 235 return (p); 236} 237 238 239static void 240create_file_names() 241{ 242 int i, len; 243 const char *tmpdir; 244 245 if (!(tmpdir = getenv("TMPDIR"))) 246 tmpdir = _PATH_TMP; 247 248 len = strlen(tmpdir); 249 i = len + strlen(temp_form) + 1; 250 if (len && tmpdir[len-1] != '/') 251 ++i; 252 253 action_file_name = MALLOC(i); 254 if (action_file_name == 0) no_space(); 255 text_file_name = MALLOC(i); 256 if (text_file_name == 0) no_space(); 257 union_file_name = MALLOC(i); 258 if (union_file_name == 0) no_space(); 259 260 strcpy(action_file_name, tmpdir); 261 strcpy(text_file_name, tmpdir); 262 strcpy(union_file_name, tmpdir); 263 264 if (len && tmpdir[len - 1] != '/') 265 { 266 action_file_name[len] = '/'; 267 text_file_name[len] = '/'; 268 union_file_name[len] = '/'; 269 ++len; 270 } 271 272 strcpy(action_file_name + len, temp_form); 273 strcpy(text_file_name + len, temp_form); 274 strcpy(union_file_name + len, temp_form); 275 276 action_file_name[len + 5] = 'a'; 277 text_file_name[len + 5] = 't'; 278 union_file_name[len + 5] = 'u'; 279 280 if (output_file_name != 0) 281 { 282 file_prefix = output_file_name; 283 len = strlen(file_prefix); 284 } 285 else 286 { 287 len = strlen(file_prefix); 288 output_file_name = MALLOC(len + 7); 289 if (output_file_name == 0) 290 no_space(); 291 strcpy(output_file_name, file_prefix); 292 strcpy(output_file_name + len, OUTPUT_SUFFIX); 293 } 294 295 if (rflag) 296 { 297 code_file_name = MALLOC(len + 8); 298 if (code_file_name == 0) 299 no_space(); 300 strcpy(code_file_name, file_prefix); 301 if (file_prefix == output_file_name) 302 { 303 /* 304 * XXX ".tab.c" here is OUTPUT_SUFFIX, but since its length is 305 * in various magic numbers, don't bother using the macro. 306 */ 307 if (len >= 6 && strcmp(code_file_name + len - 6, ".tab.c") == 0) 308 strcpy(code_file_name + len - 6, CODE_SUFFIX); 309 else if (len >= 2 && strcmp(code_file_name + len - 2, ".c") == 0) 310 strcpy(code_file_name + len - 2, CODE_SUFFIX); 311 else 312 strcpy(code_file_name + len, CODE_SUFFIX); 313 } 314 else 315 strcpy(code_file_name + len, CODE_SUFFIX); 316 } 317 else 318 code_file_name = output_file_name; 319 320 if (dflag) 321 { 322 defines_file_name = MALLOC(len + 7); 323 if (defines_file_name == 0) 324 no_space(); 325 strcpy(defines_file_name, file_prefix); 326 if (file_prefix == output_file_name) 327 { 328#define BISON_DEFINES_SUFFIX ".h" 329 if (len >= 2 && strcmp(defines_file_name + len - 2, ".c") == 0) 330 strcpy(defines_file_name + len - 2, BISON_DEFINES_SUFFIX); 331 else 332 strcpy(defines_file_name + len, BISON_DEFINES_SUFFIX); 333 } 334 else 335 strcpy(defines_file_name + len, DEFINES_SUFFIX); 336 } 337 338 if (vflag) 339 { 340 verbose_file_name = MALLOC(len + 8); 341 if (verbose_file_name == 0) 342 no_space(); 343 strcpy(verbose_file_name, file_prefix); 344 if (file_prefix == output_file_name) 345 { 346 if (len >= 6 && strcmp(verbose_file_name + len - 6, ".tab.c") == 0) 347 strcpy(verbose_file_name + len - 6, VERBOSE_SUFFIX); 348 else if (len >= 2 && strcmp(verbose_file_name + len - 2, ".c") == 0) 349 strcpy(verbose_file_name + len - 2, VERBOSE_SUFFIX); 350 else 351 strcpy(verbose_file_name + len, VERBOSE_SUFFIX); 352 } 353 else 354 strcpy(verbose_file_name + len, VERBOSE_SUFFIX); 355 } 356} 357 358 359static void 360open_files() 361{ 362 int fd; 363 364 create_file_names(); 365 366 if (input_file == 0) 367 { 368 input_file = fopen(input_file_name, "r"); 369 if (input_file == 0) 370 open_error(input_file_name); 371 } 372 373 fd = mkstemp(action_file_name); 374 if (fd < 0 || (action_file = fdopen(fd, "w")) == NULL) { 375 if (fd >= 0) 376 close(fd); 377 open_error(action_file_name); 378 } 379 fd = mkstemp(text_file_name); 380 if (fd < 0 || (text_file = fdopen(fd, "w")) == NULL) { 381 if (fd >= 0) 382 close(fd); 383 open_error(text_file_name); 384 } 385 fd = mkstemp(union_file_name); 386 if (fd < 0 || (union_file = fdopen(fd, "w")) == NULL) { 387 if (fd >= 0) 388 close(fd); 389 open_error(union_file_name); 390 } 391 392 text_file = fopen(text_file_name, "w"); 393 if (text_file == 0) 394 open_error(text_file_name); 395 396 if (vflag) 397 { 398 verbose_file = fopen(verbose_file_name, "w"); 399 if (verbose_file == 0) 400 open_error(verbose_file_name); 401 } 402 403 if (dflag) 404 { 405 defines_file = fopen(defines_file_name, "w"); 406 if (defines_file == 0) 407 open_error(defines_file_name); 408 union_file = fopen(union_file_name, "w"); 409 if (union_file == 0) 410 open_error(union_file_name); 411 } 412 413 output_file = fopen(output_file_name, "w"); 414 if (output_file == 0) 415 open_error(output_file_name); 416 417 if (rflag) 418 { 419 code_file = fopen(code_file_name, "w"); 420 if (code_file == 0) 421 open_error(code_file_name); 422 } 423 else 424 code_file = output_file; 425} 426 427 428int 429main(int argc, char *argv[]) 430{ 431 set_signals(); 432 getargs(argc, argv); 433 open_files(); 434 reader(); 435 lr0(); 436 lalr(); 437 make_parser(); 438 verbose(); 439 output(); 440 done(0); 441 /*NOTREACHED*/ 442 return (0); 443} 444