]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/make/hash.c
Style: remove a lot of unnecessary casts, add some and spell the null
[FreeBSD/FreeBSD.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  */
41
42 #include <sys/cdefs.h>
43 __FBSDID("$FreeBSD$");
44
45 /* hash.c --
46  *
47  *      This module contains routines to manipulate a hash table.
48  *      See hash.h for a definition of the structure of the hash
49  *      table.  Hash tables grow automatically as the amount of
50  *      information increases.
51  */
52 #include <unistd.h>
53 #include "sprite.h"
54 #include "make.h"
55 #include "hash.h"
56
57 /*
58  * Forward references to local procedures that are used before they're
59  * defined:
60  */
61
62 static void RebuildTable(Hash_Table *);
63
64 /*
65  * The following defines the ratio of # entries to # buckets
66  * at which we rebuild the table to make it larger.
67  */
68
69 #define rebuildLimit 8
70
71 /*
72  *---------------------------------------------------------
73  *
74  * Hash_InitTable --
75  *
76  *      Set up the hash table t with a given number of buckets, or a
77  *      reasonable default if the number requested is less than or
78  *      equal to zero.  Hash tables will grow in size as needed.
79  *
80  *
81  * Results:
82  *      None.
83  *
84  * Side Effects:
85  *      Memory is allocated for the initial bucket area.
86  *
87  *---------------------------------------------------------
88  */
89
90 void
91 Hash_InitTable(Hash_Table *t, int numBuckets)
92 {
93         int i;
94         struct Hash_Entry **hp;
95
96         /*
97          * Round up the size to a power of two.
98          */
99         if (numBuckets <= 0)
100                 i = 16;
101         else {
102                 for (i = 2; i < numBuckets; i <<= 1)
103                          continue;
104         }
105         t->numEntries = 0;
106         t->size = i;
107         t->mask = i - 1;
108         t->bucketPtr = hp = emalloc(sizeof(*hp) * i);
109         while (--i >= 0)
110                 *hp++ = NULL;
111 }
112
113 /*
114  *---------------------------------------------------------
115  *
116  * Hash_DeleteTable --
117  *
118  *      This routine removes everything from a hash table
119  *      and frees up the memory space it occupied (except for
120  *      the space in the Hash_Table structure).
121  *
122  * Results:
123  *      None.
124  *
125  * Side Effects:
126  *      Lots of memory is freed up.
127  *
128  *---------------------------------------------------------
129  */
130 void
131 Hash_DeleteTable(Hash_Table *t)
132 {
133         struct Hash_Entry **hp, *h, *nexth = NULL;
134         int i;
135
136         for (hp = t->bucketPtr, i = t->size; --i >= 0;) {
137                 for (h = *hp++; h != NULL; h = nexth) {
138                         nexth = h->next;
139                         free(h);
140                 }
141         }
142         free(t->bucketPtr);
143
144         /*
145          * Set up the hash table to cause memory faults on any future access
146          * attempts until re-initialization.
147          */
148         t->bucketPtr = NULL;
149 }
150
151 /*
152  *---------------------------------------------------------
153  *
154  * Hash_FindEntry --
155  *
156  *      Searches a hash table for an entry corresponding to key.
157  *
158  * Results:
159  *      The return value is a pointer to the entry for key,
160  *      if key was present in the table.  If key was not
161  *      present, NULL is returned.
162  *
163  * Side Effects:
164  *      None.
165  *
166  *---------------------------------------------------------
167  */
168 Hash_Entry *
169 Hash_FindEntry(Hash_Table *t, char *key)
170 {
171         Hash_Entry *e;
172         unsigned h;
173         char *p;
174
175         for (h = 0, p = key; *p;)
176                 h = (h << 5) - h + *p++;
177         p = key;
178         for (e = t->bucketPtr[h & t->mask]; e != NULL; e = e->next)
179                 if (e->namehash == h && strcmp(e->name, p) == 0)
180                         return (e);
181         return (NULL);
182 }
183
184 /*
185  *---------------------------------------------------------
186  *
187  * Hash_CreateEntry --
188  *
189  *      Searches a hash table for an entry corresponding to
190  *      key.  If no entry is found, then one is created.
191  *
192  * Results:
193  *      The return value is a pointer to the entry.  If *newPtr
194  *      isn't NULL, then *newPtr is filled in with TRUE if a
195  *      new entry was created, and FALSE if an entry already existed
196  *      with the given key.
197  *
198  * Side Effects:
199  *      Memory may be allocated, and the hash buckets may be modified.
200  *---------------------------------------------------------
201  */
202 Hash_Entry *
203 Hash_CreateEntry(Hash_Table *t, char *key, Boolean *newPtr)
204 {
205         Hash_Entry *e;
206         unsigned int h;
207         char *p;
208         int keylen;
209         struct Hash_Entry **hp;
210
211         /*
212          * Hash the key.  As a side effect, save the length (strlen) of the
213          * key in case we need to create the entry.
214          */
215         for (h = 0, p = key; *p;)
216                 h = (h << 5) - h + *p++;
217         keylen = p - key;
218         p = key;
219         for (e = t->bucketPtr[h & t->mask]; e != NULL; e = e->next) {
220                 if (e->namehash == h && strcmp(e->name, p) == 0) {
221                         if (newPtr != NULL)
222                                 *newPtr = FALSE;
223                         return (e);
224                 }
225         }
226
227         /*
228          * The desired entry isn't there.  Before allocating a new entry,
229          * expand the table if necessary (and this changes the resulting
230          * bucket chain).
231          */
232         if (t->numEntries >= rebuildLimit * t->size)
233                 RebuildTable(t);
234         e = emalloc(sizeof(*e) + keylen);
235         hp = &t->bucketPtr[h & t->mask];
236         e->next = *hp;
237         *hp = e;
238         e->clientData = NULL;
239         e->namehash = h;
240         strcpy(e->name, p);
241         t->numEntries++;
242
243         if (newPtr != NULL)
244                 *newPtr = TRUE;
245         return (e);
246 }
247
248 /*
249  *---------------------------------------------------------
250  *
251  * Hash_DeleteEntry --
252  *
253  *      Delete the given hash table entry and free memory associated with
254  *      it.
255  *
256  * Results:
257  *      None.
258  *
259  * Side Effects:
260  *      Hash chain that entry lives in is modified and memory is freed.
261  *
262  *---------------------------------------------------------
263  */
264 void
265 Hash_DeleteEntry(Hash_Table *t, Hash_Entry *e)
266 {
267         Hash_Entry **hp, *p;
268
269         if (e == NULL)
270                 return;
271         for (hp = &t->bucketPtr[e->namehash & t->mask];
272              (p = *hp) != NULL; hp = &p->next) {
273                 if (p == e) {
274                         *hp = p->next;
275                         free(p);
276                         t->numEntries--;
277                         return;
278                 }
279         }
280         write(STDERR_FILENO, "bad call to Hash_DeleteEntry\n", 29);
281         abort();
282 }
283
284 /*
285  *---------------------------------------------------------
286  *
287  * Hash_EnumFirst --
288  *      This procedure sets things up for a complete search
289  *      of all entries recorded in the hash table.
290  *
291  * Results:
292  *      The return value is the address of the first entry in
293  *      the hash table, or NULL if the table is empty.
294  *
295  * Side Effects:
296  *      The information in searchPtr is initialized so that successive
297  *      calls to Hash_Next will return successive HashEntry's
298  *      from the table.
299  *
300  *---------------------------------------------------------
301  */
302 Hash_Entry *
303 Hash_EnumFirst(Hash_Table *t, Hash_Search *searchPtr)
304 {
305
306         searchPtr->tablePtr = t;
307         searchPtr->nextIndex = 0;
308         searchPtr->hashEntryPtr = NULL;
309         return (Hash_EnumNext(searchPtr));
310 }
311
312 /*
313  *---------------------------------------------------------
314  *
315  * Hash_EnumNext --
316  *    This procedure returns successive entries in the hash table.
317  *
318  * Results:
319  *    The return value is a pointer to the next HashEntry
320  *    in the table, or NULL when the end of the table is
321  *    reached.
322  *
323  * Side Effects:
324  *    The information in searchPtr is modified to advance to the
325  *    next entry.
326  *
327  *---------------------------------------------------------
328  */
329 Hash_Entry *
330 Hash_EnumNext(Hash_Search *searchPtr)
331 {
332         Hash_Entry *e;
333         Hash_Table *t = searchPtr->tablePtr;
334
335         /*
336          * The hashEntryPtr field points to the most recently returned
337          * entry, or is NULL if we are starting up.  If not NULL, we have
338          * to start at the next one in the chain.
339          */
340         e = searchPtr->hashEntryPtr;
341         if (e != NULL)
342                 e = e->next;
343         /*
344          * If the chain ran out, or if we are starting up, we need to
345          * find the next nonempty chain.
346          */
347         while (e == NULL) {
348                 if (searchPtr->nextIndex >= t->size)
349                         return (NULL);
350                 e = t->bucketPtr[searchPtr->nextIndex++];
351         }
352         searchPtr->hashEntryPtr = e;
353         return (e);
354 }
355
356 /*
357  *---------------------------------------------------------
358  *
359  * RebuildTable --
360  *      This local routine makes a new hash table that
361  *      is larger than the old one.
362  *
363  * Results:
364  *      None.
365  *
366  * Side Effects:
367  *      The entire hash table is moved, so any bucket numbers
368  *      from the old table are invalid.
369  *
370  *---------------------------------------------------------
371  */
372 static void
373 RebuildTable(Hash_Table *t)
374 {
375         Hash_Entry *e, *next = NULL, **hp, **xp;
376         int i, mask;
377         Hash_Entry **oldhp;
378         int oldsize;
379
380         oldhp = t->bucketPtr;
381         oldsize = i = t->size;
382         i <<= 1;
383         t->size = i;
384         t->mask = mask = i - 1;
385         t->bucketPtr = hp = emalloc(sizeof(*hp) * i);
386         while (--i >= 0)
387                 *hp++ = NULL;
388         for (hp = oldhp, i = oldsize; --i >= 0;) {
389                 for (e = *hp++; e != NULL; e = next) {
390                         next = e->next;
391                         xp = &t->bucketPtr[e->namehash & mask];
392                         e->next = *xp;
393                         *xp = e;
394                 }
395         }
396         free(oldhp);
397 }