Check In tool source code based on Build tool project revision r1655.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@8964 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
lgao4
2009-07-17 09:10:31 +00:00
parent 577e30cdb4
commit 30fdf1140b
532 changed files with 231447 additions and 32 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,762 @@
/*
* genmk -- a program to make makefiles for PCCTS
*
* ANTLR 1.33MR10
* Terence John Parr 1989 - 1998
* Purdue University
* U of MN
*/
#include <stdio.h>
#include "pcctscfg.h" /* be sensitive to what ANTLR/DLG call the files */
#ifdef VAXC
#define DIE return 0;
#define DONE return 1;
#else
#define DIE return 1;
#define DONE return 0;
#endif
#ifndef require
#define require(expr, err) {if ( !(expr) ) fatal(err);}
#endif
#define MAX_FILES 50
#define MAX_CLASSES 50
char *RENAME_OBJ_FLAG="-o",
*RENAME_EXE_FLAG="-o";
char *dlg = "parser.dlg";
char *err = "err.c";
char *hdr = "stdpccts.h";
char *tok = "tokens.h";
char *mode = "mode.h";
char *scan = "scan";
char ATOKENBUFFER_O[100];
char APARSER_O[100];
char ASTBASE_O[100];
char PCCTSAST_O[100];
char LIST_O[100];
char DLEXERBASE_O[100];
/* Option flags */
static char *project="t", *files[MAX_FILES], *classes[MAX_CLASSES];
static int num_files = 0;
static int num_classes = 0;
static int user_lexer = 0;
static char *user_token_types = NULL;
static int gen_CPP = 0;
static char *outdir=".";
static char *dlg_class = "DLGLexer";
static int gen_trees = 0;
static int gen_hoist = 0;
static char cfiles[1600]="";
static char *compilerCCC="CC";
static char *compilerCC="cc";
static char *pccts_path="/usr/local/pccts";
void help();
void mk();
void pfiles();
void pclasses();
void fatal();
void warn();
typedef struct _Opt {
char *option;
int arg;
#ifdef __cplusplus
void (*process)(...);
#else
void (*process)();
#endif
char *descr;
} Opt;
#ifdef __STDC__
static void ProcessArgs(int, char **, Opt *);
#else
static void ProcessArgs();
#endif
static void
pProj( s, t )
char *s;
char *t;
{
project = t;
}
static void
pUL( s )
char *s;
{
user_lexer = 1;
}
static void
pCPP( s )
char *s;
{
gen_CPP = 1;
}
static void
pUT( s, t )
char *s;
char *t;
{
user_token_types = t;
}
static void
pTrees( s )
char *s;
{
gen_trees = 1;
}
static void
pHoist( s )
char *s;
{
gen_hoist = 1;
}
static void
#ifdef __STDC__
pFile( char *s )
#else
pFile( s )
char *s;
#endif
{
if ( *s=='-' )
{
fprintf(stderr, "invalid option: '%s'; ignored...",s);
return;
}
require(num_files<MAX_FILES, "exceeded max # of input files");
files[num_files++] = s;
}
static void
#ifdef __STDC__
pClass( char *s, char *t )
#else
pClass( s, t )
char *s;
char *t;
#endif
{
require(num_classes<MAX_CLASSES, "exceeded max # of grammar classes");
classes[num_classes++] = t;
}
static void
#ifdef __STDC__
pDLGClass( char *s, char *t )
#else
pDLGClass( s, t )
char *s;
char *t;
#endif
{
if ( !gen_CPP ) {
fprintf(stderr, "-dlg-class makes no sense without C++ mode; ignored...");
}
else dlg_class = t;
}
static void
#ifdef __STDC__
pOdir( char *s, char *t )
#else
pOdir( s, t )
char *s;
char *t;
#endif
{
outdir = t;
}
static void
#ifdef __STDC__
pHdr( char *s, char *t )
#else
pHdr( s, t )
char *s;
char *t;
#endif
{
hdr = t;
}
static void
#ifdef __STDC__
pCFiles( char *s, char *t )
#else
pCFiles( s, t )
char *s;
char *t;
#endif
{
strcat(strcat(cfiles," "), t);
}
static void
#ifdef __STDC__
pCompiler( char *s, char *t )
#else
pCompiler( s, t )
char *s;
char *t;
#endif
{
compilerCCC = t;
compilerCC = t;
}
static void
#ifdef __STDC__
ppccts_path( char *s, char *t )
#else
ppccts_path( s, t )
char *s;
char *t;
#endif
{
pccts_path = t;
}
Opt options[] = {
{ "-CC", 0, pCPP, "Generate C++ output"},
{ "-class", 1, pClass, "Name of a grammar class defined in grammar (if C++)"},
{ "-dlg-class", 1,pDLGClass,"Name of DLG lexer class (default=DLGLexer) (if C++)"},
{ "-header", 1,pHdr, "Name of ANTLR standard header info (default=no file)"},
{ "-o", 1, pOdir, "Directory where output files should go (default=\".\")"},
{ "-project", 1, pProj, "Name of executable to create (default=t)"},
{ "-token-types", 1, pUT, "Token types are in this file (don't use tokens.h)"},
{ "-trees", 0, pTrees, "Generate ASTs"},
{ "-user-lexer", 0, pUL, "Do not create a DLG-based scanner"},
{ "-mrhoist",0,pHoist, "Maintenance release style hoisting"},
{ "-cfiles",1,pCFiles, "Additional files in C or C++ to compile"},
{ "-pccts_path",1,ppccts_path,
"Path for $PCCTS directory (default is /usr/local/pccts)"},
{ "-compiler",1,pCompiler,
"Default compiler (default is CC/cc)"},
{ "*", 0,pFile, "" }, /* anything else is a file */
{ NULL, 0, NULL, NULL }
};
extern char *DIR();
int main(argc, argv)
int argc;
char **argv;
{
if ( argc == 1 ) { help(); DIE; }
ProcessArgs(argc-1, &(argv[1]), options);
strcpy(ATOKENBUFFER_O, ATOKENBUFFER_C);
ATOKENBUFFER_O[strlen(ATOKENBUFFER_C)-strlen(CPP_FILE_SUFFIX)] = '\0';
strcat(ATOKENBUFFER_O, OBJ_FILE_SUFFIX);
strcpy(APARSER_O, APARSER_C);
APARSER_O[strlen(APARSER_O)-strlen(CPP_FILE_SUFFIX)] = '\0';
strcat(APARSER_O, OBJ_FILE_SUFFIX);
strcpy(ASTBASE_O, ASTBASE_C);
ASTBASE_O[strlen(ASTBASE_C)-strlen(CPP_FILE_SUFFIX)] = '\0';
strcat(ASTBASE_O, OBJ_FILE_SUFFIX);
strcpy(PCCTSAST_O, PCCTSAST_C);
PCCTSAST_O[strlen(PCCTSAST_C)-strlen(CPP_FILE_SUFFIX)] = '\0';
strcat(PCCTSAST_O, OBJ_FILE_SUFFIX);
strcpy(LIST_O, LIST_C);
LIST_O[strlen(LIST_C)-strlen(CPP_FILE_SUFFIX)] = '\0';
strcat(LIST_O, OBJ_FILE_SUFFIX);
strcpy(DLEXERBASE_O, DLEXERBASE_C);
DLEXERBASE_O[strlen(DLEXERBASE_C)-strlen(CPP_FILE_SUFFIX)] = '\0';
strcat(DLEXERBASE_O, OBJ_FILE_SUFFIX);
if ( num_files == 0 ) fatal("no grammar files specified; exiting...");
if ( !gen_CPP && num_classes>0 ) {
warn("can't define classes w/o C++ mode; turning on C++ mode...\n");
gen_CPP=1;
}
if ( gen_CPP && num_classes==0 ) {
fatal("must define classes >0 grammar classes in C++ mode\n");
}
mk(project, files, num_files, argc, argv);
DONE;
}
void help()
{
Opt *p = options;
static char buf[1000+1];
fprintf(stderr, "genmk [options] f1.g ... fn.g\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, "\t%-16s %s\n", buf, p->descr);
p++;
}
}
void mk(project, files, n, argc, argv)
char *project;
char **files;
int n;
int argc;
char **argv;
{
int i;
printf("#\n");
printf("# PCCTS makefile for: ");
pfiles(files, n, NULL);
printf("\n");
printf("#\n");
printf("# Created from:");
for (i=0; i<argc; i++) printf(" %s", argv[i]);
printf("\n");
printf("#\n");
printf("# PCCTS release 1.33MR21\n");
printf("# Project: %s\n", project);
if ( gen_CPP ) printf("# C++ output\n");
else printf("# C output\n");
if ( user_lexer ) printf("# User-defined scanner\n");
else printf("# DLG scanner\n");
if ( user_token_types!=NULL ) printf("# User-defined token types in '%s'\n", user_token_types);
else printf("# ANTLR-defined token types\n");
printf("#\n");
printf(".SUFFIXES:\n.SUFFIXES: .o .cpp .c .h .g .i .dlg\n");
if ( user_token_types!=NULL ) {
printf("# Make sure #tokdefs directive in ANTLR grammar lists this file:\n");
printf("TOKENS = %s", user_token_types);
}
else printf("TOKENS = %stokens.h", DIR());
printf("\n");
printf("#\n");
printf("# The following filenames must be consistent with ANTLR/DLG flags\n");
printf("DLG_FILE = %s%s\n", DIR(), dlg);
printf("ERR = %serr\n", DIR());
if ( strcmp(hdr,"stdpccts.h")!=0 ) printf("HDR_FILE = %s%s\n", DIR(), hdr);
else printf("HDR_FILE =\n");
if ( !gen_CPP ) printf("MOD_FILE = %s%s\n", DIR(), mode);
if ( !gen_CPP ) printf("SCAN = %s\n", scan);
else printf("SCAN = %s%s\n", DIR(), dlg_class);
printf("PCCTS = %s\n",pccts_path);
printf("ANTLR_H = $(PCCTS)%sh\n", DirectorySymbol);
printf("BIN = $(PCCTS)%sbin\n", DirectorySymbol);
printf("ANTLR = $(BIN)%santlr\n", DirectorySymbol);
printf("DLG = $(BIN)%sdlg\n", DirectorySymbol);
printf("CFLAGS = -I. -I$(ANTLR_H)");
if ( strcmp(outdir, ".")!=0 ) printf(" -I%s", outdir);
printf(" $(COTHER)");
printf("\n");
printf("AFLAGS =");
if ( strcmp(outdir,".")!=0 ) printf(" -o %s", outdir);
if ( user_lexer ) printf(" -gx");
if ( gen_CPP ) printf(" -CC");
if ( strcmp(hdr,"stdpccts.h")!=0 ) printf(" -gh %s", hdr);
if ( gen_trees ) printf(" -gt");
if ( gen_hoist ) {
printf(" -mrhoist on") ;
} else {
printf(" -mrhoist off");
};
printf(" $(AOTHER)");
printf("\n");
printf("DFLAGS = -C2 -i");
if ( gen_CPP ) printf(" -CC");
if ( strcmp(dlg_class,"DLGLexer")!=0 ) printf(" -cl %s", dlg_class);
if ( strcmp(outdir,".")!=0 ) printf(" -o %s", outdir);
printf(" $(DOTHER)");
printf("\n");
printf("GRM = ");
pfiles(files, n, NULL);
printf("\n");
printf("MYFILES = %s\n",cfiles);
printf("SRC = ");
if ( gen_CPP ) pfiles(files, n, CPP_FILE_SUFFIX_NO_DOT);
else pfiles(files, n, "c");
if ( gen_CPP ) {
printf(" \\\n ");
printf(" ");
pclasses(classes, num_classes, CPP_FILE_SUFFIX_NO_DOT);
printf(" \\\n ");
printf("$(ANTLR_H)%s%s", DirectorySymbol, APARSER_C);
if ( !user_lexer ) printf(" $(ANTLR_H)%s%s", DirectorySymbol, DLEXERBASE_C);
if ( gen_trees ) {
printf(" \\\n ");
printf("$(ANTLR_H)%s%s", DirectorySymbol, ASTBASE_C);
printf(" $(ANTLR_H)%s%s", DirectorySymbol, PCCTSAST_C);
/* printf(" $(ANTLR_H)%s%s", DirectorySymbol, LIST_C); */
printf(" \\\n ");
}
printf(" $(ANTLR_H)%s%s", DirectorySymbol, ATOKENBUFFER_C);
}
if ( !user_lexer ) {
if ( gen_CPP ) printf(" $(SCAN)%s", CPP_FILE_SUFFIX);
else printf(" %s$(SCAN).c", DIR());
}
if ( !gen_CPP ) printf(" $(ERR).c");
printf("\\\n $(MYFILES)\n");
printf("OBJ = ");
pfiles(files, n, "o");
if ( gen_CPP ) {
printf(" \\\n ");
printf(" ");
pclasses(classes, num_classes, "o");
printf(" \\\n ");
printf(" %s%s", DIR(), APARSER_O);
if ( !user_lexer ) {
printf(" %s%s", DIR(), DLEXERBASE_O);
}
if ( gen_trees ) {
printf(" \\\n ");
printf("%s%s", DIR(), ASTBASE_O);
printf(" %s%s", DIR(), PCCTSAST_O);
/* printf(" %s%s", DIR(), LIST_O); */
printf(" \\\n ");
}
printf(" %s%s", DIR(), ATOKENBUFFER_O);
}
if ( !user_lexer ) {
if ( gen_CPP ) printf(" $(SCAN)%s", OBJ_FILE_SUFFIX);
else printf(" %s$(SCAN)%s", DIR(), OBJ_FILE_SUFFIX);
}
if ( !gen_CPP ) printf(" $(ERR)%s", OBJ_FILE_SUFFIX);
printf("\\\n $(MYFILES:.cpp=.o)\n");
printf("ANTLR_SPAWN = ");
if ( gen_CPP ) pfiles(files, n, CPP_FILE_SUFFIX_NO_DOT);
else pfiles(files, n, "c");
if ( gen_CPP ) {
printf(" ");
pclasses(classes, num_classes, CPP_FILE_SUFFIX_NO_DOT);
printf(" \\\n ");
pclasses(classes, num_classes, "h");
if ( strcmp(hdr,"stdpccts.h")!=0 ) {
printf(" \\\n ");
printf("$(HDR_FILE) stdpccts.h");
}
}
if ( user_lexer ) {
if ( !user_token_types ) printf(" $(TOKENS)");
}
else {
printf(" $(DLG_FILE)");
if ( !user_token_types ) printf(" $(TOKENS)");
}
if ( !gen_CPP ) printf(" $(ERR).c");
printf("\n");
if ( !user_lexer ) {
if ( gen_CPP ) printf("DLG_SPAWN = $(SCAN)%s", CPP_FILE_SUFFIX);
else printf("DLG_SPAWN = %s$(SCAN).c", DIR());
if ( gen_CPP ) printf(" $(SCAN).h");
if ( !gen_CPP ) printf(" $(MOD_FILE)");
printf("\n");
}
if ( gen_CPP ) {
printf("CCC = %s\n",compilerCCC);
}
else printf("CC = %s\n",compilerCC);
/* set up dependencies */
printf("\n%s : $(OBJ) $(SRC)\n", project);
printf(" %s %s %s $(CFLAGS) $(OBJ)\n",
gen_CPP?"$(CCC)":"$(CC)",
RENAME_EXE_FLAG,
project);
printf("\n");
/* implicit rules */
if(gen_CPP)
printf("%%.o : %%.cpp\n\t$(CCC) -c $(CFLAGS) $<\n\n");
printf("%%.o : %%.c\n\t%s -c $(CFLAGS) $<\n\n",
gen_CPP?"$(CCC)":"$(CC)");
/* how to compile parser files */
for (i=0; i<num_files; i++)
{
pfiles(&files[i], 1, "o");
if ( user_lexer ) {
printf(" : $(TOKENS)");
}
else {
if ( gen_CPP ) printf(" : $(TOKENS) $(SCAN).h");
else printf(" : $(MOD_FILE) $(TOKENS)");
}
printf(" ");
if ( gen_CPP ) pfiles(&files[i], 1, CPP_FILE_SUFFIX_NO_DOT);
else pfiles(&files[i], 1, "c");
if ( gen_CPP && strcmp(hdr,"stdpccts.h")!=0 ) printf(" $(HDR_FILE)");
printf("\n");
printf(" %s -c $(CFLAGS) %s ",
gen_CPP?"$(CCC)":"$(CC)",RENAME_OBJ_FLAG);
pfiles(&files[i], 1, "o");
printf(" ");
if ( gen_CPP ) pfiles(&files[i], 1, CPP_FILE_SUFFIX_NO_DOT);
else pfiles(&files[i], 1, "c");
printf("\n\n");
}
/* how to compile err.c */
if ( !gen_CPP ) {
printf("$(ERR)%s : $(ERR).c", OBJ_FILE_SUFFIX);
if ( !user_lexer ) printf(" $(TOKENS)");
printf("\n");
printf(" %s -c $(CFLAGS) %s $(ERR)%s $(ERR).c",
gen_CPP?"$(CCC)":"$(CC)",
RENAME_OBJ_FLAG,
OBJ_FILE_SUFFIX);
printf("\n\n");
}
/* how to compile Class.c */
for (i=0; i<num_classes; i++)
{
pclasses(&classes[i], 1, "o");
if ( user_lexer ) {
printf(" : $(TOKENS)");
}
else {
printf(" : $(TOKENS) $(SCAN).h");
}
printf(" ");
pclasses(&classes[i], 1, CPP_FILE_SUFFIX_NO_DOT);
printf(" ");
pclasses(&classes[i], 1, "h");
if ( gen_CPP && strcmp(hdr,"stdpccts.h")!=0 ) printf(" $(HDR_FILE)");
printf("\n");
printf(" %s -c $(CFLAGS) %s ",
gen_CPP?"$(CCC)":"$(CC)",
RENAME_OBJ_FLAG);
pclasses(&classes[i], 1, "o");
printf(" ");
pclasses(&classes[i], 1, CPP_FILE_SUFFIX_NO_DOT);
printf("\n\n");
}
/* how to compile scan.c */
if ( !user_lexer ) {
if ( gen_CPP ) printf("$(SCAN)%s : $(SCAN)%s", OBJ_FILE_SUFFIX, CPP_FILE_SUFFIX);
else printf("%s$(SCAN)%s : %s$(SCAN).c", DIR(), OBJ_FILE_SUFFIX, DIR());
if ( !user_lexer ) printf(" $(TOKENS)");
printf("\n");
if ( gen_CPP ) printf(" $(CCC) -c $(CFLAGS) %s $(SCAN)%s $(SCAN)%s",
RENAME_OBJ_FLAG,
OBJ_FILE_SUFFIX,
CPP_FILE_SUFFIX);
else printf(" $(CC) -c $(CFLAGS) %s %s$(SCAN)%s %s$(SCAN).c",
RENAME_OBJ_FLAG,
DIR(),
OBJ_FILE_SUFFIX,
DIR());
printf("\n\n");
}
printf("$(ANTLR_SPAWN) : $(GRM)\n");
printf(" $(ANTLR) $(AFLAGS) $(GRM)\n");
if ( !user_lexer )
{
printf("\n");
printf("$(DLG_SPAWN) : $(DLG_FILE)\n");
if ( gen_CPP ) printf(" $(DLG) $(DFLAGS) $(DLG_FILE)\n");
else printf(" $(DLG) $(DFLAGS) $(DLG_FILE) $(SCAN).c\n");
}
/* do the makes for ANTLR/DLG support */
if ( gen_CPP ) {
printf("\n");
printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), APARSER_O, DirectorySymbol, APARSER_C);
printf(" %s -c $(CFLAGS) %s ",
gen_CPP?"$(CCC)":"$(CC)",
RENAME_OBJ_FLAG);
printf("%s%s $(ANTLR_H)%s%s\n", DIR(), APARSER_O, DirectorySymbol, APARSER_C);
printf("\n");
printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), ATOKENBUFFER_O, DirectorySymbol, ATOKENBUFFER_C);
printf(" %s -c $(CFLAGS) %s ",
gen_CPP?"$(CCC)":"$(CC)",
RENAME_OBJ_FLAG);
printf("%s%s $(ANTLR_H)%s%s\n", DIR(), ATOKENBUFFER_O, DirectorySymbol, ATOKENBUFFER_C);
if ( !user_lexer ) {
printf("\n");
printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), DLEXERBASE_O, DirectorySymbol, DLEXERBASE_C);
printf(" %s -c $(CFLAGS) %s ",
gen_CPP?"$(CCC)":"$(CC)",
RENAME_OBJ_FLAG);
printf("%s%s $(ANTLR_H)%s%s\n", DIR(), DLEXERBASE_O, DirectorySymbol, DLEXERBASE_C);
}
if ( gen_trees ) {
printf("\n");
printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), ASTBASE_O, DirectorySymbol, ASTBASE_C);
printf(" %s -c $(CFLAGS) %s ",
gen_CPP?"$(CCC)":"$(CC)",
RENAME_OBJ_FLAG);
printf("%s%s $(ANTLR_H)%s%s\n", DIR(), ASTBASE_O, DirectorySymbol, ASTBASE_C);
printf("\n");
printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), PCCTSAST_O, DirectorySymbol, PCCTSAST_C);
printf(" %s -c $(CFLAGS) %s ",
gen_CPP?"$(CCC)":"$(CC)",
RENAME_OBJ_FLAG);
printf("%s%s $(ANTLR_H)%s%s\n", DIR(), PCCTSAST_O, DirectorySymbol, PCCTSAST_C);
printf("\n");
/*
printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), LIST_O, DirectorySymbol, LIST_C);
printf(" %s -c $(CFLAGS) %s ",
gen_CPP?"$(CCC)":"$(CC)",RENAME_OBJ_FLAG);
printf("%s%s $(ANTLR_H)%s%s\n", DIR(), LIST_O, DirectorySymbol, LIST_C);
*/
}
}
/* clean and scrub targets */
printf("\nclean:\n");
printf(" rm -f *%s core %s", OBJ_FILE_SUFFIX, project);
if ( strcmp(outdir, ".")!=0 ) printf(" %s*%s", DIR(), OBJ_FILE_SUFFIX);
printf("\n");
printf("\nscrub:\n");
printf(" rm -f *%s core %s", OBJ_FILE_SUFFIX, project);
if ( strcmp(outdir, ".")!=0 ) printf(" %s*%s", DIR(), OBJ_FILE_SUFFIX);
printf(" $(ANTLR_SPAWN)");
if ( !user_lexer ) printf(" $(DLG_SPAWN)");
printf("\n");
}
void pfiles(files, n, suffix)
char **files;
int n;
char *suffix;
{
int first=1;
while ( n>0 )
{
char *p = &(*files)[strlen(*files)-1];
if ( !first ) putchar(' ');
first=0;
while ( p > *files && *p != '.' ) --p;
if ( p == *files )
{
fprintf(stderr,
"genmk: filenames must be file.suffix format: %s\n",
*files);
exit(-1);
}
if ( suffix == NULL ) printf("%s", *files);
else
{
*p = '\0';
printf("%s", DIR());
if ( strcmp(suffix, "o")==0 ) printf("%s%s", *files, OBJ_FILE_SUFFIX);
else printf("%s.%s", *files, suffix);
*p = '.';
}
files++;
--n;
}
}
void pclasses(classes, n, suffix)
char **classes;
int n;
char *suffix;
{
int first=1;
while ( n>0 )
{
if ( !first ) putchar(' ');
first=0;
if ( suffix == NULL ) printf("%s", *classes);
else {
printf("%s", DIR());
if ( strcmp(suffix, "o")==0 ) printf("%s%s", *classes, OBJ_FILE_SUFFIX);
else printf("%s.%s", *classes, suffix);
}
classes++;
--n;
}
}
static 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++;
}
}
void fatal( err_)
char *err_;
{
fprintf(stderr, "genmk: %s\n", err_);
exit(1);
}
void warn( err_)
char *err_;
{
fprintf(stderr, "genmk: %s\n", err_);
}
char *DIR()
{
static char buf[200+1];
if ( strcmp(outdir,TopDirectory)==0 ) return "";
sprintf(buf, "%s%s", outdir, DirectorySymbol);
return buf;
}

