1*a1ee3836SEvan Lloyd /* 2*a1ee3836SEvan Lloyd * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. 3*a1ee3836SEvan Lloyd * 4*a1ee3836SEvan Lloyd * SPDX-License-Identifier: BSD-3-Clause 5*a1ee3836SEvan Lloyd */ 6*a1ee3836SEvan Lloyd 7*a1ee3836SEvan Lloyd #include <assert.h> 8*a1ee3836SEvan Lloyd 9*a1ee3836SEvan Lloyd #include "win_posix.h" 10*a1ee3836SEvan Lloyd 11*a1ee3836SEvan Lloyd /* 12*a1ee3836SEvan Lloyd * This variable is set by getopt to the index of the next element of the 13*a1ee3836SEvan Lloyd * argv array to be processed. Once getopt has found all of the option 14*a1ee3836SEvan Lloyd * arguments, you can use this variable to determine where the remaining 15*a1ee3836SEvan Lloyd * non-option arguments begin. The initial value of this variable is 1. 16*a1ee3836SEvan Lloyd */ 17*a1ee3836SEvan Lloyd int optind = 1; 18*a1ee3836SEvan Lloyd 19*a1ee3836SEvan Lloyd /* 20*a1ee3836SEvan Lloyd * If the value of this variable is nonzero, then getopt prints an error 21*a1ee3836SEvan Lloyd * message to the standard error stream if it encounters an unknown option 22*a1ee3836SEvan Lloyd * default character or an option with a missing required argument. 23*a1ee3836SEvan Lloyd * If you set this variable to zero, getopt does not print any messages, 24*a1ee3836SEvan Lloyd * but it still returns the character ? to indicate an error. 25*a1ee3836SEvan Lloyd */ 26*a1ee3836SEvan Lloyd const int opterr; /* = 0; */ 27*a1ee3836SEvan Lloyd /* const because we do not implement error printing.*/ 28*a1ee3836SEvan Lloyd /* Not initialised to conform with the coding standard. */ 29*a1ee3836SEvan Lloyd 30*a1ee3836SEvan Lloyd /* 31*a1ee3836SEvan Lloyd * When getopt encounters an unknown option character or an option with a 32*a1ee3836SEvan Lloyd * missing required argument, it stores that option character in this 33*a1ee3836SEvan Lloyd * variable. 34*a1ee3836SEvan Lloyd */ 35*a1ee3836SEvan Lloyd int optopt; /* = 0; */ 36*a1ee3836SEvan Lloyd 37*a1ee3836SEvan Lloyd /* 38*a1ee3836SEvan Lloyd * This variable is set by getopt to point at the value of the option 39*a1ee3836SEvan Lloyd * argument, for those options that accept arguments. 40*a1ee3836SEvan Lloyd */ 41*a1ee3836SEvan Lloyd char *optarg; /* = 0; */ 42*a1ee3836SEvan Lloyd 43*a1ee3836SEvan Lloyd enum return_flags { 44*a1ee3836SEvan Lloyd RET_ERROR = -1, 45*a1ee3836SEvan Lloyd RET_END_OPT_LIST = -1, 46*a1ee3836SEvan Lloyd RET_NO_PARAM = '?', 47*a1ee3836SEvan Lloyd RET_NO_PARAM2 = ':', 48*a1ee3836SEvan Lloyd RET_UNKNOWN_OPT = '?' 49*a1ee3836SEvan Lloyd }; 50*a1ee3836SEvan Lloyd 51*a1ee3836SEvan Lloyd /* 52*a1ee3836SEvan Lloyd * Common initialisation on entry. 53*a1ee3836SEvan Lloyd */ 54*a1ee3836SEvan Lloyd static 55*a1ee3836SEvan Lloyd void getopt_init(void) 56*a1ee3836SEvan Lloyd { 57*a1ee3836SEvan Lloyd optarg = (char *)0; 58*a1ee3836SEvan Lloyd optopt = 0; 59*a1ee3836SEvan Lloyd /* optind may be zero with some POSIX uses. 60*a1ee3836SEvan Lloyd * For our purposes we just change it to 1. 61*a1ee3836SEvan Lloyd */ 62*a1ee3836SEvan Lloyd if (optind == 0) 63*a1ee3836SEvan Lloyd optind = 1; 64*a1ee3836SEvan Lloyd } 65*a1ee3836SEvan Lloyd 66*a1ee3836SEvan Lloyd /* 67*a1ee3836SEvan Lloyd * Common handling for a single letter option. 68*a1ee3836SEvan Lloyd */ 69*a1ee3836SEvan Lloyd static 70*a1ee3836SEvan Lloyd int getopt_1char(int argc, 71*a1ee3836SEvan Lloyd char *const argv[], 72*a1ee3836SEvan Lloyd const char *const opstring, 73*a1ee3836SEvan Lloyd const int optchar) 74*a1ee3836SEvan Lloyd { 75*a1ee3836SEvan Lloyd size_t nlen = (opstring == 0) ? 0 : strlen(opstring); 76*a1ee3836SEvan Lloyd size_t loptn; 77*a1ee3836SEvan Lloyd 78*a1ee3836SEvan Lloyd for (loptn = 0; loptn < nlen; loptn++) { 79*a1ee3836SEvan Lloyd if (optchar == opstring[loptn]) { 80*a1ee3836SEvan Lloyd if (opstring[loptn + 1] == ':') { 81*a1ee3836SEvan Lloyd /* Option has argument */ 82*a1ee3836SEvan Lloyd if (optind < argc) { 83*a1ee3836SEvan Lloyd /* Found argument. */ 84*a1ee3836SEvan Lloyd assert(argv != 0); 85*a1ee3836SEvan Lloyd optind++; 86*a1ee3836SEvan Lloyd optarg = argv[optind++]; 87*a1ee3836SEvan Lloyd return optchar; 88*a1ee3836SEvan Lloyd } 89*a1ee3836SEvan Lloyd /* Missing argument. */ 90*a1ee3836SEvan Lloyd if (opstring[loptn + 2] == ':') { 91*a1ee3836SEvan Lloyd /* OK if optional "x::". */ 92*a1ee3836SEvan Lloyd optind++; 93*a1ee3836SEvan Lloyd return optchar; 94*a1ee3836SEvan Lloyd } 95*a1ee3836SEvan Lloyd /* Actual missing value. */ 96*a1ee3836SEvan Lloyd optopt = optchar; 97*a1ee3836SEvan Lloyd return ((opstring[0] == ':') 98*a1ee3836SEvan Lloyd ? RET_NO_PARAM2 99*a1ee3836SEvan Lloyd : RET_NO_PARAM); 100*a1ee3836SEvan Lloyd } 101*a1ee3836SEvan Lloyd /* No argument, just return option char */ 102*a1ee3836SEvan Lloyd optind++; 103*a1ee3836SEvan Lloyd return optchar; 104*a1ee3836SEvan Lloyd } 105*a1ee3836SEvan Lloyd } 106*a1ee3836SEvan Lloyd /* 107*a1ee3836SEvan Lloyd * If getopt finds an option character in argv that was not included in 108*a1ee3836SEvan Lloyd * options, ... it returns '?' and sets the external variable optopt to 109*a1ee3836SEvan Lloyd * the actual option character. 110*a1ee3836SEvan Lloyd */ 111*a1ee3836SEvan Lloyd optopt = optchar; 112*a1ee3836SEvan Lloyd return RET_UNKNOWN_OPT; 113*a1ee3836SEvan Lloyd } 114*a1ee3836SEvan Lloyd 115*a1ee3836SEvan Lloyd int getopt(int argc, 116*a1ee3836SEvan Lloyd char *argv[], 117*a1ee3836SEvan Lloyd char *opstring) 118*a1ee3836SEvan Lloyd { 119*a1ee3836SEvan Lloyd int result = RET_END_OPT_LIST; 120*a1ee3836SEvan Lloyd size_t argn = 0; 121*a1ee3836SEvan Lloyd size_t nlen = strlen(opstring); 122*a1ee3836SEvan Lloyd 123*a1ee3836SEvan Lloyd getopt_init(); 124*a1ee3836SEvan Lloyd /* If we have an argument left to play with */ 125*a1ee3836SEvan Lloyd if ((argc > optind) && (argv != 0)) { 126*a1ee3836SEvan Lloyd const char *arg = (const char *)argv[optind]; 127*a1ee3836SEvan Lloyd 128*a1ee3836SEvan Lloyd if ((arg != 0) && (arg[0] == '-')) 129*a1ee3836SEvan Lloyd result = getopt_1char(argc, argv, opstring, arg[1]); 130*a1ee3836SEvan Lloyd } 131*a1ee3836SEvan Lloyd 132*a1ee3836SEvan Lloyd return result; 133*a1ee3836SEvan Lloyd } 134*a1ee3836SEvan Lloyd 135*a1ee3836SEvan Lloyd /* 136*a1ee3836SEvan Lloyd * Match an argument value against an option name. 137*a1ee3836SEvan Lloyd * Note that we only match over the shorter length of the pair, to allow 138*a1ee3836SEvan Lloyd * for abbreviation or say --match=value 139*a1ee3836SEvan Lloyd * Long option names may be abbreviated if the abbreviation is unique or an 140*a1ee3836SEvan Lloyd * exact match for some defined option. 141*a1ee3836SEvan Lloyd * A long option may take a parameter, of the form --opt=param or --opt param. 142*a1ee3836SEvan Lloyd */ 143*a1ee3836SEvan Lloyd static 144*a1ee3836SEvan Lloyd int optmatch(const char *argval, const char *optname) 145*a1ee3836SEvan Lloyd { 146*a1ee3836SEvan Lloyd int result = 0; 147*a1ee3836SEvan Lloyd 148*a1ee3836SEvan Lloyd while ((result == 0) && (*optname != 0) && (*argval != 0)) 149*a1ee3836SEvan Lloyd result = (*argval++) - (*optname++); 150*a1ee3836SEvan Lloyd return result; 151*a1ee3836SEvan Lloyd } 152*a1ee3836SEvan Lloyd 153*a1ee3836SEvan Lloyd /* Handling for a single long option. */ 154*a1ee3836SEvan Lloyd static 155*a1ee3836SEvan Lloyd int getopt_1long(const int argc, 156*a1ee3836SEvan Lloyd char *const argv[], 157*a1ee3836SEvan Lloyd const struct option *const longopts, 158*a1ee3836SEvan Lloyd const char *const optname, 159*a1ee3836SEvan Lloyd int *const indexptr) 160*a1ee3836SEvan Lloyd { 161*a1ee3836SEvan Lloyd int result = RET_UNKNOWN_OPT; 162*a1ee3836SEvan Lloyd size_t loptn = 0; 163*a1ee3836SEvan Lloyd 164*a1ee3836SEvan Lloyd while (longopts[loptn].name != 0) { 165*a1ee3836SEvan Lloyd if (optmatch(optname, longopts[loptn].name) == 0) { 166*a1ee3836SEvan Lloyd /* We found a match. */ 167*a1ee3836SEvan Lloyd result = longopts[loptn].val; 168*a1ee3836SEvan Lloyd if (indexptr != 0) 169*a1ee3836SEvan Lloyd *indexptr = loptn; 170*a1ee3836SEvan Lloyd switch (longopts[loptn].has_arg) { 171*a1ee3836SEvan Lloyd case required_argument: 172*a1ee3836SEvan Lloyd if ((optind + 1) >= argc) { 173*a1ee3836SEvan Lloyd /* Missing argument. */ 174*a1ee3836SEvan Lloyd optopt = result; 175*a1ee3836SEvan Lloyd return RET_NO_PARAM; 176*a1ee3836SEvan Lloyd } 177*a1ee3836SEvan Lloyd /* Fallthrough to get option value. */ 178*a1ee3836SEvan Lloyd 179*a1ee3836SEvan Lloyd case optional_argument: 180*a1ee3836SEvan Lloyd if ((argc - optind) > 0) { 181*a1ee3836SEvan Lloyd /* Found argument. */ 182*a1ee3836SEvan Lloyd optarg = argv[++optind]; 183*a1ee3836SEvan Lloyd } 184*a1ee3836SEvan Lloyd /* Fallthrough to handle flag. */ 185*a1ee3836SEvan Lloyd 186*a1ee3836SEvan Lloyd case no_argument: 187*a1ee3836SEvan Lloyd optind++; 188*a1ee3836SEvan Lloyd if (longopts[loptn].flag != 0) { 189*a1ee3836SEvan Lloyd *longopts[loptn].flag = result; 190*a1ee3836SEvan Lloyd result = 0; 191*a1ee3836SEvan Lloyd } 192*a1ee3836SEvan Lloyd break; 193*a1ee3836SEvan Lloyd 194*a1ee3836SEvan Lloyd } 195*a1ee3836SEvan Lloyd return result; 196*a1ee3836SEvan Lloyd } 197*a1ee3836SEvan Lloyd ++loptn; 198*a1ee3836SEvan Lloyd } 199*a1ee3836SEvan Lloyd /* 200*a1ee3836SEvan Lloyd * If getopt finds an option character in argv that was not included 201*a1ee3836SEvan Lloyd * in options, ... it returns '?' and sets the external variable 202*a1ee3836SEvan Lloyd * optopt to the actual option character. 203*a1ee3836SEvan Lloyd */ 204*a1ee3836SEvan Lloyd return RET_UNKNOWN_OPT; 205*a1ee3836SEvan Lloyd } 206*a1ee3836SEvan Lloyd 207*a1ee3836SEvan Lloyd /* 208*a1ee3836SEvan Lloyd * getopt_long gets the next option argument from the argument list 209*a1ee3836SEvan Lloyd * specified by the argv and argc arguments. Options may be either short 210*a1ee3836SEvan Lloyd * (single letter) as for getopt, or longer names (preceded by --). 211*a1ee3836SEvan Lloyd */ 212*a1ee3836SEvan Lloyd int getopt_long(int argc, 213*a1ee3836SEvan Lloyd char *argv[], 214*a1ee3836SEvan Lloyd const char *shortopts, 215*a1ee3836SEvan Lloyd const struct option *longopts, 216*a1ee3836SEvan Lloyd int *indexptr) 217*a1ee3836SEvan Lloyd { 218*a1ee3836SEvan Lloyd int result = RET_END_OPT_LIST; 219*a1ee3836SEvan Lloyd 220*a1ee3836SEvan Lloyd getopt_init(); 221*a1ee3836SEvan Lloyd /* If we have an argument left to play with */ 222*a1ee3836SEvan Lloyd if ((argc > optind) && (argv != 0)) { 223*a1ee3836SEvan Lloyd const char *arg = argv[optind]; 224*a1ee3836SEvan Lloyd 225*a1ee3836SEvan Lloyd if ((arg != 0) && (arg[0] == '-')) { 226*a1ee3836SEvan Lloyd if (arg[1] == '-') { 227*a1ee3836SEvan Lloyd /* Looks like a long option. */ 228*a1ee3836SEvan Lloyd result = getopt_1long(argc, 229*a1ee3836SEvan Lloyd argv, 230*a1ee3836SEvan Lloyd longopts, 231*a1ee3836SEvan Lloyd &arg[2], 232*a1ee3836SEvan Lloyd indexptr); 233*a1ee3836SEvan Lloyd } else { 234*a1ee3836SEvan Lloyd result = getopt_1char(argc, 235*a1ee3836SEvan Lloyd argv, 236*a1ee3836SEvan Lloyd shortopts, 237*a1ee3836SEvan Lloyd arg[1]); 238*a1ee3836SEvan Lloyd } 239*a1ee3836SEvan Lloyd } 240*a1ee3836SEvan Lloyd } 241*a1ee3836SEvan Lloyd return result; 242*a1ee3836SEvan Lloyd } 243*a1ee3836SEvan Lloyd 244*a1ee3836SEvan Lloyd /* 245*a1ee3836SEvan Lloyd * getopt_long_only gets the next option argument from the argument list 246*a1ee3836SEvan Lloyd * specified by the argv and argc arguments. Options may be either short 247*a1ee3836SEvan Lloyd * or long as for getopt_long, but the long names may have a single '-' 248*a1ee3836SEvan Lloyd * prefix too. 249*a1ee3836SEvan Lloyd */ 250*a1ee3836SEvan Lloyd int getopt_long_only(int argc, 251*a1ee3836SEvan Lloyd char *argv[], 252*a1ee3836SEvan Lloyd const char *shortopts, 253*a1ee3836SEvan Lloyd const struct option *longopts, 254*a1ee3836SEvan Lloyd int *indexptr) 255*a1ee3836SEvan Lloyd { 256*a1ee3836SEvan Lloyd int result = RET_END_OPT_LIST; 257*a1ee3836SEvan Lloyd 258*a1ee3836SEvan Lloyd getopt_init(); 259*a1ee3836SEvan Lloyd /* If we have an argument left to play with */ 260*a1ee3836SEvan Lloyd if ((argc > optind) && (argv != 0)) { 261*a1ee3836SEvan Lloyd const char *arg = argv[optind]; 262*a1ee3836SEvan Lloyd 263*a1ee3836SEvan Lloyd if ((arg != 0) && (arg[0] == '-')) { 264*a1ee3836SEvan Lloyd if (arg[1] == '-') { 265*a1ee3836SEvan Lloyd /* Looks like a long option. */ 266*a1ee3836SEvan Lloyd result = getopt_1long(argc, 267*a1ee3836SEvan Lloyd argv, 268*a1ee3836SEvan Lloyd longopts, 269*a1ee3836SEvan Lloyd &arg[2], 270*a1ee3836SEvan Lloyd indexptr); 271*a1ee3836SEvan Lloyd } else { 272*a1ee3836SEvan Lloyd result = getopt_1long(argc, 273*a1ee3836SEvan Lloyd argv, 274*a1ee3836SEvan Lloyd longopts, 275*a1ee3836SEvan Lloyd &arg[1], 276*a1ee3836SEvan Lloyd indexptr); 277*a1ee3836SEvan Lloyd if (result == RET_UNKNOWN_OPT) { 278*a1ee3836SEvan Lloyd result = getopt_1char(argc, 279*a1ee3836SEvan Lloyd argv, 280*a1ee3836SEvan Lloyd shortopts, 281*a1ee3836SEvan Lloyd arg[1]); 282*a1ee3836SEvan Lloyd } 283*a1ee3836SEvan Lloyd } 284*a1ee3836SEvan Lloyd } 285*a1ee3836SEvan Lloyd } 286*a1ee3836SEvan Lloyd return result; 287*a1ee3836SEvan Lloyd } 288