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