#include #include #include #include #include #include #include #include typedef struct { char *filepath; bool help; bool debug; bool allow_infinite; uint64_t max_iter; } run_args_t; void print_hint() { printf("Usage: fz [flags] \n"); printf("Flags:\n"); printf("\t-h\t--help\t\t\tprint usage information\n"); printf("\t-d\t--debug\t\t\tdisplay program opcodes\n"); printf("\t\t--allow-infinite\tallow infinite loops\n"); printf("\t\t--max-iter N\t\trestrict loops to maximum N iterations\n"); } // Parse passed arguments and build args setup structure run_args_t *parse_args(int argc, char **argv) { if (argc < 2) { print_hint(); return NULL; } run_args_t *args = malloc(sizeof(run_args_t)); args->filepath = NULL; args->help = false; args->debug = false; args->allow_infinite = false; args->max_iter = 100000; for (int i = 0; i < argc; i++) { if (argv[i][0] != '-') continue; if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) { args->help = true; return args; } else if (strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--debug") == 0) args->debug = true; else if (strcmp(argv[i], "--allow-infinite") == 0) args->allow_infinite = true; else if (strcmp(argv[i], "--max-iter") == 0) { char *n = argv[++i]; if (!n || argc <= i || !(n[0] >= '0' && n[0] <= '9')) { printf("%sError%s: --max-iter options requires number after it\n", FZL_CERROR, FZL_CRST); free(args); return NULL; } uint64_t iters = strtol(n, NULL, 10); if (iters < 1) { printf("%sError%s: '--max-iter 0' is not allowed\n", FZL_CERROR, FZL_CRST); free(args); return NULL; } args->max_iter = iters; } else { printf("%sError%s: unknown flag '%s'.\n", FZL_CERROR, FZL_CRST, argv[i]); printf("Use 'fz --help' to read the usage\n"); free(args); return NULL; } } if (argv[argc - 1][0] == '-') { printf("%sError%s: last argument MUST be a file path\n", FZL_CERROR, FZL_CRST); printf("Use 'fz --help' for help\n"); free(args); return NULL; } args->filepath = argv[argc - 1]; return args; } int main(int argc, char **argv) { run_args_t *args = parse_args(argc, argv); if (!args) return -1; else if (args->help) { print_hint(); free(args); return 0; } fzl_vm_t *vm = fzl_mkvm(args->filepath); if (!vm) { printf("%sError%s: %s\n", FZL_CERROR, FZL_CRST, fzl_vm_geterror()); free(args); return -1; } if (args->debug) fzl_vm_print_ops(vm); else { int result = fzl_vm_run(vm, args->allow_infinite, args->max_iter); if (result != 0) { char *err = fzl_vm_geterror(); if (err && err[0]) printf("%sError%s: %s\n", FZL_CERROR, FZL_CRST, err); free(args); fzl_freevm(vm); return -1; } } free(args); fzl_freevm(vm); return 0; }