Move ProcExec() into proc.c
[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.24 2005/02/01 10:50:35 harti Exp $
41  * $DragonFly: src/usr.bin/make/hash.c,v 1.17 2005/05/05 09:06:23 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 "hash.h"
57 #include "util.h"
58
59 /*
60  * Forward references to local procedures that are used before they're
61  * defined:
62  */
63 static void RebuildTable(Hash_Table *);
64
65 /*
66  * The following defines the ratio of # entries to # buckets
67  * at which we rebuild the table to make it larger.
68  */
69
70 #define rebuildLimit 8
71
72 /*
73  *---------------------------------------------------------
74  *
75  * Hash_InitTable --
76  *
77  *      Set up the hash table t with a given number of buckets, or a
78  *      reasonable default if the number requested is less than or
79  *      equal to zero.  Hash tables will grow in size as needed.
80  *
81  *
82  * Results:
83  *      None.
84  *
85  * Side Effects:
86  *      Memory is allocated for the initial bucket area.
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(const Hash_Table *t, const char *key)
170 {
171         Hash_Entry *e;
172         unsigned h;
173         const 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, const char *key, Boolean *newPtr)
204 {
205         Hash_Entry *e;
206         unsigned int h;
207         const 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(const 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         const 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 }