Browse Source

Fix two compatibility issues with our getopt_long_only() vs. the GNU version:

o Check for long options even when not at the beginning of an option.
For instance, if -a is a short option w/o an arg and -static is a
boolean long option then -astatic is valid for getopt_long_only().
o If a potential long argument does not match longopts and the first
character is not a short option, print a warning and skip the rest
of the argument.
Also clean up some trailing whitespace and change return value of
parse_long_options() from -2 to -1 when unmatched and in long_only mode.
With these fixes the binutils ld seems happy with our getopt_long_only()
OPENBSD_3_3
millert 22 years ago
parent
commit
def8d6bd9d
1 changed files with 61 additions and 28 deletions
  1. +61
    -28
      src/lib/libc/stdlib/getopt_long.c

+ 61
- 28
src/lib/libc/stdlib/getopt_long.c View File

@ -1,6 +1,32 @@
/* $OpenBSD: getopt_long.c,v 1.4 2002/12/05 22:26:04 millert Exp $ */
/* $OpenBSD: getopt_long.c,v 1.5 2002/12/06 16:03:29 millert Exp $ */
/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ /* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */
/*
* Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*- /*-
* Copyright (c) 2000 The NetBSD Foundation, Inc. * Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved. * All rights reserved.
@ -38,7 +64,7 @@
*/ */
#if defined(LIBC_SCCS) && !defined(lint) #if defined(LIBC_SCCS) && !defined(lint)
static char *rcsid = "$OpenBSD: getopt_long.c,v 1.4 2002/12/05 22:26:04 millert Exp $";
static char *rcsid = "$OpenBSD: getopt_long.c,v 1.5 2002/12/06 16:03:29 millert Exp $";
#endif /* LIBC_SCCS and not lint */ #endif /* LIBC_SCCS and not lint */
#include <err.h> #include <err.h>
@ -70,7 +96,7 @@ char *optarg; /* argument associated with option */
static int getopt_internal(int, char * const *, const char *, static int getopt_internal(int, char * const *, const char *,
const struct option *, int *, int); const struct option *, int *, int);
static int parse_long_options(int, char * const *, const char *,
static int parse_long_options(char * const *, const char *,
const struct option *, int *, int); const struct option *, int *, int);
static int gcd(int, int); static int gcd(int, int);
static void permute_args(int, int, int, char * const *); static void permute_args(int, int, int, char * const *);
@ -103,7 +129,7 @@ gcd(int a, int b)
b = c; b = c;
c = a % b; c = a % b;
} }
return (b); return (b);
} }
@ -147,11 +173,11 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
/* /*
* parse_long_options -- * parse_long_options --
* Parse long options in argc/argv argument vector. * Parse long options in argc/argv argument vector.
* Returns -2 if long_only is set and the current option could be a short
* Returns -1 if long_only is set and the current option could be a short
* (single character) option instead. * (single character) option instead.
*/ */
static int static int
parse_long_options(int nargc, char * const *nargv, const char *options,
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 long_only)
{ {
char *current_argv, *has_equal; char *current_argv, *has_equal;
@ -249,7 +275,7 @@ parse_long_options(int nargc, char * const *nargv, const char *options,
} else { /* unknown option */ } else { /* unknown option */
if (long_only) { if (long_only) {
--optind; --optind;
return (-2);
return (-1);
} }
if (PRINT_ERROR) if (PRINT_ERROR)
warnx(illoptstring, current_argv); warnx(illoptstring, current_argv);
@ -261,7 +287,7 @@ parse_long_options(int nargc, char * const *nargv, const char *options,
if (long_options[match].flag) { if (long_options[match].flag) {
*long_options[match].flag = long_options[match].val; *long_options[match].flag = long_options[match].val;
return (0); return (0);
} else
} else
return (long_options[match].val); return (long_options[match].val);
} }
@ -275,6 +301,7 @@ getopt_internal(int nargc, char * const *nargv, const char *options,
{ {
char *oli; /* option letter list index */ char *oli; /* option letter list index */
int optchar; int optchar;
int long_only;
static int posixly_correct = -1; static int posixly_correct = -1;
optarg = NULL; optarg = NULL;
@ -328,7 +355,7 @@ start:
place = EMSG; place = EMSG;
if (flags & FLAG_ALLARGS) { if (flags & FLAG_ALLARGS) {
/* /*
* GNU extension:
* GNU extension:
* return non-option as argument to option 1 * return non-option as argument to option 1
*/ */
optarg = nargv[optind++]; optarg = nargv[optind++];
@ -373,31 +400,37 @@ start:
return (-1); return (-1);
} }
place++; place++;
}
/* Check long options if we have any */
if (long_options != NULL) {
int long_only = 0;
if (*place == '-' ||
(long_only = (flags & FLAG_LONGONLY))) {
if (!long_only)
place++;
optchar = parse_long_options(nargc, nargv,
options, long_options, idx, long_only);
if (optchar != -2) {
place = EMSG;
return (optchar);
}
/* 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);
} }
} }
} }
if ((optchar = (int)*place++) == (int)':' || if ((optchar = (int)*place++) == (int)':' ||
(oli = strchr(options, optchar)) == NULL) { (oli = strchr(options, optchar)) == NULL) {
/* option letter unknown or ':' */ /* option letter unknown or ':' */
if (!*place)
if (PRINT_ERROR) {
if (long_only)
warnx(illoptstring, place - 1);
else
warnx(illoptchar, optchar);
}
if (!*place || long_only) {
++optind; ++optind;
if (PRINT_ERROR)
warnx(illoptchar, optchar);
if (*place)
place = EMSG;
}
optopt = optchar; optopt = optchar;
return (BADCH); return (BADCH);
} }
@ -413,8 +446,8 @@ start:
return (BADARG); return (BADARG);
} else /* white space */ } else /* white space */
place = nargv[optind]; place = nargv[optind];
optchar = parse_long_options(nargc, nargv, options,
long_options, idx, 0);
optchar = parse_long_options(nargv, options, long_options,
idx, 0);
place = EMSG; place = EMSG;
return (optchar); return (optchar);
} }


Loading…
Cancel
Save