From 03be658a419a8c274591a469f55173b1971fff96 Mon Sep 17 00:00:00 2001 From: millert <> Date: Sat, 7 Dec 2002 19:15:59 +0000 Subject: [PATCH] For getopt_long_only() we *do* want to match single-character options as shortcuts for long ones, but only if this would not conflict with a short option in optstring. Now binutils gas works. --- src/lib/libc/stdlib/getopt_long.c | 77 +++++++++++++++---------------- 1 file changed, 36 insertions(+), 41 deletions(-) diff --git a/src/lib/libc/stdlib/getopt_long.c b/src/lib/libc/stdlib/getopt_long.c index 7674d4a1..7f6dc23c 100644 --- a/src/lib/libc/stdlib/getopt_long.c +++ b/src/lib/libc/stdlib/getopt_long.c @@ -1,4 +1,4 @@ -/* $OpenBSD: getopt_long.c,v 1.5 2002/12/06 16:03:29 millert Exp $ */ +/* $OpenBSD: getopt_long.c,v 1.6 2002/12/07 19:15:59 millert Exp $ */ /* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ /* @@ -64,7 +64,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char *rcsid = "$OpenBSD: getopt_long.c,v 1.5 2002/12/06 16:03:29 millert Exp $"; +static char *rcsid = "$OpenBSD: getopt_long.c,v 1.6 2002/12/07 19:15:59 millert Exp $"; #endif /* LIBC_SCCS and not lint */ #include @@ -173,12 +173,11 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end, /* * parse_long_options -- * Parse long options in argc/argv argument vector. - * Returns -1 if long_only is set and the current option could be a short - * (single character) option instead. + * Returns -1 if short_too is set and the option does not match long_options. */ static int parse_long_options(char * const *nargv, const char *options, - const struct option *long_options, int *idx, int long_only) + const struct option *long_options, int *idx, int short_too) { char *current_argv, *has_equal; size_t current_argv_len; @@ -208,11 +207,10 @@ parse_long_options(char * const *nargv, const char *options, break; } /* - * Don't try a partial match of a short option when in - * long_only mode. Otherwise there is a potential conflict - * between partial matches and short options. + * If this is a known short option, don't allow + * a partial match of a single character. */ - if (long_only && current_argv_len == 1) + if (short_too && current_argv_len == 1) continue; if (match == -1) /* partial match */ @@ -273,7 +271,7 @@ parse_long_options(char * const *nargv, const char *options, return (BADARG); } } else { /* unknown option */ - if (long_only) { + if (short_too) { --optind; return (-1); } @@ -300,8 +298,7 @@ getopt_internal(int nargc, char * const *nargv, const char *options, const struct option *long_options, int *idx, int flags) { char *oli; /* option letter list index */ - int optchar; - int long_only; + int optchar, short_too; static int posixly_correct = -1; optarg = NULL; @@ -320,12 +317,13 @@ getopt_internal(int nargc, char * const *nargv, const char *options, options++; /* - * XXX Some programs (like rsyncd) expect to be able to - * XXX re-initialize optind to 0 and have getopt_long(3) - * XXX properly function again. Work around this braindamage. + * XXX Some GNU programs (like cvs) set optind to 0 instead of + * XXX using optreset. Work around this braindamage. */ - if (optind == 0) + if (optind == 0) { optind = 1; + optreset = 1; + } if (optreset) nonopt_start = nonopt_end = -1; @@ -384,7 +382,10 @@ start: } if (nonopt_start != -1 && nonopt_end == -1) nonopt_end = optind; - if (strcmp(place, "--") == 0) { + + /* check for "--" or "--foo" with no long options */ + if (*++place == '-' && + (place[1] == '\0' || long_options == NULL)) { optind++; place = EMSG; /* @@ -399,38 +400,32 @@ start: nonopt_start = nonopt_end = -1; return (-1); } - place++; } - /* Check long options if we have any */ - long_only = 0; - if (long_options != NULL) { - if (*place == '-' || - (long_only = (flags & FLAG_LONGONLY))) { - if (!long_only) - place++; - optchar = parse_long_options(nargv, options, - long_options, idx, long_only); - if (optchar != -1) { - place = EMSG; - return (optchar); - } + /* check long options if we have any */ + if (long_options != NULL && + (*place == '-' || (flags & FLAG_LONGONLY))) { + short_too = 0; + if (*place == '-') + place++; /* --foo long option */ + else if (*place != ':' && strchr(options, optchar) != NULL) + short_too = 1; /* could be short option too */ + + optchar = parse_long_options(nargv, options, long_options, + idx, short_too); + if (optchar != -1) { + place = EMSG; + return (optchar); } } + if ((optchar = (int)*place++) == (int)':' || (oli = strchr(options, optchar)) == NULL) { /* option letter unknown or ':' */ - if (PRINT_ERROR) { - if (long_only) - warnx(illoptstring, place - 1); - else - warnx(illoptchar, optchar); - } - if (!*place || long_only) { + if (!*place) ++optind; - if (*place) - place = EMSG; - } + if (PRINT_ERROR) + warnx(illoptchar, optchar); optopt = optchar; return (BADCH); }