]> pd.if.org Git - pccts/blob - antlr/main.c
auto commit for import
[pccts] / antlr / main.c
1 /*
2  * main.c -- main program for PCCTS ANTLR.
3  *
4  * $Id: main.c,v 1.7 95/10/05 11:57:08 parrt Exp $
5  * $Revision: 1.7 $
6  *
7  * SOFTWARE RIGHTS
8  *
9  * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
10  * Set (PCCTS) -- PCCTS is in the public domain.  An individual or
11  * company may do whatever they wish with source code distributed with
12  * PCCTS or the code generated by PCCTS, including the incorporation of
13  * PCCTS, or its output, into commerical software.
14  * 
15  * We encourage users to develop software with PCCTS.  However, we do ask
16  * that credit is given to us for developing PCCTS.  By "credit",
17  * we mean that if you incorporate our source code into one of your
18  * programs (commercial product, research project, or otherwise) that you
19  * acknowledge this fact somewhere in the documentation, research report,
20  * etc...  If you like PCCTS and have developed a nice tool with the
21  * output, please mention that you developed it using PCCTS.  In
22  * addition, we ask that this header remain intact in our source code.
23  * As long as these guidelines are kept, we expect to continue enhancing
24  * this system and expect to make other tools available as they are
25  * completed.
26  *
27  * ANTLR 1.33
28  * Terence Parr
29  * Parr Research Corporation
30  * with Purdue University and AHPCRC, University of Minnesota
31  * 1989-1995
32  */
33
34 #include <stdio.h>
35 #ifdef __cplusplus
36 #ifndef __STDC__
37 #define __STDC__
38 #endif
39 #endif
40 #include "stdpccts.h"
41
42 #define MAX_INT_STACK 50
43 static int istack[MAX_INT_STACK];               /* Int stack */
44 static int isp = MAX_INT_STACK;
45
46 static int DontAcceptFiles = 0;                 /* if stdin, don't read files */
47 static int DontAcceptStdin = 0;                 /* if files seen first, don't accept stdin */
48
49
50                 /* C m d - L i n e  O p t i o n  S t r u c t  &  F u n c s */
51
52 typedef struct _Opt {
53                         char *option;
54                         int  arg;
55 #ifdef __cplusplus
56                         void (*process)(...);
57 #else
58                         void (*process)();
59 #endif
60                         char *descr;
61                 } Opt;
62
63 #ifdef __STDC__
64 extern void ProcessArgs(int, char **, Opt *);
65 #else
66 extern void ProcessArgs();
67 #endif
68
69 static void
70 #ifdef __STDC__
71 pStdin( void )
72 #else
73 pStdin( )
74 #endif
75 {
76         if ( DontAcceptStdin )
77         {
78                 warnNoFL("'-' (stdin) ignored as files were specified first");
79                 return;
80         }
81
82         require(NumFiles<MaxNumFiles,"exceeded max # of input files");
83         FileStr[NumFiles++] = "stdin";
84         DontAcceptFiles = 1;
85 }
86
87 static void
88 #ifdef __STDC__
89 pFile( char *s )
90 #else
91 pFile( s )
92 char *s;
93 #endif
94 {
95         if ( *s=='-' ) { warnNoFL( eMsg1("invalid option: '%s'",s) ); return; }
96         if ( DontAcceptFiles )
97         {
98                 warnNoFL(eMsg1("file '%s' ignored as '-' (stdin option) was specified first",s));
99                 return;
100         }
101
102         require(NumFiles<MaxNumFiles,"exceeded max # of input files");
103         FileStr[NumFiles++] = s;
104         DontAcceptStdin = 1;
105 }
106
107 static void
108 #ifdef __STDC__
109 pLLK( char *s, char *t )
110 #else
111 pLLK( s, t )
112 char *s;
113 char *t;
114 #endif
115 {
116         LL_k = atoi(t);
117         if ( LL_k <= 0 ) {
118                 warnNoFL("must have at least one token of lookahead (setting to 1)");
119                 LL_k = 1;
120         }
121 }
122
123 static void
124 #ifdef __STDC__
125 pCk( char *s, char *t )
126 #else
127 pCk( s, t )
128 char *s;
129 char *t;
130 #endif
131 {
132         CLL_k = atoi(t);
133         if ( CLL_k <= 0 ) {
134                 warnNoFL("must have at least one token of look-ahead (setting to 1)");
135                 CLL_k = 1;
136         }
137 }
138
139 #ifdef __STDC__
140 void chkGTFlag()
141 #else
142 void chkGTFlag(void)
143 #endif
144 {
145         if ( !GenAST )
146                 warn("#-variable or other AST item referenced w/o -gt option");
147 }
148
149 #ifdef __STDC__
150 static void pCGen(void) { CodeGen = FALSE; LexGen = FALSE; }
151 static void pLGen(void) { LexGen = FALSE; }
152 static void pTGen(void) { TraceGen = TRUE; }
153 static void pSGen(void) { GenExprSets = FALSE; }
154 static void pPrt(void)  { PrintOut = TRUE; pCGen(); pLGen(); }
155 static void pPrtA(void) { PrintOut = TRUE; PrintAnnotate = TRUE; pCGen(); pLGen(); }
156 static void pAst(void)  { GenAST = TRUE; }
157 static void pANSI(void) { GenANSI = TRUE; }
158 static void pCr(void)   { GenCR = TRUE; }
159 /*static void pCt(void) { warnNoFL("-ct option is now the default"); }*/
160 static void pLI(void)   { GenLineInfo = TRUE; }
161 static void pFr(char *s, char *t) {RemapFileName = t;}
162 static void pFe(char *s, char *t) {ErrFileName = t;}
163 static void pFl(char *s, char *t) {DlgFileName = t;}
164 static void pFm(char *s, char *t) {ModeFileName = t;}
165 static void pFt(char *s, char *t) {DefFileName = t;}
166 static void pE1(void)   { elevel = 1; }
167 static void pE2(void)   { elevel = 2; }
168 static void pE3(void)   { elevel = 3; }
169 static void pEGen(void) { GenEClasseForRules = 1; }
170 static void pDL(void)
171         {
172             DemandLookahead = 1;
173             if ( GenCC ) {
174                         warnNoFL("-gk does not work currently in C++ mode; -gk turned off");
175                         DemandLookahead = 0;
176             }
177         }
178
179 static void pGHdr(void) { GenStdPccts = 1; }
180 static void pFHdr(char *s, char *t) { stdpccts = t; pGHdr(); }
181 static void pW1(void) { WarningLevel = 1; }
182 static void pW2(void) { WarningLevel = 2; }
183 static void pCC(void) { GenCC = TRUE; }
184 #else
185 static void pCGen()     { CodeGen = FALSE; LexGen = FALSE; }
186 static void pLGen()     { LexGen = FALSE; }
187 static void pTGen()     { TraceGen = TRUE; }
188 static void pSGen()     { GenExprSets = FALSE; }
189 static void pPrt()              { PrintOut = TRUE; pCGen(); pLGen(); }
190 static void pPrtA()     { PrintOut = TRUE; PrintAnnotate = TRUE; pCGen(); pLGen(); }
191 static void pAst()              { GenAST = TRUE; }
192 static void pANSI()     { GenANSI = TRUE; }
193 static void pCr()               { GenCR = TRUE; }
194 /*static void pCt()             { warnNoFL("-ct option is now the default"); }*/
195 static void pLI()               { GenLineInfo = TRUE; }
196 static void pFr(s,t) char *s, *t; {RemapFileName = t;}
197 static void pFe(s,t) char *s, *t; {ErrFileName = t;}
198 static void pFl(s,t) char *s, *t; {DlgFileName = t;}
199 static void pFm(s,t) char *s, *t; {ModeFileName = t;}
200 static void pFt(s,t) char *s, *t; {DefFileName = t;}
201 static void pE1()               { elevel = 1; }
202 static void pE2()               { elevel = 2; }
203 static void pE3()               { elevel = 3; }
204 static void pEGen()     { GenEClasseForRules = 1; }
205 static void pDL()
206         {
207             DemandLookahead = 1;
208             if ( GenCC ) {
209                 warnNoFL("-gk does not work currently in C++ mode; -gk turned off");
210                 DemandLookahead = 0;
211             }
212         }
213 static void pGHdr()     { GenStdPccts = 1; }
214 static void pFHdr(s,t) char *s, *t; { stdpccts = t; pGHdr(); }
215 static void pW1() { WarningLevel = 1; }
216 static void pW2() { WarningLevel = 2; }
217 static void pCC() { GenCC = TRUE; }
218 #endif
219
220 static void
221 #ifdef __STDC__
222 pPre( char *s, char *t )
223 #else
224 pPre( s, t )
225 char *s;
226 char *t;
227 #endif
228 {
229         RulePrefix = t;
230 }
231
232 static void
233 #ifdef __STDC__
234 pOut( char *s, char *t )
235 #else
236 pOut( s, t )
237 char *s;
238 char *t;
239 #endif
240 {
241         OutputDirectory = t;
242 }
243
244 static void
245 #ifdef __STDC__
246 pPred( void )
247 #else
248 pPred( )
249 #endif
250 {
251         warnNoFL("-pr is no longer used (predicates employed if present); see -prc");
252 /*
253         if ( DemandLookahead )
254                 warnNoFL("-gk conflicts with -pr; -gk turned off");
255         DemandLookahead = 0;
256         HoistPredicateContext = 0;
257 */
258 }
259
260 static void
261 #ifdef __STDC__
262 pPredCtx( char *s, char *t )
263 #else
264 pPredCtx(s,t)
265 char *s;
266 char *t;
267 #endif
268 {
269         if ( strcmp(t, "on")==0 ) HoistPredicateContext = 1;
270         else if ( strcmp(t, "ON")==0 ) HoistPredicateContext = 1;
271         else if ( strcmp(t, "off")==0 ) HoistPredicateContext = 0;
272         else if ( strcmp(t, "OFF")==0 ) HoistPredicateContext = 0;
273         if ( DemandLookahead )
274         {
275                 warnNoFL("-gk incompatible with semantic predicate usage; -gk turned off");
276                 DemandLookahead = 0;
277         }
278 }
279
280 static void
281 #ifdef __STDC__
282 pTRes( char *s, char *t )
283 #else
284 pTRes( s, t )
285 char *s;
286 char *t;
287 #endif
288 {
289         TreeResourceLimit = atoi(t);
290         if ( TreeResourceLimit <= 0 )
291         {
292                 warnNoFL("analysis resource limit (# of tree nodes) must be greater than 0");
293                 TreeResourceLimit = -1; /* set to no limit */
294         }
295 }
296
297 Opt options[] = {
298 #ifdef __cplusplus
299     { "-CC", 0, (void (*)(...)) pCC,    "Generate C++ output (default=FALSE)"},
300     { "-ck", 1, (void (*)(...)) pCk,    "Set compressed lookahead depth; fast approximate lookahead"},
301     { "-cr", 0, (void (*)(...)) pCr,    "Generate cross reference (default=FALSE)"},
302     { "-e1", 0, (void (*)(...)) pE1,    "Ambiguities/errors shown in low detail (default)"},
303     { "-e2", 0, (void (*)(...)) pE2,    "Ambiguities/errors shown in more detail"},
304     { "-e3", 0, (void (*)(...)) pE3,    "Ambiguities/errors shown in excruciating detail"},
305     { "-fe", 1, (void (*)(...)) pFe,    "Rename err.c"},
306     { "-fh", 1, (void (*)(...)) pFHdr,  "Rename stdpccts.h header (turns on -gh)"},
307     { "-fl", 1, (void (*)(...)) pFl,    "Rename lexical output--parser.dlg"},
308     { "-fm", 1, (void (*)(...)) pFm,    "Rename mode.h"},
309     { "-fr", 1, (void (*)(...)) pFr,    "Rename remap.h"},
310     { "-ft", 1, (void (*)(...)) pFt,    "Rename tokens.h"},
311     { "-ga", 0, (void (*)(...)) pANSI,  "Generate ANSI-compatible code (default=FALSE)"},
312     { "-gc", 0, (void (*)(...)) pCGen,  "Do not generate output parser code (default=FALSE)"},
313     { "-gd", 0, (void (*)(...)) pTGen,  "Generate code to trace rule invocation (default=FALSE)"},
314     { "-ge", 0, (void (*)(...)) pEGen,  "Generate an error class for each non-terminal (default=FALSE)"},
315         { "-gh", 0, (void (*)(...)) pGHdr,      "Generate stdpccts.h for non-ANTLR-generated-files to include"},
316         { "-gk", 0, (void (*)(...)) pDL,        "Generate parsers that delay lookahead fetches 'til needed"},
317         { "-gl", 0, (void (*)(...)) pLI,        "Generate line info about grammar actions in C parser"},
318         { "-gp", 1, (void (*)(...)) pPre,       "Prefix all generated rule functions with a string"},
319     { "-gs", 0, (void (*)(...)) pSGen,  "Do not generate sets for token expression lists (default=FALSE)"},
320     { "-gt", 0, (void (*)(...)) pAst,   "Generate code for Abstract-Syntax-Trees (default=FALSE)"},
321     { "-gx", 0, (void (*)(...)) pLGen,  "Do not generate lexical (dlg-related) files (default=FALSE)"},
322     { "-k",  1, (void (*)(...)) pLLK,   "Set full LL(k) lookahead depth (default==1)"},
323     { "-o",  1, (void (*)(...)) pOut,   OutputDirectoryOption},
324     { "-p",  0, (void (*)(...)) pPrt,   "Print out the grammar w/o actions (default=no)"},
325     { "-pa", 0, (void (*)(...)) pPrtA,  "Print out the grammar w/o actions & w/FIRST sets (default=no)"},
326     { "-pr",0, (void (*)(...)) pPred,   "no longer used; predicates employed if present"},
327     { "-prc", 1, (void (*)(...)) pPredCtx,"Turn on/off computation of context for hoisted predicates"},
328         { "-rl", 1, (void (*)(...)) pTRes,      "Limit max # of tree nodes used by grammar analysis"},
329         { "-w1", 0, (void (*)(...)) pW1,        "Set the warning level to 1 (default)"},
330         { "-w2", 0, (void (*)(...)) pW2,        "Ambiguities yield warnings even if predicates or (...)? block"},
331         { "-",   0, (void (*)(...)) pStdin,     "Read grammar from stdin" },
332         { "*",   0, (void (*)(...)) pFile,      "" },   /* anything else is a file */
333 #else
334     { "-CC", 0, pCC,    "Generate C++ output (default=FALSE)"},
335     { "-cr", 0, pCr,    "Generate cross reference (default=FALSE)"},
336     { "-ck", 1, pCk,    "Set compressed lookahead depth; fast approximate lookahead"},
337     { "-e1", 0, pE1,    "Ambiguities/errors shown in low detail (default)"},
338     { "-e2", 0, pE2,    "Ambiguities/errors shown in more detail"},
339     { "-e3", 0, pE3,    "Ambiguities/errors shown in excrutiating detail"},
340     { "-fe", 1, pFe,    "Rename err.c"},
341     { "-fh", 1, pFHdr,  "Rename stdpccts.h header (turns on -gh)"},
342     { "-fl", 1, pFl,    "Rename lexical output--parser.dlg"},
343     { "-fm", 1, pFm,    "Rename mode.h"},
344     { "-fr", 1, pFr,    "Rename remap.h"},
345     { "-ft", 1, pFt,    "Rename tokens.h"},
346     { "-ga", 0, pANSI,  "Generate ANSI-compatible code (default=FALSE)"},
347     { "-gc", 0, pCGen,  "Do not generate output parser code (default=FALSE)"},
348     { "-gd", 0, pTGen,  "Generate code to trace rule invocation (default=FALSE)"},
349     { "-ge", 0, pEGen,  "Generate an error class for each non-terminal (default=FALSE)"},
350         { "-gh", 0, pGHdr,      "Generate stdpccts.h for non-ANTLR-generated-files to include"},
351         { "-gk", 0, pDL,        "Generate parsers that delay lookahead fetches 'til needed"},
352         { "-gl", 0, pLI,        "Generate line info about grammar actions in C parser"},
353         { "-gp", 1, pPre,       "Prefix all generated rule functions with a string"},
354     { "-gs", 0, pSGen,  "Do not generate sets for token expression lists (default=FALSE)"},
355     { "-gt", 0, pAst,   "Generate code for Abstract-Syntax-Trees (default=FALSE)"},
356     { "-gx", 0, pLGen,  "Do not generate lexical (dlg-related) files (default=FALSE)"},
357     { "-k",  1, pLLK,   "Set full LL(k) lookahead depth (default==1)"},
358     { "-o",  1, pOut,   OutputDirectoryOption},
359     { "-p",  0, pPrt,   "Print out the grammar w/o actions (default=no)"},
360     { "-pa", 0, pPrtA,  "Print out the grammar w/o actions & w/FIRST sets (default=no)"},
361     { "-pr",0, pPred,   "no longer used; predicates employed if present"},
362     { "-prc", 1, pPredCtx,"Turn on/off computation of context for hoisted predicates"},
363         { "-rl", 1, pTRes,      "Limit max # of tree nodes used by grammar analysis"},
364         { "-w1", 0, pW1,        "Set the warning level to 1 (default)"},
365         { "-w2", 0, pW2,        "Ambiguities yield warnings even if predicates or (...)? block"},
366         { "-",   0, pStdin,     "Read grammar from stdin" },
367         { "*",   0, pFile,      "" },   /* anything else is a file */
368 #endif
369         { NULL,  0, NULL }
370 };
371
372 void readDescr();
373 void cleanUp();
374
375 #ifdef __STDC__
376 static void buildRulePtr( void );
377 static void help( void );
378 static void init( void );
379 static void CompleteTokenSetRefs( void );
380 static void ensure_no_C_file_collisions(char *);
381 #else
382 static void buildRulePtr( );
383 static void help( );
384 static void init( );
385 static void CompleteTokenSetRefs( );
386 static void ensure_no_C_file_collisions();
387 #endif
388
389                                                                 /* M a i n */
390
391 int
392 #ifdef __STDC__
393 main( int argc, char *argv[] )
394 #else
395 main( argc, argv )
396 int argc;
397 char *argv[];
398 #endif
399 {
400         int i;
401         static char EPSTR[] = "[Ep]";
402
403 /*      malloc_debug(8);*/
404     special_inits();
405
406         fprintf(stderr, "Antlr parser generator   Version %s   1989-1995\n", Version);
407         if ( argc == 1 ) { help(); zzDIE; }
408         ProcessArgs(argc-1, &(argv[1]), options);
409
410         /* Fix lookahead depth */
411         /* Compressed lookahead must always be larger than or equal to full lookahead */
412         if ( CLL_k < LL_k  && CLL_k>0 )
413         {
414                 warnNoFL("must have compressed lookahead >= full LL(k) lookahead (setting -ck to -k)");
415                 CLL_k = LL_k;
416         }
417         if ( CLL_k == -1 ) CLL_k = LL_k;
418         OutputLL_k = CLL_k;
419         if ( ((CLL_k-1)&CLL_k)!=0 ) { /* output ll(k) must be power of 2 */
420                 int n;
421                 for(n=1; n<CLL_k; n<<=1) {;}
422                 OutputLL_k = n;
423         }
424
425         fpTrans = &(C_Trans[0]);                /* Translate to C Language */
426         fpJTrans = &(C_JTrans[0]);
427         init();
428         lexclass(LexStartSymbol);
429
430         readDescr();
431         LastTokenCounted = TokenNum;
432         RemapForcedTokens();
433         if ( CannotContinue ) {cleanUp(); zzDIE;}
434         if ( GenCC && no_classes_found ) fatal("required grammar class not found (exiting...)");
435         if ( WarningLevel>1 && HdrAction == NULL )
436            warnNoFL("no #header action was found");
437
438         EpToken = addTname(EPSTR);              /* add imaginary token epsilon */
439         set_orel(EpToken, &imag_tokens);
440
441         /* this won't work for hand-built scanners since EofToken is not
442          * known.  Forces EOF to be token type 1.
443          */
444         set_orel(EofToken, &imag_tokens);
445
446         set_size(NumWords(TokenNum-1));
447
448         /* compute the set of all known token types 
449          * It represents the set of tokens from 1 to last_token_num + the
450          * reserved positions above that (if any).  Don't include the set of
451          * imaginary tokens such as the token/error classes or EOF.
452          */
453         {
454                 set a;
455                 a = set_dup(reserved_positions);
456                 for (i=1; i<TokenNum; i++) { set_orel(i, &a); }
457                 all_tokens = set_dif(a, imag_tokens);
458                 set_free(a);
459         }
460
461         ComputeTokSets();                               /* Compute #tokclass sets */
462         CompleteTokenSetRefs();                 /* Change complex nodes in syn diag */
463
464         if ( CodeGen ) genDefFile();    /* create tokens.h */
465         if ( LexGen ) genLexDescr();    /* create parser.dlg */
466
467         if ( GenStdPccts )
468         {
469                 FILE *f = fopen(OutMetaName(stdpccts), "w");
470                 if ( f==NULL ) {warnNoFL( eMsg1("can't create %s",OutMetaName(stdpccts)) );}
471                 else
472                 {
473                         special_fopen_actions(OutMetaName(stdpccts));
474                         genStdPCCTSIncludeFile(f);
475                         fclose(f);
476                 }
477         }
478
479         buildRulePtr();                                 /* create mapping from rule # to RuleBlk junction */
480         ComputeErrorSets();
481         FoLink( (Node *)SynDiag );              /* add follow links to end of all rules */
482         
483         if ( GenCR ) GenCrossRef( SynDiag );
484
485         if ( CodeGen )
486         {
487                 if ( SynDiag == NULL )
488                 {
489                         warnNoFL("no grammar description recognized");
490                         cleanUp();
491                         zzDIE;
492                 }
493                 else if ( !GenCC ) {
494                         ErrFile = fopen(OutMetaName(ErrFileName), "w");
495                         require(ErrFile != NULL, "main: can't open err file");
496                         special_fopen_actions(OutMetaName(ErrFileName));
497                         NewSetWd();
498                         GenErrHdr();
499                         TRANS(SynDiag);                 /* Translate to the target language */
500                         DumpSetWd();
501                         DumpRemainingTokSets();
502                         fclose( ErrFile );
503                 }
504                 else {
505                         strcpy(Parser_h_Name, CurrentClassName);
506                         strcat(Parser_h_Name, ".h");
507                         strcpy(Parser_c_Name, CurrentClassName);
508                         strcat(Parser_c_Name, CPP_FILE_SUFFIX);
509                         ensure_no_C_file_collisions(Parser_c_Name);
510                         Parser_h = fopen(OutMetaName(Parser_h_Name), "w");
511                         require(Parser_h != NULL, "main: can't open class Parserx.h file");
512                         special_fopen_actions(OutMetaName(Parser_h_Name));
513                         Parser_c = fopen(OutMetaName(Parser_c_Name), "w");
514                         require(Parser_c != NULL, "main: can't open class Parserx.c file");
515                         special_fopen_actions(OutMetaName(Parser_c_Name));
516                         GenParser_h_Hdr();
517                         if ( class_before_actions != NULL )
518                         {
519                                 ListNode *p;
520                                 for (p = class_before_actions->next; p!=NULL; p=p->next)
521                                 {
522                                         UserAction *ua = (UserAction *)p->elem;
523                                         dumpAction( ua->action, Parser_h, 0, ua->file, ua->line, 1);
524                                 }
525                         }
526                         GenParser_c_Hdr();
527                         NewSetWd();
528                         TRANS(SynDiag);                 /* Translate to the target language */
529                         DumpSetWd();
530                         GenRuleMemberDeclarationsForCC(Parser_h, SynDiag);
531                         if ( class_after_actions != NULL )
532                         {
533                                 ListNode *p;
534                                 for (p = class_after_actions->next; p!=NULL; p=p->next)
535                                 {
536                                         UserAction *ua = (UserAction *)p->elem;
537                                         dumpAction( ua->action, Parser_h, 0, ua->file, ua->line, 1);
538                                 }
539                         }
540                         DumpRemainingTokSets();
541                         fprintf(Parser_h, "};\n");
542                         fprintf(Parser_h, "\n#endif /* %s_h */\n", CurrentClassName);
543                         fclose( Parser_h );
544                         fclose( Parser_c );
545                 }
546         }
547
548         if ( PrintOut )
549         {
550                 if ( SynDiag == NULL ) {warnNoFL("no grammar description recognized");}
551                 else PRINT(SynDiag);
552         }
553
554         GenRemapFile();                                 /* create remap.h */
555
556         cleanUp();
557         exit(PCCTS_EXIT_SUCCESS);
558 }
559
560 static void
561 #ifdef __STDC__
562 init( void )
563 #else
564 init( )
565 #endif
566 {
567         SignalEntry *q;
568
569         Tname = newHashTable();
570         Rname = newHashTable();
571         Fcache = newHashTable();
572         Tcache = newHashTable();
573         Sname = newHashTable();
574         /* Add default signal names */
575         q = (SignalEntry *)hash_add(Sname,
576                                                           "NoViableAlt",
577                                                           (Entry *)newSignalEntry("NoViableAlt"));
578         require(q!=NULL, "cannot alloc signal entry");
579         q->signum = sigNoViableAlt;
580         q = (SignalEntry *)hash_add(Sname,
581                                                           "MismatchedToken",
582                                                           (Entry *)newSignalEntry("MismatchedToken"));
583         require(q!=NULL, "cannot alloc signal entry");
584         q->signum = sigMismatchedToken;
585         q = (SignalEntry *)hash_add(Sname,
586                                                           "NoSemViableAlt",
587                                                           (Entry *)newSignalEntry("NoSemViableAlt"));
588         require(q!=NULL, "cannot alloc signal entry");
589         q->signum = sigNoSemViableAlt;
590         
591         reserved_positions = empty;
592         all_tokens = empty;
593         imag_tokens = empty;
594         tokclasses = empty;
595         TokenStr = (char **) calloc(TSChunk, sizeof(char *));
596         require(TokenStr!=NULL, "main: cannot allocate TokenStr");
597         FoStack = (int **) calloc(CLL_k+1, sizeof(int *));
598         require(FoStack!=NULL, "main: cannot allocate FoStack");
599         FoTOS = (int **) calloc(CLL_k+1, sizeof(int *));
600         require(FoTOS!=NULL, "main: cannot allocate FoTOS");
601         Cycles = (ListNode **) calloc(CLL_k+1, sizeof(ListNode *));
602         require(Cycles!=NULL, "main: cannot allocate Cycles List");
603 }
604
605 static void
606 #ifdef __STDC__
607 help( void )
608 #else
609 help( )
610 #endif
611 {
612         Opt *p = options;
613         fprintf(stderr, "antlr [options] f1 f2 ... fn\n");
614         while ( *(p->option) != '*' )
615         {
616                 fprintf(stderr, "\t%-4s %s   %s\n",
617                                                 p->option,
618                                                 (p->arg)?"___":"   ",
619                                                 p->descr);
620                 p++;
621         }
622 }
623
624 /* The RulePtr array is filled in here.  RulePtr exists primarily
625  * so that sets of rules can be maintained for the FOLLOW caching
626  * mechanism found in rJunc().  RulePtr maps a rule num from 1 to n
627  * to a pointer to its RuleBlk junction where n is the number of rules.
628  */
629 static void
630 #ifdef __STDC__
631 buildRulePtr( void )
632 #else
633 buildRulePtr( )
634 #endif
635 {
636         int r=1;
637         Junction *p  = SynDiag;
638         RulePtr = (Junction **) calloc(NumRules+1, sizeof(Junction *));
639         require(RulePtr!=NULL, "cannot allocate RulePtr array");
640         
641         while ( p!=NULL )
642         {
643                 require(r<=NumRules, "too many rules???");
644                 RulePtr[r++] = p;
645                 p = (Junction *)p->p2;
646         }
647 }
648
649 void
650 #ifdef __STDC__
651 dlgerror(const char *s)
652 #else
653 dlgerror(s)
654 char *s;
655 #endif
656 {
657         fprintf(stderr, ErrHdr, FileStr[CurFile], zzline);
658         fprintf(stderr, " lexical error: %s (text was '%s')\n",
659                                         ((s == NULL) ? "Lexical error" : s), zzlextext);
660 }
661
662 void
663 #ifdef __STDC__
664 readDescr( void )
665 #else
666 readDescr( )
667 #endif
668 {
669         zzerr = dlgerror;
670         input = NextFile();
671         if ( input==NULL ) fatal("No grammar description found (exiting...)");
672         ANTLR(grammar(), input);
673 }
674
675 FILE *
676 #ifdef __STDC__
677 NextFile( void )
678 #else
679 NextFile( )
680 #endif
681 {
682         FILE *f;
683
684         for (;;)
685         {
686                 CurFile++;
687                 if ( CurFile >= NumFiles ) return(NULL);
688                 if ( strcmp(FileStr[CurFile],"stdin") == 0 ) return stdin;
689                 f = fopen(FileStr[CurFile], "r");
690                 if ( f == NULL )
691                 {
692                         warnNoFL( eMsg1("file %s doesn't exist; ignored", FileStr[CurFile]) );
693                 }
694                 else
695                 {
696                         return(f);
697                 }
698         }
699 }
700
701 /*
702  * Return a string corresponding to the output file name associated
703  * with the input file name passed in.
704  *
705  * Observe the following rules:
706  *
707  *              f.e             --> f".c"
708  *              f               --> f".c"
709  *              f.              --> f".c"
710  *              f.e.g   --> f.e".c"
711  *
712  * Where f,e,g are arbitrarily long sequences of characters in a file
713  * name.
714  *
715  * In other words, if a ".x" appears on the end of a file name, make it
716  * ".c".  If no ".x" appears, append ".c" to the end of the file name.
717  *
718  * C++ mode using .cpp not .c.
719  *
720  * Use malloc() for new string.
721  */
722 char *
723 #ifdef __STDC__
724 outname( char *fs )
725 #else
726 outname( fs )
727 char *fs;
728 #endif
729 {
730         static char buf[MaxFileName+1];
731         char *p;
732         require(fs!=NULL&&*fs!='\0', "outname: NULL filename");
733
734         p = buf;
735         strcpy(buf, fs);
736         while ( *p != '\0' )  {p++;}                    /* Stop on '\0' */
737         while ( *p != '.' && p != buf ) {--p;}  /* Find '.' */
738         if ( p != buf ) *p = '\0';                              /* Found '.' */
739         require(strlen(buf) + 2 < (size_t)MaxFileName, "outname: filename too big");
740         if ( GenCC ) strcat(buf, CPP_FILE_SUFFIX);
741         else strcat(buf, ".c");
742         return( buf );
743 }
744
745 void
746 #ifdef __STDC__
747 fatalFL( char *err_, char *f, int l )
748 #else
749 fatalFL( err_, f, l )
750 char *err_;
751 char *f;
752 int l;
753 #endif
754 {
755         fprintf(stderr, ErrHdr, f, l);
756         fprintf(stderr, " %s\n", err_);
757         cleanUp();
758         exit(PCCTS_EXIT_FAILURE);
759 }
760
761 void
762 #ifdef __STDC__
763 fatal_intern( char *err_, char *f, int l )
764 #else
765 fatal_intern( err_, f, l )
766 char *err_;
767 char *f;
768 int l;
769 #endif
770 {
771         fprintf(stderr, ErrHdr, f, l);
772         fprintf(stderr, " #$%%*&@# internal error: %s\n", err_);
773         fprintf(stderr, ErrHdr, f, l);
774         fprintf(stderr, " [complain to nearest government official\n");
775         fprintf(stderr, ErrHdr, f, l);
776         fprintf(stderr, "  or send hate-mail to parrt@parr-research.com;\n");
777         fprintf(stderr, ErrHdr, f, l);
778         fprintf(stderr, "  please pray to the ``bug'' gods that there is a trival fix.]\n");
779         cleanUp();
780         exit(PCCTS_EXIT_FAILURE);
781 }
782
783 void
784 #ifdef __STDC__
785 cleanUp( void )
786 #else
787 cleanUp( )
788 #endif
789 {
790         if ( DefFile != NULL) fclose( DefFile );
791 }
792
793 /* sprintf up to 3 strings */
794 char *
795 #ifdef __STDC__
796 eMsg3( char *s, char *a1, char *a2, char *a3 )
797 #else
798 eMsg3( s, a1, a2, a3 )
799 char *s;
800 char *a1;
801 char *a2;
802 char *a3;
803 #endif
804 {
805         static char buf[250];                   /* DANGEROUS as hell !!!!!! */
806         
807         sprintf(buf, s, a1, a2, a3);
808         return( buf );
809 }
810
811 /* sprintf a decimal */
812 char *
813 #ifdef __STDC__
814 eMsgd( char *s, int d )
815 #else
816 eMsgd( s, d )
817 char *s;
818 int d;
819 #endif
820 {
821         static char buf[250];                   /* DANGEROUS as hell !!!!!! */
822         
823         sprintf(buf, s, d);
824         return( buf );
825 }
826
827 void
828 #ifdef __STDC__
829 s_fprT( FILE *f, set e )
830 #else
831 s_fprT( f, e )
832 FILE *f;
833 set e;
834 #endif
835 {
836         register unsigned *p;
837         unsigned *q;
838
839         if ( set_nil(e) ) return;
840         if ( (q=p=set_pdq(e)) == NULL ) fatal_internal("Can't alloc space for set_pdq");
841         fprintf(f, "{");
842         while ( *p != nil )
843         {
844                 fprintf(f, " %s", TerminalString(*p));
845                 p++;
846         }
847         fprintf(f, " }");
848         free((char *)q);
849 }
850
851 /* Return the token name or regular expression for a token number. */
852 char *
853 #ifdef __STDC__
854 TerminalString( int token )
855 #else
856 TerminalString( token )
857 int token;
858 #endif
859 {
860         int j;
861
862         /* look in all lexclasses for the token */
863         if ( TokenString(token) != NULL ) return TokenString(token);
864         for (j=0; j<NumLexClasses; j++)
865         {
866                 lexmode(j);
867                 if ( ExprString(token) != NULL ) return ExprString(token);
868         }
869         require(j<NumLexClasses, eMsgd("No label or expr for token %d",token));
870         return "invalid";
871 }
872
873                     /* S i m p l e  I n t  S t a c k */
874
875 void
876 #ifdef __STDC__
877 pushint( int i )
878 #else
879 pushint( i )
880 int i;
881 #endif
882 {
883         require(isp>0, "pushint: stack overflow");
884         istack[--isp] = i;
885 }
886
887 int
888 #ifdef __STDC__
889 popint( void )
890 #else
891 popint( )
892 #endif
893 {
894         require(isp<MAX_INT_STACK, "popint: stack underflow");
895         return istack[isp++];
896 }
897
898 int
899 #ifdef __STDC__
900 istacksize( void )
901 #else
902 istacksize( )
903 #endif
904 {
905         return MAX_INT_STACK-isp;
906 }
907
908 void
909 #ifdef __STDC__
910 istackreset( void )
911 #else
912 istackreset( )
913 #endif
914 {
915         isp = MAX_INT_STACK;
916 }
917
918 int
919 #ifdef __STDC__
920 istackempty( void )
921 #else
922 istackempty( )
923 #endif
924 {
925         return isp==MAX_INT_STACK;
926 }
927
928 int
929 #ifdef __STDC__
930 topint( void )
931 #else
932 topint( )
933 #endif
934 {
935         require(isp<MAX_INT_STACK, "topint: stack underflow");
936         return istack[isp];
937 }
938
939 void
940 #ifdef __STDC__
941 ProcessArgs( int argc, char **argv, Opt *options )
942 #else
943 ProcessArgs( argc, argv, options )
944 int argc;
945 char **argv;
946 Opt *options;
947 #endif
948 {
949         Opt *p;
950         require(argv!=NULL, "ProcessArgs: command line NULL");
951
952         while ( argc-- > 0 )
953         {
954                 p = options;
955                 while ( p->option != NULL )
956                 {
957                         if ( strcmp(p->option, "*") == 0 ||
958                                  strcmp(p->option, *argv) == 0 )
959                         {
960                                 if ( p->arg )
961                                 {
962                                         (*p->process)( *argv, *(argv+1) );
963                                         argv++;
964                                         argc--;
965                                 }
966                                 else
967                                         (*p->process)( *argv );
968                                 break;
969                         }
970                         p++;
971                 }
972                 argv++;
973         }
974 }
975
976 /* Go back into the syntax diagram and compute all meta tokens; i.e.
977  * turn all '.', ranges, token class refs etc... into actual token sets
978  */
979 static void
980 CompleteTokenSetRefs()
981 {
982         ListNode *p;
983
984         if ( MetaTokenNodes==NULL ) return;
985         for (p = MetaTokenNodes->next; p!=NULL; p=p->next)
986         {
987                 set a,b;
988
989                 TokNode *q = (TokNode *)p->elem;
990                 if ( q->wild_card )
991                 {
992                         q->tset = all_tokens;
993                 }
994                 else if ( q->tclass!=NULL )
995                 {
996                         if ( q->complement ) q->tset = set_dif(all_tokens, q->tclass->tset);
997                         else q->tset = q->tclass->tset;
998                 }
999                 else if ( q->upper_range!=0 )
1000                 {
1001                         /* we have a range on our hands: make a set from q->token .. q->upper_range */
1002                         int i;
1003                         a = empty;
1004                         for (i=q->token; i<=(int)q->upper_range; i++) { set_orel(i, &a); }
1005                         q->tset = a;
1006                 }
1007                 /* at this point, it can only be a complemented single token */
1008                 else if ( q->complement )
1009                 {
1010                         a = set_of(q->token);
1011                         b = set_dif(all_tokens, a);
1012                         set_free(a);
1013                         q->tset=b;
1014                 }
1015                 else fatal("invalid meta token");
1016         }
1017 }
1018
1019 char *
1020 #ifdef __STDC__
1021 OutMetaName(char *n)
1022 #else
1023 OutMetaName(n)
1024 char *n;
1025 #endif
1026 {
1027         static char buf[MaxFileName+1];
1028
1029         if ( strcmp(OutputDirectory,TopDirectory)==0 ) return n;
1030         strcpy(buf, OutputDirectory);
1031         if ( strcmp(&buf[strlen(buf) - 1], DirectorySymbol ) )
1032                 strcat(buf, DirectorySymbol);
1033         strcat(buf, n);
1034         return buf;
1035 }
1036
1037 static void
1038 #ifdef __STDC__
1039 ensure_no_C_file_collisions(char *class_c_file)
1040 #else
1041 ensure_no_C_file_collisions(class_c_file)
1042 char *class_c_file;
1043 #endif
1044 {
1045         int i;
1046
1047         for (i=0; i<NumFiles; i++)
1048         {
1049 #ifdef PC
1050                 /* assume that file names are case insensitive */
1051                 if ( stricmp(outname(FileStr[i]), class_c_file)==0 )
1052 #else
1053                 if ( strcmp(outname(FileStr[i]), class_c_file)==0 )
1054 #endif
1055                 {
1056                         fatal(eMsg1("class def output file conflicts with parser output file: %s",
1057                                                 outname(FileStr[i])));
1058                 }
1059         }
1060 }
1061
1062 void
1063 #ifdef __STDC__
1064 warnNoFL(char *err)
1065 #else
1066 warnNoFL(err)
1067 char *err;
1068 #endif
1069 {
1070         fprintf(stderr, "warning: %s\n", err);
1071 }
1072
1073 void
1074 #ifdef __STDC__
1075 warnFL(char *err,char *f,int l)
1076 #else
1077 warnFL(err,f,l)
1078 char *f;
1079 int l;
1080 char *err;
1081 #endif
1082 {
1083         fprintf(stderr, ErrHdr, f, l);                                          
1084         fprintf(stderr, " warning: %s\n", err);
1085 }
1086
1087 void
1088 #ifdef __STDC__
1089 warn(char *err)                                                                                         
1090 #else
1091 warn(err)                                                                                               
1092 char *err;
1093 #endif
1094 {
1095         /* back up the file number if we hit an error at the end of the last file */
1096         if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--;
1097         fprintf(stderr, ErrHdr, FileStr[CurFile], zzline);
1098         fprintf(stderr, " warning: %s\n", err);
1099 }
1100
1101 void
1102 #ifdef __STDC__
1103 warnNoCR( char *err )
1104 #else
1105 warnNoCR( err )                                                                                 
1106 char *err;
1107 #endif
1108 {
1109         /* back up the file number if we hit an error at the end of the last file */
1110         if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--;
1111         fprintf(stderr, ErrHdr, FileStr[CurFile], zzline);
1112         fprintf(stderr, " warning: %s", err);
1113 }
1114
1115 void
1116 #ifdef __STDC__
1117 errNoFL(char *err)
1118 #else
1119 errNoFL(err)
1120 char *err;
1121 #endif
1122 {
1123         fprintf(stderr, "error: %s\n", err);
1124 }
1125
1126 void
1127 #ifdef __STDC__
1128 errFL(char *err,char *f,int l)
1129 #else
1130 errFL(err,f,l)
1131 char *err;
1132 char *f;
1133 int l;
1134 #endif
1135 {
1136         fprintf(stderr, ErrHdr, f, l);                                          
1137         fprintf(stderr, " error: %s\n", err);
1138 }
1139
1140 void
1141 #ifdef __STDC__
1142 err(char *err)                                                                                          
1143 #else
1144 err(err)                                                                                                
1145 char *err;
1146 #endif
1147 {
1148         /* back up the file number if we hit an error at the end of the last file */
1149         if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--;
1150         fprintf(stderr, ErrHdr, FileStr[CurFile], zzline);
1151         fprintf(stderr, " error: %s\n", err);
1152 }
1153
1154 void
1155 #ifdef __STDC__
1156 errNoCR( char *err )                                                                                    
1157 #else
1158 errNoCR( err )                                                                                  
1159 char *err;
1160 #endif
1161 {
1162         /* back up the file number if we hit an error at the end of the last file */
1163         if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--;
1164         fprintf(stderr, ErrHdr, FileStr[CurFile], zzline);
1165         fprintf(stderr, " error: %s", err);
1166 }
1167
1168 UserAction *
1169 #ifdef __STDC__
1170 newUserAction(char *s)
1171 #else
1172 newUserAction(s)
1173 char *s;
1174 #endif
1175 {
1176         UserAction *ua = (UserAction *) calloc(1, sizeof(UserAction));
1177         require(ua!=NULL, "cannot allocate UserAction");
1178
1179         ua->action = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
1180         strcpy(ua->action, s);
1181         return ua;
1182 }
1183
1184 /* Added by TJP September 1994 */
1185 /* Take in file.h and return file_h; names w/o '.'s are left alone */
1186 char *
1187 #ifdef __USE_PROTOS
1188 gate_symbol(char *name)
1189 #else
1190 gate_symbol(name)
1191 char *name;
1192 #endif
1193 {
1194         static char buf[100];
1195         char *p;
1196         sprintf(buf, "%s", name);
1197
1198         for (p=buf; *p!='\0'; p++)
1199         {
1200                 if ( *p=='.' ) *p = '_';
1201         }
1202         return buf;
1203 }
1204
1205 char *
1206 #ifdef __USE_PROTOS
1207 makeAltID(int blockid, int altnum)
1208 #else
1209 makeAltID(blockid, altnum)
1210 int blockid;
1211 int altnum;
1212 #endif
1213 {
1214         static char buf[100];
1215         char *p;
1216         sprintf(buf, "_blk%d_alt%d", blockid, altnum);
1217         p = (char *)malloc(strlen(buf)+1);
1218         strcpy(p, buf);
1219         return p;
1220 }