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
40static int istack[MAX_INT_STACK];		/* Int stack */
41static int isp = MAX_INT_STACK;
42
43static int DontAcceptFiles = 0;			/* if stdin, don't read files */
44static int DontAcceptStdin = 0;			/* if files seen first, don't accept stdin */
45
46static 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
50typedef 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
62extern void ProcessArgs(int, char **, Opt *);
63#else
64extern void ProcessArgs();
65#endif
66
67#ifdef __USE_PROTOS
68int ci_strequ(char *a,char *b)
69#else
70int 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
81static void
82#ifdef __USE_PROTOS
83pStdin( void )
84#else
85pStdin( )
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
99static void
100#ifdef __USE_PROTOS
101pFile( char *s )
102#else
103pFile( s )
104char *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
124static void
125#ifdef __USE_PROTOS
126pFileList( char *s, char *t )
127#else
128pFileList( s, t )
129char *s;
130char *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
171static void
172#ifdef __USE_PROTOS
173pLLK( char *s, char *t )
174#else
175pLLK( s, t )
176char *s;
177char *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
187static void
188#ifdef __USE_PROTOS
189pCk( char *s, char *t )
190#else
191pCk( s, t )
192char *s;
193char *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
203static void						                                     /* MR6 */
204#ifdef __USE_PROTOS
205pTab( char *s, char *t )			                        	     /* MR6 */
206#else
207pTab( s, t )				                    		             /* MR6 */
208char *s;							                                 /* MR6 */
209char *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
219static int ambAidDepthSpecified=0;                                   /* MR11 */
220
221static void						                                     /* MR11 */
222#ifdef __USE_PROTOS
223pAAd( char *s, char *t )			                        	     /* MR11 */
224#else
225pAAd( s, t )				                    		             /* MR11 */
226char *s;							                                 /* MR11 */
227char *t;							                                 /* MR11 */
228#endif
229{								                                     /* MR11 */
230    ambAidDepthSpecified=1;                                          /* MR11 */
231	MR_AmbAidDepth = atoi(t);				                         /* MR11 */
232}							                                         /* MR11 */
233
234static void						                                     /* MR11 */
235#ifdef __USE_PROTOS
236pTreport( char *s, char *t )			                       	     /* MR11 */
237#else
238pTreport( 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
247void chkGTFlag(void)	                                    /* 7-Apr-97 MR1 */
248#else
249void 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
258static void pInfo(char *s, char *t)                         /* MR10 */
259#else
260static 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
288static void pCGen(void)	{ CodeGen = FALSE; LexGen = FALSE; }
289static void pLGen(void)	{ LexGen = FALSE; }
290static void pXTGen(void){ MR_Inhibit_Tokens_h_Gen = TRUE; }
291static void pTGen(void)	{ TraceGen = TRUE; }
292static void pSGen(void)	{ GenExprSetsOpt = FALSE; }
293static void pPrt(void)	{ PrintOut = TRUE; pCGen(); pLGen(); }
294static void pPrtA(void)	{ PrintOut = TRUE; PrintAnnotate = TRUE; pCGen(); pLGen(); }
295static void pAst(void)	{ GenAST = TRUE; }
296static void pANSI(void)	{ GenANSI = TRUE; }
297static void pCr(void)	{ GenCR = TRUE; }
298static void pNOPURIFY(void)	{ PURIFY = FALSE; }
299/*static void pCt(void)	{ warnNoFL("-ct option is now the default"); }*/
300static void pLI(void)	{ GenLineInfo = TRUE; GenLineInfoMS = FALSE; } /* MR14 */
301static void pLIms(void)	{ GenLineInfo = TRUE; GenLineInfoMS = TRUE; }  /* MR14 */
302static void pFr(char *s, char *t) {RemapFileName = t;}
303static void pFe(char *s, char *t) {ErrFileName = t;}
304static void pFl(char *s, char *t) {DlgFileName = t;}
305static void pFm(char *s, char *t) {ModeFileName = t;}
306static void pFt(char *s, char *t) {DefFileName = t;}
307
308static void pE1(void)	{ elevel = 1; }
309static void pE2(void)	{ elevel = 2; }
310static void pE3(void)	{ elevel = 3; }
311static void pEGen(void)	{ GenEClasseForRules = 1; }
312static 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
321static void pAA(char *s,char *t) {MR_AmbAidRule = t;}               /* MR11 */
322static void pAAm(char *s){MR_AmbAidMultiple = 1;}                   /* MR11 */
323static void pGHdr(void)	{ GenStdPccts = 1; }
324static void pFHdr(char *s, char *t) { stdpccts = t; pGHdr(); }
325static void pW1(void) { WarningLevel = 1; }
326static void pNewAST(void) { NewAST = 1; }                           /* MR13 */
327static void ptmakeInParser(void) { tmakeInParser = 1; }             /* MR23 */
328static void pAlpha(void) { AlphaBetaTrace = 1; }                    /* MR14 */
329static void pMR_BlkErr(void) { MR_BlkErr = 1; }                     /* MR21 */
330static void pStdout(void) {UseStdout = 1; }		                    /* MR6 */
331static void pW2(void) { WarningLevel = 2; }
332static void pCC(void) { GenCC = TRUE; }
333#else
334static void pCGen()	{ CodeGen = FALSE; LexGen = FALSE; }
335static void pLGen()	{ LexGen = FALSE; }
336static void pXTGen(){ MR_Inhibit_Tokens_h_Gen = TRUE; }             /* MR14 */
337static void pTGen()	{ TraceGen = TRUE; }
338static void pSGen()	{ GenExprSetsOpt = FALSE; }
339static void pPrt()		{ PrintOut = TRUE; pCGen(); pLGen(); }
340static void pPrtA()	{ PrintOut = TRUE; PrintAnnotate = TRUE; pCGen(); pLGen(); }
341static void pAst()		{ GenAST = TRUE; }
342static void pANSI()	{ GenANSI = TRUE; }
343static void pCr()		{ GenCR = TRUE; }
344static void pNOPURIFY()	{ PURIFY = FALSE; }
345
346/*static void pCt()		{ warnNoFL("-ct option is now the default"); }*/
347static void pLI()	    { GenLineInfo = TRUE; GenLineInfoMS = FALSE; }  /* MR14 */
348static void pLIms()	    { GenLineInfo = TRUE; GenLineInfoMS = TRUE; }   /* MR14 */
349static void pFr(s,t) char *s, *t; {RemapFileName = t;}
350static void pFe(s,t) char *s, *t; {ErrFileName = t;}
351static void pFl(s,t) char *s, *t; {DlgFileName = t;}
352static void pFm(s,t) char *s, *t; {ModeFileName = t;}
353static void pFt(s,t) char *s, *t; {DefFileName = t;}
354
355static void pE1()		{ elevel = 1; }
356static void pE2()		{ elevel = 2; }
357static void pE3()		{ elevel = 3; }
358static void pEGen()	{ GenEClasseForRules = 1; }
359static 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
368static void pAA(s,t) char *s; char *t; {MR_AmbAidRule = t;}          /* MR11 BJS 20-Mar-98 */
369static void pAAm(s) char *s; {MR_AmbAidMultiple = 1;}                /* MR11 BJS 20-Mar-98 */
370static void pGHdr()	{ GenStdPccts = 1; }
371static void pFHdr(s,t) char *s, *t; { stdpccts = t; pGHdr(); }
372static void pW1() { WarningLevel = 1; }
373static void pNewAST() { NewAST = 1; }                                /* MR13 */
374static void ptmakeInParser() { tmakeInParser = 1; }                  /* MR23 */
375static void pAlpha() { AlphaBetaTrace = 1; }                         /* MR14 */
376static void pMR_BlkErr() { MR_BlkErr = 1; }                          /* MR21 */
377static void pStdout() {UseStdout = 1; }	                             /* MR6 */
378static void pW2() { WarningLevel = 2; }
379static void pCC() { GenCC = TRUE; }
380#endif
381
382static void
383#ifdef __USE_PROTOS
384pPre( char *s, char *t )
385#else
386pPre( s, t )
387char *s;
388char *t;
389#endif
390{
391	RulePrefix = t;
392}
393
394static void
395#ifdef __USE_PROTOS
396pOut( char *s, char *t )
397#else
398pOut( s, t )
399char *s;
400char *t;
401#endif
402{
403	OutputDirectory = t;
404}
405
406static void
407#ifdef __USE_PROTOS
408pPred( void )
409#else
410pPred( )
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
422static void
423#ifdef __USE_PROTOS
424pPredCtx( char *s, char *t )
425#else
426pPredCtx(s,t)
427char *s;
428char *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
440static void
441#ifdef __USE_PROTOS
442pMRhoist( char *s, char *t )
443#else
444pMRhoist(s,t)
445char *s;
446char *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
460static void
461#ifdef __USE_PROTOS
462pMRhoistk( char *s, char *t )
463#else
464pMRhoistk(s,t)
465char *s;
466char *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
478static void
479#ifdef __USE_PROTOS
480pTRes( char *s, char *t )
481#else
482pTRes( s, t )
483char *s;
484char *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
495Opt 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
627void readDescr();
628void cleanUp();
629
630#ifdef __USE_PROTOS
631static void buildRulePtr( void );
632static void help( void );
633static void init( void );
634static void CompleteTokenSetRefs( void );
635static void ensure_no_C_file_collisions(char *);
636static void CompleteContextGuards(void);
637#else
638static void buildRulePtr( );
639static void help( );
640static void init( );
641static void CompleteTokenSetRefs( );
642static void ensure_no_C_file_collisions();
643static void CompleteContextGuards();
644#endif
645
646static void
647#ifdef __USE_PROTOS  /* <BJS> */
648report_numericPredLabels(ActionNode *a)
649#else
650report_numericPredLabels(a)
651ActionNode *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
660int
661#ifdef __USE_PROTOS
662main( int argc, char *argv[] )
663#else
664main( argc, argv )
665int argc;
666char *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
961static void
962#ifdef __USE_PROTOS
963init( void )
964#else
965init( )
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
1009static void
1010#ifdef __USE_PROTOS
1011help( void )
1012#else
1013help( )
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 */
1033static void
1034#ifdef __USE_PROTOS
1035buildRulePtr( void )
1036#else
1037buildRulePtr( )
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
1053void
1054#ifdef __USE_PROTOS
1055dlgerror(const char *s)
1056#else
1057dlgerror(s)
1058char *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
1066void
1067#ifdef __USE_PROTOS
1068readDescr( void )
1069#else
1070readDescr( )
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
1080FILE *
1081#ifdef __USE_PROTOS
1082NextFile( void )
1083#else
1084NextFile( )
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
1128char *
1129#ifdef __USE_PROTOS
1130outname( char *fs )
1131#else
1132outname( fs )
1133char *fs;
1134#endif
1135{
1136    if ( GenCC) {
1137      return outnameX(fs,CPP_FILE_SUFFIX);
1138    } else {
1139      return outnameX(fs,".c");
1140    };
1141}
1142
1143char *
1144#ifdef __USE_PROTOS
1145outnameX( char *fs ,char *suffix)
1146#else
1147outnameX( fs , suffix )
1148char *fs;
1149char *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
1166void
1167#ifdef __USE_PROTOS
1168fatalFL( char *err_, char *f, int l )
1169#else
1170fatalFL( err_, f, l )
1171char *err_;
1172char *f;
1173int 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
1182void
1183#ifdef __USE_PROTOS
1184fatal_intern( char *err_, char *f, int l )
1185#else
1186fatal_intern( err_, f, l )
1187char *err_;
1188char *f;
1189int 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
1204void
1205#ifdef __USE_PROTOS
1206cleanUp( void )
1207#else
1208cleanUp( )
1209#endif
1210{
1211	if ( DefFile != NULL) fclose( DefFile );
1212}
1213
1214/* sprintf up to 3 strings */
1215char *
1216#ifdef __USE_PROTOS
1217eMsg3( char *s, char *a1, char *a2, char *a3 )
1218#else
1219eMsg3( s, a1, a2, a3 )
1220char *s;
1221char *a1;
1222char *a2;
1223char *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 */
1233char *
1234#ifdef __USE_PROTOS
1235eMsgd( char *s, int d )
1236#else
1237eMsgd( s, d )
1238char *s;
1239int d;
1240#endif
1241{
1242	static char buf[250];			/* DANGEROUS as hell !!!!!! */
1243
1244	sprintf(buf, s, d);
1245	return( buf );
1246}
1247
1248char *
1249#ifdef __USE_PROTOS
1250eMsgd2( char *s, int d1,int d2)
1251#else
1252eMsgd2( s, d1, d2 )
1253char *s;
1254int d1;
1255int d2;
1256#endif
1257{
1258	static char buf[250];			/* DANGEROUS as hell !!!!!! */
1259
1260	sprintf(buf, s, d1, d2);
1261	return( buf );
1262}
1263
1264void
1265#ifdef __USE_PROTOS
1266s_fprT( FILE *f, set e )
1267#else
1268s_fprT( f, e )
1269FILE *f;
1270set 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. */
1289char *
1290#ifdef __USE_PROTOS
1291TerminalString( int token )
1292#else
1293TerminalString( token )
1294int 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
1319void
1320#ifdef __USE_PROTOS
1321pushint( int i )
1322#else
1323pushint( i )
1324int i;
1325#endif
1326{
1327	require(isp>0, "pushint: stack overflow");
1328	istack[--isp] = i;
1329}
1330
1331int
1332#ifdef __USE_PROTOS
1333popint( void )
1334#else
1335popint( )
1336#endif
1337{
1338	require(isp<MAX_INT_STACK, "popint: stack underflow");
1339	return istack[isp++];
1340}
1341
1342int
1343#ifdef __USE_PROTOS
1344istacksize( void )
1345#else
1346istacksize( )
1347#endif
1348{
1349	return MAX_INT_STACK-isp;
1350}
1351
1352void
1353#ifdef __USE_PROTOS
1354istackreset( void )
1355#else
1356istackreset( )
1357#endif
1358{
1359	isp = MAX_INT_STACK;
1360}
1361
1362int
1363#ifdef __USE_PROTOS
1364istackempty( void )
1365#else
1366istackempty( )
1367#endif
1368{
1369	return isp==MAX_INT_STACK;
1370}
1371
1372int
1373#ifdef __USE_PROTOS
1374topint( void )
1375#else
1376topint( )
1377#endif
1378{
1379	require(isp<MAX_INT_STACK, "topint: stack underflow");
1380	return istack[isp];
1381}
1382
1383void
1384#ifdef __USE_PROTOS
1385ProcessArgs( int argc, char **argv, Opt *options )
1386#else
1387ProcessArgs( argc, argv, options )
1388int argc;
1389char **argv;
1390Opt *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 {
1411fprintf(stderr,"error: required argument for option %s omitted\n",*argv);
1412exit(PCCTS_EXIT_FAILURE);
1413                    };
1414				}
1415				else
1416					(*p->process)( *argv );
1417				break;
1418			}
1419			p++;
1420		}
1421		argv++;
1422	}
1423}
1424
1425static void
1426#ifdef __USE_PROTOS
1427CompleteContextGuards(void)
1428#else
1429CompleteContextGuards()
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 */
1446static void
1447#ifdef __USE_PROTOS
1448CompleteTokenSetRefs(void)
1449#else
1450CompleteTokenSetRefs()
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
1503char *
1504#ifdef __USE_PROTOS
1505OutMetaName(char *n)
1506#else
1507OutMetaName(n)
1508char *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
1536char *
1537#ifdef __USE_PROTOS
1538pcctsBaseName(char *n) /* MR32 */
1539#else
1540pcctsBaseName(n)
1541char *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
1563static void
1564#ifdef __USE_PROTOS
1565ensure_no_C_file_collisions(char *class_c_file)
1566#else
1567ensure_no_C_file_collisions(class_c_file)
1568char *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
1589void
1590#ifdef __USE_PROTOS
1591warnNoFL(char *err)
1592#else
1593warnNoFL(err)
1594char *err;
1595#endif
1596{
1597	fprintf(stderr, "warning: %s\n", err);
1598}
1599
1600void
1601#ifdef __USE_PROTOS
1602warnFL(char *err,char *f,int l)
1603#else
1604warnFL(err,f,l)
1605char *f;
1606int l;
1607char *err;
1608#endif
1609{
1610	fprintf(stderr, ErrHdr, f, l);
1611	fprintf(stderr, " warning: %s\n", err);
1612}
1613
1614void
1615#ifdef __USE_PROTOS
1616warn(char *err)
1617#else
1618warn(err)
1619char *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
1628void
1629#ifdef __USE_PROTOS
1630warnNoCR( char *err )
1631#else
1632warnNoCR( err )
1633char *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
1642void
1643#ifdef __USE_PROTOS
1644errNoFL(char *err)
1645#else
1646errNoFL(err)
1647char *err;
1648#endif
1649{
1650	fprintf(stderr, "error: %s\n", err);
1651}
1652
1653void
1654#ifdef __USE_PROTOS
1655errFL(char *err,char *f,int l)
1656#else
1657errFL(err,f,l)
1658char *err;
1659char *f;
1660int l;
1661#endif
1662{
1663	fprintf(stderr, ErrHdr, f, l);
1664	fprintf(stderr, " error: %s\n", err);
1665}
1666
1667void
1668#ifdef __USE_PROTOS
1669err(char *err)
1670#else
1671err(err)
1672char *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
1681void
1682#ifdef __USE_PROTOS
1683errNoCR( char *err )
1684#else
1685errNoCR( err )
1686char *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
1695UserAction *
1696#ifdef __USE_PROTOS
1697newUserAction(char *s)
1698#else
1699newUserAction(s)
1700char *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 */
1713char *
1714#ifdef __USE_PROTOS
1715gate_symbol(char *name)
1716#else
1717gate_symbol(name)
1718char *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
1732char *
1733#ifdef __USE_PROTOS
1734makeAltID(int blockid, int altnum)
1735#else
1736makeAltID(blockid, altnum)
1737int blockid;
1738int 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