View File

@@ -0,0 +1,29 @@
##
## 7-Apr-97
## added support/genmk/makefile to pccts 1.33MR1 distribution kit
## (support/genmk/makefile" omitted from 1.33 distribution kit)
##
SRC=genmk.c
OBJ=genmk.o
# Define PC if you use a PC OS (changes directory symbol and object file extension)
# see pccts/h/pcctscfg.h
CC=cc
COPT=-O
#CFLAGS=-I../../h -DPC
CFLAGS=$(COPT) -I../../h
BAG=../../bin/bag
genmk: $(OBJ) $(SRC) ../../h/pcctscfg.h
$(CC) -o genmk $(OBJ)
clean:
rm -rf core *.o
scrub:
rm -rf genmk core *.o
shar:
shar genmk.c makefile > genmk.shar
archive:
$(BAG) genmk.c makefile > genmk.bag

View File

@@ -0,0 +1,19 @@
BAG=../../bin/bag
SRC=test.c rexpr.c
OBJ=test.o rexpr.o
CFLAGS = -g
test: $(OBJ) $(SRC)
cc -g -o texpr $(OBJ)
shar:
shar makefile test.c rexpr.c rexpr.h > rexpr.shar
archive:
$(BAG) makefile test.c rexpr.c rexpr.h > rexpr.bag
clean:
rm -rf *.o core texpr
scrub:
rm -rf *.o core texpr

