/* hash.c -- hash table routines Copyright (C) 1993, 94 Free Software Foundation, Inc. Written by Steve Chamberlain This file was lifted from BFD, the Binary File Descriptor library. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config.h" #include "system.h" #include "hash.h" #include "obstack.h" #include "gansidecl.h" #include "toplev.h" /* Obstack allocation and deallocation routines. */ #define obstack_chunk_alloc xmalloc #define obstack_chunk_free free extern char * xmalloc (); /* The default number of entries to use when creating a hash table. */ #define DEFAULT_SIZE (1009) /* Create a new hash table, given a number of entries. */ boolean hash_table_init_n (table, newfunc, size) struct hash_table *table; struct hash_entry *(*newfunc) PARAMS ((struct hash_entry *, struct hash_table *, const char *)); unsigned int size; { unsigned int alloc; alloc = size * sizeof (struct hash_entry *); if (!obstack_begin (&table->memory, alloc)) { error ("no memory"); return false; } table->table = ((struct hash_entry **) obstack_alloc (&table->memory, alloc)); if (!table->table) { error ("no memory"); return false; } memset ((PTR) table->table, 0, alloc); table->size = size; table->newfunc = newfunc; return true; } /* Create a new hash table with the default number of entries. */ boolean hash_table_init (table, newfunc) struct hash_table *table; struct hash_entry *(*newfunc) PARAMS ((struct hash_entry *, struct hash_table *, const char *)); { return hash_table_init_n (table, newfunc, DEFAULT_SIZE); } /* Free a hash table. */ void hash_table_free (table) struct hash_table *table; { obstack_free (&table->memory, (PTR) NULL); } /* Look up a string in a hash table. */ struct hash_entry * hash_lookup (table, string, create, copy) struct hash_table *table; const char *string; boolean create; boolean copy; { register const unsigned char *s; register unsigned long hash; register unsigned int c; struct hash_entry *hashp; unsigned int len; unsigned int index; hash = 0; len = 0; s = (const unsigned char *) string; while ((c = *s++) != '\0') { hash += c + (c << 17); hash ^= hash >> 2; ++len; } hash += len + (len << 17); hash ^= hash >> 2; index = hash % table->size; for (hashp = table->table[index]; hashp != (struct hash_entry *) NULL; hashp = hashp->next) { if (hashp->hash == hash && strcmp (hashp->string, string) == 0) return hashp; } if (! create) return (struct hash_entry *) NULL; hashp = (*table->newfunc) ((struct hash_entry *) NULL, table, string); if (hashp == (struct hash_entry *) NULL) return (struct hash_entry *) NULL; if (copy) { char *new; new = (char *) obstack_alloc (&table->memory, len + 1); if (!new) { error ("no memory"); return (struct hash_entry *) NULL; } strcpy (new, string); string = new; } hashp->string = string; hashp->hash = hash; hashp->next = table->table[index]; table->table[index] = hashp; return hashp; } /* Base method for creating a new hash table entry. */ /*ARGSUSED*/ struct hash_entry * hash_newfunc (entry, table, string) struct hash_entry *entry; struct hash_table *table; const char *string; { if (entry == (struct hash_entry *) NULL) entry = ((struct hash_entry *) hash_allocate (table, sizeof (struct hash_entry))); return entry; } /* Allocate space in a hash table. */ PTR hash_allocate (table, size) struct hash_table *table; unsigned int size; { PTR ret; ret = obstack_alloc (&table->memory, size); if (ret == NULL && size != 0) error ("no memory"); return ret; } /* Traverse a hash table. */ void hash_traverse (table, func, info) struct hash_table *table; boolean (*func) PARAMS ((struct hash_entry *, PTR)); PTR info; { unsigned int i; for (i = 0; i < table->size; i++) { struct hash_entry *p; for (p = table->table[i]; p != NULL; p = p->next) { if (! (*func) (p, info)) return; } } }