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