1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #ifndef __WIN32__ /*rwj -- make portable*/
6 #include <signal.h>
7 #else
8 #include <dir.h>
9 #endif
10
11 #include "defs.h"
12
13 char dflag;
14 char lflag;
15 char rflag;
16 char tflag;
17 char vflag;
18
19 /*##### JAVA FLAGS ####*/
20 char jflag; /* Are we generating Java? Yes/No */
21 char *jclass_name; /* Class name of this parser. Default = "Parser" */
22 char *jpackage_name; /* Value of "package XXXXX;" Default = none */
23 char *jextend_name; /* Value of "extends XXXXX" Default = none */
24 char *jimplement_name; /* Value of "implements XXXXX" Default = none */
25 char *jsemantic_type; /* Class name of semantic value */
26 char jrun; /* Do we provide a run()? Yes/No Default y */
27 char jconstruct; /* Do we provide constructors? Yes/No Default y */
28 int jstack_size; /* Semantic value stack size */
29 /* yio 20020304 */
30 int jdebug;
31 int jfinal_class;
32 char *jyyparse_throws;
33
34
35
36 char *file_prefix = "y";
37 char *myname = "yacc";
38 char *temp_form = "yacc.XXXXXXX";
39
40 int lineno;
41 int outline;
42
43 char *action_file_name;
44 char *code_file_name;
45 char *defines_file_name;
46 char *input_file_name = "";
47 char *output_file_name;
48 char *text_file_name;
49 char *union_file_name;
50 char *verbose_file_name;
51
52 FILE *action_file; /* a temp file, used to save actions associated */
53 /* with rules until the parser is written */
54 FILE *code_file; /* y.code.c (used when the -r option is specified) */
55 FILE *defines_file; /* y.tab.h */
56 FILE *input_file; /* the input file */
57 FILE *output_file; /* y.tab.c */
58 FILE *text_file; /* a temp file, used to save text until all */
59 /* symbols have been defined */
60 FILE *union_file; /* a temp file, used to save the union */
61 /* definition until all symbol have been */
62 /* defined */
63 FILE *verbose_file; /* y.output */
64
65 int nitems;
66 int nrules;
67 int nsyms;
68 int ntokens;
69 int nvars;
70
71 int start_symbol;
72 char **symbol_name;
73 short *symbol_value;
74 short *symbol_prec;
75 char *symbol_assoc;
76
77 short *ritem;
78 short *rlhs;
79 short *rrhs;
80 short *rprec;
81 char *rassoc;
82 short **derives;
83 char *nullable;
84
85
done(int k)86 void done(int k)
87 {
88 if (action_file) { fclose(action_file); unlink(action_file_name); }
89 if (text_file) { fclose(text_file); unlink(text_file_name); }
90 if (union_file) { fclose(union_file); unlink(union_file_name); }
91 exit(k);
92 }
93
94
onintr(int flag)95 void onintr(int flag)
96 {
97 done(1);
98 }
99
100
set_signals(void)101 void set_signals(void)
102 {
103 #ifndef __WIN32__ /*rwj -- make portable*/
104 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
105 signal(SIGINT, onintr);
106 if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
107 signal(SIGTERM, onintr);
108 if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
109 signal(SIGHUP, onintr);
110 #endif
111 }
112
113
usage(void)114 void usage(void)
115 {
116 fprintf(stderr,
117 "usage:\n %s [-dlrtvj] [-b file_prefix] [-Joption] filename\n", myname);
118 fprintf(stderr," where -Joption is one or more of:\n");
119 fprintf(stderr," -J\n");
120 fprintf(stderr," -Jclass=className\n");
121 fprintf(stderr," -Jvalue=valueClassName (avoids automatic value class creation)\n");
122 fprintf(stderr," -Jpackage=packageName\n");
123 fprintf(stderr," -Jextends=extendName\n");
124 fprintf(stderr," -Jimplements=implementsName\n");
125 fprintf(stderr," -Jsemantic=semanticType\n");
126 fprintf(stderr," -Jnorun\n");
127 fprintf(stderr," -Jnoconstruct\n");
128 fprintf(stderr," -Jstack=SIZE (default 500)\n");
129 fprintf(stderr," -Jnodebug (omits debugging code for better performance)\n");
130 fprintf(stderr," -Jfinal (makes generated class final)\n");
131 fprintf(stderr," -Jthrows (declares thrown exceptions for yyparse() method)\n");
132
133 exit(1);
134 }
135
setJavaDefaults(void)136 void setJavaDefaults(void)
137 {
138 jflag =0;
139 jclass_name ="Parser"; /* Class name of this parser. Default = "Parser" */
140 jpackage_name =""; /* Value of "package XXXXX;" Default = none */
141 jextend_name =""; /* Value of "extends XXXXX" Default = none */
142 jimplement_name=""; /* Value of "implements XXXXX" Default = none */
143 jsemantic_type =""; /* Type of semantic value Default = none */
144 jrun =1; /* Provide a default run method */
145 jconstruct =1; /* Provide default constructors */
146 jstack_size =500; /* Default stack size */
147
148 /* yio 20020304: added new flags */
149 jdebug = TRUE; /* include debugging code in parser? */
150 jfinal_class = FALSE; /* Make the class final? */
151 jyyparse_throws = ""; /* Which exceptions yyparse() throws */
152 }
153
getJavaArg(char * option)154 void getJavaArg(char *option)
155 {
156 int len;
157 jflag=1;
158 if (!option || !(*option))
159 return;
160 len=strlen(option);
161 if (strncmp("class=",option,6)==0 && len>6)
162 jclass_name=&(option[6]);
163 else if (strncmp("package=",option,8)==0 && len>8)
164 jpackage_name=&(option[8]);
165 else if (strncmp("extends=",option,8)==0 && len>8)
166 jextend_name=&(option[8]);
167 else if (strncmp("implements=",option,11)==0 && len>11)
168 jimplement_name=&(option[11]);
169 else if (strncmp("semantic=",option,9)==0 && len>9)
170 jsemantic_type=&(option[9]);
171 else if (strcmp("norun",option)==0)
172 jrun=0;
173 else if (strcmp("noconstruct",option)==0)
174 jconstruct=0;
175 else if (strncmp("stack=",option,6)==0 && len>6)
176 jstack_size=atoi(&(option[6]));
177
178 /* yio 20020304: added two new flags */
179 else if (strncmp("nodebug",option,7)==0)
180 jdebug=FALSE;
181 else if (strncmp("final",option,5)==0)
182 jfinal_class=TRUE;
183 else if (strncmp("throws=",option,6)==0 && len>6)
184 jyyparse_throws=&(option[7]);
185 }
186
getargs(int argc,char ** argv)187 void getargs(int argc,char **argv)
188 {
189 int i;
190 char *s;
191
192 setJavaDefaults(); /* rwj */
193
194 if (argc > 0) myname = argv[0];
195 for (i = 1; i < argc; ++i)
196 {
197 s = argv[i];
198 if (*s != '-') break;
199 switch (*++s)
200 {
201 case '\0':
202 input_file = stdin;
203 if (i + 1 < argc) usage();
204 return;
205
206 case '-':
207 ++i;
208 goto no_more_options;
209
210 case 'b':
211 if (*++s)
212 file_prefix = s;
213 else if (++i < argc)
214 file_prefix = argv[i];
215 else
216 usage();
217 continue;
218
219 case 'd':
220 dflag = 1;
221 break;
222
223 case 'l':
224 lflag = 1;
225 break;
226
227 case 'r':
228 rflag = 1;
229 break;
230
231 case 't':
232 tflag = 1;
233 break;
234
235 case 'v':
236 vflag = 1;
237 break;
238
239 case 'J': /* rwj -- for Java! */
240 jflag = 1;
241 getJavaArg(&(s[1]));
242 continue;
243
244
245 default:
246 usage();
247 }
248
249 for (;;) /*single letter options ex: yacc -iJr file.y */
250 {
251 switch (*++s)
252 {
253 case '\0':
254 goto end_of_option;
255
256 case 'd':
257 dflag = 1;
258 break;
259
260 case 'l':
261 lflag = 1;
262 break;
263
264 case 'r':
265 rflag = 1;
266 break;
267
268 case 't':
269 tflag = 1;
270 break;
271
272 case 'v':
273 vflag = 1;
274 break;
275
276 case 'J': /* rwj -- for java*/
277 jflag = 1;
278 break;
279
280 default:
281 usage();
282 }
283 }
284 end_of_option:;
285 }
286
287 no_more_options:;
288 if (i + 1 != argc) usage();
289 input_file_name = argv[i];
290 }
291
292
allocate(unsigned n)293 char *allocate(unsigned n)
294 {
295 char *p;
296
297 p = NULL;
298 if (n)
299 {
300 p = CALLOC(1, n);
301 if (!p) no_space();
302 }
303 return (p);
304 }
305
create_file_names(void)306 void create_file_names(void)
307 {
308 int i, len, jclass_len;
309 char *tmpdir;
310
311 tmpdir = getenv("TMPDIR");
312 #ifdef __WIN32__ /*rwj -- make portable*/
313 if (tmpdir == 0) tmpdir = ".";
314 #else
315 if (tmpdir == 0) tmpdir = "/tmp";
316 #endif
317
318 len = strlen(tmpdir);
319 i = len + 13;
320 if (len && tmpdir[len-1] != '/')
321 ++i;
322
323 action_file_name = MALLOC(i);
324 if (action_file_name == 0) no_space();
325 text_file_name = MALLOC(i);
326 if (text_file_name == 0) no_space();
327 union_file_name = MALLOC(i);
328 if (union_file_name == 0) no_space();
329 output_file_name = MALLOC(i); /* yio */
330 if (output_file_name == 0) no_space();
331
332 strcpy(action_file_name, tmpdir);
333 strcpy(text_file_name, tmpdir);
334 strcpy(union_file_name, tmpdir);
335 strcpy(output_file_name, tmpdir);
336
337 if (len && tmpdir[len - 1] != '/')
338 {
339 action_file_name[len] = '/';
340 text_file_name[len] = '/';
341 union_file_name[len] = '/';
342 output_file_name[len] = '/';
343 ++len;
344 }
345
346 strcpy(action_file_name + len, temp_form);
347 strcpy(text_file_name + len, temp_form);
348 strcpy(union_file_name + len, temp_form);
349 strcpy(output_file_name + len, temp_form);
350
351 action_file_name[len + 5] = 'a';
352 text_file_name[len + 5] = 't';
353 union_file_name[len + 5] = 'u';
354 output_file_name[len + 5] = 'o';
355
356 mktemp(action_file_name);
357 mktemp(text_file_name);
358 mktemp(union_file_name);
359 mktemp(output_file_name);
360
361 len = strlen(file_prefix);
362
363 if (rflag)
364 {
365 code_file_name = MALLOC(len + strlen(CODE_SUFFIX) + 1);
366 if (code_file_name == 0)
367 no_space();
368 strcpy(code_file_name, file_prefix);
369 strcpy(code_file_name + len, CODE_SUFFIX);
370 }
371 else
372 code_file_name = output_file_name;
373
374 if (dflag)
375 {
376 if (jflag)
377 {
378 jclass_len = strlen(jclass_name);
379
380 defines_file_name = MALLOC(jclass_len + strlen(JAVA_INTERFACE_SUFFIX JAVA_OUTPUT_SUFFIX) + 1);/*rwj for 'Tokens.java\0' */
381 if (defines_file_name == 0) no_space();
382 strcpy(defines_file_name, jclass_name);
383 strcpy(defines_file_name + jclass_len, JAVA_INTERFACE_SUFFIX JAVA_OUTPUT_SUFFIX);
384 if (jimplement_name && strlen(jimplement_name)>0)
385 {
386 char *impl_name=MALLOC(strlen(jimplement_name)+jclass_len + strlen(JAVA_INTERFACE_SUFFIX)+2);
387
388 if (impl_name == 0) no_space();
389 strcpy(impl_name,jimplement_name);
390 jimplement_name=impl_name;
391 strcat(jimplement_name,",");
392 strcat(jimplement_name,jclass_name);
393 strcat(jimplement_name,JAVA_INTERFACE_SUFFIX);
394 }
395 else
396 {
397 jimplement_name = MALLOC(jclass_len + strlen(JAVA_INTERFACE_SUFFIX)+1);
398 if (jimplement_name == 0) no_space();
399 strcpy(jimplement_name,jclass_name);
400 strcpy(jimplement_name + jclass_len, JAVA_INTERFACE_SUFFIX);
401 }
402 }
403 else
404 {
405 defines_file_name = MALLOC(len + strlen(DEFINES_SUFFIX) + 1);
406 if (defines_file_name == 0)
407 no_space();
408 strcpy(defines_file_name, file_prefix);
409 strcpy(defines_file_name + len, DEFINES_SUFFIX);
410 }
411 }
412
413 if (vflag)
414 {
415 verbose_file_name = MALLOC(len + strlen(VERBOSE_SUFFIX) + 1);
416 if (verbose_file_name == 0)
417 no_space();
418 strcpy(verbose_file_name, file_prefix);
419 strcpy(verbose_file_name + len, VERBOSE_SUFFIX);
420 }
421 }
422
423
424
425 /* yio 20020304: copy the output from the temporary file to the
426 * final output file.
427 */
write_temporary_output(void)428 void write_temporary_output(void)
429 {
430 int len;
431 char buf[8192];
432 char *temp_output_file_name;
433 FILE *temp_output_file;
434
435 temp_output_file = output_file;
436 temp_output_file_name = output_file_name;
437 fclose(temp_output_file);
438 temp_output_file = fopen(temp_output_file_name,"r");
439 if (temp_output_file == 0)
440 open_error(temp_output_file_name);
441
442
443 /* construct the filename of the final output file */
444 if (jflag)/*rwj*/
445 {
446 len = strlen(jclass_name);
447
448 output_file_name = MALLOC(len + strlen(JAVA_OUTPUT_SUFFIX) + 1);/*rwj for '.java\0' */
449 if (output_file_name == 0) no_space();
450 strcpy(output_file_name, jclass_name);
451 strcpy(output_file_name + len, JAVA_OUTPUT_SUFFIX);
452 }
453 else
454 {
455 len = strlen(file_prefix);
456
457 output_file_name = MALLOC(len + strlen(OUTPUT_SUFFIX) + 1);
458 if (output_file_name == 0) no_space();
459 strcpy(output_file_name, file_prefix);
460 strcpy(output_file_name + len, OUTPUT_SUFFIX);
461 }
462
463 output_file = fopen(output_file_name, "w");
464 if (output_file == 0)
465 open_error(output_file_name);
466
467 if (!rflag) {
468 code_file_name = output_file_name;
469 code_file = output_file;
470 }
471
472
473 /* copy the output from the temp file to the output file */
474 do {
475 len = fread(buf,sizeof(char),8192,temp_output_file);
476 fwrite(buf,sizeof(char),len,output_file);
477 }
478 while (len > 0 && !feof(temp_output_file));
479
480 fclose(temp_output_file);
481 unlink(temp_output_file_name);
482 FREE(temp_output_file_name);
483 }
484
485
486
487
open_files(void)488 void open_files(void)
489 {
490 create_file_names();
491
492 if (input_file == 0)
493 {
494 input_file = fopen(input_file_name, "r");
495 if (input_file == 0)
496 open_error(input_file_name);
497 }
498
499 action_file = fopen(action_file_name, "w");
500 if (action_file == 0)
501 open_error(action_file_name);
502
503 text_file = fopen(text_file_name, "w");
504 if (text_file == 0)
505 open_error(text_file_name);
506
507 if (vflag)
508 {
509 verbose_file = fopen(verbose_file_name, "w");
510 if (verbose_file == 0)
511 open_error(verbose_file_name);
512 }
513
514 if (dflag)
515 {
516 defines_file = fopen(defines_file_name, "w");
517 if (defines_file == 0)
518 open_error(defines_file_name);
519 union_file = fopen(union_file_name, "w");
520 if (union_file == 0)
521 open_error(union_file_name);
522 }
523
524 output_file = fopen(output_file_name, "w");
525 if (output_file == 0)
526 open_error(output_file_name);
527
528 if (rflag)
529 {
530 code_file = fopen(code_file_name, "w");
531 if (code_file == 0)
532 open_error(code_file_name);
533 }
534 else
535 code_file = output_file;
536 }
537
538
main(int argc,char ** argv)539 int main(int argc,char **argv)
540 {
541 set_signals();
542 getargs(argc, argv);
543 open_files();
544 reader();
545
546 /* yio 20020304: write the output we stored in the temporary output file
547 * so that we could read arguments from the grammar file that may affect
548 * the name of the output file.
549 */
550 write_temporary_output();
551
552 lr0();
553 lalr();
554 make_parser();
555 verbose();
556 output();
557
558 done(0);
559 /*NOTREACHED*/
560 return 1;
561 }
562
563
564
565
566