Skip to content

Instantly share code, notes, and snippets.

@exallium
Last active December 11, 2015 07:39
Show Gist options
  • Save exallium/4568129 to your computer and use it in GitHub Desktop.
Save exallium/4568129 to your computer and use it in GitHub Desktop.
Simple brainfuck interpreter
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define NUL '\0'
struct Loop {
char *start;
char *end;
struct Loop *next;
};
struct Loop* current_loop = NULL;
void get_loop(char *start) {
struct Loop *n = current_loop;
if (n == NULL || n->start != start) {
current_loop = (struct Loop *) malloc(sizeof(struct Loop));
current_loop->next = n;
current_loop->start = start;
}
}
void set_end(char *end) {
current_loop->end = end;
}
char *goto_start() {
return current_loop->start - 1;
}
char *pop_loop(char* code_seg) {
int counter = 0;
char *end = current_loop->end;
char *ip = current_loop->start;
struct Loop *n = current_loop;
current_loop = current_loop->next;
free(n);
if (end == NULL) {
while (*++ip != ']' || counter != 0) {
if (*ip == '[') counter++;
if (*ip == ']') counter--;
}
return ip;
}
return end;
}
int main(int argc, char **argv) {
FILE *fin = NULL;
char c, code_seg[3000], data_seg[3000], *ip, *dp;
memset(data_seg, 0, 3000);
if (argc < 2) {
printf("bf -- brainfuck interpreter\n");
printf("usage: bf myfile.bf\n");
return 1;
}
fin = fopen(argv[1], "r");
ip = code_seg;
while((c = fgetc(fin)) != EOF)
if (c == '+' || c == '-' || c == '[' || c == ']'
|| c == '.' || c == ',' || c == '<' || c == '>') {
*ip++ = c;
}
fclose(fin);
*ip = NUL;
dp = data_seg;
for(ip = code_seg; *ip != NUL; ip++) {
switch(*ip) {
case '+':
++*dp;
break;
case '-':
--*dp;
break;
case '[':
get_loop(ip);
if (*dp == NUL)
ip = pop_loop(code_seg);
break;
case ']':
set_end(ip);
ip = goto_start();
break;
case '>':
++dp;
break;
case '<':
--dp;
break;
case '.':
putchar(*dp);
break;
case ',':
*dp = getchar();
break;
default:
break;
}
}
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment