getopt: merge straightforward changes from gnulib

This covers changes with little or no consequences when the code is
used in glibc.

	* posix/getopt_int.h: Include getopt.h.
	Use impl-namespace names for all arguments to _getopt_internal and
	_getopt_internal_r.
	Declare __ordering enum outside the struct.
	Harmonize comments with gnulib.
	* posix/getopt1.c: Simplify #ifdeffage at top of file. Remove
	ELIDE_CODE logic entirely.  Move inclusion of stdlib.h to
	#ifdef TEST block and make unconditional.  Do not define NULL.
	* posix/getopt.c: Partial merge from gnulib, covering the
	initial includes and global declarations, commentary, and
	a couple of semantically-neutral code changes.
This commit is contained in:
Zack Weinberg 2017-03-31 07:58:07 -04:00
parent 7784135eb0
commit 7f71f9c1d6
4 changed files with 89 additions and 155 deletions

View File

@ -1,5 +1,17 @@
2017-04-07 Zack Weinberg <zackw@panix.com> 2017-04-07 Zack Weinberg <zackw@panix.com>
* posix/getopt_int.h: Include getopt.h.
Use impl-namespace names for all arguments to _getopt_internal and
_getopt_internal_r.
Declare __ordering enum outside the struct.
Harmonize comments with gnulib.
* posix/getopt1.c: Simplify #ifdeffage at top of file. Remove
ELIDE_CODE logic entirely. Move inclusion of stdlib.h to
#ifdef TEST block and make unconditional. Do not define NULL.
* posix/getopt.c: Partial merge from gnulib, covering the
initial includes and global declarations, commentary, and
a couple of semantically-neutral code changes.
* posix/getopt.c, posix/getopt.h, posix/getopt1.c, posix/getopt_int.h: * posix/getopt.c, posix/getopt.h, posix/getopt1.c, posix/getopt_int.h:
Use '...' instead of `...' for quotation marks inside Use '...' instead of `...' for quotation marks inside
comments and strings. comments and strings.

View File

@ -19,52 +19,17 @@
License along with the GNU C Library; if not, see License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */ <http://www.gnu.org/licenses/>. */
/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. #ifndef _LIBC
Ditto for AIX 3.2 and <stdlib.h>. */
#ifndef _NO_PROTO
# define _NO_PROTO
#endif
#ifdef HAVE_CONFIG_H
# include <config.h> # include <config.h>
#endif #endif
#include "getopt.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
/* Comment out all this code if we are using the GNU C Library, and are not #include <unistd.h>
actually compiling the library itself. This code is part of the GNU C
Library, but also included in many other GNU distributions. Compiling
and linking in this code is a waste when using the GNU C library
(especially if it is a shared library). Rather than having every GNU
program understand 'configure --with-gnu-libc' and omit the object files,
it is simpler to just do this in the source for each such file. */
#define GETOPT_INTERFACE_VERSION 2
#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
# include <gnu-versions.h>
# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
# define ELIDE_CODE
# endif
#endif
#ifndef ELIDE_CODE
/* This needs to come after some library #include
to get __GNU_LIBRARY__ defined. */
#ifdef __GNU_LIBRARY__
/* Don't include stdlib.h for non-GNU C libraries because some of them
contain conflicting prototypes for getopt. */
# include <stdlib.h>
# include <unistd.h>
#endif /* GNU C library. */
#include <string.h> #include <string.h>
#ifdef VMS
# include <unixlib.h>
#endif
#ifdef _LIBC #ifdef _LIBC
# include <libintl.h> # include <libintl.h>
#else #else
@ -72,29 +37,28 @@
# define _(msgid) gettext (msgid) # define _(msgid) gettext (msgid)
#endif #endif
#if defined _LIBC /* This implementation of 'getopt' has three modes for handling
# include <wchar.h> options interspersed with non-option arguments. It can stop
#endif scanning for options at the first non-option argument encountered,
as POSIX specifies. It can continue scanning for options after the
first non-option argument, but permute 'argv' as it goes so that,
after 'getopt' is done, all the options precede all the non-option
arguments and 'optind' points to the first non-option argument.
Or, it can report non-option arguments as if they were arguments to
the option character '\x01'.
#ifndef attribute_hidden The default behavior of 'getopt_long' is to permute the argument list.
# define attribute_hidden When this implementation is used standalone, the default behavior of
#endif 'getopt' is to stop at the first non-option argument, but when it is
used as part of GNU libc it also permutes the argument list. In both
cases, setting the environment variable POSIXLY_CORRECT to any value
disables permutation.
/* This version of 'getopt' appears to the caller like standard Unix 'getopt' If the first character of the OPTSTRING argument to 'getopt' or
but it behaves differently for the user, since it allows the user 'getopt_long' is '+', both functions will stop at the first
to intersperse the options with the other arguments. non-option argument. If it is '-', both functions will report
non-option arguments as arguments to the option character '\x01'. */
As 'getopt' works, it permutes the elements of ARGV so that,
when it is done, all the options precede everything else. Thus
all application programs are extended to handle flexible argument order.
Setting the environment variable POSIXLY_CORRECT disables permutation.
Then the behavior is completely standard.
GNU application programs can use a third alternative mode in which
they can distinguish the relative order of options and other arguments. */
#include "getopt.h"
#include "getopt_int.h" #include "getopt_int.h"
/* For communication from 'getopt' to the caller. /* For communication from 'getopt' to the caller.
@ -135,17 +99,6 @@ int optopt = '?';
static struct _getopt_data getopt_data; static struct _getopt_data getopt_data;
#ifndef __GNU_LIBRARY__
/* Avoid depending on library functions or files
whose names are inconsistent. */
#ifndef getenv
extern char *getenv ();
#endif
#endif /* not __GNU_LIBRARY__ */
/* Exchange two adjacent subsequences of ARGV. /* Exchange two adjacent subsequences of ARGV.
One subsequence is elements [first_nonopt,last_nonopt) One subsequence is elements [first_nonopt,last_nonopt)
@ -225,7 +178,7 @@ _getopt_initialize (int argc, char *const *argv, const char *optstring,
d->__nextchar = NULL; d->__nextchar = NULL;
d->__posixly_correct = posixly_correct | !!getenv ("POSIXLY_CORRECT"); d->__posixly_correct = 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. */
@ -731,7 +684,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
{ {
char c = *d->__nextchar++; char c = *d->__nextchar++;
char *temp = strchr (optstring, c); const 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 (*d->__nextchar == '\0') if (*d->__nextchar == '\0')
@ -776,9 +729,6 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
/* Convenience. Treat POSIX -W foo same as long option --foo */ /* Convenience. Treat POSIX -W foo same as long option --foo */
if (temp[0] == 'W' && temp[1] == ';') if (temp[0] == 'W' && temp[1] == ';')
{ {
if (longopts == NULL)
goto no_longs;
char *nameend; char *nameend;
const struct option *p; const struct option *p;
const struct option *pfound = NULL; const struct option *pfound = NULL;
@ -787,6 +737,9 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
int indfound = 0; int indfound = 0;
int option_index; int option_index;
if (longopts == NULL)
goto no_longs;
/* This is an option that requires an argument. */ /* This is an option that requires an argument. */
if (*d->__nextchar != '\0') if (*d->__nextchar != '\0')
{ {
@ -997,7 +950,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
no_longs: no_longs:
d->__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] == ':')
{ {
@ -1090,13 +1043,21 @@ _getopt_internal (int argc, char *const *argv, const char *optstring,
return result; return result;
} }
/* glibc gets a LSB-compliant getopt.
Standalone applications get a POSIX-compliant getopt. */
#if _LIBC
enum { POSIXLY_CORRECT = 0 };
#else
enum { POSIXLY_CORRECT = 1 };
#endif
int int
getopt (int argc, char *const *argv, const char *optstring) 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,
(int *) 0, (int *) 0,
0, 0); 0, POSIXLY_CORRECT);
} }
#ifdef _LIBC #ifdef _LIBC
@ -1110,7 +1071,6 @@ __posix_getopt (int argc, char *const *argv, const char *optstring)
} }
#endif #endif
#endif /* Not ELIDE_CODE. */
#ifdef TEST #ifdef TEST

View File

@ -16,48 +16,13 @@
License along with the GNU C Library; if not, see License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */ <http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H #ifndef _LIBC
#include <config.h> #include "config.h"
#endif #endif
#ifdef _LIBC #include "getopt.h"
# include <getopt.h>
#else
# include "getopt.h"
#endif
#include "getopt_int.h" #include "getopt_int.h"
#include <stdio.h>
/* Comment out all this code if we are using the GNU C Library, and are not
actually compiling the library itself. This code is part of the GNU C
Library, but also included in many other GNU distributions. Compiling
and linking in this code is a waste when using the GNU C library
(especially if it is a shared library). Rather than having every GNU
program understand 'configure --with-gnu-libc' and omit the object files,
it is simpler to just do this in the source for each such file. */
#define GETOPT_INTERFACE_VERSION 2
#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
#include <gnu-versions.h>
#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
#define ELIDE_CODE
#endif
#endif
#ifndef ELIDE_CODE
/* This needs to come after some library #include
to get __GNU_LIBRARY__ defined. */
#ifdef __GNU_LIBRARY__
#include <stdlib.h>
#endif
#ifndef NULL
#define NULL 0
#endif
int int
getopt_long (int argc, char *const *argv, const char *options, getopt_long (int argc, char *const *argv, const char *options,
const struct option *long_options, int *opt_index) const struct option *long_options, int *opt_index)
@ -95,11 +60,11 @@ _getopt_long_only_r (int argc, char *const *argv, const char *options,
1, d, 0); 1, d, 0);
} }
#endif /* Not ELIDE_CODE. */
#ifdef TEST #ifdef TEST
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
int int
main (int argc, char **argv) main (int argc, char **argv)

View File

@ -19,15 +19,43 @@
#ifndef _GETOPT_INT_H #ifndef _GETOPT_INT_H
#define _GETOPT_INT_H 1 #define _GETOPT_INT_H 1
#include <getopt.h>
extern int _getopt_internal (int ___argc, char *const *___argv, extern int _getopt_internal (int ___argc, char *const *___argv,
const char *__shortopts, const char *__shortopts,
const struct option *__longopts, int *__longind, const struct option *__longopts, int *__longind,
int __long_only, int posixly_correct); int __long_only, int __posixly_correct);
/* Reentrant versions which can handle parsing multiple argument /* Reentrant versions which can handle parsing multiple argument
vectors at the same time. */ vectors at the same time. */
/* Describe how to deal with options that follow non-option ARGV-elements.
REQUIRE_ORDER means don't recognize them as options; stop option
processing when the first non-option is seen. This is what POSIX
specifies should happen.
PERMUTE means 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.
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 __ord
{
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
};
/* Data type for reentrant functions. */ /* Data type for reentrant functions. */
struct _getopt_data struct _getopt_data
{ {
@ -52,41 +80,10 @@ struct _getopt_data
by advancing to the next ARGV-element. */ by advancing to the next ARGV-element. */
char *__nextchar; char *__nextchar;
/* Describe how to deal with options that follow non-option ARGV-elements. /* See __ord above. */
enum __ord __ordering;
If the caller did not specify anything, /* True if behaving strictly as specified by POSIX. */
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; int __posixly_correct;
@ -108,7 +105,7 @@ extern int _getopt_internal_r (int ___argc, char *const *___argv,
const char *__shortopts, const char *__shortopts,
const struct option *__longopts, int *__longind, const struct option *__longopts, int *__longind,
int __long_only, struct _getopt_data *__data, int __long_only, struct _getopt_data *__data,
int posixly_correct); int __posixly_correct);
extern int _getopt_long_r (int ___argc, char *const *___argv, extern int _getopt_long_r (int ___argc, char *const *___argv,
const char *__shortopts, const char *__shortopts,