diff options
author | millert <> | 2002-12-07 19:15:59 +0000 |
---|---|---|
committer | millert <> | 2002-12-07 19:15:59 +0000 |
commit | 5d713eb7eefea34a181f3908d1d6677902617067 (patch) | |
tree | 01e57a9a4e19bedc0829530d0a995db545834fc6 /src | |
parent | 27ad3c1b70e1ff5a88d4f7761f12549dd24f8d39 (diff) | |
download | openbsd-5d713eb7eefea34a181f3908d1d6677902617067.tar.gz openbsd-5d713eb7eefea34a181f3908d1d6677902617067.tar.bz2 openbsd-5d713eb7eefea34a181f3908d1d6677902617067.zip |
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 'src')
-rw-r--r-- | src/lib/libc/stdlib/getopt_long.c | 77 |
1 files changed, 36 insertions, 41 deletions
diff --git a/src/lib/libc/stdlib/getopt_long.c b/src/lib/libc/stdlib/getopt_long.c index 7674d4a1e4..7f6dc23c44 100644 --- a/src/lib/libc/stdlib/getopt_long.c +++ b/src/lib/libc/stdlib/getopt_long.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: getopt_long.c,v 1.5 2002/12/06 16:03:29 millert Exp $ */ | 1 | /* $OpenBSD: getopt_long.c,v 1.6 2002/12/07 19:15:59 millert Exp $ */ |
2 | /* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ | 2 | /* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ |
3 | 3 | ||
4 | /* | 4 | /* |
@@ -64,7 +64,7 @@ | |||
64 | */ | 64 | */ |
65 | 65 | ||
66 | #if defined(LIBC_SCCS) && !defined(lint) | 66 | #if defined(LIBC_SCCS) && !defined(lint) |
67 | static char *rcsid = "$OpenBSD: getopt_long.c,v 1.5 2002/12/06 16:03:29 millert Exp $"; | 67 | static char *rcsid = "$OpenBSD: getopt_long.c,v 1.6 2002/12/07 19:15:59 millert Exp $"; |
68 | #endif /* LIBC_SCCS and not lint */ | 68 | #endif /* LIBC_SCCS and not lint */ |
69 | 69 | ||
70 | #include <err.h> | 70 | #include <err.h> |
@@ -173,12 +173,11 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end, | |||
173 | /* | 173 | /* |
174 | * parse_long_options -- | 174 | * parse_long_options -- |
175 | * Parse long options in argc/argv argument vector. | 175 | * Parse long options in argc/argv argument vector. |
176 | * Returns -1 if long_only is set and the current option could be a short | 176 | * Returns -1 if short_too is set and the option does not match long_options. |
177 | * (single character) option instead. | ||
178 | */ | 177 | */ |
179 | static int | 178 | static int |
180 | parse_long_options(char * const *nargv, const char *options, | 179 | parse_long_options(char * const *nargv, const char *options, |
181 | const struct option *long_options, int *idx, int long_only) | 180 | const struct option *long_options, int *idx, int short_too) |
182 | { | 181 | { |
183 | char *current_argv, *has_equal; | 182 | char *current_argv, *has_equal; |
184 | size_t current_argv_len; | 183 | size_t current_argv_len; |
@@ -208,11 +207,10 @@ parse_long_options(char * const *nargv, const char *options, | |||
208 | break; | 207 | break; |
209 | } | 208 | } |
210 | /* | 209 | /* |
211 | * Don't try a partial match of a short option when in | 210 | * If this is a known short option, don't allow |
212 | * long_only mode. Otherwise there is a potential conflict | 211 | * a partial match of a single character. |
213 | * between partial matches and short options. | ||
214 | */ | 212 | */ |
215 | if (long_only && current_argv_len == 1) | 213 | if (short_too && current_argv_len == 1) |
216 | continue; | 214 | continue; |
217 | 215 | ||
218 | if (match == -1) /* partial match */ | 216 | if (match == -1) /* partial match */ |
@@ -273,7 +271,7 @@ parse_long_options(char * const *nargv, const char *options, | |||
273 | return (BADARG); | 271 | return (BADARG); |
274 | } | 272 | } |
275 | } else { /* unknown option */ | 273 | } else { /* unknown option */ |
276 | if (long_only) { | 274 | if (short_too) { |
277 | --optind; | 275 | --optind; |
278 | return (-1); | 276 | return (-1); |
279 | } | 277 | } |
@@ -300,8 +298,7 @@ getopt_internal(int nargc, char * const *nargv, const char *options, | |||
300 | const struct option *long_options, int *idx, int flags) | 298 | const struct option *long_options, int *idx, int flags) |
301 | { | 299 | { |
302 | char *oli; /* option letter list index */ | 300 | char *oli; /* option letter list index */ |
303 | int optchar; | 301 | int optchar, short_too; |
304 | int long_only; | ||
305 | static int posixly_correct = -1; | 302 | static int posixly_correct = -1; |
306 | 303 | ||
307 | optarg = NULL; | 304 | optarg = NULL; |
@@ -320,12 +317,13 @@ getopt_internal(int nargc, char * const *nargv, const char *options, | |||
320 | options++; | 317 | options++; |
321 | 318 | ||
322 | /* | 319 | /* |
323 | * XXX Some programs (like rsyncd) expect to be able to | 320 | * XXX Some GNU programs (like cvs) set optind to 0 instead of |
324 | * XXX re-initialize optind to 0 and have getopt_long(3) | 321 | * XXX using optreset. Work around this braindamage. |
325 | * XXX properly function again. Work around this braindamage. | ||
326 | */ | 322 | */ |
327 | if (optind == 0) | 323 | if (optind == 0) { |
328 | optind = 1; | 324 | optind = 1; |
325 | optreset = 1; | ||
326 | } | ||
329 | 327 | ||
330 | if (optreset) | 328 | if (optreset) |
331 | nonopt_start = nonopt_end = -1; | 329 | nonopt_start = nonopt_end = -1; |
@@ -384,7 +382,10 @@ start: | |||
384 | } | 382 | } |
385 | if (nonopt_start != -1 && nonopt_end == -1) | 383 | if (nonopt_start != -1 && nonopt_end == -1) |
386 | nonopt_end = optind; | 384 | nonopt_end = optind; |
387 | if (strcmp(place, "--") == 0) { | 385 | |
386 | /* check for "--" or "--foo" with no long options */ | ||
387 | if (*++place == '-' && | ||
388 | (place[1] == '\0' || long_options == NULL)) { | ||
388 | optind++; | 389 | optind++; |
389 | place = EMSG; | 390 | place = EMSG; |
390 | /* | 391 | /* |
@@ -399,38 +400,32 @@ start: | |||
399 | nonopt_start = nonopt_end = -1; | 400 | nonopt_start = nonopt_end = -1; |
400 | return (-1); | 401 | return (-1); |
401 | } | 402 | } |
402 | place++; | ||
403 | } | 403 | } |
404 | 404 | ||
405 | /* Check long options if we have any */ | 405 | /* check long options if we have any */ |
406 | long_only = 0; | 406 | if (long_options != NULL && |
407 | if (long_options != NULL) { | 407 | (*place == '-' || (flags & FLAG_LONGONLY))) { |
408 | if (*place == '-' || | 408 | short_too = 0; |
409 | (long_only = (flags & FLAG_LONGONLY))) { | 409 | if (*place == '-') |
410 | if (!long_only) | 410 | place++; /* --foo long option */ |
411 | place++; | 411 | else if (*place != ':' && strchr(options, optchar) != NULL) |
412 | optchar = parse_long_options(nargv, options, | 412 | short_too = 1; /* could be short option too */ |
413 | long_options, idx, long_only); | 413 | |
414 | if (optchar != -1) { | 414 | optchar = parse_long_options(nargv, options, long_options, |
415 | place = EMSG; | 415 | idx, short_too); |
416 | return (optchar); | 416 | if (optchar != -1) { |
417 | } | 417 | place = EMSG; |
418 | return (optchar); | ||
418 | } | 419 | } |
419 | } | 420 | } |
421 | |||
420 | if ((optchar = (int)*place++) == (int)':' || | 422 | if ((optchar = (int)*place++) == (int)':' || |
421 | (oli = strchr(options, optchar)) == NULL) { | 423 | (oli = strchr(options, optchar)) == NULL) { |
422 | /* option letter unknown or ':' */ | 424 | /* option letter unknown or ':' */ |
423 | if (PRINT_ERROR) { | 425 | if (!*place) |
424 | if (long_only) | ||
425 | warnx(illoptstring, place - 1); | ||
426 | else | ||
427 | warnx(illoptchar, optchar); | ||
428 | } | ||
429 | if (!*place || long_only) { | ||
430 | ++optind; | 426 | ++optind; |
431 | if (*place) | 427 | if (PRINT_ERROR) |
432 | place = EMSG; | 428 | warnx(illoptchar, optchar); |
433 | } | ||
434 | optopt = optchar; | 429 | optopt = optchar; |
435 | return (BADCH); | 430 | return (BADCH); |
436 | } | 431 | } |