diff options
author | Stefan Eßer <se@FreeBSD.org> | 2020-06-27 15:03:19 +0000 |
---|---|---|
committer | Stefan Eßer <se@FreeBSD.org> | 2020-06-27 15:03:19 +0000 |
commit | 1f958cfad78842ab9a1193471589231e25596cb3 (patch) | |
tree | 4bbff8044605fcfff11c9d322bb6f53495e4faa7 /src/args.c |
Diffstat (limited to 'src/args.c')
-rw-r--r-- | src/args.c | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/src/args.c b/src/args.c new file mode 100644 index 000000000000..d3735178fc48 --- /dev/null +++ b/src/args.c @@ -0,0 +1,215 @@ +/* + * ***************************************************************************** + * + * Copyright (c) 2018-2020 Gavin D. Howard and contributors. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * ***************************************************************************** + * + * Code for processing command-line arguments. + * + */ + +#include <assert.h> +#include <ctype.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> + +#include <unistd.h> + +#include <status.h> +#include <vector.h> +#include <read.h> +#include <vm.h> +#include <args.h> +#include <opt.h> + +static const BcOptLong bc_args_lopt[] = { + + { "expression", BC_OPT_REQUIRED, 'e' }, + { "file", BC_OPT_REQUIRED, 'f' }, + { "help", BC_OPT_NONE, 'h' }, + { "interactive", BC_OPT_NONE, 'i' }, + { "no-prompt", BC_OPT_NONE, 'P' }, +#if BC_ENABLED + { "global-stacks", BC_OPT_BC_ONLY, 'g' }, + { "mathlib", BC_OPT_BC_ONLY, 'l' }, + { "quiet", BC_OPT_BC_ONLY, 'q' }, + { "standard", BC_OPT_BC_ONLY, 's' }, + { "warn", BC_OPT_BC_ONLY, 'w' }, +#endif // BC_ENABLED + { "version", BC_OPT_NONE, 'v' }, + { "version", BC_OPT_NONE, 'V' }, +#if DC_ENABLED + { "extended-register", BC_OPT_DC_ONLY, 'x' }, +#endif // DC_ENABLED + { NULL, 0, 0 }, + +}; + +static void bc_args_exprs(const char *str) { + BC_SIG_ASSERT_LOCKED; + if (vm.exprs.v == NULL) bc_vec_init(&vm.exprs, sizeof(uchar), NULL); + bc_vec_concat(&vm.exprs, str); + bc_vec_concat(&vm.exprs, "\n"); +} + +static void bc_args_file(const char *file) { + + char *buf; + + BC_SIG_ASSERT_LOCKED; + + vm.file = file; + + bc_read_file(file, &buf); + bc_args_exprs(buf); + free(buf); +} + +void bc_args(int argc, char *argv[]) { + + int c; + size_t i; + bool do_exit = false, version = false; + BcOpt opts; + + BC_SIG_ASSERT_LOCKED; + + bc_opt_init(&opts, argv); + + while ((c = bc_opt_parse(&opts, bc_args_lopt)) != -1) { + + switch (c) { + + case 'e': + { + bc_args_exprs(opts.optarg); + break; + } + + case 'f': + { + bc_args_file(opts.optarg); + break; + } + + case 'h': + { + bc_vm_info(vm.help); + do_exit = true; + break; + } + + case 'i': + { + vm.flags |= BC_FLAG_I; + break; + } + + case 'P': + { + vm.flags |= BC_FLAG_P; + break; + } + +#if BC_ENABLED + case 'g': + { + assert(BC_IS_BC); + vm.flags |= BC_FLAG_G; + break; + } + + case 'l': + { + assert(BC_IS_BC); + vm.flags |= BC_FLAG_L; + break; + } + + case 'q': + { + assert(BC_IS_BC); + vm.flags |= BC_FLAG_Q; + break; + } + + case 's': + { + assert(BC_IS_BC); + vm.flags |= BC_FLAG_S; + break; + } + + case 'w': + { + assert(BC_IS_BC); + vm.flags |= BC_FLAG_W; + break; + } +#endif // BC_ENABLED + + case 'V': + case 'v': + { + do_exit = version = true; + break; + } + +#if DC_ENABLED + case 'x': + { + assert(!BC_IS_BC); + vm.flags |= DC_FLAG_X; + break; + } +#endif // DC_ENABLED + +#ifndef NDEBUG + // We shouldn't get here because bc_opt_error()/bc_vm_error() should + // longjmp() out. + case '?': + case ':': + default: + { + abort(); + } +#endif // NDEBUG + } + } + + if (version) bc_vm_info(NULL); + if (do_exit) exit((int) vm.status); + if (vm.exprs.len > 1 || !BC_IS_BC) vm.flags |= BC_FLAG_Q; + + if (opts.optind < (size_t) argc) + bc_vec_init(&vm.files, sizeof(char*), NULL); + + for (i = opts.optind; i < (size_t) argc; ++i) + bc_vec_push(&vm.files, argv + i); +} |