From 9aacd3da5ba1409250c7cef0f51ee7a5745222e8 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Sun, 1 Dec 2013 07:01:05 +0000 Subject: recursive loops --- bf.c | 91 ++++++++++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 56 insertions(+), 35 deletions(-) diff --git a/bf.c b/bf.c index 6bd9925..1903c38 100644 --- a/bf.c +++ b/bf.c @@ -45,33 +45,31 @@ alloccell(void) return c; } +Cell * +rewindcells(Cell *c) +{ + while (c->prev) + c = c->prev; + + return c; +} + void freecells(Cell *c) { Cell *next; - while (c->prev) - c = c->prev; - - while (c) { + for (c = rewindcells(c); c; c = next) { next = c->next; free(c); - c = next; } } void dumpcells(Cell *c) { - while (c->prev) - c = c->prev; - - while (c) { - printf("0x%-4.2x", c->value); - c = c->next; - } - - printf("\n"); + for (c = rewindcells(c); c; c = c->next) + printf("0x%x\n", c->value); } char * @@ -108,14 +106,46 @@ usage(void) exit(1); } -void -execute(Cell *data, char *prog) +char * +walk(char **j, char *p) { - char *p; - int loop; - - for (p = prog; *p; p++) + for (; *p; p++, j++) switch (*p) { + case '[': + *j = walk(j + 1, p + 1); + break; + case ']': + return p; + default: + break; + } + + return NULL; +} + +char * +locatejmp(char *prog) +{ + for (; *prog; prog++) + switch (*prog) { + case '[': + prog = locatejmp(prog + 1); + break; + case ']': + return prog; + default: + break; + } + + errx(1, "unbalanced loop"); + /* NOTREACHED */ +} + +Cell * +execute(Cell *data, char *prog) +{ + for (; *prog; prog++) + switch (*prog) { case '>': if (!data->next) { data->next = alloccell(); @@ -144,26 +174,17 @@ execute(Cell *data, char *prog) data->value = fgetc(stdin); break; case '[': - if (data->value == 0) - for (loop = 0; *p; p++) { - if (*p == '[') - loop++; - else if (*p == ']' && --loop == 0) - break; - } + while (data->value) + data = execute(data, prog + 1); + prog = locatejmp(prog + 1); break; case ']': - if (data->value != 0) - for (loop = 0; *p; p--) { - if (*p == ']') - loop++; - else if (*p == '[' && --loop == 0) - break; - } - break; + return data; default: break; } + + return data; } int -- cgit v1.2.3