summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2009-04-28 00:34:55 +0000
committerDimitri Sokolyuk <demon@dim13.org>2009-04-28 00:34:55 +0000
commitf1b61a6346ae695568aa51b3502d58b8b36d346a (patch)
tree2a0e24b3962b8c8dd2d68b603ed73a5a690fc7ab
brainfuck interpreter
-rw-r--r--Makefile6
-rw-r--r--bf.c118
-rw-r--r--hw.bf17
3 files changed, 141 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..82f2073
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,6 @@
+# $Id$
+
+PROG= bf
+NOMAN=
+
+.include <bsd.prog.mk>
diff --git a/bf.c b/bf.c
new file mode 100644
index 0000000..411f50d
--- /dev/null
+++ b/bf.c
@@ -0,0 +1,118 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2009 Dimitri SokolyukE <sokolyuk@gmailcom>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef struct cell Cell;
+
+struct cell {
+ char value;
+ Cell *next;
+ Cell *prev;
+};
+
+Cell *
+alloccell(void)
+{
+ Cell *c;
+
+ c = malloc(sizeof(Cell));
+ assert(c);
+
+ c->value = 0;
+ c->next = NULL;
+ c->prev = NULL;
+
+ return c;
+}
+
+int
+main(int argc, char **argv)
+{
+ FILE *fd;
+ Cell *data, *prog, **progp, *p;
+ int ch;
+
+ if (argc != 2)
+ return -1;
+
+ fd = fopen(argv[1], "r");
+ assert(fd);
+
+ prog = NULL;
+ progp = &prog;
+ p = NULL;
+
+ while ((ch = fgetc(fd)) != EOF) {
+ *progp = alloccell();
+ (*progp)->value = ch;
+ (*progp)->prev = p;
+ p = *progp;
+ progp = &(*progp)->next;
+ }
+
+ fclose(fd);
+
+ data = alloccell();
+
+ for (p = prog; p; p = p->next)
+ switch (p->value) {
+ case '>':
+ if (!data->next) {
+ data->next = alloccell();
+ data->next->prev = data;
+ }
+ data = data->next;
+ break;
+ case '<':
+ if (!data->prev) {
+ data->prev = alloccell();
+ data->prev->next = data;
+ }
+ data = data->prev;
+ break;
+ case '+':
+ ++data->value;
+ break;
+ case '-':
+ --data->value;
+ break;
+ case '.':
+ fputc(data->value, stdout);
+ fflush(stdout);
+ break;
+ case ',':
+ data->value = fgetc(stdin);
+ break;
+ case '[':
+ if (data->value == 0)
+ while (p && p->value != ']')
+ p = p->next;
+ break;
+ case ']':
+ if (data->value != 0)
+ while (p && p->value != '[')
+ p = p->prev;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
diff --git a/hw.bf b/hw.bf
new file mode 100644
index 0000000..76e0dc1
--- /dev/null
+++ b/hw.bf
@@ -0,0 +1,17 @@
+++++++++++ initializes cell zero to 10
+[
+ >+++++++>++++++++++>+++>+<<<<-
+] this loop sets the next four cells to 70/100/30/10
+>++. print 'H'
+>+. print 'e'
++++++++. 'l'
+. 'l'
++++. 'o'
+>++. space
+<<+++++++++++++++. 'W'
+>. 'o'
++++. 'r'
+------. 'l'
+--------. 'd'
+>+. '!'
+>. newline