View File

@@ -0,0 +1,586 @@
/*
* This file contains code for
*
* int rexpr(char *expr, char *s);
*
* which answers
*
* 1 if 's' is in the language described by the regular expression 'expr'
* 0 if it is not
* -1 if the regular expression is invalid
*
* Language membership is determined by constructing a non-deterministic
* finite automata (NFA) from the regular expression. A depth-
* first-search is performed on the NFA (graph) to check for a match of 's'.
* Each non-epsilon arc consumes one character from 's'. Backtracking is
* performed to check all possible paths through the NFA.
*
* Regular expressions follow the meta-language:
*
* <regExpr> ::= <andExpr> ( '|' <andExpr> )*
*
* <andExpr> ::= <expr> ( <expr> )*
*
* <expr> ::= {'~'} '[' <atomList> ']' <repeatSymbol>
* | '(' <regExpr> ')' <repeatSymbol>
* | '{' <regExpr> '}' <repeatSymbol>
* | <atom> <repeatSymbol>
*
* <repeatSymbol> ::= { '*' | '+' }
*
* <atomList> ::= <atom> ( <atom> )*
* | { <atomList> } <atom> '-' <atom> { <atomList> }
*
* <atom> ::= Token[Atom]
*
* Notes:
* ~ means complement the set in [..]. i.e. all characters not listed
* * means match 0 or more times (can be on expression or atom)
* + means match 1 or more times (can be on expression or atom)
* {} optional
* () grouping
* [] set of atoms
* x-y all characters from x to y (found only in [..])
* \xx the character with value xx
*
* Examples:
* [a-z]+
* match 1 or more lower-case letters (e.g. variable)
*
* 0x[0-9A-Fa-f]+
* match a hex number with 0x on front (e.g. 0xA1FF)
*
* [0-9]+.[0-9]+{e[0-9]+}
* match a floating point number (e.g. 3.14e21)
*
* Code example:
* if ( rexpr("[a-zA-Z][a-zA-Z0-9]+", str) ) then str is keyword
*
* Terence Parr
* Purdue University
* April 1991
*/
#include <stdio.h>
#include <ctype.h>
#ifdef __STDC__
#include <stdlib.h>
#else
#include <malloc.h>
#endif
#include "rexpr.h"
#ifdef __USE_PROTOS
static int regExpr( GraphPtr g );
static int andExpr( GraphPtr g );
static int expr( GraphPtr g );
static int repeatSymbol( GraphPtr g );
static int atomList( char *p, int complement );
static void next( void );
static ArcPtr newGraphArc( void );
static NodePtr newNode( void );
static int ArcBetweenGraphNode( NodePtr i, NodePtr j, int label );
static Graph BuildNFA_atom( int label );
static Graph BuildNFA_AB( Graph A, Graph B );
static Graph BuildNFA_AorB( Graph A, Graph B );
static Graph BuildNFA_set( char *s );
static Graph BuildNFA_Astar( Graph A );
static Graph BuildNFA_Aplus( Graph A );
static Graph BuildNFA_Aoptional( Graph A );
#else
static int regExpr();
static int andExpr();
static int expr();
static int repeatSymbol();
static int atomList();
static void next();
static ArcPtr newGraphArc();
static NodePtr newNode();
static int ArcBetweenGraphNode();
static Graph BuildNFA_atom();
static Graph BuildNFA_AB();
static Graph BuildNFA_AorB();
static Graph BuildNFA_set();
static Graph BuildNFA_Astar();
static Graph BuildNFA_Aplus();
static Graph BuildNFA_Aoptional();
#endif
static char *_c;
static int token, tokchar;
static NodePtr accept;
static NodePtr freelist = NULL;
/*
* return 1 if s in language described by expr
* 0 if s is not
* -1 if expr is an invalid regular expression
*/
#ifdef __USE_PROTOS
static int rexpr(char *expr,char *s)
#else
static int rexpr(expr, s)
char *expr, *s;
#endif
{
NodePtr p,q;
Graph nfa;
int result;
fprintf(stderr, "rexpr(%s,%s);\n", expr,s);
freelist = NULL;
_c = expr;
next();
if ( regExpr(&nfa) == -1 ) return -1;
accept = nfa.right;
result = match(nfa.left, s);
/* free all your memory */
p = q = freelist;
while ( p!=NULL ) { q = p->track; free(p); p = q; }
return result;
}
/*
* do a depth-first-search on the NFA looking for a path from start to
* accept state labelled with the characters of 's'.
*/
#ifdef __USE_PROTOS
static int match(NodePtr automaton,char *s)
#else
static int match(automaton, s)
NodePtr automaton;
char *s;
#endif
{
ArcPtr p;
if ( automaton == accept && *s == '\0' ) return 1; /* match */
for (p=automaton->arcs; p!=NULL; p=p->next) /* try all arcs */
{
if ( p->label == Epsilon )
{
if ( match(p->target, s) ) return 1;
}
else if ( p->label == *s )
if ( match(p->target, s+1) ) return 1;
}
return 0;
}
/*
* <regExpr> ::= <andExpr> ( '|' {<andExpr>} )*
*
* Return -1 if syntax error
* Return 0 if none found
* Return 1 if a regExrp was found
*/
#ifdef __USE_PROTOS
static int regExpr(GraphPtr g)
#else
static int regExpr(g)
GraphPtr g;
#endif
{
Graph g1, g2;
if ( andExpr(&g1) == -1 )
{
return -1;
}
while ( token == '|' )
{
int a;
next();
a = andExpr(&g2);
if ( a == -1 ) return -1; /* syntax error below */
else if ( !a ) return 1; /* empty alternative */
g1 = BuildNFA_AorB(g1, g2);
}
if ( token!='\0' ) return -1;
*g = g1;
return 1;
}
/*
* <andExpr> ::= <expr> ( <expr> )*
*/
#ifdef __USE_PROTOS
static int andExpr(GraphPtr g)
#else
static int andExpr(g)
GraphPtr g;
#endif
{
Graph g1, g2;
if ( expr(&g1) == -1 )
{
return -1;
}
while ( token==Atom || token=='{' || token=='(' || token=='~' || token=='[' )
{
if (expr(&g2) == -1) return -1;
g1 = BuildNFA_AB(g1, g2);
}
*g = g1;
return 1;
}
/*
* <expr> ::= {'~'} '[' <atomList> ']' <repeatSymbol>
* | '(' <regExpr> ')' <repeatSymbol>
* | '{' <regExpr> '}' <repeatSymbol>
* | <atom> <repeatSymbol>
*/
#ifdef __USE_PROTOS
static int expr(GraphPtr g)
#else
static int expr(g)
GraphPtr g;
#endif
{
int complement = 0;
char s[257]; /* alloc space for string of char in [] */
if ( token == '~' || token == '[' )
{
if ( token == '~' ) {complement = 1; next();}
if ( token != '[' ) return -1;
next();
if ( atomList( s, complement ) == -1 ) return -1;
*g = BuildNFA_set( s );
if ( token != ']' ) return -1;
next();
repeatSymbol( g );
return 1;
}
if ( token == '(' )
{
next();
if ( regExpr( g ) == -1 ) return -1;
if ( token != ')' ) return -1;
next();
repeatSymbol( g );
return 1;
}
if ( token == '{' )
{
next();
if ( regExpr( g ) == -1 ) return -1;
if ( token != '}' ) return -1;
next();
/* S p e c i a l C a s e O p t i o n a l { } */
if ( token != '*' && token != '+' )
{
*g = BuildNFA_Aoptional( *g );
}
repeatSymbol( g );
return 1;
}
if ( token == Atom )
{
*g = BuildNFA_atom( tokchar );
next();
repeatSymbol( g );
return 1;
}
return -1;
}
/*
* <repeatSymbol> ::= { '*' | '+' }
*/
#ifdef __USE_PROTOS
static int repeatSymbol(GraphPtr g)
#else
static int repeatSymbol(g)
GraphPtr g;
#endif
{
switch ( token )
{
case '*' : *g = BuildNFA_Astar( *g ); next(); break;
case '+' : *g = BuildNFA_Aplus( *g ); next(); break;
}
return 1;
}
/*
* <atomList> ::= <atom> { <atom> }*
* { <atomList> } <atom> '-' <atom> { <atomList> }
*
* a-b is same as ab
* q-a is same as q
*/
#ifdef __USE_PROTOS
static int atomList(char *p, int complement)
#else
static int atomList(p, complement)
char *p;
int complement;
#endif
{
static unsigned char set[256]; /* no duplicates */
int first, last, i;
char *s = p;
if ( token != Atom ) return -1;
for (i=0; i<256; i++) set[i] = 0;
while ( token == Atom )
{
if ( !set[tokchar] ) *s++ = tokchar;
set[tokchar] = 1; /* Add atom to set */
next();
if ( token == '-' ) /* have we found '-' */
{
first = *(s-1); /* Get last char */
next();
if ( token != Atom ) return -1;
else
{
last = tokchar;
}
for (i = first+1; i <= last; i++)
{
if ( !set[tokchar] ) *s++ = i;
set[i] = 1; /* Add atom to set */
}
next();
}
}
*s = '\0';
if ( complement )
{
for (i=0; i<256; i++) set[i] = !set[i];
for (i=1,s=p; i<256; i++) if ( set[i] ) *s++ = i;
*s = '\0';
}
return 1;
}
/* a somewhat stupid lexical analyzer */
#ifdef __USE_PROTOS
static void next(void)
#else
static void next()
#endif
{
while ( *_c==' ' || *_c=='\t' || *_c=='\n' ) _c++;
if ( *_c=='\\' )
{
_c++;
if ( isdigit(*_c) )
{
int n=0;
while ( isdigit(*_c) )
{
n = n*10 + (*_c++ - '0');
}
if ( n>255 ) n=255;
tokchar = n;
}
else
{
switch (*_c)
{
case 'n' : tokchar = '\n'; break;
case 't' : tokchar = '\t'; break;
case 'r' : tokchar = '\r'; break;
default : tokchar = *_c;
}
_c++;
}
token = Atom;
}
else if ( isgraph(*_c) && *_c!='[' && *_c!='(' && *_c!='{' &&
*_c!='-' && *_c!='}' && *_c!=')' && *_c!=']' &&
*_c!='+' && *_c!='*' && *_c!='~' && *_c!='|' )
{
token = Atom;
tokchar = *_c++;
}
else
{
token = tokchar = *_c++;
}
}
/* N F A B u i l d i n g R o u t i n e s */
#ifdef __USE_PROTOS
static ArcPtr newGraphArc(void)
#else
static ArcPtr newGraphArc()
#endif
{
ArcPtr p;
p = (ArcPtr) calloc(1, sizeof(Arc));
if ( p==NULL ) {fprintf(stderr,"rexpr: out of memory\n"); exit(-1);}
if ( freelist != NULL ) p->track = (ArcPtr) freelist;
freelist = (NodePtr) p;
return p;
}
#ifdef __USE_PROTOS
static NodePtr newNode(void)
#else
static NodePtr newNode()
#endif
{
NodePtr p;
p = (NodePtr) calloc(1, sizeof(Node));
if ( p==NULL ) {fprintf(stderr,"rexpr: out of memory\n"); exit(-1);}
if ( freelist != NULL ) p->track = freelist;
freelist = p;
return p;
}
#ifdef __USE_PROTOS
static void ArcBetweenGraphNodes(NodePtr i,NodePtr j,int label)
#else
static void ArcBetweenGraphNodes(i, j, label)
NodePtr i, j;
int label;
#endif
{
ArcPtr a;
a = newGraphArc();
if ( i->arcs == NULL ) i->arctail = i->arcs = a;
else {(i->arctail)->next = a; i->arctail = a;}
a->label = label;
a->target = j;
}
#ifdef __USE_PROTOS
static Graph BuildNFA_atom(int label)
#else
static Graph BuildNFA_atom(label)
int label;
#endif
{
Graph g;
g.left = newNode();
g.right = newNode();
ArcBetweenGraphNodes(g.left, g.right, label);
return( g );
}
#ifdef __USE_PROTOS
static Graph BuildNFA_AB(Graph A,Graph B)
#else
static Graph BuildNFA_AB(A, B)
Graph A, B;
#endif
{
Graph g;
ArcBetweenGraphNodes(A.right, B.left, Epsilon);
g.left = A.left;
g.right = B.right;
return( g );
}
#ifdef __USE_PROTOS
static Graph BuildNFA_AorB(Graph A,Graph B)
#else
static Graph BuildNFA_AorB(A, B)
Graph A, B;
#endif
{
Graph g;
g.left = newNode();
ArcBetweenGraphNodes(g.left, A.left, Epsilon);
ArcBetweenGraphNodes(g.left, B.left, Epsilon);
g.right = newNode();
ArcBetweenGraphNodes(A.right, g.right, Epsilon);
ArcBetweenGraphNodes(B.right, g.right, Epsilon);
return( g );
}
#ifdef __USE_PROTOS
static Graph BuildNFA_set(char *s)
#else
static Graph BuildNFA_set( s )
char *s;
#endif
{
Graph g;
if ( s == NULL ) return g;
g.left = newNode();
g.right = newNode();
while ( *s != '\0' )
{
ArcBetweenGraphNodes(g.left, g.right, *s++);
}
return g;
}
#ifdef __USE_PROTOS
static Graph BuildNFA_Astar(Graph A)
#else
static Graph BuildNFA_Astar( A )
Graph A;
#endif
{
Graph g;
g.left = newNode();
g.right = newNode();
ArcBetweenGraphNodes(g.left, A.left, Epsilon);
ArcBetweenGraphNodes(g.left, g.right, Epsilon);
ArcBetweenGraphNodes(A.right, g.right, Epsilon);
ArcBetweenGraphNodes(A.right, A.left, Epsilon);
return( g );
}
#ifdef __USE_PROTOS
static Graph BuildNFA_Aplus(Graph A)
#else
static Graph BuildNFA_Aplus( A )
Graph A;
#endif
{
ArcBetweenGraphNodes(A.right, A.left, Epsilon);
return( A );
}
#ifdef __USE_PROTOS
static Graph BuildNFA_Aoptional(Graph A)
#else
static Graph BuildNFA_Aoptional( A )
Graph A;
#endif
{
Graph g;
g.left = newNode();
g.right = newNode();
ArcBetweenGraphNodes(g.left, A.left, Epsilon);
ArcBetweenGraphNodes(g.left, g.right, Epsilon);
ArcBetweenGraphNodes(A.right, g.right, Epsilon);
return( g );
}

