about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog24
-rw-r--r--posix/getopt.c49
-rw-r--r--posix/getopt.h69
-rw-r--r--posix/getopt1.c17
-rw-r--r--posix/getopt_int.h8
5 files changed, 102 insertions, 65 deletions
diff --git a/ChangeLog b/ChangeLog
index d45be5fedd..e2587267b7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
diff --git a/posix/getopt.c b/posix/getopt.c
index 248fe5b03a..f54bc2d1cf 100644
--- a/posix/getopt.c
+++ b/posix/getopt.c
@@ -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
 
 
diff --git a/posix/getopt.h b/posix/getopt.h
index c83a186beb..fa6aa6be38 100644
--- a/posix/getopt.h
+++ b/posix/getopt.h
@@ -33,10 +33,11 @@
 # include <ctype.h>
 #endif
 
+#ifndef __GNUC_PREREQ
+# define __GNUC_PREREQ(maj, min) (0)
+#endif
+
 #ifndef __THROW
-# ifndef __GNUC_PREREQ
-#  define __GNUC_PREREQ(maj, min) (0)
-# endif
 # 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,45 +148,55 @@ 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
+#if defined __need_getopt && defined __USE_POSIX2 \
+    && !defined __USE_POSIX_IMPLICITLY && !defined __USE_GNU
 /* The GNU getopt has more functionality than the standard version.  The
    additional functionality can be disable at runtime.  This redirection
    helps to also do this at runtime.  */
-#  ifdef __REDIRECT
+# ifdef __REDIRECT
   extern int __REDIRECT_NTH (getopt, (int ___argc, char *const *___argv,
 				      const char *__shortopts),
 			     __posix_getopt);
-#  else
+# else
 extern int __posix_getopt (int ___argc, char *const *___argv,
-			   const char *__shortopts) __THROW;
-#   define getopt __posix_getopt
-#  endif
+			   const char *__shortopts)
+  __THROW __nonnull ((2, 3));
+#  define getopt __posix_getopt
 # endif
-#else /* not __GNU_LIBRARY__ */
-extern int getopt ();
-#endif /* __GNU_LIBRARY__ */
+#endif
 
 #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
 
diff --git a/posix/getopt1.c b/posix/getopt1.c
index b4ae6e48f2..b967d24f57 100644
--- a/posix/getopt1.c
+++ b/posix/getopt1.c
@@ -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},
diff --git a/posix/getopt_int.h b/posix/getopt_int.h
index 9ac03bdaaf..762679a305 100644
--- a/posix/getopt_int.h
+++ b/posix/getopt_int.h
@@ -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,