From 19110ce03fc8916e503efdccaaf14992eef30259 Mon Sep 17 00:00:00 2001 From: Thomas Schwery Date: Sat, 10 Feb 2024 12:25:09 +0100 Subject: [PATCH] feat: Import project state of 2011-11-13 --- bf_interpreter.c | 96 ++++++++++++++++++++++++ bf_threaded.c | 127 ++++++++++++++++++++++++++++++++ examples/cat.bf | 1 + examples/helloworld.bf | 1 + examples/helloworld_comments.bf | 21 ++++++ examples/uppercase.bf | 1 + 6 files changed, 247 insertions(+) create mode 100644 bf_interpreter.c create mode 100644 bf_threaded.c create mode 100644 examples/cat.bf create mode 100644 examples/helloworld.bf create mode 100644 examples/helloworld_comments.bf create mode 100644 examples/uppercase.bf diff --git a/bf_interpreter.c b/bf_interpreter.c new file mode 100644 index 0000000..d09e62e --- /dev/null +++ b/bf_interpreter.c @@ -0,0 +1,96 @@ +#include +#include +#include + +static unsigned char *data_start; +static unsigned char *data_ptr; + +void process_command(char command, FILE *file) { + + switch(command) { + case '>': + /* increment the data pointer (to point to the next cell to the right). */ + ++data_ptr; + /* TODO : Check if over allocated memory */ + break; + case '<': + /* decrement the data pointer (to point to the next cell to the left). */ + --data_ptr; + /* TODO : Check if under allocated memory */ + break; + case '+': + /* increment (increase by one) the byte at the data pointer. */ + ++*data_ptr; + break; + case '-': + /* decrement (decrease by one) the byte at the data pointer. */ + --*data_ptr; + break; + case '.': + /* output a character, the ASCII value of which being the byte at the + * data pointer. */ + putchar(*data_ptr); + break; + case ',': + /* accept one byte of input, storing its value in the byte at the data + * pointer. */ + *data_ptr = getchar(); + break; + case '[': + /* [ : if the byte at the data pointer is zero, then instead of moving the + * instruction pointer forward to the next command, jump it forward to + * the command after the matching ] command. + * ] : if the byte at the data pointer is nonzero, then instead of moving + * the instruction pointer forward to the next command, jump it back to + * the command after the matching [ command. */ + { + fpos_t position; + fgetpos(file, &position); + while(*data_ptr != 0) { + fsetpos(file, &position); + char c = getc(file); + while( c!= ']' && c != EOF) { + process_command(c, file); + c = getc(file); + } + } + } + break; + case ']': + /* if we encounter one here, it means there are not balanced */ + fprintf(stderr, "Error in the source file, unbalanced ']'\n"); + exit(2); + break; + default: + /* Brainfuck ignores all characters except the eight commands +-<>[],. */ + break; + } + +} + +int main(int argc, char **argv) +{ + data_start = calloc(30000, sizeof(char)); + data_ptr = data_start; + + if (argc > 1) { + char command; + FILE *file = fopen(argv[1], "r"); + + if (!file) { + fprintf(stderr, "Error: No such file %s\n", argv[1]); + return 2; + } + + while((command = getc(file)) != EOF) { + process_command(command, file); + } + + fclose(file); + return 0; + } else { + fprintf(stderr, "Usage: %s source_file\n", argv[0]); + return 1; + } + return 0; +} diff --git a/bf_threaded.c b/bf_threaded.c new file mode 100644 index 0000000..56d7e8c --- /dev/null +++ b/bf_threaded.c @@ -0,0 +1,127 @@ +#include +#include +#include + +static unsigned char *data_start; +static unsigned char *data_ptr; + +#define MEM_SIZE 30000 +#define GOTO_NEXT goto *labels[op_char] + +void engine_run(FILE* file) { + void** labels[127]; /* We will address each char */ + unsigned char op_char = 0; + fpos_t* loop_start_position = calloc(3000,sizeof(fpos_t)); + + for (int i = 0; i <= 127; i++) labels[i] = &&unknown_char; + + labels['>'] = &&ptr_increment; + labels['<'] = &&ptr_decrement; + + labels['+'] = &&value_increment; + labels['-'] = &&value_decrement; + + labels['.'] = &&value_output; + labels[','] = &&value_input; + + labels['['] = &&loop_start; + labels[']'] = &&loop_end; + + op_char = getc(file); + if (op_char > 127) return; + GOTO_NEXT; + +ptr_increment: { + if (data_ptr + 1 > data_start + MEM_SIZE) data_ptr = data_start; + ++data_ptr; + op_char = getc(file); + if (op_char > 127) return; + GOTO_NEXT; +} + +ptr_decrement: { + if (data_ptr - 1 < data_start) data_ptr = data_start + MEM_SIZE; + --data_ptr; + op_char = getc(file); + if (op_char > 127) return; + GOTO_NEXT; +} + +value_increment: { + ++*data_ptr; + op_char = getc(file); + if (op_char > 127) return; + GOTO_NEXT; +} + +value_decrement: { + --*data_ptr; + op_char = getc(file); + if (op_char > 127) return; + GOTO_NEXT; +} + +value_output: { + putchar(*data_ptr); + op_char = getc(file); + if (op_char > 127) return; + GOTO_NEXT; +} + +value_input: { + *data_ptr = getchar(); + op_char = getc(file); + if (op_char > 127) return; + GOTO_NEXT; +} + +loop_start: { + fgetpos(file, loop_start_position); + loop_start_position++; + + op_char = getc(file); + if (op_char > 127) return; + GOTO_NEXT; +} + +loop_end: { + if (*data_ptr != 0) { + fsetpos(file, loop_start_position-1); + } else { + loop_start_position--; + } + + op_char = getc(file); + if (op_char > 127) return; + GOTO_NEXT; +} + +unknown_char: { + op_char = getc(file); + if (op_char > 127) return; + GOTO_NEXT; +} +} + +int main(int argc, char **argv) +{ + data_start = calloc(MEM_SIZE, sizeof(char)); + data_ptr = data_start; + + if (argc <= 1) { + fprintf(stderr, "Usage: %s source_file\n", argv[0]); + return 1; + } + + FILE *file = fopen(argv[1], "r"); + + if (!file) { + fprintf(stderr, "Error: No such file %s\n", argv[1]); + return 2; + } + + engine_run(file); + + fclose(file); + return 0; +} diff --git a/examples/cat.bf b/examples/cat.bf new file mode 100644 index 0000000..05b49e2 --- /dev/null +++ b/examples/cat.bf @@ -0,0 +1 @@ +,[.,] diff --git a/examples/helloworld.bf b/examples/helloworld.bf new file mode 100644 index 0000000..b947c5c --- /dev/null +++ b/examples/helloworld.bf @@ -0,0 +1 @@ + ++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>. diff --git a/examples/helloworld_comments.bf b/examples/helloworld_comments.bf new file mode 100644 index 0000000..5e304b1 --- /dev/null +++ b/examples/helloworld_comments.bf @@ -0,0 +1,21 @@ ++++++ +++++ initialize counter (cell #0) to 10 +[ use loop to set the next four cells to 70/100/30/10 + > +++++ ++ add 7 to cell #1 + > +++++ +++++ add 10 to cell #2 + > +++ add 3 to cell #3 + > + add 1 to cell #4 + <<<< - decrement counter (cell #0) +] +> ++ . print 'H' +> + . print 'e' ++++++ ++ . print 'l' +. print 'l' ++++ . print 'o' +> ++ . print ' ' +<< +++++ +++++ +++++ . print 'W' +> . print 'o' ++++ . print 'r' +----- - . print 'l' +----- --- . print 'd' +> + . print '!' +> . print '\n' diff --git a/examples/uppercase.bf b/examples/uppercase.bf new file mode 100644 index 0000000..deee9bc --- /dev/null +++ b/examples/uppercase.bf @@ -0,0 +1 @@ + ,----------[----------------------.,----------]