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