1*a1bf3f78SToomas Soome #include "ficl.h" 2*a1bf3f78SToomas Soome 3*a1bf3f78SToomas Soome #define FICL_ASSERT_PHASH(hash, expression) FICL_ASSERT(NULL, expression) 4*a1bf3f78SToomas Soome 5*a1bf3f78SToomas Soome /* 6*a1bf3f78SToomas Soome * h a s h F o r g e t 7*a1bf3f78SToomas Soome * Unlink all words in the hash that have addresses greater than or 8*a1bf3f78SToomas Soome * equal to the address supplied. Implementation factor for FORGET 9*a1bf3f78SToomas Soome * and MARKER. 10*a1bf3f78SToomas Soome */ 11*a1bf3f78SToomas Soome void 12*a1bf3f78SToomas Soome ficlHashForget(ficlHash *hash, void *where) 13*a1bf3f78SToomas Soome { 14*a1bf3f78SToomas Soome ficlWord *pWord; 15*a1bf3f78SToomas Soome unsigned i; 16*a1bf3f78SToomas Soome 17*a1bf3f78SToomas Soome FICL_ASSERT_PHASH(hash, hash); 18*a1bf3f78SToomas Soome FICL_ASSERT_PHASH(hash, where); 19*a1bf3f78SToomas Soome 20*a1bf3f78SToomas Soome for (i = 0; i < hash->size; i++) { 21*a1bf3f78SToomas Soome pWord = hash->table[i]; 22*a1bf3f78SToomas Soome 23*a1bf3f78SToomas Soome while ((void *)pWord >= where) { 24*a1bf3f78SToomas Soome pWord = pWord->link; 25*a1bf3f78SToomas Soome } 26*a1bf3f78SToomas Soome 27*a1bf3f78SToomas Soome hash->table[i] = pWord; 28*a1bf3f78SToomas Soome } 29*a1bf3f78SToomas Soome } 30*a1bf3f78SToomas Soome 31*a1bf3f78SToomas Soome /* 32*a1bf3f78SToomas Soome * h a s h H a s h C o d e 33*a1bf3f78SToomas Soome * 34*a1bf3f78SToomas Soome * Generate a 16 bit hashcode from a character string using a rolling 35*a1bf3f78SToomas Soome * shift and add stolen from PJ Weinberger of Bell Labs fame. Case folds 36*a1bf3f78SToomas Soome * the name before hashing it... 37*a1bf3f78SToomas Soome * N O T E : If string has zero length, returns zero. 38*a1bf3f78SToomas Soome */ 39*a1bf3f78SToomas Soome ficlUnsigned16 40*a1bf3f78SToomas Soome ficlHashCode(ficlString s) 41*a1bf3f78SToomas Soome { 42*a1bf3f78SToomas Soome /* hashPJW */ 43*a1bf3f78SToomas Soome ficlUnsigned8 *trace; 44*a1bf3f78SToomas Soome ficlUnsigned16 code = (ficlUnsigned16)s.length; 45*a1bf3f78SToomas Soome ficlUnsigned16 shift = 0; 46*a1bf3f78SToomas Soome 47*a1bf3f78SToomas Soome if (s.length == 0) 48*a1bf3f78SToomas Soome return (0); 49*a1bf3f78SToomas Soome 50*a1bf3f78SToomas Soome /* changed to run without errors under Purify -- lch */ 51*a1bf3f78SToomas Soome for (trace = (ficlUnsigned8 *)s.text; 52*a1bf3f78SToomas Soome s.length && *trace; trace++, s.length--) { 53*a1bf3f78SToomas Soome code = (ficlUnsigned16)((code << 4) + tolower(*trace)); 54*a1bf3f78SToomas Soome shift = (ficlUnsigned16)(code & 0xf000); 55*a1bf3f78SToomas Soome if (shift) { 56*a1bf3f78SToomas Soome code ^= (ficlUnsigned16)(shift >> 8); 57*a1bf3f78SToomas Soome code ^= (ficlUnsigned16)shift; 58*a1bf3f78SToomas Soome } 59*a1bf3f78SToomas Soome } 60*a1bf3f78SToomas Soome 61*a1bf3f78SToomas Soome return ((ficlUnsigned16)code); 62*a1bf3f78SToomas Soome } 63*a1bf3f78SToomas Soome 64*a1bf3f78SToomas Soome /* 65*a1bf3f78SToomas Soome * h a s h I n s e r t W o r d 66*a1bf3f78SToomas Soome * Put a word into the hash table using the word's hashcode as 67*a1bf3f78SToomas Soome * an index (modulo the table size). 68*a1bf3f78SToomas Soome */ 69*a1bf3f78SToomas Soome void 70*a1bf3f78SToomas Soome ficlHashInsertWord(ficlHash *hash, ficlWord *word) 71*a1bf3f78SToomas Soome { 72*a1bf3f78SToomas Soome ficlWord **pList; 73*a1bf3f78SToomas Soome 74*a1bf3f78SToomas Soome FICL_ASSERT_PHASH(hash, hash); 75*a1bf3f78SToomas Soome FICL_ASSERT_PHASH(hash, word); 76*a1bf3f78SToomas Soome 77*a1bf3f78SToomas Soome if (hash->size == 1) { 78*a1bf3f78SToomas Soome pList = hash->table; 79*a1bf3f78SToomas Soome } else { 80*a1bf3f78SToomas Soome pList = hash->table + (word->hash % hash->size); 81*a1bf3f78SToomas Soome } 82*a1bf3f78SToomas Soome 83*a1bf3f78SToomas Soome word->link = *pList; 84*a1bf3f78SToomas Soome *pList = word; 85*a1bf3f78SToomas Soome } 86*a1bf3f78SToomas Soome 87*a1bf3f78SToomas Soome /* 88*a1bf3f78SToomas Soome * h a s h L o o k u p 89*a1bf3f78SToomas Soome * Find a name in the hash table given the hashcode and text of the name. 90*a1bf3f78SToomas Soome * Returns the address of the corresponding ficlWord if found, 91*a1bf3f78SToomas Soome * otherwise NULL. 92*a1bf3f78SToomas Soome * Note: outer loop on link field supports inheritance in wordlists. 93*a1bf3f78SToomas Soome * It's not part of ANS Forth - Ficl only. hashReset creates wordlists 94*a1bf3f78SToomas Soome * with NULL link fields. 95*a1bf3f78SToomas Soome */ 96*a1bf3f78SToomas Soome ficlWord * 97*a1bf3f78SToomas Soome ficlHashLookup(ficlHash *hash, ficlString name, ficlUnsigned16 hashCode) 98*a1bf3f78SToomas Soome { 99*a1bf3f78SToomas Soome ficlUnsigned nCmp = name.length; 100*a1bf3f78SToomas Soome ficlWord *word; 101*a1bf3f78SToomas Soome ficlUnsigned16 hashIdx; 102*a1bf3f78SToomas Soome 103*a1bf3f78SToomas Soome if (nCmp > FICL_NAME_LENGTH) 104*a1bf3f78SToomas Soome nCmp = FICL_NAME_LENGTH; 105*a1bf3f78SToomas Soome 106*a1bf3f78SToomas Soome for (; hash != NULL; hash = hash->link) { 107*a1bf3f78SToomas Soome if (hash->size > 1) 108*a1bf3f78SToomas Soome hashIdx = (ficlUnsigned16)(hashCode % hash->size); 109*a1bf3f78SToomas Soome else /* avoid the modulo op for single threaded lists */ 110*a1bf3f78SToomas Soome hashIdx = 0; 111*a1bf3f78SToomas Soome 112*a1bf3f78SToomas Soome for (word = hash->table[hashIdx]; word; word = word->link) { 113*a1bf3f78SToomas Soome if ((word->length == name.length) && 114*a1bf3f78SToomas Soome (!ficlStrincmp(name.text, word->name, nCmp))) 115*a1bf3f78SToomas Soome return (word); 116*a1bf3f78SToomas Soome #if FICL_ROBUST 117*a1bf3f78SToomas Soome FICL_ASSERT_PHASH(hash, word != word->link); 118*a1bf3f78SToomas Soome #endif 119*a1bf3f78SToomas Soome } 120*a1bf3f78SToomas Soome } 121*a1bf3f78SToomas Soome 122*a1bf3f78SToomas Soome return (NULL); 123*a1bf3f78SToomas Soome } 124*a1bf3f78SToomas Soome 125*a1bf3f78SToomas Soome /* 126*a1bf3f78SToomas Soome * h a s h R e s e t 127*a1bf3f78SToomas Soome * Initialize a ficlHash to empty state. 128*a1bf3f78SToomas Soome */ 129*a1bf3f78SToomas Soome void 130*a1bf3f78SToomas Soome ficlHashReset(ficlHash *hash) 131*a1bf3f78SToomas Soome { 132*a1bf3f78SToomas Soome unsigned i; 133*a1bf3f78SToomas Soome 134*a1bf3f78SToomas Soome FICL_ASSERT_PHASH(hash, hash); 135*a1bf3f78SToomas Soome 136*a1bf3f78SToomas Soome for (i = 0; i < hash->size; i++) { 137*a1bf3f78SToomas Soome hash->table[i] = NULL; 138*a1bf3f78SToomas Soome } 139*a1bf3f78SToomas Soome 140*a1bf3f78SToomas Soome hash->link = NULL; 141*a1bf3f78SToomas Soome hash->name = NULL; 142*a1bf3f78SToomas Soome } 143