Changeset 51 for trunk/src/kmk/hash.c
- Timestamp:
- Apr 7, 2003, 3:30:32 AM (22 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kmk/hash.c
r35 r51 18 18 * 3. All advertising materials mentioning features or use of this software 19 19 * must display the following acknowledgement: 20 * 21 * 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 22 * 4. Neither the name of the University nor the names of its contributors 23 23 * may be used to endorse or promote products derived from this software … … 39 39 #ifndef lint 40 40 #if 0 41 static char sccsid[] = "@(#)hash.c 41 static char sccsid[] = "@(#)hash.c 8.1 (Berkeley) 6/6/93"; 42 42 #else 43 43 static const char rcsid[] = 44 44 "$FreeBSD: src/usr.bin/make/hash.c,v 1.9 1999/09/11 13:08:01 hoek Exp $"; 45 45 #endif 46 #define KLIBFILEDEF rcsid 46 47 #endif /* not lint */ 47 48 48 49 /* hash.c -- 49 50 * 50 * 51 * 52 * 53 * 51 * This module contains routines to manipulate a hash table. 52 * See hash.h for a definition of the structure of the hash 53 * table. Hash tables grow automatically as the amount of 54 * information increases. 54 55 */ 55 56 #include "sprite.h" … … 76 77 * Hash_InitTable -- 77 78 * 78 * 79 * 80 * Results: 81 * 82 * 83 * Side Effects: 84 * 79 * This routine just sets up the hash table. 80 * 81 * Results: 82 * None. 83 * 84 * Side Effects: 85 * Memory is allocated for the initial bucket area. 85 86 * 86 87 *--------------------------------------------------------- … … 89 90 void 90 91 Hash_InitTable(t, numBuckets) 91 register Hash_Table *t;/* Structure to use to hold table. */92 int numBuckets;/* How many buckets to create for starters.93 94 95 96 97 { 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 92 register Hash_Table *t; /* Structure to use to hold table. */ 93 int numBuckets; /* How many buckets to create for starters. 94 * This number is rounded up to a power of 95 * two. If <= 0, a reasonable default is 96 * chosen. The table will grow in size later 97 * as needed. */ 98 { 99 register int i; 100 register struct Hash_Entry **hp; 101 102 /* 103 * Round up the size to a power of two. 104 */ 105 if (numBuckets <= 0) 106 i = 16; 107 else { 108 for (i = 2; i < numBuckets; i <<= 1) 109 continue; 110 } 111 t->numEntries = 0; 112 t->size = i; 113 t->mask = i - 1; 114 t->bucketPtr = hp = (struct Hash_Entry **)emalloc(sizeof(*hp) * i); 115 while (--i >= 0) 116 *hp++ = NULL; 116 117 } 117 118 … … 121 122 * Hash_DeleteTable -- 122 123 * 123 * 124 * 125 * 126 * 127 * Results: 128 * 129 * 130 * Side Effects: 131 * 124 * This routine removes everything from a hash table 125 * and frees up the memory space it occupied (except for 126 * the space in the Hash_Table structure). 127 * 128 * Results: 129 * None. 130 * 131 * Side Effects: 132 * Lots of memory is freed up. 132 133 * 133 134 *--------------------------------------------------------- … … 136 137 void 137 138 Hash_DeleteTable(t) 138 139 { 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 139 Hash_Table *t; 140 { 141 register struct Hash_Entry **hp, *h, *nexth = NULL; 142 register int i; 143 144 for (hp = t->bucketPtr, i = t->size; --i >= 0;) { 145 for (h = *hp++; h != NULL; h = nexth) { 146 nexth = h->next; 147 efree((char *)h); 148 } 149 } 150 efree((char *)t->bucketPtr); 151 152 /* 153 * Set up the hash table to cause memory faults on any future access 154 * attempts until re-initialization. 155 */ 156 t->bucketPtr = NULL; 156 157 } 157 158 … … 161 162 * Hash_FindEntry -- 162 163 * 163 * 164 * 165 * Results: 166 * 167 * 168 * 169 * 170 * Side Effects: 171 * 164 * Searches a hash table for an entry corresponding to key. 165 * 166 * Results: 167 * The return value is a pointer to the entry for key, 168 * if key was present in the table. If key was not 169 * present, NULL is returned. 170 * 171 * Side Effects: 172 * None. 172 173 * 173 174 *--------------------------------------------------------- … … 176 177 Hash_Entry * 177 178 Hash_FindEntry(t, key) 178 Hash_Table *t;/* Hash table to search. */179 char *key;/* A hash key. */180 { 181 182 183 184 185 186 187 188 189 190 191 179 Hash_Table *t; /* Hash table to search. */ 180 char *key; /* A hash key. */ 181 { 182 register Hash_Entry *e; 183 register unsigned h; 184 register char *p; 185 186 for (h = 0, p = key; *p;) 187 h = (h << 5) - h + *p++; 188 p = key; 189 for (e = t->bucketPtr[h & t->mask]; e != NULL; e = e->next) 190 if (e->namehash == h && strcmp(e->name, p) == 0) 191 return (e); 192 return (NULL); 192 193 } 193 194 … … 197 198 * Hash_CreateEntry -- 198 199 * 199 * 200 * 201 * 202 * Results: 203 * 204 * 205 * 206 * 207 * 208 * Side Effects: 209 * 200 * Searches a hash table for an entry corresponding to 201 * key. If no entry is found, then one is created. 202 * 203 * Results: 204 * The return value is a pointer to the entry. If *newPtr 205 * isn't NULL, then *newPtr is filled in with TRUE if a 206 * new entry was created, and FALSE if an entry already existed 207 * with the given key. 208 * 209 * Side Effects: 210 * Memory may be allocated, and the hash buckets may be modified. 210 211 *--------------------------------------------------------- 211 212 */ … … 213 214 Hash_Entry * 214 215 Hash_CreateEntry(t, key, newPtr) 215 register Hash_Table *t;/* Hash table to search. */216 char *key;/* A hash key. */217 Boolean *newPtr;/* Filled in with TRUE if new entry created,218 219 { 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 216 register Hash_Table *t; /* Hash table to search. */ 217 char *key; /* A hash key. */ 218 Boolean *newPtr; /* Filled in with TRUE if new entry created, 219 * FALSE otherwise. */ 220 { 221 register Hash_Entry *e; 222 register unsigned h; 223 register char *p; 224 int keylen; 225 struct Hash_Entry **hp; 226 227 /* 228 * Hash the key. As a side effect, save the length (strlen) of the 229 * key in case we need to create the entry. 230 */ 231 for (h = 0, p = key; *p;) 232 h = (h << 5) - h + *p++; 233 keylen = p - key; 234 p = key; 235 for (e = t->bucketPtr[h & t->mask]; e != NULL; e = e->next) { 236 if (e->namehash == h && strcmp(e->name, p) == 0) { 237 if (newPtr != NULL) 238 *newPtr = FALSE; 239 return (e); 240 } 241 } 242 243 /* 244 * The desired entry isn't there. Before allocating a new entry, 245 * expand the table if necessary (and this changes the resulting 246 * bucket chain). 247 */ 248 if (t->numEntries >= rebuildLimit * t->size) 249 RebuildTable(t); 250 e = (Hash_Entry *) emalloc(sizeof(*e) + keylen); 251 hp = &t->bucketPtr[h & t->mask]; 252 e->next = *hp; 253 *hp = e; 254 e->clientData = NULL; 255 e->namehash = h; 256 (void) strcpy(e->name, p); 257 t->numEntries++; 258 259 if (newPtr != NULL) 260 *newPtr = TRUE; 261 return (e); 261 262 } 262 263 … … 266 267 * Hash_DeleteEntry -- 267 268 * 268 * 269 * 270 * 271 * Results: 272 * 273 * 274 * Side Effects: 275 * 269 * Delete the given hash table entry and efree memory associated with 270 * it. 271 * 272 * Results: 273 * None. 274 * 275 * Side Effects: 276 * Hash chain that entry lives in is modified and memory is freed. 276 277 * 277 278 *--------------------------------------------------------- … … 280 281 void 281 282 Hash_DeleteEntry(t, e) 282 283 284 { 285 286 287 288 289 290 291 292 293 294 295 296 297 298 (void) write(2, "bad call to Hash_DeleteEntry\n", 29);299 283 Hash_Table *t; 284 Hash_Entry *e; 285 { 286 register Hash_Entry **hp, *p; 287 288 if (e == NULL) 289 return; 290 for (hp = &t->bucketPtr[e->namehash & t->mask]; 291 (p = *hp) != NULL; hp = &p->next) { 292 if (p == e) { 293 *hp = p->next; 294 efree((char *)p); 295 t->numEntries--; 296 return; 297 } 298 } 299 (void) write(STDERR_FILENO, "bad call to Hash_DeleteEntry\n", 29); 300 abort(); 300 301 } 301 302 … … 304 305 * 305 306 * Hash_EnumFirst -- 306 * 307 * 308 * 309 * Results: 310 * 311 * 312 * 313 * Side Effects: 314 * 315 * 316 * 307 * This procedure sets things up for a complete search 308 * of all entries recorded in the hash table. 309 * 310 * Results: 311 * The return value is the address of the first entry in 312 * the hash table, or NULL if the table is empty. 313 * 314 * Side Effects: 315 * The information in searchPtr is initialized so that successive 316 * calls to Hash_Next will return successive HashEntry's 317 * from the table. 317 318 * 318 319 *--------------------------------------------------------- … … 321 322 Hash_Entry * 322 323 Hash_EnumFirst(t, searchPtr) 323 Hash_Table *t;/* Table to be searched. */324 325 326 { 327 328 329 330 324 Hash_Table *t; /* Table to be searched. */ 325 register Hash_Search *searchPtr;/* Area in which to keep state 326 * about search.*/ 327 { 328 searchPtr->tablePtr = t; 329 searchPtr->nextIndex = 0; 330 searchPtr->hashEntryPtr = NULL; 331 return Hash_EnumNext(searchPtr); 331 332 } 332 333 … … 351 352 Hash_Entry * 352 353 Hash_EnumNext(searchPtr) 353 354 355 { 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 354 register Hash_Search *searchPtr; /* Area used to keep state about 355 search. */ 356 { 357 register Hash_Entry *e; 358 Hash_Table *t = searchPtr->tablePtr; 359 360 /* 361 * The hashEntryPtr field points to the most recently returned 362 * entry, or is nil if we are starting up. If not nil, we have 363 * to start at the next one in the chain. 364 */ 365 e = searchPtr->hashEntryPtr; 366 if (e != NULL) 367 e = e->next; 368 /* 369 * If the chain ran out, or if we are starting up, we need to 370 * find the next nonempty chain. 371 */ 372 while (e == NULL) { 373 if (searchPtr->nextIndex >= t->size) 374 return (NULL); 375 e = t->bucketPtr[searchPtr->nextIndex++]; 376 } 377 searchPtr->hashEntryPtr = e; 378 return (e); 378 379 } 379 380 … … 382 383 * 383 384 * RebuildTable -- 384 * 385 * 386 * 387 * Results: 388 * 389 * 390 * Side Effects: 391 * 392 * 385 * This local routine makes a new hash table that 386 * is larger than the old one. 387 * 388 * Results: 389 * None. 390 * 391 * Side Effects: 392 * The entire hash table is moved, so any bucket numbers 393 * from the old table are invalid. 393 394 * 394 395 *--------------------------------------------------------- … … 397 398 static void 398 399 RebuildTable(t) 399 400 { 401 402 400 register Hash_Table *t; 401 { 402 register Hash_Entry *e, *next = NULL, **hp, **xp; 403 register int i, mask; 403 404 register Hash_Entry **oldhp; 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 } 405 int oldsize; 406 407 oldhp = t->bucketPtr; 408 oldsize = i = t->size; 409 i <<= 1; 410 t->size = i; 411 t->mask = mask = i - 1; 412 t->bucketPtr = hp = (struct Hash_Entry **) emalloc(sizeof(*hp) * i); 413 while (--i >= 0) 414 *hp++ = NULL; 415 for (hp = oldhp, i = oldsize; --i >= 0;) { 416 for (e = *hp++; e != NULL; e = next) { 417 next = e->next; 418 xp = &t->bucketPtr[e->namehash & mask]; 419 e->next = *xp; 420 *xp = e; 421 } 422 } 423 efree((char *)oldhp); 424 }
Note:
See TracChangeset
for help on using the changeset viewer.