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:
parent
544ce845de
commit
7a7be6c9a2
24
ChangeLog
24
ChangeLog
|
@ -1,5 +1,29 @@
|
||||||
2017-04-07 Zack Weinberg <zackw@panix.com>
|
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.
|
* stdio-common/fxprintf.c (__fxprintf_nocancel): New function.
|
||||||
(locked_vfxprintf): New helper function. Handle arbitrary
|
(locked_vfxprintf): New helper function. Handle arbitrary
|
||||||
multibyte strings, not just ASCII.
|
multibyte strings, not just ASCII.
|
||||||
|
|
|
@ -182,7 +182,7 @@ exchange (char **argv, struct _getopt_data *d)
|
||||||
/* Initialize the internal data when the first call is made. */
|
/* Initialize the internal data when the first call is made. */
|
||||||
|
|
||||||
static const char *
|
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)
|
struct _getopt_data *d, int posixly_correct)
|
||||||
{
|
{
|
||||||
/* Start processing options with ARGV-element 1 (since ARGV-element 0
|
/* 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. */
|
long-named options. */
|
||||||
|
|
||||||
int
|
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,
|
const struct option *longopts, int *longind,
|
||||||
int long_only, struct _getopt_data *d, int posixly_correct)
|
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
|
if (d->__first_nonopt != d->__last_nonopt
|
||||||
&& d->__last_nonopt != d->optind)
|
&& d->__last_nonopt != d->optind)
|
||||||
exchange ((char **) argv, d);
|
exchange (argv, d);
|
||||||
else if (d->__last_nonopt != d->optind)
|
else if (d->__last_nonopt != d->optind)
|
||||||
d->__first_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
|
if (d->__first_nonopt != d->__last_nonopt
|
||||||
&& d->__last_nonopt != d->optind)
|
&& d->__last_nonopt != d->optind)
|
||||||
exchange ((char **) argv, d);
|
exchange (argv, d);
|
||||||
else if (d->__first_nonopt == d->__last_nonopt)
|
else if (d->__first_nonopt == d->__last_nonopt)
|
||||||
d->__first_nonopt = d->optind;
|
d->__first_nonopt = d->optind;
|
||||||
d->__last_nonopt = argc;
|
d->__last_nonopt = argc;
|
||||||
|
@ -766,7 +766,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
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,
|
const struct option *longopts, int *longind, int long_only,
|
||||||
int posixly_correct)
|
int posixly_correct)
|
||||||
{
|
{
|
||||||
|
@ -786,32 +786,23 @@ _getopt_internal (int argc, char *const *argv, const char *optstring,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* glibc gets a LSB-compliant getopt.
|
/* glibc gets a LSB-compliant getopt and a POSIX-complaint __posix_getopt.
|
||||||
Standalone applications get a POSIX-compliant getopt. */
|
Standalone applications just get a POSIX-compliant getopt.
|
||||||
#if _LIBC
|
POSIX and LSB both require these functions to take 'char *const *argv'
|
||||||
enum { POSIXLY_CORRECT = 0 };
|
even though this is incorrect (because of the permutation). */
|
||||||
#else
|
#define GETOPT_ENTRY(NAME, POSIXLY_CORRECT) \
|
||||||
enum { POSIXLY_CORRECT = 1 };
|
int \
|
||||||
#endif
|
NAME (int argc, char *const *argv, const char *optstring) \
|
||||||
|
{ \
|
||||||
int
|
return _getopt_internal (argc, (char **)argv, optstring, \
|
||||||
getopt (int argc, char *const *argv, const char *optstring)
|
0, 0, 0, POSIXLY_CORRECT); \
|
||||||
{
|
}
|
||||||
return _getopt_internal (argc, argv, optstring,
|
|
||||||
(const struct option *) 0,
|
|
||||||
(int *) 0,
|
|
||||||
0, POSIXLY_CORRECT);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _LIBC
|
#ifdef _LIBC
|
||||||
int
|
GETOPT_ENTRY(getopt, 0)
|
||||||
__posix_getopt (int argc, char *const *argv, const char *optstring)
|
GETOPT_ENTRY(__posix_getopt, 1)
|
||||||
{
|
#else
|
||||||
return _getopt_internal (argc, argv, optstring,
|
GETOPT_ENTRY(getopt, 1)
|
||||||
(const struct option *) 0,
|
|
||||||
(int *) 0,
|
|
||||||
0, 1);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -33,10 +33,11 @@
|
||||||
# include <ctype.h>
|
# include <ctype.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef __GNUC_PREREQ
|
||||||
|
# define __GNUC_PREREQ(maj, min) (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef __THROW
|
#ifndef __THROW
|
||||||
# ifndef __GNUC_PREREQ
|
|
||||||
# define __GNUC_PREREQ(maj, min) (0)
|
|
||||||
# endif
|
|
||||||
# if defined __cplusplus && __GNUC_PREREQ (2,8)
|
# if defined __cplusplus && __GNUC_PREREQ (2,8)
|
||||||
# define __THROW throw ()
|
# define __THROW throw ()
|
||||||
# else
|
# else
|
||||||
|
@ -44,6 +45,14 @@
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef __nonnull
|
||||||
|
# if __GNUC_PREREQ (3, 3)
|
||||||
|
# define __nonnull(params) __attribute__ ((__nonnull__ params))
|
||||||
|
# else
|
||||||
|
# define __nonnull(params)
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -139,45 +148,55 @@ struct option
|
||||||
scanning, explicitly telling 'getopt' that there are no more
|
scanning, explicitly telling 'getopt' that there are no more
|
||||||
options.
|
options.
|
||||||
|
|
||||||
If OPTS begins with '--', then non-option arguments are treated as
|
If OPTS begins with '-', then non-option arguments are treated as
|
||||||
arguments to the option '\0'. This behavior is specific to the GNU
|
arguments to the option '\1'. This behavior is specific to the GNU
|
||||||
'getopt'. */
|
'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)
|
extern int getopt (int ___argc, char *const *___argv, const char *__shortopts)
|
||||||
__THROW;
|
__THROW __nonnull ((2, 3));
|
||||||
|
|
||||||
# if defined __need_getopt && defined __USE_POSIX2 \
|
#if defined __need_getopt && defined __USE_POSIX2 \
|
||||||
&& !defined __USE_POSIX_IMPLICITLY && !defined __USE_GNU
|
&& !defined __USE_POSIX_IMPLICITLY && !defined __USE_GNU
|
||||||
/* The GNU getopt has more functionality than the standard version. The
|
/* The GNU getopt has more functionality than the standard version. The
|
||||||
additional functionality can be disable at runtime. This redirection
|
additional functionality can be disable at runtime. This redirection
|
||||||
helps to also do this at runtime. */
|
helps to also do this at runtime. */
|
||||||
# ifdef __REDIRECT
|
# ifdef __REDIRECT
|
||||||
extern int __REDIRECT_NTH (getopt, (int ___argc, char *const *___argv,
|
extern int __REDIRECT_NTH (getopt, (int ___argc, char *const *___argv,
|
||||||
const char *__shortopts),
|
const char *__shortopts),
|
||||||
__posix_getopt);
|
__posix_getopt);
|
||||||
# else
|
# else
|
||||||
extern int __posix_getopt (int ___argc, char *const *___argv,
|
extern int __posix_getopt (int ___argc, char *const *___argv,
|
||||||
const char *__shortopts) __THROW;
|
const char *__shortopts)
|
||||||
# define getopt __posix_getopt
|
__THROW __nonnull ((2, 3));
|
||||||
# endif
|
# define getopt __posix_getopt
|
||||||
# endif
|
# endif
|
||||||
#else /* not __GNU_LIBRARY__ */
|
#endif
|
||||||
extern int getopt ();
|
|
||||||
#endif /* __GNU_LIBRARY__ */
|
|
||||||
|
|
||||||
#ifndef __need_getopt
|
#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 char *__shortopts,
|
||||||
const struct option *__longopts, int *__longind)
|
const struct option *__longopts, int *__longind)
|
||||||
__THROW;
|
__THROW __nonnull ((2, 3));
|
||||||
extern int getopt_long_only (int ___argc, char *const *___argv,
|
extern int getopt_long_only (int ___argc, char *__getopt_argv_const *___argv,
|
||||||
const char *__shortopts,
|
const char *__shortopts,
|
||||||
const struct option *__longopts, int *__longind)
|
const struct option *__longopts, int *__longind)
|
||||||
__THROW;
|
__THROW __nonnull ((2, 3));
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -24,14 +24,15 @@
|
||||||
#include "getopt_int.h"
|
#include "getopt_int.h"
|
||||||
|
|
||||||
int
|
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)
|
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
|
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,
|
const struct option *long_options, int *opt_index,
|
||||||
struct _getopt_data *d)
|
struct _getopt_data *d)
|
||||||
{
|
{
|
||||||
|
@ -45,14 +46,16 @@ _getopt_long_r (int argc, char *const *argv, const char *options,
|
||||||
instead. */
|
instead. */
|
||||||
|
|
||||||
int
|
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)
|
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
|
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,
|
const struct option *long_options, int *opt_index,
|
||||||
struct _getopt_data *d)
|
struct _getopt_data *d)
|
||||||
{
|
{
|
||||||
|
@ -76,7 +79,7 @@ main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
int this_option_optind = optind ? optind : 1;
|
int this_option_optind = optind ? optind : 1;
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
static struct option long_options[] =
|
static const struct option long_options[] =
|
||||||
{
|
{
|
||||||
{"add", 1, 0, 0},
|
{"add", 1, 0, 0},
|
||||||
{"append", 0, 0, 0},
|
{"append", 0, 0, 0},
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
|
||||||
extern int _getopt_internal (int ___argc, char *const *___argv,
|
extern int _getopt_internal (int ___argc, char **___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);
|
||||||
|
@ -101,18 +101,18 @@ struct _getopt_data
|
||||||
default values and to clear the initialization flag. */
|
default values and to clear the initialization flag. */
|
||||||
#define _GETOPT_DATA_INITIALIZER { 1, 1 }
|
#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 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 **___argv,
|
||||||
const char *__shortopts,
|
const char *__shortopts,
|
||||||
const struct option *__longopts, int *__longind,
|
const struct option *__longopts, int *__longind,
|
||||||
struct _getopt_data *__data);
|
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 char *__shortopts,
|
||||||
const struct option *__longopts,
|
const struct option *__longopts,
|
||||||
int *__longind,
|
int *__longind,
|
||||||
|
|
Loading…
Reference in New Issue