1252884aeSStefan Eßer /* 2252884aeSStefan Eßer * ***************************************************************************** 3252884aeSStefan Eßer * 43aa99676SStefan Eßer * SPDX-License-Identifier: BSD-2-Clause 5252884aeSStefan Eßer * 63aa99676SStefan Eßer * Copyright (c) 2018-2020 Gavin D. Howard and contributors. 7252884aeSStefan Eßer * 8252884aeSStefan Eßer * Redistribution and use in source and binary forms, with or without 9252884aeSStefan Eßer * modification, are permitted provided that the following conditions are met: 10252884aeSStefan Eßer * 11252884aeSStefan Eßer * * Redistributions of source code must retain the above copyright notice, this 12252884aeSStefan Eßer * list of conditions and the following disclaimer. 13252884aeSStefan Eßer * 14252884aeSStefan Eßer * * Redistributions in binary form must reproduce the above copyright notice, 15252884aeSStefan Eßer * this list of conditions and the following disclaimer in the documentation 16252884aeSStefan Eßer * and/or other materials provided with the distribution. 17252884aeSStefan Eßer * 18252884aeSStefan Eßer * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19252884aeSStefan Eßer * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20252884aeSStefan Eßer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21252884aeSStefan Eßer * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22252884aeSStefan Eßer * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23252884aeSStefan Eßer * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24252884aeSStefan Eßer * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25252884aeSStefan Eßer * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26252884aeSStefan Eßer * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27252884aeSStefan Eßer * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28252884aeSStefan Eßer * POSSIBILITY OF SUCH DAMAGE. 29252884aeSStefan Eßer * 30252884aeSStefan Eßer * ***************************************************************************** 31252884aeSStefan Eßer * 32252884aeSStefan Eßer * Code for processing command-line arguments. 33252884aeSStefan Eßer * 34252884aeSStefan Eßer */ 35252884aeSStefan Eßer 36252884aeSStefan Eßer #include <assert.h> 37252884aeSStefan Eßer #include <ctype.h> 38252884aeSStefan Eßer #include <stdbool.h> 39252884aeSStefan Eßer #include <stdlib.h> 40252884aeSStefan Eßer #include <string.h> 41252884aeSStefan Eßer 42252884aeSStefan Eßer #include <unistd.h> 43252884aeSStefan Eßer 44252884aeSStefan Eßer #include <status.h> 45252884aeSStefan Eßer #include <vector.h> 46252884aeSStefan Eßer #include <read.h> 47252884aeSStefan Eßer #include <vm.h> 48252884aeSStefan Eßer #include <args.h> 49252884aeSStefan Eßer #include <opt.h> 50252884aeSStefan Eßer 51252884aeSStefan Eßer static const BcOptLong bc_args_lopt[] = { 52252884aeSStefan Eßer 53252884aeSStefan Eßer { "expression", BC_OPT_REQUIRED, 'e' }, 54252884aeSStefan Eßer { "file", BC_OPT_REQUIRED, 'f' }, 55252884aeSStefan Eßer { "help", BC_OPT_NONE, 'h' }, 56252884aeSStefan Eßer { "interactive", BC_OPT_NONE, 'i' }, 57252884aeSStefan Eßer { "no-prompt", BC_OPT_NONE, 'P' }, 58252884aeSStefan Eßer #if BC_ENABLED 59252884aeSStefan Eßer { "global-stacks", BC_OPT_BC_ONLY, 'g' }, 60252884aeSStefan Eßer { "mathlib", BC_OPT_BC_ONLY, 'l' }, 61252884aeSStefan Eßer { "quiet", BC_OPT_BC_ONLY, 'q' }, 62252884aeSStefan Eßer { "standard", BC_OPT_BC_ONLY, 's' }, 63252884aeSStefan Eßer { "warn", BC_OPT_BC_ONLY, 'w' }, 64252884aeSStefan Eßer #endif // BC_ENABLED 65252884aeSStefan Eßer { "version", BC_OPT_NONE, 'v' }, 66252884aeSStefan Eßer { "version", BC_OPT_NONE, 'V' }, 67252884aeSStefan Eßer #if DC_ENABLED 68252884aeSStefan Eßer { "extended-register", BC_OPT_DC_ONLY, 'x' }, 69252884aeSStefan Eßer #endif // DC_ENABLED 70252884aeSStefan Eßer { NULL, 0, 0 }, 71252884aeSStefan Eßer 72252884aeSStefan Eßer }; 73252884aeSStefan Eßer 74252884aeSStefan Eßer static void bc_args_exprs(const char *str) { 75252884aeSStefan Eßer BC_SIG_ASSERT_LOCKED; 76252884aeSStefan Eßer if (vm.exprs.v == NULL) bc_vec_init(&vm.exprs, sizeof(uchar), NULL); 77252884aeSStefan Eßer bc_vec_concat(&vm.exprs, str); 78252884aeSStefan Eßer bc_vec_concat(&vm.exprs, "\n"); 79252884aeSStefan Eßer } 80252884aeSStefan Eßer 81252884aeSStefan Eßer static void bc_args_file(const char *file) { 82252884aeSStefan Eßer 83252884aeSStefan Eßer char *buf; 84252884aeSStefan Eßer 85252884aeSStefan Eßer BC_SIG_ASSERT_LOCKED; 86252884aeSStefan Eßer 87252884aeSStefan Eßer vm.file = file; 88252884aeSStefan Eßer 89252884aeSStefan Eßer bc_read_file(file, &buf); 90252884aeSStefan Eßer bc_args_exprs(buf); 91252884aeSStefan Eßer free(buf); 92252884aeSStefan Eßer } 93252884aeSStefan Eßer 94252884aeSStefan Eßer void bc_args(int argc, char *argv[]) { 95252884aeSStefan Eßer 96252884aeSStefan Eßer int c; 97252884aeSStefan Eßer size_t i; 98252884aeSStefan Eßer bool do_exit = false, version = false; 99252884aeSStefan Eßer BcOpt opts; 100252884aeSStefan Eßer 101252884aeSStefan Eßer BC_SIG_ASSERT_LOCKED; 102252884aeSStefan Eßer 103252884aeSStefan Eßer bc_opt_init(&opts, argv); 104252884aeSStefan Eßer 105252884aeSStefan Eßer while ((c = bc_opt_parse(&opts, bc_args_lopt)) != -1) { 106252884aeSStefan Eßer 107252884aeSStefan Eßer switch (c) { 108252884aeSStefan Eßer 109252884aeSStefan Eßer case 'e': 110252884aeSStefan Eßer { 111*5d934bc0SStefan Eßer if (vm.no_exit_exprs) 112*5d934bc0SStefan Eßer bc_vm_verr(BC_ERROR_FATAL_OPTION, "-e (--expression)"); 113252884aeSStefan Eßer bc_args_exprs(opts.optarg); 114252884aeSStefan Eßer break; 115252884aeSStefan Eßer } 116252884aeSStefan Eßer 117252884aeSStefan Eßer case 'f': 118252884aeSStefan Eßer { 119*5d934bc0SStefan Eßer if (!strcmp(opts.optarg, "-")) vm.no_exit_exprs = true; 120*5d934bc0SStefan Eßer else { 121*5d934bc0SStefan Eßer if (vm.no_exit_exprs) 122*5d934bc0SStefan Eßer bc_vm_verr(BC_ERROR_FATAL_OPTION, "-f (--file)"); 123252884aeSStefan Eßer bc_args_file(opts.optarg); 124*5d934bc0SStefan Eßer } 125252884aeSStefan Eßer break; 126252884aeSStefan Eßer } 127252884aeSStefan Eßer 128252884aeSStefan Eßer case 'h': 129252884aeSStefan Eßer { 130252884aeSStefan Eßer bc_vm_info(vm.help); 131252884aeSStefan Eßer do_exit = true; 132252884aeSStefan Eßer break; 133252884aeSStefan Eßer } 134252884aeSStefan Eßer 135252884aeSStefan Eßer case 'i': 136252884aeSStefan Eßer { 137252884aeSStefan Eßer vm.flags |= BC_FLAG_I; 138252884aeSStefan Eßer break; 139252884aeSStefan Eßer } 140252884aeSStefan Eßer 141252884aeSStefan Eßer case 'P': 142252884aeSStefan Eßer { 143252884aeSStefan Eßer vm.flags |= BC_FLAG_P; 144252884aeSStefan Eßer break; 145252884aeSStefan Eßer } 146252884aeSStefan Eßer 147252884aeSStefan Eßer #if BC_ENABLED 148252884aeSStefan Eßer case 'g': 149252884aeSStefan Eßer { 150252884aeSStefan Eßer assert(BC_IS_BC); 151252884aeSStefan Eßer vm.flags |= BC_FLAG_G; 152252884aeSStefan Eßer break; 153252884aeSStefan Eßer } 154252884aeSStefan Eßer 155252884aeSStefan Eßer case 'l': 156252884aeSStefan Eßer { 157252884aeSStefan Eßer assert(BC_IS_BC); 158252884aeSStefan Eßer vm.flags |= BC_FLAG_L; 159252884aeSStefan Eßer break; 160252884aeSStefan Eßer } 161252884aeSStefan Eßer 162252884aeSStefan Eßer case 'q': 163252884aeSStefan Eßer { 164252884aeSStefan Eßer assert(BC_IS_BC); 165*5d934bc0SStefan Eßer // Do nothing. 166252884aeSStefan Eßer break; 167252884aeSStefan Eßer } 168252884aeSStefan Eßer 169252884aeSStefan Eßer case 's': 170252884aeSStefan Eßer { 171252884aeSStefan Eßer assert(BC_IS_BC); 172252884aeSStefan Eßer vm.flags |= BC_FLAG_S; 173252884aeSStefan Eßer break; 174252884aeSStefan Eßer } 175252884aeSStefan Eßer 176252884aeSStefan Eßer case 'w': 177252884aeSStefan Eßer { 178252884aeSStefan Eßer assert(BC_IS_BC); 179252884aeSStefan Eßer vm.flags |= BC_FLAG_W; 180252884aeSStefan Eßer break; 181252884aeSStefan Eßer } 182252884aeSStefan Eßer #endif // BC_ENABLED 183252884aeSStefan Eßer 184252884aeSStefan Eßer case 'V': 185252884aeSStefan Eßer case 'v': 186252884aeSStefan Eßer { 187252884aeSStefan Eßer do_exit = version = true; 188252884aeSStefan Eßer break; 189252884aeSStefan Eßer } 190252884aeSStefan Eßer 191252884aeSStefan Eßer #if DC_ENABLED 192252884aeSStefan Eßer case 'x': 193252884aeSStefan Eßer { 1943aa99676SStefan Eßer assert(BC_IS_DC); 195252884aeSStefan Eßer vm.flags |= DC_FLAG_X; 196252884aeSStefan Eßer break; 197252884aeSStefan Eßer } 198252884aeSStefan Eßer #endif // DC_ENABLED 199252884aeSStefan Eßer 200252884aeSStefan Eßer #ifndef NDEBUG 201252884aeSStefan Eßer // We shouldn't get here because bc_opt_error()/bc_vm_error() should 202252884aeSStefan Eßer // longjmp() out. 203252884aeSStefan Eßer case '?': 204252884aeSStefan Eßer case ':': 205252884aeSStefan Eßer default: 206252884aeSStefan Eßer { 207252884aeSStefan Eßer abort(); 208252884aeSStefan Eßer } 209252884aeSStefan Eßer #endif // NDEBUG 210252884aeSStefan Eßer } 211252884aeSStefan Eßer } 212252884aeSStefan Eßer 213252884aeSStefan Eßer if (version) bc_vm_info(NULL); 214252884aeSStefan Eßer if (do_exit) exit((int) vm.status); 215252884aeSStefan Eßer 216*5d934bc0SStefan Eßer if (opts.optind < (size_t) argc && vm.files.v == NULL) 217252884aeSStefan Eßer bc_vec_init(&vm.files, sizeof(char*), NULL); 218252884aeSStefan Eßer 219252884aeSStefan Eßer for (i = opts.optind; i < (size_t) argc; ++i) 220252884aeSStefan Eßer bc_vec_push(&vm.files, argv + i); 221252884aeSStefan Eßer } 222