123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318 |
- /*
- * Copyright (c) 2017 - 2020, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- #include <assert.h>
- #include "win_posix.h"
- /*
- * This variable is set by getopt to the index of the next element of the
- * argv array to be processed. Once getopt has found all of the option
- * arguments, you can use this variable to determine where the remaining
- * non-option arguments begin. The initial value of this variable is 1.
- */
- int optind = 1;
- /*
- * If the value of this variable is nonzero, then getopt prints an error
- * message to the standard error stream if it encounters an unknown option
- * default character or an option with a missing required argument.
- * If you set this variable to zero, getopt does not print any messages,
- * but it still returns the character ? to indicate an error.
- */
- const int opterr; /* = 0; */
- /* const because we do not implement error printing.*/
- /* Not initialised to conform with the coding standard. */
- /*
- * When getopt encounters an unknown option character or an option with a
- * missing required argument, it stores that option character in this
- * variable.
- */
- int optopt; /* = 0; */
- /*
- * This variable is set by getopt to point at the value of the option
- * argument, for those options that accept arguments.
- */
- char *optarg; /* = 0; */
- enum return_flags {
- RET_ERROR = -1,
- RET_END_OPT_LIST = -1,
- RET_NO_PARAM = '?',
- RET_NO_PARAM2 = ':',
- RET_UNKNOWN_OPT = '?'
- };
- /*
- * Common initialisation on entry.
- */
- static
- void getopt_init(void)
- {
- optarg = (char *)0;
- optopt = 0;
- /* optind may be zero with some POSIX uses.
- * For our purposes we just change it to 1.
- */
- if (optind == 0)
- optind = 1;
- }
- /*
- * Common handling for a single letter option.
- */
- static
- int getopt_1char(int argc,
- char *const argv[],
- const char *const opstring,
- const int optchar)
- {
- size_t nlen = (opstring == 0) ? 0 : strlen(opstring);
- size_t loptn;
- for (loptn = 0; loptn < nlen; loptn++) {
- if (optchar == opstring[loptn]) {
- if (opstring[loptn + 1] == ':') {
- /* Option has argument */
- if (optind < argc) {
- /* Found argument. */
- assert(argv != 0);
- optind++;
- optarg = argv[optind++];
- return optchar;
- }
- /* Missing argument. */
- if (opstring[loptn + 2] == ':') {
- /* OK if optional "x::". */
- optind++;
- return optchar;
- }
- /* Actual missing value. */
- optopt = optchar;
- return ((opstring[0] == ':')
- ? RET_NO_PARAM2
- : RET_NO_PARAM);
- }
- /* No argument, just return option char */
- optind++;
- return optchar;
- }
- }
- /*
- * If getopt finds an option character in argv that was not included in
- * options, ... it returns '?' and sets the external variable optopt to
- * the actual option character.
- */
- optopt = optchar;
- return RET_UNKNOWN_OPT;
- }
- int getopt(int argc,
- char *argv[],
- char *opstring)
- {
- int result = RET_END_OPT_LIST;
- size_t argn = 0;
- size_t nlen = strlen(opstring);
- getopt_init();
- /* If we have an argument left to play with */
- if ((argc > optind) && (argv != 0)) {
- const char *arg = (const char *)argv[optind];
- if ((arg != 0) && (arg[0] == '-'))
- result = getopt_1char(argc, argv, opstring, arg[1]);
- }
- return result;
- }
- /*
- * Match an argument value against an option name.
- * Note that we only match over the shorter length of the pair, to allow
- * for abbreviation or say --match=value
- * Long option names may be abbreviated if the abbreviation is unique or an
- * exact match for some defined option. This function does not check that the
- * abbreviations are unique and should be handled by the caller.
- * A long option may take a parameter, of the form --opt=param or --opt param.
- */
- static
- int optmatch(const char *argval, const char *optname)
- {
- int result = 0;
- while ((result == 0) && (*optname != 0) && (*argval != 0))
- result = (*argval++) - (*optname++);
- return result;
- }
- /* Handling for a single long option. */
- static
- int getopt_1long(const int argc,
- char *const argv[],
- const struct option *const longopts,
- const char *const optname,
- int *const indexptr)
- {
- int result = RET_UNKNOWN_OPT;
- size_t loptn = 0;
- bool match_found = false;
- /*
- * Long option names may be abbreviated if the abbreviation
- * is unique or an exact match for some defined option.
- * To handle this:
- * - First search for an exact match.
- * - If exact match was not found search for a abbreviated match.
- * By doing this an incorrect option selection can be avoided.
- */
- /* 1. Search for an exact match. */
- while (longopts[loptn].name != NULL) {
- if (strcmp(optname, longopts[loptn].name) == 0) {
- match_found = true;
- break;
- }
- ++loptn;
- }
- /* 2. If exact match was not found search for a abbreviated match. */
- if (!match_found) {
- loptn = 0;
- while (longopts[loptn].name != NULL) {
- if (optmatch(optname, longopts[loptn].name) == 0) {
- match_found = true;
- break;
- }
- ++loptn;
- }
- }
- if (match_found) {
- /* We found a match. */
- result = longopts[loptn].val;
- if (indexptr != 0) {
- *indexptr = loptn;
- }
- switch (longopts[loptn].has_arg) {
- case required_argument:
- if ((optind + 1) >= argc) {
- /* Missing argument. */
- optopt = result;
- return RET_NO_PARAM;
- }
- /* Fallthrough to get option value. */
- case optional_argument:
- if ((argc - optind) > 0) {
- /* Found argument. */
- optarg = argv[++optind];
- }
- /* Fallthrough to handle flag. */
- case no_argument:
- optind++;
- if (longopts[loptn].flag != 0) {
- *longopts[loptn].flag = result;
- result = 0;
- }
- break;
- }
- return result;
- }
- /*
- * If getopt finds an option character in argv that was not included
- * in options, ... it returns '?' and sets the external variable
- * optopt to the actual option character.
- */
- return RET_UNKNOWN_OPT;
- }
- /*
- * getopt_long gets the next option argument from the argument list
- * specified by the argv and argc arguments. Options may be either short
- * (single letter) as for getopt, or longer names (preceded by --).
- */
- int getopt_long(int argc,
- char *argv[],
- const char *shortopts,
- const struct option *longopts,
- int *indexptr)
- {
- int result = RET_END_OPT_LIST;
- getopt_init();
- /* If we have an argument left to play with */
- if ((argc > optind) && (argv != 0)) {
- const char *arg = argv[optind];
- if ((arg != 0) && (arg[0] == '-')) {
- if (arg[1] == '-') {
- /* Looks like a long option. */
- result = getopt_1long(argc,
- argv,
- longopts,
- &arg[2],
- indexptr);
- } else {
- result = getopt_1char(argc,
- argv,
- shortopts,
- arg[1]);
- }
- }
- }
- return result;
- }
- /*
- * getopt_long_only gets the next option argument from the argument list
- * specified by the argv and argc arguments. Options may be either short
- * or long as for getopt_long, but the long names may have a single '-'
- * prefix too.
- */
- int getopt_long_only(int argc,
- char *argv[],
- const char *shortopts,
- const struct option *longopts,
- int *indexptr)
- {
- int result = RET_END_OPT_LIST;
- getopt_init();
- /* If we have an argument left to play with */
- if ((argc > optind) && (argv != 0)) {
- const char *arg = argv[optind];
- if ((arg != 0) && (arg[0] == '-')) {
- if (arg[1] == '-') {
- /* Looks like a long option. */
- result = getopt_1long(argc,
- argv,
- longopts,
- &arg[2],
- indexptr);
- } else {
- result = getopt_1long(argc,
- argv,
- longopts,
- &arg[1],
- indexptr);
- if (result == RET_UNKNOWN_OPT) {
- result = getopt_1char(argc,
- argv,
- shortopts,
- arg[1]);
- }
- }
- }
- }
- return result;
- }
|