bfck

Brainfuck interpreter with breakpoint support
git clone git://git.noxz.tech/bfck
Log | Files | Refs

commit 36fae0a9fab3e39356f26cd136b3874f98ac56bf
Author: Chris Noxz <chris@noxz.tech>
Date:   Sat, 14 Sep 2019 19:41:40 +0200

Initial commit of bfck (brainfuck interpreter with break support)

Diffstat:
Abfck.c | 189+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 189 insertions(+), 0 deletions(-)

diff --git a/bfck.c b/bfck.c @@ -0,0 +1,189 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ncurses.h> + +#define ALLOCATION_SIZE 1024 +#define BETWEEN(x, a, b) (((x) >= (a)) && ((x) <= (b))) + +static unsigned char *cols; +static char *bf; + +void +allocate(int alc) +{ + size_t s = ALLOCATION_SIZE * (alc + 1); + char *new; + + if ((new = calloc(s, sizeof(char))) == NULL) + memset(new, 0, s * sizeof(char)); + memmove(new, cols, (ALLOCATION_SIZE * alc)); + + free(cols); + cols = new; +} + +void +run() +{ + int i, j, l, x; + int idx = 0, /* index of column */ + pos = 0, /* possitiong in debug */ + beg = 0, /* begining in debug */ + alc = 1, /* allocation count */ + lix = 0; /* loop index */ + char ch = 0; + + cols = calloc(ALLOCATION_SIZE, sizeof(char)); + memset(cols, 0, ALLOCATION_SIZE * sizeof(char)); + + /* remove non-brainfuck */ + for (i = j = 0, l = strlen(bf); i < l; i++) + if (strchr("[]<>+-,.!", bf[i])) + bf[j++] = bf[i]; + bf[(l = j)] = 0; + + for (i = 0; i < l; i++) { + switch (bf[i]) { + case '>': + /* check if more columns are needed */ + if (idx++ >= (ALLOCATION_SIZE * alc) - 1) + allocate(alc++); + break; + case '<': + if (idx <= 0) + break; + idx--; + break; + case '[': + /* skip if zero */ + if (cols[idx] == 0) { + for (x = 0, i++; i < l; i++) { + if (bf[i] == '[') + x++; + else if (bf[i] == ']' && x > 0) + x--; + else if (bf[i] == ']') + break; + } + break; + } + lix++; + break; + case ']': + /* go back if not zero */ + if (cols[idx] != 0) { + for (x = 0, j = i - 1; j > 0; j--) { + if (bf[j] == ']') + x++; + else if (bf[j] == '[' && x > 0) + x--; + else if (bf[j] == '[') + break; + } + i = j; /* jump to beginning */ + break; + } + lix--; /* leave loop */ + break; + case '+': + if (cols[idx] < 255) + cols[idx]++; + break; + case '-': + if (cols[idx] > 0) + cols[idx]--; + break; + case '.': + putchar(cols[idx]); + break; + case ',': + cols[idx] = getchar(); + break; + case '!': + initscr(); + cbreak(); + noecho(); + + for (pos = idx;;) { + clear(); + + if (ch == 0x1B) + break; + else if (ch == 0x68 && pos > 0) + pos--; + else if (ch == 0x6C && pos < alc * ALLOCATION_SIZE) + pos++; + else if (ch == 0x6A && cols[pos] > 0) + cols[pos]--; + else if (ch == 0x6B && cols[pos] < 255) + cols[pos]++; + + beg = pos < 5 ? 0 : pos - 5; + if (beg > (alc * ALLOCATION_SIZE - 10)) + beg = alc * ALLOCATION_SIZE - 10; + + printw("breakpoint: %d\n\n\n", i); + + if ((beg - idx) < 0) + printw("%*s!\n", (beg - idx) * 4 - 1, " "); + else + printw("\n"); + + for (int p = beg; p < beg + 11; p++) + cols[p] < 10 \ + ? printw(" %-2d ", cols[p]) \ + : printw("%-3d ", cols[p]); + printw("\n"); + + for (int p = beg; p < beg + 11; p++) + printw("[%c] ", + BETWEEN(cols[p], 32, 126) ? cols[p] : ' '); + printw("\n"); + + printw("%*s^\n", + (pos - beg != 5 ? (pos - beg) : 5) * 4 + 1, " "); + pos < 10 \ + ? printw("%*s%d\n", + (pos - beg != 5 ? (pos - beg) : 5) * 4 + 1, " ", pos) \ + : printw("%*s%d\n", + (pos - beg != 5 ? (pos - beg) : 5) * 4 + 0, " ", pos); + + printw("\n press [ESC] to continue...\n"); + ch = getch(); + } + + refresh(); + endwin(); + break; + } + } +} + +void +load(const char *fn) +{ + int b, n = 0; + char buf[1024], *p = 0; + FILE *f = NULL; + + if (!(f = fopen(fn, "r"))) + exit(0); + + while (!feof(f)) { + b = fread(buf, 1, sizeof buf, f); + if (!(p = (char *)realloc(p, (n += b) + 1))) + exit(1); + memcpy(p + n - b, buf, b); + } + fclose(f); + bf = p; +} + +int +main(int argc, char *argv[]) +{ + load(argv[1]); + run(); + free(cols); +}