Commits

Evan Gates  committed f6db2cc

add bf interpreter

  • Participants
  • Parent commits b87158d

Comments (0)

Files changed (1)

+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef void (*Inst)(void);
+#define STOP (Inst)0
+
+Inst  *prog, *pc, *ni; /* program, program counter, next instruction spot */
+char  *bfm , *p;       /* bf memory, bf pointer */
+size_t prog_size, bfm_size;
+
+void incp (void) {
+	if (++p - bfm != bfm_size) return;
+	bfm = realloc(bfm, (bfm_size *= 2) * sizeof(*bfm));
+	p = bfm + bfm_size / 2;
+	memset(bfm + bfm_size / 2, 0, bfm_size / 2 * sizeof(*bfm));
+}
+void decp (void) { if (--p < bfm) { fprintf(stderr, "p < 0\n"); *pc-- = STOP; } }
+void incat(void) { ++*p; }
+void decat(void) { --*p; }
+void putch(void) { putchar(*p); }
+void getch(void) { int c = getchar(); if (c != EOF) *p = c;}
+void lbrac(void) { pc++; if (!*p) pc = (Inst*)*pc; }
+void rbrac(void) { pc++; if ( *p) pc = (Inst*)*pc; }
+
+void code(Inst f) {
+	if (ni - prog == prog_size) {
+		prog = realloc(prog, (prog_size *= 2) * sizeof(*prog));
+		ni = prog + prog_size / 2;
+	}
+	*ni++ = f;
+}
+
+int main(void)
+{
+	Inst *ip , insts[]     = { incp, decp, incat, decat, putch, getch, lbrac, rbrac };
+	char *icp, instchars[] =   ">"   "<"   "+"    "-"    "."    ","    "["    "]"    ;
+
+	for (;;) {
+		int c, b = 0;
+		p  = bfm  = calloc(bfm_size  = 1, sizeof(*bfm ));
+		ni = prog = calloc(prog_size = 1, sizeof(*prog));
+		while ((c = getchar()) != EOF) {
+			if (!(icp = strchr(instchars, c))) continue;
+			code(insts[icp - instchars]);
+
+			switch (c) {
+				case '[': code(STOP); ++b;            break;
+				case ']': code(STOP); --b; if (b < 0) break;
+					for (ip = ni - 2; ip >= prog && *ip != STOP; ip--)
+						;
+					*ip = (Inst)(ni - 1);
+					*(ni - 1) = (Inst)ip;
+					break;
+			}
+			if (b < 0) {
+				while ((c = getchar()) != EOF)
+					;
+				break;
+			}
+		}
+		code(STOP);
+		if (b)
+			fprintf(stderr, "extra %c\n", b < 0 ? ']' : '[');
+		else
+			for (pc = prog; *pc != STOP; pc++)
+				(*(*pc))();
+		free(bfm);
+		free(prog);
+	}
+}