Updated Spanish translation
[anjuta-git-plugin.git] / tagmanager / keyword.c
blobbb0b849d56b4883f221ae9a6ab660803a41ddb82
1 /*
2 * $Id$
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.
13 * INCLUDE FILES
15 #include "general.h" /* must always come first */
17 #include <string.h>
19 #include "debug.h"
20 #include "keyword.h"
21 #include "options.h"
22 #include "routines.h"
25 * MACROS
27 #define HASH_EXPONENT 7 /* must be less than 17 */
30 * DATA DECLARATIONS
32 typedef struct sHashEntry {
33 struct sHashEntry *next;
34 const char *string;
35 langType language;
36 int value;
37 } hashEntry;
40 * DATA DEFINITIONS
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;
53 if (! allocated)
55 unsigned int i;
57 HashTable = xMalloc (TableSize, hashEntry*);
59 for (i = 0 ; i < TableSize ; ++i)
60 HashTable [i] = NULL;
62 allocated = TRUE;
64 return HashTable;
67 static hashEntry *getHashTableEntry (unsigned long hashedValue)
69 hashEntry **const table = getHashTable ();
70 hashEntry *entry;
72 Assert (hashedValue < TableSize);
73 entry = table [hashedValue];
75 return entry;
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)
90 value <<= 1;
91 if (value & 0x00000100L)
92 value = (value & 0x000000ffL) + 1L;
93 value ^= *p;
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 */
102 return value;
105 static hashEntry *newEntry (
106 const char *const string, langType language, int value)
108 hashEntry *const entry = xMalloc (1, hashEntry);
110 entry->next = NULL;
111 entry->string = string;
112 entry->language = language;
113 entry->value = value;
115 return entry;
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 *tableEntry = getHashTableEntry (hashedValue);
127 hashEntry *entry = tableEntry;
129 if (entry == NULL)
131 hashEntry **const table = getHashTable ();
132 table [hashedValue] = newEntry (string, language, value);
134 else
136 hashEntry *prev = NULL;
138 while (entry != NULL)
140 if (language == entry->language &&
141 strcmp (string, entry->string) == 0)
143 Assert (("Already in table" == NULL));
145 prev = entry;
146 entry = entry->next;
148 if (entry == NULL)
150 Assert (prev != NULL);
151 prev->next = newEntry (string, language, value);
156 extern int lookupKeyword (const char *const string, langType language)
158 const unsigned long hashedValue = hashValue (string);
159 hashEntry *entry = getHashTableEntry (hashedValue);
160 int result = -1;
162 while (entry != NULL)
164 if (language == entry->language && strcmp (string, entry->string) == 0)
166 result = entry->value;
167 break;
169 entry = entry->next;
171 return result;
174 extern void freeKeywordTable (void)
176 if (HashTable != NULL)
178 unsigned int i;
180 for (i = 0 ; i < TableSize ; ++i)
182 hashEntry *entry = HashTable [i];
184 while (entry != NULL)
186 hashEntry *next = entry->next;
187 eFree (entry);
188 entry = next;
191 eFree (HashTable);
195 #ifdef DEBUG
197 static void printEntry (const hashEntry *const entry)
199 printf (" %-15s %-7s\n", entry->string, getLanguageName (entry->language));
202 static unsigned int printBucket (const unsigned int i)
204 hashEntry **const table = getHashTable ();
205 hashEntry *entry = table [i];
206 unsigned int measure = 1;
207 boolean first = TRUE;
209 printf ("%2d:", i);
210 if (entry == NULL)
211 printf ("\n");
212 else while (entry != NULL)
214 if (! first)
215 printf (" ");
216 else
218 printf (" ");
219 first = FALSE;
221 printEntry (entry);
222 entry = entry->next;
223 measure = 2 * measure;
225 return measure - 1;
228 extern void printKeywordTable (void)
230 unsigned long emptyBucketCount = 0;
231 unsigned long measure = 0;
232 unsigned int i;
234 for (i = 0 ; i < TableSize ; ++i)
236 const unsigned int pass = printBucket (i);
238 measure += pass;
239 if (pass == 0)
240 ++emptyBucketCount;
243 printf ("spread measure = %ld\n", measure);
244 printf ("%ld empty buckets\n", emptyBucketCount);
247 #endif
249 /* vi:set tabstop=4 shiftwidth=4: */