getopt: merge from gnulib: function prototype adjustments

For standards compliance, getopt, getopt_long, and getopt_long_only in
glibc have to take 'char *const *argv' even though they can mutate the
array.  gnulib has tried to clean this up as much as possible: all the
internal functions use 'char **argv', and when used standalone, so do
getopt_long and getopt_long_only.

Also brought over are __nonnull annotations, corrections to documentation,
and apparently it is no longer necessary to worry about conflicting
prototypes for getopt.  The macroification of the definitions of
getopt and __posix_getopt goes beyond what is currently in gnulib.

At this point getopt1.c and getopt_int.h are identical to their gnulib
versions.

	* posix/getopt.h: Add backup definition of __nonnull for
	consistency with gnulib.  Define __getopt_argv_const to const
	if not already defined.
	(getopt): Update doc comment from gnulib.  Prototype
	unconditionally.  Add __nonnull annotation.
	(__posix_getopt): Add __nonnull annotation.
	(getopt_long, getopt_long_only): Use __getopt_argv_const in
	prototypes for consistency with gnulib.  Add __nonnull
	annotations.
	* posix/getopt.c (_getopt_initialize, _getopt_internal_r)
	(getopt_internal): Change 'argv' argument to type 'char **'.
	Remove now-unnecessary casts.
	(getopt, __posix_getopt): Eliminate repetition with a macro.
	Cast 'argv' to 'char **' when calling _getopt_internal.
	* posix/getopt1.c (getopt_long, getopt_long_only):
	Use __getopt_argv_const for consistency with gnulib.
	Cast 'argv' to 'char **' when calling _getopt_internal.
	(_getopt_long_r, _getopt_long_only_r):
	Change 'argv' argument to type 'char **'.
	(main): Constify 'long_options'.
	* posix/getopt_int.h (getopt_internal, _getopt_internal_r)
	(_getopt_long_r, _getopt_long_only_r):
	Change 'argv' argument to type 'char **'.
This commit is contained in:
Zack Weinberg 2017-04-01 12:11:33 -04:00
parent 544ce845de
commit 7a7be6c9a2
5 changed files with 102 additions and 65 deletions

View File

@ -1,5 +1,29 @@
2017-04-07 Zack Weinberg <zackw@panix.com>
* posix/getopt.h: Add backup definition of __nonnull for
consistency with gnulib. Define __getopt_argv_const to const
if not already defined.
(getopt): Update doc comment from gnulib. Prototype
unconditionally. Add __nonnull annotation.
(__posix_getopt): Add __nonnull annotation.
(getopt_long, getopt_long_only): Use __getopt_argv_const in
prototypes for consistency with gnulib. Add __nonnull
annotations.
* posix/getopt.c (_getopt_initialize, _getopt_internal_r)
(getopt_internal): Change 'argv' argument to type 'char **'.
Remove now-unnecessary casts.
(getopt, __posix_getopt): Eliminate repetition with a macro.
Cast 'argv' to 'char **' when calling _getopt_internal.
* posix/getopt1.c (getopt_long, getopt_long_only):
Use __getopt_argv_const for consistency with gnulib.
Cast 'argv' to 'char **' when calling _getopt_internal.
(_getopt_long_r, _getopt_long_only_r):
Change 'argv' argument to type 'char **'.
(main): Constify 'long_options'.
* posix/getopt_int.h (getopt_internal, _getopt_internal_r)
(_getopt_long_r, _getopt_long_only_r):
Change 'argv' argument to type 'char **'.
* stdio-common/fxprintf.c (__fxprintf_nocancel): New function.
(locked_vfxprintf): New helper function. Handle arbitrary
multibyte strings, not just ASCII.

View File

