keyword.c - ctags-5.8
Global variables defined
Data types defined
Functions defined
Macros defined
Source code
#include "general.h"
#include <string.h>
#include "debug.h"
#include "keyword.h"
#include "options.h"
#include "routines.h"
#define HASH_EXPONENT 7
typedef struct sHashEntry {
struct sHashEntry *next;
const char *string;
langType language;
int value;
} hashEntry;
static const unsigned int TableSize = 1 << HASH_EXPONENT;
static hashEntry **HashTable = NULL;
static hashEntry **getHashTable (void)
{
static boolean allocated = FALSE;
if (! allocated)
{
unsigned int i;
HashTable = xMalloc (TableSize, hashEntry*);
for (i = 0 ; i < TableSize ; ++i)
HashTable [i] = NULL;
allocated = TRUE;
}
return HashTable;
}
static hashEntry *getHashTableEntry (unsigned long hashedValue)
{
hashEntry **const table = getHashTable ();
hashEntry *entry;
Assert (hashedValue < TableSize);
entry = table [hashedValue];
return entry;
}
static unsigned long hashValue (const char *const string)
{
unsigned long value = 0;
const unsigned char *p;
Assert (string != NULL);
for (p = (const unsigned char *) string ; *p != '\0' ; ++p)
{
value <<= 1;
if (value & 0x00000100L)
value = (value & 0x000000ffL) + 1L;
value ^= *p;
}
value *= 40503L; value &= 0x0000ffffL; value >>= 16 - HASH_EXPONENT;
return value;
}
static hashEntry *newEntry (
const char *const string, langType language, int value)
{
hashEntry *const entry = xMalloc (1, hashEntry);
entry->next = NULL;
entry->string = string;
entry->language = language;
entry->value = value;
return entry;
}
extern void addKeyword (const char *const string, langType language, int value)
{
const unsigned long hashedValue = hashValue (string);
hashEntry *entry = getHashTableEntry (hashedValue);
if (entry == NULL)
{
hashEntry **const table = getHashTable ();
table [hashedValue] = newEntry (string, language, value);
}
else
{
hashEntry *prev = NULL;
while (entry != NULL)
{
if (language == entry->language &&
strcmp (string, entry->string) == 0)
{
Assert (("Already in table" == NULL));
}
prev = entry;
entry = entry->next;
}
if (entry == NULL)
{
Assert (prev != NULL);
prev->next = newEntry (string, language, value);
}
}
}
extern int lookupKeyword (const char *const string, langType language)
{
const unsigned long hashedValue = hashValue (string);
hashEntry *entry = getHashTableEntry (hashedValue);
int result = -1;
while (entry != NULL)
{
if (language == entry->language && strcmp (string, entry->string) == 0)
{
result = entry->value;
break;
}
entry = entry->next;
}
return result;
}
extern void freeKeywordTable (void)
{
if (HashTable != NULL)
{
unsigned int i;
for (i = 0 ; i < TableSize ; ++i)
{
hashEntry *entry = HashTable [i];
while (entry != NULL)
{
hashEntry *next = entry->next;
eFree (entry);
entry = next;
}
}
eFree (HashTable);
}
}
extern int analyzeToken (vString *const name, langType language)
{
vString *keyword = vStringNew ();
int result;
vStringCopyToLower (keyword, name);
result = lookupKeyword (vStringValue (keyword), language);
vStringDelete (keyword);
return result;
}
#ifdef DEBUG
static void printEntry (const hashEntry *const entry)
{
printf (" %-15s %-7s\n", entry->string, getLanguageName (entry->language));
}
static unsigned int printBucket (const unsigned int i)
{
hashEntry **const table = getHashTable ();
hashEntry *entry = table [i];
unsigned int measure = 1;
boolean first = TRUE;
printf ("%2d:", i);
if (entry == NULL)
printf ("\n");
else while (entry != NULL)
{
if (! first)
printf (" ");
else
{
printf (" ");
first = FALSE;
}
printEntry (entry);
entry = entry->next;
measure = 2 * measure;
}
return measure - 1;
}
extern void printKeywordTable (void)
{
unsigned long emptyBucketCount = 0;
unsigned long measure = 0;
unsigned int i;
for (i = 0 ; i < TableSize ; ++i)
{
const unsigned int pass = printBucket (i);
measure += pass;
if (pass == 0)
++emptyBucketCount;
}
printf ("spread measure = %ld\n", measure);
printf ("%ld empty buckets\n", emptyBucketCount);
}
#endif