1252884aeSStefan Eßer /* 2252884aeSStefan Eßer * ***************************************************************************** 3252884aeSStefan Eßer * 43aa99676SStefan Eßer * SPDX-License-Identifier: BSD-2-Clause 5252884aeSStefan Eßer * 610328f8bSStefan Eßer * Copyright (c) 2018-2021 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 42*7e5c51e5SStefan Eßer #ifndef _WIN32 43252884aeSStefan Eßer #include <unistd.h> 44*7e5c51e5SStefan Eßer #endif // _WIN32 45252884aeSStefan Eßer 46252884aeSStefan Eßer #include <vector.h> 47252884aeSStefan Eßer #include <read.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' }, 58*7e5c51e5SStefan Eßer { "no-read-prompt", BC_OPT_NONE, 'R' }, 59252884aeSStefan Eßer #if BC_ENABLED 60252884aeSStefan Eßer { "global-stacks", BC_OPT_BC_ONLY, 'g' }, 61252884aeSStefan Eßer { "mathlib", BC_OPT_BC_ONLY, 'l' }, 62252884aeSStefan Eßer { "quiet", BC_OPT_BC_ONLY, 'q' }, 63252884aeSStefan Eßer { "standard", BC_OPT_BC_ONLY, 's' }, 64252884aeSStefan Eßer { "warn", BC_OPT_BC_ONLY, 'w' }, 65252884aeSStefan Eßer #endif // BC_ENABLED 66252884aeSStefan Eßer { "version", BC_OPT_NONE, 'v' }, 67252884aeSStefan Eßer { "version", BC_OPT_NONE, 'V' }, 68252884aeSStefan Eßer #if DC_ENABLED 69252884aeSStefan Eßer { "extended-register", BC_OPT_DC_ONLY, 'x' }, 70252884aeSStefan Eßer #endif // DC_ENABLED 71252884aeSStefan Eßer { NULL, 0, 0 }, 72252884aeSStefan Eßer 73252884aeSStefan Eßer }; 74252884aeSStefan Eßer 75252884aeSStefan Eßer static void bc_args_exprs(const char *str) { 76252884aeSStefan Eßer BC_SIG_ASSERT_LOCKED; 77252884aeSStefan Eßer if (vm.exprs.v == NULL) bc_vec_init(&vm.exprs, sizeof(uchar), NULL); 78252884aeSStefan Eßer bc_vec_concat(&vm.exprs, str); 79252884aeSStefan Eßer bc_vec_concat(&vm.exprs, "\n"); 80252884aeSStefan Eßer } 81252884aeSStefan Eßer 82252884aeSStefan Eßer static void bc_args_file(const char *file) { 83252884aeSStefan Eßer 84252884aeSStefan Eßer char *buf; 85252884aeSStefan Eßer 86252884aeSStefan Eßer BC_SIG_ASSERT_LOCKED; 87252884aeSStefan Eßer 88252884aeSStefan Eßer vm.file = file; 89252884aeSStefan Eßer 90252884aeSStefan Eßer bc_read_file(file, &buf); 91252884aeSStefan Eßer bc_args_exprs(buf); 92252884aeSStefan Eßer free(buf); 93252884aeSStefan Eßer } 94252884aeSStefan Eßer 959a995fe1SStefan Eßer void bc_args(int argc, char *argv[], bool exit_exprs) { 96252884aeSStefan Eßer 97252884aeSStefan Eßer int c; 98252884aeSStefan Eßer size_t i; 99252884aeSStefan Eßer bool do_exit = false, version = false; 100252884aeSStefan Eßer BcOpt opts; 101252884aeSStefan Eßer 102252884aeSStefan Eßer BC_SIG_ASSERT_LOCKED; 103252884aeSStefan Eßer 104252884aeSStefan Eßer bc_opt_init(&opts, argv); 105252884aeSStefan Eßer 106252884aeSStefan Eßer while ((c = bc_opt_parse(&opts, bc_args_lopt)) != -1) { 107252884aeSStefan Eßer 108252884aeSStefan Eßer switch (c) { 109252884aeSStefan Eßer 110252884aeSStefan Eßer case 'e': 111252884aeSStefan Eßer { 1125d934bc0SStefan Eßer if (vm.no_exit_exprs) 11350696a6eSStefan Eßer bc_vm_verr(BC_ERR_FATAL_OPTION, "-e (--expression)"); 114252884aeSStefan Eßer bc_args_exprs(opts.optarg); 1159a995fe1SStefan Eßer vm.exit_exprs = (exit_exprs || vm.exit_exprs); 116252884aeSStefan Eßer break; 117252884aeSStefan Eßer } 118252884aeSStefan Eßer 119252884aeSStefan Eßer case 'f': 120252884aeSStefan Eßer { 1215d934bc0SStefan Eßer if (!strcmp(opts.optarg, "-")) vm.no_exit_exprs = true; 1225d934bc0SStefan Eßer else { 1235d934bc0SStefan Eßer if (vm.no_exit_exprs) 12450696a6eSStefan Eßer bc_vm_verr(BC_ERR_FATAL_OPTION, "-f (--file)"); 125252884aeSStefan Eßer bc_args_file(opts.optarg); 1269a995fe1SStefan Eßer vm.exit_exprs = (exit_exprs || vm.exit_exprs); 1275d934bc0SStefan Eßer } 128252884aeSStefan Eßer break; 129252884aeSStefan Eßer } 130252884aeSStefan Eßer 131252884aeSStefan Eßer case 'h': 132252884aeSStefan Eßer { 133252884aeSStefan Eßer bc_vm_info(vm.help); 134252884aeSStefan Eßer do_exit = true; 135252884aeSStefan Eßer break; 136252884aeSStefan Eßer } 137252884aeSStefan Eßer 138252884aeSStefan Eßer case 'i': 139252884aeSStefan Eßer { 140252884aeSStefan Eßer vm.flags |= BC_FLAG_I; 141252884aeSStefan Eßer break; 142252884aeSStefan Eßer } 143252884aeSStefan Eßer 144252884aeSStefan Eßer case 'P': 145252884aeSStefan Eßer { 146252884aeSStefan Eßer vm.flags |= BC_FLAG_P; 147252884aeSStefan Eßer break; 148252884aeSStefan Eßer } 149252884aeSStefan Eßer 150*7e5c51e5SStefan Eßer case 'R': 151*7e5c51e5SStefan Eßer { 152*7e5c51e5SStefan Eßer vm.flags |= BC_FLAG_R; 153*7e5c51e5SStefan Eßer break; 154*7e5c51e5SStefan Eßer } 155*7e5c51e5SStefan Eßer 156252884aeSStefan Eßer #if BC_ENABLED 157252884aeSStefan Eßer case 'g': 158252884aeSStefan Eßer { 159252884aeSStefan Eßer assert(BC_IS_BC); 160252884aeSStefan Eßer vm.flags |= BC_FLAG_G; 161252884aeSStefan Eßer break; 162252884aeSStefan Eßer } 163252884aeSStefan Eßer 164252884aeSStefan Eßer case 'l': 165252884aeSStefan Eßer { 166252884aeSStefan Eßer assert(BC_IS_BC); 167252884aeSStefan Eßer vm.flags |= BC_FLAG_L; 168252884aeSStefan Eßer break; 169252884aeSStefan Eßer } 170252884aeSStefan Eßer 171252884aeSStefan Eßer case 'q': 172252884aeSStefan Eßer { 173252884aeSStefan Eßer assert(BC_IS_BC); 1745d934bc0SStefan Eßer // Do nothing. 175252884aeSStefan Eßer break; 176252884aeSStefan Eßer } 177252884aeSStefan Eßer 178252884aeSStefan Eßer case 's': 179252884aeSStefan Eßer { 180252884aeSStefan Eßer assert(BC_IS_BC); 181252884aeSStefan Eßer vm.flags |= BC_FLAG_S; 182252884aeSStefan Eßer break; 183252884aeSStefan Eßer } 184252884aeSStefan Eßer 185252884aeSStefan Eßer case 'w': 186252884aeSStefan Eßer { 187252884aeSStefan Eßer assert(BC_IS_BC); 188252884aeSStefan Eßer vm.flags |= BC_FLAG_W; 189252884aeSStefan Eßer break; 190252884aeSStefan Eßer } 191252884aeSStefan Eßer #endif // BC_ENABLED 192252884aeSStefan Eßer 193252884aeSStefan Eßer case 'V': 194252884aeSStefan Eßer case 'v': 195252884aeSStefan Eßer { 196252884aeSStefan Eßer do_exit = version = true; 197252884aeSStefan Eßer break; 198252884aeSStefan Eßer } 199252884aeSStefan Eßer 200252884aeSStefan Eßer #if DC_ENABLED 201252884aeSStefan Eßer case 'x': 202252884aeSStefan Eßer { 2033aa99676SStefan Eßer assert(BC_IS_DC); 204252884aeSStefan Eßer vm.flags |= DC_FLAG_X; 205252884aeSStefan Eßer break; 206252884aeSStefan Eßer } 207252884aeSStefan Eßer #endif // DC_ENABLED 208252884aeSStefan Eßer 209252884aeSStefan Eßer #ifndef NDEBUG 210252884aeSStefan Eßer // We shouldn't get here because bc_opt_error()/bc_vm_error() should 211252884aeSStefan Eßer // longjmp() out. 212252884aeSStefan Eßer case '?': 213252884aeSStefan Eßer case ':': 214252884aeSStefan Eßer default: 215252884aeSStefan Eßer { 216252884aeSStefan Eßer abort(); 217252884aeSStefan Eßer } 218252884aeSStefan Eßer #endif // NDEBUG 219252884aeSStefan Eßer } 220252884aeSStefan Eßer } 221252884aeSStefan Eßer 222252884aeSStefan Eßer if (version) bc_vm_info(NULL); 223252884aeSStefan Eßer if (do_exit) exit((int) vm.status); 224252884aeSStefan Eßer 2255d934bc0SStefan Eßer if (opts.optind < (size_t) argc && vm.files.v == NULL) 226252884aeSStefan Eßer bc_vec_init(&vm.files, sizeof(char*), NULL); 227252884aeSStefan Eßer 228252884aeSStefan Eßer for (i = opts.optind; i < (size_t) argc; ++i) 229252884aeSStefan Eßer bc_vec_push(&vm.files, argv + i); 230252884aeSStefan Eßer } 231