summaryrefslogtreecommitdiff
path: root/userspace/brainfuck.c
diff options
context:
space:
mode:
authorMichal Idziorek <m.i@gmx.at>2014-10-20 20:51:01 +0200
committerMichal Idziorek <m.i@gmx.at>2014-10-20 20:51:01 +0200
commit37ceff93572bba6defd916884999c496108220ee (patch)
tree1b40ae0f5e3c2c3cf1bb60c3f1d9f7ae5dd53c1b /userspace/brainfuck.c
parent813272cd88cc6c0a1dfbb121d2130fc849042c8a (diff)
started porting simple brainfuck interpreter
Diffstat (limited to 'userspace/brainfuck.c')
-rw-r--r--userspace/brainfuck.c133
1 files changed, 133 insertions, 0 deletions
diff --git a/userspace/brainfuck.c b/userspace/brainfuck.c
new file mode 100644
index 0000000..03ce4f5
--- /dev/null
+++ b/userspace/brainfuck.c
@@ -0,0 +1,133 @@
+// taken from: http://it-ride.blogspot.com/2009/11/brainfuck-interpreter.html
+
+/* comment
+ * TODO
+ * You have a bug. You don't check for EOF while looking for square brackets.
+ */
+
+/*
+
+ A brainfuck intepreter written in C, complete with error checking so you
+ don't hurt yourself while, uh, brainfucking. Nothing really special about
+ the implementation and it is probably very poor performance-wise.
+
+ Author: Felix Oghină
+ License: (brain)fuck licenses!
+
+*/
+
+// ADDED BY FOOLOS : foolos syscalls!
+#include "syscalls.c"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// by brainfuck standards (doesn't that sound funny?), the data pointer has
+// 30,000 bytes at its disposal, but I hate hard-coding such stuff.
+#define DATA_SIZE 30000
+
+void usage() {
+ puts(
+ "Usage: brainfuck FILE\n"
+ "If FILE is ommited or is '-', standard input is read"
+ );
+}
+
+int main(int argc, char **argv) {
+
+ // ADDED BY FOOLOS: we will show usage anyway
+ usage();
+
+ // used by the bf program
+ unsigned char *dataptr = malloc(sizeof(char) * DATA_SIZE);
+ // position of the data pointer
+ unsigned int datapos = 0;
+ // input file
+ FILE *input;
+ // level - deepness of brackets
+ // i - uh, you need explanation for this one?
+ unsigned int level, i;
+ // we will read chars from the input into r
+ unsigned char r;
+
+ // determine input
+ if (argc == 2) {
+ if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0) {
+ usage();
+ return EXIT_SUCCESS;
+ }
+ else {
+ input = fopen(argv[1], "r");
+ if (input == NULL) {
+ puts("Error opening input file");
+ return EXIT_FAILURE;
+ }
+ }
+ }
+ else {
+ usage();
+ return EXIT_FAILURE;
+ }
+
+ // zero the data pointer
+ for (i=0; i < DATA_SIZE; i++) {
+ dataptr[i] = 0;
+ }
+
+ // start interpreting
+ rewind(input);
+ while (!feof(input)) {
+ r = (unsigned char) fgetc(input);
+ switch(r) {
+ case '>':
+ if (datapos < DATA_SIZE - 1) datapos++;
+ else {
+ puts("brainfuck error: pointer overflow");
+ return EXIT_FAILURE;
+ }
+ break;
+ case '<':
+ if (datapos > 0) datapos--;
+ else {
+ puts("brainfuck error: pointer underflow");
+ return EXIT_FAILURE;
+ }
+ break;
+ case '+':
+ dataptr[datapos]++;
+ break;
+ case '-':
+ dataptr[datapos]--;
+ break;
+ case '.':
+ putchar(dataptr[datapos]);
+ break;
+ case ',':
+ dataptr[datapos] = getchar();
+ break;
+ case '[':
+ if (dataptr[datapos] == 0) {
+ level = 1;
+ while (level != 0) {
+ r = (unsigned char) fgetc(input);
+ if (r == '[') level ++;
+ else if (r == ']') level --;
+ }
+ }
+ break;
+ case ']':
+ if (dataptr[datapos] != 0) {
+ level = 1;
+ while (level != 0) {
+ fseek(input, -2, SEEK_CUR);
+ r = (unsigned char) fgetc(input);
+ if (r == ']') level ++;
+ else if (r == '[') level --;
+ }
+ }
+ break;
+ }
+ }
+ return EXIT_SUCCESS;
+}