Skip to content

Instantly share code, notes, and snippets.

@owenjones
Last active July 8, 2020 18:11
Show Gist options
  • Save owenjones/cfca0c7b0ad098fdd797cce8c797e42c to your computer and use it in GitHub Desktop.
Save owenjones/cfca0c7b0ad098fdd797cce8c797e42c to your computer and use it in GitHub Desktop.
Brainfuck Interpreter
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define sblock 8 // Stack block length
#define lblock 4 // Loop-stack block length
#define readln 1024 // Length of input buffer
char* reallocate(char* array, int blocks, int blocksize, int loop, int debug) {
// Reallocates the input stack if current length is exceeded
int size = blocks * blocksize;
char* lstr = (loop) ? "loop " : "";
if(debug) printf("[\e[1;105m^\e[0m] Increasing %sstack size (to %i)\n", lstr, size);
char* addr = realloc(array, size);
if(addr != NULL) return addr;
exit(EXIT_FAILURE);
}
void brainfuck(char *inp, int debug) {
char* stack = calloc(sblock, sizeof(char));
int sblocks = 1;
char* sstart = stack;
char** loop = calloc(lblock, sizeof(char *));
int lblocks = 1;
char** lstart = loop;
if(debug) printf("[\e[1;105m^\e[0m] Stack allocated at <%p>\n", sstart);
if(debug) printf("[\e[1;105m^\e[0m] Loop allocated at <%p>\n", lstart);
while(*inp != '\0') {
switch(*inp) {
case '.' : {
if(debug) printf("[\e[1;92m.\e[0m] Echoing character at <%p> (%i) -> ", stack, *stack);
putchar(*stack);
if(debug) printf("\n");
break;
}
case ',' : {
if(debug) printf("[\e[1;92m,\e[0m] Taking Character for <%p>\n", stack);
*stack = getchar();
break;
}
case '>' : {
stack++;
int diff = (stack - sstart);
if(diff > (sblocks * sblock)) {
sstart = reallocate(sstart, ++sblocks, sblock, 0, debug);
stack = (sstart + diff);
}
if(debug) printf("[\e[1;93m>\e[0m] Incrementing pointer <%p>\n", stack);
break;
}
case '<' : {
stack--;
if((stack - sstart) < 0) {
if(debug) printf("[\e[1;41m<\e[0m] Address <%p> out of range\n", stack);
exit(EXIT_FAILURE);
}
if(debug) printf("[\e[1;93m<\e[0m] Decrementing pointer <%p>\n", stack);
break;
}
case '+' : {
*stack = *stack + 1;
if(debug) printf("[\e[1;96m+\e[0m] Incrementing value at <%p> -> %i\n", stack, *stack);
break;
}
case '-' : {
*stack = *stack - 1;
if(debug) printf("[\e[1;96m-\e[0m] Decrementing value at <%p> -> %i\n", stack, *stack);
break;
}
case '[' : {
if(debug) printf("[\e[1;95m[\e[0m] Loop start -> counter <%p> = %i\n", stack, *stack);
loop++;
int diff = (loop - lstart);
if(diff > (lblocks * lblock)) {
*lstart = reallocate(*lstart, ++lblocks, lblock, 1, debug);
loop = (lstart + diff);
}
*loop = inp;
break;
}
case ']' : {
if(debug) printf("[\e[1;95m]\e[0m] Loop end -> ");
if(*stack <= 0) {
if(debug) printf("counter <%p> is zero, continuing with program.\n", stack);
*loop = 0;
loop--;
}
else {
if(debug) printf("counter <%p> is non-zero (%i), looping again.\n", stack, *stack);
inp = *(loop);
}
break;
}
case '\n' : {
// Newlines from STDIN
break;
}
default : {
if(debug) printf("[\e[1;41m?\e[0m] Unknown symbol \"%c\"\n", *inp);
exit(EXIT_FAILURE);
}
}
inp++;
}
free(sstart);
free(lstart);
}
char* rdstdin(char* input, int debug) {
if(debug) printf("[\e[1;41m!\e[0m] Reading from STDIN...\n");
fgets(input, readln, stdin);
return input;
}
int main(int argc, char* argv[]) {
int debug = 0;
char* input = malloc(readln * sizeof(char));
if((argc > 1) && (strncmp(argv[1], "--debug", 7) == 0)) {
debug = 1;
input = (argc > 2) ? strcpy(input, argv[2]) : rdstdin(input, debug);
}
else {
input = (argc > 1) ? strcpy(input, argv[1]) : rdstdin(input, debug);
}
brainfuck(input, debug);
free(input);
exit(EXIT_SUCCESS);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment