1 /* $OpenBSD: main.c,v 1.21 2008/05/17 23:31:52 sobrado 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.21 2008/05/17 23:31:52 sobrado 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 output_file] [-p symbol_prefix] file\n", __progname); 168 exit(1); 169 } 170 171 172 void 173 getargs(int argc, char *argv[]) 174 { 175 int ch; 176 177 while ((ch = getopt(argc, argv, "b:dlo:p:rtv")) != -1) 178 { 179 switch (ch) 180 { 181 case 'b': 182 file_prefix = optarg; 183 break; 184 185 case 'd': 186 dflag = 1; 187 break; 188 189 case 'l': 190 lflag = 1; 191 break; 192 193 case 'o': 194 output_file_name = optarg; 195 explicit_file_name = 1; 196 break; 197 198 case 'p': 199 symbol_prefix = optarg; 200 break; 201 202 case 'r': 203 rflag = 1; 204 break; 205 206 case 't': 207 tflag = 1; 208 break; 209 210 case 'v': 211 vflag = 1; 212 break; 213 214 default: 215 usage(); 216 } 217 } 218 argc -= optind; 219 argv += optind; 220 221 if (argc != 1) 222 usage(); 223 if (strcmp(*argv, "-") == 0) 224 input_file = stdin; 225 else 226 input_file_name = *argv; 227 } 228 229 230 char * 231 allocate(unsigned int n) 232 { 233 char *p; 234 235 p = NULL; 236 if (n) 237 { 238 p = CALLOC(1, n); 239 if (!p) no_space(); 240 } 241 return (p); 242 } 243 244 #define TEMPNAME(s, c, d, l) \ 245 (asprintf(&(s), "%.*s/yacc.%xXXXXXXXXXX", (int)(l), (d), (c))) 246 247 void 248 create_file_names(void) 249 { 250 size_t len; 251 char *tmpdir; 252 253 if ((tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0') 254 tmpdir = _PATH_TMP; 255 256 len = strlen(tmpdir); 257 if (tmpdir[len-1] == '/') 258 len--; 259 260 if (TEMPNAME(action_file_name, 'a', tmpdir, len) == -1 || 261 TEMPNAME(text_file_name, 'r', tmpdir, len) == -1 || 262 TEMPNAME(union_file_name, 'u', tmpdir, len) == -1) 263 no_space(); 264 265 if (output_file_name == NULL) 266 { 267 if (asprintf(&output_file_name, "%s%s", file_prefix, OUTPUT_SUFFIX) 268 == -1) 269 no_space(); 270 } 271 272 if (rflag) { 273 if (asprintf(&code_file_name, "%s%s", file_prefix, CODE_SUFFIX) == -1) 274 no_space(); 275 } else 276 code_file_name = output_file_name; 277 278 if (dflag) 279 { 280 if (explicit_file_name) 281 { 282 char *suffix; 283 284 defines_file_name = strdup(output_file_name); 285 if (defines_file_name == 0) 286 no_space(); 287 288 /* does the output_file_name have a known suffix */ 289 if ((suffix = strrchr(output_file_name, '.')) != 0 && 290 (!strcmp(suffix, ".c") || /* good, old-fashioned C */ 291 !strcmp(suffix, ".C") || /* C++, or C on Windows */ 292 !strcmp(suffix, ".cc") || /* C++ */ 293 !strcmp(suffix, ".cxx") || /* C++ */ 294 !strcmp(suffix, ".cpp"))) /* C++ (Windows) */ 295 { 296 strncpy(defines_file_name, output_file_name, 297 suffix - output_file_name + 1); 298 defines_file_name[suffix - output_file_name + 1] = 'h'; 299 defines_file_name[suffix - output_file_name + 2] = '\0'; 300 } else { 301 fprintf(stderr,"%s: suffix of output file name %s" 302 " not recognized, no -d file generated.\n", 303 __progname, output_file_name); 304 dflag = 0; 305 free(defines_file_name); 306 defines_file_name = 0; 307 } 308 } 309 else 310 { 311 if (asprintf(&defines_file_name, "%s%s", file_prefix, 312 DEFINES_SUFFIX) == -1) 313 no_space(); 314 } 315 } 316 317 if (vflag) 318 { 319 if (asprintf(&verbose_file_name, "%s%s", file_prefix, 320 VERBOSE_SUFFIX) == -1) 321 no_space(); 322 } 323 } 324 325 326 FILE * 327 fsopen(char *name, char *mode) 328 { 329 FILE *fp = NULL; 330 int fd, mod = O_RDONLY; 331 332 if (strchr(mode, 'w')) 333 mod = O_RDWR; 334 if ((fd = open(name, mod | O_EXCL|O_CREAT, 0666)) == -1 || 335 (fp = fdopen(fd, mode)) == NULL) { 336 if (fd != -1) 337 close(fd); 338 } 339 return (fp); 340 } 341 342 void 343 open_files(void) 344 { 345 int fd; 346 347 create_file_names(); 348 349 if (input_file == 0) 350 { 351 input_file = fopen(input_file_name, "r"); 352 if (input_file == 0) 353 open_error(input_file_name); 354 } 355 356 fd = mkstemp(action_file_name); 357 if (fd == -1 || (action_file = fdopen(fd, "w")) == NULL) 358 open_error(action_file_name); 359 360 fd = mkstemp(text_file_name); 361 if (fd == -1 || (text_file = fdopen(fd, "w")) == NULL) 362 open_error(text_file_name); 363 364 if (vflag) 365 { 366 verbose_file = fopen(verbose_file_name, "w"); 367 if (verbose_file == 0) 368 open_error(verbose_file_name); 369 } 370 371 if (dflag) 372 { 373 defines_file = fopen(defines_file_name, "w"); 374 if (defines_file == NULL) 375 open_write_error(defines_file_name); 376 fd = mkstemp(union_file_name); 377 if (fd == -1 || (union_file = fdopen(fd, "w")) == NULL) 378 open_error(union_file_name); 379 } 380 381 output_file = fopen(output_file_name, "w"); 382 if (output_file == 0) 383 open_error(output_file_name); 384 385 if (rflag) 386 { 387 code_file = fopen(code_file_name, "w"); 388 if (code_file == 0) 389 open_error(code_file_name); 390 } 391 else 392 code_file = output_file; 393 } 394 395 396 int 397 main(int argc, char *argv[]) 398 { 399 set_signals(); 400 getargs(argc, argv); 401 open_files(); 402 reader(); 403 lr0(); 404 lalr(); 405 make_parser(); 406 verbose(); 407 output(); 408 done(0); 409 /*NOTREACHED*/ 410 return (0); 411 } 412