main.c revision 1.1 1 /* $NetBSD: main.c,v 1.1 2009/10/29 00:46:53 christos Exp $ */
2
3 /* Id: main.c,v 1.23 2009/10/27 09:06:44 tom Exp */
4
5 #include <signal.h>
6 #include <unistd.h> /* for _exit() */
7
8 #include "defs.h"
9
10 char dflag;
11 char gflag;
12 char lflag;
13 char oflag;
14 char rflag;
15 char tflag;
16 char vflag;
17
18 const char *symbol_prefix;
19 const char *myname = "yacc";
20
21 int lineno;
22 int outline;
23
24 static char empty_string[] = "";
25 static char default_file_prefix[] = "y";
26
27 static char *file_prefix = default_file_prefix;
28
29 char *code_file_name;
30 char *defines_file_name;
31 char *input_file_name = empty_string;
32 char *output_file_name = 0;
33 char *verbose_file_name;
34 char *graph_file_name;
35
36 FILE *action_file; /* a temp file, used to save actions associated */
37 /* with rules until the parser is written */
38 FILE *code_file; /* y.code.c (used when the -r option is specified) */
39 FILE *defines_file; /* y.tab.h */
40 FILE *input_file; /* the input file */
41 FILE *output_file; /* y.tab.c */
42 FILE *text_file; /* a temp file, used to save text until all */
43 /* symbols have been defined */
44 FILE *union_file; /* a temp file, used to save the union */
45 /* definition until all symbol have been */
46 /* defined */
47 FILE *verbose_file; /* y.output */
48 FILE *graph_file; /* y.dot */
49
50 int nitems;
51 int nrules;
52 int nsyms;
53 int ntokens;
54 int nvars;
55
56 Value_t start_symbol;
57 char **symbol_name;
58 char **symbol_pname;
59 Value_t *symbol_value;
60 short *symbol_prec;
61 char *symbol_assoc;
62
63 int exit_code;
64
65 Value_t *ritem;
66 Value_t *rlhs;
67 Value_t *rrhs;
68 Value_t *rprec;
69 Assoc_t *rassoc;
70 Value_t **derives;
71 char *nullable;
72
73 /*
74 * Since fclose() is called via the signal handler, it might die. Don't loop
75 * if there is a problem closing a file.
76 */
77 #define DO_CLOSE(fp) \
78 if (fp != 0) { \
79 FILE *use = fp; \
80 fp = 0; \
81 fclose(use); \
82 }
83
84 static int got_intr = 0;
85
86 void
87 done(int k)
88 {
89 DO_CLOSE(input_file);
90 DO_CLOSE(output_file);
91
92 DO_CLOSE(action_file);
93 DO_CLOSE(defines_file);
94 DO_CLOSE(graph_file);
95 DO_CLOSE(text_file);
96 DO_CLOSE(union_file);
97 DO_CLOSE(verbose_file);
98
99 if (got_intr)
100 _exit(EXIT_FAILURE);
101
102 #ifdef NO_LEAKS
103 if (rflag)
104 DO_FREE(code_file_name);
105
106 if (dflag)
107 DO_FREE(defines_file_name);
108
109 if (oflag)
110 DO_FREE(output_file_name);
111
112 if (vflag)
113 DO_FREE(verbose_file_name);
114
115 if (gflag)
116 DO_FREE(graph_file_name);
117
118 lr0_leaks();
119 lalr_leaks();
120 mkpar_leaks();
121 output_leaks();
122 reader_leaks();
123 #endif
124
125 exit(k);
126 }
127
128 static void
129 onintr(int sig GCC_UNUSED)
130 {
131 got_intr = 1;
132 done(EXIT_FAILURE);
133 }
134
135 static void
136 set_signals(void)
137 {
138 #ifdef SIGINT
139 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
140 signal(SIGINT, onintr);
141 #endif
142 #ifdef SIGTERM
143 if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
144 signal(SIGTERM, onintr);
145 #endif
146 #ifdef SIGHUP
147 if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
148 signal(SIGHUP, onintr);
149 #endif
150 }
151
152 static void
153 usage(void)
154 {
155 static const char *msg[] =
156 {
157 ""
158 ,"Options:"
159 ," -b file_prefix set filename prefix (default \"y.\")"
160 ," -d write definitions (y.tab.h)"
161 ," -g write a graphical description"
162 ," -l suppress #line directives"
163 ," -o output_file (default \"y.tab.c\")"
164 ," -p symbol_prefix set symbol prefix (default \"yy\")"
165 ," -r produce separate code and table files (y.code.c)"
166 ," -t add debugging support"
167 ," -v write description (y.output)"
168 ," -V show version information and exit"
169 };
170 unsigned n;
171
172 fflush(stdout);
173 fprintf(stderr, "Usage: %s [options] filename\n", myname);
174 for (n = 0; n < sizeof(msg) / sizeof(msg[0]); ++n)
175 fprintf(stderr, "%s\n", msg[n]);
176
177 exit(1);
178 }
179
180 static void
181 setflag(int ch)
182 {
183 switch (ch)
184 {
185 case 'd':
186 dflag = 1;
187 break;
188
189 case 'g':
190 gflag = 1;
191 break;
192
193 case 'l':
194 lflag = 1;
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 case 'V':
210 printf("%s - %s\n", myname, VERSION);
211 exit(EXIT_SUCCESS);
212
213 default:
214 usage();
215 }
216 }
217
218 static void
219 getargs(int argc, char *argv[])
220 {
221 int i;
222 char *s;
223 int ch;
224
225 if (argc > 0)
226 myname = argv[0];
227
228 for (i = 1; i < argc; ++i)
229 {
230 s = argv[i];
231 if (*s != '-')
232 break;
233 switch (ch = *++s)
234 {
235 case '\0':
236 input_file = stdin;
237 if (i + 1 < argc)
238 usage();
239 return;
240
241 case '-':
242 ++i;
243 goto no_more_options;
244
245 case 'b':
246 if (*++s)
247 file_prefix = s;
248 else if (++i < argc)
249 file_prefix = argv[i];
250 else
251 usage();
252 continue;
253
254 case 'o':
255 if (*++s)
256 output_file_name = s;
257 else if (++i < argc)
258 output_file_name = argv[i];
259 else
260 usage();
261 continue;
262
263 case 'p':
264 if (*++s)
265 symbol_prefix = s;
266 else if (++i < argc)
267 symbol_prefix = argv[i];
268 else
269 usage();
270 continue;
271
272 default:
273 setflag(ch);
274 break;
275 }
276
277 for (;;)
278 {
279 switch (ch = *++s)
280 {
281 case '\0':
282 goto end_of_option;
283
284 default:
285 setflag(ch);
286 break;
287 }
288 }
289 end_of_option:;
290 }
291
292 no_more_options:;
293 if (i + 1 != argc)
294 usage();
295 input_file_name = argv[i];
296 }
297
298 char *
299 allocate(unsigned n)
300 {
301 char *p;
302
303 p = NULL;
304 if (n)
305 {
306 p = CALLOC(1, n);
307 if (!p)
308 no_space();
309 }
310 return (p);
311 }
312
313 #define CREATE_FILE_NAME(dest, suffix) \
314 dest = MALLOC(len + strlen(suffix) + 1); \
315 if (dest == 0) \
316 no_space(); \
317 strcpy(dest, file_prefix); \
318 strcpy(dest + len, suffix)
319
320 static void
321 create_file_names(void)
322 {
323 size_t len;
324 const char *defines_suffix;
325 char *prefix;
326
327 prefix = NULL;
328 defines_suffix = DEFINES_SUFFIX;
329
330 /* compute the file_prefix from the user provided output_file_name */
331 if (output_file_name != 0)
332 {
333 if (!(prefix = strstr(output_file_name, ".tab.c"))
334 && (prefix = strstr(output_file_name, ".c")))
335 defines_suffix = ".h";
336 }
337
338 if (prefix != NULL)
339 {
340 len = (size_t) (prefix - output_file_name);
341 file_prefix = (char *)MALLOC(len + 1);
342 if (file_prefix == 0)
343 no_space();
344 strncpy(file_prefix, output_file_name, len)[len] = 0;
345 }
346 else
347 len = strlen(file_prefix);
348
349 /* if "-o filename" was not given */
350 if (output_file_name == 0)
351 {
352 oflag = 1;
353 CREATE_FILE_NAME(output_file_name, OUTPUT_SUFFIX);
354 }
355
356 if (rflag)
357 {
358 CREATE_FILE_NAME(code_file_name, CODE_SUFFIX);
359 }
360 else
361 code_file_name = output_file_name;
362
363 if (dflag)
364 {
365 CREATE_FILE_NAME(defines_file_name, defines_suffix);
366 }
367
368 if (vflag)
369 {
370 CREATE_FILE_NAME(verbose_file_name, VERBOSE_SUFFIX);
371 }
372
373 if (gflag)
374 {
375 CREATE_FILE_NAME(graph_file_name, GRAPH_SUFFIX);
376 }
377
378 if (prefix != NULL)
379 {
380 FREE(file_prefix);
381 }
382 }
383
384 static void
385 open_files(void)
386 {
387 create_file_names();
388
389 if (input_file == 0)
390 {
391 input_file = fopen(input_file_name, "r");
392 if (input_file == 0)
393 open_error(input_file_name);
394 }
395
396 action_file = tmpfile();
397 if (action_file == 0)
398 open_error("action_file");
399
400 text_file = tmpfile();
401 if (text_file == 0)
402 open_error("text_file");
403
404 if (vflag)
405 {
406 verbose_file = fopen(verbose_file_name, "w");
407 if (verbose_file == 0)
408 open_error(verbose_file_name);
409 }
410
411 if (gflag)
412 {
413 graph_file = fopen(graph_file_name, "w");
414 if (graph_file == 0)
415 open_error(graph_file_name);
416 fprintf(graph_file, "digraph %s {\n", file_prefix);
417 fprintf(graph_file, "\tedge [fontsize=10];\n");
418 fprintf(graph_file, "\tnode [shape=box,fontsize=10];\n");
419 fprintf(graph_file, "\torientation=landscape;\n");
420 fprintf(graph_file, "\trankdir=LR;\n");
421 fprintf(graph_file, "\t/*\n");
422 fprintf(graph_file, "\tmargin=0.2;\n");
423 fprintf(graph_file, "\tpage=\"8.27,11.69\"; // for A4 printing\n");
424 fprintf(graph_file, "\tratio=auto;\n");
425 fprintf(graph_file, "\t*/\n");
426 }
427
428 if (dflag)
429 {
430 defines_file = fopen(defines_file_name, "w");
431 if (defines_file == 0)
432 open_error(defines_file_name);
433 union_file = tmpfile();
434 if (union_file == 0)
435 open_error("union_file");
436 }
437
438 output_file = fopen(output_file_name, "w");
439 if (output_file == 0)
440 open_error(output_file_name);
441
442 if (rflag)
443 {
444 code_file = fopen(code_file_name, "w");
445 if (code_file == 0)
446 open_error(code_file_name);
447 }
448 else
449 code_file = output_file;
450 }
451
452 int
453 main(int argc, char *argv[])
454 {
455 SRexpect = -1;
456 RRexpect = -1;
457 exit_code = EXIT_SUCCESS;
458
459 set_signals();
460 getargs(argc, argv);
461 open_files();
462 reader();
463 lr0();
464 lalr();
465 make_parser();
466 graph();
467 finalize_closure();
468 verbose();
469 output();
470 done(exit_code);
471 /*NOTREACHED */
472 }
473