1*252884aeSStefan Eßer /* 2*252884aeSStefan Eßer * ***************************************************************************** 3*252884aeSStefan Eßer * 4*252884aeSStefan Eßer * Copyright (c) 2018-2020 Gavin D. Howard and contributors. 5*252884aeSStefan Eßer * 6*252884aeSStefan Eßer * All rights reserved. 7*252884aeSStefan Eßer * 8*252884aeSStefan Eßer * Redistribution and use in source and binary forms, with or without 9*252884aeSStefan Eßer * modification, are permitted provided that the following conditions are met: 10*252884aeSStefan Eßer * 11*252884aeSStefan Eßer * * Redistributions of source code must retain the above copyright notice, this 12*252884aeSStefan Eßer * list of conditions and the following disclaimer. 13*252884aeSStefan Eßer * 14*252884aeSStefan Eßer * * Redistributions in binary form must reproduce the above copyright notice, 15*252884aeSStefan Eßer * this list of conditions and the following disclaimer in the documentation 16*252884aeSStefan Eßer * and/or other materials provided with the distribution. 17*252884aeSStefan Eßer * 18*252884aeSStefan Eßer * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19*252884aeSStefan Eßer * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20*252884aeSStefan Eßer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21*252884aeSStefan Eßer * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22*252884aeSStefan Eßer * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23*252884aeSStefan Eßer * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24*252884aeSStefan Eßer * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25*252884aeSStefan Eßer * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26*252884aeSStefan Eßer * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27*252884aeSStefan Eßer * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28*252884aeSStefan Eßer * POSSIBILITY OF SUCH DAMAGE. 29*252884aeSStefan Eßer * 30*252884aeSStefan Eßer * ***************************************************************************** 31*252884aeSStefan Eßer * 32*252884aeSStefan Eßer * Code for processing command-line arguments. 33*252884aeSStefan Eßer * 34*252884aeSStefan Eßer */ 35*252884aeSStefan Eßer 36*252884aeSStefan Eßer #include <assert.h> 37*252884aeSStefan Eßer #include <ctype.h> 38*252884aeSStefan Eßer #include <stdbool.h> 39*252884aeSStefan Eßer #include <stdlib.h> 40*252884aeSStefan Eßer #include <string.h> 41*252884aeSStefan Eßer 42*252884aeSStefan Eßer #include <unistd.h> 43*252884aeSStefan Eßer 44*252884aeSStefan Eßer #include <status.h> 45*252884aeSStefan Eßer #include <vector.h> 46*252884aeSStefan Eßer #include <read.h> 47*252884aeSStefan Eßer #include <vm.h> 48*252884aeSStefan Eßer #include <args.h> 49*252884aeSStefan Eßer #include <opt.h> 50*252884aeSStefan Eßer 51*252884aeSStefan Eßer static const BcOptLong bc_args_lopt[] = { 52*252884aeSStefan Eßer 53*252884aeSStefan Eßer { "expression", BC_OPT_REQUIRED, 'e' }, 54*252884aeSStefan Eßer { "file", BC_OPT_REQUIRED, 'f' }, 55*252884aeSStefan Eßer { "help", BC_OPT_NONE, 'h' }, 56*252884aeSStefan Eßer { "interactive", BC_OPT_NONE, 'i' }, 57*252884aeSStefan Eßer { "no-prompt", BC_OPT_NONE, 'P' }, 58*252884aeSStefan Eßer #if BC_ENABLED 59*252884aeSStefan Eßer { "global-stacks", BC_OPT_BC_ONLY, 'g' }, 60*252884aeSStefan Eßer { "mathlib", BC_OPT_BC_ONLY, 'l' }, 61*252884aeSStefan Eßer { "quiet", BC_OPT_BC_ONLY, 'q' }, 62*252884aeSStefan Eßer { "standard", BC_OPT_BC_ONLY, 's' }, 63*252884aeSStefan Eßer { "warn", BC_OPT_BC_ONLY, 'w' }, 64*252884aeSStefan Eßer #endif // BC_ENABLED 65*252884aeSStefan Eßer { "version", BC_OPT_NONE, 'v' }, 66*252884aeSStefan Eßer { "version", BC_OPT_NONE, 'V' }, 67*252884aeSStefan Eßer #if DC_ENABLED 68*252884aeSStefan Eßer { "extended-register", BC_OPT_DC_ONLY, 'x' }, 69*252884aeSStefan Eßer #endif // DC_ENABLED 70*252884aeSStefan Eßer { NULL, 0, 0 }, 71*252884aeSStefan Eßer 72*252884aeSStefan Eßer }; 73*252884aeSStefan Eßer 74*252884aeSStefan Eßer static void bc_args_exprs(const char *str) { 75*252884aeSStefan Eßer BC_SIG_ASSERT_LOCKED; 76*252884aeSStefan Eßer if (vm.exprs.v == NULL) bc_vec_init(&vm.exprs, sizeof(uchar), NULL); 77*252884aeSStefan Eßer bc_vec_concat(&vm.exprs, str); 78*252884aeSStefan Eßer bc_vec_concat(&vm.exprs, "\n"); 79*252884aeSStefan Eßer } 80*252884aeSStefan Eßer 81*252884aeSStefan Eßer static void bc_args_file(const char *file) { 82*252884aeSStefan Eßer 83*252884aeSStefan Eßer char *buf; 84*252884aeSStefan Eßer 85*252884aeSStefan Eßer BC_SIG_ASSERT_LOCKED; 86*252884aeSStefan Eßer 87*252884aeSStefan Eßer vm.file = file; 88*252884aeSStefan Eßer 89*252884aeSStefan Eßer bc_read_file(file, &buf); 90*252884aeSStefan Eßer bc_args_exprs(buf); 91*252884aeSStefan Eßer free(buf); 92*252884aeSStefan Eßer } 93*252884aeSStefan Eßer 94*252884aeSStefan Eßer void bc_args(int argc, char *argv[]) { 95*252884aeSStefan Eßer 96*252884aeSStefan Eßer int c; 97*252884aeSStefan Eßer size_t i; 98*252884aeSStefan Eßer bool do_exit = false, version = false; 99*252884aeSStefan Eßer BcOpt opts; 100*252884aeSStefan Eßer 101*252884aeSStefan Eßer BC_SIG_ASSERT_LOCKED; 102*252884aeSStefan Eßer 103*252884aeSStefan Eßer bc_opt_init(&opts, argv); 104*252884aeSStefan Eßer 105*252884aeSStefan Eßer while ((c = bc_opt_parse(&opts, bc_args_lopt)) != -1) { 106*252884aeSStefan Eßer 107*252884aeSStefan Eßer switch (c) { 108*252884aeSStefan Eßer 109*252884aeSStefan Eßer case 'e': 110*252884aeSStefan Eßer { 111*252884aeSStefan Eßer bc_args_exprs(opts.optarg); 112*252884aeSStefan Eßer break; 113*252884aeSStefan Eßer } 114*252884aeSStefan Eßer 115*252884aeSStefan Eßer case 'f': 116*252884aeSStefan Eßer { 117*252884aeSStefan Eßer bc_args_file(opts.optarg); 118*252884aeSStefan Eßer break; 119*252884aeSStefan Eßer } 120*252884aeSStefan Eßer 121*252884aeSStefan Eßer case 'h': 122*252884aeSStefan Eßer { 123*252884aeSStefan Eßer bc_vm_info(vm.help); 124*252884aeSStefan Eßer do_exit = true; 125*252884aeSStefan Eßer break; 126*252884aeSStefan Eßer } 127*252884aeSStefan Eßer 128*252884aeSStefan Eßer case 'i': 129*252884aeSStefan Eßer { 130*252884aeSStefan Eßer vm.flags |= BC_FLAG_I; 131*252884aeSStefan Eßer break; 132*252884aeSStefan Eßer } 133*252884aeSStefan Eßer 134*252884aeSStefan Eßer case 'P': 135*252884aeSStefan Eßer { 136*252884aeSStefan Eßer vm.flags |= BC_FLAG_P; 137*252884aeSStefan Eßer break; 138*252884aeSStefan Eßer } 139*252884aeSStefan Eßer 140*252884aeSStefan Eßer #if BC_ENABLED 141*252884aeSStefan Eßer case 'g': 142*252884aeSStefan Eßer { 143*252884aeSStefan Eßer assert(BC_IS_BC); 144*252884aeSStefan Eßer vm.flags |= BC_FLAG_G; 145*252884aeSStefan Eßer break; 146*252884aeSStefan Eßer } 147*252884aeSStefan Eßer 148*252884aeSStefan Eßer case 'l': 149*252884aeSStefan Eßer { 150*252884aeSStefan Eßer assert(BC_IS_BC); 151*252884aeSStefan Eßer vm.flags |= BC_FLAG_L; 152*252884aeSStefan Eßer break; 153*252884aeSStefan Eßer } 154*252884aeSStefan Eßer 155*252884aeSStefan Eßer case 'q': 156*252884aeSStefan Eßer { 157*252884aeSStefan Eßer assert(BC_IS_BC); 158*252884aeSStefan Eßer vm.flags |= BC_FLAG_Q; 159*252884aeSStefan Eßer break; 160*252884aeSStefan Eßer } 161*252884aeSStefan Eßer 162*252884aeSStefan Eßer case 's': 163*252884aeSStefan Eßer { 164*252884aeSStefan Eßer assert(BC_IS_BC); 165*252884aeSStefan Eßer vm.flags |= BC_FLAG_S; 166*252884aeSStefan Eßer break; 167*252884aeSStefan Eßer } 168*252884aeSStefan Eßer 169*252884aeSStefan Eßer case 'w': 170*252884aeSStefan Eßer { 171*252884aeSStefan Eßer assert(BC_IS_BC); 172*252884aeSStefan Eßer vm.flags |= BC_FLAG_W; 173*252884aeSStefan Eßer break; 174*252884aeSStefan Eßer } 175*252884aeSStefan Eßer #endif // BC_ENABLED 176*252884aeSStefan Eßer 177*252884aeSStefan Eßer case 'V': 178*252884aeSStefan Eßer case 'v': 179*252884aeSStefan Eßer { 180*252884aeSStefan Eßer do_exit = version = true; 181*252884aeSStefan Eßer break; 182*252884aeSStefan Eßer } 183*252884aeSStefan Eßer 184*252884aeSStefan Eßer #if DC_ENABLED 185*252884aeSStefan Eßer case 'x': 186*252884aeSStefan Eßer { 187*252884aeSStefan Eßer assert(!BC_IS_BC); 188*252884aeSStefan Eßer vm.flags |= DC_FLAG_X; 189*252884aeSStefan Eßer break; 190*252884aeSStefan Eßer } 191*252884aeSStefan Eßer #endif // DC_ENABLED 192*252884aeSStefan Eßer 193*252884aeSStefan Eßer #ifndef NDEBUG 194*252884aeSStefan Eßer // We shouldn't get here because bc_opt_error()/bc_vm_error() should 195*252884aeSStefan Eßer // longjmp() out. 196*252884aeSStefan Eßer case '?': 197*252884aeSStefan Eßer case ':': 198*252884aeSStefan Eßer default: 199*252884aeSStefan Eßer { 200*252884aeSStefan Eßer abort(); 201*252884aeSStefan Eßer } 202*252884aeSStefan Eßer #endif // NDEBUG 203*252884aeSStefan Eßer } 204*252884aeSStefan Eßer } 205*252884aeSStefan Eßer 206*252884aeSStefan Eßer if (version) bc_vm_info(NULL); 207*252884aeSStefan Eßer if (do_exit) exit((int) vm.status); 208*252884aeSStefan Eßer if (vm.exprs.len > 1 || !BC_IS_BC) vm.flags |= BC_FLAG_Q; 209*252884aeSStefan Eßer 210*252884aeSStefan Eßer if (opts.optind < (size_t) argc) 211*252884aeSStefan Eßer bc_vec_init(&vm.files, sizeof(char*), NULL); 212*252884aeSStefan Eßer 213*252884aeSStefan Eßer for (i = opts.optind; i < (size_t) argc; ++i) 214*252884aeSStefan Eßer bc_vec_push(&vm.files, argv + i); 215*252884aeSStefan Eßer } 216