Created
August 7, 2022 16:50
-
-
Save zeaga/134a94de614f83e9d829754cb27c868a to your computer and use it in GitHub Desktop.
Simple brainfuck compiler in less than 100 lines of C
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
#include <stdio.h> | |
#include <stdlib.h> | |
char* read_file( char* file_name ) { | |
FILE* file = fopen( file_name, "r" ); | |
if ( file == NULL ) { | |
printf( "Could not open input file `%s`.\n", file_name ); | |
exit( 1 ); | |
} | |
// Get file size | |
fseek( file, 0, SEEK_END ); | |
long file_size = ftell( file ); | |
fseek( file, 0, SEEK_SET ); | |
// Allocate memory for file data | |
char* code = malloc( file_size ); | |
// Read file data | |
int c; | |
size_t n = 0; | |
while ( ( c = fgetc( file ) ) != EOF ) { | |
code[n++] = (char)c; | |
} | |
// Terminate c-string with null character | |
code[n] = '\0'; | |
return code; | |
} | |
void generate_output( char* code, char* output_path ) { | |
FILE* file = fopen( output_path, "w" ); | |
if ( file == NULL ) { | |
printf( "Could not open output file `%s`.\n", output_path ); | |
exit( 1 ); | |
} | |
// Write header with defines to slim down final file size | |
fprintf( file, | |
"#include <stdio.h>\n" | |
"#include <stdlib.h>\n" | |
"#define A ++p\n" | |
"#define B --p\n" | |
"#define C ++*p\n" | |
"#define D --*p\n" | |
"#define E putchar(*p)\n" | |
"#define F *p=getchar()\n" | |
"#define G while(*p)\n" | |
"int main(){char*p=malloc(1024*sizeof(char));" ); | |
// Write code to file | |
for ( char c = *code; c != '\0'; c = *++code ) { | |
switch ( c ) { | |
case '>': | |
fprintf( file, "A;" ); | |
break; | |
case '<': | |
fprintf( file, "B;" ); | |
break; | |
case '+': | |
fprintf( file, "C;" ); | |
break; | |
case '-': | |
fprintf( file, "D;" ); | |
break; | |
case '.': | |
fprintf( file, "E;" ); | |
break; | |
case ',': | |
fprintf( file, "F;" ); | |
break; | |
case '[': | |
fprintf( file, "G{" ); | |
break; | |
case ']': | |
fprintf( file, "}" ); | |
break; | |
default: | |
break; | |
} | |
} | |
// Write footer and close | |
fprintf( file, "return 0;}" ); | |
fclose( file ); | |
} | |
int main( int argc, char* argv[] ) { | |
if ( argc < 2 ) { | |
printf( "Usage: %s <input_file> [output_file]\n", argv[0] ); | |
exit( 1 ); | |
} | |
char* code = read_file( argv[1] ); | |
// Write output to output.c (unless a second argument is given) | |
generate_output( code, argc >= 3 ? argv[2] : "output.c" ); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment