Last active
May 25, 2021 08:26
-
-
Save smvd/0da12353c63b2cb3f68de08368103714 to your computer and use it in GitHub Desktop.
A brainfuck implementation
This file contains 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
/* | |
> : Move the pointer forward 1 slot | |
< : Move the pointer back 1 slot | |
+ : Add 1 to the current memory slot | |
- : Subtract 1 from the current memory slot | |
. : Print the ASCII character in the current memory slot | |
? : Print the number stored in the current memory slot | |
, : Save the ASCII character taken from the keyboard in the current memory slot | |
[ : Test if the current slot is not 0, otherwise enter the loop | |
] : Test if the current slot is 0, otherwise exit the loop | |
~ : End the program | |
*/ | |
/* | |
Github: https://gist.github.com/smvd/0da12353c63b2cb3f68de08368103714 | |
Licens: www.unlicense.org | |
Youtube: www.rebrand.ly/eclips-coding | |
Build command: gcc main.c -o ECBF.exe -Wall -Werror -W -s | |
*/ | |
#include <stdio.h> // IO header (STANDARD) | |
#include <string.h> // String header (STANDARD) | |
#include <stdlib.h> | |
#include <conio.h> // Special IO header (MINGW) | |
#define MEM_SIZE 30000 // Set the memory size to 30000 (the official specification) | |
#define CODE_SIZE 10000 // Set the code size to 10000 (just what i found complete overkill) | |
#define TRUE 1 // Set true to 1 (wich c handles as true) | |
#define FALSE 0 // Set false to 0 (wich c handles as false) | |
int mem[3000] = {0}; // Make the memory as all 0 | |
int *ptr = &mem[0]; // Make a reference to the memorys first slot | |
char code[CODE_SIZE]; // Make the code storage | |
char *c = &code[0]; // Make a reference to the code | |
char *lastBracket = &code[0]; // Make a reference to the code to hold the location of the last occurance of [ | |
char *temp = &code[0]; // Make a reference to the code to be used for temporary pointing | |
void ExecuteCode() // Function to run the loaded code | |
{ | |
while (TRUE) // Loop untill told to stop | |
{ | |
if (*c == '\0') // End of code | |
{ | |
break; // Leave loop | |
} | |
if (*c == '~') // Exit character | |
{ | |
break; // Leave loop | |
} | |
if (*c == '#') // Debug character | |
{ | |
printf("<DEBUG>\n"); | |
for (int i = 0; i < MEM_SIZE; i++) // Loop over each slot in memory | |
{ | |
if (mem[i] != 0) | |
{ | |
printf(" [ %d : %d ]\n", i, mem[i]); | |
} | |
} | |
printf("</DEBUG>\n"); | |
} | |
if (*c == '>') // Forwards character | |
{ | |
ptr++; // Shift the pointer forward 1 slot | |
} | |
if (*c == '<') // Backwards character | |
{ | |
ptr--; // Shift the pointer back 1 slot | |
} | |
if (*c == '+') // Addition character | |
{ | |
++*ptr; | |
if (*ptr == 256) | |
{ | |
*ptr = 0; | |
} | |
} | |
if (*c == '-') // Subtraction character | |
{ | |
--*ptr; | |
if (*ptr == -1) | |
{ | |
*ptr = 255; | |
} | |
} | |
if (*c == '.') // Print character | |
{ | |
putchar(*ptr); // Treat the int as raw ASCII and throw it at the screen | |
} | |
if (*c == '?') // Print number | |
{ | |
printf("%d", *ptr); | |
} | |
if (*c == ',') // Read character | |
{ | |
*ptr = getch(); // This is not here to stay as its using a old MS-DOS header | |
} | |
if (*c == '[') // Start loop | |
{ | |
if (*ptr == 0) | |
{ | |
temp = c +1; // Copy the next characters reference to temp | |
int brackets = 0; // Make a variable to hold the layers of depth | |
while (TRUE) // Loop untill broken | |
{ | |
if (*temp == '[') // If the character is [ | |
{ | |
brackets++; | |
} | |
if (*temp == ']' && brackets == 0) // If the character is ] and we have 0 layers of depth | |
{ | |
c = temp +1; // Copy the location of temp to be the main location | |
break; // Leave the loop | |
} | |
if (*temp == ']') // If the character is ] | |
{ | |
brackets--; | |
} | |
temp++; // Move the temp pointer forward | |
} | |
} | |
lastBracket = c; // Store the location of the last bracket | |
} | |
if (*c == ']') // End loop | |
{ | |
if (*ptr != 0) // If the current slot isnt 0 | |
{ | |
c = lastBracket; // Jump to the last bracket | |
} | |
} | |
c++; // Move the code pointer forward | |
} | |
} | |
void ImportCode(char file[]) // Function to read the code from a given file | |
{ | |
FILE *fp; // Reference to the file | |
char ch; // The currently read character | |
int i = CODE_SIZE; // The maximum ammount of code to read | |
fp = fopen(file, "r"); // Read the file | |
if (fp == NULL) // If the read failed | |
{ | |
printf("%s does not exist.\n", file); | |
exit(1); // Exit the program with an error code | |
} | |
while ((ch = fgetc(fp)) != EOF) // Loop over each character untill the end of the file | |
{ | |
if (i == 0) // If we are going to have a buffer overflow (why its important: https://www.youtube.com/watch?v=1S0aBV-Waeo ) | |
{ | |
printf("%s is too large.\n", file); | |
exit(1); // Exit the program with an error code | |
} | |
if(strchr("><+-.?,~[]#", ch)) // If its a valid character | |
{ | |
code[strlen(code)] = ch; // Add the character to the code | |
code[strlen(code)] = '\0'; // Add the end of string character | |
i++; // Add 1 to the buffer overflow test variable | |
} | |
} | |
printf("%s\n", code); // Write the code out | |
fclose(fp); // Untie the file pointer (why its important: https://www.youtube.com/watch?v=6SA6S9Ca5-U ) | |
} | |
int main(int argc, char ** argv) // Main entry point | |
{ | |
if (argc != 2) // If there are too little arguments | |
{ | |
printf("Invalid arguments.\n"); | |
exit(1); // Exit with an error code | |
} | |
ImportCode(argv[1]); // Read the file | |
ExecuteCode(); // Execute the code | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment