Skip to content

Instantly share code, notes, and snippets.

@y2q-actionman
Created May 22, 2018 06:06
Show Gist options
  • Save y2q-actionman/249b97af13b3c97e7230f5dad7fe31fc to your computer and use it in GitHub Desktop.
Save y2q-actionman/249b97af13b3c97e7230f5dad7fe31fc to your computer and use it in GitHub Desktop.
brainfuck simple impl in C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static char* instruction = NULL;
static size_t instruction_size = 0;
#define DEFAULT_DATA_SIZE 30000
static char data[DEFAULT_DATA_SIZE];
int load_instruction_from_stream(FILE* file) {
size_t iread = 0;
char buffer[1024];
while (1) {
size_t len = fread(buffer, sizeof(buffer[0]), sizeof(buffer) / sizeof(buffer[0]),
file);
if (len == 0) { // EOF or error
break;
}
instruction_size += len;
instruction = realloc(instruction, instruction_size);
if(!instruction) {
fprintf(stderr, "memory exhausted on ip.\n");
abort();
}
memcpy(instruction + iread, buffer, len);
iread += len;
}
return (ferror(file)) ? -1 : 0;
}
int load_instruction_from_path(const char* filename) {
FILE* file = fopen(filename, "r");
int ret = load_instruction_from_stream(file);
fclose(file);
return ret;
}
int do_eval(void) {
// TODO: Range check for 'ip' 'dp'.
size_t ip = 0;
char* dp = &data[0];
for (ip = 0; ip < instruction_size; ++ip) {
switch (instruction[ip]) {
case '+':
++(*dp);
break;
case '-':
--(*dp);
break;
case '>':
++dp;
break;
case '<':
--dp;
break;
case '.':
putchar(*dp);
break;
case ',': {
int c = getchar();
if (c == EOF) {
return EOF;
}
*dp = (char)c;
}
break;
case '[':
if (*dp == 0) {
int nest_level = 1;
do {
++ip;
if (ip > instruction_size) {
fprintf(stderr, "Instruction pointer overrun\n");
abort();
}
switch (instruction[ip]) {
case '[':
++nest_level;
break;
case ']':
--nest_level;
break;
}
} while (nest_level > 0);
}
break;
case ']':
if (*dp != 0) {
int nest_level = 1;
do {
if (ip == 0) {
fprintf(stderr, "Instruction pointer underrun\n");
abort();
}
--ip;
switch (instruction[ip]) {
case ']':
++nest_level;
break;
case '[':
--nest_level;
break;
}
} while (nest_level > 0);
}
break;
default:
// nop
break;
}
}
return 0;
}
int main(int argc, char* argv[]) {
if (argc < 2) {
fprintf(stderr, "please specify a file.\n");
exit(EXIT_FAILURE);
}
load_instruction_from_path(argv[1]);
do_eval();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment