Merge branch '1.37'
[geany-mirror.git] / ctags / main / keyword.c
blob374c311e5146dc15c23af3c4a03915218fa0308a
1 /*
2 * Copyright (c) 1998-2002, Darren Hiebert
4 * This source code is released for free distribution under the terms of the
5 * GNU General Public License version 2 or (at your option) any later version.
7 * Manages a keyword hash.
8 */
11 * INCLUDE FILES
13 #include "general.h" /* must always come first */
15 #include <string.h>
16 #include <ctype.h>
18 #include "debug.h"
19 #include "keyword.h"
20 #include "options.h"
21 #include "routines.h"
24 * DATA DECLARATIONS
26 typedef struct sHashEntry {
27 struct sHashEntry *next;
28 const char *string;
29 langType language;
30 int value;
31 } hashEntry;
34 * DATA DEFINITIONS
36 static const unsigned int TableSize = 2039; /* prime */
37 static hashEntry **HashTable = NULL;
40 * FUNCTION DEFINITIONS
43 static hashEntry **getHashTable (void)
45 static bool allocated = false;
47 if (! allocated)
49 unsigned int i;
51 HashTable = xMalloc (TableSize, hashEntry*);
53 for (i = 0 ; i < TableSize ; ++i)
54 HashTable [i] = NULL;
56 allocated = true;
58 return HashTable;
61 static hashEntry *getHashTableEntry (unsigned long hashedValue)
63 hashEntry **const table = getHashTable ();
64 hashEntry *entry;
66 Assert (hashedValue < TableSize);
67 entry = table [hashedValue];
69 return entry;
72 static unsigned int hashValue (const char *const string, langType language)
74 const signed char *p;
75 unsigned int h = 5381;
77 Assert (string != NULL);
79 /* "djb" hash as used in g_str_hash() in glib */
80 for (p = (const signed char *)string; *p != '\0'; p++)
81 h = (h << 5) + h + tolower (*p);
83 /* consider language as an extra "character" and add it to the hash */
84 h = (h << 5) + h + language;
86 return h;
89 static hashEntry *newEntry (
90 const char *const string, langType language, int value)
92 hashEntry *const entry = xMalloc (1, hashEntry);
94 entry->next = NULL;
95 entry->string = string;
96 entry->language = language;
97 entry->value = value;
99 return entry;
102 /* Note that it is assumed that a "value" of zero means an undefined keyword
103 * and clients of this function should observe this. Also, all keywords added
104 * should be added in lower case. If we encounter a case-sensitive language
105 * whose keywords are in upper case, we will need to redesign this.
107 extern void addKeyword (const char *const string, langType language, int value)
109 const unsigned int index = hashValue (string, language) % TableSize;
110 hashEntry *entry = getHashTableEntry (index);
112 if (entry == NULL)
114 hashEntry **const table = getHashTable ();
115 table [index] = newEntry (string, language, value);
117 else
119 hashEntry *prev = NULL;
121 while (entry != NULL)
123 if (language == entry->language &&
124 strcmp (string, entry->string) == 0)
126 Assert (("Already in table" == NULL));
128 prev = entry;
129 entry = entry->next;
131 if (entry == NULL)
133 Assert (prev != NULL);
134 prev->next = newEntry (string, language, value);
139 static int lookupKeywordFull (const char *const string, bool caseSensitive, langType language)
141 const unsigned int index = hashValue (string, language) % TableSize;
142 hashEntry *entry = getHashTableEntry (index);
143 int result = KEYWORD_NONE;
145 while (entry != NULL)
147 if (language == entry->language &&
148 ((caseSensitive && strcmp (string, entry->string) == 0) ||
149 (!caseSensitive && strcasecmp (string, entry->string) == 0)))
151 result = entry->value;
152 break;
154 entry = entry->next;
156 return result;
159 extern int lookupKeyword (const char *const string, langType language)
161 return lookupKeywordFull (string, true, language);
164 extern int lookupCaseKeyword (const char *const string, langType language)
166 return lookupKeywordFull (string, false, language);
169 extern void freeKeywordTable (void)
171 if (HashTable != NULL)
173 unsigned int i;
175 for (i = 0 ; i < TableSize ; ++i)
177 hashEntry *entry = HashTable [i];
179 while (entry != NULL)
181 hashEntry *next = entry->next;
182 eFree (entry);
183 entry = next;
186 eFree (HashTable);
190 #ifdef DEBUG
192 static void printEntry (const hashEntry *const entry)
194 printf (" %-15s %-7s\n", entry->string, getLanguageName (entry->language));
197 static unsigned int printBucket (const unsigned int i)
199 hashEntry **const table = getHashTable ();
200 hashEntry *entry = table [i];
201 unsigned int measure = 1;
202 bool first = true;
204 printf ("%2d:", i);
205 if (entry == NULL)
206 printf ("\n");
207 else while (entry != NULL)
209 if (! first)
210 printf (" ");
211 else
213 printf (" ");
214 first = false;
216 printEntry (entry);
217 entry = entry->next;
218 measure = 2 * measure;
220 return measure - 1;
223 extern void printKeywordTable (void)
225 unsigned long emptyBucketCount = 0;
226 unsigned long measure = 0;
227 unsigned int i;
229 for (i = 0 ; i < TableSize ; ++i)
231 const unsigned int pass = printBucket (i);
233 measure += pass;
234 if (pass == 0)
235 ++emptyBucketCount;
238 printf ("spread measure = %ld\n", measure);
239 printf ("%ld empty buckets\n", emptyBucketCount);
242 #endif