OBFI

Brainfuck Interpreter
git clone http://git.omkov.net/OBFI
Log | Tree | Refs | README | LICENCE | Download

AuthorJakob Wakeling <[email protected]>
Date2020-06-30 12:17:39
Commit5983903fa3bb81b4d2ab730317d52cd3f8fb6280
Parentb7279ece23b36fa3b74c324082539b89d5fdccb4

Add main program

Diffstat

A src/main.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

1 files changed, 96 insertions, 0 deletions

diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..836d6e4
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,96 @@
+// main.c
+// Main source file for OBFI
+// Copyright (C) 2020, Jakob Wakeling
+// All rights reserved.
+
+#include "lex.h"
+
+#include "error.h"
+#include "optget.h"
+
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static char arr[30000] = { 0 }, *ptr = arr;
+static tok_t **dat; static size_t cap, top;
+
+static void help(void);
+static void version(void);
+
+int main(int argc, char *argv[]) {
+	lop_t lops[] = {
+		{ "help",    ARG_NUL, 256 },
+		{ "version", ARG_NUL, 257 },
+		{ NULL, 0, 0 }
+	};
+	
+	opt_t opt = OPTGET_INIT; opt.str = ""; opt.lops = lops; int o;
+	while ((o = optget(&opt, argv, 1)) != -1) switch (o) {
+	case 256: { help(); return 0; }
+	case 257: { version(); return 0; }
+	default: { return 1; }
+	}
+	
+	if (opt.ind == argc) { error(1, "%s: missing operand", argv[0]); }
+	
+	char *file = argv[opt.ind]; struct stat fs; stat(file, &fs);
+	char *fb = malloc(sizeof (*fb) * fs.st_size + 1); fb[fs.st_size] = 0;
+	if (!fb) { error(1, "%s: %s", argv[0], serrno); }
+	
+	FILE *fi = fopen(file, "r"); fread(fb, fs.st_size, 1, fi); fclose(fi);
+	
+	tok_t *toks = parse(fb, fs.st_size); free(fb);
+	
+	cap = 64; top = 0; dat = malloc(sizeof (*dat) * cap);
+	if (!dat) { error(1, "%s: %s", argv[0], serrno); }
+	
+	for (tok_t *t = toks; t->typ != EOF; ++t) {
+start:	switch (t->typ) {
+		case RGT: { ptr += t->num; break; }
+		case LFT: { ptr -= t->num; break; }
+		case ADD: { *ptr += t->num; break; }
+		case SUB: { *ptr -= t->num; break; }
+		case PUT: { fputc(*ptr, stdout); break; }
+		case GET: { *ptr = fgetc(stdin); break; }
+		case OPN: {
+			if (!*ptr) {
+				register size_t i = 1; for (++t; i != 0; ++t) {
+					if (t->typ == OPN) { ++i; } else if (t->typ == CLS) { --i; }
+				} goto start;
+			}
+			
+			if (top == cap) {
+				register tok_t **old = dat; cap *= 2; dat = realloc(dat, cap);
+				if (!dat) { free(old); error(1, "%s: %s", argv[0], serrno); }
+			} dat[top++] = t; break;
+		}
+		case CLS: {
+			if (*ptr) { t = dat[top - 1]; } else { dat[--top] = 0; } break;
+		}
+		}
+	}
+	
+	free(dat); free(toks); return 0;
+}
+
+static void help(void) {
+	puts("obfi - interpret brainfuck source file\n");
+	puts("usage: obfi file\n");
+	puts("options:");
+	puts("  --help     Display help information");
+	puts("  --version  Display version information");
+	return;
+}
+
+static void version(void) {
+	puts("OMKOV Brainfuck Interpreter, version " VERSION);
+	puts("Copyright (C) 2020, Jakob Wakeling");
+	puts("All rights reserved.");
+	puts("OMKOV Permissive Licence (https://www.omkov.net/OLPE)");
+	return;
+}