/* symtab.c hashtable file for vasm */ /* (c) in 2002-2004,2008,2011,2014 by Volker Barthelmann and Frank Wille */ #include "vasm.h" hashtable *new_hashtable(size_t size) { hashtable *new = mymalloc(sizeof(*new)); new->size = size; new->collisions = 0; new->entries = mycalloc(size*sizeof(*new->entries)); return new; } size_t hashcode(char *name) { size_t h = 5381; int c; while (c = (unsigned char)*name++) h = ((h << 5) + h) + c; return h; } size_t hashcodelen(char *name,int len) { size_t h = 5381; while (len--) h = ((h << 5) + h) + (unsigned char)*name++; return h; } size_t hashcode_nc(char *name) { size_t h = 5381; int c; while (c = (unsigned char)*name++) h = ((h << 5) + h) + tolower(c); return h; } size_t hashcodelen_nc(char *name,int len) { size_t h = 5381; while (len--) h = ((h << 5) + h) + tolower((unsigned char)*name++); return h; } /* add to hashtable; name must be unique */ void add_hashentry(hashtable *ht,char *name,hashdata data) { size_t i=nocase?(hashcode_nc(name)%ht->size):(hashcode(name)%ht->size); hashentry *new=mymalloc(sizeof(*new)); new->name=name; new->data=data; if(debug){ if(ht->entries[i]) ht->collisions++; } new->next=ht->entries[i]; ht->entries[i]=new; } /* remove from hashtable; name must be unique */ void rem_hashentry(hashtable *ht,char *name,int no_case) { size_t i=no_case?(hashcode_nc(name)%ht->size):(hashcode(name)%ht->size); hashentry *p,*last; for(p=ht->entries[i],last=NULL;p;p=p->next){ if(!strcmp(name,p->name)||(no_case&&!stricmp(name,p->name))){ if(last==NULL) ht->entries[i]=p->next; else last->next=p->next; myfree(p); return; } last=p; } ierror(0); } /* finds unique entry in hashtable */ int find_name(hashtable *ht,char *name,hashdata *result) { if(nocase) return find_name_nc(ht,name,result); else{ size_t i=hashcode(name)%ht->size; hashentry *p; for(p=ht->entries[i];p;p=p->next){ if(!strcmp(name,p->name)){ *result=p->data; return 1; }else ht->collisions++; } } return 0; } /* same as above, but uses len instead of zero-terminated string */ int find_namelen(hashtable *ht,char *name,int len,hashdata *result) { if(nocase) return find_namelen_nc(ht,name,len,result); else{ size_t i=hashcodelen(name,len)%ht->size; hashentry *p; for(p=ht->entries[i];p;p=p->next){ if(!strncmp(name,p->name,len)&&p->name[len]==0){ *result=p->data; return 1; }else ht->collisions++; } } return 0; } /* finds unique entry in hashtable - case insensitive */ int find_name_nc(hashtable *ht,char *name,hashdata *result) { size_t i=hashcode_nc(name)%ht->size; hashentry *p; for(p=ht->entries[i];p;p=p->next){ if(!stricmp(name,p->name)){ *result=p->data; return 1; }else ht->collisions++; } return 0; } /* same as above, but uses len instead of zero-terminated string */ int find_namelen_nc(hashtable *ht,char *name,int len,hashdata *result) { size_t i=hashcodelen_nc(name,len)%ht->size; hashentry *p; for(p=ht->entries[i];p;p=p->next){ if(!strnicmp(name,p->name,len)&&p->name[len]==0){ *result=p->data; return 1; }else ht->collisions++; } return 0; }