VirtualBox

source: kBuild/trunk/src/kmk/hash.c@ 30

Last change on this file since 30 was 25, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r24,
which included commits to RCS files with non-trunk default branches.

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette