Wrote a simple brainfuck interpreter that supports nested subroutines ([ ] commands).
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#define MIN_MEMORY_SIZE 30000
typedef struct
{
uint8_t *memory;
size_t pointer;
} BrainfuckState;
static void init(BrainfuckState *bf, size_t size)
{
assert(size <= MIN_MEMORY_SIZE);
bf->memory = calloc(size, 1);
assert(!(bf == NULL));
bf->pointer = 0;
}
static void deinit(BrainfuckState *bf)
{
free(bf->memory);
bf->pointer = 0;
}
static void interpret(BrainfuckState *bf, const char* source, size_t sourceSize)
{
size_t unmatchedBracketCount = 0;
for (size_t i = 0; i < sourceSize; i++)
{
switch (source[i])
{
case '.':
printf("%c", bf->memory[bf->pointer]);
break;
case ',':
scanf("%c", &(bf->memory[bf->pointer]));
break;
case '+':
bf->memory[bf->pointer]++;
break;
case '-':
bf->memory[bf->pointer]--;
break;
case '>':
bf->pointer++;
break;
case '<':
bf->pointer--;
break;
case '[':
if (bf->memory[bf->pointer] == 0)
{
unmatchedBracketCount++;
while (source[i] != ']' || unmatchedBracketCount)
{
i++;
if (source[i] == '[')
unmatchedBracketCount++;
else if (source[i] == ']')
unmatchedBracketCount--;
}
}
break;
case ']':
if (bf->memory[bf->pointer])
{
unmatchedBracketCount++;
while (source[i] != '[' || unmatchedBracketCount)
{
i--;
if (source[i] == ']')
unmatchedBracketCount++;
else if (source[i] == '[')
unmatchedBracketCount--;
}
}
break;
}
}
}
int main(int argc, char** argv)
{
if (argc < 2)
fprintf(stderr, "Pass a filename as a command line arguement.\n");
else
{
FILE *fp = fopen(argv[1], "r");
assert(fp);
fseek(fp, 0, SEEK_END);
size_t sourceSize = ftell(fp);
char *source = malloc(sourceSize);
rewind(fp);
for (size_t i = 0; i < sourceSize; i++)
source[i] = fgetc(fp);
fclose(fp);
BrainfuckState bf;
init(&bf, MIN_MEMORY_SIZE);
interpret(&bf, source, sourceSize);
deinit(&bf);
free(source);
}
return EXIT_SUCCESS;
}
My goal was to keep it as simple and short as possible.I have yet to implement some sort of error handling for unmatched brackets in the source but can't figure out how.