2 * $Id: keyword.c 715 2009-07-06 03:31:00Z dhiebert $
4 * Copyright (c) 1998-2002, Darren Hiebert
6 * This source code is released for free distribution under the terms of the
7 * GNU General Public License.
9 * Manages a keyword hash.
15 #include "general.h" /* must always come first */
27 #define HASH_EXPONENT 7 /* must be less than 17 */
32 typedef struct sHashEntry
{
33 struct sHashEntry
*next
;
42 static const unsigned int TableSize
= 1 << HASH_EXPONENT
;
43 static hashEntry
**HashTable
= NULL
;
46 * FUNCTION DEFINITIONS
49 static hashEntry
**getHashTable (void)
51 static boolean allocated
= FALSE
;
57 HashTable
= xMalloc (TableSize
, hashEntry
*);
59 for (i
= 0 ; i
< TableSize
; ++i
)
67 static hashEntry
*getHashTableEntry (unsigned long hashedValue
)
69 hashEntry
**const table
= getHashTable ();
72 Assert (hashedValue
< TableSize
);
73 entry
= table
[hashedValue
];
78 static unsigned long hashValue (const char *const string
)
80 unsigned long value
= 0;
81 const unsigned char *p
;
83 Assert (string
!= NULL
);
85 /* We combine the various words of the multiword key using the method
86 * described on page 512 of Vol. 3 of "The Art of Computer Programming".
88 for (p
= (const unsigned char *) string
; *p
!= '\0' ; ++p
)
91 if (value
& 0x00000100L
)
92 value
= (value
& 0x000000ffL
) + 1L;
95 /* Algorithm from page 509 of Vol. 3 of "The Art of Computer Programming"
96 * Treats "value" as a 16-bit integer plus 16-bit fraction.
98 value
*= 40503L; /* = 2^16 * 0.6180339887 ("golden ratio") */
99 value
&= 0x0000ffffL
; /* keep fractional part */
100 value
>>= 16 - HASH_EXPONENT
; /* scale up by hash size and move down */
105 static hashEntry
*newEntry (
106 const char *const string
, langType language
, int value
)
108 hashEntry
*const entry
= xMalloc (1, hashEntry
);
111 entry
->string
= string
;
112 entry
->language
= language
;
113 entry
->value
= value
;
118 /* Note that it is assumed that a "value" of zero means an undefined keyword
119 * and clients of this function should observe this. Also, all keywords added
120 * should be added in lower case. If we encounter a case-sensitive language
121 * whose keywords are in upper case, we will need to redesign this.
123 extern void addKeyword (const char *const string
, langType language
, int value
)
125 const unsigned long hashedValue
= hashValue (string
);
126 hashEntry
*entry
= getHashTableEntry (hashedValue
);
130 hashEntry
**const table
= getHashTable ();
131 table
[hashedValue
] = newEntry (string
, language
, value
);
135 hashEntry
*prev
= NULL
;
137 while (entry
!= NULL
)
139 if (language
== entry
->language
&&
140 strcmp (string
, entry
->string
) == 0)
142 Assert (("Already in table" == NULL
));
149 Assert (prev
!= NULL
);
150 prev
->next
= newEntry (string
, language
, value
);
155 extern int lookupKeyword (const char *const string
, langType language
)
157 const unsigned long hashedValue
= hashValue (string
);
158 hashEntry
*entry
= getHashTableEntry (hashedValue
);
161 while (entry
!= NULL
)
163 if (language
== entry
->language
&& strcmp (string
, entry
->string
) == 0)
165 result
= entry
->value
;
173 extern void freeKeywordTable (void)
175 if (HashTable
!= NULL
)
179 for (i
= 0 ; i
< TableSize
; ++i
)
181 hashEntry
*entry
= HashTable
[i
];
183 while (entry
!= NULL
)
185 hashEntry
*next
= entry
->next
;
194 extern int analyzeToken (vString
*const name
, langType language
)
196 vString
*keyword
= vStringNew ();
198 vStringCopyToLower (keyword
, name
);
199 result
= lookupKeyword (vStringValue (keyword
), language
);
200 vStringDelete (keyword
);
206 static void printEntry (const hashEntry
*const entry
)
208 printf (" %-15s %-7s\n", entry
->string
, getLanguageName (entry
->language
));
211 static unsigned int printBucket (const unsigned int i
)
213 hashEntry
**const table
= getHashTable ();
214 hashEntry
*entry
= table
[i
];
215 unsigned int measure
= 1;
216 boolean first
= TRUE
;
221 else while (entry
!= NULL
)
232 measure
= 2 * measure
;
237 extern void printKeywordTable (void)
239 unsigned long emptyBucketCount
= 0;
240 unsigned long measure
= 0;
243 for (i
= 0 ; i
< TableSize
; ++i
)
245 const unsigned int pass
= printBucket (i
);
252 printf ("spread measure = %ld\n", measure
);
253 printf ("%ld empty buckets\n", emptyBucketCount
);
258 /* vi:set tabstop=4 shiftwidth=4: */