NetBSD/gnu/usr.bin/awk/hash.c

230 lines
4.3 KiB
C

/********************************************
hash.c
copyright 1991, Michael D. Brennan
This is a source file for mawk, an implementation of
the AWK programming language.
Mawk is distributed without warranty under the terms of
the GNU General Public License, version 2, 1991.
********************************************/
/* $Log: hash.c,v $
/* Revision 1.2 1993/07/02 23:57:26 jtc
/* Updated to mawk 1.1.4
/*
* Revision 5.1 1991/12/05 07:56:05 brennan
* 1.1 pre-release
*
*/
/* hash.c */
#include "mawk.h"
#include "memory.h"
#include "symtype.h"
unsigned hash(s)
register char *s ;
{ register unsigned h = 0 ;
while ( *s ) h += h + *s++ ;
return h ;
}
typedef struct hash {
struct hash *link ;
SYMTAB symtab ;
} HASHNODE ;
static HASHNODE *PROTO( delete, (char *) ) ;
#define new_HASHNODE() (HASHNODE *) zmalloc(sizeof(HASHNODE))
static HASHNODE *hash_table[HASH_PRIME] ;
/*
* insert -- s is not there and need not be duplicated
* -- used during initialization
*/
SYMTAB *insert(s)
char *s ;
{ register HASHNODE *p = new_HASHNODE();
register unsigned h ;
p->link = hash_table[h = hash(s) % HASH_PRIME ] ;
p->symtab.name = s ;
hash_table[h] = p ;
return &p->symtab ;
}
/*
* find -- s might be there, find it else insert and dup
* s
*/
SYMTAB *find(s)
char *s ;
{ register HASHNODE *p ;
HASHNODE *q ;
unsigned h ;
p = hash_table[h = hash(s) % HASH_PRIME ] ;
q = (HASHNODE *) 0 ;
while ( 1 )
{ if ( !p )
{ p = new_HASHNODE() ;
p->symtab.type = ST_NONE ;
p->symtab.name = strcpy(zmalloc( strlen(s)+1 ), s) ;
break ;
}
if ( strcmp(p->symtab.name, s) == 0 ) /* found */
if ( !q ) /* already at the front */
return &p->symtab ;
else /* delete from the list */
{ q->link = p->link ; break ; }
q = p ; p = p->link ;
}
/* put p on front of the list */
p->link = hash_table[h] ;
hash_table[h] = p ;
return & p->symtab ;
}
/* remove a node from the hash table
return a ptr to the node */
static unsigned last_hash ;
static HASHNODE *delete( s )
char *s ;
{ register HASHNODE *p ;
HASHNODE *q = (HASHNODE *) 0 ;
unsigned h ;
p = hash_table[ last_hash = h = hash(s) % HASH_PRIME ] ;
while ( p )
if ( strcmp(p->symtab.name, s) == 0 ) /* found */
{
if ( q ) q->link = p->link ;
else hash_table[h] = p->link ;
return p ;
}
else { q = p ; p = p->link ; }
#ifdef DEBUG /* we should not ever get here */
bozo("delete") ;
#endif
return (HASHNODE *) 0 ;
}
/* when processing user functions, global ids which are
replaced by local ids are saved on this list */
static HASHNODE *save_list ;
/* store a global id on the save list,
return a ptr to the local symtab */
SYMTAB *save_id( s )
char *s ;
{ HASHNODE *p, *q ;
unsigned h ;
p = delete(s) ;
q = new_HASHNODE() ;
q->symtab.type = ST_LOCAL_NONE ;
q->symtab.name = p->symtab.name ;
/* put q in the hash table */
q->link = hash_table[ h = last_hash ] ;
hash_table[h] = q ;
/* save p */
p->link = save_list ; save_list = p ;
return & q->symtab ;
}
/* restore all global indentifiers */
void restore_ids()
{ register HASHNODE *p, *q ;
register unsigned h ;
q = save_list ; save_list = (HASHNODE *) 0 ;
while ( q )
{
p = q ; q = q->link ;
zfree( delete(p->symtab.name) , sizeof(HASHNODE) ) ;
p->link = hash_table[h = last_hash ] ;
hash_table[h] = p ;
}
}
/* search the symbol table backwards for the
disassembler. This is slow -- so what
*/
#if ! SM_DOS
char *reverse_find( type, ptr)
int type ;
PTR ptr ;
{
CELL *cp ;
ARRAY array ;
static char uk[] = "unknown" ;
int i ;
HASHNODE *p ;
switch( type )
{
case ST_VAR :
case ST_FIELD :
cp = *(CELL **) ptr ;
break ;
case ST_ARRAY :
array = *(ARRAY *) ptr ;
break ;
default : return uk ;
}
for(i = 0 ; i < HASH_PRIME ; i++)
{
p = hash_table[i] ;
while ( p )
{
if ( p->symtab.type == type )
switch(type)
{
case ST_VAR :
case ST_FIELD :
if ( cp == p->symtab.stval.cp )
return p->symtab.name ;
break ;
case ST_ARRAY :
if ( array == p->symtab.stval.array )
return p->symtab.name ;
break ;
}
p = p->link ;
}
}
return uk ;
}
#endif