[C]Brainfuck Interpreter 09-13-2013, 06:09 PM
#1
Since i'm making the Brainfuck tutorial, i decided to make an interpreter for it:Smile:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MEMORY_SIZE 30000
int files = 0;
char ** filelist = 0;
FILE * file = 0;
char * program = 0;
char memory[MEMORY_SIZE];
void print_guide(char * runname);
int file_is_alive(char * name);
void add_file_tolist(char * name);
int decent_character(char character);
int load_program(char * name);
int check_syntax(char * name);
void run_program(char * name);
void endfunction();
int main(int number_of_arguments, char **arguments)
{
int i;
atexit(endfunction);
if (number_of_arguments < 2) {
print_guide(arguments[0]);
return EXIT_FAILURE;
}
for (i = 1; i < number_of_arguments; ++i) {
if (file_is_alive(arguments[i])) {
add_file_tolist(arguments[i]);
}
else {
printf("Error! File %s was not found or it's unable to open!\n", arguments[i]);
print_guide(arguments[0]);
return EXIT_FAILURE;
}
}
for (i = 0; i < files; ++i) {
if (load_program(filelist[i])
&& check_syntax(filelist[i])) {
run_program(filelist[i]);
}
}
return EXIT_SUCCESS;
}
void print_guide(char * runname)
{
printf("Brainfuck-compiler 0.1\nAction: %s files\n", runname);
}
int file_is_alive(char * name)
{
file = fopen(name, "r");
if (!file) {
return 0;
}
fclose(file);
return 1;
}
void add_file_tolist(char * name)
{
/* Expand the list */
++files;
filelist = (char**)realloc(filelist, files * sizeof(char*));
if (!filelist) {
printf("Program ran out of memory when creating the file list!\n");
exit(EXIT_FAILURE);
}
/* Allocate memory and put the file name into there */
filelist[files - 1] = (char*) malloc(strlen(name) + 1);
if (!filelist[files - 1]) {
printf("Program ran out of memory when creating the file list!\n");
exit(EXIT_FAILURE);
}
strcpy(filelist[files - 1], name);
}
int decent_character(char character)
{
if (character == '<') return 1;
if (character == '>') return 1;
if (character == '+') return 1;
if (character == '-') return 1;
if (character == '.') return 1;
if (character == ',') return 1;
if (character == '[') return 1;
if (character == ']') return 1;
return 0;
}
int load_program(char * name)
{
size_t size;
int i, j;
file = fopen(name, "r");
if (!file) {
printf("Error! File '%s' couldn't be opened!\n", name);
exit(EXIT_FAILURE);
}
/* Measure the file */
fseek(file, 0, SEEK_END);
size = ftell(file);
fseek(file, 0, SEEK_SET);
/* Release the old code and allocate new */
if (program) {
free(program);
}
program = (char*)malloc(size + 1);
if (!program) {
printf("Error! For the program in the file '%s' was not derived memory.", name);
exit(EXIT_FAILURE);
}
/* Read the whole file */
if (fread(program, size, 1, file) != 1) {
printf("Error! File '%s' couldn't be opened!\n", name);
exit(EXIT_FAILURE);
}
program[size] = 0;
/* Delete characters which are not part of the program */
for (i = j = 0; program[i] != 0; ++i) {
if (decent_character(program[i])) {
program[j] = program[i];
++j;
}
}
program[j] = 0;
return 1;
}
int check_syntax(char * name)
{
int i, brackets;
if (!program) {
return 0;
}
/* Count that there are enough brackets for both ways */
for (i = brackets = 0; program[i] != 0; ++i) {
if (program[i] == '[') {
++brackets;
}
else if (program[i] == ']') {
--brackets;
}
}
if (brackets != 0) {
printf("There is error in the syntax of the file '%s'!\n", name);
}
return brackets == 0;
}
void run_program(char * name)
{
int position = 0, brackets;
char *pointer = memory;
if (!program) {
return;
}
printf("Run '%s'\n", name);
/* Reset the memory */
memset(memory, 0, MEMORY_SIZE);
/* In the end of the text, there is 'zeromark', repeat until that */
while (program[position] != 0) {
switch (program[position]) {
case '>':
++pointer;
break;
case '<':
--pointer;
break;
case '+':
++*pointer;
break;
case '-':
--*pointer;
break;
case '.':
putchar(*pointer);
fflush(stdout);
break;
case ',':
*pointer = getchar();
break;
case '[':
if (*pointer == 0) {
/* Get equivalent closing bracket */
brackets = 1;
while (brackets) {
++position;
if (program[position] == '[') {
++brackets;
}
else if (program[position] == ']') {
--brackets;
}
}
}
break;
case ']':
if (*pointer != 0) {
/* Get equilevant starting bracket */
brackets = 1;
while (brackets) {
--position;
if (program[position] == ']') {
++brackets;
}
else if (program[position] == '[') {
--brackets;
}
}
}
break;
}
/* To the next character in the code */
++position;
}
printf("\nThe end.\n");
}
void endfunction()
{
int i;
if (filelist) {
for (i = 0; i < files; ++i) {
if (filelist[i]) {
free(filelist[i]);
}
}
free(filelist);
}
if (program) {
free(program);
}
if (file) {
fclose(file);
}
}
![[+]](https://sinister.ly/images/modern/collapse_collapsed.png)