3 #define FICL_ASSERT_PHASH(hash, expression) FICL_ASSERT(NULL, expression)
7 * Unlink all words in the hash that have addresses greater than or
8 * equal to the address supplied. Implementation factor for FORGET
12 ficlHashForget(ficlHash
*hash
, void *where
)
17 FICL_ASSERT_PHASH(hash
, hash
);
18 FICL_ASSERT_PHASH(hash
, where
);
20 for (i
= 0; i
< hash
->size
; i
++) {
21 pWord
= hash
->table
[i
];
23 while ((void *)pWord
>= where
) {
27 hash
->table
[i
] = pWord
;
32 * h a s h H a s h C o d e
34 * Generate a 16 bit hashcode from a character string using a rolling
35 * shift and add stolen from PJ Weinberger of Bell Labs fame. Case folds
36 * the name before hashing it...
37 * N O T E : If string has zero length, returns zero.
40 ficlHashCode(ficlString s
)
44 ficlUnsigned16 code
= (ficlUnsigned16
)s
.length
;
45 ficlUnsigned16 shift
= 0;
50 /* changed to run without errors under Purify -- lch */
51 for (trace
= (ficlUnsigned8
*)s
.text
;
52 s
.length
&& *trace
; trace
++, s
.length
--) {
53 code
= (ficlUnsigned16
)((code
<< 4) + tolower(*trace
));
54 shift
= (ficlUnsigned16
)(code
& 0xf000);
56 code
^= (ficlUnsigned16
)(shift
>> 8);
57 code
^= (ficlUnsigned16
)shift
;
61 return ((ficlUnsigned16
)code
);
65 * h a s h I n s e r t W o r d
66 * Put a word into the hash table using the word's hashcode as
67 * an index (modulo the table size).
70 ficlHashInsertWord(ficlHash
*hash
, ficlWord
*word
)
74 FICL_ASSERT_PHASH(hash
, hash
);
75 FICL_ASSERT_PHASH(hash
, word
);
77 if (hash
->size
== 1) {
80 pList
= hash
->table
+ (word
->hash
% hash
->size
);
89 * Find a name in the hash table given the hashcode and text of the name.
90 * Returns the address of the corresponding ficlWord if found,
92 * Note: outer loop on link field supports inheritance in wordlists.
93 * It's not part of ANS Forth - Ficl only. hashReset creates wordlists
94 * with NULL link fields.
97 ficlHashLookup(ficlHash
*hash
, ficlString name
, ficlUnsigned16 hashCode
)
99 ficlUnsigned nCmp
= name
.length
;
101 ficlUnsigned16 hashIdx
;
103 if (nCmp
> FICL_NAME_LENGTH
)
104 nCmp
= FICL_NAME_LENGTH
;
106 for (; hash
!= NULL
; hash
= hash
->link
) {
108 hashIdx
= (ficlUnsigned16
)(hashCode
% hash
->size
);
109 else /* avoid the modulo op for single threaded lists */
112 for (word
= hash
->table
[hashIdx
]; word
; word
= word
->link
) {
113 if ((word
->length
== name
.length
) &&
114 (!ficlStrincmp(name
.text
, word
->name
, nCmp
)))
117 FICL_ASSERT_PHASH(hash
, word
!= word
->link
);
127 * Initialize a ficlHash to empty state.
130 ficlHashReset(ficlHash
*hash
)
134 FICL_ASSERT_PHASH(hash
, hash
);
136 for (i
= 0; i
< hash
->size
; i
++) {
137 hash
->table
[i
] = NULL
;