Author | Jakob Wakeling <[email protected]> |
Date | 2020-06-30 12:17:39 |
Commit | 5983903fa3bb81b4d2ab730317d52cd3f8fb6280 |
Parent | b7279ece23b36fa3b74c324082539b89d5fdccb4 |
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; +}