home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
pccts.zip
/
pccts
/
antlr
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-03-31
|
28KB
|
1,105 lines
/*
* main.c -- main program for PCCTS ANTLR.
*
* $Id: main.c,v 1.6 1994/03/25 19:40:05 parrt Exp parrt $
* $Revision: 1.6 $
*
* SOFTWARE RIGHTS
*
* We reserve no LEGAL rights to the Purdue Compiler Construction Tool
* Set (PCCTS) -- PCCTS is in the public domain. An individual or
* company may do whatever they wish with source code distributed with
* PCCTS or the code generated by PCCTS, including the incorporation of
* PCCTS, or its output, into commerical software.
*
* We encourage users to develop software with PCCTS. However, we do ask
* that credit is given to us for developing PCCTS. By "credit",
* we mean that if you incorporate our source code into one of your
* programs (commercial product, research project, or otherwise) that you
* acknowledge this fact somewhere in the documentation, research report,
* etc... If you like PCCTS and have developed a nice tool with the
* output, please mention that you developed it using PCCTS. In
* addition, we ask that this header remain intact in our source code.
* As long as these guidelines are kept, we expect to continue enhancing
* this system and expect to make other tools available as they are
* completed.
*
* ANTLR 1.20
* Terence Parr
* Purdue University
* With AHPCRC, University of Minnesota
* 1989-1994
*/
#include <stdio.h>
#ifdef __cplusplus
#ifndef __STDC__
#define __STDC__
#endif
#endif
#include "stdpccts.h"
#ifdef VAXC
#define DIE return 0;
#else
#define DIE return 1;
#endif
#define MAX_INT_STACK 50
static int istack[MAX_INT_STACK]; /* Int stack */
static int isp = MAX_INT_STACK;
static int DontAcceptFiles = 0; /* if stdin, don't read files */
static int DontAcceptStdin = 0; /* if files seen first, don't accept stdin */
/* C m d - L i n e O p t i o n S t r u c t & F u n c s */
typedef struct _Opt {
char *option;
int arg;
#ifdef __cplusplus
void (*process)(...);
#else
void (*process)();
#endif
char *descr;
} Opt;
#ifdef __STDC__
extern void ProcessArgs(int, char **, Opt *);
#else
extern void ProcessArgs();
#endif
static void
#ifdef __STDC__
pStdin( void )
#else
pStdin( )
#endif
{
if ( DontAcceptStdin )
{
warnNoFL("'-' (stdin) ignored as files were specified first");
return;
}
require(NumFiles<MaxNumFiles,"exceeded max # of input files");
FileStr[NumFiles++] = "stdin";
DontAcceptFiles = 1;
}
static void
#ifdef __STDC__
pFile( char *s )
#else
pFile( s )
char *s;
#endif
{
if ( *s=='-' ) { warnNoFL( eMsg1("invalid option: '%s'",s) ); return; }
if ( DontAcceptFiles )
{
warnNoFL(eMsg1("file '%s' ignored as '-' (stdin option) was specified first",s));
return;
}
require(NumFiles<MaxNumFiles,"exceeded max # of input files");
FileStr[NumFiles++] = s;
DontAcceptStdin = 1;
}
static void
#ifdef __STDC__
pLLK( char *s, char *t )
#else
pLLK( s, t )
char *s;
char *t;
#endif
{
LL_k = atoi(t);
if ( LL_k <= 0 ) {
warnNoFL("must have at least one token of lookahead (setting to 1)");
LL_k = 1;
}
}
static void
#ifdef __STDC__
pCk( char *s, char *t )
#else
pCk( s, t )
char *s;
char *t;
#endif
{
CLL_k = atoi(t);
if ( CLL_k <= 0 ) {
warnNoFL("must have at least one token of look-ahead (setting to 1)");
CLL_k = 1;
}
}
#ifdef __STDC__
static void pCGen(void) { CodeGen = FALSE; LexGen = FALSE; }
static void pLGen(void) { LexGen = FALSE; }
static void pTGen(void) { TraceGen = TRUE; }
static void pSGen(void) { GenExprSets = FALSE; }
static void pPrt(void) { PrintOut = TRUE; pCGen(); pLGen(); }
static void pPrtA(void) { PrintOut = TRUE; PrintAnnotate = TRUE; pCGen(); pLGen(); }
static void pAst(void) { GenAST = TRUE; }
static void pANSI(void) { GenANSI = TRUE; }
static void pCr(void) { GenCR = TRUE; }
static void pCt(void) { DontCopyTokens = TRUE; }
static void pLI(void) { GenLineInfo = TRUE; }
static void pFr(char *s, char *t) {RemapFileName = t;}
static void pFe(char *s, char *t) {ErrFileName = t;}
static void pFl(char *s, char *t) {DlgFileName = t;}
static void pFm(char *s, char *t) {ModeFileName = t;}
static void pFt(char *s, char *t) {DefFileName = t;}
static void pE1(void) { elevel = 1; }
static void pE2(void) { elevel = 2; }
static void pE3(void) { elevel = 3; }
static void pEGen(void) { GenEClasseForRules = 1; }
static void pDL(void) { DemandLookahead = 1; }
static void pGHdr(void) { GenStdPccts = 1; }
static void pFHdr(char *s, char *t) { stdpccts = t; pGHdr(); }
static void pW1(void) { WarningLevel = 1; }
static void pW2(void) { WarningLevel = 2; }
static void pCC(void) { GenCC = TRUE; }
#else
static void pCGen() { CodeGen = FALSE; LexGen = FALSE; }
static void pLGen() { LexGen = FALSE; }
static void pTGen() { TraceGen = TRUE; }
static void pSGen() { GenExprSets = FALSE; }
static void pPrt() { PrintOut = TRUE; pCGen(); pLGen(); }
static void pPrtA() { PrintOut = TRUE; PrintAnnotate = TRUE; pCGen(); pLGen(); }
static void pAst() { GenAST = TRUE; }
static void pANSI() { GenANSI = TRUE; }
static void pCr() { GenCR = TRUE; }
static void pCt() { DontCopyTokens = TRUE; }
static void pLI() { GenLineInfo = TRUE; }
static void pFr(s,t) char *s, *t; {RemapFileName = t;}
static void pFe(s,t) char *s, *t; {ErrFileName = t;}
static void pFl(s,t) char *s, *t; {DlgFileName = t;}
static void pFm(s,t) char *s, *t; {ModeFileName = t;}
static void pFt(s,t) char *s, *t; {DefFileName = t;}
static void pE1() { elevel = 1; }
static void pE2() { elevel = 2; }
static void pE3() { elevel = 3; }
static void pEGen() { GenEClasseForRules = 1; }
static void pDL() { DemandLookahead = 1; }
static void pGHdr() { GenStdPccts = 1; }
static void pFHdr(s,t) char *s, *t; { stdpccts = t; pGHdr(); }
static void pW1() { WarningLevel = 1; }
static void pW2() { WarningLevel = 2; }
static void pCC() { GenCC = TRUE; }
#endif
static void
#ifdef __STDC__
pPre( char *s, char *t )
#else
pPre( s, t )
char *s;
char *t;
#endif
{
RulePrefix = t;
}
static void
#ifdef __STDC__
pOut( char *s, char *t )
#else
pOut( s, t )
char *s;
char *t;
#endif
{
OutputDirectory = t;
}
static void
#ifdef __STDC__
pPred( void )
#else
pPred( )
#endif
{
warnNoFL("-pr is no longer used (predicates employed if present); see -prc");
/*
if ( DemandLookahead )
warnNoFL("-gk conflicts with -pr; -gk turned off");
DemandLookahead = 0;
HoistPredicateContext = 0;
*/
}
static void
#ifdef __STDC__
pPredCtx( char *s, char *t )
#else
pPredCtx(s,t)
char *s;
char *t;
#endif
{
if ( strcmp(t, "on")==0 ) HoistPredicateContext = 1;
else if ( strcmp(t, "ON")==0 ) HoistPredicateContext = 1;
else if ( strcmp(t, "off")==0 ) HoistPredicateContext = 0;
else if ( strcmp(t, "OFF")==0 ) HoistPredicateContext = 0;
if ( DemandLookahead )
{
warnNoFL("-gk incompatible with semantic predicate usage; -gk turned off");
DemandLookahead = 0;
}
}
static void
#ifdef __STDC__
pTRes( char *s, char *t )
#else
pTRes( s, t )
char *s;
char *t;
#endif
{
TreeResourceLimit = atoi(t);
if ( TreeResourceLimit <= 0 )
{
warnNoFL("analysis resource limit (# of tree nodes) must be greater than 0");
TreeResourceLimit = -1; /* set to no limit */
}
}
Opt options[] = {
#ifdef __cplusplus
{ "-CC", 0, (void (*)(...)) pCC, "Generate C++ output (default=FALSE)"},
{ "-ck", 1, (void (*)(...)) pCk, "Set compressed lookahead depth; fast approximate lookahead"},
{ "-cr", 0, (void (*)(...)) pCr, "Generate cross reference (default=FALSE)"},
{ "-ct", 0, (void (*)(...)) pCt, "Do not copy tokens in C++ mode (default=to copy)"},
{ "-e1", 0, (void (*)(...)) pE1, "Ambiguities/errors shown in low detail (default)"},
{ "-e2", 0, (void (*)(...)) pE2, "Ambiguities/errors shown in more detail"},
{ "-e3", 0, (void (*)(...)) pE3, "Ambiguities/errors shown in excruciating detail"},
{ "-fe", 1, (void (*)(...)) pFe, "Rename err.c"},
{ "-fh", 1, (void (*)(...)) pFHdr, "Rename stdpccts.h header (turns on -gh)"},
{ "-fl", 1, (void (*)(...)) pFl, "Rename lexical output--parser.dlg"},
{ "-fm", 1, (void (*)(...)) pFm, "Rename mode.h"},
{ "-fr", 1, (void (*)(...)) pFr, "Rename remap.h"},
{ "-ft", 1, (void (*)(...)) pFt, "Rename tokens.h"},
{ "-ga", 0, (void (*)(...)) pANSI, "Generate ANSI-compatible code (default=FALSE)"},
{ "-gc", 0, (void (*)(...)) pCGen, "Do not generate output parser code (default=FALSE)"},
{ "-gd", 0, (void (*)(...)) pTGen, "Generate code to trace rule invocation (default=FALSE)"},
{ "-ge", 0, (void (*)(...)) pEGen, "Generate an error class for each non-terminal (default=FALSE)"},
{ "-gh", 0, (void (*)(...)) pGHdr, "Generate stdpccts.h for non-ANTLR-generated-files to include"},
{ "-gk", 0, (void (*)(...)) pDL, "Generate parsers that delay lookahead fetches 'til needed"},
{ "-gl", 0, (void (*)(...)) pLI, "Generate line info about grammar actions in C parser"},
{ "-gp", 1, (void (*)(...)) pPre, "Prefix all generated rule functions with a string"},
{ "-gs", 0, (void (*)(...)) pSGen, "Do not generate sets for token expression lists (default=FALSE)"},
{ "-gt", 0, (void (*)(...)) pAst, "Generate code for Abstract-Syntax-Trees (default=FALSE)"},
{ "-gx", 0, (void (*)(...)) pLGen, "Do not generate lexical (dlg-related) files (default=FALSE)"},
{ "-k", 1, (void (*)(...)) pLLK, "Set full LL(k) lookahead depth (default==1)"},
{ "-o", 1, (void (*)(...)) pOut, "Directory where all output files should go (default=\".\")"},
{ "-p", 0, (void (*)(...)) pPrt, "Print out the grammar w/o actions (default=no)"},
{ "-pa", 0, (void (*)(...)) pPrtA, "Print out the grammar w/o actions & w/FIRST sets (default=no)"},
{ "-pr",0, (void (*)(...)) pPred, "no longer used; predicates employed if present"},
{ "-prc", 1, (void (*)(...)) pPredCtx,"Turn on/off computation of context for hoisted predicates"},
{ "-rl", 1, (void (*)(...)) pTRes, "Limit max # of tree nodes used by grammar analysis"},
{ "-w1", 0, (void (*)(...)) pW1, "Set the warning level to 1 (default)"},
{ "-w2", 0, (void (*)(...)) pW2, "Ambiguities yield warnings even if predicates or (...)? block"},
{ "-", 0, (void (*)(...)) pStdin, "Read grammar from stdin" },
{ "*", 0, (void (*)(...)) pFile, "" }, /* anything else is a file */
#else
{ "-CC", 0, pCC, "Generate C++ output (default=FALSE)"},
{ "-cr", 0, pCr, "Generate cross reference (default=FALSE)"},
{ "-ct", 0, pCt, "Do not copy tokens in C++ mode (default=to copy)"},
{ "-ck", 1, pCk, "Set compressed lookahead depth; fast approximate lookahead"},
{ "-e1", 0, pE1, "Ambiguities/errors shown in low detail (default)"},
{ "-e2", 0, pE2, "Ambiguities/errors shown in more detail"},
{ "-e3", 0, pE3, "Ambiguities/errors shown in excrutiating detail"},
{ "-fe", 1, pFe, "Rename err.c"},
{ "-fh", 1, pFHdr, "Rename stdpccts.h header (turns on -gh)"},
{ "-fl", 1, pFl, "Rename lexical output--parser.dlg"},
{ "-fm", 1, pFm, "Rename mode.h"},
{ "-fr", 1, pFr, "Rename remap.h"},
{ "-ft", 1, pFt, "Rename tokens.h"},
{ "-ga", 0, pANSI, "Generate ANSI-compatible code (default=FALSE)"},
{ "-gc", 0, pCGen, "Do not generate output parser code (default=FALSE)"},
{ "-gd", 0, pTGen, "Generate code to trace rule invocation (default=FALSE)"},
{ "-ge", 0, pEGen, "Generate an error class for each non-terminal (default=FALSE)"},
{ "-gh", 0, pGHdr, "Generate stdpccts.h for non-ANTLR-generated-files to include"},
{ "-gk", 0, pDL, "Generate parsers that delay lookahead fetches 'til needed"},
{ "-gl", 0, pLI, "Generate line info about grammar actions in C parser"},
{ "-gp", 1, pPre, "Prefix all generated rule functions with a string"},
{ "-gs", 0, pSGen, "Do not generate sets for token expression lists (default=FALSE)"},
{ "-gt", 0, pAst, "Generate code for Abstract-Syntax-Trees (default=FALSE)"},
{ "-gx", 0, pLGen, "Do not generate lexical (dlg-related) files (default=FALSE)"},
{ "-k", 1, pLLK, "Set full LL(k) lookahead depth (default==1)"},
{ "-o", 1, pOut, "Directory where all output files should go (default=\".\")"},
{ "-p", 0, pPrt, "Print out the grammar w/o actions (default=no)"},
{ "-pa", 0, pPrtA, "Print out the grammar w/o actions & w/FIRST sets (default=no)"},
{ "-pr",0, pPred, "no longer used; predicates employed if present"},
{ "-prc", 1, pPredCtx,"Turn on/off computation of context for hoisted predicates"},
{ "-rl", 1, pTRes, "Limit max # of tree nodes used by grammar analysis"},
{ "-w1", 0, pW1, "Set the warning level to 1 (default)"},
{ "-w2", 0, pW2, "Ambiguities yield warnings even if predicates or (...)? block"},
{ "-", 0, pStdin, "Read grammar from stdin" },
{ "*", 0, pFile, "" }, /* anything else is a file */
#endif
{ NULL, 0, NULL }
};
void readDescr();
void cleanUp();
#ifdef __STDC__
static void buildRulePtr( void );
static void help( void );
static void init( void );
static void CompleteTokenSetRefs( void );
static void ensure_no_C_file_collisions(char *);
#else
static void buildRulePtr( );
static void help( );
static void init( );
static void CompleteTokenSetRefs( );
static void ensure_no_C_file_collisions();
#endif
/* M a i n */
int
#ifdef __STDC__
main( int argc, char *argv[] )
#else
main( argc, argv )
int argc;
char *argv[];
#endif
{
int i;
static char EPSTR[] = "[Ep]";
fprintf(stderr, "Antlr parser generator Version %s 1989-1994\n", Version);
if ( argc == 1 ) { help(); DIE; }
ProcessArgs(argc-1, &(argv[1]), options);
/* Fix lookahead depth */
/* Compressed lookahead must always be larger than or equal to full lookahead */
if ( CLL_k < LL_k && CLL_k>0 )
{
warnNoFL("must have compressed lookahead >= full LL(k) lookahead (setting -ck to -k)");
CLL_k = LL_k;
}
if ( CLL_k == -1 ) CLL_k = LL_k;
OutputLL_k = CLL_k;
if ( ((CLL_k-1)&CLL_k)!=0 ) { /* output ll(k) must be power of 2 */
int n;
for(n=1; n<CLL_k; n<<=1) {;}
OutputLL_k = n;
}
fpTrans = &(C_Trans[0]); /* Translate to C Language */
fpJTrans = &(C_JTrans[0]);
init();
lexclass(LexStartSymbol);
readDescr();
LastTokenCounted = TokenNum;
RemapForcedTokens();
if ( CannotContinue ) {cleanUp(); DIE;}
if ( GenCC && no_classes_found ) fatal("required grammar class not found (exiting...)");
if ( WarningLevel>1 && HdrAction == NULL )
warnNoFL("no #header action was found");
EpToken = addTname(EPSTR); /* add imaginary token epsilon */
set_orel(EpToken, &imag_tokens);
/* this won't work for hand-built scanners since EofToken is not
* known. Forces EOF to be token type 1.
*/
set_orel(EofToken, &imag_tokens);
set_size(NumWords(TokenNum-1));
/* compute the set of all known token types
* It represents the set of tokens from 1 to last_token_num + the
* reserved positions above that (if any). Don't include the set of
* imaginary tokens such as the token/error classes or EOF.
*/
{
set a;
a = set_dup(reserved_positions);
for (i=1; i<TokenNum; i++) { set_orel(i, &a); }
all_tokens = set_dif(a, imag_tokens);
set_free(a);
}
ComputeTokSets();
CompleteTokenSetRefs();
if ( CodeGen ) genDefFile(); /* create tokens.h */
if ( LexGen ) genLexDescr(); /* create parser.dlg */
if ( GenStdPccts )
{
FILE *f = fopen(OutMetaName(stdpccts), "w");
if ( f==NULL ) {warnNoFL( eMsg1("can't create %s",OutMetaName(stdpccts)) );}
else
{
genStdPCCTSIncludeFile(f);
fclose(f);
}
}
buildRulePtr(); /* create mapping from rule # to RuleBlk junction */
ComputeErrorSets();
FoLink( (Node *)SynDiag ); /* add follow links to end of all rules */
if ( GenCR ) GenCrossRef( SynDiag );
if ( CodeGen )
{
if ( SynDiag == NULL )
{
warnNoFL("no grammar description recognized");
cleanUp();
DIE;
}
else if ( !GenCC ) {
ErrFile = fopen(OutMetaName(ErrFileName), "w");
require(ErrFile != NULL, "main: can't open err file");
NewSetWd();
GenErrHdr();
TRANS(SynDiag); /* Translate to the target language */
DumpSetWd();
fclose( ErrFile );
}
else {
strcpy(Parser_h_Name, CurrentClassName);
strcat(Parser_h_Name, ".h");
strcpy(Parser_c_Name, CurrentClassName);
strcat(Parser_c_Name, ".C");
ensure_no_C_file_collisions(Parser_c_Name);
Parser_h = fopen(OutMetaName(Parser_h_Name), "w");
require(Parser_h != NULL, "main: can't open class Parserx.h file");
Parser_c = fopen(OutMetaName(Parser_c_Name), "w");
require(Parser_c != NULL, "main: can't open class Parserx.c file");
GenParser_h_Hdr();
GenParser_c_Hdr();
NewSetWd();
TRANS(SynDiag); /* Translate to the target language */
DumpSetWd();
GenRuleMemberDeclarationsForCC(Parser_h, SynDiag);
/* Dump class members */
if ( class_actions != NULL )
{
ListNode *p;
for (p = class_actions->next; p!=NULL; p=p->next)
dumpAction( (char *)p->elem, Parser_h, 0, -1, 0, 1);
}
fprintf(Parser_h, "};\n");
fclose( Parser_h );
fclose( Parser_c );
}
}
if ( PrintOut )
{
if ( SynDiag == NULL ) {warnNoFL("no grammar description recognized");}
else PRINT(SynDiag);
}
GenRemapFile(); /* create remap.h */
cleanUp();
#ifdef VAXC
return 1; /* report all is well for make etc... */
#else
return 0; /* report all is well for make etc... */
#endif
}
static void
#ifdef __STDC__
init( void )
#else
init( )
#endif
{
Tname = newHashTable();
Rname = newHashTable();
Fcache = newHashTable();
Tcache = newHashTable();
reserved_positions = empty;
all_tokens = empty;
imag_tokens = empty;
TokenStr = (char **) calloc(TSChunk, sizeof(char *));
require(TokenStr!=NULL, "main: cannot allocate TokenStr");
FoStack = (int **) calloc(CLL_k+1, sizeof(int *));
require(FoStack!=NULL, "main: cannot allocate FoStack");
FoTOS = (int **) calloc(CLL_k+1, sizeof(int *));
require(FoTOS!=NULL, "main: cannot allocate FoTOS");
Cycles = (ListNode **) calloc(CLL_k+1, sizeof(ListNode *));
require(Cycles!=NULL, "main: cannot allocate Cycles List");
}
static void
#ifdef __STDC__
help( void )
#else
help( )
#endif
{
Opt *p = options;
fprintf(stderr, "antlr [options] f1 f2 ... fn\n");
while ( *(p->option) != '*' )
{
fprintf(stderr, "\t%-4s %s %s\n",
p->option,
(p->arg)?"___":" ",
p->descr);
p++;
}
}
/* The RulePtr array is filled in here. RulePtr exists primarily
* so that sets of rules can be maintained for the FOLLOW caching
* mechanism found in rJunc(). RulePtr maps a rule num from 1 to n
* to a pointer to its RuleBlk junction where n is the number of rules.
*/
static void
#ifdef __STDC__
buildRulePtr( void )
#else
buildRulePtr( )
#endif
{
int r=1;
Junction *p = SynDiag;
RulePtr = (Junction **) calloc(NumRules+1, sizeof(Junction *));
require(RulePtr!=NULL, "cannot allocate RulePtr array");
while ( p!=NULL )
{
require(r<=NumRules, "too many rules???");
RulePtr[r++] = p;
p = (Junction *)p->p2;
}
}
void
#ifdef __STDC__
dlgerror(char *s)
#else
dlgerror(s)
char *s;
#endif
{
fprintf(stderr, ErrHdr, FileStr[CurFile], zzline);
fprintf(stderr, " lexical error: %s (text was '%s')\n",
((s == NULL) ? "Lexical error" : s), zzlextext);
}
void
#ifdef __STDC__
readDescr( void )
#else
readDescr( )
#endif
{
zzerr = dlgerror;
input = NextFile();
if ( input==NULL ) fatal("No grammar description found (exiting...)");
ANTLR(grammar(), input);
}
FILE *
#ifdef __STDC__
NextFile( void )
#else
NextFile( )
#endif
{
FILE *f;
for (;;)
{
CurFile++;
if ( CurFile >= NumFiles ) return(NULL);
if ( strcmp(FileStr[CurFile],"stdin") == 0 ) return stdin;
f = fopen(FileStr[CurFile], "r");
if ( f == NULL )
{
warnNoFL( eMsg1("file %s doesn't exist; ignored", FileStr[CurFile]) );
}
else
{
return(f);
}
}
}
/*
* Return a string corresponding to the output file name associated
* with the input file name passed in.
*
* Observe the following rules:
*
* f.e --> f".c"
* f --> f".c"
* f. --> f".c"
* f.e.g --> f.e".c"
*
* Where f,e,g are arbitrarily long sequences of characters in a file
* name.
*
* In other words, if a ".x" appears on the end of a file name, make it
* ".c". If no ".x" appears, append ".c" to the end of the file name.
*
* C++ mode using .C not .c.
*
* Use malloc() for new string.
*/
char *
#ifdef __STDC__
outname( char *fs )
#else
outname( fs )
char *fs;
#endif
{
static char buf[MaxFileName+1];
char *p;
require(fs!=NULL&&*fs!='\0', "outname: NULL filename");
p = buf;
strcpy(buf, fs);
while ( *p != '\0' ) {p++;} /* Stop on '\0' */
while ( *p != '.' && p != buf ) {--p;} /* Find '.' */
if ( p != buf ) *p = '\0'; /* Found '.' */
require(strlen(buf) + 2 < MaxFileName, "outname: filename too big");
if ( GenCC ) strcat(buf, ".C");
else strcat(buf, ".c");
return( buf );
}
void
#ifdef __STDC__
fatalFL( char *err_, char *f, int l )
#else
fatalFL( err_, f, l )
char *err_;
char *f;
int l;
#endif
{
fprintf(stderr, ErrHdr, f, l);
fprintf(stderr, " %s\n", err_);
cleanUp();
exit(1);
}
void
#ifdef __STDC__
fatal_internal( char *err_, char *f, int l )
#else
fatal_internal( err_, f, l )
char *err_;
char *f;
int l;
#endif
{
fprintf(stderr, ErrHdr, f, l);
fprintf(stderr, " #$%%*&@# internal error: %s\n", err_);
fprintf(stderr, ErrHdr, f, l);
fprintf(stderr, " [complain to nearest government official\n");
fprintf(stderr, ErrHdr, f, l);
fprintf(stderr, " or send hate-mail to parrt@acm.org;\n");
fprintf(stderr, ErrHdr, f, l);
fprintf(stderr, " please pray to the ``bug'' gods that there is a trival fix.]\n");
cleanUp();
exit(1);
}
void
#ifdef __STDC__
cleanUp( void )
#else
cleanUp( )
#endif
{
if ( DefFile != NULL) fclose( DefFile );
}
/* sprintf up to 3 strings */
char *
#ifdef __STDC__
eMsg3( char *s, char *a1, char *a2, char *a3 )
#else
eMsg3( s, a1, a2, a3 )
char *s;
char *a1;
char *a2;
char *a3;
#endif
{
static char buf[250]; /* DANGEROUS as hell !!!!!! */
sprintf(buf, s, a1, a2, a3);
return( buf );
}
/* sprintf a decimal */
char *
#ifdef __STDC__
eMsgd( char *s, int d )
#else
eMsgd( s, d )
char *s;
int d;
#endif
{
static char buf[250]; /* DANGEROUS as hell !!!!!! */
sprintf(buf, s, d);
return( buf );
}
void
#ifdef __STDC__
s_fprT( FILE *f, set e )
#else
s_fprT( f, e )
FILE *f;
set e;
#endif
{
register unsigned *p;
unsigned *q;
if ( set_nil(e) ) return;
if ( (q=p=set_pdq(e)) == NULL ) fatal("Can't alloc space for set_pdq");
fprintf(f, "{");
while ( *p != nil )
{
fprintf(f, " %s", TerminalString(*p));
p++;
}
fprintf(f, " }");
free(q);
}
/* Return the token name or regular expression for a token number. */
char *
#ifdef __STDC__
TerminalString( int token )
#else
TerminalString( token )
int token;
#endif
{
int j;
/* look in all lexclasses for the token */
if ( TokenString(token) != NULL ) return TokenString(token);
for (j=0; j<NumLexClasses; j++)
{
lexmode(j);
if ( ExprString(token) != NULL ) return ExprString(token);
}
require(j<NumLexClasses, eMsgd("No label or expr for token %d",token));
return "invalid";
}
/* S i m p l e I n t S t a c k */
void
#ifdef __STDC__
pushint( int i )
#else
pushint( i )
int i;
#endif
{
require(isp>0, "pushint: stack overflow");
istack[--isp] = i;
}
int
#ifdef __STDC__
popint( void )
#else
popint( )
#endif
{
require(isp<MAX_INT_STACK, "popint: stack underflow");
return istack[isp++];
}
int
#ifdef __STDC__
istacksize( void )
#else
istacksize( )
#endif
{
return MAX_INT_STACK-isp;
}
void
#ifdef __STDC__
istackreset( void )
#else
istackreset( )
#endif
{
isp = MAX_INT_STACK;
}
int
#ifdef __STDC__
istackempty( void )
#else
istackempty( )
#endif
{
return isp==MAX_INT_STACK;
}
int
#ifdef __STDC__
topint( void )
#else
topint( )
#endif
{
require(isp<MAX_INT_STACK, "topint: stack underflow");
return istack[isp];
}
void
#ifdef __STDC__
ProcessArgs( int argc, char **argv, Opt *options )
#else
ProcessArgs( argc, argv, options )
int argc;
char **argv;
Opt *options;
#endif
{
Opt *p;
require(argv!=NULL, "ProcessArgs: command line NULL");
while ( argc-- > 0 )
{
p = options;
while ( p->option != NULL )
{
if ( strcmp(p->option, "*") == 0 ||
strcmp(p->option, *argv) == 0 )
{
if ( p->arg )
{
(*p->process)( *argv, *(argv+1) );
argv++;
argc--;
}
else
(*p->process)( *argv );
break;
}
p++;
}
argv++;
}
}
/* Go back into the syntax diagram and compute all meta tokens; i.e.
* turn all '.', ranges, token class refs etc... into actual token sets
*/
static void
CompleteTokenSetRefs()
{
ListNode *p;
if ( MetaTokenNodes==NULL ) return;
for (p = MetaTokenNodes->next; p!=NULL; p=p->next)
{
set a,b;
TokNode *q = (TokNode *)p->elem;
if ( q->wild_card )
{
q->tset = all_tokens;
}
else if ( q->tclass!=NULL )
{
if ( q->complement ) q->tset = set_dif(all_tokens, q->tclass->tset);
else q->tset = q->tclass->tset;
}
else if ( q->upper_range!=0 )
{
/* we have a range on our hands: make a set from q->token .. q->upper_range */
int i;
a = empty;
for (i=q->token; i<=q->upper_range; i++) { set_orel(i, &a); }
q->tset = a;
}
/* at this point, it can only be a complemented single token */
else if ( q->complement )
{
a = set_of(q->token);
b = set_dif(all_tokens, a);
set_free(a);
q->tset=b;
}
else fatal("invalid meta token");
}
}
char *
#ifdef __STDC__
OutMetaName(char *n)
#else
OutMetaName(n)
char *n;
#endif
{
static char buf[MaxFileName+1];
strcpy(buf, OutputDirectory);
strcat(buf, DirectorySymbol);
strcat(buf, n);
return buf;
}
static void
#ifdef __STDC__
ensure_no_C_file_collisions(char *class_c_file)
#else
ensure_no_C_file_collisions(class_c_file)
char *class_c_file;
#endif
{
int i;
for (i=0; i<NumFiles; i++)
{
if ( strcmp(outname(FileStr[i]), class_c_file)==0 )
{
fatal(eMsg1("class def output file conflicts with parser output file: %s",
outname(FileStr[i])));
}
}
}
void
#ifdef __STDC__
warnNoFL(char *err)
#else
warnNoFL(err)
char *err;
#endif
{
fprintf(stderr, "warning: %s\n", err);
}
void
#ifdef __STDC__
warnFL(char *err,char *f,int l)
#else
warnFL(err,f,l)
char *f;
int l;
char *err;
#endif
{
fprintf(stderr, ErrHdr, f, l);
fprintf(stderr, " warning: %s\n", err);
}
void
#ifdef __STDC__
warn(char *err)
#else
warn(err)
char *err;
#endif
{
/* back up the file number if we hit an error at the end of the last file */
if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--;
fprintf(stderr, ErrHdr, FileStr[CurFile], zzline);
fprintf(stderr, " warning: %s\n", err);
}
void
#ifdef __STDC__
warnNoCR( char *err )
#else
warnNoCR( err )
char *err;
#endif
{
/* back up the file number if we hit an error at the end of the last file */
if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--;
fprintf(stderr, ErrHdr, FileStr[CurFile], zzline);
fprintf(stderr, " warning: %s", err);
}
void
#ifdef __STDC__
errNoFL(char *err)
#else
errNoFL(err)
char *err;
#endif
{
fprintf(stderr, "error: %s\n", err);
}
void
#ifdef __STDC__
errFL(char *err,char *f,int l)
#else
errFL(err,f,l)
char *err;
char *f;
int l;
#endif
{
fprintf(stderr, ErrHdr, f, l);
fprintf(stderr, " error: %s\n", err);
}
void
#ifdef __STDC__
err(char *err)
#else
err(err)
char *err;
#endif
{
/* back up the file number if we hit an error at the end of the last file */
if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--;
fprintf(stderr, ErrHdr, FileStr[CurFile], zzline);
fprintf(stderr, " error: %s\n", err);
}
void
#ifdef __STDC__
errNoCR( char *err )
#else
errNoCR( err )
char *err;
#endif
{
/* back up the file number if we hit an error at the end of the last file */
if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--;
fprintf(stderr, ErrHdr, FileStr[CurFile], zzline);
fprintf(stderr, " error: %s", err);
}