summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2002-12-07 19:16:00 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2002-12-07 19:16:00 +0000
commit73616ca407e72a16e7a681ad3110749fbf014961 (patch)
treeafb89ca35a927b6acc06ddc65c4ac90cceffd1c8 /lib
parentf799b5fa73a85d905541af837a1c0e3caf673a04 (diff)
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.
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/stdlib/getopt_long.c77
1 files changed, 36 insertions, 41 deletions
diff --git a/lib/libc/stdlib/getopt_long.c b/lib/libc/stdlib/getopt_long.c
index 7674d4a1e48..7f6dc23c448 100644
--- a/lib/libc/stdlib/getopt_long.c
+++ b/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 <err.h>
@@ -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);
}