diff options
Diffstat (limited to '6.6/hash.c')
-rw-r--r-- | 6.6/hash.c | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/6.6/hash.c b/6.6/hash.c new file mode 100644 index 0000000..5d5d6f8 --- /dev/null +++ b/6.6/hash.c @@ -0,0 +1,117 @@ +#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); +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 *np, *prev; + uint32_t h; + + prev = NULL; + h = hash(name, hashsize); + for (np = hashtab[h]; np != NULL; prev = np, np = np->next) + if (!strcmp(name, np->name)) + break; + + if (np != NULL) { + if (prev == NULL) + hashtab[h] = np->next; + else + prev->next = np->next; + + np->next = NULL; + nlfree(np); + 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]); +} |