/*******************************************/ /* */ /* File: tlstable.c */ /* Purpose: Symbol Table routines */ /* */ /* Author: Sfiligoi Igor */ /* */ /* Last modified: 19.10.1996 */ /* */ /*******************************************/ #include <string.h> #include <stdlib.h> #include <ctype.h> #include "tlstable.h" #define EOS '\0' /* function hash pjw */ int HashFunc(char *name, unsigned int size) { char *p; unsigned long h=0, g; for (p=name; *p != EOS; p++) { h = (h<<4) + (*p); if ((g=h&0xf0000000)) /* assign to g */ { h = h ^ (g>>24); h = h ^ g; } } return h % size; } typedef struct stelement { char *name; void *data; struct stelement *next; } STElement; typedef struct strecord { unsigned int size; int case_sensitive; STElement * *hash; } STRecord; /* Create a new Symbol Table */ /* Initialy it is empty */ /* Returns a pointer to the Symbol Table */ void *STableNew(unsigned int size, int case_sensitive) { STRecord *newST; int i; /* Create Symbol table */ newST = (STRecord *) malloc(sizeof(STRecord)); newST->size = size; newST->case_sensitive = case_sensitive; /* Create Hash */ newST->hash = (STElement * *) malloc(size*sizeof(STElement *)); /*init Hash*/ for ( i=0; i<size; i++) { newST->hash[i] = (STElement *) NULL; } return (void *) newST; } /*Add name(max ST_varnamelng) to Symbol Table */ /*0 if error, 1 if OK */ int STableAdd(void *STable, /* Symol Table obtained from NewSTable() */ char *name, /* Name to add */ void *data) /* Data that you want to preserve */ { STRecord *actST; STElement *element,*temp; int hashNr; /* where to put name */ char *iname; int result; actST = (STRecord *) STable; iname = (char *) malloc(strlen(name)+1); strcpy(iname, name); if (actST->case_sensitive==0) iname = ST2insensitive(name); else { iname = (char *) malloc(strlen(name)+1); strcpy(iname, name); } hashNr = HashFunc(iname,actST->size); /* Find if Name allready exists */ temp = actST->hash[hashNr]; while ( (temp != NULL) && (strcmp(iname, temp->name)!=0) ) { temp = temp->next; } if (temp!=NULL) { /* found another name */ return ST_Duplicate; } /* name is unique => do add*/ element = (STElement *) malloc( sizeof(STElement) ); element->name = iname; element->data = data; if (actST->hash[hashNr]==NULL) result = ST_OK; else result = ST_OK_Hit; element->next = actST->hash[hashNr]; actST->hash[hashNr] = element; return result; } /* Find name in the Symbol Table*/ /* Return 1 if found, 0 otherwise */ int STableFind(void *STable, /* Symol Table obtained from NewSTable() */ char *name, /* Name to find */ void * *data) /* OUT - Data of the found item */ { STRecord *actST; STElement *element; int hashNr; char *iname; actST = (STRecord *) STable; if (actST->case_sensitive==0) iname = ST2insensitive(name); else iname = name; hashNr = HashFunc(iname,actST->size); element = actST->hash[hashNr]; while ( (element != NULL) && (strcmp(iname, element->name)!=0) ) { element = element->next; } if (actST->case_sensitive==0) free(iname); if (element==NULL) { /* not found */ return ST_NotFound; } else { /* found, return data */ *data = element->data; return ST_OK; } } /* Find name in the Symbol Table*/ /* and delete it from ST */ /* Return ST_OK if found, ST_NotFound otherwise */ int STableCut(void *STable, /* Symbol Table obtained from NewSTable() */ char *name, /* Name to find */ void * *data) /* OUT - Data of the found item */ { STRecord *actST; STElement *element; STElement *prevel; int hashNr; char *iname; actST = (STRecord *) STable; if (actST->case_sensitive==0) iname = ST2insensitive(name); else iname= name; hashNr = HashFunc(iname,actST->size); prevel = NULL; element = actST->hash[hashNr]; while ( (element != NULL) && (strcmp(iname, element->name)!=0) ) { prevel = element; element = element->next; } if (actST->case_sensitive==0) free(iname); if (element==NULL) { /* not found */ return ST_NotFound; } else { /* found, return data and delete from hash */ *data = element->data; if (prevel!=NULL) prevel->next = element->next; else actST->hash[hashNr] = element->next; free(element->name); free(element); return ST_OK; } } /* Destroy a Symbol Table */ /* Call when you do not need the table anymore */ void STableDispose(void *STable, /* Symbol Table obtained from NewSTable() */ void (*freedata)(void *)) /* function that disposes the data passed */ { STRecord *actST; int i; actST = STable; /* Dispose data in each element of hash*/ for (i=0; i<actST->size; i++) { STElement *element; element = actST->hash[i]; while ( element != NULL ) { STElement *temp; free(element->name); /* Delete the user data */ (*freedata)(element->data); temp = element; element = element->next; /* delete the element */ free(temp); } } /* Dispose hash */ free(actST->hash); /* Dispose Symbol Table */ free(actST); return; } /***************************************************************************/ /* return a case insensitive string for case sensitive STable */ /* returned string must be freed by hand */ char *ST2insensitive(char *str) { /* set-up case insensitive name */ int i; int slng; char *istr; slng = strlen(str); istr = (char *) malloc(slng+3); istr[0] = 1; for (i=0; str[i] != EOS; i++) istr[i+1] = tolower(str[i]); istr[slng+1] = 1; istr[slng+2] = 0; return istr; }