View File

@@ -0,0 +1,30 @@
#define Atom 256 /* token Atom (an impossible char value) */
#define Epsilon 257 /* epsilon arc (an impossible char value) */
/* track field must be same for all node types */
typedef struct _a {
struct _a *track; /* track mem allocation */
int label;
struct _a *next;
struct _n *target;
} Arc, *ArcPtr;
typedef struct _n {
struct _n *track;
ArcPtr arcs, arctail;
} Node, *NodePtr;
typedef struct {
NodePtr left,
right;
} Graph, *GraphPtr;
#ifdef __USE_PROTOS
int rexpr( char *expr, char *s );
int match( NodePtr automaton, char *s );
#else
int rexpr();
int match();
#endif

View File

@@ -0,0 +1,19 @@
#include <stdio.h>
#include "rexpr.h"
/*
* test for rexpr().
* To make this test:
* cc -o rexpr test.c rexpr.c
* Then from command line type:
* rexpr r string
* where r is the regular expression that decribes a language
* and string is the string to verify.
*/
main(argc,argv)
int argc;
char *argv[];
{
if ( argc!=3 ) fprintf(stderr,"rexpr: expr s\n");
else printf("%d\n", rexpr(argv[1], argv[2]));
}

View File

@@ -0,0 +1,816 @@
/* set.c
The following is a general-purpose set library originally developed
by Hank Dietz and enhanced by Terence Parr to allow dynamic sets.
Sets are now structs containing the #words in the set and
a pointer to the actual set words.
Generally, sets need not be explicitly allocated. They are
created/extended/shrunk when appropriate (e.g. in set_of()).
HOWEVER, sets need to be destroyed (free()ed) when they go out of scope
or are otherwise no longer needed. A routine is provided to
free a set.
Sets can be explicitly created with set_new(s, max_elem).
Sets can be declared to have minimum size to reduce realloc traffic.
Default minimum size = 1.
Sets can be explicitly initialized to have no elements (set.n == 0)
by using the 'empty' initializer:
Examples:
set a = empty; -- set_deg(a) == 0
return( empty );
Example set creation and destruction:
set
set_of2(e,g)
unsigned e,g;
{
set a,b,c;
b = set_of(e); -- Creates space for b and sticks in e
set_new(c, g); -- set_new(); set_orel() ==> set_of()
set_orel(g, &c);
a = set_or(b, c);
.
.
.
set_free(b);
set_free(c);
return( a );
}
1987 by Hank Dietz
Modified by:
Terence Parr
Purdue University
October 1989
Made it smell less bad to C++ 7/31/93 -- TJP
*/
#include <stdio.h>
#include "pcctscfg.h"
#ifdef __STDC__
#include <stdlib.h>
#else
#include <malloc.h>
#endif
#include <string.h>
#include "set.h"
#define MIN(i,j) ( (i) > (j) ? (j) : (i))
#define MAX(i,j) ( (i) < (j) ? (j) : (i))
/* elems can be a maximum of 32 bits */
static unsigned bitmask[] = {
0x00000001, 0x00000002, 0x00000004, 0x00000008,
0x00000010, 0x00000020, 0x00000040, 0x00000080,
0x00000100, 0x00000200, 0x00000400, 0x00000800,
0x00001000, 0x00002000, 0x00004000, 0x00008000,
#if !defined(PC) || defined(PC32)
0x00010000, 0x00020000, 0x00040000, 0x00080000,
0x00100000, 0x00200000, 0x00400000, 0x00800000,
0x01000000, 0x02000000, 0x04000000, 0x08000000,
0x10000000, 0x20000000, 0x40000000, 0x80000000
#endif
};
set empty = set_init;
static unsigned min=1;
#define StrSize 200
#ifdef MEMCHK
#define CHK(a) \
if ( a.setword != NULL ) \
if ( !valid(a.setword) ) \
{fprintf(stderr, "%s(%d): invalid set\n",__FILE__,__LINE__); exit(-1);}
#else
#define CHK(a)
#endif
/*
* Set the minimum size (in words) of a set to reduce realloc calls
*/
void
#ifdef __USE_PROTOS
set_size( unsigned n )
#else
set_size( n )
unsigned n;
#endif
{
min = n;
}
unsigned int
#ifdef __USE_PROTOS
set_deg( set a )
#else
set_deg( a )
set a;
#endif
{
/* Fast compute degree of a set... the number
of elements present in the set. Assumes
that all word bits are used in the set
and that SETSIZE(a) is a multiple of WORDSIZE.
*/
register unsigned *p = &(a.setword[0]);
register unsigned *endp = NULL; /* MR27 Avoid false memory check report */
register unsigned degree = 0;
CHK(a);
if ( a.n == 0 ) return(0);
endp = &(a.setword[a.n]);
while ( p < endp )
{
register unsigned t = *p;
register unsigned *b = &(bitmask[0]);
do {
if (t & *b) ++degree;
} while (++b < &(bitmask[WORDSIZE]));
p++;
}
return(degree);
}
set
#ifdef __USE_PROTOS
set_or( set b, set c )
#else
set_or( b, c )
set b;
set c;
#endif
{
/* Fast set union operation */
/* resultant set size is max(b, c); */
set *big;
set t;
unsigned int m,n;
register unsigned *r, *p, *q, *endp;
CHK(b); CHK(c);
t = empty;
if (b.n > c.n) {big= &b; m=b.n; n=c.n;} else {big= &c; m=c.n; n=b.n;}
set_ext(&t, m);
r = t.setword;
/* Or b,c until max of smaller set */
q = c.setword;
p = b.setword;
endp = &(b.setword[n]);
while ( p < endp ) *r++ = *p++ | *q++;
/* Copy rest of bigger set into result */
p = &(big->setword[n]);
endp = &(big->setword[m]);
while ( p < endp ) *r++ = *p++;
return(t);
}
set
#ifdef __USE_PROTOS
set_and( set b, set c )
#else
set_and( b, c )
set b;
set c;
#endif
{
/* Fast set intersection operation */
/* resultant set size is min(b, c); */
set t;
unsigned int n;
register unsigned *r, *p, *q, *endp;
CHK(b); CHK(c);
t = empty;
n = (b.n > c.n) ? c.n : b.n;
if ( n == 0 ) return t; /* TJP 4-27-92 fixed for empty set */
set_ext(&t, n);
r = t.setword;
/* & b,c until max of smaller set */
q = c.setword;
p = b.setword;
endp = &(b.setword[n]);
while ( p < endp ) *r++ = *p++ & *q++;
return(t);
}
set
#ifdef __USE_PROTOS
set_dif( set b, set c )
#else
set_dif( b, c )
set b;
set c;
#endif
{
/* Fast set difference operation b - c */
/* resultant set size is size(b) */
set t;
unsigned int n;
register unsigned *r, *p, *q, *endp;
CHK(b); CHK(c);
t = empty;
n = (b.n <= c.n) ? b.n : c.n ;
if ( b.n == 0 ) return t; /* TJP 4-27-92 fixed for empty set */
/* WEC 12-1-92 fixed for c.n = 0 */
set_ext(&t, b.n);
r = t.setword;
/* Dif b,c until smaller set size */
q = c.setword;
p = b.setword;
endp = &(b.setword[n]);
while ( p < endp ) *r++ = *p++ & (~ *q++);
/* Copy rest of b into result if size(b) > c */
if ( b.n > n )
{
p = &(b.setword[n]);
endp = &(b.setword[b.n]);
while ( p < endp ) *r++ = *p++;
}
return(t);
}
set
#ifdef __USE_PROTOS
set_of( unsigned b )
#else
set_of( b )
unsigned b;
#endif
{
/* Fast singleton set constructor operation */
static set a;
if ( b == nil ) return( empty );
set_new(a, b);
a.setword[DIVWORD(b)] = bitmask[MODWORD(b)];
return(a);
}
/*
* Extend (or shrink) the set passed in to have n words.
*
* if n is smaller than the minimum, boost n to have the minimum.
* if the new set size is the same as the old one, do nothing.
*
* TJP 4-27-92 Fixed so won't try to alloc 0 bytes
*/
void
#ifdef __USE_PROTOS
set_ext( set *a, unsigned int n )
#else
set_ext( a, n )
set *a;
unsigned int n;
#endif
{
register unsigned *p;
register unsigned *endp;
unsigned int size;
CHK((*a));
if ( a->n == 0 )
{
if ( n == 0 ) return;
if (a->setword != NULL) {
free (a->setword); /* MR20 */
}
a->setword = (unsigned *) calloc(n, BytesPerWord);
if ( a->setword == NULL )
{
fprintf(stderr, "set_ext(%d words): cannot allocate set\n", n);
exit(-1);
}
a->n = n;
return;
}
if ( n < min ) n = min;
if ( a->n == n || n == 0 ) return;
size = a->n;
a->n = n;
a->setword = (unsigned *) realloc( (char *)a->setword, (n*BytesPerWord) );
if ( a->setword == NULL )
{
fprintf(stderr, "set_ext(%d words): cannot allocate set\n", n);
exit(-1);
}
p = &(a->setword[size]); /* clear from old size to new size */
endp = &(a->setword[a->n]);
do {
*p++ = 0;
} while ( p < endp );
}
set
#ifdef __USE_PROTOS
set_not( set a )
#else
set_not( a )
set a;
#endif
{
/* Fast not of set a (assumes all bits used) */
/* size of resultant set is size(a) */
/* ~empty = empty cause we don't know how bit to make set */
set t;
register unsigned *r;
register unsigned *p = a.setword;
register unsigned *endp = &(a.setword[a.n]);
CHK(a);
t = empty;
if ( a.n == 0 ) return( empty );
set_ext(&t, a.n);
r = t.setword;
do {
*r++ = (~ *p++);
} while ( p < endp );
return(t);
}
int
#ifdef __USE_PROTOS
set_equ( set a, set b )
#else
set_equ( a, b )
set a;
set b;
#endif
{
/* 8-Nov-97 Make it work with sets of different sizes */
/* Easy to understand, too. Probably faster. */
/* Check for a equal to b */
unsigned int count; /* MR11 */
unsigned int i; /* MR11 */
CHK(a); CHK(b);
count=MIN(a.n,b.n);
if (count == 0) return 1;
for (i=0; i < count; i++) {
if (a.setword[i] != b.setword[i]) return 0;
};
if (a.n < b.n) {
for (i=count; i < b.n; i++) {
if (b.setword[i] != 0) return 0;
}
return 1;
} else if (a.n > b.n) {
for (i=count; i < a.n; i++) {
if (a.setword[i] != 0) return 0;
}
return 1;
} else {
return 1;
};
}
int
#ifdef __USE_PROTOS
set_sub( set a, set b )
#else
set_sub( a, b )
set a;
set b;
#endif
{
/* 8-Nov-97 Make it work with sets of different sizes */
/* Easy to understand, too. Probably faster. */
/* Check for a is a PROPER subset of b */
unsigned int count;
unsigned int i;
CHK(a); CHK(b);
if (a.n == 0) return 1;
count=MIN(a.n,b.n);
for (i=0; i < count; i++) {
if (a.setword[i] & ~b.setword[i]) return 0;
};
if (a.n <= b.n) {
return 1;
} else {
for (i=count; i<a.n ; i++) {
if (a.setword[i]) return 0;
};
};
return 1;
}
unsigned
#ifdef __USE_PROTOS
set_int( set b )
#else
set_int( b )
set b;
#endif
{
/* Fast pick any element of the set b */
register unsigned *p = b.setword;
register unsigned *endp = &(b.setword[b.n]);
CHK(b);
if ( b.n == 0 ) return( nil );
do {
if (*p) {
/* Found a non-empty word of the set */
register unsigned i = ((p - b.setword) << LogWordSize);
register unsigned t = *p;
p = &(bitmask[0]);
while (!(*p & t)) {
++i; ++p;
}
return(i);
}
} while (++p < endp);
/* Empty -- only element it contains is nil */
return(nil);
}
int
#ifdef __USE_PROTOS
set_el( unsigned b, set a )
#else
set_el( b, a )
unsigned b;
set a;
#endif
{
CHK(a);
/* nil is an element of every set */
if (b == nil) return(1);
if ( a.n == 0 || NumWords(b) > a.n ) return(0);
/* Otherwise, we have to check */
return( a.setword[DIVWORD(b)] & bitmask[MODWORD(b)] );
}
int
#ifdef __USE_PROTOS
set_nil( set a )
#else
set_nil( a )
set a;
#endif
{
/* Fast check for nil set */
register unsigned *p = a.setword;
register unsigned *endp;
CHK(a);
if ( a.n == 0 ) return(1);
endp = &(a.setword[a.n]);
/* The set is not empty if any word used to store
the set is non-zero. This means one must be a
bit careful about doing things like negation.
*/
do {
if (*p) return(0);
} while (++p < endp);
return(1);
}
char *
#ifdef __USE_PROTOS
set_str( set a )
#else
set_str( a )
set a;
#endif
{
/* Fast convert set a into ASCII char string...
assumes that all word bits are used in the set
and that SETSIZE is a multiple of WORDSIZE.
Trailing 0 bits are removed from the string.
if no bits are on or set is empty, "" is returned.
*/
register unsigned *p = a.setword;
register unsigned *endp = &(a.setword[a.n]);
static char str_tmp[StrSize+1];
register char *q = &(str_tmp[0]);
CHK(a);
if ( a.n==0 ) {*q=0; return( &(str_tmp[0]) );}
do {
register unsigned t = *p;
register unsigned *b = &(bitmask[0]);
do {
*(q++) = (char) ((t & *b) ? '1' : '0');
} while (++b < &(bitmask[WORDSIZE]));
} while (++p < endp);
/* Trim trailing 0s & NULL terminate the string */
while ((q > &(str_tmp[0])) && (*(q-1) != '1')) --q;
*q = 0;
return(&(str_tmp[0]));
}
set
#ifdef __USE_PROTOS
set_val( register char *s )
#else
set_val( s )
register char *s;
#endif
{
/* Fast convert set ASCII char string into a set.
If the string ends early, the remaining set bits
are all made zero.
The resulting set size is just big enough to hold all elements.
*/
static set a;
register unsigned *p, *endp;
set_new(a, strlen(s));
p = a.setword;
endp = &(a.setword[a.n]);
do {
register unsigned *b = &(bitmask[0]);
/* Start with a word with no bits on */
*p = 0;
do {
if (*s) {
if (*s == '1') {
/* Turn-on this bit */
*p |= *b;
}
++s;
}
} while (++b < &(bitmask[WORDSIZE]));
} while (++p < endp);
return(a);
}
/*
* Or element e into set a. a can be empty.
*/
void
#ifdef __USE_PROTOS
set_orel( unsigned e, set *a )
#else
set_orel( e, a )
unsigned e;
set *a;
#endif
{
CHK((*a));
if ( e == nil ) return;
if ( NumWords(e) > a->n ) set_ext(a, NumWords(e));
a->setword[DIVWORD(e)] |= bitmask[MODWORD(e)];
}
/*
* Or set b into set a. a can be empty. does nothing if b empty.
*/
void
#ifdef __USE_PROTOS
set_orin( set *a, set b )
#else
set_orin( a, b )
set *a;
set b;
#endif
{
/* Fast set union operation */
/* size(a) is max(a, b); */
unsigned int m;
register unsigned *p,
*q = b.setword,
*endq; /* MR20 */
CHK((*a)); CHK(b);
if ( b.n == 0 ) return;
endq = &(b.setword[b.n]); /* MR20 */
m = (a->n > b.n) ? a->n : b.n;
set_ext(a, m);
p = a->setword;
do {
*p++ |= *q++;
} while ( q < endq );
}
/*
* And set b into set a. a can be empty. does nothing if b empty.
*/
void
#ifdef __USE_PROTOS
set_andin( set *a, set b )
#else
set_andin( a, b )
set *a;
set b;
#endif
{
/* Fast set intersection operation */
/* size(a) is max(a, b); */
unsigned int m;
register unsigned *p,
*q = b.setword,
*endq = &(b.setword[b.n]);
CHK((*a)); CHK(b);
if ( b.n == 0 ) return;
m = (a->n > b.n) ? a->n : b.n;
set_ext(a, m);
p = a->setword;
do {
*p++ &= *q++;
} while ( q < endq );
}
void
#ifdef __USE_PROTOS
set_rm( unsigned e, set a )
#else
set_rm( e, a )
unsigned e;
set a;
#endif
{
/* Does not effect size of set */
CHK(a);
if ( (e == nil) || (NumWords(e) > a.n) ) return;
a.setword[DIVWORD(e)] ^= (a.setword[DIVWORD(e)]&bitmask[MODWORD(e)]);
}
void
#ifdef __USE_PROTOS
set_clr( set a )
#else
set_clr( a )
set a;
#endif
{
/* Does not effect size of set */
register unsigned *p = a.setword;
register unsigned *endp;
CHK(a);
if ( a.n == 0 ) return;
endp = &(a.setword[a.n]);
do {
*p++ = 0;
} while ( p < endp );
}
set
#ifdef __USE_PROTOS
set_dup( set a )
#else
set_dup( a )
set a;
#endif
{
set b;
register unsigned *p,
*q = a.setword,
*endq; /* MR20 */
CHK(a);
b = empty;
if ( a.n == 0 ) return( empty );
endq = &(a.setword[a.n]); /* MR20 */
set_ext(&b, a.n);
p = b.setword;
do {
*p++ = *q++;
} while ( q < endq );
return(b);
}
/*
* Return a nil terminated list of unsigned ints that represents all
* "on" bits in the bit set.
*
* e.g. {011011} --> {1, 2, 4, 5, nil}
*
* _set_pdq and set_pdq are useful when an operation is required on each element
* of a set. Normally, the sequence is:
*
* while ( set_deg(a) > 0 ) {
* e = set_int(a);
* set_rm(e, a);
* ...process e...
* }
* Now,
*
* t = e = set_pdq(a);
* while ( *e != nil ) {
* ...process *e...
* e++;
* }
* free( t );
*
* We have saved many set calls and have not destroyed set a.
*/
void
#ifdef __USE_PROTOS
_set_pdq( set a, register unsigned *q )
#else
_set_pdq( a, q )
set a;
register unsigned *q;
#endif
{
register unsigned *p = a.setword,
*endp = &(a.setword[a.n]);
register unsigned e=0;
CHK(a);
/* are there any space (possibility of elements)? */
if ( a.n == 0 ) return;
do {
register unsigned t = *p;
register unsigned *b = &(bitmask[0]);
do {
if ( t & *b ) *q++ = e;
++e;
} while (++b < &(bitmask[WORDSIZE]));
} while (++p < endp);
*q = nil;
}
/*
* Same as _set_pdq except allocate memory. set_pdq is the natural function
* to use.
*/
unsigned *
#ifdef __USE_PROTOS
set_pdq( set a )
#else
set_pdq( a )
set a;
#endif
{
unsigned *q;
int max_deg;
CHK(a);
max_deg = WORDSIZE*a.n;
/* assume a.n!=0 & no elements is rare, but still ok */
if ( a.n == 0 ) return(NULL);
q = (unsigned *) malloc((max_deg+1)*BytesPerWord);
if ( q == NULL ) return( NULL );
_set_pdq(a, q);
return( q );
}
/* a function that produces a hash number for the set
*/
unsigned int
#ifdef __USE_PROTOS
set_hash( set a, register unsigned int mod )
#else
set_hash( a, mod )
set a;
register unsigned int mod;
#endif
{
/* Fast hash of set a (assumes all bits used) */
register unsigned *p = &(a.setword[0]);
register unsigned *endp = &(a.setword[a.n]);
register unsigned i = 0;
CHK(a);
while (p<endp){
i += (*p);
++p;
}
return(i % mod);
}

