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