xref: /minix/usr.bin/make/hash.c (revision 84d9c625)
1*84d9c625SLionel Sambuc /*	$NetBSD: hash.c,v 1.20 2013/11/14 00:27:05 sjg Exp $	*/
22e2caf59SThomas Veerman 
32e2caf59SThomas Veerman /*
42e2caf59SThomas Veerman  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
52e2caf59SThomas Veerman  * All rights reserved.
62e2caf59SThomas Veerman  *
72e2caf59SThomas Veerman  * This code is derived from software contributed to Berkeley by
82e2caf59SThomas Veerman  * Adam de Boor.
92e2caf59SThomas Veerman  *
102e2caf59SThomas Veerman  * Redistribution and use in source and binary forms, with or without
112e2caf59SThomas Veerman  * modification, are permitted provided that the following conditions
122e2caf59SThomas Veerman  * are met:
132e2caf59SThomas Veerman  * 1. Redistributions of source code must retain the above copyright
142e2caf59SThomas Veerman  *    notice, this list of conditions and the following disclaimer.
152e2caf59SThomas Veerman  * 2. Redistributions in binary form must reproduce the above copyright
162e2caf59SThomas Veerman  *    notice, this list of conditions and the following disclaimer in the
172e2caf59SThomas Veerman  *    documentation and/or other materials provided with the distribution.
182e2caf59SThomas Veerman  * 3. Neither the name of the University nor the names of its contributors
192e2caf59SThomas Veerman  *    may be used to endorse or promote products derived from this software
202e2caf59SThomas Veerman  *    without specific prior written permission.
212e2caf59SThomas Veerman  *
222e2caf59SThomas Veerman  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
232e2caf59SThomas Veerman  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
242e2caf59SThomas Veerman  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
252e2caf59SThomas Veerman  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
262e2caf59SThomas Veerman  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
272e2caf59SThomas Veerman  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
282e2caf59SThomas Veerman  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
292e2caf59SThomas Veerman  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
302e2caf59SThomas Veerman  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
312e2caf59SThomas Veerman  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
322e2caf59SThomas Veerman  * SUCH DAMAGE.
332e2caf59SThomas Veerman  */
342e2caf59SThomas Veerman 
352e2caf59SThomas Veerman /*
362e2caf59SThomas Veerman  * Copyright (c) 1988, 1989 by Adam de Boor
372e2caf59SThomas Veerman  * Copyright (c) 1989 by Berkeley Softworks
382e2caf59SThomas Veerman  * All rights reserved.
392e2caf59SThomas Veerman  *
402e2caf59SThomas Veerman  * This code is derived from software contributed to Berkeley by
412e2caf59SThomas Veerman  * Adam de Boor.
422e2caf59SThomas Veerman  *
432e2caf59SThomas Veerman  * Redistribution and use in source and binary forms, with or without
442e2caf59SThomas Veerman  * modification, are permitted provided that the following conditions
452e2caf59SThomas Veerman  * are met:
462e2caf59SThomas Veerman  * 1. Redistributions of source code must retain the above copyright
472e2caf59SThomas Veerman  *    notice, this list of conditions and the following disclaimer.
482e2caf59SThomas Veerman  * 2. Redistributions in binary form must reproduce the above copyright
492e2caf59SThomas Veerman  *    notice, this list of conditions and the following disclaimer in the
502e2caf59SThomas Veerman  *    documentation and/or other materials provided with the distribution.
512e2caf59SThomas Veerman  * 3. All advertising materials mentioning features or use of this software
522e2caf59SThomas Veerman  *    must display the following acknowledgement:
532e2caf59SThomas Veerman  *	This product includes software developed by the University of
542e2caf59SThomas Veerman  *	California, Berkeley and its contributors.
552e2caf59SThomas Veerman  * 4. Neither the name of the University nor the names of its contributors
562e2caf59SThomas Veerman  *    may be used to endorse or promote products derived from this software
572e2caf59SThomas Veerman  *    without specific prior written permission.
582e2caf59SThomas Veerman  *
592e2caf59SThomas Veerman  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
602e2caf59SThomas Veerman  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
612e2caf59SThomas Veerman  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
622e2caf59SThomas Veerman  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
632e2caf59SThomas Veerman  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
642e2caf59SThomas Veerman  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
652e2caf59SThomas Veerman  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
662e2caf59SThomas Veerman  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
672e2caf59SThomas Veerman  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
682e2caf59SThomas Veerman  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
692e2caf59SThomas Veerman  * SUCH DAMAGE.
702e2caf59SThomas Veerman  */
712e2caf59SThomas Veerman 
722e2caf59SThomas Veerman #ifndef MAKE_NATIVE
73*84d9c625SLionel Sambuc static char rcsid[] = "$NetBSD: hash.c,v 1.20 2013/11/14 00:27:05 sjg Exp $";
742e2caf59SThomas Veerman #else
752e2caf59SThomas Veerman #include <sys/cdefs.h>
762e2caf59SThomas Veerman #ifndef lint
772e2caf59SThomas Veerman #if 0
782e2caf59SThomas Veerman static char sccsid[] = "@(#)hash.c	8.1 (Berkeley) 6/6/93";
792e2caf59SThomas Veerman #else
80*84d9c625SLionel Sambuc __RCSID("$NetBSD: hash.c,v 1.20 2013/11/14 00:27:05 sjg Exp $");
812e2caf59SThomas Veerman #endif
822e2caf59SThomas Veerman #endif /* not lint */
832e2caf59SThomas Veerman #endif
842e2caf59SThomas Veerman 
852e2caf59SThomas Veerman /* hash.c --
862e2caf59SThomas Veerman  *
872e2caf59SThomas Veerman  * 	This module contains routines to manipulate a hash table.
882e2caf59SThomas Veerman  * 	See hash.h for a definition of the structure of the hash
892e2caf59SThomas Veerman  * 	table.  Hash tables grow automatically as the amount of
902e2caf59SThomas Veerman  * 	information increases.
912e2caf59SThomas Veerman  */
922e2caf59SThomas Veerman #include "sprite.h"
932e2caf59SThomas Veerman #include "make.h"
942e2caf59SThomas Veerman #include "hash.h"
952e2caf59SThomas Veerman 
962e2caf59SThomas Veerman /*
972e2caf59SThomas Veerman  * Forward references to local procedures that are used before they're
982e2caf59SThomas Veerman  * defined:
992e2caf59SThomas Veerman  */
1002e2caf59SThomas Veerman 
1012e2caf59SThomas Veerman static void RebuildTable(Hash_Table *);
1022e2caf59SThomas Veerman 
1032e2caf59SThomas Veerman /*
1042e2caf59SThomas Veerman  * The following defines the ratio of # entries to # buckets
1052e2caf59SThomas Veerman  * at which we rebuild the table to make it larger.
1062e2caf59SThomas Veerman  */
1072e2caf59SThomas Veerman 
1082e2caf59SThomas Veerman #define rebuildLimit 3
1092e2caf59SThomas Veerman 
1102e2caf59SThomas Veerman /*
1112e2caf59SThomas Veerman  *---------------------------------------------------------
1122e2caf59SThomas Veerman  *
1132e2caf59SThomas Veerman  * Hash_InitTable --
1142e2caf59SThomas Veerman  *
1152e2caf59SThomas Veerman  *	This routine just sets up the hash table.
1162e2caf59SThomas Veerman  *
1172e2caf59SThomas Veerman  * Input:
1182e2caf59SThomas Veerman  *	t		Structure to to hold table.
1192e2caf59SThomas Veerman  *	numBuckets	How many buckets to create for starters. This
1202e2caf59SThomas Veerman  *			number is rounded up to a power of two.   If
1212e2caf59SThomas Veerman  *			<= 0, a reasonable default is chosen. The
1222e2caf59SThomas Veerman  *			table will grow in size later as needed.
1232e2caf59SThomas Veerman  *
1242e2caf59SThomas Veerman  * Results:
1252e2caf59SThomas Veerman  *	None.
1262e2caf59SThomas Veerman  *
1272e2caf59SThomas Veerman  * Side Effects:
1282e2caf59SThomas Veerman  *	Memory is allocated for the initial bucket area.
1292e2caf59SThomas Veerman  *
1302e2caf59SThomas Veerman  *---------------------------------------------------------
1312e2caf59SThomas Veerman  */
1322e2caf59SThomas Veerman 
1332e2caf59SThomas Veerman void
Hash_InitTable(Hash_Table * t,int numBuckets)1342e2caf59SThomas Veerman Hash_InitTable(Hash_Table *t, int numBuckets)
1352e2caf59SThomas Veerman {
1362e2caf59SThomas Veerman 	int i;
1372e2caf59SThomas Veerman 	struct Hash_Entry **hp;
1382e2caf59SThomas Veerman 
1392e2caf59SThomas Veerman 	/*
1402e2caf59SThomas Veerman 	 * Round up the size to a power of two.
1412e2caf59SThomas Veerman 	 */
1422e2caf59SThomas Veerman 	if (numBuckets <= 0)
1432e2caf59SThomas Veerman 		i = 16;
1442e2caf59SThomas Veerman 	else {
1452e2caf59SThomas Veerman 		for (i = 2; i < numBuckets; i <<= 1)
1462e2caf59SThomas Veerman 			 continue;
1472e2caf59SThomas Veerman 	}
1482e2caf59SThomas Veerman 	t->numEntries = 0;
1492e2caf59SThomas Veerman 	t->size = i;
1502e2caf59SThomas Veerman 	t->mask = i - 1;
1512e2caf59SThomas Veerman 	t->bucketPtr = hp = bmake_malloc(sizeof(*hp) * i);
1522e2caf59SThomas Veerman 	while (--i >= 0)
1532e2caf59SThomas Veerman 		*hp++ = NULL;
1542e2caf59SThomas Veerman }
1552e2caf59SThomas Veerman 
1562e2caf59SThomas Veerman /*
1572e2caf59SThomas Veerman  *---------------------------------------------------------
1582e2caf59SThomas Veerman  *
1592e2caf59SThomas Veerman  * Hash_DeleteTable --
1602e2caf59SThomas Veerman  *
1612e2caf59SThomas Veerman  *	This routine removes everything from a hash table
1622e2caf59SThomas Veerman  *	and frees up the memory space it occupied (except for
1632e2caf59SThomas Veerman  *	the space in the Hash_Table structure).
1642e2caf59SThomas Veerman  *
1652e2caf59SThomas Veerman  * Results:
1662e2caf59SThomas Veerman  *	None.
1672e2caf59SThomas Veerman  *
1682e2caf59SThomas Veerman  * Side Effects:
1692e2caf59SThomas Veerman  *	Lots of memory is freed up.
1702e2caf59SThomas Veerman  *
1712e2caf59SThomas Veerman  *---------------------------------------------------------
1722e2caf59SThomas Veerman  */
1732e2caf59SThomas Veerman 
1742e2caf59SThomas Veerman void
Hash_DeleteTable(Hash_Table * t)1752e2caf59SThomas Veerman Hash_DeleteTable(Hash_Table *t)
1762e2caf59SThomas Veerman {
1772e2caf59SThomas Veerman 	struct Hash_Entry **hp, *h, *nexth = NULL;
1782e2caf59SThomas Veerman 	int i;
1792e2caf59SThomas Veerman 
1802e2caf59SThomas Veerman 	for (hp = t->bucketPtr, i = t->size; --i >= 0;) {
1812e2caf59SThomas Veerman 		for (h = *hp++; h != NULL; h = nexth) {
1822e2caf59SThomas Veerman 			nexth = h->next;
1832e2caf59SThomas Veerman 			free(h);
1842e2caf59SThomas Veerman 		}
1852e2caf59SThomas Veerman 	}
1862e2caf59SThomas Veerman 	free(t->bucketPtr);
1872e2caf59SThomas Veerman 
1882e2caf59SThomas Veerman 	/*
1892e2caf59SThomas Veerman 	 * Set up the hash table to cause memory faults on any future access
1902e2caf59SThomas Veerman 	 * attempts until re-initialization.
1912e2caf59SThomas Veerman 	 */
1922e2caf59SThomas Veerman 	t->bucketPtr = NULL;
1932e2caf59SThomas Veerman }
1942e2caf59SThomas Veerman 
1952e2caf59SThomas Veerman /*
1962e2caf59SThomas Veerman  *---------------------------------------------------------
1972e2caf59SThomas Veerman  *
1982e2caf59SThomas Veerman  * Hash_FindEntry --
1992e2caf59SThomas Veerman  *
2002e2caf59SThomas Veerman  * 	Searches a hash table for an entry corresponding to key.
2012e2caf59SThomas Veerman  *
2022e2caf59SThomas Veerman  * Input:
2032e2caf59SThomas Veerman  *	t		Hash table to search.
2042e2caf59SThomas Veerman  *	key		A hash key.
2052e2caf59SThomas Veerman  *
2062e2caf59SThomas Veerman  * Results:
2072e2caf59SThomas Veerman  *	The return value is a pointer to the entry for key,
2082e2caf59SThomas Veerman  *	if key was present in the table.  If key was not
2092e2caf59SThomas Veerman  *	present, NULL is returned.
2102e2caf59SThomas Veerman  *
2112e2caf59SThomas Veerman  * Side Effects:
2122e2caf59SThomas Veerman  *	None.
2132e2caf59SThomas Veerman  *
2142e2caf59SThomas Veerman  *---------------------------------------------------------
2152e2caf59SThomas Veerman  */
2162e2caf59SThomas Veerman 
2172e2caf59SThomas Veerman Hash_Entry *
Hash_FindEntry(Hash_Table * t,const char * key)2182e2caf59SThomas Veerman Hash_FindEntry(Hash_Table *t, const char *key)
2192e2caf59SThomas Veerman {
2202e2caf59SThomas Veerman 	Hash_Entry *e;
2212e2caf59SThomas Veerman 	unsigned h;
2222e2caf59SThomas Veerman 	const char *p;
2232e2caf59SThomas Veerman 
224*84d9c625SLionel Sambuc 	if (t == NULL || t->bucketPtr == NULL) {
225*84d9c625SLionel Sambuc 	    return NULL;
226*84d9c625SLionel Sambuc 	}
2272e2caf59SThomas Veerman 	for (h = 0, p = key; *p;)
2282e2caf59SThomas Veerman 		h = (h << 5) - h + *p++;
2292e2caf59SThomas Veerman 	p = key;
2302e2caf59SThomas Veerman 	for (e = t->bucketPtr[h & t->mask]; e != NULL; e = e->next)
2312e2caf59SThomas Veerman 		if (e->namehash == h && strcmp(e->name, p) == 0)
2322e2caf59SThomas Veerman 			return (e);
2332e2caf59SThomas Veerman 	return NULL;
2342e2caf59SThomas Veerman }
2352e2caf59SThomas Veerman 
2362e2caf59SThomas Veerman /*
2372e2caf59SThomas Veerman  *---------------------------------------------------------
2382e2caf59SThomas Veerman  *
2392e2caf59SThomas Veerman  * Hash_CreateEntry --
2402e2caf59SThomas Veerman  *
2412e2caf59SThomas Veerman  *	Searches a hash table for an entry corresponding to
2422e2caf59SThomas Veerman  *	key.  If no entry is found, then one is created.
2432e2caf59SThomas Veerman  *
2442e2caf59SThomas Veerman  * Input:
2452e2caf59SThomas Veerman  *	t		Hash table to search.
2462e2caf59SThomas Veerman  *	key		A hash key.
2472e2caf59SThomas Veerman  *	newPtr		Filled in with TRUE if new entry created,
2482e2caf59SThomas Veerman  *			FALSE otherwise.
2492e2caf59SThomas Veerman  *
2502e2caf59SThomas Veerman  * Results:
2512e2caf59SThomas Veerman  *	The return value is a pointer to the entry.  If *newPtr
2522e2caf59SThomas Veerman  *	isn't NULL, then *newPtr is filled in with TRUE if a
2532e2caf59SThomas Veerman  *	new entry was created, and FALSE if an entry already existed
2542e2caf59SThomas Veerman  *	with the given key.
2552e2caf59SThomas Veerman  *
2562e2caf59SThomas Veerman  * Side Effects:
2572e2caf59SThomas Veerman  *	Memory may be allocated, and the hash buckets may be modified.
2582e2caf59SThomas Veerman  *---------------------------------------------------------
2592e2caf59SThomas Veerman  */
2602e2caf59SThomas Veerman 
2612e2caf59SThomas Veerman Hash_Entry *
Hash_CreateEntry(Hash_Table * t,const char * key,Boolean * newPtr)2622e2caf59SThomas Veerman Hash_CreateEntry(Hash_Table *t, const char *key, Boolean *newPtr)
2632e2caf59SThomas Veerman {
2642e2caf59SThomas Veerman 	Hash_Entry *e;
2652e2caf59SThomas Veerman 	unsigned h;
2662e2caf59SThomas Veerman 	const char *p;
2672e2caf59SThomas Veerman 	int keylen;
2682e2caf59SThomas Veerman 	struct Hash_Entry **hp;
2692e2caf59SThomas Veerman 
2702e2caf59SThomas Veerman 	/*
2712e2caf59SThomas Veerman 	 * Hash the key.  As a side effect, save the length (strlen) of the
2722e2caf59SThomas Veerman 	 * key in case we need to create the entry.
2732e2caf59SThomas Veerman 	 */
2742e2caf59SThomas Veerman 	for (h = 0, p = key; *p;)
2752e2caf59SThomas Veerman 		h = (h << 5) - h + *p++;
2762e2caf59SThomas Veerman 	keylen = p - key;
2772e2caf59SThomas Veerman 	p = key;
2782e2caf59SThomas Veerman 	for (e = t->bucketPtr[h & t->mask]; e != NULL; e = e->next) {
2792e2caf59SThomas Veerman 		if (e->namehash == h && strcmp(e->name, p) == 0) {
2802e2caf59SThomas Veerman 			if (newPtr != NULL)
2812e2caf59SThomas Veerman 				*newPtr = FALSE;
2822e2caf59SThomas Veerman 			return (e);
2832e2caf59SThomas Veerman 		}
2842e2caf59SThomas Veerman 	}
2852e2caf59SThomas Veerman 
2862e2caf59SThomas Veerman 	/*
2872e2caf59SThomas Veerman 	 * The desired entry isn't there.  Before allocating a new entry,
2882e2caf59SThomas Veerman 	 * expand the table if necessary (and this changes the resulting
2892e2caf59SThomas Veerman 	 * bucket chain).
2902e2caf59SThomas Veerman 	 */
2912e2caf59SThomas Veerman 	if (t->numEntries >= rebuildLimit * t->size)
2922e2caf59SThomas Veerman 		RebuildTable(t);
2932e2caf59SThomas Veerman 	e = bmake_malloc(sizeof(*e) + keylen);
2942e2caf59SThomas Veerman 	hp = &t->bucketPtr[h & t->mask];
2952e2caf59SThomas Veerman 	e->next = *hp;
2962e2caf59SThomas Veerman 	*hp = e;
2972e2caf59SThomas Veerman 	Hash_SetValue(e, NULL);
2982e2caf59SThomas Veerman 	e->namehash = h;
2992e2caf59SThomas Veerman 	(void)strcpy(e->name, p);
3002e2caf59SThomas Veerman 	t->numEntries++;
3012e2caf59SThomas Veerman 
3022e2caf59SThomas Veerman 	if (newPtr != NULL)
3032e2caf59SThomas Veerman 		*newPtr = TRUE;
3042e2caf59SThomas Veerman 	return (e);
3052e2caf59SThomas Veerman }
3062e2caf59SThomas Veerman 
3072e2caf59SThomas Veerman /*
3082e2caf59SThomas Veerman  *---------------------------------------------------------
3092e2caf59SThomas Veerman  *
3102e2caf59SThomas Veerman  * Hash_DeleteEntry --
3112e2caf59SThomas Veerman  *
3122e2caf59SThomas Veerman  * 	Delete the given hash table entry and free memory associated with
3132e2caf59SThomas Veerman  *	it.
3142e2caf59SThomas Veerman  *
3152e2caf59SThomas Veerman  * Results:
3162e2caf59SThomas Veerman  *	None.
3172e2caf59SThomas Veerman  *
3182e2caf59SThomas Veerman  * Side Effects:
3192e2caf59SThomas Veerman  *	Hash chain that entry lives in is modified and memory is freed.
3202e2caf59SThomas Veerman  *
3212e2caf59SThomas Veerman  *---------------------------------------------------------
3222e2caf59SThomas Veerman  */
3232e2caf59SThomas Veerman 
3242e2caf59SThomas Veerman void
Hash_DeleteEntry(Hash_Table * t,Hash_Entry * e)3252e2caf59SThomas Veerman Hash_DeleteEntry(Hash_Table *t, Hash_Entry *e)
3262e2caf59SThomas Veerman {
3272e2caf59SThomas Veerman 	Hash_Entry **hp, *p;
3282e2caf59SThomas Veerman 
3292e2caf59SThomas Veerman 	if (e == NULL)
3302e2caf59SThomas Veerman 		return;
3312e2caf59SThomas Veerman 	for (hp = &t->bucketPtr[e->namehash & t->mask];
3322e2caf59SThomas Veerman 	     (p = *hp) != NULL; hp = &p->next) {
3332e2caf59SThomas Veerman 		if (p == e) {
3342e2caf59SThomas Veerman 			*hp = p->next;
3352e2caf59SThomas Veerman 			free(p);
3362e2caf59SThomas Veerman 			t->numEntries--;
3372e2caf59SThomas Veerman 			return;
3382e2caf59SThomas Veerman 		}
3392e2caf59SThomas Veerman 	}
3402e2caf59SThomas Veerman 	(void)write(2, "bad call to Hash_DeleteEntry\n", 29);
3412e2caf59SThomas Veerman 	abort();
3422e2caf59SThomas Veerman }
3432e2caf59SThomas Veerman 
3442e2caf59SThomas Veerman /*
3452e2caf59SThomas Veerman  *---------------------------------------------------------
3462e2caf59SThomas Veerman  *
3472e2caf59SThomas Veerman  * Hash_EnumFirst --
3482e2caf59SThomas Veerman  *	This procedure sets things up for a complete search
3492e2caf59SThomas Veerman  *	of all entries recorded in the hash table.
3502e2caf59SThomas Veerman  *
3512e2caf59SThomas Veerman  * Input:
3522e2caf59SThomas Veerman  *	t		Table to be searched.
3532e2caf59SThomas Veerman  *	searchPtr	Area in which to keep state about search.
3542e2caf59SThomas Veerman  *
3552e2caf59SThomas Veerman  * Results:
3562e2caf59SThomas Veerman  *	The return value is the address of the first entry in
3572e2caf59SThomas Veerman  *	the hash table, or NULL if the table is empty.
3582e2caf59SThomas Veerman  *
3592e2caf59SThomas Veerman  * Side Effects:
3602e2caf59SThomas Veerman  *	The information in searchPtr is initialized so that successive
3612e2caf59SThomas Veerman  *	calls to Hash_Next will return successive HashEntry's
3622e2caf59SThomas Veerman  *	from the table.
3632e2caf59SThomas Veerman  *
3642e2caf59SThomas Veerman  *---------------------------------------------------------
3652e2caf59SThomas Veerman  */
3662e2caf59SThomas Veerman 
3672e2caf59SThomas Veerman Hash_Entry *
Hash_EnumFirst(Hash_Table * t,Hash_Search * searchPtr)3682e2caf59SThomas Veerman Hash_EnumFirst(Hash_Table *t, Hash_Search *searchPtr)
3692e2caf59SThomas Veerman {
3702e2caf59SThomas Veerman 	searchPtr->tablePtr = t;
3712e2caf59SThomas Veerman 	searchPtr->nextIndex = 0;
3722e2caf59SThomas Veerman 	searchPtr->hashEntryPtr = NULL;
3732e2caf59SThomas Veerman 	return Hash_EnumNext(searchPtr);
3742e2caf59SThomas Veerman }
3752e2caf59SThomas Veerman 
3762e2caf59SThomas Veerman /*
3772e2caf59SThomas Veerman  *---------------------------------------------------------
3782e2caf59SThomas Veerman  *
3792e2caf59SThomas Veerman  * Hash_EnumNext --
3802e2caf59SThomas Veerman  *    This procedure returns successive entries in the hash table.
3812e2caf59SThomas Veerman  *
3822e2caf59SThomas Veerman  * Input:
3832e2caf59SThomas Veerman  *	searchPtr	Area used to keep state about search.
3842e2caf59SThomas Veerman  *
3852e2caf59SThomas Veerman  * Results:
3862e2caf59SThomas Veerman  *    The return value is a pointer to the next HashEntry
3872e2caf59SThomas Veerman  *    in the table, or NULL when the end of the table is
3882e2caf59SThomas Veerman  *    reached.
3892e2caf59SThomas Veerman  *
3902e2caf59SThomas Veerman  * Side Effects:
3912e2caf59SThomas Veerman  *    The information in searchPtr is modified to advance to the
3922e2caf59SThomas Veerman  *    next entry.
3932e2caf59SThomas Veerman  *
3942e2caf59SThomas Veerman  *---------------------------------------------------------
3952e2caf59SThomas Veerman  */
3962e2caf59SThomas Veerman 
3972e2caf59SThomas Veerman Hash_Entry *
Hash_EnumNext(Hash_Search * searchPtr)3982e2caf59SThomas Veerman Hash_EnumNext(Hash_Search *searchPtr)
3992e2caf59SThomas Veerman {
4002e2caf59SThomas Veerman 	Hash_Entry *e;
4012e2caf59SThomas Veerman 	Hash_Table *t = searchPtr->tablePtr;
4022e2caf59SThomas Veerman 
4032e2caf59SThomas Veerman 	/*
4042e2caf59SThomas Veerman 	 * The hashEntryPtr field points to the most recently returned
4052e2caf59SThomas Veerman 	 * entry, or is nil if we are starting up.  If not nil, we have
4062e2caf59SThomas Veerman 	 * to start at the next one in the chain.
4072e2caf59SThomas Veerman 	 */
4082e2caf59SThomas Veerman 	e = searchPtr->hashEntryPtr;
4092e2caf59SThomas Veerman 	if (e != NULL)
4102e2caf59SThomas Veerman 		e = e->next;
4112e2caf59SThomas Veerman 	/*
4122e2caf59SThomas Veerman 	 * If the chain ran out, or if we are starting up, we need to
4132e2caf59SThomas Veerman 	 * find the next nonempty chain.
4142e2caf59SThomas Veerman 	 */
4152e2caf59SThomas Veerman 	while (e == NULL) {
4162e2caf59SThomas Veerman 		if (searchPtr->nextIndex >= t->size)
4172e2caf59SThomas Veerman 			return NULL;
4182e2caf59SThomas Veerman 		e = t->bucketPtr[searchPtr->nextIndex++];
4192e2caf59SThomas Veerman 	}
4202e2caf59SThomas Veerman 	searchPtr->hashEntryPtr = e;
4212e2caf59SThomas Veerman 	return (e);
4222e2caf59SThomas Veerman }
4232e2caf59SThomas Veerman 
4242e2caf59SThomas Veerman /*
4252e2caf59SThomas Veerman  *---------------------------------------------------------
4262e2caf59SThomas Veerman  *
4272e2caf59SThomas Veerman  * RebuildTable --
4282e2caf59SThomas Veerman  *	This local routine makes a new hash table that
4292e2caf59SThomas Veerman  *	is larger than the old one.
4302e2caf59SThomas Veerman  *
4312e2caf59SThomas Veerman  * Results:
4322e2caf59SThomas Veerman  * 	None.
4332e2caf59SThomas Veerman  *
4342e2caf59SThomas Veerman  * Side Effects:
4352e2caf59SThomas Veerman  *	The entire hash table is moved, so any bucket numbers
4362e2caf59SThomas Veerman  *	from the old table are invalid.
4372e2caf59SThomas Veerman  *
4382e2caf59SThomas Veerman  *---------------------------------------------------------
4392e2caf59SThomas Veerman  */
4402e2caf59SThomas Veerman 
4412e2caf59SThomas Veerman static void
RebuildTable(Hash_Table * t)4422e2caf59SThomas Veerman RebuildTable(Hash_Table *t)
4432e2caf59SThomas Veerman {
4442e2caf59SThomas Veerman 	Hash_Entry *e, *next = NULL, **hp, **xp;
4452e2caf59SThomas Veerman 	int i, mask;
4462e2caf59SThomas Veerman         Hash_Entry **oldhp;
4472e2caf59SThomas Veerman 	int oldsize;
4482e2caf59SThomas Veerman 
4492e2caf59SThomas Veerman 	oldhp = t->bucketPtr;
4502e2caf59SThomas Veerman 	oldsize = i = t->size;
4512e2caf59SThomas Veerman 	i <<= 1;
4522e2caf59SThomas Veerman 	t->size = i;
4532e2caf59SThomas Veerman 	t->mask = mask = i - 1;
4542e2caf59SThomas Veerman 	t->bucketPtr = hp = bmake_malloc(sizeof(*hp) * i);
4552e2caf59SThomas Veerman 	while (--i >= 0)
4562e2caf59SThomas Veerman 		*hp++ = NULL;
4572e2caf59SThomas Veerman 	for (hp = oldhp, i = oldsize; --i >= 0;) {
4582e2caf59SThomas Veerman 		for (e = *hp++; e != NULL; e = next) {
4592e2caf59SThomas Veerman 			next = e->next;
4602e2caf59SThomas Veerman 			xp = &t->bucketPtr[e->namehash & mask];
4612e2caf59SThomas Veerman 			e->next = *xp;
4622e2caf59SThomas Veerman 			*xp = e;
4632e2caf59SThomas Veerman 		}
4642e2caf59SThomas Veerman 	}
4652e2caf59SThomas Veerman 	free(oldhp);
4662e2caf59SThomas Veerman }
467