summaryrefslogtreecommitdiff
path: root/src/program.c
diff options
context:
space:
mode:
authorTyler Murphy <tylerm@tylerm.dev>2023-04-13 17:04:05 -0400
committerTyler Murphy <tylerm@tylerm.dev>2023-04-13 17:04:05 -0400
commitfafd290ed990aa2bef34b44fe373175eb6133093 (patch)
tree5d4848b3006bc4eec5d5f49d6372516e1a2a0ba3 /src/program.c
downloadbrainfucked-fafd290ed990aa2bef34b44fe373175eb6133093.tar.gz
brainfucked-fafd290ed990aa2bef34b44fe373175eb6133093.tar.bz2
brainfucked-fafd290ed990aa2bef34b44fe373175eb6133093.zip
brainfucked
Diffstat (limited to 'src/program.c')
-rw-r--r--src/program.c166
1 files changed, 166 insertions, 0 deletions
diff --git a/src/program.c b/src/program.c
new file mode 100644
index 0000000..43f6ee9
--- /dev/null
+++ b/src/program.c
@@ -0,0 +1,166 @@
+#include "program.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+
+static FILE* f;
+static uint32_t count;
+
+static char next_char() {
+ char c;
+ if (fread(&c, 1, 1, f) != 1) {
+ return EOF;
+ } else {
+ count++;
+ return c;
+ }
+}
+
+static Symbol next_symbol() {
+ char c = next_char();
+retest:
+ switch (c) {
+ case '<':
+ return MoveLeft;
+ case '>':
+ return MoveRight;
+ case '+':
+ return Increment;
+ case '-':
+ return Decrement;
+ case '[':
+ return StartLoop;
+ case ']':
+ return EndLoop;
+ case '.':
+ return PutChar;
+ case ',':
+ return GetChar;
+ case '*':
+ return Allocate;
+ case '!':
+ return Free;
+ case '(':
+ return EnterTape;
+ case ')':
+ return LeaveTape;
+ case '`':
+ return PutString;
+ case '~':
+ return GetString;
+ case '%':
+ return Clear;
+ case '\n':
+ case ' ':
+ while(c = next_char(), c == '\n' || c == ' ');
+ goto retest;
+ case '/':
+ while(c = next_char(), c != '\n' && c != EOF);
+ goto retest;
+ case EOF:
+ return Eof;
+ default:
+ return Invalid;
+ }
+}
+
+void program_init(char* file_path, Program* program) {
+ f = fopen (file_path, "r");
+ if (f == NULL) {
+ printf("error: failed to open %s (%s)\n", file_path, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ uint32_t capacity = 8;
+ count = 0;
+
+ program->data = malloc(capacity * sizeof(Symbol));
+ program->len = 0;
+
+ Symbol s;
+ while(true) {
+ s = next_symbol();
+
+ if (s == Invalid) {
+ printf("error: invalid symbol at character %d\n", count);
+ exit(EXIT_FAILURE);
+ }
+
+ if (program->len == capacity) {
+ capacity *= 2;
+ program->data = realloc(program->data, capacity * sizeof(Symbol));
+ }
+
+ program->data[program->len] = s;
+ program->len++;
+
+ if (s == Eof) break;
+ }
+
+ fclose(f);
+}
+
+void program_peek(Program* program, Symbol* symbol) {
+ *symbol = program->data[program->index];
+}
+
+void program_next(Program* program, Symbol* symbol) {
+ if (program->index >= program->len) {
+ *symbol = Eof;
+ return;
+ }
+ program_peek(program, symbol);
+ program->index++;
+}
+
+void program_last(Program* program, Symbol* symbol) {
+ if (program->index == 0) {
+ *symbol = Eof;
+ return;
+ }
+ program->index--;
+ program_peek(program, symbol);
+}
+
+void program_free(Program* program) {
+ free(program->data);
+}
+
+void tape_init(uint32_t len, Tape* tape) {
+ tape->len = len;
+ tape->data = malloc(len);
+ tape->index = 0;
+ memset(tape->data, 0, len);
+}
+
+void tape_left(Tape* tape) {
+ if (tape->index == 0) {
+ tape->index = tape->len - 1;
+ } else {
+ tape->index--;
+ }
+}
+
+void tape_right(Tape* tape) {
+ tape->index++;
+ tape->index %= tape->len;
+}
+
+uint8_t tape_get(Tape* tape) {
+ return tape->data[tape->index];
+}
+
+void tape_set(Tape* tape, uint8_t value) {
+ tape->data[tape->index] = value;
+}
+
+uint8_t* tape_ptr(Tape* tape) {
+ return tape->data;
+}
+
+void tape_free(Tape* tape) {
+ free(tape->data);
+}