From 37e49d4684f54e113400781beb54815ce37721f0 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Tue, 24 Nov 2015 15:38:54 +0000 Subject: Jumptable --- bf.c | 157 +++++++++++++++++++++++++------------------------------------------ 1 file changed, 59 insertions(+), 98 deletions(-) diff --git a/bf.c b/bf.c index 4578488..ddda53d 100644 --- a/bf.c +++ b/bf.c @@ -26,19 +26,10 @@ #include #include #include -#include #include -struct cell { - int value; - int number; - TAILQ_ENTRY(cell) link; -} *dp, *dpn; - -TAILQ_HEAD(cells, cell) data; - char * -readall(char *fname) +readall(char *fname, size_t *len) { int fd; char *buf; @@ -46,14 +37,14 @@ readall(char *fname) fd = open(fname, O_RDONLY); if (!fd) - errx(1, "cannot open %s", fname); + return NULL; + fstat(fd, &st); + *len = st.st_size; - buf = calloc(st.st_size + 1, sizeof(char)); - if (!buf) - errx(1, "calloc"); + buf = calloc(*len + 1, sizeof(char)); - read(fd, buf, st.st_size); + read(fd, buf, *len); close(fd); return buf; @@ -64,137 +55,107 @@ usage(void) { extern char *__progname; - fprintf(stderr, "usage: %s [-d] \n", __progname); - + fprintf(stderr, "usage: %s \n", __progname); exit(1); /* NOTREACHED */ } char * -locatejmp(char *p) +mkjmptbl(char *prog, char **jmp) { - for (; *p; p++) - switch (*p) { + char *to; + + for (; *prog; prog++, jmp++) { + switch (*prog) { case '[': - p = locatejmp(p + 1); + *jmp = to = mkjmptbl(prog + 1, jmp + 1); + jmp += to - prog; + *jmp = prog; + prog = to; break; case ']': - return p; + return prog; default: break; } + } - errx(1, "unbalanced loop"); - /* NOTREACHED */ -} - -struct cell * -alloccell(void) -{ - struct cell *c; - - c = calloc(1, sizeof(struct cell)); - if (!c) - errx(1, "calloc"); - - return c; + return NULL; } -char * -execute(char *p) +void +execute(char *data, char *prog, char **jmp, size_t sz) { - char *jmp; + char *pc = prog; + char *dp = data + sz / 4; - for (; *p; p++) - switch (*p) { + for (; *pc; pc++) + switch (*pc) { case '>': - dpn = TAILQ_NEXT(dp, link); - if (!dpn) { - dpn = alloccell(); - dpn->number = dp->number + 1; - TAILQ_INSERT_TAIL(&data, dpn, link); - } - dp = dpn; + if (dp - data == sz) + errx(1, "memory overflow"); + ++dp; break; case '<': - dpn = TAILQ_PREV(dp, cells, link); - if (!dpn) { - dpn = alloccell(); - dpn->number = dp->number - 1; - TAILQ_INSERT_HEAD(&data, dpn, link); - } - dp = dpn; + if (dp - data == 0) + errx(1, "memory underflow"); + --dp; break; case '+': - ++dp->value; + ++*dp; break; case '-': - --dp->value; + --*dp; break; case '.': - fputc(dp->value, stdout); - fflush(stdout); + fputc(*dp, stdout); break; case ',': - dp->value = fgetc(stdin); + *dp = fgetc(stdin); break; case '[': - if (!dp->value) - jmp = locatejmp(p + 1); - else while (dp->value) - jmp = execute(p + 1); - p = jmp; + if (*dp == 0) + pc = jmp[pc - prog]; break; case ']': - return p; + if (*dp != 0) + pc = jmp[pc - prog]; + break; default: break; } - - return p; } int main(int argc, char **argv) { + char **jmp; char *prog; - int c, dflag = 0; + char *data; + size_t datasz; + size_t len; - while ((c = getopt(argc, argv, "dh")) != -1) - switch (c) { - case 'd': - dflag = 1; - break; - case 'h': - case '?': - default: - usage(); - /* NOTREACHED */ - } - - argc -= optind; - argv += optind; + argc--; + argv++; if (!argc) - errx(1, "no argument"); + usage(); + /* NOTREACHED */ - /* init first cell */ - TAILQ_INIT(&data); - dp = alloccell(); - TAILQ_INSERT_HEAD(&data, dp, link); + prog = readall(*argv, &len); + if (!prog) + errx(1, "cannot open %s", *argv); - prog = readall(*argv); - execute(prog); - free(prog); + datasz = getpagesize(); + data = calloc(datasz, sizeof(char)); + jmp = calloc(len, sizeof(char *)); - /* dump cells */ - if (dflag) - TAILQ_FOREACH(dp, &data, link) - printf("%4d: 0x%.8x\n", dp->number, dp->value); + mkjmptbl(prog, jmp); + execute(data, prog, jmp, datasz); - /* free cells */ - TAILQ_FOREACH_SAFE(dp, &data, link, dpn) - free(dp); + free(data); + free(prog); + free(jmp); return 0; } -- cgit v1.2.3