main.c (8053B)
1 /* $OpenBSD: main.c,v 1.26 2014/03/13 00:33:55 tedu 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 switch (ch) { 165 case 'b': 166 file_prefix = optarg; 167 break; 168 169 case 'd': 170 dflag = 1; 171 break; 172 173 case 'l': 174 lflag = 1; 175 break; 176 177 case 'o': 178 output_file_name = optarg; 179 explicit_file_name = 1; 180 break; 181 182 case 'p': 183 symbol_prefix = optarg; 184 break; 185 186 case 'r': 187 rflag = 1; 188 break; 189 190 case 't': 191 tflag = 1; 192 break; 193 194 case 'v': 195 vflag = 1; 196 break; 197 198 default: 199 usage(); 200 } 201 } 202 argc -= optind; 203 argv += optind; 204 205 if (argc != 1) 206 usage(); 207 if (strcmp(*argv, "-") == 0) 208 input_file = stdin; 209 else 210 input_file_name = *argv; 211 } 212 213 214 void * 215 allocate(size_t n) 216 { 217 void *v; 218 219 v = NULL; 220 if (n) { 221 v = calloc(1, n); 222 if (!v) 223 no_space(); 224 } 225 return (v); 226 } 227 228 #define TEMPNAME(s, c, d, l) \ 229 (asprintf(&(s), "%.*s/yacc.%xXXXXXXXXXX", (int)(l), (d), (c))) 230 231 void 232 create_file_names(void) 233 { 234 size_t len; 235 char *tmpdir; 236 237 if ((tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0') 238 tmpdir = _PATH_TMP; 239 240 len = strlen(tmpdir); 241 if (tmpdir[len - 1] == '/') 242 len--; 243 244 if (TEMPNAME(action_file_name, 'a', tmpdir, len) == -1 || 245 TEMPNAME(text_file_name, 'r', tmpdir, len) == -1 || 246 TEMPNAME(union_file_name, 'u', tmpdir, len) == -1) 247 no_space(); 248 249 if (output_file_name == NULL) { 250 if (asprintf(&output_file_name, "%s%s", file_prefix, OUTPUT_SUFFIX) 251 == -1) 252 no_space(); 253 } 254 if (rflag) { 255 if (asprintf(&code_file_name, "%s%s", file_prefix, CODE_SUFFIX) == -1) 256 no_space(); 257 } else 258 code_file_name = output_file_name; 259 260 if (dflag) { 261 if (explicit_file_name) { 262 char *suffix; 263 264 defines_file_name = strdup(output_file_name); 265 if (defines_file_name == 0) 266 no_space(); 267 268 /* does the output_file_name have a known suffix */ 269 if ((suffix = strrchr(output_file_name, '.')) != 0 && 270 (!strcmp(suffix, ".c") || /* good, old-fashioned C */ 271 !strcmp(suffix, ".C") || /* C++, or C on Windows */ 272 !strcmp(suffix, ".cc") || /* C++ */ 273 !strcmp(suffix, ".cxx") || /* C++ */ 274 !strcmp(suffix, ".cpp"))) {/* C++ (Windows) */ 275 strncpy(defines_file_name, output_file_name, 276 suffix - output_file_name + 1); 277 defines_file_name[suffix - output_file_name + 1] = 'h'; 278 defines_file_name[suffix - output_file_name + 2] = '\0'; 279 } else { 280 fprintf(stderr, "%s: suffix of output file name %s" 281 " not recognized, no -d file generated.\n", 282 __progname, output_file_name); 283 dflag = 0; 284 free(defines_file_name); 285 defines_file_name = 0; 286 } 287 } else { 288 if (asprintf(&defines_file_name, "%s%s", file_prefix, 289 DEFINES_SUFFIX) == -1) 290 no_space(); 291 } 292 } 293 if (vflag) { 294 if (asprintf(&verbose_file_name, "%s%s", file_prefix, 295 VERBOSE_SUFFIX) == -1) 296 no_space(); 297 } 298 } 299 300 301 void 302 open_files(void) 303 { 304 int fd; 305 306 create_file_names(); 307 308 if (input_file == 0) { 309 input_file = fopen(input_file_name, "r"); 310 if (input_file == 0) 311 open_error(input_file_name); 312 } 313 fd = mkstemp(action_file_name); 314 if (fd == -1 || (action_file = fdopen(fd, "w")) == NULL) 315 open_error(action_file_name); 316 317 fd = mkstemp(text_file_name); 318 if (fd == -1 || (text_file = fdopen(fd, "w")) == NULL) 319 open_error(text_file_name); 320 321 if (vflag) { 322 verbose_file = fopen(verbose_file_name, "w"); 323 if (verbose_file == 0) 324 open_error(verbose_file_name); 325 } 326 if (dflag) { 327 defines_file = fopen(defines_file_name, "w"); 328 if (defines_file == NULL) 329 open_write_error(defines_file_name); 330 fd = mkstemp(union_file_name); 331 if (fd == -1 || (union_file = fdopen(fd, "w")) == NULL) 332 open_error(union_file_name); 333 } 334 output_file = fopen(output_file_name, "w"); 335 if (output_file == 0) 336 open_error(output_file_name); 337 338 if (rflag) { 339 code_file = fopen(code_file_name, "w"); 340 if (code_file == 0) 341 open_error(code_file_name); 342 } else 343 code_file = output_file; 344 } 345 346 347 int 348 main(int argc, char *argv[]) 349 { 350 set_signals(); 351 getargs(argc, argv); 352 open_files(); 353 reader(); 354 lr0(); 355 lalr(); 356 make_parser(); 357 verbose(); 358 output(); 359 done(0); 360 /* NOTREACHED */ 361 return (0); 362 }