diff options
Diffstat (limited to 'Build/source/texk/kpathsea/win32hash.c')
-rw-r--r-- | Build/source/texk/kpathsea/win32hash.c | 760 |
1 files changed, 0 insertions, 760 deletions
diff --git a/Build/source/texk/kpathsea/win32hash.c b/Build/source/texk/kpathsea/win32hash.c deleted file mode 100644 index 1c1252b3797..00000000000 --- a/Build/source/texk/kpathsea/win32hash.c +++ /dev/null @@ -1,760 +0,0 @@ -/* hash.c: hash table operations. - -Copyright (C) 1994, 95, 96, 97, 98, 99, 2000 Karl Berry & Olaf Weber. - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -#include <kpathsea/config.h> -#include <kpathsea/c-ctype.h> - -#include <kpathsea/hash.h> -#include <kpathsea/str-list.h> - -#ifdef HAVE_GETURL -#include <kpathsea/remote.h> -#endif - -/* The hash function. We go for simplicity here. */ - -/* All our hash tables are related to filenames. */ -#ifdef MONOCASE_FILENAMES -#if defined(WIN32) && !defined(__i386_pc_gnu__) -/* This is way faster under Win32. */ -#define TRANSFORM(x) ((unsigned)CharLower((LPTSTR)(BYTE)(x))) -#else -#define TRANSFORM(x) (tolower(x)) -#endif -#else -#define TRANSFORM(x) (x) -#endif - -#define MAX_HASH_TABLES 64 - -#define HASH_NULL(ptr) (ptr == hash_memory) -#define HASH_PTR(ptr) ((char *)hash_memory + (unsigned long)(ptr)) -#define HASH_REL(rel) ((unsigned long)((char *)(rel) - (char *)hash_memory)) -#define HASH_BUCKETS(table, n) (*((hash_element_type **)((char *)hash_memory + (unsigned long)table->buckets + (n) * sizeof(hash_element_type *)))) -/* #define HASH_BUCKETS(table, n) *((hash_element_type **)(HASH_PTR((unsigned long) ((hash_element_type **)HASH_PTR(table->buckets))[n]))) */ -HANDLE hash_handle = 0; -void *hash_memory = NULL; -static unsigned long hash_memory_allocated = 0; -unsigned long hash_memory_size = 8L*1024L*1024L; - -typedef struct _hash_memory_description { - unsigned long sig; - unsigned long memory_size; - unsigned long first_free_address; - unsigned long hash_offsets[MAX_HASH_TABLES]; - unsigned long db_dir_list_len; - unsigned long db_dir_list; -} hash_memory_description; - -hash_memory_description *hash_bloc; - -/* We need to protect initialisation and insert / lookup */ -static HANDLE hash_mutex; -static boolean hash_init_done = false; - -extern str_list_type db_dir_list; - -void hash_restore_str_list(unsigned long ptr, unsigned len, str_list_type *l); -void hash_save_str_list(str_list_type l); - -#if 0 -extern unsigned hash P2H(hash_table_type *table, const_string key); -#ifdef NORMALIZED -extern unsigned hash_normalized P2H(hash_table_type *table, const_string key); -#endif -#else -static unsigned -hash P2C(hash_table_type *, table, const_string, key) -{ - unsigned n = 0; - - // fprintf(stderr, "Hashing %s to ", key); - - /* Our keys aren't often anagrams of each other, so no point in - weighting the characters. */ - while (*key != 0) - n = (n + n + TRANSFORM (*key++)) % table->size; - - // fprintf(stderr, "%d\n", n); - - return n; -} - -#ifdef NORMALIZED -/* Identical has function as above, but does not normalize keys. */ -static unsigned -hash_normalized P2C(hash_table_type *, table, const_string, key) -{ - unsigned n = 0; - - // fprintf(stderr, "Hashing (normalized) %s to ", key); - - /* Our keys aren't often anagrams of each other, so no point in - weighting the characters. */ - while (*key != 0) - n = (n + n + (*key++)) % table->size; - - // fprintf(stderr, "%d\n", n); - - return n; -} -#endif -#endif - -/* - This function will be registered by atexit() to be called upon - program termination. It will free resources allocated for - hash-tables. It has to be registered only once, when the very first - hash-table is allocated. -*/ -void CDECL -hash_cleanup (void) -{ -#ifdef HAVE_GETURL - cleanup_remote_files(); -#endif - - if (hash_memory != NULL) { - if (UnmapViewOfFile(hash_memory) == 0) { - /* Report an error */ - WARNING2("Can't UnMapViewOfFile(%x) (Error %d)!\n", hash_memory, GetLastError()); - } - hash_memory = NULL; - } - - if (hash_handle) { - if (CloseHandle(hash_handle) == 0) { - /* Report an error */ - WARNING2("Can't CloseHandle(%x) (Error %d)!\n", hash_handle, GetLastError()); - } - hash_handle = NULL; - } - - if (hash_mutex) { - if (CloseHandle(hash_mutex) == 0) { - /* Report an error */ - WARNING2("Can't CloseHandle(%x) (Error %d)!\n", hash_mutex, GetLastError()); - } - hash_mutex = NULL; - } - -#ifdef KPSE_DEBUG - if (KPSE_DEBUG_P (KPSE_DEBUG_SHM)) - DEBUGF1("Cleaned up shared hash tables, %ld memory was allocated.\n", hash_memory_allocated); -#endif -} - -KPSEDLL boolean hash_init_needed = false; - -boolean -hash_lock(boolean force) -{ - int dwWaitResult; - - if (!force && !hash_init_done) - return true; - - /* Request ownership of mutex. */ - dwWaitResult = WaitForSingleObject(hash_mutex, 25000L); - - switch (dwWaitResult) { - /* The thread got mutex ownership. */ - case WAIT_OBJECT_0: - return true; - - /* Cannot get mutex ownership due to time-out. */ - case WAIT_TIMEOUT: - WARNING("Timeout waiting to lock shared memory access!\n"); - return false; - - /* Got ownership of the abandoned mutex object. */ - case WAIT_ABANDONED: - WARNING("Waiting to lock shared memory access abandoned!\n"); - return false; - } - - return false; -} - -void -hash_unlock(void) -{ - if (! hash_init_done) - return; - - if (ReleaseMutex(hash_mutex) == 0) { - FATAL2("%s: Can't ReleaseMutex() access to shared memory databases (Error %d)!\n", kpse_program_name, GetLastError()); - } -} - -static void -hash_start_init() -{ -#ifdef KPSE_DEBUG - if (KPSE_DEBUG_P (KPSE_DEBUG_SHM)) - DEBUGF1("%s: Start of shared hash tables initialisation.\n", kpse_program_name); -#endif - hash_lock(true); -} - -void -hash_end_init() -{ - hash_init_done = true; - hash_unlock(); - -#ifdef KPSE_DEBUG - if (KPSE_DEBUG_P (KPSE_DEBUG_SHM)) - DEBUGF1("%s: End of shared hash tables initialisation.\n", kpse_program_name); -#endif -} - -void -hash_init (void) -{ - SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; - - hash_init_done = false; - if ((hash_mutex = CreateMutex(NULL, FALSE, "kpse_initialization")) == 0) { - FATAL1("Can't CreateMutex() for shared memory locking (Error %d)!\n", GetLastError()); - } - - if ((hash_handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, TRUE, HASH_MAPPING_NAME)) == 0) { - - hash_start_init(); - - /* First call, need to allocate memory. */ - if ((hash_handle = CreateFileMapping(INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE, - 0, hash_memory_size, HASH_MAPPING_NAME)) == 0) { - /* Report an error. */ - FATAL2("Can't CreateFileMapping() of size %ul (Error %d)!\n", hash_memory_size, GetLastError()); - }; - atexit(hash_cleanup); - hash_init_needed = true; - } - - if ((hash_memory = MapViewOfFile(hash_handle, FILE_MAP_ALL_ACCESS, 0, 0, 0)) == NULL) { - /* Report an error. */ - FATAL2("Can't MapViewOfFile(%x) (Error %d)!\n", hash_handle, GetLastError()); - } - - hash_bloc = (hash_memory_description *)hash_memory; - if (hash_init_needed) { - /* Is it more efficient to zero the whole block first ? */ - ZeroMemory(hash_memory, sizeof(hash_bloc)); - hash_bloc->sig = sizeof(hash_memory_description); - hash_bloc->memory_size = hash_memory_size; - hash_bloc->first_free_address = sizeof(hash_memory_description); - } - else { - extern boolean first_search; - - hash_start_init(); - -#ifdef KPSE_DEBUG - if (KPSE_DEBUG_P (KPSE_DEBUG_SHM)) - DEBUGF1("Reusing shared hash tables at %x.\n", hash_memory); -#endif - - assert(hash_bloc->sig == sizeof(hash_memory_description)); - /* - We could be a little bit cleaner here, just - relying on the hashtable_instances enumeration. - */ - cnf_hash = (hash_table_type *)hash_exists_p(hashtable_cnf); - db = (hash_table_type *)hash_exists_p(hashtable_db); - alias_db = (hash_table_type *)hash_exists_p(hashtable_alias); - map = (hash_table_type *)hash_exists_p(hashtable_map); - link_table = (hash_table_type *)hash_exists_p(hashtable_links); - remote_db = (hash_table_type *)hash_exists_p(hashtable_remote); - - db_dir_list = str_list_init(); - /* Awful kludge ! */ - first_search = false; - hash_restore_str_list(hash_bloc->db_dir_list, hash_bloc->db_dir_list_len, &db_dir_list); - - } -} - -void -hash_reinit() -{ - if (!hash_init_needed) { - fprintf(stderr, "%s: your `ls-R' database files have been modified\n", kpse_program_name); - fprintf(stderr, "while kpathsea Dll was loaded by other programs.\n"); - fprintf(stderr, "It is recommended that you terminate all of them.\n"); - fprintf(stderr, "in order to reinitialize the shared databases.\n"); - } -} - -boolean -hash_extend_memory () -{ - /* We need to allocate a new memory bloc twice the size - of the previous one, copy everything and free the previous block. - */ - SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; - HANDLE new_hash_handle = 0; - void *new_hash_memory = NULL; - unsigned long new_hash_memory_size = 2 * hash_memory_size; - - assert(hash_memory != NULL); - - /* First, create some private unnamed bloc */ - if ((new_hash_handle = CreateFileMapping(INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE, - 0, new_hash_memory_size, NULL)) == 0) { - /* Report an error. */ - FATAL2("Can't CreateFileMapping() of size %ul (Error %d)!\n", new_hash_memory_size, GetLastError()); - }; - - if ((new_hash_memory = MapViewOfFile(new_hash_handle, FILE_MAP_ALL_ACCESS, 0, 0, 0)) == NULL) { - /* Report an error. */ - FATAL2("Can't MapViewOfFile(%x) (Error %d)!\n", new_hash_handle, GetLastError()); - } - /* Copy the data */ - CopyMemory(new_hash_memory, hash_memory, hash_memory_size); - /* Cleanup handles */ - hash_cleanup(); - /* make the values point to the new bloc */ - hash_memory_size = new_hash_memory_size; - hash_memory = new_hash_memory; - hash_handle = new_hash_handle; - - /* Now, create the actual named, shareable bloc */ - if ((new_hash_handle = CreateFileMapping(INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE, - 0, hash_memory_size, HASH_MAPPING_NAME)) == 0) { - /* Report an error. */ - FATAL2("Can't CreateFileMapping() of size %ul (Error %d)!\n", new_hash_memory_size, GetLastError()); - }; - - if ((new_hash_memory = MapViewOfFile(new_hash_handle, FILE_MAP_ALL_ACCESS, 0, 0, 0)) == NULL) { - /* Report an error. */ - FATAL2("Can't MapViewOfFile(%x) (Error %d)!\n", new_hash_handle, GetLastError()); - } - /* Copy the data */ - CopyMemory(new_hash_memory, hash_memory, hash_memory_size); - /* Cleanup the handles */ - hash_cleanup(); - - hash_memory = new_hash_memory; - hash_handle = new_hash_handle; - hash_bloc = (hash_memory_description *)hash_memory; - - return true; -} - -unsigned long -hash_malloc P1C(unsigned, size) -{ - unsigned long ret = hash_bloc->first_free_address; - hash_bloc->first_free_address += size; - - if ((unsigned long)hash_bloc->first_free_address > (unsigned long)hash_bloc->memory_size) { - if (! hash_extend_memory()) { - fprintf(stderr, "Memory exhausted: base = %x, first_free_address = %x, size = %x\n", - hash_memory, hash_bloc->first_free_address, hash_bloc->memory_size); - } - } - assert((unsigned long)hash_bloc->first_free_address < (unsigned long)hash_bloc->memory_size); - - hash_memory_allocated += size; - - return ret; -} - -unsigned long -hash_strdup P1C(const_string, p) -{ - unsigned long q = hash_malloc(strlen(p)+1); - memcpy(HASH_PTR(q), p, strlen(p)+1); - return q; -} - -void -hash_free P1C(void *, address) -{ - /* Don't want to play with this for the moment. - Hash-Tables just grow up, no need to remove - anything from them. The `hash_remove' function - is only called from contrib/variables.c . - */ -} - -void -hash_save_str_list(str_list_type l) -{ - unsigned int i; - unsigned long *q; - assert(hash_bloc != NULL); - hash_bloc->db_dir_list_len = STR_LIST_LENGTH(l); - - if (hash_bloc->db_dir_list_len == 0) return; - - hash_bloc->db_dir_list = hash_malloc(hash_bloc->db_dir_list_len * sizeof(unsigned long)); - for (i = 0, q = (unsigned long *)HASH_PTR(hash_bloc->db_dir_list); - i < hash_bloc->db_dir_list_len; - i++, q++) { - *q = hash_strdup(STR_LIST_ELT(l, i)); - } -} - -void -hash_restore_str_list(unsigned long ptr, unsigned len, str_list_type *l) -{ - int i; - unsigned long *q; - for (i = 0, q = (unsigned long *)HASH_PTR(ptr); - i < len; - i++, q++) { - str_list_add (l, HASH_PTR(*q)); - } -#if 0 - fprintf(stderr, "Restored db_dir_list :\n"); - for (i = 0; i < STR_LIST_LENGTH(*l); i++) { - fprintf(stderr, "\t%s\n", STR_LIST_ELT(*l, i)); - } -#endif -} - -hash_table_type * -hash_exists_p P1C(hashtable_instances, hash_number) -{ - unsigned long rel; - - assert(hash_memory != NULL); - assert(hash_bloc != NULL); - -#if 0 - fprintf(stderr, "Looking up for table %d ... ", hash_number); -#endif - if (hash_bloc) { - if (rel = hash_bloc->hash_offsets[hash_number]) { -#if 0 - fprintf(stderr, "found (%x) for %d\n", (char *)hash_memory + rel, hash_number); -#endif - return (hash_table_type *)((char *)hash_memory + rel); - } - } -#if 0 - fprintf(stderr, "found (null) for %d\n", hash_number); -#endif - return NULL; -} - -hash_table_type * -hash_create P2C(unsigned, size, hashtable_instances, hash_number) -{ - /* hash_table_type ret; changed into "static ..." to work around gcc - optimizer bug for Alpha. */ - static hash_table_type *ret; - unsigned b; - - if (hash_memory == NULL) { - hash_init(); - } - - if (ret = hash_exists_p(hash_number)) { - assert(size == ret->size); - return ret; - } - - hash_lock(false); - -#ifdef KPSE_DEBUG - if (KPSE_DEBUG_P (KPSE_DEBUG_SHM)) - DEBUGF2("Hash: creating shared hash table %u of size %u\n", hash_number, size); -#endif - - hash_bloc->hash_offsets[hash_number] = hash_malloc(sizeof(hash_table_type)); - ret = (hash_table_type *)HASH_PTR(hash_bloc->hash_offsets[hash_number]); - - ret->buckets = (hash_element_type **)hash_malloc(size * sizeof(hash_element_type *)); - ret->size = size; - - /* calloc's zeroes aren't necessarily NULL, so be safe. */ - for (b = 0; b <ret->size; b++) - HASH_BUCKETS(ret, b) = NULL; - - hash_unlock(); - - return ret; -} - -#if 0 -/* Not really usable. */ -hash_table_type * -hash_reset P1C(hashtable_instances, hash_number) -{ - /* hash_table_type ret; changed into "static ..." to work around gcc - optimizer bug for Alpha. */ - static hash_table_type *ret; - unsigned b; - - if (hash_memory == NULL - || (ret = hash_exists_p(hash_number)) == NULL) { - return NULL; - } - - hash_lock(false); - -#ifdef KPSE_DEBUG - if (KPSE_DEBUG_P (KPSE_DEBUG_SHM)) - DEBUGF1("Hash: resetting shared hash table %u\n", hash_number); -#endif - - /* calloc's zeroes aren't necessarily NULL, so be safe. */ - for (b = 0; b <ret->size; b++) - HASH_BUCKETS(ret, b) = NULL; - - hash_unlock(); - - return ret; -} - -#endif -/* WARNING: the comment below is frightening ! - However, it does not seem to be the case that the strings - are changed after being inserted in the map. - IHMO, this should be strictly forbidden. -*/ -/* Whether or not KEY is already in MAP, insert it and VALUE. Do not - duplicate the strings, in case they're being purposefully shared. */ - -void -hash_insert P3C(hash_table_type *, table, const_string, key, - const_string, value) -{ - - unsigned n = hash (table, key); - unsigned long new_elt; - - hash_lock(false); - - new_elt = hash_malloc(sizeof(hash_element_type)); - - ((hash_element_type *)(HASH_PTR(new_elt)))->key = (const_string)hash_strdup(key); - ((hash_element_type *)(HASH_PTR(new_elt)))->value = (const_string)hash_strdup(value); - ((hash_element_type *)(HASH_PTR(new_elt)))->next = NULL; - - /* Insert the new element at the end of the list. */ - if (! HASH_BUCKETS(table, n)) - /* first element in bucket is a special case. */ - HASH_BUCKETS(table, n) = (hash_element_type *)new_elt; - else - { - hash_element_type *loc = (hash_element_type *)HASH_PTR(HASH_BUCKETS(table, n)); - while (loc->next) /* Find the last element. */ - loc = (hash_element_type *)HASH_PTR(loc->next); - loc->next = (hash_element_type *)new_elt; /* Insert the new one after. */ - } - - hash_unlock(); -} - -#ifdef NORMALIZED -/* Same as above, for normalized keys. */ -void -hash_insert_normalized P3C(hash_table_type *, table, - const_string, key, - const_string, value) -{ - unsigned n = hash_normalized (table, key); - unsigned long new_elt; - - hash_lock(false); - - new_elt = hash_malloc(sizeof(hash_element_type)); - - ((hash_element_type *)(HASH_PTR(new_elt)))->key = (const_string)hash_strdup(key); - ((hash_element_type *)(HASH_PTR(new_elt)))->value = (const_string)hash_strdup(value); - ((hash_element_type *)(HASH_PTR(new_elt)))->next = NULL; - - /* Insert the new element at the end of the list. */ - if (! HASH_BUCKETS(table, n)) - /* first element in bucket is a special case. */ - HASH_BUCKETS(table, n) = (hash_element_type *)new_elt; - else - { - hash_element_type *loc = (hash_element_type *)HASH_PTR(HASH_BUCKETS(table, n)); - while (loc->next) /* Find the last element. */ - loc = (hash_element_type *)HASH_PTR(loc->next); - loc->next = (hash_element_type *)new_elt; /* Insert the new one after. */ - } - - hash_unlock(); -} -#endif /* WIN32*/ - -/* Remove a (KEY, VALUE) pair. */ - -void -hash_remove P3C(hash_table_type *, table, const_string, key, - const_string, value) -{ - hash_element_type *p; - hash_element_type *q; - unsigned n = hash (table, key); - - hash_lock(false); - - /* Find pair. */ - for (q = NULL, p = (hash_element_type *)HASH_PTR(HASH_BUCKETS(table, n)); ! HASH_NULL(p); q = p, p = (hash_element_type *)HASH_PTR(p->next)) - if (FILESTRCASEEQ (key, HASH_PTR(p->key)) && STREQ (value, HASH_PTR(p->value))) - break; - if (p) { - /* We found something, remove it from the chain. */ - if (q) q->next = p->next; else HASH_BUCKETS(table, n) = p->next; - /* We cannot dispose of the contents. */ - hash_free ((void *)HASH_REL(p)); - } - - hash_unlock(); -} - -/* Look up STR in MAP. Return a (dynamically-allocated) list of the - corresponding strings or NULL if no match. */ - -#ifdef KPSE_DEBUG -/* Print the hash values as integers if this is nonzero. */ -boolean kpse_debug_hash_lookup_int = false; -#endif - -string * -hash_lookup P2C(hash_table_type *, table, const_string, key) -{ - hash_element_type *p; - str_list_type ret; - unsigned n = hash (table, key); - - ret = str_list_init (); - - hash_lock(false); - - /* Look at everything in this bucket. */ - for (p = (hash_element_type *)HASH_PTR(HASH_BUCKETS(table, n)); ! HASH_NULL(p); p = (hash_element_type *)HASH_PTR(p->next)) - if (FILESTRCASEEQ (key, HASH_PTR(p->key))) - /* Cast because the general str_list_type shouldn't force const data. */ - str_list_add (&ret, (string) xstrdup((string)HASH_PTR(p->value))); - - /* If we found anything, mark end of list with null. */ - if (STR_LIST (ret)) - str_list_add (&ret, NULL); - -#ifdef KPSE_DEBUG - if (KPSE_DEBUG_P (KPSE_DEBUG_HASH)) - { - DEBUGF1 ("hash_shared_lookup(%s) =>", key); - if (!STR_LIST (ret)) - fputs (" (nil)\n", stderr); - else - { - string *r; - for (r = STR_LIST (ret); *r; r++) - { - putc (' ', stderr); - if (kpse_debug_hash_lookup_int) - fprintf (stderr, "%ld", (long) *r); - else - fputs (*r, stderr); - } - putc ('\n', stderr); - } - fflush (stderr); - } -#endif - - hash_unlock(); - - return STR_LIST (ret); -} - -/* We only print nonempty buckets, to decrease output volume. */ - -void -hash_print P2C(hash_table_type *, table, boolean, summary_only) -{ - unsigned b; - unsigned total_elements = 0, total_buckets = 0; - - if (table == NULL) return; - - hash_lock(false); - - for (b = 0; b < table->size; b++) { - hash_element_type *bucket = (hash_element_type *)HASH_PTR(HASH_BUCKETS(table, b)); - - if (! HASH_NULL(bucket)) { - unsigned len = 1; - hash_element_type *tb; - - total_buckets++; - if (!summary_only) fprintf (stderr, "%4d ", b); - - for (tb = (hash_element_type *)HASH_PTR(bucket->next); ! HASH_NULL(tb); tb = (hash_element_type *)HASH_PTR(tb->next)) - len++; - if (!summary_only) fprintf (stderr, ":%-5d", len); - total_elements += len; - - if (!summary_only) { - for (tb = bucket; ! HASH_NULL(tb); tb = (hash_element_type *)HASH_PTR(tb->next)) - fprintf (stderr, " %s=>%s", HASH_PTR(tb->key), HASH_PTR(tb->value)); - putc ('\n', stderr); - } - } - } - - hash_unlock(); - - fprintf (stderr, - "%u buckets, %u nonempty (%u%%); %u entries, average chain %.1f.\n", - table->size, - total_buckets, - 100 * total_buckets / table->size, - total_elements, - total_buckets ? total_elements / (double) total_buckets : 0.0); -} - -/* Simple iterator over hash-table elements */ -void -hash_iter P2C(hash_table_type *, table, hash_iter_fn, fn) -{ - unsigned b; - - if (! table) return; - - hash_lock(false); - - for (b = 0; b < table->size; b++) { - hash_element_type *bucket = (hash_element_type *)HASH_PTR(HASH_BUCKETS(table, b)); - if (! HASH_NULL(bucket)) { - unsigned len = 1; - hash_element_type *tb; - for (tb = bucket; ! HASH_NULL(tb); tb = (hash_element_type *)HASH_PTR(tb->next)) { -#ifdef KPSE_DEBUG - if (KPSE_DEBUG_P (KPSE_DEBUG_HASH)) - { - DEBUGF2("applying (shared) fn to %s%s\n", HASH_PTR(tb->value), HASH_PTR(tb->key)); - } -#endif - (*fn)(HASH_PTR(tb->key), HASH_PTR(tb->value)); - } - } - } - - hash_unlock(); -} |