1 /* $OpenBSD: main.c,v 1.23 2009/10/27 23:59:50 deraadt 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 #include <sys/types.h> 37 #include <fcntl.h> 38 #include <paths.h> 39 #include <signal.h> 40 #include <stdlib.h> 41 #include <unistd.h> 42 #include "defs.h" 43 44 char dflag; 45 char lflag; 46 char rflag; 47 char tflag; 48 char vflag; 49 50 char *symbol_prefix; 51 char *file_prefix = "y"; 52 53 int lineno; 54 int outline; 55 56 int explicit_file_name; 57 58 char *action_file_name; 59 char *code_file_name; 60 char *defines_file_name; 61 char *input_file_name = ""; 62 char *output_file_name; 63 char *text_file_name; 64 char *union_file_name; 65 char *verbose_file_name; 66 67 FILE *action_file; /* a temp file, used to save actions associated */ 68 /* with rules until the parser is written */ 69 FILE *code_file; /* y.code.c (used when the -r option is specified) */ 70 FILE *defines_file; /* y.tab.h */ 71 FILE *input_file; /* the input file */ 72 FILE *output_file; /* y.tab.c */ 73 FILE *text_file; /* a temp file, used to save text until all */ 74 /* symbols have been defined */ 75 FILE *union_file; /* a temp file, used to save the union */ 76 /* definition until all symbol have been */ 77 /* defined */ 78 FILE *verbose_file; /* y.output */ 79 80 int nitems; 81 int nrules; 82 int nsyms; 83 int ntokens; 84 int nvars; 85 86 int start_symbol; 87 char **symbol_name; 88 short *symbol_value; 89 short *symbol_prec; 90 char *symbol_assoc; 91 92 short *ritem; 93 short *rlhs; 94 short *rrhs; 95 short *rprec; 96 char *rassoc; 97 short **derives; 98 char *nullable; 99 100 void onintr(int); 101 void set_signals(void); 102 void usage(void); 103 void getargs(int, char *[]); 104 void create_file_names(void); 105 void open_files(void); 106 107 volatile sig_atomic_t sigdie; 108 109 void 110 done(int k) 111 { 112 if (action_file) 113 unlink(action_file_name); 114 if (text_file) 115 unlink(text_file_name); 116 if (union_file) 117 unlink(union_file_name); 118 if (sigdie) 119 _exit(k); 120 exit(k); 121 } 122 123 124 void 125 onintr(int signo) 126 { 127 sigdie = 1; 128 done(1); 129 } 130 131 132 void 133 set_signals(void) 134 { 135 #ifdef SIGINT 136 if (signal(SIGINT, SIG_IGN) != SIG_IGN) 137 signal(SIGINT, onintr); 138 #endif 139 #ifdef SIGTERM 140 if (signal(SIGTERM, SIG_IGN) != SIG_IGN) 141 signal(SIGTERM, onintr); 142 #endif 143 #ifdef SIGHUP 144 if (signal(SIGHUP, SIG_IGN) != SIG_IGN) 145 signal(SIGHUP, onintr); 146 #endif 147 } 148 149 150 void 151 usage(void) 152 { 153 fprintf(stderr, "usage: %s [-dlrtv] [-b file_prefix] [-o output_file] [-p symbol_prefix] file\n", __progname); 154 exit(1); 155 } 156 157 158 void 159 getargs(int argc, char *argv[]) 160 { 161 int ch; 162 163 while ((ch = getopt(argc, argv, "b:dlo:p:rtv")) != -1) 164 { 165 switch (ch) 166 { 167 case 'b': 168 file_prefix = optarg; 169 break; 170 171 case 'd': 172 dflag = 1; 173 break; 174 175 case 'l': 176 lflag = 1; 177 break; 178 179 case 'o': 180 output_file_name = optarg; 181 explicit_file_name = 1; 182 break; 183 184 case 'p': 185 symbol_prefix = optarg; 186 break; 187 188 case 'r': 189 rflag = 1; 190 break; 191 192 case 't': 193 tflag = 1; 194 break; 195 196 case 'v': 197 vflag = 1; 198 break; 199 200 default: 201 usage(); 202 } 203 } 204 argc -= optind; 205 argv += optind; 206 207 if (argc != 1) 208 usage(); 209 if (strcmp(*argv, "-") == 0) 210 input_file = stdin; 211 else 212 input_file_name = *argv; 213 } 214 215 216 char * 217 allocate(unsigned int n) 218 { 219 char *p; 220 221 p = NULL; 222 if (n) 223 { 224 p = CALLOC(1, n); 225 if (!p) no_space(); 226 } 227 return (p); 228 } 229 230 #define TEMPNAME(s, c, d, l) \ 231 (asprintf(&(s), "%.*s/yacc.%xXXXXXXXXXX", (int)(l), (d), (c))) 232 233 void 234 create_file_names(void) 235 { 236 size_t len; 237 char *tmpdir; 238 239 if ((tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0') 240 tmpdir = _PATH_TMP; 241 242 len = strlen(tmpdir); 243 if (tmpdir[len-1] == '/') 244 len--; 245 246 if (TEMPNAME(action_file_name, 'a', tmpdir, len) == -1 || 247 TEMPNAME(text_file_name, 'r', tmpdir, len) == -1 || 248 TEMPNAME(union_file_name, 'u', tmpdir, len) == -1) 249 no_space(); 250 251 if (output_file_name == NULL) 252 { 253 if (asprintf(&output_file_name, "%s%s", file_prefix, OUTPUT_SUFFIX) 254 == -1) 255 no_space(); 256 } 257 258 if (rflag) { 259 if (asprintf(&code_file_name, "%s%s", file_prefix, CODE_SUFFIX) == -1) 260 no_space(); 261 } else 262 code_file_name = output_file_name; 263 264 if (dflag) 265 { 266 if (explicit_file_name) 267 { 268 char *suffix; 269 270 defines_file_name = strdup(output_file_name); 271 if (defines_file_name == 0) 272 no_space(); 273 274 /* does the output_file_name have a known suffix */ 275 if ((suffix = strrchr(output_file_name, '.')) != 0 && 276 (!strcmp(suffix, ".c") || /* good, old-fashioned C */ 277 !strcmp(suffix, ".C") || /* C++, or C on Windows */ 278 !strcmp(suffix, ".cc") || /* C++ */ 279 !strcmp(suffix, ".cxx") || /* C++ */ 280 !strcmp(suffix, ".cpp"))) /* C++ (Windows) */ 281 { 282 strncpy(defines_file_name, output_file_name, 283 suffix - output_file_name + 1); 284 defines_file_name[suffix - output_file_name + 1] = 'h'; 285 defines_file_name[suffix - output_file_name + 2] = '\0'; 286 } else { 287 fprintf(stderr,"%s: suffix of output file name %s" 288 " not recognized, no -d file generated.\n", 289 __progname, output_file_name); 290 dflag = 0; 291 free(defines_file_name); 292 defines_file_name = 0; 293 } 294 } 295 else 296 { 297 if (asprintf(&defines_file_name, "%s%s", file_prefix, 298 DEFINES_SUFFIX) == -1) 299 no_space(); 300 } 301 } 302 303 if (vflag) 304 { 305 if (asprintf(&verbose_file_name, "%s%s", file_prefix, 306 VERBOSE_SUFFIX) == -1) 307 no_space(); 308 } 309 } 310 311 312 void 313 open_files(void) 314 { 315 int fd; 316 317 create_file_names(); 318 319 if (input_file == 0) 320 { 321 input_file = fopen(input_file_name, "r"); 322 if (input_file == 0) 323 open_error(input_file_name); 324 } 325 326 fd = mkstemp(action_file_name); 327 if (fd == -1 || (action_file = fdopen(fd, "w")) == NULL) 328 open_error(action_file_name); 329 330 fd = mkstemp(text_file_name); 331 if (fd == -1 || (text_file = fdopen(fd, "w")) == NULL) 332 open_error(text_file_name); 333 334 if (vflag) 335 { 336 verbose_file = fopen(verbose_file_name, "w"); 337 if (verbose_file == 0) 338 open_error(verbose_file_name); 339 } 340 341 if (dflag) 342 { 343 defines_file = fopen(defines_file_name, "w"); 344 if (defines_file == NULL) 345 open_write_error(defines_file_name); 346 fd = mkstemp(union_file_name); 347 if (fd == -1 || (union_file = fdopen(fd, "w")) == NULL) 348 open_error(union_file_name); 349 } 350 351 output_file = fopen(output_file_name, "w"); 352 if (output_file == 0) 353 open_error(output_file_name); 354 355 if (rflag) 356 { 357 code_file = fopen(code_file_name, "w"); 358 if (code_file == 0) 359 open_error(code_file_name); 360 } 361 else 362 code_file = output_file; 363 } 364 365 366 int 367 main(int argc, char *argv[]) 368 { 369 set_signals(); 370 getargs(argc, argv); 371 open_files(); 372 reader(); 373 lr0(); 374 lalr(); 375 make_parser(); 376 verbose(); 377 output(); 378 done(0); 379 /*NOTREACHED*/ 380 return (0); 381 } 382