@ -182,7 +182,7 @@ exchange (char **argv, struct _getopt_data *d)
/* Initialize the internal data when the first call is made. */
static const char *
_getopt_initialize (int argc, char *const *argv, const char *optstring,
_getopt_initialize (int argc, char **argv, const char *optstring,
struct _getopt_data *d, int posixly_correct)
{
/* Start processing options with ARGV-element 1 (since ARGV-element 0
@ -272,7 +272,7 @@ _getopt_initialize (int argc, char *const *argv, const char *optstring,
long-named options. */
int
_getopt_internal_r (int argc, char *const *argv, const char *optstring,
_getopt_internal_r (int argc, char **argv, const char *optstring,
const struct option *longopts, int *longind,
int long_only, struct _getopt_data *d, int posixly_correct)
{
@ -317,7 +317,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
if (d->__first_nonopt != d->__last_nonopt
&& d->__last_nonopt != d->optind)
exchange ((char **) argv, d);
exchange (argv, d);
else if (d->__last_nonopt != d->optind)
d->__first_nonopt = d->optind;
@ -340,7 +340,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
if (d->__first_nonopt != d->__last_nonopt
&& d->__last_nonopt != d->optind)
exchange ((char **) argv, d);
exchange (argv, d);
else if (d->__first_nonopt == d->__last_nonopt)
d->__first_nonopt = d->optind;
d->__last_nonopt = argc;
@ -766,7 +766,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
}
int
_getopt_internal (int argc, char *const *argv, const char *optstring,
_getopt_internal (int argc, char **argv, const char *optstring,
const struct option *longopts, int *longind, int long_only,
int posixly_correct)
{
@ -786,32 +786,23 @@ _getopt_internal (int argc, char *const *argv, const char *optstring,
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
getopt (int argc, char *const *argv, const char *optstring)
{
return _getopt_internal (argc, argv, optstring,
(const struct option *) 0,
(int *) 0,
0, POSIXLY_CORRECT);
/* glibc gets a LSB-compliant getopt and a POSIX-complaint __posix_getopt.
Standalone applications just get a POSIX-compliant getopt.
POSIX and LSB both require these functions to take 'char *const *argv'
even though this is incorrect (because of the permutation). */
#define GETOPT_ENTRY(NAME, POSIXLY_CORRECT) \
int \
NAME (int argc, char *const *argv, const char *optstring) \
{ \
return _getopt_internal (argc, (char **)argv, optstring, \
0, 0, 0, POSIXLY_CORRECT); \
}
#ifdef _LIBC
int
__posix_getopt (int argc, char *const *argv, const char *optstring)
{
return _getopt_internal (argc, argv, optstring,
(const struct option *) 0,
(int *) 0,
0, 1);
}
GETOPT_ENTRY(getopt, 0)
GETOPT_ENTRY(__posix_getopt, 1)
#else
GETOPT_ENTRY(getopt, 1)
#endif

View File

@ -33,10 +33,11 @@
# include <ctype.h>
#endif
#ifndef __THROW
#ifndef __GNUC_PREREQ
# define __GNUC_PREREQ(maj, min) (0)
#endif
#ifndef __THROW
# if defined __cplusplus && __GNUC_PREREQ (2,8)
# define __THROW throw ()
# else
@ -44,6 +45,14 @@
# endif
#endif
#ifndef __nonnull
# if __GNUC_PREREQ (3, 3)
# define __nonnull(params) __attribute__ ((__nonnull__ params))
# else
# define __nonnull(params)
# endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
@ -139,16 +148,18 @@ struct option
scanning, explicitly telling 'getopt' that there are no more
options.
If OPTS begins with '--', then non-option arguments are treated as
arguments to the option '\0'. This behavior is specific to the GNU
'getopt'. */
If OPTS begins with '-', then non-option arguments are treated as
arguments to the option '\1'. This behavior is specific to the GNU
'getopt'. If OPTS begins with '+', or POSIXLY_CORRECT is set in
the environment, then do not permute arguments.
For standards compliance, the 'argv' argument has the type
char *const *, but this is inaccurate; if argument permutation is
enabled, the argv array (not the strings it points to) must be
writable. */
#ifdef __GNU_LIBRARY__
/* Many other libraries have conflicting prototypes for getopt, with
differences in the consts, in stdlib.h. To avoid compilation
errors, only prototype getopt for the GNU C library. */
extern int getopt (int ___argc, char *const *___argv, const char *__shortopts)
__THROW;
__THROW __nonnull ((2, 3));
#if defined __need_getopt && defined __USE_POSIX2 \
&& !defined __USE_POSIX_IMPLICITLY && !defined __USE_GNU
@ -161,23 +172,31 @@ extern int getopt (int ___argc, char *const *___argv, const char *__shortopts)
__posix_getopt);
# else
extern int __posix_getopt (int ___argc, char *const *___argv,
const char *__shortopts) __THROW;
const char *__shortopts)
__THROW __nonnull ((2, 3));
# define getopt __posix_getopt
# endif
#endif
#else /* not __GNU_LIBRARY__ */
extern int getopt ();
#endif /* __GNU_LIBRARY__ */
#ifndef __need_getopt
extern int getopt_long (int ___argc, char *const *___argv,
/* The type of the 'argv' argument to getopt_long and getopt_long_only
is properly 'char **', since both functions may write to the array
(in order to move all the options to the beginning). However, for
compatibility with old versions of LSB, glibc has to use 'char *const *'
instead. */
#ifndef __getopt_argv_const
# define __getopt_argv_const const
#endif
extern int getopt_long (int ___argc, char *__getopt_argv_const *___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind)
__THROW;
extern int getopt_long_only (int ___argc, char *const *___argv,
__THROW __nonnull ((2, 3));
extern int getopt_long_only (int ___argc, char *__getopt_argv_const *___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind)
__THROW;
__THROW __nonnull ((2, 3));
#endif

View File

@ -24,14 +24,15 @@
#include "getopt_int.h"
int
getopt_long (int argc, char *const *argv, const char *options,
getopt_long (int argc, char *__getopt_argv_const *argv, const char *options,
const struct option *long_options, int *opt_index)
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 0, 0);
return _getopt_internal (argc, (char **) argv, options, long_options,
opt_index, 0, 0);
}
int
_getopt_long_r (int argc, char *const *argv, const char *options,
_getopt_long_r (int argc, char **argv, const char *options,
const struct option *long_options, int *opt_index,
struct _getopt_data *d)
{
@ -45,14 +46,16 @@ _getopt_long_r (int argc, char *const *argv, const char *options,
instead. */
int
getopt_long_only (int argc, char *const *argv, const char *options,
getopt_long_only (int argc, char *__getopt_argv_const *argv,
const char *options,
const struct option *long_options, int *opt_index)
{
return _getopt_internal (argc, argv, options, long_options, opt_index, 1, 0);
return _getopt_internal (argc, (char **) argv, options, long_options,
opt_index, 1, 0);
}
int
_getopt_long_only_r (int argc, char *const *argv, const char *options,
_getopt_long_only_r (int argc, char **argv, const char *options,
const struct option *long_options, int *opt_index,
struct _getopt_data *d)
{
@ -76,7 +79,7 @@ main (int argc, char **argv)
{
int this_option_optind = optind ? optind : 1;
int option_index = 0;
static struct option long_options[] =
static const struct option long_options[] =
{
{"add", 1, 0, 0},
{"append", 0, 0, 0},

View File

@ -21,7 +21,7 @@
#include <getopt.h>
extern int _getopt_internal (int ___argc, char *const *___argv,
extern int _getopt_internal (int ___argc, char **___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind,
int __long_only, int __posixly_correct);
@ -101,18 +101,18 @@ struct _getopt_data
default values and to clear the initialization flag. */
#define _GETOPT_DATA_INITIALIZER { 1, 1 }
extern int _getopt_internal_r (int ___argc, char *const *___argv,
extern int _getopt_internal_r (int ___argc, char **___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind,
int __long_only, struct _getopt_data *__data,
int __posixly_correct);
extern int _getopt_long_r (int ___argc, char *const *___argv,
extern int _getopt_long_r (int ___argc, char **___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,
extern int _getopt_long_only_r (int ___argc, char **___argv,
const char *__shortopts,
const struct option *__longopts,
int *__longind,