home *** CD-ROM | disk | FTP | other *** search
- /* File: symbol.c
-
- Symbol table manager.
- */
-
- #include "all.h"
- #include "cvr.h"
-
- static int gensymworking;
- static long int gensymnum;
-
- /* This is the table of symbol strings. Each used symbol string should
- occur here exactly once, so that a compare on equal names is
- simplified to comparing the pointers to the strings. This must be
- ensured by the routines 'addsymbol()' and 'gensymbol()'.
- */
- static symbol symtab[HASHWIDTH];
-
- /* The hashing function:
- Return a value in the range 0..HASHWIDTH-1.
-
- Current hashing function:
- Add all characters in the given string and shift one position
- after each addition.
- */
- static unsigned int hash( s )
- register char *s;
- {
- register unsigned int sum = 0;
-
- while( *s != '\0' ){
- sum += *s++;
- sum <<= 1;
- }
- return( sum % HASHWIDTH );
- }
-
- /* make a new storage space for a symbol */
- static symbol newsymbol( l, s )
- symbol l;
- char *s;
- {
- register symbol new;
-
- new = (symbol) ckmalloc( (unsigned int) sizeof(*new) );
- new->next = l;
- new->symstr = s;
- new->priority = 2;
- return( new );
- }
-
- /* Try to locate string 'name' in the given list 'list'.
-
- If the name occurs in the list, a pointer to the entry is returned,
- else symbolNIL is returned.
- */
- static symbol dofindsymbol( name, list )
- register char *name;
- register symbol list;
- {
-
- while( list != symbolNIL ){
- if( strcmp( list->symstr, name ) == 0 ) return( list );
- list = list->next;
- }
- return( symbolNIL );
- }
-
- /* Search the symbol table for the given symbol.
- If the name occurs in the table, a pointer to the entry is returned,
- else symbolNIL is returned.
- */
- symbol findsymbol( name )
- register char *name;
- {
- register symbol entry;
- unsigned int hashval;
-
- hashval = hash( name );
- entry = dofindsymbol( name, symtab[hashval] );
- return( entry );
- }
-
- /* Add string 'name' to the symbol table.
- If the name already occurs in the table, a pointer to the old
- entry is returned, else a new entry is added, and a pointer to this
- new entry is returned.
-
- This routine must ensure that for all symbols with the same name,
- the same pointer is returned.
- */
- symbol addsymbol( name )
- register char *name;
- {
- register symbol entry;
- unsigned int hashval;
-
- if( gensymworking ){
- fprintf(
- stderr,
- "You can't add symbols after using gensymbol() (name = '%s')\n",
- name
- );
- exit( 1 );
- }
- hashval = hash( name );
- entry = dofindsymbol( name, symtab[hashval] );
- if( entry != symbolNIL ) return( entry );
- entry = newsymbol( symtab[hashval], new_string( name ) );
- symtab[hashval] = entry;
- return( entry );
- }
-
- /* given a prefix 'pre', generate a new symbol with an unique name.
-
- This is done by systematically generating names of the form
- <pre><number> until a name is found that doesn't occur in the
- list.
-
- To ensure that the symbol remains unique, the flag 'gensymworking'
- is set after the first symbol has been generated. After that it is
- an error to add new symbols to the table using 'addsymbol()'.
- */
- symbol gensymbol( pre )
- char *pre;
- {
- unsigned int hashval;
- register char *name;
- register symbol entry;
-
- name = new_string( pre );
- name = ckrealloc( name, (unsigned int) strlen( pre ) + 30 );
- for(;;){
- (void) sprintf( name, "%s%ld", pre, gensymnum++ );
- hashval = hash( name );
- if( dofindsymbol( name, symtab[hashval] ) == symbolNIL ) break;
- }
- entry = newsymbol( symtab[hashval], name );
- entry->priority = 0;
- symtab[hashval] = entry;
- return( entry );
- }
-
- /* initalize symbol routines */
- void initsymbol(){
- register int i;
-
- for( i=0; i<HASHWIDTH; i++ ){
- symtab[i] = symbolNIL;
- }
- gensymworking = FALSE;
- gensymnum = 0;
- }
-
- /* flush symbol routines */
- void flushsymbol(){
- symbol s;
- symbol n;
- register int i;
-
- for( i=0; i<HASHWIDTH; i++ ){
- s = symtab[i];
- while( s != symbolNIL ){
- n = s->next;
- free( s->symstr );
- free( (char *) s );
- s = n;
- }
- symtab[i] = symbolNIL;
- }
- gensymworking = FALSE;
- gensymnum = 0;
- }
-