View File

@@ -0,0 +1,121 @@
#ifndef __GATE_SET_H
#define __GATE_SET_H
/* set.h
The following is a general-purpose set library originally developed
by Hank Dietz and enhanced by Terence Parr to allow dynamic sets.
Sets are now structs containing the #words in the set and
a pointer to the actual set words.
1987 by Hank Dietz
Modified by:
Terence Parr
Purdue University
October 1989
Added ANSI prototyping Dec. 1992 -- TJP
*/
#include "pcctscfg.h"
#ifdef NOT_USED /* SEE config.h */
/* Define usable bits per unsigned int word */
#ifdef PC
#define WORDSIZE 16
#define LogWordSize 4
#else
#define WORDSIZE 32
#define LogWordSize 5
#endif
#define BytesPerWord sizeof(unsigned)
#endif
#define SETSIZE(a) ((a).n<<LogWordSize) /* Maximum items per set */
#define MODWORD(x) ((x) & (WORDSIZE-1)) /* x % WORDSIZE */
#define DIVWORD(x) ((x) >> LogWordSize) /* x / WORDSIZE */
#define nil (~((unsigned) 0)) /* An impossible set member all bits on (big!) */
typedef struct _set {
unsigned int n; /* Number of words in set */
unsigned *setword;
} set;
#define set_init {0, NULL}
#define set_null(a) ((a).setword==NULL)
#define NumBytes(x) (((x)>>3)+1) /* Num bytes to hold x */
#define NumWords(x) ((((unsigned)(x))>>LogWordSize)+1) /* Num words to hold x */
/* M a c r o s */
/* make arg1 a set big enough to hold max elem # of arg2 */
#define set_new(a,_max) \
if (((a).setword=(unsigned *)calloc(NumWords(_max),BytesPerWord))==NULL) \
fprintf(stderr, "set_new: Cannot allocate set with max of %d\n", _max); \
(a).n = NumWords(_max);
#define set_free(a) \
{if ( (a).setword != NULL ) free((char *)((a).setword)); \
(a) = empty;}
#ifdef __USE_PROTOS
extern void set_size( unsigned );
extern unsigned int set_deg( set );
extern set set_or( set, set );
extern set set_and( set, set );
extern set set_dif( set, set );
extern set set_of( unsigned );
extern void set_ext( set *, unsigned int );
extern set set_not( set );
extern int set_equ( set, set );
extern int set_sub( set, set );
extern unsigned set_int( set );
extern int set_el( unsigned, set );
extern int set_nil( set );
extern char * set_str( set );
extern set set_val( register char * );
extern void set_orel( unsigned, set * );
extern void set_orin( set *, set );
extern void set_andin( set *, set );
extern void set_rm( unsigned, set );
extern void set_clr( set );
extern set set_dup( set );
extern void set_PDQ( set, register unsigned * );
extern unsigned *set_pdq( set );
extern void _set_pdq( set a, register unsigned *q );
extern unsigned int set_hash( set, register unsigned int );
#else
extern void set_size();
extern unsigned int set_deg();
extern set set_or();
extern set set_and();
extern set set_dif();
extern set set_of();
extern void set_ext();
extern set set_not();
extern int set_equ();
extern int set_sub();
extern unsigned set_int();
extern int set_el();
extern int set_nil();
extern char * set_str();
extern set set_val();
extern void set_orel();
extern void set_orin();
extern void set_andin();
extern void set_rm();
extern void set_clr();
extern set set_dup();
extern void set_PDQ();
extern unsigned *set_pdq();
extern void _set_pdq();
extern unsigned int set_hash();
#endif
extern set empty;
#endif

