4 * Implementation of in-memory hash tables for Tcl and Tcl-based
7 * Copyright (c) 1991-1993 The Regents of the University of California.
8 * Copyright (c) 1994 Sun Microsystems, Inc.
10 * This software is copyrighted by the Regents of the University of
11 * California, Sun Microsystems, Inc., and other parties. The following
12 * terms apply to all files associated with the software unless explicitly
13 * disclaimed in individual files.
15 * The authors hereby grant permission to use, copy, modify, distribute,
16 * and license this software and its documentation for any purpose, provided
17 * that existing copyright notices are retained in all copies and that this
18 * notice is included verbatim in any distributions. No written agreement,
19 * license, or royalty fee is required for any of the authorized uses.
20 * Modifications to this software may be copyrighted by their authors
21 * and need not follow the licensing terms described here, provided that
22 * the new terms are clearly indicated on the first page of each file where
25 * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
26 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
27 * ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
28 * DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
31 * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
32 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
33 * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
34 * IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
35 * NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
38 * RESTRICTED RIGHTS: Use, duplication or disclosure by the government
39 * is subject to the restrictions as set forth in subparagraph (c) (1) (ii)
40 * of the Rights in Technical Data and Computer Software Clause as DFARS
41 * 252.227-7013 and FAR 52.227-19.
43 * $Id: tclHash.c,v 1.2 1999/01/30 22:27:35 roberts Exp $
48 static const char rcsid[] = "$Id: tclHash.c,v 1.2 1999/01/30 22:27:35 roberts Exp $";
54 * When there are this many entries per bucket, on average, rebuild
55 * the hash table to make it larger.
58 #define REBUILD_MULTIPLIER 3
62 * The following macro takes a preliminary integer hash value and
63 * produces an index into a hash tables bucket list. The idea is
64 * to make it so that preliminary values that are arbitrarily similar
65 * will end up in different buckets. The hash function was taken
66 * from a random-number generator.
69 #define RANDOM_INDEX(tablePtr, i) \
70 (((((long) (i))*1103515245) >> (tablePtr)->downShift) & (tablePtr)->mask)
73 * Procedure prototypes for static procedures in this file:
76 static Tcl_HashEntry * ArrayFind _ANSI_ARGS_((Tcl_HashTable *tablePtr,
78 static Tcl_HashEntry * ArrayCreate _ANSI_ARGS_((Tcl_HashTable *tablePtr,
79 char *key, int *newPtr));
80 static Tcl_HashEntry * BogusFind _ANSI_ARGS_((Tcl_HashTable *tablePtr,
82 static Tcl_HashEntry * BogusCreate _ANSI_ARGS_((Tcl_HashTable *tablePtr,
83 char *key, int *newPtr));
84 static unsigned int HashString _ANSI_ARGS_((char *string));
85 static void RebuildTable _ANSI_ARGS_((Tcl_HashTable *tablePtr));
86 static Tcl_HashEntry * StringFind _ANSI_ARGS_((Tcl_HashTable *tablePtr,
88 static Tcl_HashEntry * StringCreate _ANSI_ARGS_((Tcl_HashTable *tablePtr,
89 char *key, int *newPtr));
90 static Tcl_HashEntry * OneWordFind _ANSI_ARGS_((Tcl_HashTable *tablePtr,
92 static Tcl_HashEntry * OneWordCreate _ANSI_ARGS_((Tcl_HashTable *tablePtr,
93 char *key, int *newPtr));
96 *----------------------------------------------------------------------
98 * Tcl_InitHashTable --
100 * Given storage for a hash table, set up the fields to prepare
101 * the hash table for use.
107 * TablePtr is now ready to be passed to Tcl_FindHashEntry and
108 * Tcl_CreateHashEntry.
110 *----------------------------------------------------------------------
114 Tcl_InitHashTable(tablePtr, keyType)
115 register Tcl_HashTable *tablePtr; /* Pointer to table record, which
116 * is supplied by the caller. */
117 int keyType; /* Type of keys to use in table:
118 * TCL_STRING_KEYS, TCL_ONE_WORD_KEYS,
119 * or an integer >= 2. */
121 tablePtr->buckets = tablePtr->staticBuckets;
122 tablePtr->staticBuckets[0] = tablePtr->staticBuckets[1] = 0;
123 tablePtr->staticBuckets[2] = tablePtr->staticBuckets[3] = 0;
124 tablePtr->numBuckets = TCL_SMALL_HASH_TABLE;
125 tablePtr->numEntries = 0;
126 tablePtr->rebuildSize = TCL_SMALL_HASH_TABLE*REBUILD_MULTIPLIER;
127 tablePtr->downShift = 28;
129 tablePtr->keyType = keyType;
130 if (keyType == TCL_STRING_KEYS) {
131 tablePtr->findProc = StringFind;
132 tablePtr->createProc = StringCreate;
133 } else if (keyType == TCL_ONE_WORD_KEYS) {
134 tablePtr->findProc = OneWordFind;
135 tablePtr->createProc = OneWordCreate;
137 tablePtr->findProc = ArrayFind;
138 tablePtr->createProc = ArrayCreate;
143 *----------------------------------------------------------------------
145 * Tcl_DeleteHashEntry --
147 * Remove a single entry from a hash table.
153 * The entry given by entryPtr is deleted from its table and
154 * should never again be used by the caller. It is up to the
155 * caller to free the clientData field of the entry, if that
158 *----------------------------------------------------------------------
162 Tcl_DeleteHashEntry(entryPtr)
163 Tcl_HashEntry *entryPtr;
165 register Tcl_HashEntry *prevPtr;
167 if (*entryPtr->bucketPtr == entryPtr) {
168 *entryPtr->bucketPtr = entryPtr->nextPtr;
170 for (prevPtr = *entryPtr->bucketPtr; ; prevPtr = prevPtr->nextPtr) {
171 if (prevPtr == NULL) {
172 panic("malformed bucket chain in Tcl_DeleteHashEntry");
174 if (prevPtr->nextPtr == entryPtr) {
175 prevPtr->nextPtr = entryPtr->nextPtr;
180 entryPtr->tablePtr->numEntries--;
181 ckfree((char *) entryPtr);
185 *----------------------------------------------------------------------
187 * Tcl_DeleteHashTable --
189 * Free up everything associated with a hash table except for
190 * the record for the table itself.
196 * The hash table is no longer useable.
198 *----------------------------------------------------------------------
202 Tcl_DeleteHashTable(tablePtr)
203 register Tcl_HashTable *tablePtr; /* Table to delete. */
205 register Tcl_HashEntry *hPtr, *nextPtr;
209 * Free up all the entries in the table.
212 for (i = 0; i < tablePtr->numBuckets; i++) {
213 hPtr = tablePtr->buckets[i];
214 while (hPtr != NULL) {
215 nextPtr = hPtr->nextPtr;
216 ckfree((char *) hPtr);
222 * Free up the bucket array, if it was dynamically allocated.
225 if (tablePtr->buckets != tablePtr->staticBuckets) {
226 ckfree((char *) tablePtr->buckets);
230 * Arrange for panics if the table is used again without
234 tablePtr->findProc = BogusFind;
235 tablePtr->createProc = BogusCreate;
239 *----------------------------------------------------------------------
241 * Tcl_FirstHashEntry --
243 * Locate the first entry in a hash table and set up a record
244 * that can be used to step through all the remaining entries
248 * The return value is a pointer to the first entry in tablePtr,
249 * or NULL if tablePtr has no entries in it. The memory at
250 * *searchPtr is initialized so that subsequent calls to
251 * Tcl_NextHashEntry will return all of the entries in the table,
257 *----------------------------------------------------------------------
261 Tcl_FirstHashEntry(tablePtr, searchPtr)
262 Tcl_HashTable *tablePtr; /* Table to search. */
263 Tcl_HashSearch *searchPtr; /* Place to store information about
264 * progress through the table. */
266 searchPtr->tablePtr = tablePtr;
267 searchPtr->nextIndex = 0;
268 searchPtr->nextEntryPtr = NULL;
269 return Tcl_NextHashEntry(searchPtr);
273 *----------------------------------------------------------------------
275 * Tcl_NextHashEntry --
277 * Once a hash table enumeration has been initiated by calling
278 * Tcl_FirstHashEntry, this procedure may be called to return
279 * successive elements of the table.
282 * The return value is the next entry in the hash table being
283 * enumerated, or NULL if the end of the table is reached.
288 *----------------------------------------------------------------------
292 Tcl_NextHashEntry(searchPtr)
293 register Tcl_HashSearch *searchPtr; /* Place to store information about
294 * progress through the table. Must
295 * have been initialized by calling
296 * Tcl_FirstHashEntry. */
300 while (searchPtr->nextEntryPtr == NULL) {
301 if (searchPtr->nextIndex >= searchPtr->tablePtr->numBuckets) {
304 searchPtr->nextEntryPtr =
305 searchPtr->tablePtr->buckets[searchPtr->nextIndex];
306 searchPtr->nextIndex++;
308 hPtr = searchPtr->nextEntryPtr;
309 searchPtr->nextEntryPtr = hPtr->nextPtr;
314 *----------------------------------------------------------------------
318 * Return statistics describing the layout of the hash table
319 * in its hash buckets.
322 * The return value is a malloc-ed string containing information
323 * about tablePtr. It is the caller's responsibility to free
329 *----------------------------------------------------------------------
333 Tcl_HashStats(tablePtr)
334 Tcl_HashTable *tablePtr; /* Table for which to produce stats. */
336 #define NUM_COUNTERS 10
337 int count[NUM_COUNTERS], overflow, i, j;
339 register Tcl_HashEntry *hPtr;
343 * Compute a histogram of bucket usage.
346 for (i = 0; i < NUM_COUNTERS; i++) {
351 for (i = 0; i < tablePtr->numBuckets; i++) {
353 for (hPtr = tablePtr->buckets[i]; hPtr != NULL; hPtr = hPtr->nextPtr) {
356 if (j < NUM_COUNTERS) {
362 average += (tmp+1.0)*(tmp/tablePtr->numEntries)/2.0;
366 * Print out the histogram and a few other pieces of information.
369 result = (char *) ckalloc((unsigned) ((NUM_COUNTERS*60) + 300));
370 sprintf(result, "%d entries in table, %d buckets\n",
371 tablePtr->numEntries, tablePtr->numBuckets);
372 p = result + strlen(result);
373 for (i = 0; i < NUM_COUNTERS; i++) {
374 sprintf(p, "number of buckets with %d entries: %d\n",
378 sprintf(p, "number of buckets with %d or more entries: %d\n",
379 NUM_COUNTERS, overflow);
381 sprintf(p, "average search distance for entry: %.1f", average);
386 *----------------------------------------------------------------------
390 * Compute a one-word summary of a text string, which can be
391 * used to generate a hash index.
394 * The return value is a one-word summary of the information in
400 *----------------------------------------------------------------------
405 register char *string; /* String from which to compute hash value. */
407 register unsigned int result;
411 * I tried a zillion different hash functions and asked many other
412 * people for advice. Many people had their own favorite functions,
413 * all different, but no-one had much idea why they were good ones.
414 * I chose the one below (multiply by 9 and add new character)
415 * because of the following reasons:
417 * 1. Multiplying by 10 is perfect for keys that are decimal strings,
418 * and multiplying by 9 is just about as good.
419 * 2. Times-9 is (shift-left-3) plus (old). This means that each
420 * character's bits hang around in the low-order bits of the
421 * hash value for ever, plus they spread fairly rapidly up to
422 * the high-order bits to fill out the hash value. This seems
423 * works well both for decimal and non-decimal strings.
433 result += (result<<3) + c;
439 *----------------------------------------------------------------------
443 * Given a hash table with string keys, and a string key, find
444 * the entry with a matching key.
447 * The return value is a token for the matching entry in the
448 * hash table, or NULL if there was no matching entry.
453 *----------------------------------------------------------------------
456 static Tcl_HashEntry *
457 StringFind(tablePtr, key)
458 Tcl_HashTable *tablePtr; /* Table in which to lookup entry. */
459 char *key; /* Key to use to find matching entry. */
461 register Tcl_HashEntry *hPtr;
462 register char *p1, *p2;
465 index = HashString(key) & tablePtr->mask;
468 * Search all of the entries in the appropriate bucket.
471 for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
472 hPtr = hPtr->nextPtr) {
473 for (p1 = key, p2 = hPtr->key.string; ; p1++, p2++) {
486 *----------------------------------------------------------------------
490 * Given a hash table with string keys, and a string key, find
491 * the entry with a matching key. If there is no matching entry,
492 * then create a new entry that does match.
495 * The return value is a pointer to the matching entry. If this
496 * is a newly-created entry, then *newPtr will be set to a non-zero
497 * value; otherwise *newPtr will be set to 0. If this is a new
498 * entry the value stored in the entry will initially be 0.
501 * A new entry may be added to the hash table.
503 *----------------------------------------------------------------------
506 static Tcl_HashEntry *
507 StringCreate(tablePtr, key, newPtr)
508 Tcl_HashTable *tablePtr; /* Table in which to lookup entry. */
509 char *key; /* Key to use to find or create matching
511 int *newPtr; /* Store info here telling whether a new
512 * entry was created. */
514 register Tcl_HashEntry *hPtr;
515 register char *p1, *p2;
518 index = HashString(key) & tablePtr->mask;
521 * Search all of the entries in this bucket.
524 for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
525 hPtr = hPtr->nextPtr) {
526 for (p1 = key, p2 = hPtr->key.string; ; p1++, p2++) {
538 * Entry not found. Add a new one to the bucket.
542 hPtr = (Tcl_HashEntry *) ckalloc((unsigned)
543 (sizeof(Tcl_HashEntry) + strlen(key) - (sizeof(hPtr->key) -1)));
544 hPtr->tablePtr = tablePtr;
545 hPtr->bucketPtr = &(tablePtr->buckets[index]);
546 hPtr->nextPtr = *hPtr->bucketPtr;
547 hPtr->clientData = 0;
548 strcpy(hPtr->key.string, key);
549 *hPtr->bucketPtr = hPtr;
550 tablePtr->numEntries++;
553 * If the table has exceeded a decent size, rebuild it with many
557 if (tablePtr->numEntries >= tablePtr->rebuildSize) {
558 RebuildTable(tablePtr);
564 *----------------------------------------------------------------------
568 * Given a hash table with one-word keys, and a one-word key, find
569 * the entry with a matching key.
572 * The return value is a token for the matching entry in the
573 * hash table, or NULL if there was no matching entry.
578 *----------------------------------------------------------------------
581 static Tcl_HashEntry *
582 OneWordFind(tablePtr, key)
583 Tcl_HashTable *tablePtr; /* Table in which to lookup entry. */
584 register char *key; /* Key to use to find matching entry. */
586 register Tcl_HashEntry *hPtr;
589 index = RANDOM_INDEX(tablePtr, key);
592 * Search all of the entries in the appropriate bucket.
595 for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
596 hPtr = hPtr->nextPtr) {
597 if (hPtr->key.oneWordValue == key) {
605 *----------------------------------------------------------------------
609 * Given a hash table with one-word keys, and a one-word key, find
610 * the entry with a matching key. If there is no matching entry,
611 * then create a new entry that does match.
614 * The return value is a pointer to the matching entry. If this
615 * is a newly-created entry, then *newPtr will be set to a non-zero
616 * value; otherwise *newPtr will be set to 0. If this is a new
617 * entry the value stored in the entry will initially be 0.
620 * A new entry may be added to the hash table.
622 *----------------------------------------------------------------------
625 static Tcl_HashEntry *
626 OneWordCreate(tablePtr, key, newPtr)
627 Tcl_HashTable *tablePtr; /* Table in which to lookup entry. */
628 register char *key; /* Key to use to find or create matching
630 int *newPtr; /* Store info here telling whether a new
631 * entry was created. */
633 register Tcl_HashEntry *hPtr;
636 index = RANDOM_INDEX(tablePtr, key);
639 * Search all of the entries in this bucket.
642 for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
643 hPtr = hPtr->nextPtr) {
644 if (hPtr->key.oneWordValue == key) {
651 * Entry not found. Add a new one to the bucket.
655 hPtr = (Tcl_HashEntry *) ckalloc(sizeof(Tcl_HashEntry));
656 hPtr->tablePtr = tablePtr;
657 hPtr->bucketPtr = &(tablePtr->buckets[index]);
658 hPtr->nextPtr = *hPtr->bucketPtr;
659 hPtr->clientData = 0;
660 hPtr->key.oneWordValue = key;
661 *hPtr->bucketPtr = hPtr;
662 tablePtr->numEntries++;
665 * If the table has exceeded a decent size, rebuild it with many
669 if (tablePtr->numEntries >= tablePtr->rebuildSize) {
670 RebuildTable(tablePtr);
676 *----------------------------------------------------------------------
680 * Given a hash table with array-of-int keys, and a key, find
681 * the entry with a matching key.
684 * The return value is a token for the matching entry in the
685 * hash table, or NULL if there was no matching entry.
690 *----------------------------------------------------------------------
693 static Tcl_HashEntry *
694 ArrayFind(tablePtr, key)
695 Tcl_HashTable *tablePtr; /* Table in which to lookup entry. */
696 char *key; /* Key to use to find matching entry. */
698 register Tcl_HashEntry *hPtr;
699 int *arrayPtr = (int *) key;
700 register int *iPtr1, *iPtr2;
703 for (index = 0, count = tablePtr->keyType, iPtr1 = arrayPtr;
704 count > 0; count--, iPtr1++) {
707 index = RANDOM_INDEX(tablePtr, index);
710 * Search all of the entries in the appropriate bucket.
713 for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
714 hPtr = hPtr->nextPtr) {
715 for (iPtr1 = arrayPtr, iPtr2 = hPtr->key.words,
716 count = tablePtr->keyType; ; count--, iPtr1++, iPtr2++) {
720 if (*iPtr1 != *iPtr2) {
729 *----------------------------------------------------------------------
733 * Given a hash table with one-word keys, and a one-word key, find
734 * the entry with a matching key. If there is no matching entry,
735 * then create a new entry that does match.
738 * The return value is a pointer to the matching entry. If this
739 * is a newly-created entry, then *newPtr will be set to a non-zero
740 * value; otherwise *newPtr will be set to 0. If this is a new
741 * entry the value stored in the entry will initially be 0.
744 * A new entry may be added to the hash table.
746 *----------------------------------------------------------------------
749 static Tcl_HashEntry *
750 ArrayCreate(tablePtr, key, newPtr)
751 Tcl_HashTable *tablePtr; /* Table in which to lookup entry. */
752 register char *key; /* Key to use to find or create matching
754 int *newPtr; /* Store info here telling whether a new
755 * entry was created. */
757 register Tcl_HashEntry *hPtr;
758 int *arrayPtr = (int *) key;
759 register int *iPtr1, *iPtr2;
762 for (index = 0, count = tablePtr->keyType, iPtr1 = arrayPtr;
763 count > 0; count--, iPtr1++) {
766 index = RANDOM_INDEX(tablePtr, index);
769 * Search all of the entries in the appropriate bucket.
772 for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
773 hPtr = hPtr->nextPtr) {
774 for (iPtr1 = arrayPtr, iPtr2 = hPtr->key.words,
775 count = tablePtr->keyType; ; count--, iPtr1++, iPtr2++) {
780 if (*iPtr1 != *iPtr2) {
787 * Entry not found. Add a new one to the bucket.
791 hPtr = (Tcl_HashEntry *) ckalloc((unsigned) (sizeof(Tcl_HashEntry)
792 + (tablePtr->keyType*sizeof(int)) - 4));
793 hPtr->tablePtr = tablePtr;
794 hPtr->bucketPtr = &(tablePtr->buckets[index]);
795 hPtr->nextPtr = *hPtr->bucketPtr;
796 hPtr->clientData = 0;
797 for (iPtr1 = arrayPtr, iPtr2 = hPtr->key.words, count = tablePtr->keyType;
798 count > 0; count--, iPtr1++, iPtr2++) {
801 *hPtr->bucketPtr = hPtr;
802 tablePtr->numEntries++;
805 * If the table has exceeded a decent size, rebuild it with many
809 if (tablePtr->numEntries >= tablePtr->rebuildSize) {
810 RebuildTable(tablePtr);
816 *----------------------------------------------------------------------
820 * This procedure is invoked when an Tcl_FindHashEntry is called
821 * on a table that has been deleted.
824 * If panic returns (which it shouldn't) this procedure returns
830 *----------------------------------------------------------------------
834 static Tcl_HashEntry *
835 BogusFind(tablePtr, key)
836 Tcl_HashTable *tablePtr; /* Table in which to lookup entry. */
837 char *key; /* Key to use to find matching entry. */
839 panic("called Tcl_FindHashEntry on deleted table");
844 *----------------------------------------------------------------------
848 * This procedure is invoked when an Tcl_CreateHashEntry is called
849 * on a table that has been deleted.
852 * If panic returns (which it shouldn't) this procedure returns
858 *----------------------------------------------------------------------
862 static Tcl_HashEntry *
863 BogusCreate(tablePtr, key, newPtr)
864 Tcl_HashTable *tablePtr; /* Table in which to lookup entry. */
865 char *key; /* Key to use to find or create matching
867 int *newPtr; /* Store info here telling whether a new
868 * entry was created. */
870 panic("called Tcl_CreateHashEntry on deleted table");
875 *----------------------------------------------------------------------
879 * This procedure is invoked when the ratio of entries to hash
880 * buckets becomes too large. It creates a new table with a
881 * larger bucket array and moves all of the entries into the
888 * Memory gets reallocated and entries get re-hashed to new
891 *----------------------------------------------------------------------
895 RebuildTable(tablePtr)
896 register Tcl_HashTable *tablePtr; /* Table to enlarge. */
898 int oldSize, count, index;
899 Tcl_HashEntry **oldBuckets;
900 register Tcl_HashEntry **oldChainPtr, **newChainPtr;
901 register Tcl_HashEntry *hPtr;
903 oldSize = tablePtr->numBuckets;
904 oldBuckets = tablePtr->buckets;
907 * Allocate and initialize the new bucket array, and set up
908 * hashing constants for new array size.
911 tablePtr->numBuckets *= 4;
912 tablePtr->buckets = (Tcl_HashEntry **) ckalloc((unsigned)
913 (tablePtr->numBuckets * sizeof(Tcl_HashEntry *)));
914 for (count = tablePtr->numBuckets, newChainPtr = tablePtr->buckets;
915 count > 0; count--, newChainPtr++) {
918 tablePtr->rebuildSize *= 4;
919 tablePtr->downShift -= 2;
920 tablePtr->mask = (tablePtr->mask << 2) + 3;
923 * Rehash all of the existing entries into the new bucket array.
926 for (oldChainPtr = oldBuckets; oldSize > 0; oldSize--, oldChainPtr++) {
927 for (hPtr = *oldChainPtr; hPtr != NULL; hPtr = *oldChainPtr) {
928 *oldChainPtr = hPtr->nextPtr;
929 if (tablePtr->keyType == TCL_STRING_KEYS) {
930 index = HashString(hPtr->key.string) & tablePtr->mask;
931 } else if (tablePtr->keyType == TCL_ONE_WORD_KEYS) {
932 index = RANDOM_INDEX(tablePtr, hPtr->key.oneWordValue);
937 for (index = 0, count = tablePtr->keyType,
938 iPtr = hPtr->key.words; count > 0; count--, iPtr++) {
941 index = RANDOM_INDEX(tablePtr, index);
943 hPtr->bucketPtr = &(tablePtr->buckets[index]);
944 hPtr->nextPtr = *hPtr->bucketPtr;
945 *hPtr->bucketPtr = hPtr;
950 * Free up the old bucket array, if it was dynamically allocated.
953 if (oldBuckets != tablePtr->staticBuckets) {
954 ckfree((char *) oldBuckets);