Implemented a brainfuck object which holds all variables

This commit is contained in:
id101010
2016-11-14 03:00:38 +01:00
parent fc24af9195
commit 58fd208ef9
2 changed files with 87 additions and 61 deletions

View File

@@ -7,7 +7,7 @@ HFILES=$(shell find . -name '*.h')
STYLE=astyle --style=1tbs STYLE=astyle --style=1tbs
RUN=valgrind --leak-check=full RUN=valgrind --leak-check=full
DEBUG=gdb --args DEBUG=gdb --args
ARGS="examples/rot13.bf" ARGS="examples/pi.bf"
all: build all: build

146
bfckr.c
View File

@@ -12,21 +12,46 @@
#include<errno.h> #include<errno.h>
#include<assert.h> #include<assert.h>
#include<ctype.h> #include<ctype.h>
#include<stdbool.h>
// Amount of memory on the band tape // Defines
#define MEMORY_SIZE 10000 #define MEMORY_SIZE 10000
#define MAX_INPUT_SIZE 10000 #define MAX_INPUT_SIZE 10000
#define clear() printf("\033[H\033[J") #define clear() printf("\033[H\033[J")
// Memory initialized with zeros and its pointer // Struct which holds the brainfuck code, the bandtape and some helpervariables
char memory[MEMORY_SIZE] = {0}; typedef struct bf_code_s {
char *p = memory; char memory[MEMORY_SIZE]; // Memory initialized
int memcnt = 0; size_t mp; // Memory pointer
char code[MAX_INPUT_SIZE]; // Input buffer for the bf code
size_t ip; // Instruction pointer
bool debug; // debug flag
} bf_code_t;
// Prototypes // Prototypes
void bfuck_parser(char *input); void bfuck_parser(bf_code_t *bf);
void bfuck_debugger(bf_code_t *bf);
void print_sourceviewer(bf_code_t *bf);
void print_memoryviewer(bf_code_t *bf);
void init_bf_object(bf_code_t *bf);
// Error handler /* initialize bf object */
void init_bf_object(bf_code_t *bf)
{
bf->mp = 0; // set data pointer to zero
bf->ip = 0; // set instruction pointer to zero
bf->debug = false; // reset the debug flag
for(size_t i = 0; i < MEMORY_SIZE; i++) {
bf->memory[i] = 0;
}
for(size_t i = 0; i < MAX_INPUT_SIZE; i++) {
bf->code[i] = 0;
}
}
/* Error handler */
void die(const char *message) void die(const char *message)
{ {
if(errno) { if(errno) {
@@ -38,40 +63,40 @@ void die(const char *message)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
// Prints the bf source at the current location /* Prints the bf source at the current location */
void print_sourceviewer() void print_sourceviewer(bf_code_t *bf)
{ {
printf("Source viewer:" printf("\nSource viewer: \n"
"-----------------------------------------------------------" "-----------------------------------------------------------\n"
"_____________________________>+++++++++++++++[<+>>>>>>>>+++" "_____________________________>+++++++++++++++[<+>>>>>>>>+++\n"
" ^ " " ^ \n"
" ip=0 " " ip=0 \n"
"-----------------------------------------------------------"); // just to get the idea ... "-----------------------------------------------------------\n"); // just to get the idea ...
} }
// Prints memory information at the current memory location /* Prints memory information at the current memory location */
void print_memoryviewer() void print_memoryviewer(bf_code_t *bf)
{ {
int pointerlocation = (p - memory)*sizeof(*memory); // find the arrayindex at which the pointer is pointing // int pointerlocation = (p - memory)*sizeof(*memory); // find the arrayindex at which the pointer is pointing
printf("Memory viewer: " printf("\nMemory viewer: \n"
"-----------------------------------------------------------" "-----------------------------------------------------------\n"
"000 000 000 000 000 000 001 001 000 000 000 000 000 000 000" "000 000 000 000 000 000 001 001 000 000 000 000 000 000 000\n"
" ^ " " ^ \n"
" mp=1 " " mp=1 \n"
"249 250 251 252 253 254 000 001 002 003 004 005 006 007 008" "249 250 251 252 253 254 000 001 002 003 004 005 006 007 008\n"
"-----------------------------------------------------------"); // just to get the idea ... "-----------------------------------------------------------\n"); // just to get the idea ...
} }
// Pauses the program flow and prints information /* Pauses the program flow and prints information */
void bfuck_debugger(char *bf_source_input, int instructionpointer) void bfuck_debugger(bf_code_t *bf) //char *bf_source_input, int instructionpointer)
{ {
clear(); // clear terminal clear(); // clear terminal
printf("[s]: single step [c]: continue"); printf("[s]: single step [c]: continue\n");
print_sourceviewer(); print_sourceviewer(bf);
print_memoryviewer(); print_memoryviewer(bf);
switch(getchar()) { switch(getchar()) {
case 's': case 's':
@@ -79,64 +104,61 @@ void bfuck_debugger(char *bf_source_input, int instructionpointer)
break; break;
case 'c': case 'c':
// continue // continue
bf->debug = false;
break; break;
} }
} }
// Parses and executes a brainfuck expression /* Parses and executes a brainfuck expression */
void bfuck_execute(char *input) void bfuck_execute(bf_code_t *bf)
{ {
int loop = 0; int loop = 0;
for(size_t i = 0; input[i] != 0; i++) { // where i is the instruction pointer for(size_t i = bf->ip; bf->code[i] != 0; bf->ip=i++) { // where i is the instruction pointer
switch(input[i]) { switch(bf->code[i]) {
case '>': case '>':
if(memcnt >= MEMORY_SIZE) { // prevent overrun if(bf->mp >= MEMORY_SIZE) { // prevent overrun
p = &memory[0]; bf->mp = 0;
memcnt = 0;
} else { } else {
++p; // increment data pointer ++(bf->mp); // increment memory pointer
++memcnt;
} }
break; break;
case '<': case '<':
if(memcnt < 0) { // prevent underun if(bf->mp < 0) { // prevent underun
p = &memory[MEMORY_SIZE - 1]; bf->mp = MEMORY_SIZE-1;
memcnt = MEMORY_SIZE - 1;
} else { } else {
--p; // decrement data pointer --(bf->mp); // decrement memory pointer
--memcnt;
} }
break; break;
case '+': case '+':
++(*p); // increment byte at data pointer ++(bf->memory[bf->mp]); // increment byte at memory pointer
break; break;
case '-': case '-':
--(*p); // decrement byte at data pointer --(bf->memory[bf->mp]); // decrement byte at memory pointer
break; break;
case '.': case '.':
putchar(*p); // output the byte at data pointer putchar(bf->memory[bf->mp]); // output the byte at memory pointer
break; break;
case ',': case ',':
*p = getchar(); // accept one byte of input and store it at data pointer bf->memory[bf->mp] = getchar(); // accept one byte of input and store it at memory pointer
break; break;
case '[': case '[':
if(*p == 0) { // if the byte at the data pointer is zero if(bf->memory[bf->mp] == 0) { // if the byte at the memory pointer is zero
// jump forward to the command after the next ] // jump forward to the command after the next ]
loop = 1; loop = 1;
while(loop > 0) { // count nested loops and make sure to get the matching ] while(loop > 0) { // count nested loops and make sure to get the matching ]
i++; bf->ip = i++;
if(input[i] == '[') { if(bf->code[i] == '[') {
loop++; loop++;
} }
if(input[i] == ']') { if(bf->code[i] == ']') {
loop--; loop--;
} }
} }
@@ -146,15 +168,15 @@ void bfuck_execute(char *input)
break; break;
case ']': case ']':
if(*p != 0) { // if the byte at the data pointer is nonzero if(bf->memory[bf->mp] != 0) { // if the byte at the memory pointer is nonzero
// jump back to the command after the matching [ // jump back to the command after the matching [
loop = 1; loop = 1;
while(loop > 0) { // count nested loops and make sure to get the matching [ while(loop > 0) { // count nested loops and make sure to get the matching [
i--; bf->ip = i--;
if(input[i] == '[') { if(bf->code[i] == '[') {
loop--; loop--;
} }
if(input[i] == ']') { if(bf->code[i] == ']') {
loop++; loop++;
} }
} }
@@ -166,6 +188,7 @@ void bfuck_execute(char *input)
case '#': case '#':
// Breakpoint reached, start debugger ... // Breakpoint reached, start debugger ...
bf->debug = true;
break; break;
default: default:
@@ -180,13 +203,16 @@ int main(int argc, char* argv[])
FILE *fp; FILE *fp;
int i = 0; int i = 0;
int c; int c;
char input[MAX_INPUT_SIZE]; bf_code_t bf;
// check arguments // check arguments
if(argc < 2) { if(argc < 2) {
die("Need more arguments."); die("Need more arguments.");
} }
// initialize bf object
init_bf_object(&bf);
// try to open file // try to open file
if((fp = fopen(argv[1], "rt")) == NULL) { if((fp = fopen(argv[1], "rt")) == NULL) {
die("Couldn't open file."); die("Couldn't open file.");
@@ -194,14 +220,14 @@ int main(int argc, char* argv[])
// read the file and store it in the input buffer // read the file and store it in the input buffer
while((c = getc(fp)) != EOF) { while((c = getc(fp)) != EOF) {
input[i++] = c; bf.code[i++] = c;
} }
// close file after reading // close file after reading
fclose(fp); fclose(fp);
// try to interpret it // try to interpret it
bfuck_execute(input); bfuck_execute(&bf);
// exit // exit
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);