xref: /minix/usr.bin/make/hash.c (revision 2e2caf59)
1*2e2caf59SThomas Veerman /*	$NetBSD: hash.c,v 1.19 2009/01/24 10:59:09 dsl Exp $	*/
2*2e2caf59SThomas Veerman 
3*2e2caf59SThomas Veerman /*
4*2e2caf59SThomas Veerman  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
5*2e2caf59SThomas Veerman  * All rights reserved.
6*2e2caf59SThomas Veerman  *
7*2e2caf59SThomas Veerman  * This code is derived from software contributed to Berkeley by
8*2e2caf59SThomas Veerman  * Adam de Boor.
9*2e2caf59SThomas Veerman  *
10*2e2caf59SThomas Veerman  * Redistribution and use in source and binary forms, with or without
11*2e2caf59SThomas Veerman  * modification, are permitted provided that the following conditions
12*2e2caf59SThomas Veerman  * are met:
13*2e2caf59SThomas Veerman  * 1. Redistributions of source code must retain the above copyright
14*2e2caf59SThomas Veerman  *    notice, this list of conditions and the following disclaimer.
15*2e2caf59SThomas Veerman  * 2. Redistributions in binary form must reproduce the above copyright
16*2e2caf59SThomas Veerman  *    notice, this list of conditions and the following disclaimer in the
17*2e2caf59SThomas Veerman  *    documentation and/or other materials provided with the distribution.
18*2e2caf59SThomas Veerman  * 3. Neither the name of the University nor the names of its contributors
19*2e2caf59SThomas Veerman  *    may be used to endorse or promote products derived from this software
20*2e2caf59SThomas Veerman  *    without specific prior written permission.
21*2e2caf59SThomas Veerman  *
22*2e2caf59SThomas Veerman  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23*2e2caf59SThomas Veerman  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24*2e2caf59SThomas Veerman  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25*2e2caf59SThomas Veerman  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26*2e2caf59SThomas Veerman  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27*2e2caf59SThomas Veerman  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28*2e2caf59SThomas Veerman  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29*2e2caf59SThomas Veerman  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30*2e2caf59SThomas Veerman  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31*2e2caf59SThomas Veerman  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32*2e2caf59SThomas Veerman  * SUCH DAMAGE.
33*2e2caf59SThomas Veerman  */
34*2e2caf59SThomas Veerman 
35*2e2caf59SThomas Veerman /*
36*2e2caf59SThomas Veerman  * Copyright (c) 1988, 1989 by Adam de Boor
37*2e2caf59SThomas Veerman  * Copyright (c) 1989 by Berkeley Softworks
38*2e2caf59SThomas Veerman  * All rights reserved.
39*2e2caf59SThomas Veerman  *
40*2e2caf59SThomas Veerman  * This code is derived from software contributed to Berkeley by
41*2e2caf59SThomas Veerman  * Adam de Boor.
42*2e2caf59SThomas Veerman  *
43*2e2caf59SThomas Veerman  * Redistribution and use in source and binary forms, with or without
44*2e2caf59SThomas Veerman  * modification, are permitted provided that the following conditions
45*2e2caf59SThomas Veerman  * are met:
46*2e2caf59SThomas Veerman  * 1. Redistributions of source code must retain the above copyright
47*2e2caf59SThomas Veerman  *    notice, this list of conditions and the following disclaimer.
48*2e2caf59SThomas Veerman  * 2. Redistributions in binary form must reproduce the above copyright
49*2e2caf59SThomas Veerman  *    notice, this list of conditions and the following disclaimer in the
50*2e2caf59SThomas Veerman  *    documentation and/or other materials provided with the distribution.
51*2e2caf59SThomas Veerman  * 3. All advertising materials mentioning features or use of this software
52*2e2caf59SThomas Veerman  *    must display the following acknowledgement:
53*2e2caf59SThomas Veerman  *	This product includes software developed by the University of
54*2e2caf59SThomas Veerman  *	California, Berkeley and its contributors.
55*2e2caf59SThomas Veerman  * 4. Neither the name of the University nor the names of its contributors
56*2e2caf59SThomas Veerman  *    may be used to endorse or promote products derived from this software
57*2e2caf59SThomas Veerman  *    without specific prior written permission.
58*2e2caf59SThomas Veerman  *
59*2e2caf59SThomas Veerman  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
60*2e2caf59SThomas Veerman  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61*2e2caf59SThomas Veerman  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62*2e2caf59SThomas Veerman  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
63*2e2caf59SThomas Veerman  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64*2e2caf59SThomas Veerman  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65*2e2caf59SThomas Veerman  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66*2e2caf59SThomas Veerman  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67*2e2caf59SThomas Veerman  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68*2e2caf59SThomas Veerman  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69*2e2caf59SThomas Veerman  * SUCH DAMAGE.
70*2e2caf59SThomas Veerman  */
71*2e2caf59SThomas Veerman 
72*2e2caf59SThomas Veerman #ifndef MAKE_NATIVE
73*2e2caf59SThomas Veerman static char rcsid[] = "$NetBSD: hash.c,v 1.19 2009/01/24 10:59:09 dsl Exp $";
74*2e2caf59SThomas Veerman #else
75*2e2caf59SThomas Veerman #include <sys/cdefs.h>
76*2e2caf59SThomas Veerman #ifndef lint
77*2e2caf59SThomas Veerman #if 0
78*2e2caf59SThomas Veerman static char sccsid[] = "@(#)hash.c	8.1 (Berkeley) 6/6/93";
79*2e2caf59SThomas Veerman #else
80*2e2caf59SThomas Veerman __RCSID("$NetBSD: hash.c,v 1.19 2009/01/24 10:59:09 dsl Exp $");
81*2e2caf59SThomas Veerman #endif
82*2e2caf59SThomas Veerman #endif /* not lint */
83*2e2caf59SThomas Veerman #endif
84*2e2caf59SThomas Veerman 
85*2e2caf59SThomas Veerman /* hash.c --
86*2e2caf59SThomas Veerman  *
87*2e2caf59SThomas Veerman  * 	This module contains routines to manipulate a hash table.
88*2e2caf59SThomas Veerman  * 	See hash.h for a definition of the structure of the hash
89*2e2caf59SThomas Veerman  * 	table.  Hash tables grow automatically as the amount of
90*2e2caf59SThomas Veerman  * 	information increases.
91*2e2caf59SThomas Veerman  */
92*2e2caf59SThomas Veerman #include "sprite.h"
93*2e2caf59SThomas Veerman #include "make.h"
94*2e2caf59SThomas Veerman #include "hash.h"
95*2e2caf59SThomas Veerman 
96*2e2caf59SThomas Veerman /*
97*2e2caf59SThomas Veerman  * Forward references to local procedures that are used before they're
98*2e2caf59SThomas Veerman  * defined:
99*2e2caf59SThomas Veerman  */
100*2e2caf59SThomas Veerman 
101*2e2caf59SThomas Veerman static void RebuildTable(Hash_Table *);
102*2e2caf59SThomas Veerman 
103*2e2caf59SThomas Veerman /*
104*2e2caf59SThomas Veerman  * The following defines the ratio of # entries to # buckets
105*2e2caf59SThomas Veerman  * at which we rebuild the table to make it larger.
106*2e2caf59SThomas Veerman  */
107*2e2caf59SThomas Veerman 
108*2e2caf59SThomas Veerman #define rebuildLimit 3
109*2e2caf59SThomas Veerman 
110*2e2caf59SThomas Veerman /*
111*2e2caf59SThomas Veerman  *---------------------------------------------------------
112*2e2caf59SThomas Veerman  *
113*2e2caf59SThomas Veerman  * Hash_InitTable --
114*2e2caf59SThomas Veerman  *
115*2e2caf59SThomas Veerman  *	This routine just sets up the hash table.
116*2e2caf59SThomas Veerman  *
117*2e2caf59SThomas Veerman  * Input:
118*2e2caf59SThomas Veerman  *	t		Structure to to hold table.
119*2e2caf59SThomas Veerman  *	numBuckets	How many buckets to create for starters. This
120*2e2caf59SThomas Veerman  *			number is rounded up to a power of two.   If
121*2e2caf59SThomas Veerman  *			<= 0, a reasonable default is chosen. The
122*2e2caf59SThomas Veerman  *			table will grow in size later as needed.
123*2e2caf59SThomas Veerman  *
124*2e2caf59SThomas Veerman  * Results:
125*2e2caf59SThomas Veerman  *	None.
126*2e2caf59SThomas Veerman  *
127*2e2caf59SThomas Veerman  * Side Effects:
128*2e2caf59SThomas Veerman  *	Memory is allocated for the initial bucket area.
129*2e2caf59SThomas Veerman  *
130*2e2caf59SThomas Veerman  *---------------------------------------------------------
131*2e2caf59SThomas Veerman  */
132*2e2caf59SThomas Veerman 
133*2e2caf59SThomas Veerman void
134*2e2caf59SThomas Veerman Hash_InitTable(Hash_Table *t, int numBuckets)
135*2e2caf59SThomas Veerman {
136*2e2caf59SThomas Veerman 	int i;
137*2e2caf59SThomas Veerman 	struct Hash_Entry **hp;
138*2e2caf59SThomas Veerman 
139*2e2caf59SThomas Veerman 	/*
140*2e2caf59SThomas Veerman 	 * Round up the size to a power of two.
141*2e2caf59SThomas Veerman 	 */
142*2e2caf59SThomas Veerman 	if (numBuckets <= 0)
143*2e2caf59SThomas Veerman 		i = 16;
144*2e2caf59SThomas Veerman 	else {
145*2e2caf59SThomas Veerman 		for (i = 2; i < numBuckets; i <<= 1)
146*2e2caf59SThomas Veerman 			 continue;
147*2e2caf59SThomas Veerman 	}
148*2e2caf59SThomas Veerman 	t->numEntries = 0;
149*2e2caf59SThomas Veerman 	t->size = i;
150*2e2caf59SThomas Veerman 	t->mask = i - 1;
151*2e2caf59SThomas Veerman 	t->bucketPtr = hp = bmake_malloc(sizeof(*hp) * i);
152*2e2caf59SThomas Veerman 	while (--i >= 0)
153*2e2caf59SThomas Veerman 		*hp++ = NULL;
154*2e2caf59SThomas Veerman }
155*2e2caf59SThomas Veerman 
156*2e2caf59SThomas Veerman /*
157*2e2caf59SThomas Veerman  *---------------------------------------------------------
158*2e2caf59SThomas Veerman  *
159*2e2caf59SThomas Veerman  * Hash_DeleteTable --
160*2e2caf59SThomas Veerman  *
161*2e2caf59SThomas Veerman  *	This routine removes everything from a hash table
162*2e2caf59SThomas Veerman  *	and frees up the memory space it occupied (except for
163*2e2caf59SThomas Veerman  *	the space in the Hash_Table structure).
164*2e2caf59SThomas Veerman  *
165*2e2caf59SThomas Veerman  * Results:
166*2e2caf59SThomas Veerman  *	None.
167*2e2caf59SThomas Veerman  *
168*2e2caf59SThomas Veerman  * Side Effects:
169*2e2caf59SThomas Veerman  *	Lots of memory is freed up.
170*2e2caf59SThomas Veerman  *
171*2e2caf59SThomas Veerman  *---------------------------------------------------------
172*2e2caf59SThomas Veerman  */
173*2e2caf59SThomas Veerman 
174*2e2caf59SThomas Veerman void
175*2e2caf59SThomas Veerman Hash_DeleteTable(Hash_Table *t)
176*2e2caf59SThomas Veerman {
177*2e2caf59SThomas Veerman 	struct Hash_Entry **hp, *h, *nexth = NULL;
178*2e2caf59SThomas Veerman 	int i;
179*2e2caf59SThomas Veerman 
180*2e2caf59SThomas Veerman 	for (hp = t->bucketPtr, i = t->size; --i >= 0;) {
181*2e2caf59SThomas Veerman 		for (h = *hp++; h != NULL; h = nexth) {
182*2e2caf59SThomas Veerman 			nexth = h->next;
183*2e2caf59SThomas Veerman 			free(h);
184*2e2caf59SThomas Veerman 		}
185*2e2caf59SThomas Veerman 	}
186*2e2caf59SThomas Veerman 	free(t->bucketPtr);
187*2e2caf59SThomas Veerman 
188*2e2caf59SThomas Veerman 	/*
189*2e2caf59SThomas Veerman 	 * Set up the hash table to cause memory faults on any future access
190*2e2caf59SThomas Veerman 	 * attempts until re-initialization.
191*2e2caf59SThomas Veerman 	 */
192*2e2caf59SThomas Veerman 	t->bucketPtr = NULL;
193*2e2caf59SThomas Veerman }
194*2e2caf59SThomas Veerman 
195*2e2caf59SThomas Veerman /*
196*2e2caf59SThomas Veerman  *---------------------------------------------------------
197*2e2caf59SThomas Veerman  *
198*2e2caf59SThomas Veerman  * Hash_FindEntry --
199*2e2caf59SThomas Veerman  *
200*2e2caf59SThomas Veerman  * 	Searches a hash table for an entry corresponding to key.
201*2e2caf59SThomas Veerman  *
202*2e2caf59SThomas Veerman  * Input:
203*2e2caf59SThomas Veerman  *	t		Hash table to search.
204*2e2caf59SThomas Veerman  *	key		A hash key.
205*2e2caf59SThomas Veerman  *
206*2e2caf59SThomas Veerman  * Results:
207*2e2caf59SThomas Veerman  *	The return value is a pointer to the entry for key,
208*2e2caf59SThomas Veerman  *	if key was present in the table.  If key was not
209*2e2caf59SThomas Veerman  *	present, NULL is returned.
210*2e2caf59SThomas Veerman  *
211*2e2caf59SThomas Veerman  * Side Effects:
212*2e2caf59SThomas Veerman  *	None.
213*2e2caf59SThomas Veerman  *
214*2e2caf59SThomas Veerman  *---------------------------------------------------------
215*2e2caf59SThomas Veerman  */
216*2e2caf59SThomas Veerman 
217*2e2caf59SThomas Veerman Hash_Entry *
218*2e2caf59SThomas Veerman Hash_FindEntry(Hash_Table *t, const char *key)
219*2e2caf59SThomas Veerman {
220*2e2caf59SThomas Veerman 	Hash_Entry *e;
221*2e2caf59SThomas Veerman 	unsigned h;
222*2e2caf59SThomas Veerman 	const char *p;
223*2e2caf59SThomas Veerman 
224*2e2caf59SThomas Veerman 	for (h = 0, p = key; *p;)
225*2e2caf59SThomas Veerman 		h = (h << 5) - h + *p++;
226*2e2caf59SThomas Veerman 	p = key;
227*2e2caf59SThomas Veerman 	for (e = t->bucketPtr[h & t->mask]; e != NULL; e = e->next)
228*2e2caf59SThomas Veerman 		if (e->namehash == h && strcmp(e->name, p) == 0)
229*2e2caf59SThomas Veerman 			return (e);
230*2e2caf59SThomas Veerman 	return NULL;
231*2e2caf59SThomas Veerman }
232*2e2caf59SThomas Veerman 
233*2e2caf59SThomas Veerman /*
234*2e2caf59SThomas Veerman  *---------------------------------------------------------
235*2e2caf59SThomas Veerman  *
236*2e2caf59SThomas Veerman  * Hash_CreateEntry --
237*2e2caf59SThomas Veerman  *
238*2e2caf59SThomas Veerman  *	Searches a hash table for an entry corresponding to
239*2e2caf59SThomas Veerman  *	key.  If no entry is found, then one is created.
240*2e2caf59SThomas Veerman  *
241*2e2caf59SThomas Veerman  * Input:
242*2e2caf59SThomas Veerman  *	t		Hash table to search.
243*2e2caf59SThomas Veerman  *	key		A hash key.
244*2e2caf59SThomas Veerman  *	newPtr		Filled in with TRUE if new entry created,
245*2e2caf59SThomas Veerman  *			FALSE otherwise.
246*2e2caf59SThomas Veerman  *
247*2e2caf59SThomas Veerman  * Results:
248*2e2caf59SThomas Veerman  *	The return value is a pointer to the entry.  If *newPtr
249*2e2caf59SThomas Veerman  *	isn't NULL, then *newPtr is filled in with TRUE if a
250*2e2caf59SThomas Veerman  *	new entry was created, and FALSE if an entry already existed
251*2e2caf59SThomas Veerman  *	with the given key.
252*2e2caf59SThomas Veerman  *
253*2e2caf59SThomas Veerman  * Side Effects:
254*2e2caf59SThomas Veerman  *	Memory may be allocated, and the hash buckets may be modified.
255*2e2caf59SThomas Veerman  *---------------------------------------------------------
256*2e2caf59SThomas Veerman  */
257*2e2caf59SThomas Veerman 
258*2e2caf59SThomas Veerman Hash_Entry *
259*2e2caf59SThomas Veerman Hash_CreateEntry(Hash_Table *t, const char *key, Boolean *newPtr)
260*2e2caf59SThomas Veerman {
261*2e2caf59SThomas Veerman 	Hash_Entry *e;
262*2e2caf59SThomas Veerman 	unsigned h;
263*2e2caf59SThomas Veerman 	const char *p;
264*2e2caf59SThomas Veerman 	int keylen;
265*2e2caf59SThomas Veerman 	struct Hash_Entry **hp;
266*2e2caf59SThomas Veerman 
267*2e2caf59SThomas Veerman 	/*
268*2e2caf59SThomas Veerman 	 * Hash the key.  As a side effect, save the length (strlen) of the
269*2e2caf59SThomas Veerman 	 * key in case we need to create the entry.
270*2e2caf59SThomas Veerman 	 */
271*2e2caf59SThomas Veerman 	for (h = 0, p = key; *p;)
272*2e2caf59SThomas Veerman 		h = (h << 5) - h + *p++;
273*2e2caf59SThomas Veerman 	keylen = p - key;
274*2e2caf59SThomas Veerman 	p = key;
275*2e2caf59SThomas Veerman 	for (e = t->bucketPtr[h & t->mask]; e != NULL; e = e->next) {
276*2e2caf59SThomas Veerman 		if (e->namehash == h && strcmp(e->name, p) == 0) {
277*2e2caf59SThomas Veerman 			if (newPtr != NULL)
278*2e2caf59SThomas Veerman 				*newPtr = FALSE;
279*2e2caf59SThomas Veerman 			return (e);
280*2e2caf59SThomas Veerman 		}
281*2e2caf59SThomas Veerman 	}
282*2e2caf59SThomas Veerman 
283*2e2caf59SThomas Veerman 	/*
284*2e2caf59SThomas Veerman 	 * The desired entry isn't there.  Before allocating a new entry,
285*2e2caf59SThomas Veerman 	 * expand the table if necessary (and this changes the resulting
286*2e2caf59SThomas Veerman 	 * bucket chain).
287*2e2caf59SThomas Veerman 	 */
288*2e2caf59SThomas Veerman 	if (t->numEntries >= rebuildLimit * t->size)
289*2e2caf59SThomas Veerman 		RebuildTable(t);
290*2e2caf59SThomas Veerman 	e = bmake_malloc(sizeof(*e) + keylen);
291*2e2caf59SThomas Veerman 	hp = &t->bucketPtr[h & t->mask];
292*2e2caf59SThomas Veerman 	e->next = *hp;
293*2e2caf59SThomas Veerman 	*hp = e;
294*2e2caf59SThomas Veerman 	Hash_SetValue(e, NULL);
295*2e2caf59SThomas Veerman 	e->namehash = h;
296*2e2caf59SThomas Veerman 	(void)strcpy(e->name, p);
297*2e2caf59SThomas Veerman 	t->numEntries++;
298*2e2caf59SThomas Veerman 
299*2e2caf59SThomas Veerman 	if (newPtr != NULL)
300*2e2caf59SThomas Veerman 		*newPtr = TRUE;
301*2e2caf59SThomas Veerman 	return (e);
302*2e2caf59SThomas Veerman }
303*2e2caf59SThomas Veerman 
304*2e2caf59SThomas Veerman /*
305*2e2caf59SThomas Veerman  *---------------------------------------------------------
306*2e2caf59SThomas Veerman  *
307*2e2caf59SThomas Veerman  * Hash_DeleteEntry --
308*2e2caf59SThomas Veerman  *
309*2e2caf59SThomas Veerman  * 	Delete the given hash table entry and free memory associated with
310*2e2caf59SThomas Veerman  *	it.
311*2e2caf59SThomas Veerman  *
312*2e2caf59SThomas Veerman  * Results:
313*2e2caf59SThomas Veerman  *	None.
314*2e2caf59SThomas Veerman  *
315*2e2caf59SThomas Veerman  * Side Effects:
316*2e2caf59SThomas Veerman  *	Hash chain that entry lives in is modified and memory is freed.
317*2e2caf59SThomas Veerman  *
318*2e2caf59SThomas Veerman  *---------------------------------------------------------
319*2e2caf59SThomas Veerman  */
320*2e2caf59SThomas Veerman 
321*2e2caf59SThomas Veerman void
322*2e2caf59SThomas Veerman Hash_DeleteEntry(Hash_Table *t, Hash_Entry *e)
323*2e2caf59SThomas Veerman {
324*2e2caf59SThomas Veerman 	Hash_Entry **hp, *p;
325*2e2caf59SThomas Veerman 
326*2e2caf59SThomas Veerman 	if (e == NULL)
327*2e2caf59SThomas Veerman 		return;
328*2e2caf59SThomas Veerman 	for (hp = &t->bucketPtr[e->namehash & t->mask];
329*2e2caf59SThomas Veerman 	     (p = *hp) != NULL; hp = &p->next) {
330*2e2caf59SThomas Veerman 		if (p == e) {
331*2e2caf59SThomas Veerman 			*hp = p->next;
332*2e2caf59SThomas Veerman 			free(p);
333*2e2caf59SThomas Veerman 			t->numEntries--;
334*2e2caf59SThomas Veerman 			return;
335*2e2caf59SThomas Veerman 		}
336*2e2caf59SThomas Veerman 	}
337*2e2caf59SThomas Veerman 	(void)write(2, "bad call to Hash_DeleteEntry\n", 29);
338*2e2caf59SThomas Veerman 	abort();
339*2e2caf59SThomas Veerman }
340*2e2caf59SThomas Veerman 
341*2e2caf59SThomas Veerman /*
342*2e2caf59SThomas Veerman  *---------------------------------------------------------
343*2e2caf59SThomas Veerman  *
344*2e2caf59SThomas Veerman  * Hash_EnumFirst --
345*2e2caf59SThomas Veerman  *	This procedure sets things up for a complete search
346*2e2caf59SThomas Veerman  *	of all entries recorded in the hash table.
347*2e2caf59SThomas Veerman  *
348*2e2caf59SThomas Veerman  * Input:
349*2e2caf59SThomas Veerman  *	t		Table to be searched.
350*2e2caf59SThomas Veerman  *	searchPtr	Area in which to keep state about search.
351*2e2caf59SThomas Veerman  *
352*2e2caf59SThomas Veerman  * Results:
353*2e2caf59SThomas Veerman  *	The return value is the address of the first entry in
354*2e2caf59SThomas Veerman  *	the hash table, or NULL if the table is empty.
355*2e2caf59SThomas Veerman  *
356*2e2caf59SThomas Veerman  * Side Effects:
357*2e2caf59SThomas Veerman  *	The information in searchPtr is initialized so that successive
358*2e2caf59SThomas Veerman  *	calls to Hash_Next will return successive HashEntry's
359*2e2caf59SThomas Veerman  *	from the table.
360*2e2caf59SThomas Veerman  *
361*2e2caf59SThomas Veerman  *---------------------------------------------------------
362*2e2caf59SThomas Veerman  */
363*2e2caf59SThomas Veerman 
364*2e2caf59SThomas Veerman Hash_Entry *
365*2e2caf59SThomas Veerman Hash_EnumFirst(Hash_Table *t, Hash_Search *searchPtr)
366*2e2caf59SThomas Veerman {
367*2e2caf59SThomas Veerman 	searchPtr->tablePtr = t;
368*2e2caf59SThomas Veerman 	searchPtr->nextIndex = 0;
369*2e2caf59SThomas Veerman 	searchPtr->hashEntryPtr = NULL;
370*2e2caf59SThomas Veerman 	return Hash_EnumNext(searchPtr);
371*2e2caf59SThomas Veerman }
372*2e2caf59SThomas Veerman 
373*2e2caf59SThomas Veerman /*
374*2e2caf59SThomas Veerman  *---------------------------------------------------------
375*2e2caf59SThomas Veerman  *
376*2e2caf59SThomas Veerman  * Hash_EnumNext --
377*2e2caf59SThomas Veerman  *    This procedure returns successive entries in the hash table.
378*2e2caf59SThomas Veerman  *
379*2e2caf59SThomas Veerman  * Input:
380*2e2caf59SThomas Veerman  *	searchPtr	Area used to keep state about search.
381*2e2caf59SThomas Veerman  *
382*2e2caf59SThomas Veerman  * Results:
383*2e2caf59SThomas Veerman  *    The return value is a pointer to the next HashEntry
384*2e2caf59SThomas Veerman  *    in the table, or NULL when the end of the table is
385*2e2caf59SThomas Veerman  *    reached.
386*2e2caf59SThomas Veerman  *
387*2e2caf59SThomas Veerman  * Side Effects:
388*2e2caf59SThomas Veerman  *    The information in searchPtr is modified to advance to the
389*2e2caf59SThomas Veerman  *    next entry.
390*2e2caf59SThomas Veerman  *
391*2e2caf59SThomas Veerman  *---------------------------------------------------------
392*2e2caf59SThomas Veerman  */
393*2e2caf59SThomas Veerman 
394*2e2caf59SThomas Veerman Hash_Entry *
395*2e2caf59SThomas Veerman Hash_EnumNext(Hash_Search *searchPtr)
396*2e2caf59SThomas Veerman {
397*2e2caf59SThomas Veerman 	Hash_Entry *e;
398*2e2caf59SThomas Veerman 	Hash_Table *t = searchPtr->tablePtr;
399*2e2caf59SThomas Veerman 
400*2e2caf59SThomas Veerman 	/*
401*2e2caf59SThomas Veerman 	 * The hashEntryPtr field points to the most recently returned
402*2e2caf59SThomas Veerman 	 * entry, or is nil if we are starting up.  If not nil, we have
403*2e2caf59SThomas Veerman 	 * to start at the next one in the chain.
404*2e2caf59SThomas Veerman 	 */
405*2e2caf59SThomas Veerman 	e = searchPtr->hashEntryPtr;
406*2e2caf59SThomas Veerman 	if (e != NULL)
407*2e2caf59SThomas Veerman 		e = e->next;
408*2e2caf59SThomas Veerman 	/*
409*2e2caf59SThomas Veerman 	 * If the chain ran out, or if we are starting up, we need to
410*2e2caf59SThomas Veerman 	 * find the next nonempty chain.
411*2e2caf59SThomas Veerman 	 */
412*2e2caf59SThomas Veerman 	while (e == NULL) {
413*2e2caf59SThomas Veerman 		if (searchPtr->nextIndex >= t->size)
414*2e2caf59SThomas Veerman 			return NULL;
415*2e2caf59SThomas Veerman 		e = t->bucketPtr[searchPtr->nextIndex++];
416*2e2caf59SThomas Veerman 	}
417*2e2caf59SThomas Veerman 	searchPtr->hashEntryPtr = e;
418*2e2caf59SThomas Veerman 	return (e);
419*2e2caf59SThomas Veerman }
420*2e2caf59SThomas Veerman 
421*2e2caf59SThomas Veerman /*
422*2e2caf59SThomas Veerman  *---------------------------------------------------------
423*2e2caf59SThomas Veerman  *
424*2e2caf59SThomas Veerman  * RebuildTable --
425*2e2caf59SThomas Veerman  *	This local routine makes a new hash table that
426*2e2caf59SThomas Veerman  *	is larger than the old one.
427*2e2caf59SThomas Veerman  *
428*2e2caf59SThomas Veerman  * Results:
429*2e2caf59SThomas Veerman  * 	None.
430*2e2caf59SThomas Veerman  *
431*2e2caf59SThomas Veerman  * Side Effects:
432*2e2caf59SThomas Veerman  *	The entire hash table is moved, so any bucket numbers
433*2e2caf59SThomas Veerman  *	from the old table are invalid.
434*2e2caf59SThomas Veerman  *
435*2e2caf59SThomas Veerman  *---------------------------------------------------------
436*2e2caf59SThomas Veerman  */
437*2e2caf59SThomas Veerman 
438*2e2caf59SThomas Veerman static void
439*2e2caf59SThomas Veerman RebuildTable(Hash_Table *t)
440*2e2caf59SThomas Veerman {
441*2e2caf59SThomas Veerman 	Hash_Entry *e, *next = NULL, **hp, **xp;
442*2e2caf59SThomas Veerman 	int i, mask;
443*2e2caf59SThomas Veerman         Hash_Entry **oldhp;
444*2e2caf59SThomas Veerman 	int oldsize;
445*2e2caf59SThomas Veerman 
446*2e2caf59SThomas Veerman 	oldhp = t->bucketPtr;
447*2e2caf59SThomas Veerman 	oldsize = i = t->size;
448*2e2caf59SThomas Veerman 	i <<= 1;
449*2e2caf59SThomas Veerman 	t->size = i;
450*2e2caf59SThomas Veerman 	t->mask = mask = i - 1;
451*2e2caf59SThomas Veerman 	t->bucketPtr = hp = bmake_malloc(sizeof(*hp) * i);
452*2e2caf59SThomas Veerman 	while (--i >= 0)
453*2e2caf59SThomas Veerman 		*hp++ = NULL;
454*2e2caf59SThomas Veerman 	for (hp = oldhp, i = oldsize; --i >= 0;) {
455*2e2caf59SThomas Veerman 		for (e = *hp++; e != NULL; e = next) {
456*2e2caf59SThomas Veerman 			next = e->next;
457*2e2caf59SThomas Veerman 			xp = &t->bucketPtr[e->namehash & mask];
458*2e2caf59SThomas Veerman 			e->next = *xp;
459*2e2caf59SThomas Veerman 			*xp = e;
460*2e2caf59SThomas Veerman 		}
461*2e2caf59SThomas Veerman 	}
462*2e2caf59SThomas Veerman 	free(oldhp);
463*2e2caf59SThomas Veerman }
464