main.c
来自「SRI international 发布的OAA框架软件」· C语言 代码 · 共 1,115 行 · 第 1/2 页
C
1,115 行
/*
* main.c
*
* SOFTWARE RIGHTS
*
* We reserve no LEGAL rights to SORCERER -- SORCERER is in the public
* domain. An individual or company may do whatever they wish with
* source code distributed with SORCERER or the code generated by
* SORCERER, including the incorporation of SORCERER, or its output, into
* commerical software.
*
* We encourage users to develop software with SORCERER. However, we do
* ask that credit is given to us for developing SORCERER. 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 SORCERER and have developed a nice tool with the
* output, please mention that you developed it using SORCERER. 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.
*
* SORCERER 1.00B
* Terence Parr
* AHPCRC, University of Minnesota
* 1992-2001
*/
#include "pcctscfg.h"
#include "stdpccts.h"
#include "sym.h"
#include "proto.h"
#include <ctype.h>
#define MAX_INT_STACK 50
static int istack[MAX_INT_STACK]; /* Int stack */
static int isp = MAX_INT_STACK;
static int DontAcceptStdin = 0;
static int DontAcceptFiles = 0;
typedef struct _Opt {
char *option;
int arg;
#ifdef __cplusplus
void (*process)(...);
#else
void (*process)();
#endif
char *descr;
} Opt;
#ifdef __USE_PROTOS
static int cistrequ(char *a,char *b)
#else
static int cistrequ(a,b)
char *a;
char *b;
#endif
{
for ( ;*a != 0 && *b != 0; a++, b++) {
if (toupper(*a) != toupper(*b)) return 0;
}
return (*a == *b);
}
#ifdef __USE_PROTOS
static void ProcessArgs(int, char **, Opt *);
#else
static void ProcessArgs();
#endif
static void
#ifdef __USE_PROTOS
pOut( char *s, char *t )
#else
pOut( s, t )
char *s;
char *t;
#endif
{
OutputDirectory = t;
}
static void
#ifdef __USE_PROTOS
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 __USE_PROTOS
pDToks( char *s, char *t )
#else
pDToks( s, t )
char *s, *t;
#endif
{
if ( !GenCPP )
{
warnNoFL("-def-tokens valid with C++ interface only; ignored");
return;
}
else {
def_tokens = 1;
}
}
static void
#ifdef __USE_PROTOS
pDToksFile( char *s, char *t )
#else
pDToksFile( s, t )
char *s, *t;
#endif
{
if ( GenCPP )
{
warnNoFL("-def-tokens-file not valid with C++ interface; ignored");
return;
}
if ( Inline )
{
warnNoFL("-def-tokens-file conflicts with -inline; ignored");
}
else {
def_token_file = t;
if ( def_token_file == NULL )
{
warnNoFL("don't you want filename with that -def-tokens-file?; ignored");
}
}
}
static void
#ifdef __USE_PROTOS
pPrefix( char *s, char *t )
#else
pPrefix( s, t )
char *s, *t;
#endif
{
Prefix = t;
if ( GenCPP ) {
warnNoFL("-prefix conflicts with C++ interface; ignored");
Prefix = "";
return;
}
if ( Prefix == NULL )
{
warnNoFL("don't you want string with that -prefix?; ignored");
Prefix = "";
}
}
static void
#ifdef __USE_PROTOS
pFuncs( char *s, char *t )
#else
pFuncs( s, t )
char *s, *t;
#endif
{
if ( GenCPP ) { errNoFL("-funcs option makes no sense in C++ mode; ignored"); return; }
GenKRProtos = GenAnsiProtos = 0;
if ( cistrequ(t, "kr")) GenKRProtos = 1;
else if ( cistrequ(t, "ansi")) GenAnsiProtos = 1;
else if ( cistrequ(t, "both")) {GenAnsiProtos = 1; GenKRProtos = 1;}
else {
warnNoFL(eMsg1("don't know how to generate '%s' style functions; assuming ANSI",t));
GenAnsiProtos = 1;
}
}
static void
#ifdef __USE_PROTOS
pProtoFile( char *s, char *t )
#else
pProtoFile( s, t )
char *s, *t;
#endif
{
if ( GenCPP )
{warnNoFL("-proto-file not valid with C++ interface; ignored");}
if ( t==NULL )
{warnNoFL("don't you want filename with that -proto-file?; ignored");}
else {
GenProtoFile = t;
}
}
static void
pstdin()
{
if ( DontAcceptStdin )
{
warnNoFL("'-' (stdin) ignored as files were specified first");
return;
}
if ( GenCPP )
{warnNoFL("'-' (stdin) cannot be used with C++ interface; ignored");}
require(NumFiles<MaxNumFiles,"exceeded max # of input files");
FileStr[NumFiles++] = "stdin";
DontAcceptFiles = 1;
}
static void
pGuts()
{
print_guts = 1;
}
static void
pTrans()
{
transform = 1;
}
static void
pInline()
{
if ( def_token_file!=NULL )
{
warnNoFL("-inline conflicts with -def-tokens; ignored");
}
else if ( GenCPP )
{
warnNoFL("-inline conflicts with C++ interface; ignored");
}
else Inline = 1;
}
static void
pCPP()
{
GenCPP = 1;
}
/* MR23 */
static void
pNoCtor()
{
NoCtor = 1;
if ( ! GenCPP )
{warnNoFL("-noctor needs -CPP option; ignored");}
}
Opt options[] = {
#ifdef __cplusplus
{ "-CPP", 0, (void (*)(...)) pCPP,"Generate C++ output"},
{ "-def-tokens", 0, (void (*)(...)) pDToks,"Define ref'd tokens w/unique integer (C++ interface)"},
{ "-def-tokens-file", 1, (void (*)(...)) pDToksFile,"Define ref'd tokens w/unique integer (put in file)"},
{ "-funcs", 1, (void (*)(...)) pFuncs,"Gen 'ANSI', 'KR', or 'both' style function headers"},
{ "-guts", 0, (void (*)(...)) pGuts,"Print out a bunch of internal data structures"},
{ "-inline", 0, (void (*)(...)) pInline, "Gen only actions and functions for given rules"},
{ "-noctor", 0, (void (*)(...)) pNoCtor, "Do not generate a blank constructor"}, /* MR23 */
{ "-prefix", 1, (void (*)(...)) pPrefix, "Prefix all globally visible symbols"},
{ "-proto-file", 1, (void (*)(...)) pProtoFile, "Put all prototypes for rule functions in this file"},
{ "-out-dir", 1, (void (*)(...)) pOut, "Directory where all output files go (default=\".\")"},
{ "-transform", 0, (void (*)(...)) pTrans, "Transformation mode; read/write to different pointers"},
{ "-", 0, (void (*)(...)) pstdin, "take input from stdin"},
{ "*", 0, (void (*)(...)) pFile, "" }, /* anything else is a file */
#else
{ "-CPP", 0, pCPP, "Generate C++ output"},
{ "-def-tokens", 0, pDToks,"Define ref'd tokens w/unique integer (C++ interface)"},
{ "-def-tokens-file", 1, pDToksFile,"Define ref'd tokens w/unique integer (put in file)"},
{ "-funcs", 1, pFuncs,"Gen 'ANSI', 'KR', or 'both' style function headers"},
{ "-guts", 0, pGuts,"Print out a bunch of internal data structures"},
{ "-inline", 0, pInline, "Gen only actions and functions for given rules"},
{ "-noctor", 0, pNoCtor, "Do not generate a blank constructor"}, /* MR23 */
{ "-prefix", 1, pPrefix, "Prefix all globally visible symbols"},
{ "-proto-file", 1, pProtoFile, "Put all prototypes for rule functions in this file"},
{ "-out-dir", 1, pOut, "Directory where all output files go (default=\".\")"},
{ "-transform", 0, pTrans, "Transformation mode; read/write to different pointers"},
{ "-", 0, pstdin, "take input from stdin"},
{ "*", 0, pFile, "" }, /* anything else is a file */
#endif
{ NULL, 0, NULL, NULL }
};
int
#ifdef __USE_PROTOS
main(int argc, char *argv[])
#else
main(argc, argv)
int argc;
char *argv[];
#endif
{
AST *root;
#ifdef THINK_C
#include <console.h>
argc = ccommand (&argv);
#endif
fprintf(stderr,
"Sorcerer - A simple tree-parser generator Version %s 1992-2001\n",
VersionText);
if ( argc == 1 ) { help(); zzDONE; }
ProcessArgs(argc-1, &(argv[1]), options);
symbols = newHashTable();
token_dict = (char **) calloc(token_table_size, sizeof(char *));
require(token_dict != NULL, "main: can't create token_dict");
output = stdout;
input = NextFile();
require(input!=NULL, "No grammar description found (exiting...)");
root = read_sor_desc(input);
if ( root!=NULL ) gen(root);
if ( found_error )
{
fprintf(stderr, "no parser generated due to parsing errors; exiting...\n");
zzDIE;
}
if ( GenCPP ) {
GenCPPClassHeader();
GenCPPClassCode();
}
if ( !UserDefdTokens ) gen_tokens_file();
else if ( def_token_file!=NULL ) {
warnNoFL("tokens file not generated; it conflicts with use of #tokdefs");
}
if ( GenProtoFile!=NULL )
{
FILE *ProtoFILE;
ProtoFILE = fopen(OutMetaName(GenProtoFile), "w");
if ( ProtoFILE==NULL ) {warnNoFL(eMsg1("Can't open prototype file '%s'; ignored",GenProtoFile));}
else {
#ifdef SPECIAL_FOPEN
special_fopen_actions(OutMetaName(GenProtoFile));
#endif
gen_info_hdr( ProtoFILE );
if ( header_action!=NULL )
dumpAction(header_action, ProtoFILE, 0, -1, 0, 1);
GenRulePrototypes( ProtoFILE, 0 );
fclose(ProtoFILE);
}
}
if ( found_error ) {zzDIE;}
else zzDONE;
}
void
#ifdef __USE_PROTOS
help(void)
#else
help()
#endif
{
Opt *p = options;
static char buf[MaxRuleName+1];
fprintf(stderr, "sor [options] f1.sor ... fn.sor\n");
while ( p->option!=NULL && *(p->option) != '*' )
{
buf[0]='\0';
if ( p->arg ) sprintf(buf, "%s ___", p->option);
else strcpy(buf, p->option);
fprintf(stderr, " %-20s %s\n", buf, p->descr);
p++;
}
}
FILE *
#ifdef __USE_PROTOS
NextFile( void )
#else
NextFile( )
#endif
{
FILE *f;
for (;;)
{
if ( CurFile+1 >= NumFiles ) return(NULL);
CurFile++;
if ( cistrequ(FileStr[CurFile],"stdin")) return stdin;
f = fopen(FileStr[CurFile], "r");
if ( f == NULL )
{
warnNoFL( eMsg1("file %s doesn't exist; ignored", FileStr[CurFile]) );
}
else
{
return(f);
}
}
}
void
#ifdef __USE_PROTOS
pushint( int i )
#else
pushint( i )
int i;
#endif
{
require(isp>0, "pushint: stack overflow");
istack[--isp] = i;
}
int
#ifdef __USE_PROTOS
popint( void )
#else
popint( )
#endif
{
require(isp<MAX_INT_STACK, "popint: stack underflow");
return istack[isp++];
}
int
#ifdef __USE_PROTOS
istacksize( void )
#else
istacksize( )
#endif
{
return MAX_INT_STACK-isp;
}
void
#ifdef __USE_PROTOS
istackreset( void )
#else
istackreset( )
#endif
{
isp = MAX_INT_STACK;
}
int
#ifdef __USE_PROTOS
istackempty( void )
#else
istackempty( )
#endif
{
return isp==MAX_INT_STACK;
}
int
#ifdef __USE_PROTOS
topint( void )
#else
topint( )
#endif
{
require(isp<MAX_INT_STACK, "topint: stack underflow");
return istack[isp];
}
/* sprintf up to 3 strings */
char *
#ifdef __USE_PROTOS
eMsg3( char *s, char *a1, char *a2, char *a3 )
#else
eMsg3( s, a1, a2, a3 )
char *s;
char *a1;
char *a2;
char *a3;
#endif
{
static char buf[250]; /* DANGEROUS as hell !!!!!! */
sprintf(buf, s, a1, a2, a3);
return( buf );
}
char *
#ifdef __USE_PROTOS
eMsgd( char *s, int d )
#else
eMsgd( s, d )
char *s;
int d;
#endif
{
static char buf[250]; /* DANGEROUS as hell !!!!!! */
sprintf(buf, s, d);
return( buf );
}
void
#ifdef __USE_PROTOS
fatalFL( char *err_, char *f, int l )
#else
fatalFL( err_, f, l )
char *err_;
char *f;
int l;
#endif
{
fprintf(stderr, ErrHdr, f, l);
fprintf(stderr, " %s\n", err_);
exit(1);
}
/*
* add an element to a list.
*
* Any non-empty list has a sentinel node whose 'elem' pointer is really
* a pointer to the last element. (i.e. length(list) = #elemIn(list)+1).
* Elements are appended to the list.
*/
void
#ifdef __USE_PROTOS
list_add( ListNode **list, void *e )
#else
list_add( list, e )
ListNode **list;
void *e;
#endif
{
ListNode *p, *tail;
require(e!=NULL, "list_add: attempting to add NULL list element");
p = newListNode;
require(p!=NULL, "list_add: cannot alloc new list node");
p->elem = e;
if ( *list == NULL )
{
ListNode *sentinel = newListNode;
require(sentinel!=NULL, "list_add: cannot alloc sentinel node");
*list=sentinel;
sentinel->next = p;
sentinel->elem = (char *)p; /* set tail pointer */
}
else /* find end of list */
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?