1 /*
2  * main.c -- main program for PCCTS ANTLR.
3  *
4  * SOFTWARE RIGHTS
5  *
6  * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
7  * Set (PCCTS) -- PCCTS is in the public domain.  An individual or
8  * company may do whatever they wish with source code distributed with
9  * PCCTS or the code generated by PCCTS, including the incorporation of
10  * PCCTS, or its output, into commerical software.
11  *
12  * We encourage users to develop software with PCCTS.  However, we do ask
13  * that credit is given to us for developing PCCTS.  By "credit",
14  * we mean that if you incorporate our source code into one of your
15  * programs (commercial product, research project, or otherwise) that you
16  * acknowledge this fact somewhere in the documentation, research report,
17  * etc...  If you like PCCTS and have developed a nice tool with the
18  * output, please mention that you developed it using PCCTS.  In
19  * addition, we ask that this header remain intact in our source code.
20  * As long as these guidelines are kept, we expect to continue enhancing
21  * this system and expect to make other tools available as they are
22  * completed.
23  *
24  * ANTLR 1.33
25  * Terence Parr
26  * Parr Research Corporation
27  * with Purdue University and AHPCRC, University of Minnesota
28  * 1989-2001
29  */
30 
31 /* To set a breakpoint just before exit look for "cleanUp".    */
32 /* To set a breakpoint for fatal error look for "fatal_intern" */
33 
34 #include <stdio.h>
35 
36 #include "pcctscfg.h"
37 #include "stdpccts.h"
38 
39 #define MAX_INT_STACK 50
40 static int istack[MAX_INT_STACK];		/* Int stack */
41 static int isp = MAX_INT_STACK;
42 
43 static int DontAcceptFiles = 0;			/* if stdin, don't read files */
44 static int DontAcceptStdin = 0;			/* if files seen first, don't accept stdin */
45 
46 static int tnodes_used_in_guard_predicates_etc;     /* MR10 */
47 
48 		/* C m d - L i n e  O p t i o n  S t r u c t  &  F u n c s */
49 
50 typedef struct _Opt {
51 			char *option;
52 			int  arg;
53 #ifdef __cplusplus
54 			void (*process)(...);
55 #else
56 			void (*process)();
57 #endif
58 			char *descr;
59 		} Opt;
60 
61 #ifdef __USE_PROTOS
62 extern void ProcessArgs(int, char **, Opt *);
63 #else
64 extern void ProcessArgs();
65 #endif
66 
67 #ifdef __USE_PROTOS
ci_strequ(char * a,char * b)68 int ci_strequ(char *a,char *b)
69 #else
70 int ci_strequ(a,b)
71   char  *a;
72   char  *b;
73 #endif
74 {
75   for ( ;*a != 0 && *b != 0; a++, b++) {
76     if (toupper(*a) != toupper(*b)) return 0;
77   }
78   return (*a == *b);
79 }
80 
81 static void
82 #ifdef __USE_PROTOS
pStdin(void)83 pStdin( void )
84 #else
85 pStdin( )
86 #endif
87 {
88 	if ( DontAcceptStdin )
89 	{
90 		warnNoFL("'-' (stdin) ignored as files were specified first");
91 		return;
92 	}
93 
94 	require(NumFiles<MaxNumFiles,"exceeded max # of input files");
95 	FileStr[NumFiles++] = "stdin";
96 	DontAcceptFiles = 1;
97 }
98 
99 static void
100 #ifdef __USE_PROTOS
pFile(char * s)101 pFile( char *s )
102 #else
103 pFile( s )
104 char *s;
105 #endif
106 {
107 	if ( *s=='-' ) { warnNoFL( eMsg1("invalid option: '%s'",s) ); return; }
108 	if ( DontAcceptFiles )
109 	{
110 		warnNoFL(eMsg1("file '%s' ignored as '-' (stdin option) was specified first",s));
111 		return;
112 	}
113 
114 	require(NumFiles<MaxNumFiles,"exceeded max # of input files");
115 	FileStr[NumFiles++] = s;
116 	DontAcceptStdin = 1;
117 }
118 
119 /* MR14
120         Allow input to be a file containing a list of files
121         Bernard Giroud (b_giroud@decus.ch)
122 */
123 
124 static void
125 #ifdef __USE_PROTOS
pFileList(char * s,char * t)126 pFileList( char *s, char *t )
127 #else
128 pFileList( s, t )
129 char *s;
130 char *t;
131 #endif
132 {
133 #define MaxFLArea 1024
134 	FILE *fl;
135 	static char Fn_in_Fl[MaxFLArea] = "";
136         char one_fn[MaxFileName];
137 	char *flp = &Fn_in_Fl[0];
138 	int fnl, left = MaxFLArea, i;
139 
140 	if ( *t=='-' ) { warnNoFL( eMsg1("invalid option: '%s'",t) ); return; }
141 	if ( DontAcceptFiles )
142 	{
143 		warnNoFL(eMsg1("file '%s' ignored as '-' (stdin option) was specified first",t));
144 		return;
145 	}
146 
147         if ((fl = fopen(t, "r")) == NULL)
148 	{
149 		warnNoFL(eMsg1("file '%s' can't be opened", t));
150 		return;
151 	}
152         for (;;)
153 	{
154 		if (fgets(one_fn, 128 - 1, fl) == NULL)
155 			break;
156 		fnl = strlen(one_fn);
157 		require(fnl<=left, "no more room in File List Area");
158 		/* drop the trailing LF */
159 		if (one_fn[fnl - 1] == 0x0a) one_fn[fnl - 1] = ' ';
160 		strcat(Fn_in_Fl, one_fn);
161 		left = left - fnl;
162 		require(NumFiles<MaxNumFiles,"exceeded max # of input files");
163 		FileStr[NumFiles++] = flp;
164 		flp = flp + fnl;
165 	}
166 	fclose(fl);
167 	for (i=0;i < MaxFLArea;i++) if (Fn_in_Fl[i] == ' ') Fn_in_Fl[i] = '\0';
168 	DontAcceptStdin = 1;
169 }
170 
171 static void
172 #ifdef __USE_PROTOS
pLLK(char * s,char * t)173 pLLK( char *s, char *t )
174 #else
175 pLLK( s, t )
176 char *s;
177 char *t;
178 #endif
179 {
180 	LL_k = atoi(t);
181 	if ( LL_k <= 0 ) {
182 		warnNoFL("must have at least one token of lookahead (setting to 1)");
183 		LL_k = 1;
184 	}
185 }
186 
187 static void
188 #ifdef __USE_PROTOS
pCk(char * s,char * t)189 pCk( char *s, char *t )
190 #else
191 pCk( s, t )
192 char *s;
193 char *t;
194 #endif
195 {
196 	CLL_k = atoi(t);
197 	if ( CLL_k <= 0 ) {
198 		warnNoFL("must have at least one token of look-ahead (setting to 1)");
199 		CLL_k = 1;
200 	}
201 }
202 
203 static void						                                     /* MR6 */
204 #ifdef __USE_PROTOS
pTab(char * s,char * t)205 pTab( char *s, char *t )			                        	     /* MR6 */
206 #else
207 pTab( s, t )				                    		             /* MR6 */
208 char *s;							                                 /* MR6 */
209 char *t;							                                 /* MR6 */
210 #endif
211 {								                                     /* MR6 */
212 	TabWidth = atoi(t);					                             /* MR6 */
213 	if ( TabWidth < 0 || TabWidth > 8 ) {	            		     /* MR6 */
214 		warnNoFL("tab width must be between 1 and 8");               /* MR6 */
215 	  TabWidth=0;						                             /* MR6 */
216 	}							                                     /* MR6 */
217 }							                                         /* MR6 */
218 
219 static int ambAidDepthSpecified=0;                                   /* MR11 */
220 
221 static void						                                     /* MR11 */
222 #ifdef __USE_PROTOS
pAAd(char * s,char * t)223 pAAd( char *s, char *t )			                        	     /* MR11 */
224 #else
225 pAAd( s, t )				                    		             /* MR11 */
226 char *s;							                                 /* MR11 */
227 char *t;							                                 /* MR11 */
228 #endif
229 {								                                     /* MR11 */
230     ambAidDepthSpecified=1;                                          /* MR11 */
231 	MR_AmbAidDepth = atoi(t);				                         /* MR11 */
232 }							                                         /* MR11 */
233 
234 static void						                                     /* MR11 */
235 #ifdef __USE_PROTOS
pTreport(char * s,char * t)236 pTreport( char *s, char *t )			                       	     /* MR11 */
237 #else
238 pTreport( s, t )				                  		             /* MR11 */
239     char *s;							                             /* MR11 */
240     char *t;							                             /* MR11 */
241 #endif
242 {								                                     /* MR11 */
243 	TnodesReportThreshold = atoi(t);				                 /* MR11 */
244 }							                                         /* MR11 */
245 
246 #ifdef __USE_PROTOS
chkGTFlag(void)247 void chkGTFlag(void)	                                    /* 7-Apr-97 MR1 */
248 #else
249 void chkGTFlag()                                            /* 7-Apr-97 MR1 */
250 #endif
251 {
252 	if ( !GenAST )
253 		warn("#-variable or other AST item referenced w/o -gt option");
254 }
255 
256 
257 #ifdef __USE_PROTOS
pInfo(char * s,char * t)258 static void pInfo(char *s, char *t)                         /* MR10 */
259 #else
260 static void pInfo(s,t)                                      /* MR10 */
261   char  *s;
262   char  *t;
263 #endif
264 {
265   char  *p;
266   int   q;
267   for (p=t; *p != 0; p++) {
268     q=tolower(*p);
269     if (q=='t') {
270       InfoT=1;
271     } else if (q=='p') {
272       InfoP=1;
273     } else if (q=='m') {
274       InfoM=1;
275     } else if (q=='o') {
276       InfoO=1;
277     } else if (q=='0') {
278       ; /* nothing */
279     } else if (q=='f') {
280       InfoF=1;
281     } else {
282       warnNoFL(eMsgd("unrecognized -info option \"%c\"",(int)*p));
283     };
284   };
285 }
286 
287 #ifdef __USE_PROTOS
pCGen(void)288 static void pCGen(void)	{ CodeGen = FALSE; LexGen = FALSE; }
pLGen(void)289 static void pLGen(void)	{ LexGen = FALSE; }
pXTGen(void)290 static void pXTGen(void){ MR_Inhibit_Tokens_h_Gen = TRUE; }
pTGen(void)291 static void pTGen(void)	{ TraceGen = TRUE; }
pSGen(void)292 static void pSGen(void)	{ GenExprSetsOpt = FALSE; }
pPrt(void)293 static void pPrt(void)	{ PrintOut = TRUE; pCGen(); pLGen(); }
pPrtA(void)294 static void pPrtA(void)	{ PrintOut = TRUE; PrintAnnotate = TRUE; pCGen(); pLGen(); }
pAst(void)295 static void pAst(void)	{ GenAST = TRUE; }
pANSI(void)296 static void pANSI(void)	{ GenANSI = TRUE; }
pCr(void)297 static void pCr(void)	{ GenCR = TRUE; }
pNOPURIFY(void)298 static void pNOPURIFY(void)	{ PURIFY = FALSE; }
299 /*static void pCt(void)	{ warnNoFL("-ct option is now the default"); }*/
pLI(void)300 static void pLI(void)	{ GenLineInfo = TRUE; GenLineInfoMS = FALSE; } /* MR14 */
pLIms(void)301 static void pLIms(void)	{ GenLineInfo = TRUE; GenLineInfoMS = TRUE; }  /* MR14 */
pFr(char * s,char * t)302 static void pFr(char *s, char *t) {RemapFileName = t;}
pFe(char * s,char * t)303 static void pFe(char *s, char *t) {ErrFileName = t;}
pFl(char * s,char * t)304 static void pFl(char *s, char *t) {DlgFileName = t;}
pFm(char * s,char * t)305 static void pFm(char *s, char *t) {ModeFileName = t;}
pFt(char * s,char * t)306 static void pFt(char *s, char *t) {DefFileName = t;}
307 
pE1(void)308 static void pE1(void)	{ elevel = 1; }
pE2(void)309 static void pE2(void)	{ elevel = 2; }
pE3(void)310 static void pE3(void)	{ elevel = 3; }
pEGen(void)311 static void pEGen(void)	{ GenEClasseForRules = 1; }
pDL(void)312 static void pDL(void)
313 	{
314 	    DemandLookahead = 1;
315 	    if ( GenCC ) {
316 			warnNoFL("-gk does not work currently in C++ mode; -gk turned off");
317 			DemandLookahead = 0;
318 	    }
319 	}
320 
pAA(char * s,char * t)321 static void pAA(char *s,char *t) {MR_AmbAidRule = t;}               /* MR11 */
pAAm(char * s)322 static void pAAm(char *s){MR_AmbAidMultiple = 1;}                   /* MR11 */
pGHdr(void)323 static void pGHdr(void)	{ GenStdPccts = 1; }
pFHdr(char * s,char * t)324 static void pFHdr(char *s, char *t) { stdpccts = t; pGHdr(); }
pW1(void)325 static void pW1(void) { WarningLevel = 1; }
pNewAST(void)326 static void pNewAST(void) { NewAST = 1; }                           /* MR13 */
ptmakeInParser(void)327 static void ptmakeInParser(void) { tmakeInParser = 1; }             /* MR23 */
pAlpha(void)328 static void pAlpha(void) { AlphaBetaTrace = 1; }                    /* MR14 */
pMR_BlkErr(void)329 static void pMR_BlkErr(void) { MR_BlkErr = 1; }                     /* MR21 */
pStdout(void)330 static void pStdout(void) {UseStdout = 1; }		                    /* MR6 */
pW2(void)331 static void pW2(void) { WarningLevel = 2; }
pCC(void)332 static void pCC(void) { GenCC = TRUE; }
333 #else
pCGen()334 static void pCGen()	{ CodeGen = FALSE; LexGen = FALSE; }
pLGen()335 static void pLGen()	{ LexGen = FALSE; }
pXTGen()336 static void pXTGen(){ MR_Inhibit_Tokens_h_Gen = TRUE; }             /* MR14 */
pTGen()337 static void pTGen()	{ TraceGen = TRUE; }
pSGen()338 static void pSGen()	{ GenExprSetsOpt = FALSE; }
pPrt()339 static void pPrt()		{ PrintOut = TRUE; pCGen(); pLGen(); }
pPrtA()340 static void pPrtA()	{ PrintOut = TRUE; PrintAnnotate = TRUE; pCGen(); pLGen(); }
pAst()341 static void pAst()		{ GenAST = TRUE; }
pANSI()342 static void pANSI()	{ GenANSI = TRUE; }
pCr()343 static void pCr()		{ GenCR = TRUE; }
pNOPURIFY()344 static void pNOPURIFY()	{ PURIFY = FALSE; }
345 
346 /*static void pCt()		{ warnNoFL("-ct option is now the default"); }*/
pLI()347 static void pLI()	    { GenLineInfo = TRUE; GenLineInfoMS = FALSE; }  /* MR14 */
pLIms()348 static void pLIms()	    { GenLineInfo = TRUE; GenLineInfoMS = TRUE; }   /* MR14 */
pFr(s,t)349 static void pFr(s,t) char *s, *t; {RemapFileName = t;}
pFe(s,t)350 static void pFe(s,t) char *s, *t; {ErrFileName = t;}
pFl(s,t)351 static void pFl(s,t) char *s, *t; {DlgFileName = t;}
pFm(s,t)352 static void pFm(s,t) char *s, *t; {ModeFileName = t;}
pFt(s,t)353 static void pFt(s,t) char *s, *t; {DefFileName = t;}
354 
pE1()355 static void pE1()		{ elevel = 1; }
pE2()356 static void pE2()		{ elevel = 2; }
pE3()357 static void pE3()		{ elevel = 3; }
pEGen()358 static void pEGen()	{ GenEClasseForRules = 1; }
pDL()359 static void pDL()
360 	{
361 	    DemandLookahead = 1;
362 	    if ( GenCC ) {
363           warnNoFL("-gk does not work currently in C++ mode; -gk turned off");
364 	      DemandLookahead = 0;
365 	    }
366 	}
367 
pAA(s,t)368 static void pAA(s,t) char *s; char *t; {MR_AmbAidRule = t;}          /* MR11 BJS 20-Mar-98 */
pAAm(s)369 static void pAAm(s) char *s; {MR_AmbAidMultiple = 1;}                /* MR11 BJS 20-Mar-98 */
pGHdr()370 static void pGHdr()	{ GenStdPccts = 1; }
pFHdr(s,t)371 static void pFHdr(s,t) char *s, *t; { stdpccts = t; pGHdr(); }
pW1()372 static void pW1() { WarningLevel = 1; }
pNewAST()373 static void pNewAST() { NewAST = 1; }                                /* MR13 */
ptmakeInParser()374 static void ptmakeInParser() { tmakeInParser = 1; }                  /* MR23 */
pAlpha()375 static void pAlpha() { AlphaBetaTrace = 1; }                         /* MR14 */
pMR_BlkErr()376 static void pMR_BlkErr() { MR_BlkErr = 1; }                          /* MR21 */
pStdout()377 static void pStdout() {UseStdout = 1; }	                             /* MR6 */
pW2()378 static void pW2() { WarningLevel = 2; }
pCC()379 static void pCC() { GenCC = TRUE; }
380 #endif
381 
382 static void
383 #ifdef __USE_PROTOS
pPre(char * s,char * t)384 pPre( char *s, char *t )
385 #else
386 pPre( s, t )
387 char *s;
388 char *t;
389 #endif
390 {
391 	RulePrefix = t;
392 }
393 
394 static void
395 #ifdef __USE_PROTOS
pOut(char * s,char * t)396 pOut( char *s, char *t )
397 #else
398 pOut( s, t )
399 char *s;
400 char *t;
401 #endif
402 {
403 	OutputDirectory = t;
404 }
405 
406 static void
407 #ifdef __USE_PROTOS
pPred(void)408 pPred( void )
409 #else
410 pPred( )
411 #endif
412 {
413 	warnNoFL("-pr is no longer used (predicates employed if present); see -prc, -mrhoist, -mrhoistk");
414 /*
415 **	if ( DemandLookahead )
416 **		warnNoFL("-gk conflicts with -pr; -gk turned off");
417 **	DemandLookahead = 0;
418 **	HoistPredicateContext = 0;
419 */
420 }
421 
422 static void
423 #ifdef __USE_PROTOS
pPredCtx(char * s,char * t)424 pPredCtx( char *s, char *t )
425 #else
426 pPredCtx(s,t)
427 char *s;
428 char *t;
429 #endif
430 {
431 	if ( ci_strequ(t,"on")) HoistPredicateContext = 1;
432 	else if ( ci_strequ(t,"off")) HoistPredicateContext = 0;
433 	if ( DemandLookahead )
434 	{
435 		warnNoFL("-gk incompatible with semantic predicate usage; -gk turned off");
436 		DemandLookahead = 0;
437 	}
438 }
439 
440 static void
441 #ifdef __USE_PROTOS
pMRhoist(char * s,char * t)442 pMRhoist( char *s, char *t )
443 #else
444 pMRhoist(s,t)
445 char *s;
446 char *t;
447 #endif
448 {
449 	if ( ci_strequ(t,"on")) MRhoisting = 1;
450 	else if ( ci_strequ(t,"off")==0 ) MRhoisting = 0;
451     if (MRhoisting) {
452         fprintf(stderr,"Maintenance Release style hoisting enabled for predicates with lookahead depth = 1\n");
453         fprintf(stderr,"  No longer considered experimental\n");
454         fprintf(stderr,"  Can't consider suppression for predicates with lookahead depth > 1\n");
455         fprintf(stderr,"  Implies -prc on but does *not* imply -mrhoistk for k>1 predicates\n");
456         fprintf(stderr,"  This is a reminder, not a warning or error.\n");
457     };
458 }
459 
460 static void
461 #ifdef __USE_PROTOS
pMRhoistk(char * s,char * t)462 pMRhoistk( char *s, char *t )
463 #else
464 pMRhoistk(s,t)
465 char *s;
466 char *t;
467 #endif
468 {
469 	if ( ci_strequ(t,"on")) MRhoistingk = 1;
470 	else if ( ci_strequ(t,"off")==0 ) MRhoistingk = 0;
471     if (MRhoistingk) {
472         fprintf(stderr,"EXPERIMENTAL Maintenance Release style hoisting enabled\n");
473         fprintf(stderr,"  Applies to predicates with lookahead depth > 1\n");
474         fprintf(stderr,"  Implies -prc on and -mrhoist on\n");
475     };
476 }
477 
478 static void
479 #ifdef __USE_PROTOS
pTRes(char * s,char * t)480 pTRes( char *s, char *t )
481 #else
482 pTRes( s, t )
483 char *s;
484 char *t;
485 #endif
486 {
487 	TreeResourceLimit = atoi(t);
488 	if ( TreeResourceLimit <= 0 )
489 	{
490 		warnNoFL("analysis resource limit (# of tree nodes) must be greater than 0");
491 		TreeResourceLimit = -1; /* set to no limit */
492 	}
493 }
494 
495 Opt options[] = {
496 #ifdef __cplusplus
497     { "-CC", 0, (void (*)(...)) pCC,	"Generate C++ output (default=FALSE)"},
498     { "-ck", 1, (void (*)(...)) pCk,	"Set compressed lookahead depth; fast approximate lookahead"},
499     { "-cr", 0, (void (*)(...)) pCr,	"Generate cross reference (default=FALSE)"},
500     { "-e1", 0, (void (*)(...)) pE1,	"Ambiguities/errors shown in low detail (default)"},
501     { "-e2", 0, (void (*)(...)) pE2,	"Ambiguities/errors shown in more detail"},
502     { "-e3", 0, (void (*)(...)) pE3,
503     	"Ambiguities for k>1 grammars shown with exact tuples (not lookahead sets)"},
504     { "-f",  1, (void (*)(...)) pFileList,"Read names of grammar files from specified file"}, /* MR14 */
505     { "-fe", 1, (void (*)(...)) pFe,	"Rename err.c"},
506     { "-fh", 1, (void (*)(...)) pFHdr,	"Rename stdpccts.h header (turns on -gh)"},
507     { "-fl", 1, (void (*)(...)) pFl,	"Rename lexical output--parser.dlg"},
508     { "-fm", 1, (void (*)(...)) pFm,	"Rename mode.h"},
509     { "-fr", 1, (void (*)(...)) pFr,	"Rename remap.h"},
510     { "-ft", 1, (void (*)(...)) pFt,	"Rename tokens.h"},
511     { "-ga", 0, (void (*)(...)) pANSI,	"Generate ANSI-compatible code (default=FALSE)"},
512     { "-gc", 0, (void (*)(...)) pCGen,	"Do not generate output parser code (default=FALSE)"},
513     { "-gd", 0, (void (*)(...)) pTGen,	"Generate code to trace rule invocation (default=FALSE)"},
514     { "-ge", 0, (void (*)(...)) pEGen,	"Generate an error class for each non-terminal (default=FALSE)"},
515     { "-gh", 0, (void (*)(...)) pGHdr,	"Generate stdpccts.h for non-ANTLR-generated-files to include"},
516     { "-gk", 0, (void (*)(...)) pDL,	"Generate parsers that delay lookahead fetches until needed"},
517     { "-gl", 0, (void (*)(...)) pLI,	"Generate line info about grammar actions in parser"},
518     { "-glms", 0, (void (*)(...)) pLIms,"Like -gl but replace '\\' with '/' in #line filenames for MS C/C++ systems"},
519     { "-gp", 1, (void (*)(...)) pPre,	"Prefix all generated rule functions with a string"},
520     { "-gs", 0, (void (*)(...)) pSGen,	"Do not generate sets for token expression lists (default=FALSE)"},
521     { "-gt", 0, (void (*)(...)) pAst,	"Generate code for Abstract-Syntax-Trees (default=FALSE)"},
522     { "-gx", 0, (void (*)(...)) pLGen,	"Do not generate lexical (dlg-related) files (default=FALSE)"},
523     { "-gxt",0, (void (*)(...)) pXTGen,	"Do not generate tokens.h (default=FALSE)"},
524     { "-k",  1, (void (*)(...)) pLLK,	"Set full LL(k) lookahead depth (default==1)"},
525     { "-o",  1, (void (*)(...)) pOut,	OutputDirectoryOption},
526     { "-p",  0, (void (*)(...)) pPrt,	"Print out the grammar w/o actions (default=no)"},
527     { "-pa", 0, (void (*)(...)) pPrtA,	"Print out the grammar w/o actions & w/FIRST sets (default=no)"},
528     { "-pr",0, (void (*)(...)) pPred,	"no longer used; predicates employed if present"},
529     { "-prc", 1, (void (*)(...)) pPredCtx,"Turn on/off computation of context for hoisted predicates"},
530    	{ "-rl", 1, (void (*)(...)) pTRes,	"Limit max # of tree nodes used by grammar analysis"},
531     { "-stdout",0,  (void (*)(...)) pStdout,"Send grammar.c/grammar.cpp to stdout"},           /* MR6 */
532 	{ "-tab", 1, (void (*)(...)) pTab,	"Width of tabs (1 to 8) for grammar.c/grammar.cpp files"}, /* MR6 */
533 	{ "-w1", 0, (void (*)(...)) pW1,	"Set the warning level to 1 (default)"},
534 	{ "-w2", 0, (void (*)(...)) pW2,	"Ambiguities yield warnings even if predicates or (...)? block"},
535 	{ "-",   0, (void (*)(...)) pStdin,	"Read grammar from stdin" },
536     { "-mrhoist",1, (void (*)(...)) pMRhoist,                                                  /* MR9 */
537                                         "Turn on/off k=1 Maintenance Release style hoisting"},  /* MR9 */
538     { "-mrhoistk",1, (void (*)(...)) pMRhoistk,                                                  /* MR9 */
539                                         "Turn on/off EXPERIMENTAL k>1 Maintenance Release style hoisting"},  /* MR13 */
540     { "-aa"  , 1, (void (*)(...)) pAA,  "Ambiguity aid for a rule (rule name or line number)"},          /* MR11 */
541     { "-aam" , 0, (void (*)(...)) pAAm,
542                                          "Lookahead token may appear multiple times in -aa listing"},    /* MR11 */
543     { "-aad" , 1, (void (*)(...)) pAAd,
544                                          "Limits exp growth of -aa listing - default=1 (max=ck value)"}, /* MR11 */
545 	{ "-info", 1, (void (*)(...)) pInfo,
546       "Extra info: p=pred t=tnodes f=first/follow m=monitor o=orphans 0=noop"},                          /* MR12 */
547     { "-treport",1,(void (*)(...)) pTreport,
548                         "Report when tnode usage exceeds value during ambiguity resolution"},            /* MR11 */
549 	{ "-newAST", 0, (void (*)(...)) pNewAST,
550                  "In C++ mode use \"newAST(...)\" rather than \"new AST(...)\""},                        /* MR13 */
551 	{ "-tmake", 0, (void (*)(...)) ptmakeInParser,
552                  "In C++ mode use parser's tmake method rather than \"ASTBase::tmake(...)\""},			 /* MR23 */
553     { "-alpha",0,(void (*)(...)) pAlpha,
554                  "Provide additional information for \"(alpha)? beta\" error messages"},                 /* MR14 */
555     { "-mrblkerr",0,(void (*)(...)) pMR_BlkErr,                                        /* MR21 */
556                  "EXPERIMENTAL change to (...)* and (...)+ syntax error sets"},        /* MR21 */
557 	{ "-nopurify",0,(void (*)(...)) pNOPURIFY,
558 		"Don't use the notorious PURIFY macro (replaced by MR23 initial value syntax) to zero return arguments of rules"},   /* MR23 */
559     { "*",   0, (void (*)(...)) pFile, 	"" },	/* anything else is a file */
560 #else
561     { "-CC", 0, pCC,	"Generate C++ output (default=FALSE)"},
562     { "-cr", 0, pCr,	"Generate cross reference (default=FALSE)"},
563     { "-ck", 1, pCk,	"Set compressed lookahead depth; fast approximate lookahead"},
564     { "-e1", 0, pE1,	"Ambiguities/errors shown in low detail (default)"},
565     { "-e2", 0, pE2,	"Ambiguities/errors shown in more detail"},
566     { "-e3", 0, pE3,   	"Ambiguities for k>1 grammars shown with exact tuples (not lookahead sets)"},
567     { "-f",  1, pFileList,"Read names of grammar files from specified file"},   /* MR14 */
568     { "-fe", 1, pFe,	"Rename err.c"},
569     { "-fh", 1, pFHdr,	"Rename stdpccts.h header (turns on -gh)"},
570     { "-fl", 1, pFl,	"Rename lexical output--parser.dlg"},
571     { "-fm", 1, pFm,	"Rename mode.h"},
572     { "-fr", 1, pFr,	"Rename remap.h"},
573     { "-ft", 1, pFt,	"Rename tokens.h"},
574     { "-ga", 0, pANSI,	"Generate ANSI-compatible code (default=FALSE)"},
575     { "-gc", 0, pCGen,	"Do not generate output parser code (default=FALSE)"},
576     { "-gd", 0, pTGen,	"Generate code to trace rule invocation (default=FALSE)"},
577     { "-ge", 0, pEGen,	"Generate an error class for each non-terminal (default=FALSE)"},
578     { "-gh", 0, pGHdr,	"Generate stdpccts.h for non-ANTLR-generated-files to include"},
579     { "-gk", 0, pDL,	"Generate parsers that delay lookahead fetches until needed"},
580     { "-gl", 0, pLI,	"Generate line info about grammar actions in C parser"},
581     { "-glms", 0, pLIms,"Like -gl but replace '\\' with '/' in #line filenames for MS C/C++ systems"},
582     { "-gp", 1, pPre,	"Prefix all generated rule functions with a string"},
583     { "-gs", 0, pSGen,	"Do not generate sets for token expression lists (default=FALSE)"},
584     { "-gt", 0, pAst,	"Generate code for Abstract-Syntax-Trees (default=FALSE)"},
585     { "-gx", 0, pLGen,	"Do not generate lexical (dlg-related) files (default=FALSE)"},
586     { "-gxt",0, pXTGen,	"Do not generate tokens.h (default=FALSE)"},
587     { "-k",  1, pLLK,	"Set full LL(k) lookahead depth (default==1)"},
588     { "-o",  1, pOut,	OutputDirectoryOption},
589     { "-p",  0, pPrt,	"Print out the grammar w/o actions (default=no)"},
590     { "-pa", 0, pPrtA,	"Print out the grammar w/o actions & w/FIRST sets (default=no)"},
591     { "-pr",0, pPred,	"no longer used; predicates employed if present"},
592     { "-prc", 1, pPredCtx,"Turn on/off computation of context for hoisted predicates"},
593     { "-rl", 1, pTRes,	"Limit max # of tree nodes used by grammar analysis"},
594     { "-stdout",0, pStdout,	"Send grammar.c/grammar.cpp to stdout"},               /* MR6 */
595     { "-tab", 1, pTab,	"Width of tabs (1 to 8) for grammar.c/grammar.cpp files"}, /* MR6 */
596 	{ "-w1", 0, pW1,	"Set the warning level to 1 (default)"},
597 	{ "-w2", 0, pW2,	"Ambiguities yield warnings even if predicates or (...)? block"},
598     { "-mrhoist",1,pMRhoist,                                                       /* MR9 */
599                          "Turn on/off k=1 Maintenance Release style hoisting"},  /* MR9 */
600     { "-mrhoistk",1,pMRhoistk,                                                       /* MR13 */
601                          "Turn on/off k>1 EXPERIMENTAL Maintenance Release style hoisting"},  /* MR13 */
602     { "-aa"  ,1,pAA,     "Ambiguity aid for a rule (rule name or line number)"},          /* MR11 */
603     { "-aam" ,0,pAAm,
604                          "Lookahead token may appear multiple times in -aa listing"},     /* MR11 */
605     { "-aad" ,1,pAAd,
606                          "Limits exp growth of -aa listing - default=1 (max=ck value)"},  /* MR11 */
607 	{ "-info",1,pInfo,
608       "Extra info: p=pred t=tnodes f=first/follow m=monitor o=orphans 0=noop"},           /* MR11 */
609     { "-treport",1,pTreport,
610                         "Report when tnode usage exceeds value during ambiguity resolution"},   /* MR11 */
611 	{ "-newAST", 0, pNewAST,
612                  "In C++ mode use \"newAST(...)\" rather than \"new AST(...)\""},         /* MR13 */
613 	{ "-tmake", 0, ptmakeInParser,
614                  "In C++ mode use parser's tmake method rather than \"ASTBase::tmake(...)\""},   /* MR23 */
615     { "-alpha",0, pAlpha,
616                  "Provide additional information for \"(alpha)? beta\" error messages"},  /* MR14 */
617     { "-mrblkerr",0,pMR_BlkErr,                                                           /* MR21 */
618                  "EXPERIMENTAL change to (...)* and (...)+ syntax error sets"},           /* MR21 */
619 	{ "-nopurify",0,pNOPURIFY,
620 		"Don't use the notorious PURIFY macro (replaced by MR23 initial value syntax) to zero return arguments of rules"},   /* MR23 */
621 	{ "-",   0, pStdin,	"Read grammar from stdin" },
622 	{ "*",   0, pFile, 	"" },	/* anything else is a file */
623 #endif
624 	{ NULL,  0, NULL }
625  };
626 
627 void readDescr();
628 void cleanUp();
629 
630 #ifdef __USE_PROTOS
631 static void buildRulePtr( void );
632 static void help( void );
633 static void init( void );
634 static void CompleteTokenSetRefs( void );
635 static void ensure_no_C_file_collisions(char *);
636 static void CompleteContextGuards(void);
637 #else
638 static void buildRulePtr( );
639 static void help( );
640 static void init( );
641 static void CompleteTokenSetRefs( );
642 static void ensure_no_C_file_collisions();
643 static void CompleteContextGuards();
644 #endif
645 
646 static void
647 #ifdef __USE_PROTOS  /* <BJS> */
report_numericPredLabels(ActionNode * a)648 report_numericPredLabels(ActionNode *a)
649 #else
650 report_numericPredLabels(a)
651 ActionNode *a;
652 #endif
653 {                                                                           /* MR10 */
654   warnFL("numeric references to attributes (e.g. $i or $i.j) in semantic pred will be null during guess mode",  /* MR10 */
655             FileStr[a->file],a->line);                                      /* MR10 */
656 }                                                                           /* MR10 */
657 
658 								/* M a i n */
659 
660 int
661 #ifdef __USE_PROTOS
main(int argc,char * argv[])662 main( int argc, char *argv[] )
663 #else
664 main( argc, argv )
665 int argc;
666 char *argv[];
667 #endif
668 {
669 	int i;
670 	static char EPSTR[] = "[Ep]";
671 
672     Save_argc=argc;                                                  /* MR10 */
673     Save_argv=argv;                                                  /* MR10 */
674 
675 /*	malloc_debug(8);*/
676 
677 #ifdef SPECIAL_INITS
678     special_inits();                                                 /* MR1 */
679 #endif
680 	fprintf(stderr, "Antlr parser generator   Version %s   1989-2001\n", Version);
681 	if ( argc == 1 ) { help(); zzDIE; }
682 	ProcessArgs(argc-1, &(argv[1]), options);
683 
684 /* MR14 */    if (MR_AmbAidRule && AlphaBetaTrace) {
685 /* MR14 */       fatal("Can't specify both -aa (ambiguity aid) and -alpha (\"(alpha)? beta\" aid)");
686 /* MR14 */    }
687 
688     if (MRhoistingk) {              /* MR13 */
689       HoistPredicateContext=1;      /* MR13 */
690       MRhoisting=1;                 /* MR13 */
691     };                              /* MR13 */
692     if (MRhoisting && ! HoistPredicateContext) {
693 /***      warnNoFL("Using \"-mrhoist\" forces \"-prc on\"");    ***/
694       HoistPredicateContext=1;
695     };
696     if (HoistPredicateContext && ! MRhoisting) {
697         warnNoFL("When using predicate context (-prc on) -mrhoist on is recommended");
698     }
699 	/* Fix lookahead depth */
700 	/* Compressed lookahead must always be larger than or equal to full lookahead */
701 	if ( CLL_k < LL_k  && CLL_k>0 )
702 	{
703 		warnNoFL("must have compressed lookahead >= full LL(k) lookahead (setting -ck to -k)");
704 		CLL_k = LL_k;
705 	}
706 	if ( CLL_k == -1 ) CLL_k = LL_k;
707 	OutputLL_k = CLL_k;
708 	if ( ((CLL_k-1)&CLL_k)!=0 ) { /* output ll(k) must be power of 2 */
709 		int n;
710 		for(n=1; n<CLL_k; n<<=1) {;}
711 		OutputLL_k = n;
712 	};
713 
714 	if (MR_BlkErr) {
715 		warnNoFL("The -mrblkerr option is EXPERIMENTAL");
716         if (LL_k > 1) {
717     		warnNoFL("The -mrblkerr option is designed only for k=1 ck=1 grammars");
718         }
719 	};
720 
721     if ( ! ambAidDepthSpecified) {
722       MR_AmbAidDepth=1;
723     } else {
724       if (MR_AmbAidDepth > CLL_k || MR_AmbAidDepth <= 0) {
725         warnNoFL(eMsgd(
726             "Ambiguity aid depth (\"-aad ...\") must be a number between 1 and max(k,ck)=%d",CLL_k));
727         MR_AmbAidDepth=1;
728       };
729       if (MR_AmbAidDepth == 0) {
730         MR_AmbAidDepth=2;
731       };
732     };
733 
734     if (MR_AmbAidRule != NULL) MR_AmbAidLine=atoi(MR_AmbAidRule);
735 
736 	fpTrans = &(C_Trans[0]);		/* Translate to C Language */
737 	fpJTrans = &(C_JTrans[0]);
738 	init();
739 	lexclass(LexStartSymbol);
740 
741 	readDescr();
742 	LastTokenCounted = TokenNum;
743 	RemapForcedTokens();
744 	if ( CannotContinue ) {cleanUp(); zzDIE;}
745 	if ( GenCC && no_classes_found ) fatal("required grammar class not found (exiting...)");
746 	if ( WarningLevel>1 && HdrAction == NULL )
747 	   warnNoFL("no #header action was found");
748 	if ( FoundAtOperator && ! FoundExceptionGroup) {
749 	   warnNoFL("found the exception operator '@' - but no exception group was found");
750 	};
751 	EpToken = addTname(EPSTR);		/* add imaginary token epsilon */
752 	set_orel(EpToken, &imag_tokens);
753 
754 	/* this won't work for hand-built scanners since EofToken is not
755 	 * known.  Forces EOF to be token type 1.
756 	 */
757 	set_orel(EofToken, &imag_tokens);
758 
759 	set_size(NumWords(TokenNum-1));
760 
761 	/* compute the set of all known token types
762 	 * It represents the set of tokens from 1 to last_token_num + the
763 	 * reserved positions above that (if any).  Don't include the set of
764 	 * imaginary tokens such as the token/error classes or EOF.
765 	 */
766 	{
767 		set a;
768 		a = set_dup(reserved_positions);
769 		for (i=1; i<TokenNum; i++) { set_orel(i, &a); }
770 		all_tokens = set_dif(a, imag_tokens);
771 		set_free(a);
772 	}
773 
774 	ComputeTokSets();				/* Compute #tokclass sets */
775 	CompleteTokenSetRefs();			/* Change complex nodes in syn diag */
776     CompleteContextGuards();        /* MR13 */
777 
778 	if ( CodeGen ) genDefFile();	/* create tokens.h */
779 	if ( LexGen ) genLexDescr();	/* create parser.dlg */
780 
781 	if ( GenStdPccts )
782 	{
783 		FILE *f = fopen(OutMetaName(stdpccts), "w");
784 		if ( f==NULL ) {warnNoFL( eMsg1("can't create %s",OutMetaName(stdpccts)) );}
785 		else
786 		{
787 #ifdef SPECIAL_FOPEN
788 			special_fopen_actions(OutMetaName(stdpccts));            /* MR1 */
789 #endif
790             if (strcmp(stdpccts,"stdpccts.h") == 0) {                /* MR10 */
791  	  	      genStdPCCTSIncludeFile(f,NULL);                        /* MR10 */
792             } else {                                                 /* MR10 */
793  	  	      genStdPCCTSIncludeFile(f,pcctsBaseName(stdpccts));     /* MR32 */
794             };
795 			fclose(f);
796 		}
797 	}
798 
799 	buildRulePtr();					/* create mapping from rule # to RuleBlk junction */
800 	ComputeErrorSets();
801 	FoLink( (Node *)SynDiag );		/* add follow links to end of all rules */
802 
803 	if ( GenCR ) GenCrossRef( SynDiag );
804 
805 	if ( CodeGen )
806 	{
807 		if ( SynDiag == NULL )
808 		{
809 			warnNoFL("no grammar description recognized");
810 			cleanUp();
811 			zzDIE;
812 		}
813 		else if ( !GenCC ) {
814 			ErrFile = fopen(OutMetaName(ErrFileName), "w");
815 			require(ErrFile != NULL, "main: can't open err file");
816 #ifdef SPECIAL_FOPEN
817 	              special_fopen_actions(OutMetaName(ErrFileName));   /* MR1 */
818 #endif
819 			NewSetWd();
820 			GenErrHdr();
821 			TRANS(SynDiag);			/* Translate to the target language */
822 			DumpSetWd();
823 			DumpRemainingTokSets();
824 			fclose( ErrFile );
825 		}
826 		else {
827 			strcpy(Parser_h_Name, CurrentClassName);
828 			strcat(Parser_h_Name, ".h");
829 			strcpy(Parser_c_Name, CurrentClassName);
830 			strcat(Parser_c_Name, CPP_FILE_SUFFIX);
831 			ensure_no_C_file_collisions(Parser_c_Name);
832 			Parser_h = fopen(OutMetaName(Parser_h_Name), "w");
833 			require(Parser_h != NULL, "main: can't open class Parserx.h file");
834 #ifdef SPECIAL_FOPEN
835 		    special_fopen_actions(OutMetaName(Parser_h_Name));       /* MR1 */
836 #endif
837 			Parser_c = fopen(OutMetaName(Parser_c_Name), "w");
838 			require(Parser_c != NULL, "main: can't open class Parserx.c file");
839 #ifdef SPECIAL_FOPEN
840 		    special_fopen_actions(OutMetaName(Parser_c_Name));       /* MR1 */
841 #endif
842 			GenParser_h_Hdr();
843 			if ( class_before_actions != NULL )
844 			{
845 				ListNode *p;
846 				for (p = class_before_actions->next; p!=NULL; p=p->next)
847 				{
848 					UserAction *ua = (UserAction *)p->elem;
849 					dumpAction( ua->action, Parser_h, 0, ua->file, ua->line, 1);
850 				}
851 			}
852 			GenParser_c_Hdr();
853 			fprintf(Parser_h, "protected:\n");  /* MR20 */
854 			NewSetWd();
855 			TRANS(SynDiag);			/* Translate to the target language */
856 			DumpSetWd();
857 			GenRuleMemberDeclarationsForCC(Parser_h, SynDiag);
858 			if ( class_after_actions != NULL )
859 			{
860 				ListNode *p;
861 				for (p = class_after_actions->next; p!=NULL; p=p->next)
862 				{
863 					UserAction *ua = (UserAction *)p->elem;
864 					dumpAction( ua->action, Parser_h, 0, ua->file, ua->line, 1);
865 				}
866 			}
867 			DumpRemainingTokSets();
868 			fprintf(Parser_h, "};\n");
869 			fprintf(Parser_h, "\n#endif /* %s_h */\n", CurrentClassName);
870 			fclose( Parser_h );
871 			fclose( Parser_c );
872 		}
873 	}
874 
875     MR_orphanRules(stderr);
876     if (LTinTokenAction && WarningLevel >= 2) {
877 		if (GenCC) {
878 			warnNoFL("At least one <<action>> following a token match contains a reference to LT(...)\n      this will reference the immediately preceding token,\n      not the one which follows as is the case with semantic predicates.");
879 		}
880 			warnNoFL("At least one <<action>> following a token match contains a reference to LA(...) or LATEXT(...)\n      this will reference the immediately preceding token,\n      not the one which follows as is the case with semantic predicates.");
881 	}
882 
883 	if ( PrintOut )
884 	{
885 		if ( SynDiag == NULL ) {warnNoFL("no grammar description recognized");}
886 		else PRINT(SynDiag);
887 	}
888 
889 #ifdef DBG_LL1
890 #endif
891 	GenRemapFile();					/* create remap.h */
892 /* MR10 */    if (FoundGuessBlk) {
893 #ifdef __cplusplus__
894 /* MR10 */      list_apply(NumericPredLabels, (void (*)(void *))report_numericPredLabels);
895 #else
896 #ifdef __USE_PROTOS
897 /* MR10 */      list_apply(NumericPredLabels, (void (*)(void *))report_numericPredLabels);
898 #else
899 /* MR10 */      list_apply(NumericPredLabels,report_numericPredLabels);
900 #endif
901 #endif
902 /* MR10 */    };
903 
904     if (InfoT && TnodesAllocated > 0) {
905       if (TnodesPeak > 10000) {
906         fprintf(stdout,"\nTree Nodes:  peak %dk  created %dk  lost %d\n",
907                         (TnodesPeak/1000),
908                         (TnodesAllocated/1000),
909                         TnodesInUse-tnodes_used_in_guard_predicates_etc);
910        } else {
911          fprintf(stdout,"\nTree Nodes:  peak %d  created %d  lost %d\n",
912                         TnodesPeak,
913                         TnodesAllocated,
914                         TnodesInUse-tnodes_used_in_guard_predicates_etc);
915        };
916     };
917     if (InfoF) {
918       DumpFcache();
919     };
920     if (MR_skipped_e3_report) {
921       fprintf(stderr,"note: use -e3 to get exact information on ambiguous tuples\n");
922     };
923     if (MR_BadExprSets != 0) {
924       fprintf(stderr,"note: Unreachable C or C++ code was generated for empty expression sets,\n");
925       fprintf(stderr,"        probably due to undefined rules or infinite left recursion.\n");
926       fprintf(stderr,"      To locate: search the generated code for \"empty set expression\"\n");
927     };
928     if (MR_AmbAidRule != NULL && MR_matched_AmbAidRule==0) {
929       RuleEntry *q = (RuleEntry *) hash_get(Rname,MR_AmbAidRule);
930       if (MR_AmbAidLine == 0 && q == NULL) {
931          warnNoFL(eMsg2("there is no rule \"%s\" so \"-aa %s\" will never match",
932                                                         MR_AmbAidRule,MR_AmbAidRule));
933       } else {
934         warnNoFL(eMsg1("there was no ambiguity that matched \"-aa %s\"",MR_AmbAidRule));
935       };
936     };
937     if (AlphaBetaTrace) {
938 
939       if (MR_AlphaBetaMessageCount == 0) {
940          fprintf(stderr,"note: there were no messages about \"(alpha)? beta\" blocks added to the generated code\n");
941       } else {
942          fprintf(stderr,"note: there were %d messages about \"(alpha)? beta\" blocks added to the generated code\n",
943                     MR_AlphaBetaMessageCount);
944       }
945 
946       if (set_null(MR_CompromisedRules)) {
947          fprintf(stderr,"note: the list of rules with compromised follow sets is empty\n");
948       } else {
949          fprintf(stderr,"note: the following is a list of rules which *may* have incorrect\n");
950          fprintf(stderr,"      follow sets computed as a result of an \"(alpha)? beta\" block\n");
951          fprintf(stderr,"\n");
952          MR_dumpRuleSet(MR_CompromisedRules);
953          fprintf(stderr,"\n");
954       }
955     }
956 	cleanUp();
957 	exit(PCCTS_EXIT_SUCCESS);
958     return 0;           /* MR11 make compilers happy */
959 }
960 
961 static void
962 #ifdef __USE_PROTOS
init(void)963 init( void )
964 #else
965 init( )
966 #endif
967 {
968 	SignalEntry *q;
969 
970 	Tname = newHashTable();
971 	Rname = newHashTable();
972 	Fcache = newHashTable();
973 	Tcache = newHashTable();
974 	Sname = newHashTable();
975     Pname = newHashTable();     /* MR11 */
976 
977 	/* Add default signal names */
978 	q = (SignalEntry *)hash_add(Sname,
979 							  "NoViableAlt",
980 							  (Entry *)newSignalEntry("NoViableAlt"));
981 	require(q!=NULL, "cannot alloc signal entry");
982 	q->signum = sigNoViableAlt;
983 	q = (SignalEntry *)hash_add(Sname,
984 							  "MismatchedToken",
985 							  (Entry *)newSignalEntry("MismatchedToken"));
986 	require(q!=NULL, "cannot alloc signal entry");
987 	q->signum = sigMismatchedToken;
988 	q = (SignalEntry *)hash_add(Sname,
989 							  "NoSemViableAlt",
990 							  (Entry *)newSignalEntry("NoSemViableAlt"));
991 	require(q!=NULL, "cannot alloc signal entry");
992 	q->signum = sigNoSemViableAlt;
993 
994 	reserved_positions = empty;
995 	all_tokens = empty;
996 	imag_tokens = empty;
997 	tokclasses = empty;
998 	TokenStr = (char **) calloc(TSChunk, sizeof(char *));
999 	require(TokenStr!=NULL, "main: cannot allocate TokenStr");
1000 	FoStack = (int **) calloc(CLL_k+1, sizeof(int *));
1001 	require(FoStack!=NULL, "main: cannot allocate FoStack");
1002 	FoTOS = (int **) calloc(CLL_k+1, sizeof(int *));
1003 	require(FoTOS!=NULL, "main: cannot allocate FoTOS");
1004 	Cycles = (ListNode **) calloc(CLL_k+1, sizeof(ListNode *));
1005 	require(Cycles!=NULL, "main: cannot allocate Cycles List");
1006     MR_CompromisedRules=empty;  /* MR14 */
1007 }
1008 
1009 static void
1010 #ifdef __USE_PROTOS
help(void)1011 help( void )
1012 #else
1013 help( )
1014 #endif
1015 {
1016 	Opt *p = options;
1017 	fprintf(stderr, "antlr [options] f1 f2 ... fn\n");
1018 	while ( *(p->option) != '*' )
1019 	{
1020 		fprintf(stderr, "    %-9s%s   %s\n",
1021 						p->option,
1022 						(p->arg)?"___":"   ",
1023 						p->descr);
1024 		p++;
1025 	}
1026 }
1027 
1028 /* The RulePtr array is filled in here.  RulePtr exists primarily
1029  * so that sets of rules can be maintained for the FOLLOW caching
1030  * mechanism found in rJunc().  RulePtr maps a rule num from 1 to n
1031  * to a pointer to its RuleBlk junction where n is the number of rules.
1032  */
1033 static void
1034 #ifdef __USE_PROTOS
buildRulePtr(void)1035 buildRulePtr( void )
1036 #else
1037 buildRulePtr( )
1038 #endif
1039 {
1040 	int r=1;
1041 	Junction *p  = SynDiag;
1042 	RulePtr = (Junction **) calloc(NumRules+1, sizeof(Junction *));
1043 	require(RulePtr!=NULL, "cannot allocate RulePtr array");
1044 
1045 	while ( p!=NULL )
1046 	{
1047 		require(r<=NumRules, "too many rules???");
1048 		RulePtr[r++] = p;
1049 		p = (Junction *)p->p2;
1050 	}
1051 }
1052 
1053 void
1054 #ifdef __USE_PROTOS
dlgerror(const char * s)1055 dlgerror(const char *s)
1056 #else
1057 dlgerror(s)
1058 char *s;
1059 #endif
1060 {
1061 	fprintf(stderr, ErrHdr, FileStr[CurFile], zzline);
1062 	fprintf(stderr, " lexical error: %s (text was '%s')\n",
1063 					((s == NULL) ? "Lexical error" : s), zzlextext);
1064 }
1065 
1066 void
1067 #ifdef __USE_PROTOS
readDescr(void)1068 readDescr( void )
1069 #else
1070 readDescr( )
1071 #endif
1072 {
1073 	zzerr = dlgerror;
1074 	input = NextFile();
1075 	if ( input==NULL ) fatal("No grammar description found (exiting...)");
1076 	ANTLR(grammar(), input);
1077     tnodes_used_in_guard_predicates_etc=TnodesInUse;    /* MR10 */
1078 }
1079 
1080 FILE *
1081 #ifdef __USE_PROTOS
NextFile(void)1082 NextFile( void )
1083 #else
1084 NextFile( )
1085 #endif
1086 {
1087 	FILE *f;
1088 
1089 	for (;;)
1090 	{
1091 		CurFile++;
1092 		if ( CurFile >= NumFiles ) return(NULL);
1093 		if ( ci_strequ(FileStr[CurFile],"stdin")) return stdin;
1094 		f = fopen(FileStr[CurFile], "r");
1095 		if ( f == NULL )
1096 		{
1097 			warnNoFL( eMsg1("file %s doesn't exist; ignored", FileStr[CurFile]) );
1098 		}
1099 		else
1100 		{
1101 			return(f);
1102 		}
1103 	}
1104 }
1105 
1106 /*
1107  * Return a string corresponding to the output file name associated
1108  * with the input file name passed in.
1109  *
1110  * Observe the following rules:
1111  *
1112  *		f.e		--> f".c"
1113  *		f		--> f".c"
1114  *		f.		--> f".c"
1115  *		f.e.g	--> f.e".c"
1116  *
1117  * Where f,e,g are arbitrarily long sequences of characters in a file
1118  * name.
1119  *
1120  * In other words, if a ".x" appears on the end of a file name, make it
1121  * ".c".  If no ".x" appears, append ".c" to the end of the file name.
1122  *
1123  * C++ mode using .cpp not .c.
1124  *
1125  * Use malloc() for new string.
1126  */
1127 
1128 char *
1129 #ifdef __USE_PROTOS
outname(char * fs)1130 outname( char *fs )
1131 #else
1132 outname( fs )
1133 char *fs;
1134 #endif
1135 {
1136     if ( GenCC) {
1137       return outnameX(fs,CPP_FILE_SUFFIX);
1138     } else {
1139       return outnameX(fs,".c");
1140     };
1141 }
1142 
1143 char *
1144 #ifdef __USE_PROTOS
outnameX(char * fs,char * suffix)1145 outnameX( char *fs ,char *suffix)
1146 #else
1147 outnameX( fs , suffix )
1148 char *fs;
1149 char *suffix;
1150 #endif
1151 {
1152 	static char buf[MaxFileName+1];
1153 	char *p;
1154 	require(fs!=NULL&&*fs!='\0', "outname: NULL filename");
1155 
1156 	p = buf;
1157 	strcpy(buf, fs);
1158 	while ( *p != '\0' )  {p++;}			/* Stop on '\0' */
1159 	while ( *p != '.' && p != buf ) {--p;}	/* Find '.' */
1160 	if ( p != buf ) *p = '\0';				/* Found '.' */
1161 	require(strlen(buf) + 2 < (size_t)MaxFileName, "outname: filename too big");
1162     strcat(buf,suffix);
1163 	return( buf );
1164 }
1165 
1166 void
1167 #ifdef __USE_PROTOS
fatalFL(char * err_,char * f,int l)1168 fatalFL( char *err_, char *f, int l )
1169 #else
1170 fatalFL( err_, f, l )
1171 char *err_;
1172 char *f;
1173 int l;
1174 #endif
1175 {
1176 	fprintf(stderr, ErrHdr, f, l);
1177 	fprintf(stderr,	" %s\n", err_);
1178 	cleanUp();
1179 	exit(PCCTS_EXIT_FAILURE);
1180 }
1181 
1182 void
1183 #ifdef __USE_PROTOS
fatal_intern(char * err_,char * f,int l)1184 fatal_intern( char *err_, char *f, int l )
1185 #else
1186 fatal_intern( err_, f, l )
1187 char *err_;
1188 char *f;
1189 int l;
1190 #endif
1191 {
1192 	fprintf(stderr, ErrHdr, f, l);
1193 	fprintf(stderr,	" #$%%*&@# internal error: %s\n", err_);
1194 	fprintf(stderr, ErrHdr, f, l);
1195 	fprintf(stderr, " [complain to nearest government official\n");
1196 	fprintf(stderr, ErrHdr, f, l);
1197 	fprintf(stderr, "  or send hate-mail to parrt@parr-research.com;\n");
1198 	fprintf(stderr, ErrHdr, f, l);
1199 	fprintf(stderr, "  please pray to the ``bug'' gods that there is a trival fix.]\n");
1200 	cleanUp();
1201 	exit(PCCTS_EXIT_FAILURE);
1202 }
1203 
1204 void
1205 #ifdef __USE_PROTOS
cleanUp(void)1206 cleanUp( void )
1207 #else
1208 cleanUp( )
1209 #endif
1210 {
1211 	if ( DefFile != NULL) fclose( DefFile );
1212 }
1213 
1214 /* sprintf up to 3 strings */
1215 char *
1216 #ifdef __USE_PROTOS
eMsg3(char * s,char * a1,char * a2,char * a3)1217 eMsg3( char *s, char *a1, char *a2, char *a3 )
1218 #else
1219 eMsg3( s, a1, a2, a3 )
1220 char *s;
1221 char *a1;
1222 char *a2;
1223 char *a3;
1224 #endif
1225 {
1226 	static char buf[250];			/* DANGEROUS as hell !!!!!! */
1227 
1228 	sprintf(buf, s, a1, a2, a3);
1229 	return( buf );
1230 }
1231 
1232 /* sprintf a decimal */
1233 char *
1234 #ifdef __USE_PROTOS
eMsgd(char * s,int d)1235 eMsgd( char *s, int d )
1236 #else
1237 eMsgd( s, d )
1238 char *s;
1239 int d;
1240 #endif
1241 {
1242 	static char buf[250];			/* DANGEROUS as hell !!!!!! */
1243 
1244 	sprintf(buf, s, d);
1245 	return( buf );
1246 }
1247 
1248 char *
1249 #ifdef __USE_PROTOS
eMsgd2(char * s,int d1,int d2)1250 eMsgd2( char *s, int d1,int d2)
1251 #else
1252 eMsgd2( s, d1, d2 )
1253 char *s;
1254 int d1;
1255 int d2;
1256 #endif
1257 {
1258 	static char buf[250];			/* DANGEROUS as hell !!!!!! */
1259 
1260 	sprintf(buf, s, d1, d2);
1261 	return( buf );
1262 }
1263 
1264 void
1265 #ifdef __USE_PROTOS
s_fprT(FILE * f,set e)1266 s_fprT( FILE *f, set e )
1267 #else
1268 s_fprT( f, e )
1269 FILE *f;
1270 set e;
1271 #endif
1272 {
1273 	register unsigned *p;
1274 	unsigned *q;
1275 
1276 	if ( set_nil(e) ) return;
1277 	if ( (q=p=set_pdq(e)) == NULL ) fatal_internal("Can't alloc space for set_pdq");
1278 	fprintf(f, "{");
1279 	while ( *p != nil )
1280 	{
1281 		fprintf(f, " %s", TerminalString(*p));
1282 		p++;
1283 	}
1284 	fprintf(f, " }");
1285 	free((char *)q);
1286 }
1287 
1288 /* Return the token name or regular expression for a token number. */
1289 char *
1290 #ifdef __USE_PROTOS
TerminalString(int token)1291 TerminalString( int token )
1292 #else
1293 TerminalString( token )
1294 int token;
1295 #endif
1296 {
1297 	int     j;
1298         static    char    imag_name[20];
1299 
1300 	/* look in all lexclasses for the token */
1301 	if ( TokenString(token) != NULL ) return TokenString(token);
1302 	for (j=0; j<NumLexClasses; j++)
1303 	{
1304 		lexmode(j);
1305 		if ( ExprString(token) != NULL ) return ExprString(token);
1306 	}
1307 
1308     if (1) {
1309       sprintf(imag_name,"UnknownToken#%d",token);           /* MR13 */
1310       return imag_name;                                     /* MR13 */
1311     }
1312 
1313 	require(j<NumLexClasses, eMsgd("No label or expr for token %d",token));
1314 	return "invalid";
1315 }
1316 
1317                     /* S i m p l e  I n t  S t a c k */
1318 
1319 void
1320 #ifdef __USE_PROTOS
pushint(int i)1321 pushint( int i )
1322 #else
1323 pushint( i )
1324 int i;
1325 #endif
1326 {
1327 	require(isp>0, "pushint: stack overflow");
1328 	istack[--isp] = i;
1329 }
1330 
1331 int
1332 #ifdef __USE_PROTOS
popint(void)1333 popint( void )
1334 #else
1335 popint( )
1336 #endif
1337 {
1338 	require(isp<MAX_INT_STACK, "popint: stack underflow");
1339 	return istack[isp++];
1340 }
1341 
1342 int
1343 #ifdef __USE_PROTOS
istacksize(void)1344 istacksize( void )
1345 #else
1346 istacksize( )
1347 #endif
1348 {
1349 	return MAX_INT_STACK-isp;
1350 }
1351 
1352 void
1353 #ifdef __USE_PROTOS
istackreset(void)1354 istackreset( void )
1355 #else
1356 istackreset( )
1357 #endif
1358 {
1359 	isp = MAX_INT_STACK;
1360 }
1361 
1362 int
1363 #ifdef __USE_PROTOS
istackempty(void)1364 istackempty( void )
1365 #else
1366 istackempty( )
1367 #endif
1368 {
1369 	return isp==MAX_INT_STACK;
1370 }
1371 
1372 int
1373 #ifdef __USE_PROTOS
topint(void)1374 topint( void )
1375 #else
1376 topint( )
1377 #endif
1378 {
1379 	require(isp<MAX_INT_STACK, "topint: stack underflow");
1380 	return istack[isp];
1381 }
1382 
1383 void
1384 #ifdef __USE_PROTOS
ProcessArgs(int argc,char ** argv,Opt * options)1385 ProcessArgs( int argc, char **argv, Opt *options )
1386 #else
1387 ProcessArgs( argc, argv, options )
1388 int argc;
1389 char **argv;
1390 Opt *options;
1391 #endif
1392 {
1393 	Opt *p;
1394 	require(argv!=NULL, "ProcessArgs: command line NULL");
1395 
1396 	while ( argc-- > 0 )
1397 	{
1398 		p = options;
1399 		while ( p->option != NULL )
1400 		{
1401 			if ( strcmp(p->option, "*") == 0 ||
1402 				 ci_strequ(p->option, *argv) == 1 )
1403 			{
1404 				if ( p->arg )
1405 				{
1406 /* MR9  26-Sep-97   Check for argv valid                */
1407                     if (argc-- > 0) {
1408   				     	(*p->process)( *argv, *(argv+1) );
1409 					    argv++;
1410                     } else {
1411 fprintf(stderr,"error: required argument for option %s omitted\n",*argv);
1412 exit(PCCTS_EXIT_FAILURE);
1413                     };
1414 				}
1415 				else
1416 					(*p->process)( *argv );
1417 				break;
1418 			}
1419 			p++;
1420 		}
1421 		argv++;
1422 	}
1423 }
1424 
1425 static void
1426 #ifdef __USE_PROTOS
CompleteContextGuards(void)1427 CompleteContextGuards(void)
1428 #else
1429 CompleteContextGuards()
1430 #endif
1431 {
1432     ListNode *      p;
1433     Predicate *     pred;
1434 
1435     if (ContextGuardPredicateList == NULL) return;
1436 
1437     for (p=ContextGuardPredicateList->next; p != NULL; p=p->next) {
1438       pred=(Predicate *)p->elem;
1439       recomputeContextGuard(pred);
1440     }
1441 }
1442 
1443 /* Go back into the syntax diagram and compute all meta tokens; i.e.
1444  * turn all '.', ranges, token class refs etc... into actual token sets
1445  */
1446 static void
1447 #ifdef __USE_PROTOS
CompleteTokenSetRefs(void)1448 CompleteTokenSetRefs(void)
1449 #else
1450 CompleteTokenSetRefs()
1451 #endif
1452 {
1453 	ListNode *p;
1454 
1455 	if ( MetaTokenNodes==NULL ) return;
1456 	for (p = MetaTokenNodes->next; p!=NULL; p=p->next)
1457 	{
1458 		set a,b;
1459 
1460 		TokNode *q = (TokNode *)p->elem;
1461 		if ( q->wild_card )
1462 		{
1463 			q->tset = all_tokens;
1464 		}
1465 		else if ( q->tclass!=NULL )
1466 		{
1467 			if ( q->complement ) q->tset = set_dif(all_tokens, q->tclass->tset);
1468 			else q->tset = q->tclass->tset;
1469 		}
1470 		else if ( q->upper_range!=0 )
1471 		{
1472 			/* we have a range on our hands: make a set from q->token .. q->upper_range */
1473 			int i;
1474 			a = empty;
1475 			for (i=q->token; i<=q->upper_range; i++) { set_orel(i, &a); }   /* MR13 */
1476 
1477 /* MR13 */    if (q->complement) {
1478 /* MR13 */      q->tset = set_dif(all_tokens, a);
1479 /* MR13 */        set_free(a);
1480 /* MR13 */      } else {
1481 /* MR13 */	      q->tset = a;
1482 /* MR13 */      }
1483 
1484         }
1485 
1486 		/* at this point, it can only be a complemented single token */
1487 		else if ( q->complement )
1488 		{
1489 			a = set_of(q->token);
1490 			b = set_dif(all_tokens, a);
1491 			set_free(a);
1492 			q->tset=b;
1493 		}
1494 		else fatal("invalid meta token");
1495 	}
1496 }
1497 
1498 /* MR10: Jeff Vincent
1499    MR10: Changed to remove directory information from n only if
1500    MR10: if OutputDirectory was changed by user (-o option)
1501 */
1502 
1503 char *
1504 #ifdef __USE_PROTOS
OutMetaName(char * n)1505 OutMetaName(char *n)
1506 #else
1507 OutMetaName(n)
1508 char *n;
1509 #endif
1510 {
1511     static char *dir_sym = DirectorySymbol;
1512     static char newname[MaxFileName+1];
1513     char *p;
1514 
1515 	/* If OutputDirectory is same as TopDirectory (platform default) then leave n alone. */
1516     if (strcmp(OutputDirectory, TopDirectory) == 0)		/* TopDirectory is "." on Unix. */
1517 		return n;
1518 
1519 	/* p will point to filename without path information */
1520 	if ((p = strrchr(n, *dir_sym)) != NULL)				/* Directory symbol is "/" on Unix. */
1521 		p++;
1522 	else
1523 		p = n;
1524 
1525 	/* Copy new output directory into newname[] */
1526 	strcpy(newname, OutputDirectory);
1527 
1528 	/* if new output directory does not have trailing dir_sym, add it! */
1529 	if (newname[strlen(newname)-1] != *dir_sym) {
1530 		strcat(newname, dir_sym);
1531 	}
1532 	strcat(newname, p);
1533 	return newname;
1534 }
1535 
1536 char *
1537 #ifdef __USE_PROTOS
pcctsBaseName(char * n)1538 pcctsBaseName(char *n) /* MR32 */
1539 #else
1540 pcctsBaseName(n)
1541 char *n;
1542 #endif
1543 {
1544     static char newname[MaxFileName+1];
1545     static char* dir_sym = DirectorySymbol;
1546     int count = 0;
1547     char *p;
1548 
1549     p = n;
1550 
1551     while ( *p != '\0' )  {p++;}                    /* go to end of string */
1552     while ( (*p != *dir_sym) && (p != n) ) {--p;}   /* Find last DirectorySymbol */
1553     while ( *p == *dir_sym) p++;                    /* step forward if we're on a dir symbol */
1554     while ( *p != '\0' && *p != '.')
1555     {
1556         newname[count++] = *p;
1557         p++;
1558     }                                               /* create a new name */
1559     newname[count] = '\0';
1560     return newname;
1561 }
1562 
1563 static void
1564 #ifdef __USE_PROTOS
ensure_no_C_file_collisions(char * class_c_file)1565 ensure_no_C_file_collisions(char *class_c_file)
1566 #else
1567 ensure_no_C_file_collisions(class_c_file)
1568 char *class_c_file;
1569 #endif
1570 {
1571 	int i;
1572 
1573 	for (i=0; i<NumFiles; i++)
1574 	{
1575 
1576 #ifdef PCCTS_CASE_INSENSITIVE_FILE_NAME
1577 		/* assume that file names are case insensitive */
1578 		if ( STRICMP(outname(FileStr[i]), class_c_file)==0 )
1579 #else
1580 		if ( strcmp(outname(FileStr[i]), class_c_file)==0 )
1581 #endif
1582 		{
1583 			fatal(eMsg1("class def output file conflicts with parser output file: %s",
1584 						outname(FileStr[i])));
1585 		}
1586 	}
1587 }
1588 
1589 void
1590 #ifdef __USE_PROTOS
warnNoFL(char * err)1591 warnNoFL(char *err)
1592 #else
1593 warnNoFL(err)
1594 char *err;
1595 #endif
1596 {
1597 	fprintf(stderr, "warning: %s\n", err);
1598 }
1599 
1600 void
1601 #ifdef __USE_PROTOS
warnFL(char * err,char * f,int l)1602 warnFL(char *err,char *f,int l)
1603 #else
1604 warnFL(err,f,l)
1605 char *f;
1606 int l;
1607 char *err;
1608 #endif
1609 {
1610 	fprintf(stderr, ErrHdr, f, l);
1611 	fprintf(stderr, " warning: %s\n", err);
1612 }
1613 
1614 void
1615 #ifdef __USE_PROTOS
warn(char * err)1616 warn(char *err)
1617 #else
1618 warn(err)
1619 char *err;
1620 #endif
1621 {
1622 	/* back up the file number if we hit an error at the end of the last file */
1623 	if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--;
1624 	fprintf(stderr, ErrHdr, FileStr[CurFile], zzline);
1625 	fprintf(stderr, " warning: %s\n", err);
1626 }
1627 
1628 void
1629 #ifdef __USE_PROTOS
warnNoCR(char * err)1630 warnNoCR( char *err )
1631 #else
1632 warnNoCR( err )
1633 char *err;
1634 #endif
1635 {
1636 	/* back up the file number if we hit an error at the end of the last file */
1637 	if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--;
1638 	fprintf(stderr, ErrHdr, FileStr[CurFile], zzline);
1639 	fprintf(stderr, " warning: %s", err);
1640 }
1641 
1642 void
1643 #ifdef __USE_PROTOS
errNoFL(char * err)1644 errNoFL(char *err)
1645 #else
1646 errNoFL(err)
1647 char *err;
1648 #endif
1649 {
1650 	fprintf(stderr, "error: %s\n", err);
1651 }
1652 
1653 void
1654 #ifdef __USE_PROTOS
errFL(char * err,char * f,int l)1655 errFL(char *err,char *f,int l)
1656 #else
1657 errFL(err,f,l)
1658 char *err;
1659 char *f;
1660 int l;
1661 #endif
1662 {
1663 	fprintf(stderr, ErrHdr, f, l);
1664 	fprintf(stderr, " error: %s\n", err);
1665 }
1666 
1667 void
1668 #ifdef __USE_PROTOS
err(char * err)1669 err(char *err)
1670 #else
1671 err(err)
1672 char *err;
1673 #endif
1674 {
1675 	/* back up the file number if we hit an error at the end of the last file */
1676 	if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--;
1677 	fprintf(stderr, ErrHdr, FileStr[CurFile], zzline);
1678 	fprintf(stderr, " error: %s\n", err);
1679 }
1680 
1681 void
1682 #ifdef __USE_PROTOS
errNoCR(char * err)1683 errNoCR( char *err )
1684 #else
1685 errNoCR( err )
1686 char *err;
1687 #endif
1688 {
1689 	/* back up the file number if we hit an error at the end of the last file */
1690 	if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--;
1691 	fprintf(stderr, ErrHdr, FileStr[CurFile], zzline);
1692 	fprintf(stderr, " error: %s", err);
1693 }
1694 
1695 UserAction *
1696 #ifdef __USE_PROTOS
newUserAction(char * s)1697 newUserAction(char *s)
1698 #else
1699 newUserAction(s)
1700 char *s;
1701 #endif
1702 {
1703 	UserAction *ua = (UserAction *) calloc(1, sizeof(UserAction));
1704 	require(ua!=NULL, "cannot allocate UserAction");
1705 
1706 	ua->action = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
1707 	strcpy(ua->action, s);
1708 	return ua;
1709 }
1710 
1711 /* Added by TJP September 1994 */
1712 /* Take in file.h and return file_h; names w/o '.'s are left alone */
1713 char *
1714 #ifdef __USE_PROTOS
gate_symbol(char * name)1715 gate_symbol(char *name)
1716 #else
1717 gate_symbol(name)
1718 char *name;
1719 #endif
1720 {
1721 	static char buf[100];
1722 	char *p;
1723 	sprintf(buf, "%s", name);
1724 
1725 	for (p=buf; *p!='\0'; p++)
1726 	{
1727 		if ( *p=='.' ) *p = '_';
1728 	}
1729 	return buf;
1730 }
1731 
1732 char *
1733 #ifdef __USE_PROTOS
makeAltID(int blockid,int altnum)1734 makeAltID(int blockid, int altnum)
1735 #else
1736 makeAltID(blockid, altnum)
1737 int blockid;
1738 int altnum;
1739 #endif
1740 {
1741 	static char buf[100];
1742 	char *p;
1743 	sprintf(buf, "_blk%d_alt%d", blockid, altnum);
1744 	p = (char *)malloc(strlen(buf)+1);
1745 	strcpy(p, buf);
1746 	return p;
1747 }
1748