commit: 36fae0a9fab3e39356f26cd136b3874f98ac56bf
parent:
author: Chris Noxz <chris@noxz.tech>
date: Sat, 14 Sep 2019 19:41:40 +0200
Initial commit of bfck (brainfuck interpreter with break support)
A | bfck.c | 189 | ++++++++++++++++++++ |
1 file changed, 189 insertions(+)
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);
+}