Skip to content

Instantly share code, notes, and snippets.

@exallium
Created February 24, 2014 05:23
Show Gist options
  • Select an option

  • Save exallium/9182376 to your computer and use it in GitHub Desktop.

Select an option

Save exallium/9182376 to your computer and use it in GitHub Desktop.
BF Interpreter in C... Because I can. And I was a bit bored.
/**
* usage: ./bf "<program>"
* example: ./bf ",[>++<-]>. ; multiplies a number by 2"
*
* Brainfuck Interpreter
*
* BF has the following commands:
* > Move to next memory position
* < Move to prev memory position
* + Increment current memory position
* - Decrement current memory position
* [ Begin loop frame
* ] End loop frame
* , Read value from stdin
* . Print value to stdout
*
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define D_SEG_SIZE 64
#define INC(a, b) (a + 1 < b ? a + 1 : b)
#define DEC(a) (a > 0 ? a - 1 : a)
typedef struct _STACK {
struct _STACK *next;
unsigned int start;
} Stack;
typedef struct _VM {
unsigned int ip; // Instruction pointer
char *is; // Instruction segment
unsigned int is_len; // Instruction segment length
unsigned int dp; // Data pointer
unsigned int ds[D_SEG_SIZE]; // Data Segment
Stack *frames; // Loop frames
} State;
void push_frame(State *state) {
#ifdef DEBUG
printf("pushstack(%d)\n", state->ip);
#endif
Stack *stack = (Stack *) malloc(sizeof(Stack));
stack->next = state->frames;
stack->start = state->ip;
state->frames = stack;
}
void pop_frame(State *state) {
#ifdef DEBUG
printf("popstack(%d)\n", state->ip);
#endif
Stack *stack = state->frames;
state->frames = state->frames->next;
free(stack);
}
int perform_action(State *state) {
switch (state->is[state->ip]) {
case '>': // Move to position right
state->dp = INC(state->dp, D_SEG_SIZE - 1);
break;
case '<': // Move to position left
state->dp = DEC(state->dp);
break;
case '+': // Increment current position
state->ds[state->dp]++;
break;
case '-': // Decrement current position
state->ds[state->dp] = DEC(state->ds[state->dp]);
break;
case '[': // Begin loop frame
if (state->frames == NULL || state->frames->start != state->dp)
push_frame(state);
break;
case ']': // End loop frame
if (state->ds[state->dp] == 0)
pop_frame(state);
else {
state->ip = state->frames->start;
}
break;
case ',': // Read value from stdin
scanf("%d", (state->ds + state->dp));
break;
case '.': // Print current location to screen
printf("%d", *(state->ds + state->dp));
break;
default: // Ignore anything else
break;
}
#ifdef DEBUG
printf("BF LOG :: ip(%d) dp(%d) :: is(%c) ds(%d) \n", state->ip, state->dp, state->is[state->ip], state->ds[state->dp]);
#endif
state->ip++;
return state->ip < state->is_len;
}
int main(int argc, char **argv) {
State state;
memset(&state, 0, sizeof(state));
state.is = argv[1];
state.is_len = strlen(argv[1]);
while(perform_action(&state)) ;
while(state.frames != NULL) { pop_frame(&state); }
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment