2004-03-08  Paul Eggert  <eggert@cs.ucla.edu>

	Merge from gnulib.  We now assume C89 or better.
	* posix/getopt1.c (const): Remove.
	* posix/getopt.c (const): Likewise.
	* posix/getopt1.c (getopt_long, _getopt_long_r, getopt_long_only,
	_getopt_long_only_r, main): Use prototypes, not old-style definitions.
	* posix/getopt.c (exchange, _getopt_initialize, _getopt_internal_r,
	_getopt_internal, getopt, main): Likewise.
	* posix/getopt.h (getopt, getopt_long, getopt_long_only): Likewise.
	* posix/getopt.c [!defined VMS || !HAVE_STRING_H]:
	Include <string.h> regardless.  No need for <strings.h>.
	[!defined _LIBC]: Include "gettext.h" rather than rolling it ourselves.
	(_): Define to gettext always.
	(my_index): Remove: all uses changed to strchr.
	(strlen): Remove declaration.
	* posix/getopt.h (struct option.name): Always const char *.

2004-03-08  Marcus Brinkmann  <marcus@gnu.org>

	* posix/getopt.h (_getopt_internal): Move to ...
	* posix/getopt_int.h: ... here.  New file.
	* include/getopt_int.h: New file.
	* include/getopt.h: Remove libc_hidden_proto for getopt_long
	and getopt_long_only.
	* posix/getopt1.c: Include "getopt_int.h".  Remove
	libc_hidden_def for getopt_long and getopt_long_only.
	(_getopt_long_r, _getopt_long_only_r): New functions.
	* posix/getopt.c: Include "getopt_int.h".
	(__getopt_initialized): Variable removed.
	(nextchar, ordering, posixly_correct, first_nonopt, last_nonopt):
	Static variables removed.
	(nonoption_flags_max_len, nonoption_flags_len) [_LIBC &&
	USE_NONOPTION_FLAGS]: Static variables removed.
	(getopt_data): New static variable.
	(SWAP_FLAGS): Use d->__nonoption_flags_len instead
	nonoption_flags_len.
	(exchange): Add new argument D of type struct getopt_data *.
	Replace optind with d->optind, optarg with d->optarg, opterr with
	d->opterr, optopt with d->optopt, nextchar with d->__nextchar,
	first_nonopt with d->__first_nonopt, last_nonopt with
	d->__last_nonopt, d->ordering with d->__ordering,
	d->posixly_correct with d->__posixly_correct (which is now an
	int instead a string, so fix users), nonoption_flags_len
	with d->__nonoption_flags_len, nonoption_flags_max_len with
	d->__nonoption_flags_max_len.
	(_getopt_initialize): Likewise.
	(_getopt_internal): Rename to ...
	(_getopt_internal_r): ... this.  Also add new argument D of type
	struct getopt_data * and use of members of D rather than global or
	static variables as described for exchange() above.  Add new argument
	to invocations of _getopt_initialize and exchange.
	(_getopt_internal): Reimplement in terms of _getopt_internal_r.
	* argp/argp-parse.c: Include <getopt_int.h>.
	[_LIBC]: Do not include <bits/libc-lock.h>.
	[!_LIBC && HAVE_CTHREADS_H]: Do not include <cthreads.h>.
	[!_LIBC] (_argp_hang): Make static.
	(getopt_lock, LOCK_GETOPT, UNLOCK_GETOPT): Remove.
	(_argp_unlock_xxx): Remove.
	(parser_init): Do not use LOCK_GETOPT.
	(parser_finalize): Do not use UNLOCK_GETOPT.
	(struct parser): New member OPT_DATA.
	(parser_init): Initialize parser->opt_data.  Use
	parser->opt_data.opterr instead of opterr.
	(parser_parse_opt): Use parser->opt_data.optarg instead optarg.
	(parser_parse_next): Likewise.  Use parser->opt_data.optind
	instead optind.  Use parser->opt_data.optopt instead of optopt.
	Call _getopt_long_only_r and _getopt_long_r instead of
	getopt_long_only and getopt_long, and pass the extra argument.
This commit is contained in:
Ulrich Drepper 2004-03-09 10:36:53 +00:00
parent db30e3097a
commit 511676f708
8 changed files with 452 additions and 424 deletions

View file

@ -1,3 +1,73 @@
2004-03-08 Paul Eggert <eggert@cs.ucla.edu>
Merge from gnulib. We now assume C89 or better.
* posix/getopt1.c (const): Remove.
* posix/getopt.c (const): Likewise.
* posix/getopt1.c (getopt_long, _getopt_long_r, getopt_long_only,
_getopt_long_only_r, main): Use prototypes, not old-style definitions.
* posix/getopt.c (exchange, _getopt_initialize, _getopt_internal_r,
_getopt_internal, getopt, main): Likewise.
* posix/getopt.h (getopt, getopt_long, getopt_long_only): Likewise.
* posix/getopt.c [!defined VMS || !HAVE_STRING_H]:
Include <string.h> regardless. No need for <strings.h>.
[!defined _LIBC]: Include "gettext.h" rather than rolling it ourselves.
(_): Define to gettext always.
(my_index): Remove: all uses changed to strchr.
(strlen): Remove declaration.
* posix/getopt.h (struct option.name): Always const char *.
2004-03-08 Marcus Brinkmann <marcus@gnu.org>
* posix/getopt.h (_getopt_internal): Move to ...
* posix/getopt_int.h: ... here. New file.
* include/getopt_int.h: New file.
* include/getopt.h: Remove libc_hidden_proto for getopt_long
and getopt_long_only.
* posix/getopt1.c: Include "getopt_int.h". Remove
libc_hidden_def for getopt_long and getopt_long_only.
(_getopt_long_r, _getopt_long_only_r): New functions.
* posix/getopt.c: Include "getopt_int.h".
(__getopt_initialized): Variable removed.
(nextchar, ordering, posixly_correct, first_nonopt, last_nonopt):
Static variables removed.
(nonoption_flags_max_len, nonoption_flags_len) [_LIBC &&
USE_NONOPTION_FLAGS]: Static variables removed.
(getopt_data): New static variable.
(SWAP_FLAGS): Use d->__nonoption_flags_len instead
nonoption_flags_len.
(exchange): Add new argument D of type struct getopt_data *.
Replace optind with d->optind, optarg with d->optarg, opterr with
d->opterr, optopt with d->optopt, nextchar with d->__nextchar,
first_nonopt with d->__first_nonopt, last_nonopt with
d->__last_nonopt, d->ordering with d->__ordering,
d->posixly_correct with d->__posixly_correct (which is now an
int instead a string, so fix users), nonoption_flags_len
with d->__nonoption_flags_len, nonoption_flags_max_len with
d->__nonoption_flags_max_len.
(_getopt_initialize): Likewise.
(_getopt_internal): Rename to ...
(_getopt_internal_r): ... this. Also add new argument D of type
struct getopt_data * and use of members of D rather than global or
static variables as described for exchange() above. Add new argument
to invocations of _getopt_initialize and exchange.
(_getopt_internal): Reimplement in terms of _getopt_internal_r.
* argp/argp-parse.c: Include <getopt_int.h>.
[_LIBC]: Do not include <bits/libc-lock.h>.
[!_LIBC && HAVE_CTHREADS_H]: Do not include <cthreads.h>.
[!_LIBC] (_argp_hang): Make static.
(getopt_lock, LOCK_GETOPT, UNLOCK_GETOPT): Remove.
(_argp_unlock_xxx): Remove.
(parser_init): Do not use LOCK_GETOPT.
(parser_finalize): Do not use UNLOCK_GETOPT.
(struct parser): New member OPT_DATA.
(parser_init): Initialize parser->opt_data. Use
parser->opt_data.opterr instead of opterr.
(parser_parse_opt): Use parser->opt_data.optarg instead optarg.
(parser_parse_next): Likewise. Use parser->opt_data.optind
instead optind. Use parser->opt_data.optopt instead of optopt.
Call _getopt_long_only_r and _getopt_long_r instead of
getopt_long_only and getopt_long, and pass the extra argument.
2004-03-09 Ulrich Drepper <drepper@redhat.com> 2004-03-09 Ulrich Drepper <drepper@redhat.com>
* iconv/gconv_db.c: Don't define lock as static. Rename to * iconv/gconv_db.c: Don't define lock as static. Rename to

View file

@ -1,5 +1,5 @@
/* Hierarchial argument parsing, layered over getopt /* Hierarchial argument parsing, layered over getopt
Copyright (C) 1995-2000, 2002, 2003 Free Software Foundation, Inc. Copyright (C) 1995-2000, 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
Written by Miles Bader <miles@gnu.ai.mit.edu>. Written by Miles Bader <miles@gnu.ai.mit.edu>.
@ -42,6 +42,7 @@ char *alloca ();
#include <unistd.h> #include <unistd.h>
#include <limits.h> #include <limits.h>
#include <getopt.h> #include <getopt.h>
#include <getopt_int.h>
#ifndef _ #ifndef _
/* This is for other GNU distributions with internationalized messages. /* This is for other GNU distributions with internationalized messages.
@ -62,14 +63,6 @@ char *alloca ();
# define N_(msgid) (msgid) # define N_(msgid) (msgid)
#endif #endif
#if _LIBC - 0
#include <bits/libc-lock.h>
#else
#ifdef HAVE_CTHREADS_H
#include <cthreads.h>
#endif
#endif /* _LIBC */
#include "argp.h" #include "argp.h"
#include "argp-namefrob.h" #include "argp-namefrob.h"
@ -97,14 +90,8 @@ char *alloca ();
/* When argp is given the --HANG switch, _ARGP_HANG is set and argp will sleep /* When argp is given the --HANG switch, _ARGP_HANG is set and argp will sleep
for one second intervals, decrementing _ARGP_HANG until it's zero. Thus for one second intervals, decrementing _ARGP_HANG until it's zero. Thus
you can force the program to continue by attaching a debugger and setting you can force the program to continue by attaching a debugger and setting
it to 0 yourself. it to 0 yourself. */
static volatile int _argp_hang;
XXX This variable used to be exported. But there seems to be no
need, at least not inside libc. */
#ifdef _LIBC
static
#endif
volatile int _argp_hang;
#define OPT_PROGNAME -2 #define OPT_PROGNAME -2
#define OPT_USAGE -3 #define OPT_USAGE -3
@ -223,42 +210,7 @@ find_long_option (struct option *long_options, const char *name)
else else
return -1; return -1;
} }
/* If we can, we regulate access to getopt, which is non-reentrant, with a
mutex. Since the case we're trying to guard against is two different
threads interfering, and it's possible that someone might want to call
argp_parse recursively (they're careful), we use a recursive lock if
possible. */
#if _LIBC - 0
__libc_lock_define_initialized_recursive (static, getopt_lock)
#define LOCK_GETOPT __libc_lock_lock_recursive (getopt_lock)
#define UNLOCK_GETOPT __libc_lock_unlock_recursive (getopt_lock)
#else /* !_LIBC */
#ifdef HAVE_CTHREADS_H
static struct mutex getopt_lock = MUTEX_INITIALIZER;
#define LOCK_GETOPT mutex_lock (&getopt_lock)
#define UNLOCK_GETOPT mutex_unlock (&getopt_lock)
#else /* !HAVE_CTHREADS_H */
#define LOCK_GETOPT (void)0
#define UNLOCK_GETOPT (void)0
#endif /* HAVE_CTHREADS_H */
#endif /* _LIBC */
/* This hack to allow programs that know what's going on to call argp
recursively. If someday argp is changed not to use the non-reentrant
getopt interface, we can get rid of this shit. XXX */
void
_argp_unlock_xxx (void)
{
UNLOCK_GETOPT;
}
/* The state of a `group' during parsing. Each group corresponds to a /* The state of a `group' during parsing. Each group corresponds to a
particular argp structure from the tree of such descending from the top particular argp structure from the tree of such descending from the top
@ -320,6 +272,8 @@ struct parser
/* LONG_OPTS is the array of getop long option structures for the union of /* LONG_OPTS is the array of getop long option structures for the union of
all the groups of options. */ all the groups of options. */
struct option *long_opts; struct option *long_opts;
/* OPT_DATA is the getopt data used for the re-entrant getopt. */
struct _getopt_data opt_data;
/* States of the various parsing groups. */ /* States of the various parsing groups. */
struct group *groups; struct group *groups;
@ -531,6 +485,7 @@ parser_init (struct parser *parser, const struct argp *argp,
error_t err = 0; error_t err = 0;
struct group *group; struct group *group;
struct parser_sizes szs; struct parser_sizes szs;
struct _getopt_data opt_data = _GETOPT_DATA_INITIALIZER;
szs.short_len = (flags & ARGP_NO_ARGS) ? 0 : 1; szs.short_len = (flags & ARGP_NO_ARGS) ? 0 : 1;
szs.long_len = 0; szs.long_len = 0;
@ -554,6 +509,7 @@ parser_init (struct parser *parser, const struct argp *argp,
parser->child_inputs = parser->storage + GLEN; parser->child_inputs = parser->storage + GLEN;
parser->long_opts = parser->storage + GLEN + CLEN; parser->long_opts = parser->storage + GLEN + CLEN;
parser->short_opts = parser->storage + GLEN + CLEN + LLEN; parser->short_opts = parser->storage + GLEN + CLEN + LLEN;
parser->opt_data = opt_data;
memset (parser->child_inputs, 0, szs.num_child_inputs * sizeof (void *)); memset (parser->child_inputs, 0, szs.num_child_inputs * sizeof (void *));
parser_convert (parser, argp, flags); parser_convert (parser, argp, flags);
@ -597,19 +553,16 @@ parser_init (struct parser *parser, const struct argp *argp,
if (err) if (err)
return err; return err;
/* Getopt is (currently) non-reentrant. */
LOCK_GETOPT;
if (parser->state.flags & ARGP_NO_ERRS) if (parser->state.flags & ARGP_NO_ERRS)
{ {
opterr = 0; parser->opt_data.opterr = 0;
if (parser->state.flags & ARGP_PARSE_ARGV0) if (parser->state.flags & ARGP_PARSE_ARGV0)
/* getopt always skips ARGV[0], so we have to fake it out. As long /* getopt always skips ARGV[0], so we have to fake it out. As long
as OPTERR is 0, then it shouldn't actually try to access it. */ as OPTERR is 0, then it shouldn't actually try to access it. */
parser->state.argv--, parser->state.argc++; parser->state.argv--, parser->state.argc++;
} }
else else
opterr = 1; /* Print error messages. */ parser->opt_data.opterr = 1; /* Print error messages. */
if (parser->state.argv == argv && argv[0]) if (parser->state.argv == argv && argv[0])
/* There's an argv[0]; use it for messages. */ /* There's an argv[0]; use it for messages. */
@ -630,8 +583,6 @@ parser_finalize (struct parser *parser,
{ {
struct group *group; struct group *group;
UNLOCK_GETOPT;
if (err == EBADKEY && arg_ebadkey) if (err == EBADKEY && arg_ebadkey)
/* Suppress errors generated by unparsed arguments. */ /* Suppress errors generated by unparsed arguments. */
err = 0; err = 0;
@ -793,7 +744,8 @@ parser_parse_opt (struct parser *parser, int opt, char *val)
for (group = parser->groups; group < parser->egroup; group++) for (group = parser->groups; group < parser->egroup; group++)
if (group->short_end > short_index) if (group->short_end > short_index)
{ {
err = group_parse (group, &parser->state, opt, optarg); err = group_parse (group, &parser->state, opt,
parser->opt_data.optarg);
break; break;
} }
} }
@ -802,7 +754,8 @@ parser_parse_opt (struct parser *parser, int opt, char *val)
the user value in order to preserve the sign. */ the user value in order to preserve the sign. */
err = err =
group_parse (&parser->groups[group_key - 1], &parser->state, group_parse (&parser->groups[group_key - 1], &parser->state,
(opt << GROUP_BITS) >> GROUP_BITS, optarg); (opt << GROUP_BITS) >> GROUP_BITS,
parser->opt_data.optarg);
if (err == EBADKEY) if (err == EBADKEY)
/* At least currently, an option not recognized is an error in the /* At least currently, an option not recognized is an error in the
@ -848,15 +801,20 @@ parser_parse_next (struct parser *parser, int *arg_ebadkey)
if (parser->try_getopt && !parser->state.quoted) if (parser->try_getopt && !parser->state.quoted)
/* Give getopt a chance to parse this. */ /* Give getopt a chance to parse this. */
{ {
optind = parser->state.next; /* Put it back in OPTIND for getopt. */ /* Put it back in OPTIND for getopt. */
optopt = KEY_END; /* Distinguish KEY_ERR from a real option. */ parser->opt_data.optind = parser->state.next;
/* Distinguish KEY_ERR from a real option. */
parser->opt_data.optopt = KEY_END;
if (parser->state.flags & ARGP_LONG_ONLY) if (parser->state.flags & ARGP_LONG_ONLY)
opt = getopt_long_only (parser->state.argc, parser->state.argv, opt = _getopt_long_only_r (parser->state.argc, parser->state.argv,
parser->short_opts, parser->long_opts, 0); parser->short_opts, parser->long_opts, 0,
&parser->opt_data);
else else
opt = getopt_long (parser->state.argc, parser->state.argv, opt = _getopt_long_r (parser->state.argc, parser->state.argv,
parser->short_opts, parser->long_opts, 0); parser->short_opts, parser->long_opts, 0,
parser->state.next = optind; /* And see what getopt did. */ &parser->opt_data);
/* And see what getopt did. */
parser->state.next = parser->opt_data.optind;
if (opt == KEY_END) if (opt == KEY_END)
/* Getopt says there are no more options, so stop using /* Getopt says there are no more options, so stop using
@ -872,7 +830,7 @@ parser_parse_next (struct parser *parser, int *arg_ebadkey)
here, whatever happens. */ here, whatever happens. */
parser->state.quoted = parser->state.next; parser->state.quoted = parser->state.next;
} }
else if (opt == KEY_ERR && optopt != KEY_END) else if (opt == KEY_ERR && parser->opt_data.optopt != KEY_END)
/* KEY_ERR can have the same value as a valid user short /* KEY_ERR can have the same value as a valid user short
option, but in the case of a real error, getopt sets OPTOPT option, but in the case of a real error, getopt sets OPTOPT
to the offending character, which can never be KEY_END. */ to the offending character, which can never be KEY_END. */
@ -898,15 +856,15 @@ parser_parse_next (struct parser *parser, int *arg_ebadkey)
/* A non-option arg; simulate what getopt might have done. */ /* A non-option arg; simulate what getopt might have done. */
{ {
opt = KEY_ARG; opt = KEY_ARG;
optarg = parser->state.argv[parser->state.next++]; parser->opt_data.optarg = parser->state.argv[parser->state.next++];
} }
} }
if (opt == KEY_ARG) if (opt == KEY_ARG)
/* A non-option argument; try each parser in turn. */ /* A non-option argument; try each parser in turn. */
err = parser_parse_arg (parser, optarg); err = parser_parse_arg (parser, parser->opt_data.optarg);
else else
err = parser_parse_opt (parser, opt, optarg); err = parser_parse_opt (parser, opt, parser->opt_data.optarg);
if (err == EBADKEY) if (err == EBADKEY)
*arg_ebadkey = (opt == KEY_END || opt == KEY_ARG); *arg_ebadkey = (opt == KEY_END || opt == KEY_ARG);

View file

@ -5,9 +5,6 @@
# ifdef _GETOPT_H # ifdef _GETOPT_H
libc_hidden_proto (getopt_long)
libc_hidden_proto (getopt_long_only)
/* Now define the internal interfaces. */ /* Now define the internal interfaces. */
extern void __getopt_clean_environment (char **__env); extern void __getopt_clean_environment (char **__env);

1
include/getopt_int.h Normal file
View file

@ -0,0 +1 @@
#include <posix/getopt_int.h>

View file

@ -2,7 +2,7 @@
NOTE: getopt is now part of the C library, so if you don't know what NOTE: getopt is now part of the C library, so if you don't know what
"Keep this file name-space clean" means, talk to drepper@gnu.org "Keep this file name-space clean" means, talk to drepper@gnu.org
before changing it! before changing it!
Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002,2003 Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002,2003,2004
Free Software Foundation, Inc. Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
@ -31,14 +31,6 @@
# include <config.h> # include <config.h>
#endif #endif
#if !defined __STDC__ || !__STDC__
/* This is a separate conditional since some stdc systems
reject `defined (const)'. */
# ifndef const
# define const
# endif
#endif
#include <stdio.h> #include <stdio.h>
/* Comment out all this code if we are using the GNU C Library, and are not /* Comment out all this code if we are using the GNU C Library, and are not
@ -69,27 +61,22 @@
# include <unistd.h> # include <unistd.h>
#endif /* GNU C library. */ #endif /* GNU C library. */
#include <string.h>
#ifdef VMS #ifdef VMS
# include <unixlib.h> # include <unixlib.h>
# if HAVE_STRING_H - 0
# include <string.h>
# endif
#endif #endif
#ifndef _ #ifdef _LIBC
/* This is for other GNU distributions with internationalized messages. */
# if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC
# include <libintl.h> # include <libintl.h>
# ifndef _
# define _(msgid) gettext (msgid)
# endif
#else #else
# define _(msgid) (msgid) # include "gettext.h"
#endif #endif
#define _(msgid) gettext (msgid)
#if defined _LIBC && defined USE_IN_LIBIO #if defined _LIBC && defined USE_IN_LIBIO
# include <wchar.h> # include <wchar.h>
#endif #endif
#endif
#ifndef attribute_hidden #ifndef attribute_hidden
# define attribute_hidden # define attribute_hidden
@ -110,6 +97,7 @@
they can distinguish the relative order of options and other arguments. */ they can distinguish the relative order of options and other arguments. */
#include "getopt.h" #include "getopt.h"
#include "getopt_int.h"
/* For communication from `getopt' to the caller. /* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument, When `getopt' finds an option that takes an argument,
@ -134,21 +122,6 @@ char *optarg;
/* 1003.2 says this must be 1 before any call. */ /* 1003.2 says this must be 1 before any call. */
int optind = 1; int optind = 1;
/* Formerly, initialization of getopt depended on optind==0, which
causes problems with re-calling getopt as programs generally don't
know that. */
int __getopt_initialized attribute_hidden;
/* The next char to be scanned in the option-element
in which the last option character we returned was found.
This allows us to pick up the scan where we left off.
If this is zero, or a null string, it means resume the scan
by advancing to the next ARGV-element. */
static char *nextchar;
/* Callers store zero here to inhibit the error message /* Callers store zero here to inhibit the error message
for unrecognized options. */ for unrecognized options. */
@ -160,57 +133,12 @@ int opterr = 1;
int optopt = '?'; int optopt = '?';
/* Describe how to deal with options that follow non-option ARGV-elements. /* Keep a global copy of all internal members of getopt_data. */
If the caller did not specify anything, static struct _getopt_data getopt_data;
the default is REQUIRE_ORDER if the environment variable
POSIXLY_CORRECT is defined, PERMUTE otherwise.
REQUIRE_ORDER means don't recognize them as options;
stop option processing when the first non-option is seen.
This is what Unix does.
This mode of operation is selected by either setting the environment
variable POSIXLY_CORRECT, or using `+' as the first character
of the list of option characters.
PERMUTE is the default. We permute the contents of ARGV as we scan,
so that eventually all the non-options are at the end. This allows options
to be given in any order, even with programs that were not written to
expect this.
RETURN_IN_ORDER is an option available to programs that were written
to expect options and other ARGV-elements in any order and that care about
the ordering of the two. We describe each non-option ARGV-element
as if it were the argument of an option with character code 1.
Using `-' as the first character of the list of option characters
selects this mode of operation.
The special argument `--' forces an end of option-scanning regardless
of the value of `ordering'. In the case of RETURN_IN_ORDER, only
`--' can cause `getopt' to return -1 with `optind' != ARGC. */
static enum
{
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
} ordering;
/* Value of POSIXLY_CORRECT environment variable. */
static char *posixly_correct;
#ifdef __GNU_LIBRARY__ #ifndef __GNU_LIBRARY__
/* We want to avoid inclusion of string.h with non-GNU libraries
because there are many ways it can cause trouble.
On some systems, it contains special magic macros that don't work
in GCC. */
# include <string.h>
# define my_index strchr
#else
# if HAVE_STRING_H
# include <string.h>
# else
# include <strings.h>
# endif
/* Avoid depending on library functions or files /* Avoid depending on library functions or files
whose names are inconsistent. */ whose names are inconsistent. */
@ -219,43 +147,8 @@ static char *posixly_correct;
extern char *getenv (); extern char *getenv ();
#endif #endif
static char *
my_index (str, chr)
const char *str;
int chr;
{
while (*str)
{
if (*str == chr)
return (char *) str;
str++;
}
return 0;
}
/* If using GCC, we can safely declare strlen this way.
If not using GCC, it is ok not to declare it. */
#ifdef __GNUC__
/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
That was relevant to code that was here before. */
# if (!defined __STDC__ || !__STDC__) && !defined strlen
/* gcc with -traditional declares the built-in strlen to return int,
and has done so at least since version 2.4.5. -- rms. */
extern int strlen (const char *);
# endif /* not __STDC__ */
#endif /* __GNUC__ */
#endif /* not __GNU_LIBRARY__ */ #endif /* not __GNU_LIBRARY__ */
/* Handle permutation of arguments. */
/* Describe the part of ARGV that contains non-options that have
been skipped. `first_nonopt' is the index in ARGV of the first of them;
`last_nonopt' is the index after the last of them. */
static int first_nonopt;
static int last_nonopt;
#ifdef _LIBC #ifdef _LIBC
/* Stored original parameters. /* Stored original parameters.
XXX This is no good solution. We should rather copy the args so XXX This is no good solution. We should rather copy the args so
@ -269,14 +162,11 @@ extern char **__libc_argv;
# ifdef USE_NONOPTION_FLAGS # ifdef USE_NONOPTION_FLAGS
/* Defined in getopt_init.c */ /* Defined in getopt_init.c */
extern char *__getopt_nonoption_flags; extern char *__getopt_nonoption_flags;
static int nonoption_flags_max_len;
static int nonoption_flags_len;
# endif # endif
# ifdef USE_NONOPTION_FLAGS # ifdef USE_NONOPTION_FLAGS
# define SWAP_FLAGS(ch1, ch2) \ # define SWAP_FLAGS(ch1, ch2) \
if (nonoption_flags_len > 0) \ if (d->__nonoption_flags_len > 0) \
{ \ { \
char __tmp = __getopt_nonoption_flags[ch1]; \ char __tmp = __getopt_nonoption_flags[ch1]; \
__getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \
@ -298,17 +188,12 @@ static int nonoption_flags_len;
`first_nonopt' and `last_nonopt' are relocated so that they describe `first_nonopt' and `last_nonopt' are relocated so that they describe
the new indices of the non-options in ARGV after they are moved. */ the new indices of the non-options in ARGV after they are moved. */
#if defined __STDC__ && __STDC__
static void exchange (char **);
#endif
static void static void
exchange (argv) exchange (char **argv, struct _getopt_data *d)
char **argv;
{ {
int bottom = first_nonopt; int bottom = d->__first_nonopt;
int middle = last_nonopt; int middle = d->__last_nonopt;
int top = optind; int top = d->optind;
char *tem; char *tem;
/* Exchange the shorter segment with the far end of the longer segment. /* Exchange the shorter segment with the far end of the longer segment.
@ -320,19 +205,19 @@ exchange (argv)
/* First make sure the handling of the `__getopt_nonoption_flags' /* First make sure the handling of the `__getopt_nonoption_flags'
string can work normally. Our top argument must be in the range string can work normally. Our top argument must be in the range
of the string. */ of the string. */
if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) if (d->__nonoption_flags_len > 0 && top >= d->__nonoption_flags_max_len)
{ {
/* We must extend the array. The user plays games with us and /* We must extend the array. The user plays games with us and
presents new arguments. */ presents new arguments. */
char *new_str = malloc (top + 1); char *new_str = malloc (top + 1);
if (new_str == NULL) if (new_str == NULL)
nonoption_flags_len = nonoption_flags_max_len = 0; d->__nonoption_flags_len = d->__nonoption_flags_max_len = 0;
else else
{ {
memset (__mempcpy (new_str, __getopt_nonoption_flags, memset (__mempcpy (new_str, __getopt_nonoption_flags,
nonoption_flags_max_len), d->__nonoption_flags_max_len),
'\0', top + 1 - nonoption_flags_max_len); '\0', top + 1 - d->__nonoption_flags_max_len);
nonoption_flags_max_len = top + 1; d->__nonoption_flags_max_len = top + 1;
__getopt_nonoption_flags = new_str; __getopt_nonoption_flags = new_str;
} }
} }
@ -378,76 +263,71 @@ exchange (argv)
/* Update records for the slots the non-options now occupy. */ /* Update records for the slots the non-options now occupy. */
first_nonopt += (optind - last_nonopt); d->__first_nonopt += (d->optind - d->__last_nonopt);
last_nonopt = optind; d->__last_nonopt = d->optind;
} }
/* Initialize the internal data when the first call is made. */ /* Initialize the internal data when the first call is made. */
#if defined __STDC__ && __STDC__
static const char *_getopt_initialize (int, char *const *, const char *);
#endif
static const char * static const char *
_getopt_initialize (argc, argv, optstring) _getopt_initialize (int argc, char *const *argv, const char *optstring,
int argc; struct _getopt_data *d)
char *const *argv;
const char *optstring;
{ {
/* Start processing options with ARGV-element 1 (since ARGV-element 0 /* Start processing options with ARGV-element 1 (since ARGV-element 0
is the program name); the sequence of previously skipped is the program name); the sequence of previously skipped
non-option ARGV-elements is empty. */ non-option ARGV-elements is empty. */
first_nonopt = last_nonopt = optind; d->__first_nonopt = d->__last_nonopt = d->optind;
nextchar = NULL; d->__nextchar = NULL;
posixly_correct = getenv ("POSIXLY_CORRECT"); d->__posixly_correct = !!getenv ("POSIXLY_CORRECT");
/* Determine how to handle the ordering of options and nonoptions. */ /* Determine how to handle the ordering of options and nonoptions. */
if (optstring[0] == '-') if (optstring[0] == '-')
{ {
ordering = RETURN_IN_ORDER; d->__ordering = RETURN_IN_ORDER;
++optstring; ++optstring;
} }
else if (optstring[0] == '+') else if (optstring[0] == '+')
{ {
ordering = REQUIRE_ORDER; d->__ordering = REQUIRE_ORDER;
++optstring; ++optstring;
} }
else if (posixly_correct != NULL) else if (d->__posixly_correct)
ordering = REQUIRE_ORDER; d->__ordering = REQUIRE_ORDER;
else else
ordering = PERMUTE; d->__ordering = PERMUTE;
#if defined _LIBC && defined USE_NONOPTION_FLAGS #if defined _LIBC && defined USE_NONOPTION_FLAGS
if (posixly_correct == NULL if (!d->__posixly_correct
&& argc == __libc_argc && argv == __libc_argv) && argc == __libc_argc && argv == __libc_argv)
{ {
if (nonoption_flags_max_len == 0) if (d->__nonoption_flags_max_len == 0)
{ {
if (__getopt_nonoption_flags == NULL if (__getopt_nonoption_flags == NULL
|| __getopt_nonoption_flags[0] == '\0') || __getopt_nonoption_flags[0] == '\0')
nonoption_flags_max_len = -1; d->__nonoption_flags_max_len = -1;
else else
{ {
const char *orig_str = __getopt_nonoption_flags; const char *orig_str = __getopt_nonoption_flags;
int len = nonoption_flags_max_len = strlen (orig_str); int len = d->__nonoption_flags_max_len = strlen (orig_str);
if (nonoption_flags_max_len < argc) if (d->__nonoption_flags_max_len < argc)
nonoption_flags_max_len = argc; d->__nonoption_flags_max_len = argc;
__getopt_nonoption_flags = __getopt_nonoption_flags =
(char *) malloc (nonoption_flags_max_len); (char *) malloc (d->__nonoption_flags_max_len);
if (__getopt_nonoption_flags == NULL) if (__getopt_nonoption_flags == NULL)
nonoption_flags_max_len = -1; d->__nonoption_flags_max_len = -1;
else else
memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), memset (__mempcpy (__getopt_nonoption_flags, orig_str, len),
'\0', nonoption_flags_max_len - len); '\0', d->__nonoption_flags_max_len - len);
} }
} }
nonoption_flags_len = nonoption_flags_max_len; d->__nonoption_flags_len = d->__nonoption_flags_max_len;
} }
else else
nonoption_flags_len = 0; d->__nonoption_flags_len = 0;
#endif #endif
return optstring; return optstring;
@ -510,29 +390,25 @@ _getopt_initialize (argc, argv, optstring)
long-named options. */ long-named options. */
int int
_getopt_internal (argc, argv, optstring, longopts, longind, long_only) _getopt_internal_r (int argc, char *const *argv, const char *optstring,
int argc; const struct option *longopts, int *longind,
char *const *argv; int long_only, struct _getopt_data *d)
const char *optstring;
const struct option *longopts;
int *longind;
int long_only;
{ {
int print_errors = opterr; int print_errors = d->opterr;
if (optstring[0] == ':') if (optstring[0] == ':')
print_errors = 0; print_errors = 0;
if (argc < 1) if (argc < 1)
return -1; return -1;
optarg = NULL; d->optarg = NULL;
if (optind == 0 || !__getopt_initialized) if (d->optind == 0 || !d->__initialized)
{ {
if (optind == 0) if (d->optind == 0)
optind = 1; /* Don't scan ARGV[0], the program name. */ d->optind = 1; /* Don't scan ARGV[0], the program name. */
optstring = _getopt_initialize (argc, argv, optstring); optstring = _getopt_initialize (argc, argv, optstring, d);
__getopt_initialized = 1; d->__initialized = 1;
} }
/* Test whether ARGV[optind] points to a non-option argument. /* Test whether ARGV[optind] points to a non-option argument.
@ -540,40 +416,41 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
from the shell indicating it is not an option. The later information from the shell indicating it is not an option. The later information
is only used when the used in the GNU libc. */ is only used when the used in the GNU libc. */
#if defined _LIBC && defined USE_NONOPTION_FLAGS #if defined _LIBC && defined USE_NONOPTION_FLAGS
# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ # define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0' \
|| (optind < nonoption_flags_len \ || (d->optind < d->__nonoption_flags_len \
&& __getopt_nonoption_flags[optind] == '1')) && __getopt_nonoption_flags[d->optind] == '1'))
#else #else
# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') # define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0')
#endif #endif
if (nextchar == NULL || *nextchar == '\0') if (d->__nextchar == NULL || *d->__nextchar == '\0')
{ {
/* Advance to the next ARGV-element. */ /* Advance to the next ARGV-element. */
/* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
moved back by the user (who may also have changed the arguments). */ moved back by the user (who may also have changed the arguments). */
if (last_nonopt > optind) if (d->__last_nonopt > d->optind)
last_nonopt = optind; d->__last_nonopt = d->optind;
if (first_nonopt > optind) if (d->__first_nonopt > d->optind)
first_nonopt = optind; d->__first_nonopt = d->optind;
if (ordering == PERMUTE) if (d->__ordering == PERMUTE)
{ {
/* If we have just processed some options following some non-options, /* If we have just processed some options following some non-options,
exchange them so that the options come first. */ exchange them so that the options come first. */
if (first_nonopt != last_nonopt && last_nonopt != optind) if (d->__first_nonopt != d->__last_nonopt
exchange ((char **) argv); && d->__last_nonopt != d->optind)
else if (last_nonopt != optind) exchange ((char **) argv, d);
first_nonopt = optind; else if (d->__last_nonopt != d->optind)
d->__first_nonopt = d->optind;
/* Skip any additional non-options /* Skip any additional non-options
and extend the range of non-options previously skipped. */ and extend the range of non-options previously skipped. */
while (optind < argc && NONOPTION_P) while (d->optind < argc && NONOPTION_P)
optind++; d->optind++;
last_nonopt = optind; d->__last_nonopt = d->optind;
} }
/* The special ARGV-element `--' means premature end of options. /* The special ARGV-element `--' means premature end of options.
@ -581,28 +458,29 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
then exchange with previous non-options as if it were an option, then exchange with previous non-options as if it were an option,
then skip everything else like a non-option. */ then skip everything else like a non-option. */
if (optind != argc && !strcmp (argv[optind], "--")) if (d->optind != argc && !strcmp (argv[d->optind], "--"))
{ {
optind++; d->optind++;
if (first_nonopt != last_nonopt && last_nonopt != optind) if (d->__first_nonopt != d->__last_nonopt
exchange ((char **) argv); && d->__last_nonopt != d->optind)
else if (first_nonopt == last_nonopt) exchange ((char **) argv, d);
first_nonopt = optind; else if (d->__first_nonopt == d->__last_nonopt)
last_nonopt = argc; d->__first_nonopt = d->optind;
d->__last_nonopt = argc;
optind = argc; d->optind = argc;
} }
/* If we have done all the ARGV-elements, stop the scan /* If we have done all the ARGV-elements, stop the scan
and back over any non-options that we skipped and permuted. */ and back over any non-options that we skipped and permuted. */
if (optind == argc) if (d->optind == argc)
{ {
/* Set the next-arg-index to point at the non-options /* Set the next-arg-index to point at the non-options
that we previously skipped, so the caller will digest them. */ that we previously skipped, so the caller will digest them. */
if (first_nonopt != last_nonopt) if (d->__first_nonopt != d->__last_nonopt)
optind = first_nonopt; d->optind = d->__first_nonopt;
return -1; return -1;
} }
@ -611,17 +489,17 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
if (NONOPTION_P) if (NONOPTION_P)
{ {
if (ordering == REQUIRE_ORDER) if (d->__ordering == REQUIRE_ORDER)
return -1; return -1;
optarg = argv[optind++]; d->optarg = argv[d->optind++];
return 1; return 1;
} }
/* We have found another option-ARGV-element. /* We have found another option-ARGV-element.
Skip the initial punctuation. */ Skip the initial punctuation. */
nextchar = (argv[optind] + 1 d->__nextchar = (argv[d->optind] + 1
+ (longopts != NULL && argv[optind][1] == '-')); + (longopts != NULL && argv[d->optind][1] == '-'));
} }
/* Decode the current option-ARGV-element. */ /* Decode the current option-ARGV-element. */
@ -640,8 +518,9 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
This distinction seems to be the most useful approach. */ This distinction seems to be the most useful approach. */
if (longopts != NULL if (longopts != NULL
&& (argv[optind][1] == '-' && (argv[d->optind][1] == '-'
|| (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) || (long_only && (argv[d->optind][2]
|| !strchr (optstring, argv[d->optind][1])))))
{ {
char *nameend; char *nameend;
const struct option *p; const struct option *p;
@ -651,15 +530,15 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
int indfound = -1; int indfound = -1;
int option_index; int option_index;
for (nameend = nextchar; *nameend && *nameend != '='; nameend++) for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++)
/* Do nothing. */ ; /* Do nothing. */ ;
/* Test all long options for either exact match /* Test all long options for either exact match
or abbreviated matches. */ or abbreviated matches. */
for (p = longopts, option_index = 0; p->name; p++, option_index++) for (p = longopts, option_index = 0; p->name; p++, option_index++)
if (!strncmp (p->name, nextchar, nameend - nextchar)) if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar))
{ {
if ((unsigned int) (nameend - nextchar) if ((unsigned int) (nameend - d->__nextchar)
== (unsigned int) strlen (p->name)) == (unsigned int) strlen (p->name))
{ {
/* Exact match found. */ /* Exact match found. */
@ -690,7 +569,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
char *buf; char *buf;
if (__asprintf (&buf, _("%s: option `%s' is ambiguous\n"), if (__asprintf (&buf, _("%s: option `%s' is ambiguous\n"),
argv[0], argv[optind]) >= 0) argv[0], argv[d->optind]) >= 0)
{ {
_IO_flockfile (stderr); _IO_flockfile (stderr);
@ -709,25 +588,25 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
} }
#else #else
fprintf (stderr, _("%s: option `%s' is ambiguous\n"), fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
argv[0], argv[optind]); argv[0], argv[d->optind]);
#endif #endif
} }
nextchar += strlen (nextchar); d->__nextchar += strlen (d->__nextchar);
optind++; d->optind++;
optopt = 0; d->optopt = 0;
return '?'; return '?';
} }
if (pfound != NULL) if (pfound != NULL)
{ {
option_index = indfound; option_index = indfound;
optind++; d->optind++;
if (*nameend) if (*nameend)
{ {
/* Don't test has_arg with >, because some C compilers don't /* Don't test has_arg with >, because some C compilers don't
allow it to be used on enums. */ allow it to be used on enums. */
if (pfound->has_arg) if (pfound->has_arg)
optarg = nameend + 1; d->optarg = nameend + 1;
else else
{ {
if (print_errors) if (print_errors)
@ -737,7 +616,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
int n; int n;
#endif #endif
if (argv[optind - 1][1] == '-') if (argv[d->optind - 1][1] == '-')
{ {
/* --option */ /* --option */
#if defined _LIBC && defined USE_IN_LIBIO #if defined _LIBC && defined USE_IN_LIBIO
@ -756,12 +635,13 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
#if defined _LIBC && defined USE_IN_LIBIO #if defined _LIBC && defined USE_IN_LIBIO
n = __asprintf (&buf, _("\ n = __asprintf (&buf, _("\
%s: option `%c%s' doesn't allow an argument\n"), %s: option `%c%s' doesn't allow an argument\n"),
argv[0], argv[optind - 1][0], argv[0], argv[d->optind - 1][0],
pfound->name); pfound->name);
#else #else
fprintf (stderr, _("\ fprintf (stderr, _("\
%s: option `%c%s' doesn't allow an argument\n"), %s: option `%c%s' doesn't allow an argument\n"),
argv[0], argv[optind - 1][0], pfound->name); argv[0], argv[d->optind - 1][0],
pfound->name);
#endif #endif
} }
@ -787,16 +667,16 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
#endif #endif
} }
nextchar += strlen (nextchar); d->__nextchar += strlen (d->__nextchar);
optopt = pfound->val; d->optopt = pfound->val;
return '?'; return '?';
} }
} }
else if (pfound->has_arg == 1) else if (pfound->has_arg == 1)
{ {
if (optind < argc) if (d->optind < argc)
optarg = argv[optind++]; d->optarg = argv[d->optind++];
else else
{ {
if (print_errors) if (print_errors)
@ -806,7 +686,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
if (__asprintf (&buf, _("\ if (__asprintf (&buf, _("\
%s: option `%s' requires an argument\n"), %s: option `%s' requires an argument\n"),
argv[0], argv[optind - 1]) >= 0) argv[0], argv[d->optind - 1]) >= 0)
{ {
_IO_flockfile (stderr); _IO_flockfile (stderr);
@ -827,15 +707,15 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
#else #else
fprintf (stderr, fprintf (stderr,
_("%s: option `%s' requires an argument\n"), _("%s: option `%s' requires an argument\n"),
argv[0], argv[optind - 1]); argv[0], argv[d->optind - 1]);
#endif #endif
} }
nextchar += strlen (nextchar); d->__nextchar += strlen (d->__nextchar);
optopt = pfound->val; d->optopt = pfound->val;
return optstring[0] == ':' ? ':' : '?'; return optstring[0] == ':' ? ':' : '?';
} }
} }
nextchar += strlen (nextchar); d->__nextchar += strlen (d->__nextchar);
if (longind != NULL) if (longind != NULL)
*longind = option_index; *longind = option_index;
if (pfound->flag) if (pfound->flag)
@ -850,8 +730,8 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
or the option starts with '--' or is not a valid short or the option starts with '--' or is not a valid short
option, then it's an error. option, then it's an error.
Otherwise interpret it as a short option. */ Otherwise interpret it as a short option. */
if (!long_only || argv[optind][1] == '-' if (!long_only || argv[d->optind][1] == '-'
|| my_index (optstring, *nextchar) == NULL) || strchr (optstring, *d->__nextchar) == NULL)
{ {
if (print_errors) if (print_errors)
{ {
@ -860,15 +740,15 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
int n; int n;
#endif #endif
if (argv[optind][1] == '-') if (argv[d->optind][1] == '-')
{ {
/* --option */ /* --option */
#if defined _LIBC && defined USE_IN_LIBIO #if defined _LIBC && defined USE_IN_LIBIO
n = __asprintf (&buf, _("%s: unrecognized option `--%s'\n"), n = __asprintf (&buf, _("%s: unrecognized option `--%s'\n"),
argv[0], nextchar); argv[0], d->__nextchar);
#else #else
fprintf (stderr, _("%s: unrecognized option `--%s'\n"), fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
argv[0], nextchar); argv[0], d->__nextchar);
#endif #endif
} }
else else
@ -876,10 +756,10 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
/* +option or -option */ /* +option or -option */
#if defined _LIBC && defined USE_IN_LIBIO #if defined _LIBC && defined USE_IN_LIBIO
n = __asprintf (&buf, _("%s: unrecognized option `%c%s'\n"), n = __asprintf (&buf, _("%s: unrecognized option `%c%s'\n"),
argv[0], argv[optind][0], nextchar); argv[0], argv[d->optind][0], d->__nextchar);
#else #else
fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
argv[0], argv[optind][0], nextchar); argv[0], argv[d->optind][0], d->__nextchar);
#endif #endif
} }
@ -903,9 +783,9 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
} }
#endif #endif
} }
nextchar = (char *) ""; d->__nextchar = (char *) "";
optind++; d->optind++;
optopt = 0; d->optopt = 0;
return '?'; return '?';
} }
} }
@ -913,12 +793,12 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
/* Look at and handle the next short option-character. */ /* Look at and handle the next short option-character. */
{ {
char c = *nextchar++; char c = *d->__nextchar++;
char *temp = my_index (optstring, c); char *temp = strchr (optstring, c);
/* Increment `optind' when we start to process its last character. */ /* Increment `optind' when we start to process its last character. */
if (*nextchar == '\0') if (*d->__nextchar == '\0')
++optind; ++d->optind;
if (temp == NULL || c == ':') if (temp == NULL || c == ':')
{ {
@ -929,7 +809,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
int n; int n;
#endif #endif
if (posixly_correct) if (d->__posixly_correct)
{ {
/* 1003.2 specifies the format of this message. */ /* 1003.2 specifies the format of this message. */
#if defined _LIBC && defined USE_IN_LIBIO #if defined _LIBC && defined USE_IN_LIBIO
@ -969,7 +849,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
} }
#endif #endif
} }
optopt = c; d->optopt = c;
return '?'; return '?';
} }
/* Convenience. Treat POSIX -W foo same as long option --foo */ /* Convenience. Treat POSIX -W foo same as long option --foo */
@ -984,14 +864,14 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
int option_index; int option_index;
/* This is an option that requires an argument. */ /* This is an option that requires an argument. */
if (*nextchar != '\0') if (*d->__nextchar != '\0')
{ {
optarg = nextchar; d->optarg = d->__nextchar;
/* If we end this ARGV-element by taking the rest as an arg, /* If we end this ARGV-element by taking the rest as an arg,
we must advance to the next element now. */ we must advance to the next element now. */
optind++; d->optind++;
} }
else if (optind == argc) else if (d->optind == argc)
{ {
if (print_errors) if (print_errors)
{ {
@ -1023,7 +903,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
argv[0], c); argv[0], c);
#endif #endif
} }
optopt = c; d->optopt = c;
if (optstring[0] == ':') if (optstring[0] == ':')
c = ':'; c = ':';
else else
@ -1031,22 +911,23 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
return c; return c;
} }
else else
/* We already incremented `optind' once; /* We already incremented `d->optind' once;
increment it again when taking next ARGV-elt as argument. */ increment it again when taking next ARGV-elt as argument. */
optarg = argv[optind++]; d->optarg = argv[d->optind++];
/* optarg is now the argument, see if it's in the /* optarg is now the argument, see if it's in the
table of longopts. */ table of longopts. */
for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '=';
nameend++)
/* Do nothing. */ ; /* Do nothing. */ ;
/* Test all long options for either exact match /* Test all long options for either exact match
or abbreviated matches. */ or abbreviated matches. */
for (p = longopts, option_index = 0; p->name; p++, option_index++) for (p = longopts, option_index = 0; p->name; p++, option_index++)
if (!strncmp (p->name, nextchar, nameend - nextchar)) if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar))
{ {
if ((unsigned int) (nameend - nextchar) == strlen (p->name)) if ((unsigned int) (nameend - d->__nextchar) == strlen (p->name))
{ {
/* Exact match found. */ /* Exact match found. */
pfound = p; pfound = p;
@ -1072,7 +953,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
char *buf; char *buf;
if (__asprintf (&buf, _("%s: option `-W %s' is ambiguous\n"), if (__asprintf (&buf, _("%s: option `-W %s' is ambiguous\n"),
argv[0], argv[optind]) >= 0) argv[0], argv[d->optind]) >= 0)
{ {
_IO_flockfile (stderr); _IO_flockfile (stderr);
@ -1091,11 +972,11 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
} }
#else #else
fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
argv[0], argv[optind]); argv[0], argv[d->optind]);
#endif #endif
} }
nextchar += strlen (nextchar); d->__nextchar += strlen (d->__nextchar);
optind++; d->optind++;
return '?'; return '?';
} }
if (pfound != NULL) if (pfound != NULL)
@ -1106,7 +987,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
/* Don't test has_arg with >, because some C compilers don't /* Don't test has_arg with >, because some C compilers don't
allow it to be used on enums. */ allow it to be used on enums. */
if (pfound->has_arg) if (pfound->has_arg)
optarg = nameend + 1; d->optarg = nameend + 1;
else else
{ {
if (print_errors) if (print_errors)
@ -1141,14 +1022,14 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
#endif #endif
} }
nextchar += strlen (nextchar); d->__nextchar += strlen (d->__nextchar);
return '?'; return '?';
} }
} }
else if (pfound->has_arg == 1) else if (pfound->has_arg == 1)
{ {
if (optind < argc) if (d->optind < argc)
optarg = argv[optind++]; d->optarg = argv[d->optind++];
else else
{ {
if (print_errors) if (print_errors)
@ -1158,7 +1039,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
if (__asprintf (&buf, _("\ if (__asprintf (&buf, _("\
%s: option `%s' requires an argument\n"), %s: option `%s' requires an argument\n"),
argv[0], argv[optind - 1]) >= 0) argv[0], argv[d->optind - 1]) >= 0)
{ {
_IO_flockfile (stderr); _IO_flockfile (stderr);
@ -1179,14 +1060,14 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
#else #else
fprintf (stderr, fprintf (stderr,
_("%s: option `%s' requires an argument\n"), _("%s: option `%s' requires an argument\n"),
argv[0], argv[optind - 1]); argv[0], argv[d->optind - 1]);
#endif #endif
} }
nextchar += strlen (nextchar); d->__nextchar += strlen (d->__nextchar);
return optstring[0] == ':' ? ':' : '?'; return optstring[0] == ':' ? ':' : '?';
} }
} }
nextchar += strlen (nextchar); d->__nextchar += strlen (d->__nextchar);
if (longind != NULL) if (longind != NULL)
*longind = option_index; *longind = option_index;
if (pfound->flag) if (pfound->flag)
@ -1196,7 +1077,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
} }
return pfound->val; return pfound->val;
} }
nextchar = NULL; d->__nextchar = NULL;
return 'W'; /* Let the application handle it. */ return 'W'; /* Let the application handle it. */
} }
if (temp[1] == ':') if (temp[1] == ':')
@ -1204,26 +1085,26 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
if (temp[2] == ':') if (temp[2] == ':')
{ {
/* This is an option that accepts an argument optionally. */ /* This is an option that accepts an argument optionally. */
if (*nextchar != '\0') if (*d->__nextchar != '\0')
{ {
optarg = nextchar; d->optarg = d->__nextchar;
optind++; d->optind++;
} }
else else
optarg = NULL; d->optarg = NULL;
nextchar = NULL; d->__nextchar = NULL;
} }
else else
{ {
/* This is an option that requires an argument. */ /* This is an option that requires an argument. */
if (*nextchar != '\0') if (*d->__nextchar != '\0')
{ {
optarg = nextchar; d->optarg = d->__nextchar;
/* If we end this ARGV-element by taking the rest as an arg, /* If we end this ARGV-element by taking the rest as an arg,
we must advance to the next element now. */ we must advance to the next element now. */
optind++; d->optind++;
} }
else if (optind == argc) else if (d->optind == argc)
{ {
if (print_errors) if (print_errors)
{ {
@ -1256,7 +1137,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
argv[0], c); argv[0], c);
#endif #endif
} }
optopt = c; d->optopt = c;
if (optstring[0] == ':') if (optstring[0] == ':')
c = ':'; c = ':';
else else
@ -1265,8 +1146,8 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
else else
/* We already incremented `optind' once; /* We already incremented `optind' once;
increment it again when taking next ARGV-elt as argument. */ increment it again when taking next ARGV-elt as argument. */
optarg = argv[optind++]; d->optarg = argv[d->optind++];
nextchar = NULL; d->__nextchar = NULL;
} }
} }
return c; return c;
@ -1274,10 +1155,26 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
} }
int int
getopt (argc, argv, optstring) _getopt_internal (int argc, char *const *argv, const char *optstring,
int argc; const struct option *longopts, int *longind, int long_only)
char *const *argv; {
const char *optstring; int result;
getopt_data.optind = optind;
getopt_data.opterr = opterr;
result = _getopt_internal_r (argc, argv, optstring, longopts,
longind, long_only, &getopt_data);
optind = getopt_data.optind;
optarg = getopt_data.optarg;
optopt = getopt_data.optopt;
return result;
}
int
getopt (int argc, char *const *argv, const char *optstring)
{ {
return _getopt_internal (argc, argv, optstring, return _getopt_internal (argc, argv, optstring,
(const struct option *) 0, (const struct option *) 0,
@ -1293,9 +1190,7 @@ getopt (argc, argv, optstring)
the above definition of `getopt'. */ the above definition of `getopt'. */
int int
main (argc, argv) main (int argc, char **argv)
int argc;
char **argv;
{ {
int c; int c;
int digit_optind = 0; int digit_optind = 0;

View file

@ -105,11 +105,7 @@ extern int optopt;
struct option struct option
{ {
# if (defined __STDC__ && __STDC__) || defined __cplusplus
const char *name; const char *name;
# else
char *name;
# endif
/* has_arg can't be an enum because some compilers complain about /* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */ type mismatches in all the code that assumes it is an int. */
int has_arg; int has_arg;
@ -149,7 +145,6 @@ struct option
arguments to the option '\0'. This behavior is specific to the GNU arguments to the option '\0'. This behavior is specific to the GNU
`getopt'. */ `getopt'. */
#if (defined __STDC__ && __STDC__) || defined __cplusplus
#ifdef __GNU_LIBRARY__ #ifdef __GNU_LIBRARY__
/* Many other libraries have conflicting prototypes for getopt, with /* Many other libraries have conflicting prototypes for getopt, with
differences in the consts, in stdlib.h. To avoid compilation differences in the consts, in stdlib.h. To avoid compilation
@ -170,21 +165,7 @@ extern int getopt_long_only (int ___argc, char *const *___argv,
const struct option *__longopts, int *__longind) const struct option *__longopts, int *__longind)
__THROW; __THROW;
/* Internal only. Users should not call this directly. */
extern int _getopt_internal (int ___argc, char *const *___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind,
int __long_only);
#endif #endif
#else /* not __STDC__ */
extern int getopt ();
# ifndef __need_getopt
extern int getopt_long ();
extern int getopt_long_only ();
extern int _getopt_internal ();
# endif
#endif /* __STDC__ */
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -1,5 +1,5 @@
/* getopt_long and getopt_long_only entry points for GNU getopt. /* getopt_long and getopt_long_only entry points for GNU getopt.
Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98 Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98,2004
Free Software Foundation, Inc. Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
@ -27,14 +27,7 @@
#else #else
# include "getopt.h" # include "getopt.h"
#endif #endif
#include "getopt_int.h"
#if !defined __STDC__ || !__STDC__
/* This is a separate conditional since some stdc systems
reject `defined (const)'. */
#ifndef const
#define const
#endif
#endif
#include <stdio.h> #include <stdio.h>
@ -68,36 +61,41 @@
#endif #endif
int int
getopt_long (argc, argv, options, long_options, opt_index) getopt_long (int argc, char *const *argv, const char *options,
int argc; const struct option *long_options, int *opt_index)
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{ {
return _getopt_internal (argc, argv, options, long_options, opt_index, 0); return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
} }
int
_getopt_long_r (int argc, char *const *argv, const char *options,
const struct option *long_options, int *opt_index,
struct _getopt_data *d)
{
return _getopt_internal_r (argc, argv, options, long_options, opt_index,
0, d);
}
/* Like getopt_long, but '-' as well as '--' can indicate a long option. /* Like getopt_long, but '-' as well as '--' can indicate a long option.
If an option that starts with '-' (not '--') doesn't match a long option, If an option that starts with '-' (not '--') doesn't match a long option,
but does match a short option, it is parsed as a short option but does match a short option, it is parsed as a short option
instead. */ instead. */
int int
getopt_long_only (argc, argv, options, long_options, opt_index) getopt_long_only (int argc, char *const *argv, const char *options,
int argc; const struct option *long_options, int *opt_index)
char *const *argv;
const char *options;
const struct option *long_options;
int *opt_index;
{ {
return _getopt_internal (argc, argv, options, long_options, opt_index, 1); return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
} }
# ifdef _LIBC int
libc_hidden_def (getopt_long) _getopt_long_only_r (int argc, char *const *argv, const char *options,
libc_hidden_def (getopt_long_only) const struct option *long_options, int *opt_index,
# endif struct _getopt_data *d)
{
return _getopt_internal_r (argc, argv, options, long_options, opt_index,
1, d);
}
#endif /* Not ELIDE_CODE. */ #endif /* Not ELIDE_CODE. */
@ -106,9 +104,7 @@ libc_hidden_def (getopt_long_only)
#include <stdio.h> #include <stdio.h>
int int
main (argc, argv) main (int argc, char **argv)
int argc;
char **argv;
{ {
int c; int c;
int digit_optind = 0; int digit_optind = 0;

130
posix/getopt_int.h Normal file
View file

@ -0,0 +1,130 @@
/* Internal declarations for getopt.
Copyright (C) 1989-1994,1996-1999,2001,2003,2004
Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _GETOPT_INT_H
#define _GETOPT_INT_H 1
extern int _getopt_internal (int ___argc, char *const *___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind,
int __long_only);
/* Reentrant versions which can handle parsing multiple argument
vectors at the same time. */
/* Data type for reentrant functions. */
struct _getopt_data
{
/* These have exactly the same meaning as the corresponding global
variables, except that they are used for the reentrant
versions of getopt. */
int optind;
int opterr;
int optopt;
char *optarg;
/* Internal members. */
/* True if the internal members have been initialized. */
int __initialized;
/* The next char to be scanned in the option-element
in which the last option character we returned was found.
This allows us to pick up the scan where we left off.
If this is zero, or a null string, it means resume the scan
by advancing to the next ARGV-element. */
char *__nextchar;
/* Describe how to deal with options that follow non-option ARGV-elements.
If the caller did not specify anything,
the default is REQUIRE_ORDER if the environment variable
POSIXLY_CORRECT is defined, PERMUTE otherwise.
REQUIRE_ORDER means don't recognize them as options;
stop option processing when the first non-option is seen.
This is what Unix does.
This mode of operation is selected by either setting the environment
variable POSIXLY_CORRECT, or using `+' as the first character
of the list of option characters.
PERMUTE is the default. We permute the contents of ARGV as we
scan, so that eventually all the non-options are at the end.
This allows options to be given in any order, even with programs
that were not written to expect this.
RETURN_IN_ORDER is an option available to programs that were
written to expect options and other ARGV-elements in any order
and that care about the ordering of the two. We describe each
non-option ARGV-element as if it were the argument of an option
with character code 1. Using `-' as the first character of the
list of option characters selects this mode of operation.
The special argument `--' forces an end of option-scanning regardless
of the value of `ordering'. In the case of RETURN_IN_ORDER, only
`--' can cause `getopt' to return -1 with `optind' != ARGC. */
enum
{
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
} __ordering;
/* If the POSIXLY_CORRECT environment variable is set. */
int __posixly_correct;
/* Handle permutation of arguments. */
/* Describe the part of ARGV that contains non-options that have
been skipped. `first_nonopt' is the index in ARGV of the first
of them; `last_nonopt' is the index after the last of them. */
int __first_nonopt;
int __last_nonopt;
#if defined _LIBC && defined USE_NONOPTION_FLAGS
int __nonoption_flags_max_len;
int __nonoption_flags_len;
# endif
};
/* The initializer is necessary to set OPTIND and OPTERR to their
default values and to clear the initialization flag. */
#define _GETOPT_DATA_INITIALIZER { 1, 1 }
extern int _getopt_internal_r (int ___argc, char *const *___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind,
int __long_only, struct _getopt_data *__data);
extern int _getopt_long_r (int ___argc, char *const *___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind,
struct _getopt_data *__data);
extern int _getopt_long_only_r (int ___argc, char *const *___argv,
const char *__shortopts,
const struct option *__longopts,
int *__longind,
struct _getopt_data *__data);
#endif /* getopt_int.h */