1 /* hash.c -- hash table maintenance
2 Copyright (C) 1995, 1999, 2002 Free Software Foundation, Inc.
3 Written by Greg McGary <gkm@gnu.org> <greg@mcgary.org>
5 GNU Make is free software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3 of the License, or (at your option) any later
10 GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License along with
15 this program. If not, see <http://www.gnu.org/licenses/>. */
19 #ifdef CONFIG_WITH_STRCACHE2
24 #define CALLOC(t, n) ((t *) calloc (sizeof (t), (n)))
25 #define MALLOC(t, n) ((t *) xmalloc (sizeof (t) * (n)))
26 #define REALLOC(o, t, n) ((t *) xrealloc ((o), sizeof (t) * (n)))
27 #define CLONE(o, t, n) ((t *) memcpy (MALLOC (t, (n)), (o), sizeof (t) * (n)))
29 static void hash_rehash
__P((struct hash_table
* ht
));
30 static unsigned long round_up_2
__P((unsigned long rough
));
32 /* Implement double hashing with open addressing. The table size is
33 always a power of two. The secondary (`increment') hash function
34 is forced to return an odd-value, in order to be relatively prime
35 to the table size. This guarantees that the increment can
36 potentially hit every slot in the table during collision
39 void *hash_deleted_item
= &hash_deleted_item
;
41 /* Force the table size to be a power of two, possibly rounding up the
45 hash_init (struct hash_table
*ht
, unsigned long size
,
46 hash_func_t hash_1
, hash_func_t hash_2
, hash_cmp_func_t hash_cmp
)
48 ht
->ht_size
= round_up_2 (size
);
49 ht
->ht_empty_slots
= ht
->ht_size
;
50 ht
->ht_vec
= (void**) CALLOC (struct token
*, ht
->ht_size
);
53 fprintf (stderr
, _("can't allocate %ld bytes for hash table: memory exhausted"),
54 ht
->ht_size
* sizeof(struct token
*));
58 ht
->ht_capacity
= ht
->ht_size
- (ht
->ht_size
/ 16); /* 93.75% loading factor */
60 ht
->ht_collisions
= 0;
63 ht
->ht_hash_1
= hash_1
;
64 ht
->ht_hash_2
= hash_2
;
65 ht
->ht_compare
= hash_cmp
;
66 #ifdef CONFIG_WITH_STRCACHE2
68 ht
->ht_off_string
= 0;
72 #ifdef CONFIG_WITH_STRCACHE2
73 /* Same as hash_init, except that no callbacks are needed since all
74 keys - including the ones being searched for - are from a string
75 cache. This means that any give string will only have one pointer
76 value and that the hash and length can be retrived very cheaply,
77 thus permitting some nice optimizations.
79 STRCACHE points to the string cache, while OFF_STRING gives the
80 offset of the string pointer in the item structures the hash table
82 void hash_init_strcached (struct hash_table
*ht
, unsigned long size
,
83 struct strcache2
*strcache
, unsigned int off_string
)
85 hash_init (ht
, size
, 0, 0, 0);
86 ht
->ht_strcache
= strcache
;
87 ht
->ht_off_string
= off_string
;
89 #endif /* CONFIG_WITH_STRCACHE2 */
91 /* Load an array of items into `ht'. */
94 hash_load (struct hash_table
*ht
, void *item_table
,
95 unsigned long cardinality
, unsigned long size
)
97 char *items
= (char *) item_table
;
98 #ifndef CONFIG_WITH_STRCACHE2
101 hash_insert (ht
, items
);
104 #else /* CONFIG_WITH_STRCACHE2 */
106 while (cardinality
--)
108 hash_insert_strcached (ht
, items
);
112 while (cardinality
--)
114 hash_insert (ht
, items
);
117 #endif /* CONFIG_WITH_STRCACHE2 */
120 /* Returns the address of the table slot matching `key'. If `key' is
121 not found, return the address of an empty slot suitable for
122 inserting `key'. The caller is responsible for incrementing
123 ht_fill on insertion. */
126 hash_find_slot (struct hash_table
*ht
, const void *key
)
129 void **deleted_slot
= 0;
130 unsigned int hash_2
= 0;
131 unsigned int hash_1
= (*ht
->ht_hash_1
) (key
);
133 #ifdef CONFIG_WITH_STRCACHE2
134 assert (ht
->ht_strcache
== 0);
137 MAKE_STATS (ht
->ht_lookups
++);
138 MAKE_STATS_3 (make_stats_ht_lookups
++);
141 hash_1
&= (ht
->ht_size
- 1);
142 slot
= &ht
->ht_vec
[hash_1
];
145 return (deleted_slot
? deleted_slot
: slot
);
146 if (*slot
== hash_deleted_item
)
148 if (deleted_slot
== 0)
155 if ((*ht
->ht_compare
) (key
, *slot
) == 0)
157 MAKE_STATS (ht
->ht_collisions
++);
158 MAKE_STATS_3 (make_stats_ht_collisions
++);
161 hash_2
= (*ht
->ht_hash_2
) (key
) | 1;
166 #ifdef CONFIG_WITH_STRCACHE2
167 /* hash_find_slot version for tables created with hash_init_strcached. */
169 hash_find_slot_strcached (struct hash_table
*ht
, const void *key
)
172 void **deleted_slot
= 0;
173 const char *str1
= *(const char **)((const char *)key
+ ht
->ht_off_string
);
175 unsigned int hash_1
= strcache2_calc_ptr_hash (ht
->ht_strcache
, str1
);
178 #ifdef CONFIG_WITH_STRCACHE2
179 assert (ht
->ht_strcache
!= 0);
182 MAKE_STATS (ht
->ht_lookups
++);
183 MAKE_STATS_3 (make_stats_ht_lookups
++);
185 /* first iteration unrolled. */
187 hash_1
&= (ht
->ht_size
- 1);
188 slot
= &ht
->ht_vec
[hash_1
];
191 if (*slot
!= hash_deleted_item
)
193 str2
= *(const char **)((const char *)(*slot
) + ht
->ht_off_string
);
197 MAKE_STATS (ht
->ht_collisions
++);
198 MAKE_STATS_3 (make_stats_ht_collisions
++);
203 /* the rest of the loop. */
205 hash_2
= strcache2_get_hash (ht
->ht_strcache
, str1
) | 1;
209 hash_1
&= (ht
->ht_size
- 1);
210 slot
= &ht
->ht_vec
[hash_1
];
213 return (deleted_slot
? deleted_slot
: slot
);
214 if (*slot
== hash_deleted_item
)
216 if (deleted_slot
== 0)
221 str2
= *(const char **)((const char *)(*slot
) + ht
->ht_off_string
);
225 MAKE_STATS (ht
->ht_collisions
++);
226 MAKE_STATS_3 (make_stats_ht_collisions
++);
232 #endif /* CONFIG_WITH_STRCACHE2 */
235 hash_find_item (struct hash_table
*ht
, const void *key
)
237 void **slot
= hash_find_slot (ht
, key
);
238 return ((HASH_VACANT (*slot
)) ? 0 : *slot
);
241 #ifdef CONFIG_WITH_STRCACHE2
243 hash_find_item_strcached (struct hash_table
*ht
, const void *key
)
245 void **slot
= hash_find_slot_strcached (ht
, key
);
246 return ((HASH_VACANT (*slot
)) ? 0 : *slot
);
248 #endif /* CONFIG_WITH_STRCACHE2 */
251 hash_insert (struct hash_table
*ht
, const void *item
)
253 void **slot
= hash_find_slot (ht
, item
);
254 const void *old_item
= slot
? *slot
: 0;
255 hash_insert_at (ht
, item
, slot
);
256 return (void *)((HASH_VACANT (old_item
)) ? 0 : old_item
);
259 #ifdef CONFIG_WITH_STRCACHE2
261 hash_insert_strcached (struct hash_table
*ht
, const void *item
)
263 void **slot
= hash_find_slot_strcached (ht
, item
);
264 const void *old_item
= slot
? *slot
: 0;
265 hash_insert_at (ht
, item
, slot
);
266 return (void *)((HASH_VACANT (old_item
)) ? 0 : old_item
);
268 #endif /* CONFIG_WITH_STRCACHE2 */
271 hash_insert_at (struct hash_table
*ht
, const void *item
, const void *slot
)
273 const void *old_item
= *(void **) slot
;
274 if (HASH_VACANT (old_item
))
278 ht
->ht_empty_slots
--;
281 *(void const **) slot
= item
;
282 if (ht
->ht_empty_slots
< ht
->ht_size
- ht
->ht_capacity
)
285 #ifdef CONFIG_WITH_STRCACHE2
287 return (void *)hash_find_slot_strcached (ht
, item
);
288 #endif /* CONFIG_WITH_STRCACHE2 */
289 return (void *) hash_find_slot (ht
, item
);
292 return (void *) slot
;
296 hash_delete (struct hash_table
*ht
, const void *item
)
298 void **slot
= hash_find_slot (ht
, item
);
299 return hash_delete_at (ht
, slot
);
302 #ifdef CONFIG_WITH_STRCACHE2
304 hash_delete_strcached (struct hash_table
*ht
, const void *item
)
306 void **slot
= hash_find_slot_strcached (ht
, item
);
307 return hash_delete_at (ht
, slot
);
309 #endif /* CONFIG_WITH_STRCACHE2 */
312 hash_delete_at (struct hash_table
*ht
, const void *slot
)
314 void *item
= *(void **) slot
;
315 if (!HASH_VACANT (item
))
317 *(void const **) slot
= hash_deleted_item
;
326 hash_free_items (struct hash_table
*ht
)
328 void **vec
= ht
->ht_vec
;
329 void **end
= &vec
[ht
->ht_size
];
330 for (; vec
< end
; vec
++)
333 if (!HASH_VACANT (item
))
338 ht
->ht_empty_slots
= ht
->ht_size
;
341 #ifdef CONFIG_WITH_ALLOC_CACHES
343 hash_free_items_cached (struct hash_table
*ht
, struct alloccache
*cache
)
345 void **vec
= ht
->ht_vec
;
346 void **end
= &vec
[ht
->ht_size
];
347 for (; vec
< end
; vec
++)
350 if (!HASH_VACANT (item
))
351 alloccache_free (cache
, item
);
355 ht
->ht_empty_slots
= ht
->ht_size
;
357 #endif /* CONFIG_WITH_ALLOC_CACHES */
360 hash_delete_items (struct hash_table
*ht
)
362 void **vec
= ht
->ht_vec
;
363 void **end
= &vec
[ht
->ht_size
];
364 for (; vec
< end
; vec
++)
367 ht
->ht_collisions
= 0;
370 ht
->ht_empty_slots
= ht
->ht_size
;
374 hash_free (struct hash_table
*ht
, int free_items
)
377 hash_free_items (ht
);
381 ht
->ht_empty_slots
= ht
->ht_size
;
388 #ifdef CONFIG_WITH_ALLOC_CACHES
390 hash_free_cached (struct hash_table
*ht
, int free_items
, struct alloccache
*cache
)
393 hash_free_items_cached (ht
, cache
);
397 ht
->ht_empty_slots
= ht
->ht_size
;
403 #endif /* CONFIG_WITH_ALLOC_CACHES */
406 hash_map (struct hash_table
*ht
, hash_map_func_t map
)
409 void **end
= &ht
->ht_vec
[ht
->ht_size
];
411 for (slot
= ht
->ht_vec
; slot
< end
; slot
++)
413 if (!HASH_VACANT (*slot
))
419 hash_map_arg (struct hash_table
*ht
, hash_map_arg_func_t map
, void *arg
)
422 void **end
= &ht
->ht_vec
[ht
->ht_size
];
424 for (slot
= ht
->ht_vec
; slot
< end
; slot
++)
426 if (!HASH_VACANT (*slot
))
431 /* Double the size of the hash table in the event of overflow... */
434 hash_rehash (struct hash_table
*ht
)
436 unsigned long old_ht_size
= ht
->ht_size
;
437 void **old_vec
= ht
->ht_vec
;
440 if (ht
->ht_fill
>= ht
->ht_capacity
)
443 ht
->ht_capacity
= ht
->ht_size
- (ht
->ht_size
>> 4);
446 ht
->ht_vec
= (void **) CALLOC (struct token
*, ht
->ht_size
);
448 #ifndef CONFIG_WITH_STRCACHE2
449 for (ovp
= old_vec
; ovp
< &old_vec
[old_ht_size
]; ovp
++)
451 if (! HASH_VACANT (*ovp
))
453 void **slot
= hash_find_slot (ht
, *ovp
);
457 #else /* CONFIG_WITH_STRCACHE2 */
459 for (ovp
= old_vec
; ovp
< &old_vec
[old_ht_size
]; ovp
++)
461 if (! HASH_VACANT (*ovp
))
463 void **slot
= hash_find_slot_strcached (ht
, *ovp
);
468 for (ovp
= old_vec
; ovp
< &old_vec
[old_ht_size
]; ovp
++)
470 if (! HASH_VACANT (*ovp
))
472 void **slot
= hash_find_slot (ht
, *ovp
);
476 #endif /* CONFIG_WITH_STRCACHE2 */
477 ht
->ht_empty_slots
= ht
->ht_size
- ht
->ht_fill
;
482 hash_print_stats (struct hash_table
*ht
, FILE *out_FILE
)
484 /* GKM FIXME: honor NO_FLOAT */
485 fprintf (out_FILE
, _("Load=%ld/%ld=%.0f%%, "), ht
->ht_fill
, ht
->ht_size
,
486 100.0 * (double) ht
->ht_fill
/ (double) ht
->ht_size
);
487 fprintf (out_FILE
, _("Rehash=%d, "), ht
->ht_rehashes
);
489 fprintf (out_FILE
, _("Collisions=%ld/%ld=%.0f%%"), ht
->ht_collisions
, ht
->ht_lookups
,
491 ? (100.0 * (double) ht
->ht_collisions
/ (double) ht
->ht_lookups
)
496 /* Dump all items into a NULL-terminated vector. Use the
497 user-supplied vector, or malloc one. */
500 hash_dump (struct hash_table
*ht
, void **vector_0
, qsort_cmp_t compare
)
504 void **end
= &ht
->ht_vec
[ht
->ht_size
];
507 vector_0
= MALLOC (void *, ht
->ht_fill
+ 1);
510 for (slot
= ht
->ht_vec
; slot
< end
; slot
++)
511 if (!HASH_VACANT (*slot
))
516 qsort (vector_0
, ht
->ht_fill
, sizeof (void *), compare
);
520 /* Round a given number up to the nearest power of 2. */
523 round_up_2 (unsigned long n
)
531 #if !defined(HAVE_LIMITS_H) || ULONG_MAX > 4294967295
532 /* We only need this on systems where unsigned long is >32 bits. */