-
-
Save y2q-actionman/249b97af13b3c97e7230f5dad7fe31fc to your computer and use it in GitHub Desktop.
brainfuck simple impl in C
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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