diff options
Diffstat (limited to 'tools/fiptool/win_posix.c')
-rw-r--r-- | tools/fiptool/win_posix.c | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/tools/fiptool/win_posix.c b/tools/fiptool/win_posix.c new file mode 100644 index 0000000..33b44d4 --- /dev/null +++ b/tools/fiptool/win_posix.c @@ -0,0 +1,318 @@ +/* + * 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; +} |