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