View File

@@ -0,0 +1,402 @@
/*
* Simple symbol table manager using coalesced chaining to resolve collisions
*
* Doubly-linked lists are used for fast removal of entries.
*
* 'sym.h' must have a definition for typedef "Sym". Sym must include at
* minimum the following fields:
*
* ...
* char *symbol;
* struct ... *next, *prev, **head, *scope;
* unsigned int hash;
* ...
*
* 'template.h' can be used as a template to create a 'sym.h'.
*
* 'head' is &(table[hash(itself)]).
* The hash table is not resizable at run-time.
* The scope field is used to link all symbols of a current scope together.
* Scope() sets the current scope (linked list) to add symbols to.
* Any number of scopes can be handled. The user passes the address of
* a pointer to a symbol table
* entry (INITIALIZED TO NULL first time).
*
* Available Functions:
*
* zzs_init(s1,s2) -- Create hash table with size s1, string table size s2.
* zzs_done() -- Free hash and string table created with zzs_init().
* zzs_add(key,rec)-- Add 'rec' with key 'key' to the symbol table.
* zzs_newadd(key) -- create entry; add using 'key' to the symbol table.
* zzs_get(key) -- Return pointer to last record entered under 'key'
* Else return NULL
* zzs_del(p) -- Unlink the entry associated with p. This does
* NOT free 'p' and DOES NOT remove it from a scope
* list. If it was a part of your intermediate code
* tree or another structure. It will still be there.
* It is only removed from further consideration
* by the symbol table.
* zzs_keydel(s) -- Unlink the entry associated with key s.
* Calls zzs_del(p) to unlink.
* zzs_scope(sc) -- Specifies that everything added to the symbol
* table with zzs_add() is added to the list (scope)
* 'sc'. 'sc' is of 'Sym **sc' type and must be
* initialized to NULL before trying to add anything
* to it (passing it to zzs_scope()). Scopes can be
* switched at any time and merely links a set of
* symbol table entries. If a NULL pointer is
* passed, the current scope is returned.
* zzs_rmscope(sc) -- Remove (zzs_del()) all elements of scope 'sc'
* from the symbol table. The entries are NOT
* free()'d. A pointer to the first
* element in the "scope" is returned. The user
* can then manipulate the list as he/she chooses
* (such as freeing them all). NOTE that this
* function sets your scope pointer to NULL,
* but returns a pointer to the list for you to use.
* zzs_stat() -- Print out the symbol table and some relevant stats.
* zzs_new(key) -- Create a new record with calloc() of type Sym.
* Add 'key' to the string table and make the new
* records 'symbol' pointer point to it.
* zzs_strdup(s) -- Add s to the string table and return a pointer
* to it. Very fast allocation routine
* and does not require strlen() nor calloc().
*
* Example:
*
* #include <stdio.h>
* #include "sym.h"
*
* main()
* {
* Sym *scope1=NULL, *scope2=NULL, *a, *p;
*
* zzs_init(101, 100);
*
* a = zzs_new("Apple"); zzs_add(a->symbol, a); -- No scope
* zzs_scope( &scope1 ); -- enter scope 1
* a = zzs_new("Plum"); zzs_add(a->symbol, a);
* zzs_scope( &scope2 ); -- enter scope 2
* a = zzs_new("Truck"); zzs_add(a->symbol, a);
*
* p = zzs_get("Plum");
* if ( p == NULL ) fprintf(stderr, "Hmmm...Can't find 'Plum'\n");
*
* p = zzs_rmscope(&scope1)
* for (; p!=NULL; p=p->scope) {printf("Scope1: %s\n", p->symbol);}
* p = zzs_rmscope(&scope2)
* for (; p!=NULL; p=p->scope) {printf("Scope2: %s\n", p->symbol);}
* }
*
* Terence Parr
* Purdue University
* February 1990
*
* CHANGES
*
* Terence Parr
* May 1991
* Renamed functions to be consistent with ANTLR
* Made HASH macro
* Added zzs_keydel()
* Added zzs_newadd()
* Fixed up zzs_stat()
*
* July 1991
* Made symbol table entry save its hash code for fast comparison
* during searching etc...
*/
#include <stdio.h>
#if defined(__STDC__) || defined(__USE_PROTOS)
#include <string.h>
#include <stdlib.h>
#else
#include <malloc.h>
#endif
#include "sym.h"
#define StrSame 0
static Sym **CurScope = NULL;
static unsigned size = 0;
static Sym **table=NULL;
static char *strings;
static char *strp;
static int strsize = 0;
#ifdef __USE_PROTOS
void zzs_init(int sz,int strs)
#else
void zzs_init(sz, strs)
int sz, strs;
#endif
{
if ( sz <= 0 || strs <= 0 ) return;
table = (Sym **) calloc(sz, sizeof(Sym *));
if ( table == NULL )
{
fprintf(stderr, "Cannot allocate table of size %d\n", sz);
exit(1);
}
strings = (char *) calloc(strs, sizeof(char));
if ( strings == NULL )
{
fprintf(stderr, "Cannot allocate string table of size %d\n", strs);
exit(1);
}
size = sz;
strsize = strs;
strp = strings;
}
#ifdef __USE_PROTOS
void zzs_done(void)
#else
void zzs_done()
#endif
{
if ( table != NULL ) free( table );
if ( strings != NULL ) free( strings );
}
#ifdef __USE_PROTOS
void zzs_add(char *key,Sym rec)
#else
void zzs_add(key, rec)
char *key;
register Sym *rec;
#endif
{
register unsigned int h=0;
register char *p=key;
HASH(p, h);
rec->hash = h; /* save hash code for fast comp later */
h %= size;
if ( CurScope != NULL ) {rec->scope = *CurScope; *CurScope = rec;}
rec->next = table[h]; /* Add to doubly-linked list */
rec->prev = NULL;
if ( rec->next != NULL ) (rec->next)->prev = rec;
table[h] = rec;
rec->head = &(table[h]);
}
#ifdef __USE_PROTOS
Sym * zzs_get(char *key)
#else
Sym * zzs_get(key)
char *key;
#endif
{
register unsigned int h=0;
register char *p=key;
register Sym *q;
HASH(p, h);
for (q = table[h%size]; q != NULL; q = q->next)
{
if ( q->hash == h ) /* do we even have a chance of matching? */
if ( strcmp(key, q->symbol) == StrSame ) return( q );
}
return( NULL );
}
/*
* Unlink p from the symbol table. Hopefully, it's actually in the
* symbol table.
*
* If p is not part of a bucket chain of the symbol table, bad things
* will happen.
*
* Will do nothing if all list pointers are NULL
*/
#ifdef __USE_PROTOS
void zzs_del(Sym *p)
#else
void zzs_del(p)
register Sym *p;
#endif
{
if ( p == NULL ) {fprintf(stderr, "zzs_del(NULL)\n"); exit(1);}
if ( p->prev == NULL ) /* Head of list */
{
register Sym **t = p->head;
if ( t == NULL ) return; /* not part of symbol table */
(*t) = p->next;
if ( (*t) != NULL ) (*t)->prev = NULL;
}
else
{
(p->prev)->next = p->next;
if ( p->next != NULL ) (p->next)->prev = p->prev;
}
p->next = p->prev = NULL; /* not part of symbol table anymore */
p->head = NULL;
}
#ifdef __USE_PROTOS
void zzs_keydel(char *key)
#else
void zzs_keydel(key)
char *key;
#endif
{
Sym *p = zzs_get(key);
if ( p != NULL ) zzs_del( p );
}
/* S c o p e S t u f f */
/* Set current scope to 'scope'; return current scope if 'scope' == NULL */
#ifdef __USE_PROTOS
Sym ** zzs_scope(Sym **scope)
#else
Sym ** zzs_scope(scope)
Sym **scope;
#endif
{
if ( scope == NULL ) return( CurScope );
CurScope = scope;
return( scope );
}
/* Remove a scope described by 'scope'. Return pointer to 1st element in scope */
#ifdef __USE_PROTOS
Sym * zzs_rmscope(Sym **scope)
#else
Sym * zzs_rmscope(scope)
register Sym **scope;
#endif
{
register Sym *p;
Sym *start;
if ( scope == NULL ) return(NULL);
start = p = *scope;
for (; p != NULL; p=p->scope) { zzs_del( p ); }
*scope = NULL;
return( start );
}
#ifdef __USE_PROTOS
void zzs_stat(void)
#else
void zzs_stat()
#endif
{
static unsigned short count[20];
unsigned int i,n=0,low=0, hi=0;
register Sym **p;
float avg=0.0;
for (i=0; i<20; i++) count[i] = 0;
for (p=table; p<&(table[size]); p++)
{
register Sym *q = *p;
unsigned int len;
if ( q != NULL && low==0 ) low = p-table;
len = 0;
if ( q != NULL ) printf("[%d]", p-table);
while ( q != NULL )
{
len++;
n++;
printf(" %s", q->symbol);
q = q->next;
if ( q == NULL ) printf("\n");
}
if ( len>=20 ) printf("zzs_stat: count table too small\n");
else count[len]++;
if ( *p != NULL ) hi = p-table;
}
printf("Storing %d recs used %d hash positions out of %d\n",
n, size-count[0], size);
printf("%f %% utilization\n",
((float)(size-count[0]))/((float)size));
for (i=0; i<20; i++)
{
if ( count[i] != 0 )
{
avg += (((float)(i*count[i]))/((float)n)) * i;
printf("Buckets of len %d == %d (%f %% of recs)\n",
i, count[i], 100.0*((float)(i*count[i]))/((float)n));
}
}
printf("Avg bucket length %f\n", avg);
printf("Range of hash function: %d..%d\n", low, hi);
}
/*
* Given a string, this function allocates and returns a pointer to a
* symbol table record whose "symbol" pointer is reset to a position
* in the string table.
*/
#ifdef __USE_PROTOS
Sym * zzs_new(char *text)
#else
Sym * zzs_new(text)
char *text;
#endif
{
Sym *p;
if ( (p = (Sym *) calloc(1,sizeof(Sym))) == 0 )
{
fprintf(stderr,"Out of memory\n");
exit(1);
}
p->symbol = zzs_strdup(text);
return p;
}
/* create a new symbol table entry and add it to the symbol table */
#ifdef __USE_PROTOS
Sym * zzs_newadd(char *text)
#else
Sym * zzs_newadd(text)
char *text;
#endif
{
Sym *p = zzs_new(text);
if ( p != NULL ) zzs_add(text, p);
return p;
}
/* Add a string to the string table and return a pointer to it.
* Bump the pointer into the string table to next avail position.
*/
#ifdef __USE_PROTOS
char * zzs_strdup(char *s)
#else
char * zzs_strdup(s)
register char *s;
#endif
{
register char *start=strp;
while ( *s != '\0' )
{
if ( strp >= &(strings[strsize-2]) )
{
fprintf(stderr, "sym: string table overflow (%d chars)\n", strsize);
exit(-1);
}
*strp++ = *s++;
}
*strp++ = '\0';
return( start );
}

View File

@@ -0,0 +1,41 @@
/* T e m p l a t e F o r S y m b o l T a b l e M a n a g e r */
/* define some hash function */
#ifndef HASH
#define HASH(p, h) while ( *p != '\0' ) h = (h<<1) + *p++;
#endif
/* minimum symbol table record */
typedef struct _sym {
char *symbol;
struct _sym *next, *prev, **head, *scope;
unsigned int hash;
} Sym, *SymPtr;
#ifdef __USE_PROTOS
void zzs_init(int, int);
void zzs_done(void);
void zzs_add(char *, Sym *);
Sym *zzs_get(char *);
void zzs_del(Sym *);
void zzs_keydel(char *);
Sym **zzs_scope(Sym **);
Sym *zzs_rmscope(Sym **);
void zzs_stat(void);
Sym *zzs_new(char *);
Sym *zzs_newadd(char *);
char *zzs_strdup(char *);
#else
void zzs_init();
void zzs_done();
void zzs_add();
Sym *zzs_get();
void zzs_del();
void zzs_keydel();
Sym **zzs_scope();
Sym *zzs_rmscope();
void zzs_stat();
Sym *zzs_new();
Sym *zzs_newadd();
char *zzs_strdup();
#endif