summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormillert <>2002-12-07 19:15:59 +0000
committermillert <>2002-12-07 19:15:59 +0000
commit5d713eb7eefea34a181f3908d1d6677902617067 (patch)
tree01e57a9a4e19bedc0829530d0a995db545834fc6 /src
parent27ad3c1b70e1ff5a88d4f7761f12549dd24f8d39 (diff)
downloadopenbsd-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.c77
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)
67static char *rcsid = "$OpenBSD: getopt_long.c,v 1.5 2002/12/06 16:03:29 millert Exp $"; 67static 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 */
179static int 178static int
180parse_long_options(char * const *nargv, const char *options, 179parse_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 }