From: Dennis Glatting Date: Thu, 24 Oct 1991 00:45:39 +0000 (+0000) Subject: Initial check in. Preliminary development stage. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4217c4568b6eb6c50946a9482df1e13389e0dc09;p=gcc.git Initial check in. Preliminary development stage. From-SVN: r46 --- diff --git a/gcc/objc/hash.c b/gcc/objc/hash.c new file mode 100644 index 00000000000..80719ce8058 --- /dev/null +++ b/gcc/objc/hash.c @@ -0,0 +1,237 @@ +/* -*-c-*- + * This file contains the hashing implementation. + * + $Header$ + $Author$ + $Date$ + $Log$ +*/ + + +#include +#include + +#include +#include +#include + + + /* Local forward decl. */ + u_int hashValue( Cache_t, void* ); + + +Cache_t hash_new( u_int numberOfBuckets ) { + + Cache_t retCache; + int i; + + + assert( numberOfBuckets ); + + /* Allocate the cache + structure. calloc() insures + its initialization for + default values. */ + retCache = calloc( 1, sizeof( Cache )); + assert( retCache ); + + /* Allocate the array of + buckets for the cache. + calloc() initializes all of + the pointers to NULL. */ + retCache->theNodeTable = calloc( numberOfBuckets, sizeof( CacheNode_t )); + assert( retCache->theNodeTable ); + + retCache->numberOfBuckets = numberOfBuckets; + + /* Calculate the number of + bits required to represent + the hash mask. */ + retCache->numberOfMaskBits = + ceil( log( retCache->numberOfBuckets ) / log( 2 )); + + /* Form a bit mask for the + hash. */ + for( i = 0; i < retCache->numberOfMaskBits; ++i ) + retCache->mask = ( retCache->mask << 1 ) | 0x01 ; + + assert( retCache->numberOfMaskBits ); + assert( retCache->mask ); + + return retCache; +} + + +void hash_delete( Cache_t theCache ) { + + void* aNode; + + + /* Purge all key/value pairs + from the table. */ + while( aNode = hash_next( theCache, NULL )) + hash_remove( theCache, aNode ); + + /* Release the array of nodes + and the cache itself. */ + free( theCache->theNodeTable ); + free( theCache ); +} + + +void hash_add( Cache_t theCache, void* aKey, void* aValue ) { + + u_int indx = hashValue( theCache, aKey ); + CacheNode_t aCacheNode = calloc( 1, sizeof( CacheNode )); + + + assert( aCacheNode ); + + /* Initialize the new node. */ + aCacheNode->theKey = aKey; + aCacheNode->theValue = aValue; + aCacheNode->nextNode = ( *theCache->theNodeTable )[ indx ]; + + /* Debugging. + + Check the list for another + key. */ +#ifdef DEBUG + { CacheNode_t checkHashNode = ( *theCache->theNodeTable )[ indx ]; + + while( checkHashNode ) { + + assert( checkHashNode->theKey != aKey ); + checkHashNode = checkHashNode->nextNode; + } + } + + /* Install the node as the + first element on the list. */ + ( *theCache->theNodeTable )[ indx ] = aCacheNode; + +#endif +} + + +void hash_remove( Cache_t theCache, void* aKey ) { + + u_int indx = hashValue( theCache, aKey ); + CacheNode_t aCacheNode = ( *theCache->theNodeTable )[ indx ]; + + + /* We assume there is an entry + in the table. Error if it + is not. */ + assert( aCacheNode ); + + /* Special case. First element + is the key/value pair to be + removed. */ + if( aCacheNode->theKey == aKey ) { + ( *theCache->theNodeTable )[ indx ] = aCacheNode->nextNode; + free( aCacheNode ); + } else { + /* Otherwise, find the hash + entry. */ + CacheNode_t prevHashNode = aCacheNode; + BOOL removed = NO; + + do { + + if( aCacheNode->theKey == aKey ) { + prevHashNode->nextNode = aCacheNode->nextNode, removed = YES; + free( aCacheNode ); + } else + prevHashNode = aCacheNode, aCacheNode = aCacheNode->nextNode; + } while( !removed && aCacheNode ); + assert( removed ); + } +} + + +void* hash_value_for_key( Cache_t theCache, void* aKey ) { + + u_int indx = hashValue( theCache, aKey ); + CacheNode_t aCacheNode = ( *theCache->theNodeTable )[ indx ]; + void* retVal = NULL; + + + if( aCacheNode ) { + BOOL found = NO; + + do { + if( aCacheNode->theKey == aKey ) + retVal = aCacheNode->theValue, found = YES; + else + aCacheNode = aCacheNode->nextNode; + } while( !found && aCacheNode ); + } + + return retVal; +} + + +CacheNode_t hash_next( Cache_t theCache, CacheNode_t aCacheNode ) { + + CacheNode_t theCacheNode = aCacheNode; + + + /* If the scan is being started + then reset the last node + visitied pointer and bucket + index. */ + if( !theCacheNode ) + theCache->lastBucket = 0; + + /* If there is a node visited + last then check for another + entry in the same bucket; + Otherwise step to the next + bucket. */ + if( theCacheNode ) + if( theCacheNode->nextNode ) + /* There is a node which + follows the last node + returned. Step to that node + and retun it. */ + return theCacheNode->nextNode; + else + ++theCache->lastBucket; + + /* If the list isn't exhausted + then search the buckets for + other nodes. */ + if( theCache->lastBucket < theCache->numberOfBuckets ) { + /* Scan the remainder of the + buckets looking for an entry + at the head of the list. + Return the first item + found. */ + while( theCache->lastBucket < theCache->numberOfBuckets ) + if(( *theCache->theNodeTable )[ theCache->lastBucket ]) + return ( *theCache->theNodeTable )[ theCache->lastBucket ]; + else + ++theCache->lastBucket; + + /* No further nodes were found + in the hash table. */ + return NULL; + } else + return NULL; +} + + +u_int hashValue( Cache_t theCache, void* aKey ) { + + u_int hash = 0; + int i; + + + assert( theCache->numberOfMaskBits ); + for( i = 0; i < ( sizeof( aKey ) * 8 ); i += theCache->numberOfMaskBits ) + hash ^= (( u_int )aKey ) >> i ; + + return ( hash & theCache->mask ) % theCache->numberOfBuckets; +} + diff --git a/gcc/objc/hash.h b/gcc/objc/hash.h new file mode 100644 index 00000000000..34c77dcfa3e --- /dev/null +++ b/gcc/objc/hash.h @@ -0,0 +1,134 @@ +/* -*-c-*- + * This is a general purpose hash object. + * + * The hash object used throughout the run-time + * is an integer hash. The key and data is of type + * void*. The hashing function converts the key to + * an integer and computes it hash value. + * + $Header$ + $Author$ + $Date$ + $Log$ +*/ + + +#ifndef _hash_INCLUDE_GNU +#define _hash_INCLUDE_GNU + + /* If someone is using a c++ + compiler then adjust the + types in the file back + to C. */ +#ifdef __cplusplus +extern "C" { +#endif + +#include + + +/* + * This data structure is used to hold items + * stored in a hash table. Each node holds + * a key/value pair. + * + * Items in the cache are really of type void*. + */ +typedef struct cache_node { + struct cache_node* nextNode; /* Pointer to next entry on + the list. NULL indicates + end of list. */ + void* theKey; /* Key used to locate the + value. Used to locate + value when more than one + key computes the same hash + value. */ + void* theValue; /* Value stored for the + key. */ +} CacheNode, *CacheNode_t; + + +/* + * This data structure is the cache. + * + * It must be passed to all of the hashing routines + * (except for new). + */ +typedef struct cache { + /* + * Variables used to implement the + * hash itself. + */ + CacheNode_t (* theNodeTable )[]; /* Pointer to an array of + hash nodes. */ + u_int numberOfBuckets, /* Number of buckets + allocated for the hash + table (number of array + entries allocated for + "theCache"). */ + mask, /* Mask used when computing + a hash value. The number + of bits set in the mask + is contained in the next + member variable. */ + numberOfMaskBits; /* Number of bits used for + the mask. Useful for + efficient hash value + calculation. */ + /* + * Variables used to implement indexing + * through the hash table. + */ + u_int lastBucket; /* Tracks which entry in the + array where the last value + was returned. */ +} Cache, *Cache_t; + + + /* Prototypes for hash + functions. */ + /* Allocate and initialize + a hash table. Hash table + size taken as a parameter. + A value of 0 is not + allowed. */ +Cache_t hash_new( u_int numberOfBuckets ); + /* Deallocate all of the + hash nodes and the cache + itself. */ +void hash_delete( Cache_t theCache ); + /* Add the key/value pair + to the hash table. assert() + if the key is already in + the hash. */ +void hash_add( Cache_t theCache, void* aKey, void* aValue ); + /* Remove the key/value pair + from the hash table. + assert() if the key isn't + in the table. */ +void hash_remove( Cache_t theCache, void* aKey ); + /* Given key, return its + value. Return NULL if the + key/value pair isn't in + the hash. */ +void* hash_value_for_key( Cache_t theCache, void* aKey ); + /* Used to index through the + hash table. Start with NULL + to get the first entry. + + Successive calls pass the + value returned previously. + ** Don't modify the hash + during this operation *** + + Cache nodes are returned + such that key or value can + ber extracted. */ +CacheNode_t hash_next( Cache_t theCache, CacheNode_t aCacheNode ); + + +#ifdef __cplusplus +} +#endif + +#endif