Annotation of 43BSDReno/usr.bin/make/hash.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
                      3:  * Copyright (c) 1988, 1989 by Adam de Boor
                      4:  * Copyright (c) 1989 by Berkeley Softworks
                      5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to Berkeley by
                      8:  * Adam de Boor.
                      9:  *
                     10:  * Redistribution and use in source and binary forms are permitted
                     11:  * provided that: (1) source distributions retain this entire copyright
                     12:  * notice and comment, and (2) distributions including binaries display
                     13:  * the following acknowledgement:  ``This product includes software
                     14:  * developed by the University of California, Berkeley and its contributors''
                     15:  * in the documentation or other materials provided with the distribution
                     16:  * and in all advertising materials mentioning features or use of this
                     17:  * software. Neither the name of the University nor the names of its
                     18:  * contributors may be used to endorse or promote products derived
                     19:  * from this software without specific prior written permission.
                     20:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     21:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     22:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     23:  */
                     24: 
                     25: #ifndef lint
                     26: static char sccsid[] = "@(#)hash.c     5.4 (Berkeley) 6/1/90";
                     27: #endif /* not lint */
                     28: 
                     29: /* hash.c --
                     30:  *
                     31:  *     This module contains routines to manipulate a hash table.
                     32:  *     See hash.h for a definition of the structure of the hash
                     33:  *     table.  Hash tables grow automatically as the amount of
                     34:  *     information increases.
                     35:  */
                     36: 
                     37: #include "sprite.h"
                     38: #include "hash.h"
                     39: #include "list.h"
                     40: 
                     41: /*
                     42:  * Forward references to local procedures that are used before they're
                     43:  * defined:
                     44:  */
                     45: 
                     46: static Hash_Entry *    ChainSearch();
                     47: static int             Hash();
                     48: static void            RebuildTable();
                     49: 
                     50: /* 
                     51:  * The following defines the ratio of # entries to # buckets
                     52:  * at which we rebuild the table to make it larger.
                     53:  */
                     54: 
                     55: static rebuildLimit = 3;
                     56: 
                     57: /*
                     58:  *---------------------------------------------------------
                     59:  * 
                     60:  * Hash_InitTable --
                     61:  *
                     62:  *     This routine just sets up the hash table.
                     63:  *
                     64:  * Results:    
                     65:  *     None.
                     66:  *
                     67:  * Side Effects:
                     68:  *     Memory is allocated for the initial bucket area.
                     69:  *
                     70:  *---------------------------------------------------------
                     71:  */
                     72: 
                     73: void
                     74: Hash_InitTable(tablePtr, numBuckets, keyType)
                     75:     register Hash_Table *tablePtr;     /* Structure to use to hold table. */
                     76:     int                numBuckets;     /* How many buckets to create for
                     77:                                         * starters. This number is rounded
                     78:                                         * up to a power of two.   If <= 0,
                     79:                                         * a reasonable default is chosen.
                     80:                                         * The table will grow in size later
                     81:                                         * as needed. */
                     82:     int                keyType;        /* HASH_STRING_KEYS means that key
                     83:                                         * values passed to HashFind will be
                     84:                                         * strings, passed via a (char *)
                     85:                                         * pointer.  HASH_ONE_WORD_KEYS means
                     86:                                         * that key values will be any
                     87:                                         * one-word value passed as Address.
                     88:                                         * > 1 means that key values will be 
                     89:                                         * multi-word values whose address is
                     90:                                         * passed as Address.  In this last
                     91:                                         * case, keyType is the number of
                     92:                                         * words in the key, not the number
                     93:                                         * of bytes. */
                     94: {
                     95:     register   int             i;
                     96:     register   List_Links      *bucketPtr;
                     97: 
                     98:     /* 
                     99:      * Round up the size to a power of two. 
                    100:      */
                    101: 
                    102:     if (numBuckets <= 0) {
                    103:        numBuckets = 16;
                    104:     }
                    105:     tablePtr->numEntries = 0;
                    106:     tablePtr->keyType = keyType;
                    107:     tablePtr->size = 2;
                    108:     tablePtr->mask = 1;
                    109:     tablePtr->downShift = 29;
                    110:     while (tablePtr->size < numBuckets) {
                    111:        tablePtr->size <<= 1;
                    112:        tablePtr->mask = (tablePtr->mask << 1) + 1;
                    113:        tablePtr->downShift--;
                    114:     }
                    115: 
                    116:     tablePtr->bucketPtr = (List_Links *) emalloc(sizeof(List_Links)
                    117:            * tablePtr->size);
                    118:     for (i=0, bucketPtr = tablePtr->bucketPtr; i < tablePtr->size;
                    119:            i++, bucketPtr++) {
                    120:        List_Init(bucketPtr);
                    121:     }
                    122: }
                    123: 
                    124: /*
                    125:  *---------------------------------------------------------
                    126:  *
                    127:  * Hash_DeleteTable --
                    128:  *
                    129:  *     This routine removes everything from a hash table
                    130:  *     and frees up the memory space it occupied (except for
                    131:  *     the space in the Hash_Table structure).
                    132:  *
                    133:  * Results:    
                    134:  *     None.
                    135:  *
                    136:  * Side Effects:
                    137:  *     Lots of memory is freed up.
                    138:  *
                    139:  *---------------------------------------------------------
                    140:  */
                    141: 
                    142: void
                    143: Hash_DeleteTable(tablePtr)
                    144:     Hash_Table *tablePtr;              /* Hash table whose entries are all to
                    145:                                         * be freed.  */
                    146: {
                    147:     register List_Links *hashTableEnd;
                    148:     register Hash_Entry *hashEntryPtr;
                    149:     register List_Links *bucketPtr;
                    150: 
                    151:     bucketPtr = tablePtr->bucketPtr;
                    152:     hashTableEnd = &(bucketPtr[tablePtr->size]);
                    153:     for (; bucketPtr < hashTableEnd; bucketPtr++) {
                    154:        while (!List_IsEmpty(bucketPtr)) {
                    155:            hashEntryPtr = (Hash_Entry *) List_First(bucketPtr);
                    156:            List_Remove((List_Links *) hashEntryPtr);
                    157:            free((Address) hashEntryPtr);
                    158:        }
                    159:     }
                    160:     free((Address) tablePtr->bucketPtr);
                    161: 
                    162:     /*
                    163:      * Set up the hash table to cause memory faults on any future
                    164:      * access attempts until re-initialization.
                    165:      */
                    166: 
                    167:     tablePtr->bucketPtr = (List_Links *) NIL;
                    168: }
                    169: 
                    170: /*
                    171:  *---------------------------------------------------------
                    172:  *
                    173:  * Hash_FindEntry --
                    174:  *
                    175:  *     Searches a hash table for an entry corresponding to key.
                    176:  *
                    177:  * Results:
                    178:  *     The return value is a pointer to the entry for key,
                    179:  *     if key was present in the table.  If key was not
                    180:  *     present, NULL is returned.
                    181:  *
                    182:  * Side Effects:
                    183:  *     None.
                    184:  *
                    185:  *---------------------------------------------------------
                    186:  */
                    187: 
                    188: Hash_Entry *
                    189: Hash_FindEntry(tablePtr, key)
                    190:     Hash_Table *tablePtr;      /* Hash table to search. */
                    191:     Address key;               /* A hash key. */
                    192: {
                    193:     return(ChainSearch(tablePtr, key,
                    194:            &(tablePtr->bucketPtr[Hash(tablePtr, key)])));
                    195: }
                    196: 
                    197: /*
                    198:  *---------------------------------------------------------
                    199:  *
                    200:  * Hash_CreateEntry --
                    201:  *
                    202:  *     Searches a hash table for an entry corresponding to
                    203:  *     key.  If no entry is found, then one is created.
                    204:  *
                    205:  * Results:
                    206:  *     The return value is a pointer to the entry.  If *newPtr
                    207:  *     isn't NULL, then *newPtr is filled in with TRUE if a
                    208:  *     new entry was created, and FALSE if an entry already existed
                    209:  *     with the given key.
                    210:  *
                    211:  * Side Effects:
                    212:  *     Memory may be allocated, and the hash buckets may be modified.
                    213:  *---------------------------------------------------------
                    214:  */
                    215: 
                    216: Hash_Entry *
                    217: Hash_CreateEntry(tablePtr, key, newPtr)
                    218:     register Hash_Table *tablePtr;     /* Hash table to search. */
                    219:     Address key;                       /* A hash key. */
                    220:     Boolean *newPtr;                   /* Filled in with TRUE if new entry
                    221:                                         * created, FALSE otherwise. */
                    222: {
                    223:     register Hash_Entry *hashEntryPtr;
                    224:     register int       *hashKeyPtr;
                    225:     register int       *keyPtr;
                    226:     List_Links                 *hashList;
                    227: 
                    228:     keyPtr = (int *) key;
                    229: 
                    230:     hashList = &(tablePtr->bucketPtr[Hash(tablePtr, (Address) keyPtr)]);
                    231:     hashEntryPtr = ChainSearch(tablePtr, (Address) keyPtr, hashList);
                    232: 
                    233:     if (hashEntryPtr != (Hash_Entry *) NULL) {
                    234:        if (newPtr != NULL) {
                    235:            *newPtr = FALSE;
                    236:        }
                    237:        return hashEntryPtr;
                    238:     }
                    239: 
                    240:     /* 
                    241:      * The desired entry isn't there.  Before allocating a new entry,
                    242:      * see if we're overloading the buckets.  If so, then make a
                    243:      * bigger table.
                    244:      */
                    245: 
                    246:     if (tablePtr->numEntries >= rebuildLimit * tablePtr->size) {
                    247:        RebuildTable(tablePtr);
                    248:        hashList = &(tablePtr->bucketPtr[Hash(tablePtr, (Address) keyPtr)]);
                    249:     }
                    250:     tablePtr->numEntries += 1;
                    251: 
                    252:     /*
                    253:      * Not there, we have to allocate.  If the string is longer
                    254:      * than 3 bytes, then we have to allocate extra space in the
                    255:      * entry.
                    256:      */
                    257: 
                    258:     switch (tablePtr->keyType) {
                    259:        case HASH_STRING_KEYS:
                    260:            hashEntryPtr = (Hash_Entry *) emalloc(sizeof(Hash_Entry) + 
                    261:                    strlen((char *) keyPtr) - 3);
                    262:            strcpy(hashEntryPtr->key.name, (char *) keyPtr);
                    263:            break;
                    264:        case HASH_ONE_WORD_KEYS:
                    265:            hashEntryPtr = (Hash_Entry *) emalloc(sizeof(Hash_Entry));
                    266:            hashEntryPtr->key.ptr = (Address) keyPtr;
                    267:            break;
                    268:        case 2:
                    269:            hashEntryPtr = 
                    270:                (Hash_Entry *) emalloc(sizeof(Hash_Entry) + sizeof(int));
                    271:            hashKeyPtr = hashEntryPtr->key.words;
                    272:            *hashKeyPtr++ = *keyPtr++;
                    273:            *hashKeyPtr = *keyPtr;
                    274:            break;
                    275:        default: {
                    276:            register    n;
                    277: 
                    278:            n = tablePtr->keyType;
                    279:            hashEntryPtr = (Hash_Entry *) 
                    280:                    emalloc(sizeof(Hash_Entry) + (n - 1) * sizeof(int));
                    281:            hashKeyPtr = hashEntryPtr->key.words;
                    282:            do { 
                    283:                *hashKeyPtr++ = *keyPtr++; 
                    284:            } while (--n);
                    285:            break;
                    286:        }
                    287:     }
                    288: 
                    289:     hashEntryPtr->clientData = (ClientData) NULL;
                    290:     List_Insert((List_Links *) hashEntryPtr, LIST_ATFRONT(hashList));
                    291: 
                    292:     if (newPtr != NULL) {
                    293:        *newPtr = TRUE;
                    294:     }
                    295:     return hashEntryPtr;
                    296: }
                    297: 
                    298: /*
                    299:  *---------------------------------------------------------
                    300:  *
                    301:  * Hash_DeleteEntry --
                    302:  *
                    303:  *     Delete the given hash table entry and free memory associated with
                    304:  *     it.
                    305:  *
                    306:  * Results:
                    307:  *     None.
                    308:  *
                    309:  * Side Effects:
                    310:  *     Hash chain that entry lives in is modified and memory is freed.
                    311:  *
                    312:  *---------------------------------------------------------
                    313:  */
                    314: 
                    315: void
                    316: Hash_DeleteEntry(tablePtr, hashEntryPtr)
                    317:     Hash_Table                 *tablePtr;
                    318:     register   Hash_Entry      *hashEntryPtr;
                    319: {
                    320:     if (hashEntryPtr != (Hash_Entry *) NULL) {
                    321:        List_Remove((List_Links *) hashEntryPtr);
                    322:        free((Address) hashEntryPtr);
                    323:        tablePtr->numEntries--;
                    324:     }
                    325: }
                    326: 
                    327: /*
                    328:  *---------------------------------------------------------
                    329:  *
                    330:  * Hash_EnumFirst --
                    331:  *     This procedure sets things up for a complete search
                    332:  *     of all entries recorded in the hash table.
                    333:  *
                    334:  * Results:    
                    335:  *     The return value is the address of the first entry in
                    336:  *     the hash table, or NULL if the table is empty.
                    337:  *
                    338:  * Side Effects:
                    339:  *     The information in hashSearchPtr is initialized so that successive
                    340:  *     calls to Hash_Next will return successive HashEntry's
                    341:  *     from the table.
                    342:  *
                    343:  *---------------------------------------------------------
                    344:  */
                    345: 
                    346: Hash_Entry *
                    347: Hash_EnumFirst(tablePtr, hashSearchPtr)
                    348:     Hash_Table *tablePtr;                      /* Table to be searched. */
                    349:     register Hash_Search *hashSearchPtr;       /* Area in which to keep state 
                    350:                                                 * about search.*/
                    351: {
                    352:     hashSearchPtr->tablePtr = tablePtr;
                    353:     hashSearchPtr->nextIndex = 0;
                    354:     hashSearchPtr->hashEntryPtr = (Hash_Entry *) NULL;
                    355:     return Hash_EnumNext(hashSearchPtr);
                    356: }
                    357: 
                    358: /*
                    359:  *---------------------------------------------------------
                    360:  *
                    361:  * Hash_EnumNext --
                    362:  *    This procedure returns successive entries in the hash table.
                    363:  *
                    364:  * Results:
                    365:  *    The return value is a pointer to the next HashEntry
                    366:  *    in the table, or NULL when the end of the table is
                    367:  *    reached.
                    368:  *
                    369:  * Side Effects:
                    370:  *    The information in hashSearchPtr is modified to advance to the
                    371:  *    next entry.
                    372:  *
                    373:  *---------------------------------------------------------
                    374:  */
                    375: 
                    376: Hash_Entry *
                    377: Hash_EnumNext(hashSearchPtr)
                    378:     register Hash_Search *hashSearchPtr; /* Area used to keep state about 
                    379:                                            search. */
                    380: {
                    381:     register List_Links *hashList;
                    382:     register Hash_Entry *hashEntryPtr;
                    383: 
                    384:     hashEntryPtr = hashSearchPtr->hashEntryPtr;
                    385:     while (hashEntryPtr == (Hash_Entry *) NULL ||
                    386:           List_IsAtEnd(hashSearchPtr->hashList,
                    387:           (List_Links *) hashEntryPtr)) {
                    388:        if (hashSearchPtr->nextIndex >= hashSearchPtr->tablePtr->size) {
                    389:            return((Hash_Entry *) NULL);
                    390:        }
                    391:        hashList = &(hashSearchPtr->tablePtr->bucketPtr[
                    392:                hashSearchPtr->nextIndex]);
                    393:        hashSearchPtr->nextIndex++;
                    394:        if (!List_IsEmpty(hashList)) {
                    395:            hashEntryPtr = (Hash_Entry *) List_First(hashList);
                    396:            hashSearchPtr->hashList = hashList;
                    397:            break;
                    398:        }
                    399:     }
                    400: 
                    401:     hashSearchPtr->hashEntryPtr = 
                    402:                (Hash_Entry *) List_Next((List_Links *) hashEntryPtr);
                    403: 
                    404:     return(hashEntryPtr);
                    405: }
                    406: 
                    407: /*
                    408:  *---------------------------------------------------------
                    409:  *
                    410:  * Hash_PrintStats --
                    411:  *
                    412:  *     This routine calls a caller-supplied procedure to print
                    413:  *     statistics about the current bucket situation.
                    414:  *
                    415:  * Results:    
                    416:  *     None.
                    417:  *
                    418:  * Side Effects:       
                    419:  *     Proc gets called (potentially many times) to output information
                    420:  *     about the hash table. It must have the following calling sequence:
                    421:  *
                    422:  *     void
                    423:  *     proc(clientData, string)
                    424:  *         ClientData clientData;
                    425:  *         char *string;
                    426:  *     {
                    427:  *     }
                    428:  *
                    429:  *     In each call, clientData is the same as the clientData argument
                    430:  *     to this procedure, and string is a null-terminated string of
                    431:  *     characters to output.
                    432:  *
                    433:  *---------------------------------------------------------
                    434:  */
                    435: 
                    436: void
                    437: Hash_PrintStats(tablePtr, proc, clientData)
                    438:     Hash_Table *tablePtr;              /* Table for which to print info. */
                    439:     void (*proc)();                    /* Procedure to call to do actual
                    440:                                         * I/O. */
                    441: {
                    442:     int count[10], overflow, i, j;
                    443:     char msg[100];
                    444:     Hash_Entry         *hashEntryPtr;
                    445:     List_Links *hashList;
                    446: 
                    447:     for (i=0; i<10; i++) {
                    448:        count[i] = 0;
                    449:     }
                    450:     overflow = 0;
                    451:     for (i = 0; i < tablePtr->size; i++) {
                    452:        j = 0;
                    453:        hashList = &(tablePtr->bucketPtr[i]);
                    454:        LIST_FORALL(hashList, (List_Links *) hashEntryPtr) {
                    455:            j++;
                    456:        }
                    457:        if (j < 10) {
                    458:            count[j]++;
                    459:        } else {
                    460:            overflow++;
                    461:        }
                    462:     }
                    463: 
                    464:     sprintf(msg, "Entries in table %d number of buckets %d\n", 
                    465:                tablePtr->numEntries, tablePtr->size);
                    466:     (*proc)(clientData, msg);
                    467:     for (i = 0;  i < 10; i++) {
                    468:        sprintf(msg, "Number of buckets with %d entries: %d.\n",
                    469:                i, count[i]);
                    470:        (*proc)(clientData, msg);
                    471:     }
                    472:     sprintf(msg, "Number of buckets with > 9 entries: %d.\n",
                    473:            overflow);
                    474:     (*proc)(clientData, msg);
                    475: }
                    476: 
                    477: /*
                    478:  *---------------------------------------------------------
                    479:  *
                    480:  * Hash --
                    481:  *     This is a local procedure to compute a hash table
                    482:  *     bucket address based on a string value.
                    483:  *
                    484:  * Results:
                    485:  *     The return value is an integer between 0 and size - 1.
                    486:  *
                    487:  * Side Effects:       
                    488:  *     None.
                    489:  *
                    490:  * Design:
                    491:  *     It is expected that most keys are decimal numbers,
                    492:  *     so the algorithm behaves accordingly.  The randomizing
                    493:  *     code is stolen straight from the rand library routine.
                    494:  *
                    495:  *---------------------------------------------------------
                    496:  */
                    497: 
                    498: static int
                    499: Hash(tablePtr, key)
                    500:     register Hash_Table *tablePtr;
                    501:     register char      *key;
                    502: {
                    503:     register int       i = 0;
                    504:     register int       j;
                    505:     register int       *intPtr;
                    506: 
                    507:     switch (tablePtr->keyType) {
                    508:        case HASH_STRING_KEYS:
                    509:            while (*key != 0) {
                    510:                i = (i * 10) + (*key++ - '0');
                    511:            }
                    512:            break;
                    513:        case HASH_ONE_WORD_KEYS:
                    514:            i = (int) key;
                    515:            break;
                    516:        case 2:
                    517:            i = ((int *) key)[0] + ((int *) key)[1];
                    518:            break;
                    519:        default:
                    520:            j = tablePtr->keyType;
                    521:            intPtr = (int *) key;
                    522:            do { 
                    523:                i += *intPtr++; 
                    524:                j--;
                    525:            } while (j > 0);
                    526:            break;
                    527:     }
                    528: 
                    529: 
                    530:     return(((i*1103515245 + 12345) >> tablePtr->downShift) & tablePtr->mask);
                    531: }
                    532: 
                    533: /*
                    534:  *---------------------------------------------------------
                    535:  *
                    536:  * ChainSearch --
                    537:  *
                    538:  *     Search the hash table for the entry in the hash chain.
                    539:  *
                    540:  * Results:
                    541:  *     Pointer to entry in hash chain, NULL if none found.
                    542:  *
                    543:  * Side Effects:
                    544:  *     None.
                    545:  *
                    546:  *---------------------------------------------------------
                    547:  */
                    548: 
                    549: static Hash_Entry *
                    550: ChainSearch(tablePtr, key, hashList)
                    551:     Hash_Table                 *tablePtr;      /* Hash table to search. */
                    552:     register Address   key;    /* A hash key. */
                    553:     register List_Links *hashList;
                    554: {
                    555:     register Hash_Entry *hashEntryPtr;
                    556:     register int       *hashKeyPtr;
                    557:     int                *keyPtr;
                    558:     register int       numKeys;
                    559: 
                    560:     numKeys = tablePtr->keyType;
                    561:     LIST_FORALL(hashList, (List_Links *) hashEntryPtr) {
                    562:        switch (numKeys) {
                    563:            case 0:
                    564:                if (strcmp(hashEntryPtr->key.name, key) == 0) {
                    565:                    return(hashEntryPtr);
                    566:                }
                    567:                break;
                    568:            case 1:
                    569:                if (hashEntryPtr->key.ptr == key) {
                    570:                    return(hashEntryPtr);
                    571:                }
                    572:                break;
                    573:            case 2:
                    574:                hashKeyPtr = hashEntryPtr->key.words;
                    575:                keyPtr = (int *) key;
                    576:                if (*hashKeyPtr++ == *keyPtr++ && *hashKeyPtr == *keyPtr) {
                    577:                    return(hashEntryPtr);
                    578:                }
                    579:                break;
                    580:            default:
                    581:                if (bcmp((Address) hashEntryPtr->key.words,
                    582:                            (Address) key, numKeys * sizeof(int))) {
                    583:                    return(hashEntryPtr);
                    584:                }
                    585:                break;
                    586:        }
                    587:     }
                    588: 
                    589:     /* 
                    590:      * The desired entry isn't there 
                    591:      */
                    592: 
                    593:     return ((Hash_Entry *) NULL);
                    594: }
                    595: 
                    596: /*
                    597:  *---------------------------------------------------------
                    598:  *
                    599:  * RebuildTable --
                    600:  *     This local routine makes a new hash table that
                    601:  *     is larger than the old one.
                    602:  *
                    603:  * Results:    
                    604:  *     None.
                    605:  *
                    606:  * Side Effects:
                    607:  *     The entire hash table is moved, so any bucket numbers
                    608:  *     from the old table are invalid.
                    609:  *
                    610:  *---------------------------------------------------------
                    611:  */
                    612: 
                    613: static void
                    614: RebuildTable(tablePtr)
                    615:     Hash_Table         *tablePtr;              /* Table to be enlarged. */
                    616: {
                    617:     int                 oldSize;
                    618:     int                 bucket;
                    619:     List_Links          *oldBucketPtr;
                    620:     register Hash_Entry  *hashEntryPtr;
                    621:     register List_Links         *oldHashList;
                    622: 
                    623:     oldBucketPtr = tablePtr->bucketPtr;
                    624:     oldSize = tablePtr->size;
                    625: 
                    626:     /* 
                    627:      * Build a new table 4 times as large as the old one. 
                    628:      */
                    629: 
                    630:     Hash_InitTable(tablePtr, tablePtr->size * 4, tablePtr->keyType);
                    631: 
                    632:     for (oldHashList = oldBucketPtr; oldSize > 0; oldSize--, oldHashList++) {
                    633:        while (!List_IsEmpty(oldHashList)) {
                    634:            hashEntryPtr = (Hash_Entry *) List_First(oldHashList);
                    635:            List_Remove((List_Links *) hashEntryPtr);
                    636:            switch (tablePtr->keyType) {
                    637:                case HASH_STRING_KEYS:
                    638:                    bucket = Hash(tablePtr, (Address) hashEntryPtr->key.name);
                    639:                    break;
                    640:                case HASH_ONE_WORD_KEYS:
                    641:                    bucket = Hash(tablePtr, (Address) hashEntryPtr->key.ptr);
                    642:                    break;
                    643:                default:
                    644:                    bucket = Hash(tablePtr, (Address) hashEntryPtr->key.words);
                    645:                    break;
                    646:            }
                    647:            List_Insert((List_Links *) hashEntryPtr, 
                    648:                LIST_ATFRONT(&(tablePtr->bucketPtr[bucket])));
                    649:            tablePtr->numEntries++;
                    650:        }
                    651:     }
                    652: 
                    653:     free((Address) oldBucketPtr);
                    654: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.