Brain Fuck - C
Earlier this year I was playing around with making simple programming languages and came across "BrainFuck". I, being bored decided to write my own BrainFuck Interpreter and of course made a few changes along the way (only in I/O functions, added integer support since BrainFuck only deals with characters). If interested, I recommend reading more information about BrainFuck on Wikipedia.
The Full download including Source and examples can be found on GitHub.
Here are the basic rules of BrainFuck with some added I/O Functions.
brainfuck command | C equivalent |
---|---|
> | ++CP; |
< | --CP; |
+ | ++*CP; |
- | --*CP; |
[ | while (*CP) { |
] | } |
. | printf("%c",(char)*CP) |
: | printf("%u",*CP); |
, | while (scanf("%c", CP) != 1); |
; | while (scanf("%u", CP) != 1); |
M | Print out Cell and Pointers |
I | Print out Instruction Pointer |
CP is the Cell Pointer
Below are various scripts written in BrainFuck
Hello World
+++++ +++++
[
> +++++ ++
> +++++ +++++
> +++
> +
<<<< -
]
> ++ .
> + .
+++++ ++ .
.
+++ .
> ++ .
<< +++++ +++++ +++++ .
> .
+++ .
----- - .
----- --- .
> + .
> .
M
Hello World Version 2
+++++
[
> +++++ +++++ +++
< -
]
+++++ +++++
[
>> +++++ ++++
<< -
]
>> +++++ ++
< +++++ ++ . ----- --
> ++++ . +++++ ++ .. +++ . ----- ----- ----
<< +++
[
>>> +++++ +++++
<<< -
]
>>> ++ .
<< +++++ +++++ +++++ +++++ ++ . ----- ----- ----- ----- --
> +++++ +++++ ++++ . +++ . ------ . -------- . ---
> + .
M
3 Nested While loops
+++
M
[
> +++
[
> +++
[
-
M
]
< -
]
< -
]
M
Below is the source for the BrainFuck Interpreter
#include <stdio.h>
#include <stdlib.h>
#define DEFAULT_IN_FILE "in.bf"
#define DEFAULT_MEMORY_SIZE 8
char inFile[256] = DEFAULT_IN_FILE;
/* function definitions */
void runInstructions();
int loadFile(char inFile[256]);
void printInstructions();
void clearDataBuffer();
void printDataBuffer();
unsigned int* cell; /* cell buffer, all program cell is stored in here */
unsigned int cellSize = 0;
unsigned int IP; // instruction pointer
unsigned char* instructions; /* the Instructions loaded from input file */
unsigned int instructionsSize = 0;
unsigned int* CP = NULL; /* cell Pointer */
int main(int argc, char *argv[]) {
int i;
for(i = 1; i < argc; i++) { /* handle parameters */
if(strcmp(argv[i], "-i") == 0) { /* input file */
if( i + 1 < argc) {
sprintf(inFile, "%s", argv[i + 1]);
} else { /* improper format */
return -1;
}
} else if(strcmp(argv[i], "-size") == 0) { /* size of cell buffer */
if( i + 1 < argc) {
cell = (unsigned int*) malloc( atoi(argv[i + 1]) * sizeof(unsigned int) );
cellSize = atoi(argv[i + 1]);
} else { /* improper format */
return -1;
}
}
}
if(cellSize == 0) {
cell = (unsigned int*) malloc( DEFAULT_MEMORY_SIZE * sizeof(unsigned int) );
cellSize = DEFAULT_MEMORY_SIZE;
}
CP = cell;
loadFile(inFile);
clearDataBuffer();
runInstructions();
return 0;
}
void runInstructions() {
int i; // used in for loops
int numCloseBrackets = 0;
int numOpenBrackets = 0;
for(IP = 0; IP < instructionsSize; IP++) {
switch(instructions[IP]) {
case '>': /* INC/DEC */
++CP;
break;
case '<':
--CP;
break;
case '+': /* INC/DEC POINTER */
++(*CP);
break;
case '-':
--(*CP);
break;
case '[': /* WHILE LOOP */
if(*CP == 0) { // if CP == 0, then skip to the next matching ']'
numOpenBrackets = 0;
for(i = IP + 1; i < instructionsSize; i++) {
if(instructions[i] == '[') {
numOpenBrackets++;
} else if(instructions[i] == ']') {
if(numOpenBrackets == 0) {
IP = i;
break;
} else {
numOpenBrackets--;
}
}
}
}
break;
case ']': /* END WHILE*/
if(*CP != 0) { // if CP != 0, loopback to the previous matching'['
numCloseBrackets = 0;
for(i = IP - 1; i >= 0; i--) {
if(instructions[i] == ']') {
numCloseBrackets++;
}else if(instructions[i] == '[') {
if(numCloseBrackets == 0) {
IP = i;
break;
} else {
numCloseBrackets--;
}
}
}
}
break;
case '.': /* OUTPUT */
printf("%c",(char)*CP);
break;
case ':':
printf("%u",*CP);
break;
case ',': /* INPUT */
while (scanf("%c", CP) != 1);
break;
case ';':
while (scanf("%u", CP) != 1);
break;
case 'M': /* print Data Buffer */
printDataBuffer();
break;
case 'I': /* print Instructions as is*/
printInstructions();
break;
default:
/* unknown command, ignore it */
break;
}
}
}
/*
*
*/
int loadFile(char inFile[256]) {
FILE *fp;
fp=fopen(inFile, "r");
if(fp == NULL) {
return -1;
}
fseek(fp, 0, SEEK_END); // seek to end of file
instructionsSize = ftell(fp); // get current file pointer
rewind (fp);
instructions = (char*) malloc( instructionsSize );
int i;
for(i = 0; i < instructionsSize; i++) {
instructions[i] = ' ';
}
if(instructions == NULL) {
return -1;
}
fread (instructions,1,instructionsSize,fp);
fclose(fp);
return 0;
}
void printInstructions() {
int i;
for(i = 0; i < instructionsSize; i++) {
printf("%c", instructions[i]);
}
printf("\n");
}
void clearDataBuffer() {
int i;
for(i = 0; i < cellSize; i++) {
cell[i] = 0;
}
}
void printDataBuffer() {
int i;
printf("\n");
for(i = 0; i < cellSize; i++) {
printf("[%d]=%d", i, cell[i]);
if(CP == &cell[i]) {
printf(" <-- (CP)");
}
printf("\n");
}
printf("\nIP = %d\n", IP);
}