From c8c991a6a094f4678e7f9b36faf1fb0534328fc1 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 2 Jul 2010 18:00:42 -0700 Subject: [PATCH] com32: update getopt() to the current version from klibc Update getopt() to the current klibc version. Signed-off-by: H. Peter Anvin --- com32/lib/getopt.c | 117 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 71 insertions(+), 46 deletions(-) diff --git a/com32/lib/getopt.c b/com32/lib/getopt.c index 5e9b7c6..806735d 100644 --- a/com32/lib/getopt.c +++ b/com32/lib/getopt.c @@ -9,64 +9,89 @@ #include char *optarg; -int optind = 1; -int opterr, optopt; -static const char *__optptr; +int optind, opterr, optopt; +static struct getopt_private_state { + const char *optptr; + const char *last_optstring; + char *const *last_argv; +} pvt; int getopt(int argc, char *const *argv, const char *optstring) { - const char *carg = argv[optind]; - const char *osptr; - int opt; + const char *carg; + const char *osptr; + int opt; - /* We don't actually need argc */ - (void)argc; + /* getopt() relies on a number of different global state + variables, which can make this really confusing if there is + more than one use of getopt() in the same program. This + attempts to detect that situation by detecting if the + "optstring" or "argv" argument have changed since last time + we were called; if so, reinitialize the query state. */ - /* First, eliminate all non-option cases */ - - if (!carg || carg[0] != '-' || !carg[1]) { - return -1; - } + if (optstring != pvt.last_optstring || argv != pvt.last_argv || + optind < 1 || optind > argc) { + /* optind doesn't match the current query */ + pvt.last_optstring = optstring; + pvt.last_argv = argv; + optind = 1; + pvt.optptr = NULL; + } - if (carg[1] == '-' && !carg[2]) { - optind++; - return -1; - } + carg = argv[optind]; - if ((uintptr_t) (__optptr - carg) > (uintptr_t) strlen(carg)) - __optptr = carg + 1; /* Someone frobbed optind, change to new opt. */ + /* First, eliminate all non-option cases */ - opt = *__optptr++; + if (!carg || carg[0] != '-' || !carg[1]) { + return -1; + } - if (opt != ':' && (osptr = strchr(optstring, opt))) { - if (osptr[1] == ':') { - if (*__optptr) { - /* Argument-taking option with attached argument */ - optarg = (char *)__optptr; + if (carg[1] == '-' && !carg[2]) { optind++; - } else { - /* Argument-taking option with non-attached argument */ - if (argv[optind + 1]) { - optarg = (char *)argv[optind + 1]; - optind += 2; + return -1; + } + + if ((uintptr_t) (pvt.optptr - carg) > (uintptr_t) strlen(carg)) { + /* Someone frobbed optind, change to new opt. */ + pvt.optptr = carg + 1; + } + + opt = *pvt.optptr++; + + if (opt != ':' && (osptr = strchr(optstring, opt))) { + if (osptr[1] == ':') { + if (*pvt.optptr) { + /* Argument-taking option with attached + argument */ + optarg = (char *)pvt.optptr; + optind++; + } else { + /* Argument-taking option with non-attached + argument */ + if (argv[optind + 1]) { + optarg = (char *)argv[optind+1]; + optind += 2; + } else { + /* Missing argument */ + optind++; + return (optstring[0] == ':') + ? ':' : '?'; + } + } + return opt; } else { - /* Missing argument */ - return (optstring[0] == ':') ? ':' : '?'; + /* Non-argument-taking option */ + /* pvt.optptr will remember the exact position to + resume at */ + if (!*pvt.optptr) + optind++; + return opt; } - } - return opt; } else { - /* Non-argument-taking option */ - /* __optptr will remember the exact position to resume at */ - if (!*__optptr) - optind++; - return opt; + /* Unknown option */ + optopt = opt; + if (!*pvt.optptr) + optind++; + return '?'; } - } else { - /* Unknown option */ - optopt = opt; - if (!*__optptr) - optind++; - return '?'; - } } -- 2.7.4