/src/config.c
C | 194 lines | 179 code | 15 blank | 0 comment | 52 complexity | 8f9ebd4d81739462afa118f84830d598 MD5 | raw file
Possible License(s): GPL-3.0
- #include <stddef.h>
- #include <stdbool.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- #define OPTPARSE_IMPLEMENTATION
- #define OPTPARSE_API static
- #include <optparse/optparse.h>
- #include "config.h"
- void afb_config_init(struct afb_config* config)
- {
- config->std = STD_BRAINFUCK;
- config->print = false;
- config->debug = false;
- config->help = false;
- config->bin = NULL;
- config->in_filename = NULL;
- config->out_filename = NULL;
- config->err_filename = NULL;
- config->in_stream = stdin;
- config->out_stream = stdout;
- config->err_stream = stderr;
- config->wordsize = 0;
- config->memsize = 0;
- }
- void afb_config_free(struct afb_config* config)
- {
- if (config->in_stream) fclose(config->in_stream);
- if (config->out_stream) fclose(config->out_stream);
- if (config->err_stream) fclose(config->err_stream);
- }
- static int set_standard(struct afb_config* config, const char* arg)
- {
- if (0 == strcmp(arg, "bf")) {
- config->std = STD_BRAINFUCK;
- } else if (0 == strcmp(arg, "ook")) {
- config->std = STD_OOK;
- } else if (0 == strcmp(arg, "bf++")) {
- config->std = STD_BRAINFUCKPP;
- } else if (0 == strcmp(arg, "bf--")) {
- config->std = STD_BRAINFUCKMM;
- } else if (0 == strcmp(arg, "*bf")) {
- config->std = STD_PTRBRAINFUCK;
- } else if (0 == strcmp(arg, "lcbf")) {
- config->std = STD_LCBF;
- } else if (0 == strcmp(arg, "mndb")) {
- config->std = STD_MNDB;
- } else if (0 == strcmp(arg, "brainfork")) {
- config->std = STD_BRAINFORK;
- } else if (0 == strcmp(arg, "bfp3")) {
- config->std = STD_BFP3;
- } else {
- fprintf(config->err_stream, "%s: standard \"%s\" does not exist\n", config->bin, arg);
- return 1 << 0;
- }
- return 0;
- }
- static int set_wordsize(struct afb_config* config, const char* arg)
- {
- unsigned long ws = strtoul(arg, NULL, 10);
- if ((0 < ws) && (ws <= 64)) {
- config->wordsize = ws;
- return 0;
- } else {
- fprintf(config->err_stream, "%s: invalid wordsize: %s (1-64 expected)\n", config->bin, arg);
- return 1 << 1;
- }
- }
- static int set_memsize(struct afb_config* config, const char* arg)
- {
- unsigned long ms = strtoul(arg, NULL, 10);
- if (ms != 0) {
- config->memsize = ms;
- return 0;
- } else {
- fprintf(config->err_stream, "%s: invalid memory size (must be >0)\n", config->bin);
- return 1 << 1;
- }
- }
- int afb_config_parse(struct afb_config* config, char** argv)
- {
- int res = 0;
- config->bin = argv[0];
- struct optparse_long longopts[] = {
- { "help", 'h', OPTPARSE_NONE },
- { "print", 'p', OPTPARSE_NONE },
- { "debug", 'd', OPTPARSE_NONE },
- { "std", 's', OPTPARSE_REQUIRED },
- { "wordsize", 'w', OPTPARSE_REQUIRED },
- { "memsize", 'm', OPTPARSE_REQUIRED },
- { NULL, 0, 0 }
- };
- int option;
- struct optparse options;
- optparse_init(&options, argv);
- while ((option = optparse_long(&options, longopts, NULL)) != -1) {
- switch (option) {
- case 'p':
- config->print = true;
- break;
- case 'd':
- config->debug = true;
- break;
- case 's':
- res |= set_standard(config, options.optarg);
- break;
- case 'w':
- res |= set_wordsize(config, options.optarg);
- break;
- case 'm':
- res |= set_memsize(config, options.optarg);
- break;
- case 'h':
- config->help = true;
- break;
- case '?':
- fprintf(config->err_stream, "%s: %s\n", config->bin, options.errmsg);
- res |= 1 << 2;
- }
- }
- char* arg;
- while ((arg = optparse_arg(&options))) {
- if (config->in_filename == NULL) {
- config->in_filename = arg;
- } else {
- fprintf(config->err_stream, "%s: unexpected argument \"%s\", input file already set (\"%s\")\n", config->bin, arg, config->in_filename);
- res |= 1 << 3;
- }
- }
- return res;
- }
- int afb_config_open_streams(struct afb_config* config)
- {
- int res = 0;
- if (config->in_filename != NULL) {
- config->in_stream = fopen(config->in_filename, "r");
- if (!config->in_stream) {
- fprintf(config->err_stream, "%s: cannot open file \"%s\": %s\n", config->bin, config->in_filename, strerror(errno));
- res |= 1 << 0;
- }
- }
- if (config->out_filename != NULL) {
- config->out_stream = fopen(config->out_filename, "r");
- if (!config->out_stream) {
- fprintf(config->err_stream, "%s: cannot open file \"%s\": %s\n", config->bin, config->out_filename, strerror(errno));
- res |= 1 << 1;
- }
- }
- if (config->err_filename != NULL) {
- config->err_stream = fopen(config->err_filename, "r");
- if (!config->err_stream) {
- fprintf(config->err_stream, "%s: cannot open file \"%s\": %s\n", config->bin, config->err_filename, strerror(errno));
- res |= 1 << 2;
- }
- }
- return res;
- }
- void afb_config_usage(struct afb_config* config)
- {
- fprintf(config->err_stream,
- "usage:\n"
- "\n"
- " %s [options] [input file]\n"
- "\n"
- " -h --help\n"
- " print print this help message\n"
- " -p --print\n"
- " print program after parse (remove comments and line breaks)\n"
- " -d --debug\n"
- " display memory content after each instruction\n"
- " -s --std {bf|ook|bf++|bf--|*bf|lcbf|mndb|brainfork|bfp3}\n"
- " set brainf*ck standard\n"
- " -w --wordsize {1-64}\n"
- " set cellsize in bits\n"
- " -m --memsize {0..}\n"
- " set memory size in bytes (byte size set by --wordsize)\n",
- config->bin);
- }