diff options
Diffstat (limited to '6.5/hash.c')
-rw-r--r-- | 6.5/hash.c | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/6.5/hash.c b/6.5/hash.c new file mode 100644 index 0000000..1e29bd7 --- /dev/null +++ b/6.5/hash.c @@ -0,0 +1,115 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include "hash.h" + +void nlfree(struct nlist *p); +uint32_t hash(char *s, uint32_t hashsize); +struct nlist *lookup(struct nlist *hashtab[], uint32_t hashsize, char *s); +void pnl(struct nlist *np); + +uint32_t hash(char *s, uint32_t hashsize) +{ + uint32_t hashval; + + for (hashval = 0; *s != '\0'; ++s) + hashval = *s + 31*hashval; + + return hashval % hashsize; +} + +struct nlist *lookup(struct nlist *hashtab[], uint32_t hashsize, char *s) +{ + struct nlist *np; + + for (np = hashtab[hash(s, hashsize)]; np != NULL; np = np->next) + if (!strcmp(s, np->name)) + return np; + + return NULL; +} + +struct nlist *install(struct nlist *hashtab[], uint32_t hashsize, + char *name, char *defn) +{ + struct nlist *np; + uint32_t hashval; + + if ((np = lookup(hashtab, hashsize, name)) == NULL) { + np = (struct nlist *) malloc(sizeof(*np)); + if (np == NULL || (np->name = strdup(name)) == NULL) { + nlfree(np); + return NULL; + } + + hashval = hash(name, hashsize); + np->next = hashtab[hashval]; + hashtab[hashval] = np; + } else { + free(np->defn); + } + + if ((np->defn = strdup(defn)) == NULL) { + undef(hashtab, hashsize, name); + return NULL; + } + + return np; +} + +void undef(struct nlist *hashtab[], uint32_t hashsize, char *name) +{ + struct nlist *cur, *last; + uint32_t hashval = hash(name, hashsize); + + for (cur = hashtab[hashval], last = NULL; cur !=NULL; last = cur, + cur = cur->next) { + if (!strcmp(cur->name, name)) { + if (last == NULL) + hashtab[hashval] = cur->next; + else + last->next = cur->next; + + cur->next = NULL; + nlfree(cur); + return; + } + } +} + +void pnl(struct nlist *np) +{ + if (np != NULL) { + pnl(np->next); + printf("%10s %s\n", np->name, np->defn); + } +} + +void phashtab(struct nlist *hashtab[], int lim) +{ + int i; + + for (i = 0; i < lim; ++i) + pnl(hashtab[i]); +} + +void nlfree(struct nlist *p) +{ + if (p != NULL ) { + nlfree(p->next); + if (p->defn != NULL) + free(p->defn); + if (p->name != NULL) + free(p->name); + free(p); + } +} + +void hashfree(struct nlist *hashtab[], int lim) +{ + int i; + + for (i = 0; i < lim; ++i) + nlfree(hashtab[i]); +} |