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
ficlHashForget(ficlHash * hash,void * where)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
ficlHashCode(ficlString s)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
ficlHashInsertWord(ficlHash * hash,ficlWord * word)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 *
ficlHashLookup(ficlHash * hash,ficlString name,ficlUnsigned16 hashCode)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
ficlHashReset(ficlHash * hash)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