PageRenderTime 51ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/contrib/bmake/hash.c

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