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