[syslinux:master] com32: update getopt() to the current version from klibc

syslinux-bot for H. Peter Anvin hpa at zytor.com
Fri Jul 2 18:03:18 PDT 2010


Commit-ID:  c8c991a6a094f4678e7f9b36faf1fb0534328fc1
Gitweb:     http://syslinux.zytor.com/commit/c8c991a6a094f4678e7f9b36faf1fb0534328fc1
Author:     H. Peter Anvin <hpa at zytor.com>
AuthorDate: Fri, 2 Jul 2010 18:00:42 -0700
Committer:  H. Peter Anvin <hpa at zytor.com>
CommitDate: Fri, 2 Jul 2010 18:00:42 -0700

com32: update getopt() to the current version from klibc

Update getopt() to the current klibc version.

Signed-off-by: H. Peter Anvin <hpa at zytor.com>


---
 com32/lib/getopt.c |  117 +++++++++++++++++++++++++++++++--------------------
 1 files 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 <string.h>
 
 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 '?';
-    }
 }



More information about the Syslinux-commits mailing list