| /* | |
| * main.c -- main program for PCCTS ANTLR. | |
| * | |
| * SOFTWARE RIGHTS | |
| * | |
| * We reserve no LEGAL rights to the Purdue Compiler Construction Tool | |
| * Set (PCCTS) -- PCCTS is in the public domain. An individual or | |
| * company may do whatever they wish with source code distributed with | |
| * PCCTS or the code generated by PCCTS, including the incorporation of | |
| * PCCTS, or its output, into commerical software. | |
| * | |
| * We encourage users to develop software with PCCTS. However, we do ask | |
| * that credit is given to us for developing PCCTS. By "credit", | |
| * we mean that if you incorporate our source code into one of your | |
| * programs (commercial product, research project, or otherwise) that you | |
| * acknowledge this fact somewhere in the documentation, research report, | |
| * etc... If you like PCCTS and have developed a nice tool with the | |
| * output, please mention that you developed it using PCCTS. In | |
| * addition, we ask that this header remain intact in our source code. | |
| * As long as these guidelines are kept, we expect to continue enhancing | |
| * this system and expect to make other tools available as they are | |
| * completed. | |
| * | |
| * ANTLR 1.33 | |
| * Terence Parr | |
| * Parr Research Corporation | |
| * with Purdue University and AHPCRC, University of Minnesota | |
| * 1989-2001 | |
| */ | |
| /* To set a breakpoint just before exit look for "cleanUp". */ | |
| /* To set a breakpoint for fatal error look for "fatal_intern" */ | |
| #include <stdio.h> | |
| #include "pcctscfg.h" | |
| #include "stdpccts.h" | |
| #define MAX_INT_STACK 50 | |
| static int istack[MAX_INT_STACK]; /* Int stack */ | |
| static int isp = MAX_INT_STACK; | |
| static int DontAcceptFiles = 0; /* if stdin, don't read files */ | |
| static int DontAcceptStdin = 0; /* if files seen first, don't accept stdin */ | |
| static int tnodes_used_in_guard_predicates_etc; /* MR10 */ | |
| /* C m d - L i n e O p t i o n S t r u c t & F u n c s */ | |
| typedef struct _Opt { | |
| char *option; | |
| int arg; | |
| #ifdef __cplusplus | |
| void (*process)(...); | |
| #else | |
| void (*process)(); | |
| #endif | |
| char *descr; | |
| } Opt; | |
| #ifdef __USE_PROTOS | |
| extern void ProcessArgs(int, char **, Opt *); | |
| #else | |
| extern void ProcessArgs(); | |
| #endif | |
| #ifdef __USE_PROTOS | |
| int ci_strequ(char *a,char *b) | |
| #else | |
| int ci_strequ(a,b) | |
| char *a; | |
| char *b; | |
| #endif | |
| { | |
| for ( ;*a != 0 && *b != 0; a++, b++) { | |
| if (toupper(*a) != toupper(*b)) return 0; | |
| } | |
| return (*a == *b); | |
| } | |
| static void | |
| #ifdef __USE_PROTOS | |
| pStdin( void ) | |
| #else | |
| pStdin( ) | |
| #endif | |
| { | |
| if ( DontAcceptStdin ) | |
| { | |
| warnNoFL("'-' (stdin) ignored as files were specified first"); | |
| return; | |
| } | |
| require(NumFiles<MaxNumFiles,"exceeded max # of input files"); | |
| FileStr[NumFiles++] = "stdin"; | |
| DontAcceptFiles = 1; | |
| } | |
| static void | |
| #ifdef __USE_PROTOS | |
| pFile( char *s ) | |
| #else | |
| pFile( s ) | |
| char *s; | |
| #endif | |
| { | |
| if ( *s=='-' ) { warnNoFL( eMsg1("invalid option: '%s'",s) ); return; } | |
| if ( DontAcceptFiles ) | |
| { | |
| warnNoFL(eMsg1("file '%s' ignored as '-' (stdin option) was specified first",s)); | |
| return; | |
| } | |
| require(NumFiles<MaxNumFiles,"exceeded max # of input files"); | |
| FileStr[NumFiles++] = s; | |
| DontAcceptStdin = 1; | |
| } | |
| /* MR14 | |
| Allow input to be a file containing a list of files | |
| Bernard Giroud (b_giroud@decus.ch) | |
| */ | |
| static void | |
| #ifdef __USE_PROTOS | |
| pFileList( char *s, char *t ) | |
| #else | |
| pFileList( s, t ) | |
| char *s; | |
| char *t; | |
| #endif | |
| { | |
| #define MaxFLArea 1024 | |
| FILE *fl; | |
| static char Fn_in_Fl[MaxFLArea] = ""; | |
| char one_fn[MaxFileName]; | |
| char *flp = &Fn_in_Fl[0]; | |
| int fnl, left = MaxFLArea, i; | |
| if ( *t=='-' ) { warnNoFL( eMsg1("invalid option: '%s'",t) ); return; } | |
| if ( DontAcceptFiles ) | |
| { | |
| warnNoFL(eMsg1("file '%s' ignored as '-' (stdin option) was specified first",t)); | |
| return; | |
| } | |
| if ((fl = fopen(t, "r")) == NULL) | |
| { | |
| warnNoFL(eMsg1("file '%s' can't be opened", t)); | |
| return; | |
| } | |
| for (;;) | |
| { | |
| if (fgets(one_fn, 128 - 1, fl) == NULL) | |
| break; | |
| fnl = strlen(one_fn); | |
| require(fnl<=left, "no more room in File List Area"); | |
| /* drop the trailing LF */ | |
| if (one_fn[fnl - 1] == 0x0a) one_fn[fnl - 1] = ' '; | |
| strcat(Fn_in_Fl, one_fn); | |
| left = left - fnl; | |
| require(NumFiles<MaxNumFiles,"exceeded max # of input files"); | |
| FileStr[NumFiles++] = flp; | |
| flp = flp + fnl; | |
| } | |
| fclose(fl); | |
| for (i=0;i < MaxFLArea;i++) if (Fn_in_Fl[i] == ' ') Fn_in_Fl[i] = '\0'; | |
| DontAcceptStdin = 1; | |
| } | |
| static void | |
| #ifdef __USE_PROTOS | |
| pLLK( char *s, char *t ) | |
| #else | |
| pLLK( s, t ) | |
| char *s; | |
| char *t; | |
| #endif | |
| { | |
| LL_k = atoi(t); | |
| if ( LL_k <= 0 ) { | |
| warnNoFL("must have at least one token of lookahead (setting to 1)"); | |
| LL_k = 1; | |
| } | |
| } | |
| static void | |
| #ifdef __USE_PROTOS | |
| pCk( char *s, char *t ) | |
| #else | |
| pCk( s, t ) | |
| char *s; | |
| char *t; | |
| #endif | |
| { | |
| CLL_k = atoi(t); | |
| if ( CLL_k <= 0 ) { | |
| warnNoFL("must have at least one token of look-ahead (setting to 1)"); | |
| CLL_k = 1; | |
| } | |
| } | |
| static void /* MR6 */ | |
| #ifdef __USE_PROTOS | |
| pTab( char *s, char *t ) /* MR6 */ | |
| #else | |
| pTab( s, t ) /* MR6 */ | |
| char *s; /* MR6 */ | |
| char *t; /* MR6 */ | |
| #endif | |
| { /* MR6 */ | |
| TabWidth = atoi(t); /* MR6 */ | |
| if ( TabWidth < 0 || TabWidth > 8 ) { /* MR6 */ | |
| warnNoFL("tab width must be between 1 and 8"); /* MR6 */ | |
| TabWidth=0; /* MR6 */ | |
| } /* MR6 */ | |
| } /* MR6 */ | |
| static int ambAidDepthSpecified=0; /* MR11 */ | |
| static void /* MR11 */ | |
| #ifdef __USE_PROTOS | |
| pAAd( char *s, char *t ) /* MR11 */ | |
| #else | |
| pAAd( s, t ) /* MR11 */ | |
| char *s; /* MR11 */ | |
| char *t; /* MR11 */ | |
| #endif | |
| { /* MR11 */ | |
| ambAidDepthSpecified=1; /* MR11 */ | |
| MR_AmbAidDepth = atoi(t); /* MR11 */ | |
| } /* MR11 */ | |
| static void /* MR11 */ | |
| #ifdef __USE_PROTOS | |
| pTreport( char *s, char *t ) /* MR11 */ | |
| #else | |
| pTreport( s, t ) /* MR11 */ | |
| char *s; /* MR11 */ | |
| char *t; /* MR11 */ | |
| #endif | |
| { /* MR11 */ | |
| TnodesReportThreshold = atoi(t); /* MR11 */ | |
| } /* MR11 */ | |
| #ifdef __USE_PROTOS | |
| void chkGTFlag(void) /* 7-Apr-97 MR1 */ | |
| #else | |
| void chkGTFlag() /* 7-Apr-97 MR1 */ | |
| #endif | |
| { | |
| if ( !GenAST ) | |
| warn("#-variable or other AST item referenced w/o -gt option"); | |
| } | |
| #ifdef __USE_PROTOS | |
| static void pInfo(char *s, char *t) /* MR10 */ | |
| #else | |
| static void pInfo(s,t) /* MR10 */ | |
| char *s; | |
| char *t; | |
| #endif | |
| { | |
| char *p; | |
| int q; | |
| for (p=t; *p != 0; p++) { | |
| q=tolower(*p); | |
| if (q=='t') { | |
| InfoT=1; | |
| } else if (q=='p') { | |
| InfoP=1; | |
| } else if (q=='m') { | |
| InfoM=1; | |
| } else if (q=='o') { | |
| InfoO=1; | |
| } else if (q=='0') { | |
| ; /* nothing */ | |
| } else if (q=='f') { | |
| InfoF=1; | |
| } else { | |
| warnNoFL(eMsgd("unrecognized -info option \"%c\"",(int)*p)); | |
| }; | |
| }; | |
| } | |
| #ifdef __USE_PROTOS | |
| static void pCGen(void) { CodeGen = FALSE; LexGen = FALSE; } | |
| static void pLGen(void) { LexGen = FALSE; } | |
| static void pXTGen(void){ MR_Inhibit_Tokens_h_Gen = TRUE; } | |
| static void pTGen(void) { TraceGen = TRUE; } | |
| static void pSGen(void) { GenExprSetsOpt = FALSE; } | |
| static void pPrt(void) { PrintOut = TRUE; pCGen(); pLGen(); } | |
| static void pPrtA(void) { PrintOut = TRUE; PrintAnnotate = TRUE; pCGen(); pLGen(); } | |
| static void pAst(void) { GenAST = TRUE; } | |
| static void pANSI(void) { GenANSI = TRUE; } | |
| static void pCr(void) { GenCR = TRUE; } | |
| static void pNOPURIFY(void) { PURIFY = FALSE; } | |
| /*static void pCt(void) { warnNoFL("-ct option is now the default"); }*/ | |
| static void pLI(void) { GenLineInfo = TRUE; GenLineInfoMS = FALSE; } /* MR14 */ | |
| static void pLIms(void) { GenLineInfo = TRUE; GenLineInfoMS = TRUE; } /* MR14 */ | |
| static void pFr(char *s, char *t) {RemapFileName = t;} | |
| static void pFe(char *s, char *t) {ErrFileName = t;} | |
| static void pFl(char *s, char *t) {DlgFileName = t;} | |
| static void pFm(char *s, char *t) {ModeFileName = t;} | |
| static void pFt(char *s, char *t) {DefFileName = t;} | |
| static void pE1(void) { elevel = 1; } | |
| static void pE2(void) { elevel = 2; } | |
| static void pE3(void) { elevel = 3; } | |
| static void pEGen(void) { GenEClasseForRules = 1; } | |
| static void pDL(void) | |
| { | |
| DemandLookahead = 1; | |
| if ( GenCC ) { | |
| warnNoFL("-gk does not work currently in C++ mode; -gk turned off"); | |
| DemandLookahead = 0; | |
| } | |
| } | |
| static void pAA(char *s,char *t) {MR_AmbAidRule = t;} /* MR11 */ | |
| static void pAAm(char *s){MR_AmbAidMultiple = 1;} /* MR11 */ | |
| static void pGHdr(void) { GenStdPccts = 1; } | |
| static void pFHdr(char *s, char *t) { stdpccts = t; pGHdr(); } | |
| static void pW1(void) { WarningLevel = 1; } | |
| static void pNewAST(void) { NewAST = 1; } /* MR13 */ | |
| static void ptmakeInParser(void) { tmakeInParser = 1; } /* MR23 */ | |
| static void pAlpha(void) { AlphaBetaTrace = 1; } /* MR14 */ | |
| static void pMR_BlkErr(void) { MR_BlkErr = 1; } /* MR21 */ | |
| static void pStdout(void) {UseStdout = 1; } /* MR6 */ | |
| static void pW2(void) { WarningLevel = 2; } | |
| static void pCC(void) { GenCC = TRUE; } | |
| #else | |
| static void pCGen() { CodeGen = FALSE; LexGen = FALSE; } | |
| static void pLGen() { LexGen = FALSE; } | |
| static void pXTGen(){ MR_Inhibit_Tokens_h_Gen = TRUE; } /* MR14 */ | |
| static void pTGen() { TraceGen = TRUE; } | |
| static void pSGen() { GenExprSetsOpt = FALSE; } | |
| static void pPrt() { PrintOut = TRUE; pCGen(); pLGen(); } | |
| static void pPrtA() { PrintOut = TRUE; PrintAnnotate = TRUE; pCGen(); pLGen(); } | |
| static void pAst() { GenAST = TRUE; } | |
| static void pANSI() { GenANSI = TRUE; } | |
| static void pCr() { GenCR = TRUE; } | |
| static void pNOPURIFY() { PURIFY = FALSE; } | |
| /*static void pCt() { warnNoFL("-ct option is now the default"); }*/ | |
| static void pLI() { GenLineInfo = TRUE; GenLineInfoMS = FALSE; } /* MR14 */ | |
| static void pLIms() { GenLineInfo = TRUE; GenLineInfoMS = TRUE; } /* MR14 */ | |
| static void pFr(s,t) char *s, *t; {RemapFileName = t;} | |
| static void pFe(s,t) char *s, *t; {ErrFileName = t;} | |
| static void pFl(s,t) char *s, *t; {DlgFileName = t;} | |
| static void pFm(s,t) char *s, *t; {ModeFileName = t;} | |
| static void pFt(s,t) char *s, *t; {DefFileName = t;} | |
| static void pE1() { elevel = 1; } | |
| static void pE2() { elevel = 2; } | |
| static void pE3() { elevel = 3; } | |
| static void pEGen() { GenEClasseForRules = 1; } | |
| static void pDL() | |
| { | |
| DemandLookahead = 1; | |
| if ( GenCC ) { | |
| warnNoFL("-gk does not work currently in C++ mode; -gk turned off"); | |
| DemandLookahead = 0; | |
| } | |
| } | |
| static void pAA(s,t) char *s; char *t; {MR_AmbAidRule = t;} /* MR11 BJS 20-Mar-98 */ | |
| static void pAAm(s) char *s; {MR_AmbAidMultiple = 1;} /* MR11 BJS 20-Mar-98 */ | |
| static void pGHdr() { GenStdPccts = 1; } | |
| static void pFHdr(s,t) char *s, *t; { stdpccts = t; pGHdr(); } | |
| static void pW1() { WarningLevel = 1; } | |
| static void pNewAST() { NewAST = 1; } /* MR13 */ | |
| static void ptmakeInParser() { tmakeInParser = 1; } /* MR23 */ | |
| static void pAlpha() { AlphaBetaTrace = 1; } /* MR14 */ | |
| static void pMR_BlkErr() { MR_BlkErr = 1; } /* MR21 */ | |
| static void pStdout() {UseStdout = 1; } /* MR6 */ | |
| static void pW2() { WarningLevel = 2; } | |
| static void pCC() { GenCC = TRUE; } | |
| #endif | |
| static void | |
| #ifdef __USE_PROTOS | |
| pPre( char *s, char *t ) | |
| #else | |
| pPre( s, t ) | |
| char *s; | |
| char *t; | |
| #endif | |
| { | |
| RulePrefix = t; | |
| } | |
| static void | |
| #ifdef __USE_PROTOS | |
| pOut( char *s, char *t ) | |
| #else | |
| pOut( s, t ) | |
| char *s; | |
| char *t; | |
| #endif | |
| { | |
| OutputDirectory = t; | |
| } | |
| static void | |
| #ifdef __USE_PROTOS | |
| pPred( void ) | |
| #else | |
| pPred( ) | |
| #endif | |
| { | |
| warnNoFL("-pr is no longer used (predicates employed if present); see -prc, -mrhoist, -mrhoistk"); | |
| /* | |
| ** if ( DemandLookahead ) | |
| ** warnNoFL("-gk conflicts with -pr; -gk turned off"); | |
| ** DemandLookahead = 0; | |
| ** HoistPredicateContext = 0; | |
| */ | |
| } | |
| static void | |
| #ifdef __USE_PROTOS | |
| pPredCtx( char *s, char *t ) | |
| #else | |
| pPredCtx(s,t) | |
| char *s; | |
| char *t; | |
| #endif | |
| { | |
| if ( ci_strequ(t,"on")) HoistPredicateContext = 1; | |
| else if ( ci_strequ(t,"off")) HoistPredicateContext = 0; | |
| if ( DemandLookahead ) | |
| { | |
| warnNoFL("-gk incompatible with semantic predicate usage; -gk turned off"); | |
| DemandLookahead = 0; | |
| } | |
| } | |
| static void | |
| #ifdef __USE_PROTOS | |
| pMRhoist( char *s, char *t ) | |
| #else | |
| pMRhoist(s,t) | |
| char *s; | |
| char *t; | |
| #endif | |
| { | |
| if ( ci_strequ(t,"on")) MRhoisting = 1; | |
| else if ( ci_strequ(t,"off")==0 ) MRhoisting = 0; | |
| if (MRhoisting) { | |
| fprintf(stderr,"Maintenance Release style hoisting enabled for predicates with lookahead depth = 1\n"); | |
| fprintf(stderr," No longer considered experimental\n"); | |
| fprintf(stderr," Can't consider suppression for predicates with lookahead depth > 1\n"); | |
| fprintf(stderr," Implies -prc on but does *not* imply -mrhoistk for k>1 predicates\n"); | |
| fprintf(stderr," This is a reminder, not a warning or error.\n"); | |
| }; | |
| } | |
| static void | |
| #ifdef __USE_PROTOS | |
| pMRhoistk( char *s, char *t ) | |
| #else | |
| pMRhoistk(s,t) | |
| char *s; | |
| char *t; | |
| #endif | |
| { | |
| if ( ci_strequ(t,"on")) MRhoistingk = 1; | |
| else if ( ci_strequ(t,"off")==0 ) MRhoistingk = 0; | |
| if (MRhoistingk) { | |
| fprintf(stderr,"EXPERIMENTAL Maintenance Release style hoisting enabled\n"); | |
| fprintf(stderr," Applies to predicates with lookahead depth > 1\n"); | |
| fprintf(stderr," Implies -prc on and -mrhoist on\n"); | |
| }; | |
| } | |
| static void | |
| #ifdef __USE_PROTOS | |
| pTRes( char *s, char *t ) | |
| #else | |
| pTRes( s, t ) | |
| char *s; | |
| char *t; | |
| #endif | |
| { | |
| TreeResourceLimit = atoi(t); | |
| if ( TreeResourceLimit <= 0 ) | |
| { | |
| warnNoFL("analysis resource limit (# of tree nodes) must be greater than 0"); | |
| TreeResourceLimit = -1; /* set to no limit */ | |
| } | |
| } | |
| Opt options[] = { | |
| #ifdef __cplusplus | |
| { "-CC", 0, (void (*)(...)) pCC, "Generate C++ output (default=FALSE)"}, | |
| { "-ck", 1, (void (*)(...)) pCk, "Set compressed lookahead depth; fast approximate lookahead"}, | |
| { "-cr", 0, (void (*)(...)) pCr, "Generate cross reference (default=FALSE)"}, | |
| { "-e1", 0, (void (*)(...)) pE1, "Ambiguities/errors shown in low detail (default)"}, | |
| { "-e2", 0, (void (*)(...)) pE2, "Ambiguities/errors shown in more detail"}, | |
| { "-e3", 0, (void (*)(...)) pE3, | |
| "Ambiguities for k>1 grammars shown with exact tuples (not lookahead sets)"}, | |
| { "-f", 1, (void (*)(...)) pFileList,"Read names of grammar files from specified file"}, /* MR14 */ | |
| { "-fe", 1, (void (*)(...)) pFe, "Rename err.c"}, | |
| { "-fh", 1, (void (*)(...)) pFHdr, "Rename stdpccts.h header (turns on -gh)"}, | |
| { "-fl", 1, (void (*)(...)) pFl, "Rename lexical output--parser.dlg"}, | |
| { "-fm", 1, (void (*)(...)) pFm, "Rename mode.h"}, | |
| { "-fr", 1, (void (*)(...)) pFr, "Rename remap.h"}, | |
| { "-ft", 1, (void (*)(...)) pFt, "Rename tokens.h"}, | |
| { "-ga", 0, (void (*)(...)) pANSI, "Generate ANSI-compatible code (default=FALSE)"}, | |
| { "-gc", 0, (void (*)(...)) pCGen, "Do not generate output parser code (default=FALSE)"}, | |
| { "-gd", 0, (void (*)(...)) pTGen, "Generate code to trace rule invocation (default=FALSE)"}, | |
| { "-ge", 0, (void (*)(...)) pEGen, "Generate an error class for each non-terminal (default=FALSE)"}, | |
| { "-gh", 0, (void (*)(...)) pGHdr, "Generate stdpccts.h for non-ANTLR-generated-files to include"}, | |
| { "-gk", 0, (void (*)(...)) pDL, "Generate parsers that delay lookahead fetches until needed"}, | |
| { "-gl", 0, (void (*)(...)) pLI, "Generate line info about grammar actions in parser"}, | |
| { "-glms", 0, (void (*)(...)) pLIms,"Like -gl but replace '\\' with '/' in #line filenames for MS C/C++ systems"}, | |
| { "-gp", 1, (void (*)(...)) pPre, "Prefix all generated rule functions with a string"}, | |
| { "-gs", 0, (void (*)(...)) pSGen, "Do not generate sets for token expression lists (default=FALSE)"}, | |
| { "-gt", 0, (void (*)(...)) pAst, "Generate code for Abstract-Syntax-Trees (default=FALSE)"}, | |
| { "-gx", 0, (void (*)(...)) pLGen, "Do not generate lexical (dlg-related) files (default=FALSE)"}, | |
| { "-gxt",0, (void (*)(...)) pXTGen, "Do not generate tokens.h (default=FALSE)"}, | |
| { "-k", 1, (void (*)(...)) pLLK, "Set full LL(k) lookahead depth (default==1)"}, | |
| { "-o", 1, (void (*)(...)) pOut, OutputDirectoryOption}, | |
| { "-p", 0, (void (*)(...)) pPrt, "Print out the grammar w/o actions (default=no)"}, | |
| { "-pa", 0, (void (*)(...)) pPrtA, "Print out the grammar w/o actions & w/FIRST sets (default=no)"}, | |
| { "-pr",0, (void (*)(...)) pPred, "no longer used; predicates employed if present"}, | |
| { "-prc", 1, (void (*)(...)) pPredCtx,"Turn on/off computation of context for hoisted predicates"}, | |
| { "-rl", 1, (void (*)(...)) pTRes, "Limit max # of tree nodes used by grammar analysis"}, | |
| { "-stdout",0, (void (*)(...)) pStdout,"Send grammar.c/grammar.cpp to stdout"}, /* MR6 */ | |
| { "-tab", 1, (void (*)(...)) pTab, "Width of tabs (1 to 8) for grammar.c/grammar.cpp files"}, /* MR6 */ | |
| { "-w1", 0, (void (*)(...)) pW1, "Set the warning level to 1 (default)"}, | |
| { "-w2", 0, (void (*)(...)) pW2, "Ambiguities yield warnings even if predicates or (...)? block"}, | |
| { "-", 0, (void (*)(...)) pStdin, "Read grammar from stdin" }, | |
| { "-mrhoist",1, (void (*)(...)) pMRhoist, /* MR9 */ | |
| "Turn on/off k=1 Maintenance Release style hoisting"}, /* MR9 */ | |
| { "-mrhoistk",1, (void (*)(...)) pMRhoistk, /* MR9 */ | |
| "Turn on/off EXPERIMENTAL k>1 Maintenance Release style hoisting"}, /* MR13 */ | |
| { "-aa" , 1, (void (*)(...)) pAA, "Ambiguity aid for a rule (rule name or line number)"}, /* MR11 */ | |
| { "-aam" , 0, (void (*)(...)) pAAm, | |
| "Lookahead token may appear multiple times in -aa listing"}, /* MR11 */ | |
| { "-aad" , 1, (void (*)(...)) pAAd, | |
| "Limits exp growth of -aa listing - default=1 (max=ck value)"}, /* MR11 */ | |
| { "-info", 1, (void (*)(...)) pInfo, | |
| "Extra info: p=pred t=tnodes f=first/follow m=monitor o=orphans 0=noop"}, /* MR12 */ | |
| { "-treport",1,(void (*)(...)) pTreport, | |
| "Report when tnode usage exceeds value during ambiguity resolution"}, /* MR11 */ | |
| { "-newAST", 0, (void (*)(...)) pNewAST, | |
| "In C++ mode use \"newAST(...)\" rather than \"new AST(...)\""}, /* MR13 */ | |
| { "-tmake", 0, (void (*)(...)) ptmakeInParser, | |
| "In C++ mode use parser's tmake method rather than \"ASTBase::tmake(...)\""}, /* MR23 */ | |
| { "-alpha",0,(void (*)(...)) pAlpha, | |
| "Provide additional information for \"(alpha)? beta\" error messages"}, /* MR14 */ | |
| { "-mrblkerr",0,(void (*)(...)) pMR_BlkErr, /* MR21 */ | |
| "EXPERIMENTAL change to (...)* and (...)+ syntax error sets"}, /* MR21 */ | |
| { "-nopurify",0,(void (*)(...)) pNOPURIFY, | |
| "Don't use the notorious PURIFY macro (replaced by MR23 initial value syntax) to zero return arguments of rules"}, /* MR23 */ | |
| { "*", 0, (void (*)(...)) pFile, "" }, /* anything else is a file */ | |
| #else | |
| { "-CC", 0, pCC, "Generate C++ output (default=FALSE)"}, | |
| { "-cr", 0, pCr, "Generate cross reference (default=FALSE)"}, | |
| { "-ck", 1, pCk, "Set compressed lookahead depth; fast approximate lookahead"}, | |
| { "-e1", 0, pE1, "Ambiguities/errors shown in low detail (default)"}, | |
| { "-e2", 0, pE2, "Ambiguities/errors shown in more detail"}, | |
| { "-e3", 0, pE3, "Ambiguities for k>1 grammars shown with exact tuples (not lookahead sets)"}, | |
| { "-f", 1, pFileList,"Read names of grammar files from specified file"}, /* MR14 */ | |
| { "-fe", 1, pFe, "Rename err.c"}, | |
| { "-fh", 1, pFHdr, "Rename stdpccts.h header (turns on -gh)"}, | |
| { "-fl", 1, pFl, "Rename lexical output--parser.dlg"}, | |
| { "-fm", 1, pFm, "Rename mode.h"}, | |
| { "-fr", 1, pFr, "Rename remap.h"}, | |
| { "-ft", 1, pFt, "Rename tokens.h"}, | |
| { "-ga", 0, pANSI, "Generate ANSI-compatible code (default=FALSE)"}, | |
| { "-gc", 0, pCGen, "Do not generate output parser code (default=FALSE)"}, | |
| { "-gd", 0, pTGen, "Generate code to trace rule invocation (default=FALSE)"}, | |
| { "-ge", 0, pEGen, "Generate an error class for each non-terminal (default=FALSE)"}, | |
| { "-gh", 0, pGHdr, "Generate stdpccts.h for non-ANTLR-generated-files to include"}, | |
| { "-gk", 0, pDL, "Generate parsers that delay lookahead fetches until needed"}, | |
| { "-gl", 0, pLI, "Generate line info about grammar actions in C parser"}, | |
| { "-glms", 0, pLIms,"Like -gl but replace '\\' with '/' in #line filenames for MS C/C++ systems"}, | |
| { "-gp", 1, pPre, "Prefix all generated rule functions with a string"}, | |
| { "-gs", 0, pSGen, "Do not generate sets for token expression lists (default=FALSE)"}, | |
| { "-gt", 0, pAst, "Generate code for Abstract-Syntax-Trees (default=FALSE)"}, | |
| { "-gx", 0, pLGen, "Do not generate lexical (dlg-related) files (default=FALSE)"}, | |
| { "-gxt",0, pXTGen, "Do not generate tokens.h (default=FALSE)"}, | |
| { "-k", 1, pLLK, "Set full LL(k) lookahead depth (default==1)"}, | |
| { "-o", 1, pOut, OutputDirectoryOption}, | |
| { "-p", 0, pPrt, "Print out the grammar w/o actions (default=no)"}, | |
| { "-pa", 0, pPrtA, "Print out the grammar w/o actions & w/FIRST sets (default=no)"}, | |
| { "-pr",0, pPred, "no longer used; predicates employed if present"}, | |
| { "-prc", 1, pPredCtx,"Turn on/off computation of context for hoisted predicates"}, | |
| { "-rl", 1, pTRes, "Limit max # of tree nodes used by grammar analysis"}, | |
| { "-stdout",0, pStdout, "Send grammar.c/grammar.cpp to stdout"}, /* MR6 */ | |
| { "-tab", 1, pTab, "Width of tabs (1 to 8) for grammar.c/grammar.cpp files"}, /* MR6 */ | |
| { "-w1", 0, pW1, "Set the warning level to 1 (default)"}, | |
| { "-w2", 0, pW2, "Ambiguities yield warnings even if predicates or (...)? block"}, | |
| { "-mrhoist",1,pMRhoist, /* MR9 */ | |
| "Turn on/off k=1 Maintenance Release style hoisting"}, /* MR9 */ | |
| { "-mrhoistk",1,pMRhoistk, /* MR13 */ | |
| "Turn on/off k>1 EXPERIMENTAL Maintenance Release style hoisting"}, /* MR13 */ | |
| { "-aa" ,1,pAA, "Ambiguity aid for a rule (rule name or line number)"}, /* MR11 */ | |
| { "-aam" ,0,pAAm, | |
| "Lookahead token may appear multiple times in -aa listing"}, /* MR11 */ | |
| { "-aad" ,1,pAAd, | |
| "Limits exp growth of -aa listing - default=1 (max=ck value)"}, /* MR11 */ | |
| { "-info",1,pInfo, | |
| "Extra info: p=pred t=tnodes f=first/follow m=monitor o=orphans 0=noop"}, /* MR11 */ | |
| { "-treport",1,pTreport, | |
| "Report when tnode usage exceeds value during ambiguity resolution"}, /* MR11 */ | |
| { "-newAST", 0, pNewAST, | |
| "In C++ mode use \"newAST(...)\" rather than \"new AST(...)\""}, /* MR13 */ | |
| { "-tmake", 0, ptmakeInParser, | |
| "In C++ mode use parser's tmake method rather than \"ASTBase::tmake(...)\""}, /* MR23 */ | |
| { "-alpha",0, pAlpha, | |
| "Provide additional information for \"(alpha)? beta\" error messages"}, /* MR14 */ | |
| { "-mrblkerr",0,pMR_BlkErr, /* MR21 */ | |
| "EXPERIMENTAL change to (...)* and (...)+ syntax error sets"}, /* MR21 */ | |
| { "-nopurify",0,pNOPURIFY, | |
| "Don't use the notorious PURIFY macro (replaced by MR23 initial value syntax) to zero return arguments of rules"}, /* MR23 */ | |
| { "-", 0, pStdin, "Read grammar from stdin" }, | |
| { "*", 0, pFile, "" }, /* anything else is a file */ | |
| #endif | |
| { NULL, 0, NULL } | |
| }; | |
| void readDescr(); | |
| void cleanUp(); | |
| #ifdef __USE_PROTOS | |
| static void buildRulePtr( void ); | |
| static void help( void ); | |
| static void init( void ); | |
| static void CompleteTokenSetRefs( void ); | |
| static void ensure_no_C_file_collisions(char *); | |
| static void CompleteContextGuards(void); | |
| #else | |
| static void buildRulePtr( ); | |
| static void help( ); | |
| static void init( ); | |
| static void CompleteTokenSetRefs( ); | |
| static void ensure_no_C_file_collisions(); | |
| static void CompleteContextGuards(); | |
| #endif | |
| static void | |
| #ifdef __USE_PROTOS /* <BJS> */ | |
| report_numericPredLabels(ActionNode *a) | |
| #else | |
| report_numericPredLabels(a) | |
| ActionNode *a; | |
| #endif | |
| { /* MR10 */ | |
| warnFL("numeric references to attributes (e.g. $i or $i.j) in semantic pred will be null during guess mode", /* MR10 */ | |
| FileStr[a->file],a->line); /* MR10 */ | |
| } /* MR10 */ | |
| /* M a i n */ | |
| int | |
| #ifdef __USE_PROTOS | |
| main( int argc, char *argv[] ) | |
| #else | |
| main( argc, argv ) | |
| int argc; | |
| char *argv[]; | |
| #endif | |
| { | |
| int i; | |
| static char EPSTR[] = "[Ep]"; | |
| Save_argc=argc; /* MR10 */ | |
| Save_argv=argv; /* MR10 */ | |
| /* malloc_debug(8);*/ | |
| #ifdef SPECIAL_INITS | |
| special_inits(); /* MR1 */ | |
| #endif | |
| fprintf(stderr, "Antlr parser generator Version %s 1989-2001\n", Version); | |
| if ( argc == 1 ) { help(); zzDIE; } | |
| ProcessArgs(argc-1, &(argv[1]), options); | |
| /* MR14 */ if (MR_AmbAidRule && AlphaBetaTrace) { | |
| /* MR14 */ fatal("Can't specify both -aa (ambiguity aid) and -alpha (\"(alpha)? beta\" aid)"); | |
| /* MR14 */ } | |
| if (MRhoistingk) { /* MR13 */ | |
| HoistPredicateContext=1; /* MR13 */ | |
| MRhoisting=1; /* MR13 */ | |
| }; /* MR13 */ | |
| if (MRhoisting && ! HoistPredicateContext) { | |
| /*** warnNoFL("Using \"-mrhoist\" forces \"-prc on\""); ***/ | |
| HoistPredicateContext=1; | |
| }; | |
| if (HoistPredicateContext && ! MRhoisting) { | |
| warnNoFL("When using predicate context (-prc on) -mrhoist on is recommended"); | |
| } | |
| /* Fix lookahead depth */ | |
| /* Compressed lookahead must always be larger than or equal to full lookahead */ | |
| if ( CLL_k < LL_k && CLL_k>0 ) | |
| { | |
| warnNoFL("must have compressed lookahead >= full LL(k) lookahead (setting -ck to -k)"); | |
| CLL_k = LL_k; | |
| } | |
| if ( CLL_k == -1 ) CLL_k = LL_k; | |
| OutputLL_k = CLL_k; | |
| if ( ((CLL_k-1)&CLL_k)!=0 ) { /* output ll(k) must be power of 2 */ | |
| int n; | |
| for(n=1; n<CLL_k; n<<=1) {;} | |
| OutputLL_k = n; | |
| }; | |
| if (MR_BlkErr) { | |
| warnNoFL("The -mrblkerr option is EXPERIMENTAL"); | |
| if (LL_k > 1) { | |
| warnNoFL("The -mrblkerr option is designed only for k=1 ck=1 grammars"); | |
| } | |
| }; | |
| if ( ! ambAidDepthSpecified) { | |
| MR_AmbAidDepth=1; | |
| } else { | |
| if (MR_AmbAidDepth > CLL_k || MR_AmbAidDepth <= 0) { | |
| warnNoFL(eMsgd( | |
| "Ambiguity aid depth (\"-aad ...\") must be a number between 1 and max(k,ck)=%d",CLL_k)); | |
| MR_AmbAidDepth=1; | |
| }; | |
| if (MR_AmbAidDepth == 0) { | |
| MR_AmbAidDepth=2; | |
| }; | |
| }; | |
| if (MR_AmbAidRule != NULL) MR_AmbAidLine=atoi(MR_AmbAidRule); | |
| fpTrans = &(C_Trans[0]); /* Translate to C Language */ | |
| fpJTrans = &(C_JTrans[0]); | |
| init(); | |
| lexclass(LexStartSymbol); | |
| readDescr(); | |
| LastTokenCounted = TokenNum; | |
| RemapForcedTokens(); | |
| if ( CannotContinue ) {cleanUp(); zzDIE;} | |
| if ( GenCC && no_classes_found ) fatal("required grammar class not found (exiting...)"); | |
| if ( WarningLevel>1 && HdrAction == NULL ) | |
| warnNoFL("no #header action was found"); | |
| if ( FoundAtOperator && ! FoundExceptionGroup) { | |
| warnNoFL("found the exception operator '@' - but no exception group was found"); | |
| }; | |
| EpToken = addTname(EPSTR); /* add imaginary token epsilon */ | |
| set_orel(EpToken, &imag_tokens); | |
| /* this won't work for hand-built scanners since EofToken is not | |
| * known. Forces EOF to be token type 1. | |
| */ | |
| set_orel(EofToken, &imag_tokens); | |
| set_size(NumWords(TokenNum-1)); | |
| /* compute the set of all known token types | |
| * It represents the set of tokens from 1 to last_token_num + the | |
| * reserved positions above that (if any). Don't include the set of | |
| * imaginary tokens such as the token/error classes or EOF. | |
| */ | |
| { | |
| set a; | |
| a = set_dup(reserved_positions); | |
| for (i=1; i<TokenNum; i++) { set_orel(i, &a); } | |
| all_tokens = set_dif(a, imag_tokens); | |
| set_free(a); | |
| } | |
| ComputeTokSets(); /* Compute #tokclass sets */ | |
| CompleteTokenSetRefs(); /* Change complex nodes in syn diag */ | |
| CompleteContextGuards(); /* MR13 */ | |
| if ( CodeGen ) genDefFile(); /* create tokens.h */ | |
| if ( LexGen ) genLexDescr(); /* create parser.dlg */ | |
| if ( GenStdPccts ) | |
| { | |
| FILE *f = fopen(OutMetaName(stdpccts), "w"); | |
| if ( f==NULL ) {warnNoFL( eMsg1("can't create %s",OutMetaName(stdpccts)) );} | |
| else | |
| { | |
| #ifdef SPECIAL_FOPEN | |
| special_fopen_actions(OutMetaName(stdpccts)); /* MR1 */ | |
| #endif | |
| if (strcmp(stdpccts,"stdpccts.h") == 0) { /* MR10 */ | |
| genStdPCCTSIncludeFile(f,NULL); /* MR10 */ | |
| } else { /* MR10 */ | |
| genStdPCCTSIncludeFile(f,pcctsBaseName(stdpccts)); /* MR32 */ | |
| }; | |
| fclose(f); | |
| } | |
| } | |
| buildRulePtr(); /* create mapping from rule # to RuleBlk junction */ | |
| ComputeErrorSets(); | |
| FoLink( (Node *)SynDiag ); /* add follow links to end of all rules */ | |
| if ( GenCR ) GenCrossRef( SynDiag ); | |
| if ( CodeGen ) | |
| { | |
| if ( SynDiag == NULL ) | |
| { | |
| warnNoFL("no grammar description recognized"); | |
| cleanUp(); | |
| zzDIE; | |
| } | |
| else if ( !GenCC ) { | |
| ErrFile = fopen(OutMetaName(ErrFileName), "w"); | |
| require(ErrFile != NULL, "main: can't open err file"); | |
| #ifdef SPECIAL_FOPEN | |
| special_fopen_actions(OutMetaName(ErrFileName)); /* MR1 */ | |
| #endif | |
| NewSetWd(); | |
| GenErrHdr(); | |
| TRANS(SynDiag); /* Translate to the target language */ | |
| DumpSetWd(); | |
| DumpRemainingTokSets(); | |
| fclose( ErrFile ); | |
| } | |
| else { | |
| strcpy(Parser_h_Name, CurrentClassName); | |
| strcat(Parser_h_Name, ".h"); | |
| strcpy(Parser_c_Name, CurrentClassName); | |
| strcat(Parser_c_Name, CPP_FILE_SUFFIX); | |
| ensure_no_C_file_collisions(Parser_c_Name); | |
| Parser_h = fopen(OutMetaName(Parser_h_Name), "w"); | |
| require(Parser_h != NULL, "main: can't open class Parserx.h file"); | |
| #ifdef SPECIAL_FOPEN | |
| special_fopen_actions(OutMetaName(Parser_h_Name)); /* MR1 */ | |
| #endif | |
| Parser_c = fopen(OutMetaName(Parser_c_Name), "w"); | |
| require(Parser_c != NULL, "main: can't open class Parserx.c file"); | |
| #ifdef SPECIAL_FOPEN | |
| special_fopen_actions(OutMetaName(Parser_c_Name)); /* MR1 */ | |
| #endif | |
| GenParser_h_Hdr(); | |
| if ( class_before_actions != NULL ) | |
| { | |
| ListNode *p; | |
| for (p = class_before_actions->next; p!=NULL; p=p->next) | |
| { | |
| UserAction *ua = (UserAction *)p->elem; | |
| dumpAction( ua->action, Parser_h, 0, ua->file, ua->line, 1); | |
| } | |
| } | |
| GenParser_c_Hdr(); | |
| fprintf(Parser_h, "protected:\n"); /* MR20 */ | |
| NewSetWd(); | |
| TRANS(SynDiag); /* Translate to the target language */ | |
| DumpSetWd(); | |
| GenRuleMemberDeclarationsForCC(Parser_h, SynDiag); | |
| if ( class_after_actions != NULL ) | |
| { | |
| ListNode *p; | |
| for (p = class_after_actions->next; p!=NULL; p=p->next) | |
| { | |
| UserAction *ua = (UserAction *)p->elem; | |
| dumpAction( ua->action, Parser_h, 0, ua->file, ua->line, 1); | |
| } | |
| } | |
| DumpRemainingTokSets(); | |
| fprintf(Parser_h, "};\n"); | |
| fprintf(Parser_h, "\n#endif /* %s_h */\n", CurrentClassName); | |
| fclose( Parser_h ); | |
| fclose( Parser_c ); | |
| } | |
| } | |
| MR_orphanRules(stderr); | |
| if (LTinTokenAction && WarningLevel >= 2) { | |
| if (GenCC) { | |
| 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."); | |
| } | |
| 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."); | |
| } | |
| if ( PrintOut ) | |
| { | |
| if ( SynDiag == NULL ) {warnNoFL("no grammar description recognized");} | |
| else PRINT(SynDiag); | |
| } | |
| #ifdef DBG_LL1 | |
| #endif | |
| GenRemapFile(); /* create remap.h */ | |
| /* MR10 */ if (FoundGuessBlk) { | |
| #ifdef __cplusplus__ | |
| /* MR10 */ list_apply(NumericPredLabels, (void (*)(void *))report_numericPredLabels); | |
| #else | |
| #ifdef __USE_PROTOS | |
| /* MR10 */ list_apply(NumericPredLabels, (void (*)(void *))report_numericPredLabels); | |
| #else | |
| /* MR10 */ list_apply(NumericPredLabels,report_numericPredLabels); | |
| #endif | |
| #endif | |
| /* MR10 */ }; | |
| if (InfoT && TnodesAllocated > 0) { | |
| if (TnodesPeak > 10000) { | |
| fprintf(stdout,"\nTree Nodes: peak %dk created %dk lost %d\n", | |
| (TnodesPeak/1000), | |
| (TnodesAllocated/1000), | |
| TnodesInUse-tnodes_used_in_guard_predicates_etc); | |
| } else { | |
| fprintf(stdout,"\nTree Nodes: peak %d created %d lost %d\n", | |
| TnodesPeak, | |
| TnodesAllocated, | |
| TnodesInUse-tnodes_used_in_guard_predicates_etc); | |
| }; | |
| }; | |
| if (InfoF) { | |
| DumpFcache(); | |
| }; | |
| if (MR_skipped_e3_report) { | |
| fprintf(stderr,"note: use -e3 to get exact information on ambiguous tuples\n"); | |
| }; | |
| if (MR_BadExprSets != 0) { | |
| fprintf(stderr,"note: Unreachable C or C++ code was generated for empty expression sets,\n"); | |
| fprintf(stderr," probably due to undefined rules or infinite left recursion.\n"); | |
| fprintf(stderr," To locate: search the generated code for \"empty set expression\"\n"); | |
| }; | |
| if (MR_AmbAidRule != NULL && MR_matched_AmbAidRule==0) { | |
| RuleEntry *q = (RuleEntry *) hash_get(Rname,MR_AmbAidRule); | |
| if (MR_AmbAidLine == 0 && q == NULL) { | |
| warnNoFL(eMsg2("there is no rule \"%s\" so \"-aa %s\" will never match", | |
| MR_AmbAidRule,MR_AmbAidRule)); | |
| } else { | |
| warnNoFL(eMsg1("there was no ambiguity that matched \"-aa %s\"",MR_AmbAidRule)); | |
| }; | |
| }; | |
| if (AlphaBetaTrace) { | |
| if (MR_AlphaBetaMessageCount == 0) { | |
| fprintf(stderr,"note: there were no messages about \"(alpha)? beta\" blocks added to the generated code\n"); | |
| } else { | |
| fprintf(stderr,"note: there were %d messages about \"(alpha)? beta\" blocks added to the generated code\n", | |
| MR_AlphaBetaMessageCount); | |
| } | |
| if (set_null(MR_CompromisedRules)) { | |
| fprintf(stderr,"note: the list of rules with compromised follow sets is empty\n"); | |
| } else { | |
| fprintf(stderr,"note: the following is a list of rules which *may* have incorrect\n"); | |
| fprintf(stderr," follow sets computed as a result of an \"(alpha)? beta\" block\n"); | |
| fprintf(stderr,"\n"); | |
| MR_dumpRuleSet(MR_CompromisedRules); | |
| fprintf(stderr,"\n"); | |
| } | |
| } | |
| cleanUp(); | |
| exit(PCCTS_EXIT_SUCCESS); | |
| return 0; /* MR11 make compilers happy */ | |
| } | |
| static void | |
| #ifdef __USE_PROTOS | |
| init( void ) | |
| #else | |
| init( ) | |
| #endif | |
| { | |
| SignalEntry *q; | |
| Tname = newHashTable(); | |
| Rname = newHashTable(); | |
| Fcache = newHashTable(); | |
| Tcache = newHashTable(); | |
| Sname = newHashTable(); | |
| Pname = newHashTable(); /* MR11 */ | |
| /* Add default signal names */ | |
| q = (SignalEntry *)hash_add(Sname, | |
| "NoViableAlt", | |
| (Entry *)newSignalEntry("NoViableAlt")); | |
| require(q!=NULL, "cannot alloc signal entry"); | |
| q->signum = sigNoViableAlt; | |
| q = (SignalEntry *)hash_add(Sname, | |
| "MismatchedToken", | |
| (Entry *)newSignalEntry("MismatchedToken")); | |
| require(q!=NULL, "cannot alloc signal entry"); | |
| q->signum = sigMismatchedToken; | |
| q = (SignalEntry *)hash_add(Sname, | |
| "NoSemViableAlt", | |
| (Entry *)newSignalEntry("NoSemViableAlt")); | |
| require(q!=NULL, "cannot alloc signal entry"); | |
| q->signum = sigNoSemViableAlt; | |
| reserved_positions = empty; | |
| all_tokens = empty; | |
| imag_tokens = empty; | |
| tokclasses = empty; | |
| TokenStr = (char **) calloc(TSChunk, sizeof(char *)); | |
| require(TokenStr!=NULL, "main: cannot allocate TokenStr"); | |
| FoStack = (int **) calloc(CLL_k+1, sizeof(int *)); | |
| require(FoStack!=NULL, "main: cannot allocate FoStack"); | |
| FoTOS = (int **) calloc(CLL_k+1, sizeof(int *)); | |
| require(FoTOS!=NULL, "main: cannot allocate FoTOS"); | |
| Cycles = (ListNode **) calloc(CLL_k+1, sizeof(ListNode *)); | |
| require(Cycles!=NULL, "main: cannot allocate Cycles List"); | |
| MR_CompromisedRules=empty; /* MR14 */ | |
| } | |
| static void | |
| #ifdef __USE_PROTOS | |
| help( void ) | |
| #else | |
| help( ) | |
| #endif | |
| { | |
| Opt *p = options; | |
| fprintf(stderr, "antlr [options] f1 f2 ... fn\n"); | |
| while ( *(p->option) != '*' ) | |
| { | |
| fprintf(stderr, " %-9s%s %s\n", | |
| p->option, | |
| (p->arg)?"___":" ", | |
| p->descr); | |
| p++; | |
| } | |
| } | |
| /* The RulePtr array is filled in here. RulePtr exists primarily | |
| * so that sets of rules can be maintained for the FOLLOW caching | |
| * mechanism found in rJunc(). RulePtr maps a rule num from 1 to n | |
| * to a pointer to its RuleBlk junction where n is the number of rules. | |
| */ | |
| static void | |
| #ifdef __USE_PROTOS | |
| buildRulePtr( void ) | |
| #else | |
| buildRulePtr( ) | |
| #endif | |
| { | |
| int r=1; | |
| Junction *p = SynDiag; | |
| RulePtr = (Junction **) calloc(NumRules+1, sizeof(Junction *)); | |
| require(RulePtr!=NULL, "cannot allocate RulePtr array"); | |
| while ( p!=NULL ) | |
| { | |
| require(r<=NumRules, "too many rules???"); | |
| RulePtr[r++] = p; | |
| p = (Junction *)p->p2; | |
| } | |
| } | |
| void | |
| #ifdef __USE_PROTOS | |
| dlgerror(const char *s) | |
| #else | |
| dlgerror(s) | |
| char *s; | |
| #endif | |
| { | |
| fprintf(stderr, ErrHdr, FileStr[CurFile], zzline); | |
| fprintf(stderr, " lexical error: %s (text was '%s')\n", | |
| ((s == NULL) ? "Lexical error" : s), zzlextext); | |
| } | |
| void | |
| #ifdef __USE_PROTOS | |
| readDescr( void ) | |
| #else | |
| readDescr( ) | |
| #endif | |
| { | |
| zzerr = dlgerror; | |
| input = NextFile(); | |
| if ( input==NULL ) fatal("No grammar description found (exiting...)"); | |
| ANTLR(grammar(), input); | |
| tnodes_used_in_guard_predicates_etc=TnodesInUse; /* MR10 */ | |
| } | |
| FILE * | |
| #ifdef __USE_PROTOS | |
| NextFile( void ) | |
| #else | |
| NextFile( ) | |
| #endif | |
| { | |
| FILE *f; | |
| for (;;) | |
| { | |
| CurFile++; | |
| if ( CurFile >= NumFiles ) return(NULL); | |
| if ( ci_strequ(FileStr[CurFile],"stdin")) return stdin; | |
| f = fopen(FileStr[CurFile], "r"); | |
| if ( f == NULL ) | |
| { | |
| warnNoFL( eMsg1("file %s doesn't exist; ignored", FileStr[CurFile]) ); | |
| } | |
| else | |
| { | |
| return(f); | |
| } | |
| } | |
| } | |
| /* | |
| * Return a string corresponding to the output file name associated | |
| * with the input file name passed in. | |
| * | |
| * Observe the following rules: | |
| * | |
| * f.e --> f".c" | |
| * f --> f".c" | |
| * f. --> f".c" | |
| * f.e.g --> f.e".c" | |
| * | |
| * Where f,e,g are arbitrarily long sequences of characters in a file | |
| * name. | |
| * | |
| * In other words, if a ".x" appears on the end of a file name, make it | |
| * ".c". If no ".x" appears, append ".c" to the end of the file name. | |
| * | |
| * C++ mode using .cpp not .c. | |
| * | |
| * Use malloc() for new string. | |
| */ | |
| char * | |
| #ifdef __USE_PROTOS | |
| outname( char *fs ) | |
| #else | |
| outname( fs ) | |
| char *fs; | |
| #endif | |
| { | |
| if ( GenCC) { | |
| return outnameX(fs,CPP_FILE_SUFFIX); | |
| } else { | |
| return outnameX(fs,".c"); | |
| }; | |
| } | |
| char * | |
| #ifdef __USE_PROTOS | |
| outnameX( char *fs ,char *suffix) | |
| #else | |
| outnameX( fs , suffix ) | |
| char *fs; | |
| char *suffix; | |
| #endif | |
| { | |
| static char buf[MaxFileName+1]; | |
| char *p; | |
| require(fs!=NULL&&*fs!='\0', "outname: NULL filename"); | |
| p = buf; | |
| strcpy(buf, fs); | |
| while ( *p != '\0' ) {p++;} /* Stop on '\0' */ | |
| while ( *p != '.' && p != buf ) {--p;} /* Find '.' */ | |
| if ( p != buf ) *p = '\0'; /* Found '.' */ | |
| require(strlen(buf) + 2 < (size_t)MaxFileName, "outname: filename too big"); | |
| strcat(buf,suffix); | |
| return( buf ); | |
| } | |
| void | |
| #ifdef __USE_PROTOS | |
| fatalFL( char *err_, char *f, int l ) | |
| #else | |
| fatalFL( err_, f, l ) | |
| char *err_; | |
| char *f; | |
| int l; | |
| #endif | |
| { | |
| fprintf(stderr, ErrHdr, f, l); | |
| fprintf(stderr, " %s\n", err_); | |
| cleanUp(); | |
| exit(PCCTS_EXIT_FAILURE); | |
| } | |
| void | |
| #ifdef __USE_PROTOS | |
| fatal_intern( char *err_, char *f, int l ) | |
| #else | |
| fatal_intern( err_, f, l ) | |
| char *err_; | |
| char *f; | |
| int l; | |
| #endif | |
| { | |
| fprintf(stderr, ErrHdr, f, l); | |
| fprintf(stderr, " #$%%*&@# internal error: %s\n", err_); | |
| fprintf(stderr, ErrHdr, f, l); | |
| fprintf(stderr, " [complain to nearest government official\n"); | |
| fprintf(stderr, ErrHdr, f, l); | |
| fprintf(stderr, " or send hate-mail to parrt@parr-research.com;\n"); | |
| fprintf(stderr, ErrHdr, f, l); | |
| fprintf(stderr, " please pray to the ``bug'' gods that there is a trival fix.]\n"); | |
| cleanUp(); | |
| exit(PCCTS_EXIT_FAILURE); | |
| } | |
| void | |
| #ifdef __USE_PROTOS | |
| cleanUp( void ) | |
| #else | |
| cleanUp( ) | |
| #endif | |
| { | |
| if ( DefFile != NULL) fclose( DefFile ); | |
| } | |
| /* sprintf up to 3 strings */ | |
| char * | |
| #ifdef __USE_PROTOS | |
| eMsg3( char *s, char *a1, char *a2, char *a3 ) | |
| #else | |
| eMsg3( s, a1, a2, a3 ) | |
| char *s; | |
| char *a1; | |
| char *a2; | |
| char *a3; | |
| #endif | |
| { | |
| static char buf[250]; /* DANGEROUS as hell !!!!!! */ | |
| sprintf(buf, s, a1, a2, a3); | |
| return( buf ); | |
| } | |
| /* sprintf a decimal */ | |
| char * | |
| #ifdef __USE_PROTOS | |
| eMsgd( char *s, int d ) | |
| #else | |
| eMsgd( s, d ) | |
| char *s; | |
| int d; | |
| #endif | |
| { | |
| static char buf[250]; /* DANGEROUS as hell !!!!!! */ | |
| sprintf(buf, s, d); | |
| return( buf ); | |
| } | |
| char * | |
| #ifdef __USE_PROTOS | |
| eMsgd2( char *s, int d1,int d2) | |
| #else | |
| eMsgd2( s, d1, d2 ) | |
| char *s; | |
| int d1; | |
| int d2; | |
| #endif | |
| { | |
| static char buf[250]; /* DANGEROUS as hell !!!!!! */ | |
| sprintf(buf, s, d1, d2); | |
| return( buf ); | |
| } | |
| void | |
| #ifdef __USE_PROTOS | |
| s_fprT( FILE *f, set e ) | |
| #else | |
| s_fprT( f, e ) | |
| FILE *f; | |
| set e; | |
| #endif | |
| { | |
| register unsigned *p; | |
| unsigned *q; | |
| if ( set_nil(e) ) return; | |
| if ( (q=p=set_pdq(e)) == NULL ) fatal_internal("Can't alloc space for set_pdq"); | |
| fprintf(f, "{"); | |
| while ( *p != nil ) | |
| { | |
| fprintf(f, " %s", TerminalString(*p)); | |
| p++; | |
| } | |
| fprintf(f, " }"); | |
| free((char *)q); | |
| } | |
| /* Return the token name or regular expression for a token number. */ | |
| char * | |
| #ifdef __USE_PROTOS | |
| TerminalString( int token ) | |
| #else | |
| TerminalString( token ) | |
| int token; | |
| #endif | |
| { | |
| int j; | |
| static char imag_name[20]; | |
| /* look in all lexclasses for the token */ | |
| if ( TokenString(token) != NULL ) return TokenString(token); | |
| for (j=0; j<NumLexClasses; j++) | |
| { | |
| lexmode(j); | |
| if ( ExprString(token) != NULL ) return ExprString(token); | |
| } | |
| if (1) { | |
| sprintf(imag_name,"UnknownToken#%d",token); /* MR13 */ | |
| return imag_name; /* MR13 */ | |
| } | |
| require(j<NumLexClasses, eMsgd("No label or expr for token %d",token)); | |
| return "invalid"; | |
| } | |
| /* S i m p l e I n t S t a c k */ | |
| void | |
| #ifdef __USE_PROTOS | |
| pushint( int i ) | |
| #else | |
| pushint( i ) | |
| int i; | |
| #endif | |
| { | |
| require(isp>0, "pushint: stack overflow"); | |
| istack[--isp] = i; | |
| } | |
| int | |
| #ifdef __USE_PROTOS | |
| popint( void ) | |
| #else | |
| popint( ) | |
| #endif | |
| { | |
| require(isp<MAX_INT_STACK, "popint: stack underflow"); | |
| return istack[isp++]; | |
| } | |
| int | |
| #ifdef __USE_PROTOS | |
| istacksize( void ) | |
| #else | |
| istacksize( ) | |
| #endif | |
| { | |
| return MAX_INT_STACK-isp; | |
| } | |
| void | |
| #ifdef __USE_PROTOS | |
| istackreset( void ) | |
| #else | |
| istackreset( ) | |
| #endif | |
| { | |
| isp = MAX_INT_STACK; | |
| } | |
| int | |
| #ifdef __USE_PROTOS | |
| istackempty( void ) | |
| #else | |
| istackempty( ) | |
| #endif | |
| { | |
| return isp==MAX_INT_STACK; | |
| } | |
| int | |
| #ifdef __USE_PROTOS | |
| topint( void ) | |
| #else | |
| topint( ) | |
| #endif | |
| { | |
| require(isp<MAX_INT_STACK, "topint: stack underflow"); | |
| return istack[isp]; | |
| } | |
| void | |
| #ifdef __USE_PROTOS | |
| ProcessArgs( int argc, char **argv, Opt *options ) | |
| #else | |
| ProcessArgs( argc, argv, options ) | |
| int argc; | |
| char **argv; | |
| Opt *options; | |
| #endif | |
| { | |
| Opt *p; | |
| require(argv!=NULL, "ProcessArgs: command line NULL"); | |
| while ( argc-- > 0 ) | |
| { | |
| p = options; | |
| while ( p->option != NULL ) | |
| { | |
| if ( strcmp(p->option, "*") == 0 || | |
| ci_strequ(p->option, *argv) == 1 ) | |
| { | |
| if ( p->arg ) | |
| { | |
| /* MR9 26-Sep-97 Check for argv valid */ | |
| if (argc-- > 0) { | |
| (*p->process)( *argv, *(argv+1) ); | |
| argv++; | |
| } else { | |
| fprintf(stderr,"error: required argument for option %s omitted\n",*argv); | |
| exit(PCCTS_EXIT_FAILURE); | |
| }; | |
| } | |
| else | |
| (*p->process)( *argv ); | |
| break; | |
| } | |
| p++; | |
| } | |
| argv++; | |
| } | |
| } | |
| static void | |
| #ifdef __USE_PROTOS | |
| CompleteContextGuards(void) | |
| #else | |
| CompleteContextGuards() | |
| #endif | |
| { | |
| ListNode * p; | |
| Predicate * pred; | |
| if (ContextGuardPredicateList == NULL) return; | |
| for (p=ContextGuardPredicateList->next; p != NULL; p=p->next) { | |
| pred=(Predicate *)p->elem; | |
| recomputeContextGuard(pred); | |
| } | |
| } | |
| /* Go back into the syntax diagram and compute all meta tokens; i.e. | |
| * turn all '.', ranges, token class refs etc... into actual token sets | |
| */ | |
| static void | |
| #ifdef __USE_PROTOS | |
| CompleteTokenSetRefs(void) | |
| #else | |
| CompleteTokenSetRefs() | |
| #endif | |
| { | |
| ListNode *p; | |
| if ( MetaTokenNodes==NULL ) return; | |
| for (p = MetaTokenNodes->next; p!=NULL; p=p->next) | |
| { | |
| set a,b; | |
| TokNode *q = (TokNode *)p->elem; | |
| if ( q->wild_card ) | |
| { | |
| q->tset = all_tokens; | |
| } | |
| else if ( q->tclass!=NULL ) | |
| { | |
| if ( q->complement ) q->tset = set_dif(all_tokens, q->tclass->tset); | |
| else q->tset = q->tclass->tset; | |
| } | |
| else if ( q->upper_range!=0 ) | |
| { | |
| /* we have a range on our hands: make a set from q->token .. q->upper_range */ | |
| int i; | |
| a = empty; | |
| for (i=q->token; i<=q->upper_range; i++) { set_orel(i, &a); } /* MR13 */ | |
| /* MR13 */ if (q->complement) { | |
| /* MR13 */ q->tset = set_dif(all_tokens, a); | |
| /* MR13 */ set_free(a); | |
| /* MR13 */ } else { | |
| /* MR13 */ q->tset = a; | |
| /* MR13 */ } | |
| } | |
| /* at this point, it can only be a complemented single token */ | |
| else if ( q->complement ) | |
| { | |
| a = set_of(q->token); | |
| b = set_dif(all_tokens, a); | |
| set_free(a); | |
| q->tset=b; | |
| } | |
| else fatal("invalid meta token"); | |
| } | |
| } | |
| /* MR10: Jeff Vincent | |
| MR10: Changed to remove directory information from n only if | |
| MR10: if OutputDirectory was changed by user (-o option) | |
| */ | |
| char * | |
| #ifdef __USE_PROTOS | |
| OutMetaName(char *n) | |
| #else | |
| OutMetaName(n) | |
| char *n; | |
| #endif | |
| { | |
| static char *dir_sym = DirectorySymbol; | |
| static char newname[MaxFileName+1]; | |
| char *p; | |
| /* If OutputDirectory is same as TopDirectory (platform default) then leave n alone. */ | |
| if (strcmp(OutputDirectory, TopDirectory) == 0) /* TopDirectory is "." on Unix. */ | |
| return n; | |
| /* p will point to filename without path information */ | |
| if ((p = strrchr(n, *dir_sym)) != NULL) /* Directory symbol is "/" on Unix. */ | |
| p++; | |
| else | |
| p = n; | |
| /* Copy new output directory into newname[] */ | |
| strcpy(newname, OutputDirectory); | |
| /* if new output directory does not have trailing dir_sym, add it! */ | |
| if (newname[strlen(newname)-1] != *dir_sym) { | |
| strcat(newname, dir_sym); | |
| } | |
| strcat(newname, p); | |
| return newname; | |
| } | |
| char * | |
| #ifdef __USE_PROTOS | |
| pcctsBaseName(char *n) /* MR32 */ | |
| #else | |
| pcctsBaseName(n) | |
| char *n; | |
| #endif | |
| { | |
| static char newname[MaxFileName+1]; | |
| static char* dir_sym = DirectorySymbol; | |
| int count = 0; | |
| char *p; | |
| p = n; | |
| while ( *p != '\0' ) {p++;} /* go to end of string */ | |
| while ( (*p != *dir_sym) && (p != n) ) {--p;} /* Find last DirectorySymbol */ | |
| while ( *p == *dir_sym) p++; /* step forward if we're on a dir symbol */ | |
| while ( *p != '\0' && *p != '.') | |
| { | |
| newname[count++] = *p; | |
| p++; | |
| } /* create a new name */ | |
| newname[count] = '\0'; | |
| return newname; | |
| } | |
| static void | |
| #ifdef __USE_PROTOS | |
| ensure_no_C_file_collisions(char *class_c_file) | |
| #else | |
| ensure_no_C_file_collisions(class_c_file) | |
| char *class_c_file; | |
| #endif | |
| { | |
| int i; | |
| for (i=0; i<NumFiles; i++) | |
| { | |
| #ifdef PCCTS_CASE_INSENSITIVE_FILE_NAME | |
| /* assume that file names are case insensitive */ | |
| if ( STRICMP(outname(FileStr[i]), class_c_file)==0 ) | |
| #else | |
| if ( strcmp(outname(FileStr[i]), class_c_file)==0 ) | |
| #endif | |
| { | |
| fatal(eMsg1("class def output file conflicts with parser output file: %s", | |
| outname(FileStr[i]))); | |
| } | |
| } | |
| } | |
| void | |
| #ifdef __USE_PROTOS | |
| warnNoFL(char *err) | |
| #else | |
| warnNoFL(err) | |
| char *err; | |
| #endif | |
| { | |
| fprintf(stderr, "warning: %s\n", err); | |
| } | |
| void | |
| #ifdef __USE_PROTOS | |
| warnFL(char *err,char *f,int l) | |
| #else | |
| warnFL(err,f,l) | |
| char *f; | |
| int l; | |
| char *err; | |
| #endif | |
| { | |
| fprintf(stderr, ErrHdr, f, l); | |
| fprintf(stderr, " warning: %s\n", err); | |
| } | |
| void | |
| #ifdef __USE_PROTOS | |
| warn(char *err) | |
| #else | |
| warn(err) | |
| char *err; | |
| #endif | |
| { | |
| /* back up the file number if we hit an error at the end of the last file */ | |
| if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--; | |
| fprintf(stderr, ErrHdr, FileStr[CurFile], zzline); | |
| fprintf(stderr, " warning: %s\n", err); | |
| } | |
| void | |
| #ifdef __USE_PROTOS | |
| warnNoCR( char *err ) | |
| #else | |
| warnNoCR( err ) | |
| char *err; | |
| #endif | |
| { | |
| /* back up the file number if we hit an error at the end of the last file */ | |
| if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--; | |
| fprintf(stderr, ErrHdr, FileStr[CurFile], zzline); | |
| fprintf(stderr, " warning: %s", err); | |
| } | |
| void | |
| #ifdef __USE_PROTOS | |
| errNoFL(char *err) | |
| #else | |
| errNoFL(err) | |
| char *err; | |
| #endif | |
| { | |
| fprintf(stderr, "error: %s\n", err); | |
| } | |
| void | |
| #ifdef __USE_PROTOS | |
| errFL(char *err,char *f,int l) | |
| #else | |
| errFL(err,f,l) | |
| char *err; | |
| char *f; | |
| int l; | |
| #endif | |
| { | |
| fprintf(stderr, ErrHdr, f, l); | |
| fprintf(stderr, " error: %s\n", err); | |
| } | |
| void | |
| #ifdef __USE_PROTOS | |
| err(char *err) | |
| #else | |
| err(err) | |
| char *err; | |
| #endif | |
| { | |
| /* back up the file number if we hit an error at the end of the last file */ | |
| if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--; | |
| fprintf(stderr, ErrHdr, FileStr[CurFile], zzline); | |
| fprintf(stderr, " error: %s\n", err); | |
| } | |
| void | |
| #ifdef __USE_PROTOS | |
| errNoCR( char *err ) | |
| #else | |
| errNoCR( err ) | |
| char *err; | |
| #endif | |
| { | |
| /* back up the file number if we hit an error at the end of the last file */ | |
| if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--; | |
| fprintf(stderr, ErrHdr, FileStr[CurFile], zzline); | |
| fprintf(stderr, " error: %s", err); | |
| } | |
| UserAction * | |
| #ifdef __USE_PROTOS | |
| newUserAction(char *s) | |
| #else | |
| newUserAction(s) | |
| char *s; | |
| #endif | |
| { | |
| UserAction *ua = (UserAction *) calloc(1, sizeof(UserAction)); | |
| require(ua!=NULL, "cannot allocate UserAction"); | |
| ua->action = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); | |
| strcpy(ua->action, s); | |
| return ua; | |
| } | |
| /* Added by TJP September 1994 */ | |
| /* Take in file.h and return file_h; names w/o '.'s are left alone */ | |
| char * | |
| #ifdef __USE_PROTOS | |
| gate_symbol(char *name) | |
| #else | |
| gate_symbol(name) | |
| char *name; | |
| #endif | |
| { | |
| static char buf[100]; | |
| char *p; | |
| sprintf(buf, "%s", name); | |
| for (p=buf; *p!='\0'; p++) | |
| { | |
| if ( *p=='.' ) *p = '_'; | |
| } | |
| return buf; | |
| } | |
| char * | |
| #ifdef __USE_PROTOS | |
| makeAltID(int blockid, int altnum) | |
| #else | |
| makeAltID(blockid, altnum) | |
| int blockid; | |
| int altnum; | |
| #endif | |
| { | |
| static char buf[100]; | |
| char *p; | |
| sprintf(buf, "_blk%d_alt%d", blockid, altnum); | |
| p = (char *)malloc(strlen(buf)+1); | |
| strcpy(p, buf); | |
| return p; | |
| } |