diff options
-rw-r--r-- | 6.6/Makefile | 14 | ||||
-rw-r--r-- | 6.6/def.c | 72 | ||||
-rw-r--r-- | 6.6/def.h | 3 | ||||
-rw-r--r-- | 6.6/getch.c | 23 | ||||
-rw-r--r-- | 6.6/getch.h | 2 | ||||
-rw-r--r-- | 6.6/hash.c | 117 | ||||
-rw-r--r-- | 6.6/hash.h | 19 | ||||
-rw-r--r-- | 6.6/main.c | 32 | ||||
-rw-r--r-- | 6.6/test.c | 8 | ||||
-rw-r--r-- | 6.6/word.c | 26 | ||||
-rw-r--r-- | 6.6/word.h | 2 |
11 files changed, 318 insertions, 0 deletions
diff --git a/6.6/Makefile b/6.6/Makefile new file mode 100644 index 0000000..0900c66 --- /dev/null +++ b/6.6/Makefile @@ -0,0 +1,14 @@ +objects = main.o hash.o word.o getch.o def.o +CC = gcc +CFLAGS = -Wvla -Wall -Wextra -Wstrict-prototypes -Wmissing-prototypes -fsanitize=address + +def : $(objects) + $(CC) $(CFLAGS) -o def $(objects) + +main.o : word.h hash.h def.h +def.o : hash.h word.h getch.h def.h +word.o : getch.h + +.PHONY : clean +clean: + rm def $(objects) diff --git a/6.6/def.c b/6.6/def.c new file mode 100644 index 0000000..b3fef1f --- /dev/null +++ b/6.6/def.c @@ -0,0 +1,72 @@ +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#include <ctype.h> +#include "word.h" +#include "hash.h" +#include "getch.h" +#include "def.h" + +#define MAXWORD 100 + +static void error(char c, char *s); +void skipblanks(void); +int endline(char *s, int lim); + +void getdef(struct nlist *hashtab[], uint32_t hashsize) +{ + char dir[MAXWORD], name[MAXWORD], def[MAXWORD]; + + skipblanks(); + if (!isalpha(getword(dir, MAXWORD))) { + error(dir[0], "getdef: expecting a directive after #"); + } else if (!strcmp(dir, "define")) { + skipblanks(); + if (!isalpha(getword(name, MAXWORD))) { + error(name[0], "getdef: non-alpha in undef"); + } else { + if(endline(def, MAXWORD) == MAXWORD) + error(def[0], "getdef: incomplete define"); + else + install(hashtab, hashsize, name, def); + } + } else if (!strcmp(dir, "undef")) { + skipblanks(); + if (isalpha(getword(name, MAXWORD))) + undef(hashtab, hashsize, name); + else + error(name[0], "getdef: non-alpha in undef"); + } else { + error(dir[0], "getdef: directive invalid or not implemented"); + } +} + +static void error(char c, char *s) +{ + printf("err: %s\n", s); + + while (c != EOF && c != '\n') + c = getch(); +} + +void skipblanks(void) +{ + char c; + + while (isblank(c = getch())) + ; + + ungetch(c); +} + +int endline(char *s, int lim) +{ + int i; + + skipblanks(); + for (i = 0; i < lim - 1; ++i) + if ((s[i] = getch()) == EOF || s[i] == '\n') + break; + s[i] = '\0'; + return lim - i; +} diff --git a/6.6/def.h b/6.6/def.h new file mode 100644 index 0000000..f2f2533 --- /dev/null +++ b/6.6/def.h @@ -0,0 +1,3 @@ +#include <stdint.h> + +void getdef(struct nlist *hashtab[], uint32_t hashsize); diff --git a/6.6/getch.c b/6.6/getch.c new file mode 100644 index 0000000..f271434 --- /dev/null +++ b/6.6/getch.c @@ -0,0 +1,23 @@ +#include <stdio.h> +#include <stdlib.h> +#include <error.h> +#include <errno.h> +#include "getch.h" + +#define MAXBUFF 100 + +int top; +char buff[MAXBUFF]; + +char getch(void) +{ + return (top > 0) ? buff[--top] : getchar(); +} + +void ungetch(char c) +{ + if (top < MAXBUFF) + buff[top++] = c; + else + error(EXIT_FAILURE, ENOBUFS, "getch"); +} diff --git a/6.6/getch.h b/6.6/getch.h new file mode 100644 index 0000000..b0e086b --- /dev/null +++ b/6.6/getch.h @@ -0,0 +1,2 @@ +char getch(void); +void ungetch(char c); 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]); +} diff --git a/6.6/hash.h b/6.6/hash.h new file mode 100644 index 0000000..b6bdf82 --- /dev/null +++ b/6.6/hash.h @@ -0,0 +1,19 @@ +#include <stdint.h> + +#ifndef HASH_H + +struct nlist { + struct nlist *next; + char *name; + char *defn; +}; + +#define HASH_H +#endif + +struct nlist *install(struct nlist *hashtab[], uint32_t hashsize, + char *name, char *defn); +struct nlist *lookup(struct nlist *hashtab[], uint32_t hashsize, char *s); +void undef(struct nlist *hashtab[], uint32_t hashsize, char *name); +void phashtab(struct nlist *hastab[], int hashsize); +void hashfree(struct nlist *hastab[], int hashsize); diff --git a/6.6/main.c b/6.6/main.c new file mode 100644 index 0000000..19a7323 --- /dev/null +++ b/6.6/main.c @@ -0,0 +1,32 @@ +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include "word.h" +#include "hash.h" +#include "def.h" + +#define MAXWORD 100 +#define HASHSIZE 100 + +struct nlist *hashtab[HASHSIZE]; + +int main(void) +{ + char word[MAXWORD]; + struct nlist *np, *temp; + + while (getword(word, MAXWORD) != EOF) { + if (!strcmp(word, "#")) { + getdef(hashtab, HASHSIZE); + } else if (!isalpha(word[0])) { + printf("%s", word); + } else if ((np = lookup(hashtab, HASHSIZE, word)) == NULL) { + printf("%s", word); + } else { + ungetword(np->defn); + } + } + + hashfree(hashtab, HASHSIZE); + return 0; +} diff --git a/6.6/test.c b/6.6/test.c new file mode 100644 index 0000000..d6e7240 --- /dev/null +++ b/6.6/test.c @@ -0,0 +1,8 @@ +#define sneed feed +#define chuck seek +#define based soy +#undef chuck + +int based; +int chuck; +int soy; diff --git a/6.6/word.c b/6.6/word.c new file mode 100644 index 0000000..7f26dfd --- /dev/null +++ b/6.6/word.c @@ -0,0 +1,26 @@ +#include <ctype.h> +#include <string.h> +#include "getch.h" +#include "word.h" + +char getword(char *word, int lim) +{ + char *w = word; + + if (isalpha(*w = getch())) { + while ((isalnum(*++w = getch()) || *w == '_') && --lim > 0) + ; + ungetch(*w--); + } + + *++w = '\0'; + return word[0]; +} + +void ungetword(char *word) +{ + int len; + + for (len = strlen(word); len >= 0; --len) + ungetch(word[len]); +} diff --git a/6.6/word.h b/6.6/word.h new file mode 100644 index 0000000..9bcfcf8 --- /dev/null +++ b/6.6/word.h @@ -0,0 +1,2 @@ +char getword(char *word, int lim); +void ungetword(char *word); |