bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Bug-gnulib] getopt fix to prevent it from lying to the compiler abo


From: Paul Eggert
Subject: Re: [Bug-gnulib] getopt fix to prevent it from lying to the compiler about const
Date: Tue, 16 Nov 2004 17:18:25 -0800
User-agent: Gnus/5.1006 (Gnus v5.10.6) Emacs/21.3 (gnu/linux)

Bruno Haible <address@hidden> writes:

> Separating getopt into getopt and getopt_permute (or getopt_reorder)
> indeed looks like the cleanest solution.

I tried it with coreutils, and in hindsight it's even cleaner just to
make getopt behave in the standard way.  People who want getopt_permute
can just invoke getopt_long with a couple of extra NULL arguments.  This
simplifies autoconfigury and explanation.

> I don't see the need for getopt_long_permute and getopt_long_only_permute:

Good point.  I removed those too.

> The only remaining problem with this solution would be that on non-glibc
> systems, programs that are not yet adapted (i.e. which call getopt(),
> not getopt_permute()) will get a POSIX compliant getopt(), which handles
> "--" in an inferior way.

Yes, that's a drawback, but I think the advantages outweigh it.  I
installed this:


2004-11-16  Paul Eggert  <address@hidden>

        * getopt.c (_getopt_initialize, _getopt_internal_r, _getopt_internal):
        New arg POSIXLY_CORRECT.  All callers changed.
        (getopt): Argv is now char * const *, as per standard.
        (_getopt_internal_r, _getopt_internal): Argv is now char **,
        not char *__getopt_argv_const *.
        * getopt1.c (getopt_long, _getopt_long_r, getopt_long_only,
        _getopt_long_only_r): Likewise.
        * getopt_.h (getopt, getopt_long, geopt_long_only): Likewise.
        * getopt_int.h (_getopt_internal, _getopt_internal_r,
        _getopt_long_r, _getopt_long_only_r): Likewise.
        * getopt_.h (__getopt_argv_const): Remove.
        (getopt): Argv is now char * const *, as per standard.

Index: lib/getopt.c
===================================================================
RCS file: /fetish/cu/lib/getopt.c,v
retrieving revision 1.45
diff -p -u -r1.45 getopt.c
--- lib/getopt.c        12 Nov 2004 06:00:02 -0000      1.45
+++ lib/getopt.c        17 Nov 2004 01:01:19 -0000
@@ -62,16 +62,16 @@
 # define attribute_hidden
 #endif
 
-/* This version of `getopt' appears to the caller like standard Unix `getopt'
-   but it behaves differently for the user, since it allows the user
-   to intersperse the options with the other arguments.
+/* Unlike standard Unix `getopt', functions like `getopt_long'
+   let the user intersperse the options with the other arguments.
 
-   As `getopt' works, it permutes the elements of ARGV so that,
+   As `getopt_long' 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.
+   Using `getopt' or setting the environment variable POSIXLY_CORRECT
+   disables permutation.
+   Then the application's 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.  */
@@ -250,8 +250,8 @@ exchange (char **argv, struct _getopt_da
 /* Initialize the internal data when the first call is made.  */
 
 static const char *
-_getopt_initialize (int argc, char *__getopt_argv_const *argv,
-                   const char *optstring, struct _getopt_data *d)
+_getopt_initialize (int argc, char **argv, const char *optstring,
+                   int posixly_correct, struct _getopt_data *d)
 {
   /* Start processing options with ARGV-element 1 (since ARGV-element 0
      is the program name); the sequence of previously skipped
@@ -261,7 +261,7 @@ _getopt_initialize (int argc, char *__ge
 
   d->__nextchar = NULL;
 
-  d->__posixly_correct = !!getenv ("POSIXLY_CORRECT");
+  d->__posixly_correct = posixly_correct || !!getenv ("POSIXLY_CORRECT");
 
   /* Determine how to handle the ordering of options and nonoptions.  */
 
@@ -355,11 +355,6 @@ _getopt_initialize (int argc, char *__ge
    `flag' field is nonzero, the value of the option's `val' field
    if the `flag' field is zero.
 
-   The elements of ARGV aren't really const, because we permute them.
-   If __getopt_argv_const is defined to const, pretend they're
-   const in the prototype to be compatible with Posix.
-   But tell the truth if __getopt_argv_const is defined to empty.
-
    LONGOPTS is a vector of `struct option' terminated by an
    element containing a name which is zero.
 
@@ -368,13 +363,15 @@ _getopt_initialize (int argc, char *__ge
    recent call.
 
    If LONG_ONLY is nonzero, '-' as well as '--' can introduce
-   long-named options.  */
+   long-named options.
+
+   If POSIXLY_CORRECT is nonzero, behave as if the POSIXLY_CORRECT
+   environment variable were set.  */
 
 int
-_getopt_internal_r (int argc, char *__getopt_argv_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 long_only, int posixly_correct, struct _getopt_data *d)
 {
   int print_errors = d->opterr;
   if (optstring[0] == ':')
@@ -389,7 +386,8 @@ _getopt_internal_r (int argc, char *__ge
     {
       if (d->optind == 0)
        d->optind = 1;  /* Don't scan ARGV[0], the program name.  */
-      optstring = _getopt_initialize (argc, argv, optstring, d);
+      optstring = _getopt_initialize (argc, argv, optstring,
+                                     posixly_correct, d);
       d->__initialized = 1;
     }
 
@@ -1137,17 +1135,17 @@ _getopt_internal_r (int argc, char *__ge
 }
 
 int
-_getopt_internal (int argc, char *__getopt_argv_const *argv,
-                 const char *optstring,
-                 const struct option *longopts, int *longind, int long_only)
+_getopt_internal (int argc, char **argv, const char *optstring,
+                 const struct option *longopts, int *longind,
+                 int long_only, int posixly_correct)
 {
   int result;
 
   getopt_data.optind = optind;
   getopt_data.opterr = opterr;
 
-  result = _getopt_internal_r (argc, argv, optstring, longopts,
-                              longind, long_only, &getopt_data);
+  result = _getopt_internal_r (argc, argv, optstring, longopts, longind,
+                              long_only, posixly_correct, &getopt_data);
 
   optind = getopt_data.optind;
   optarg = getopt_data.optarg;
@@ -1157,12 +1155,9 @@ _getopt_internal (int argc, char *__geto
 }
 
 int
-getopt (int argc, char *__getopt_argv_const *argv, const char *optstring)
+getopt (int argc, char *const *argv, const char *optstring)
 {
-  return _getopt_internal (argc, argv, optstring,
-                          (const struct option *) 0,
-                          (int *) 0,
-                          0);
+  return _getopt_internal (argc, (char **) argv, optstring, NULL, NULL, 0, 1);
 }
 
 
Index: lib/getopt1.c
===================================================================
RCS file: /fetish/cu/lib/getopt1.c,v
retrieving revision 1.19
diff -p -u -r1.19 getopt1.c
--- lib/getopt1.c       12 Nov 2004 06:00:02 -0000      1.19
+++ lib/getopt1.c       17 Nov 2004 01:01:19 -0000
@@ -41,19 +41,19 @@
 #endif
 
 int
-getopt_long (int argc, char *__getopt_argv_const *argv, const char *options,
+getopt_long (int argc, char **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, 0);
 }
 
 int
-_getopt_long_r (int argc, char *__getopt_argv_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)
 {
   return _getopt_internal_r (argc, argv, options, long_options, opt_index,
-                            0, d);
+                            0, 0, d);
 }
 
 /* Like getopt_long, but '-' as well as '--' can indicate a long option.
@@ -62,21 +62,19 @@ _getopt_long_r (int argc, char *__getopt
    instead.  */
 
 int
-getopt_long_only (int argc, char *__getopt_argv_const *argv,
-                 const char *options,
+getopt_long_only (int argc, char **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, 0);
 }
 
 int
-_getopt_long_only_r (int argc, char *__getopt_argv_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)
 {
   return _getopt_internal_r (argc, argv, options, long_options, opt_index,
-                            1, d);
+                            1, 0, d);
 }
 
 
Index: lib/getopt_.h
===================================================================
RCS file: /fetish/cu/lib/getopt_.h,v
retrieving revision 1.3
diff -p -u -r1.3 getopt_.h
--- lib/getopt_.h       12 Nov 2004 06:00:02 -0000      1.3
+++ lib/getopt_.h       17 Nov 2004 01:01:19 -0000
@@ -53,18 +53,6 @@
 # define optopt __GETOPT_PREFIX##optopt
 #endif
 
-/* The elements of the ARGV arguments to getopt aren't really const,
-   because we permute them.  For glibc, __getopt_argv_const is const
-   so that prototypes pretend the elements are const, to be compatible
-   with Posix.  However, drop this pretense for standalone
-   applications, since it's not needed there and it's safer not to lie
-   to compilers.  */
-#ifdef __GETOPT_PREFIX
-# define __getopt_argv_const /* empty */
-#else
-# define __getopt_argv_const const
-#endif
-
 /* If __GNU_LIBRARY__ is not already defined, either we are being used
    standalone, or this is the first header included in the source file.
    If we are being used with glibc, we need to include <features.h>, but
@@ -186,16 +174,15 @@ struct option
    arguments to the option '\0'.  This behavior is specific to the GNU
    `getopt'.  */
 
-extern int getopt (int ___argc, char *__getopt_argv_const *___argv,
-                  const char *__shortopts)
+extern int getopt (int ___argc, char *const *___argv, const char *__shortopts)
        __THROW;
 
 #ifndef __need_getopt
-extern int getopt_long (int ___argc, char *__getopt_argv_const *___argv,
+extern int getopt_long (int ___argc, char **___argv,
                        const char *__shortopts,
                        const struct option *__longopts, int *__longind)
        __THROW;
-extern int getopt_long_only (int ___argc, char *__getopt_argv_const *___argv,
+extern int getopt_long_only (int ___argc, char **___argv,
                             const char *__shortopts,
                             const struct option *__longopts, int *__longind)
        __THROW;
Index: lib/getopt_int.h
===================================================================
RCS file: /fetish/cu/lib/getopt_int.h,v
retrieving revision 1.3
diff -p -u -r1.3 getopt_int.h
--- lib/getopt_int.h    12 Nov 2004 06:00:02 -0000      1.3
+++ lib/getopt_int.h    17 Nov 2004 01:01:19 -0000
@@ -20,10 +20,10 @@
 #ifndef _GETOPT_INT_H
 #define _GETOPT_INT_H  1
 
-extern int _getopt_internal (int ___argc, char *__getopt_argv_const *___argv,
+extern int _getopt_internal (int ___argc, char **___argv,
                             const char *__shortopts,
                             const struct option *__longopts, int *__longind,
-                            int __long_only);
+                            int __long_only, int __posixly_correct);
 
 
 /* Reentrant versions which can handle parsing multiple argument
@@ -64,7 +64,7 @@ struct _getopt_data
      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.
+     of the list of option characters, or by calling getopt.
 
      PERMUTE is the default.  We permute the contents of ARGV as we
      scan, so that eventually all the non-options are at the end.
@@ -87,7 +87,8 @@ struct _getopt_data
       REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
     } __ordering;
 
-  /* If the POSIXLY_CORRECT environment variable is set.  */
+  /* If the POSIXLY_CORRECT environment variable is set
+     or getopt was called.  */
   int __posixly_correct;
 
 
@@ -110,18 +111,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 *__getopt_argv_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 __long_only, int __posixly_correct,
+                              struct _getopt_data *__data);
 
-extern int _getopt_long_r (int ___argc, char *__getopt_argv_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 *__getopt_argv_const *___argv,
+extern int _getopt_long_only_r (int ___argc, char **___argv,
                                const char *__shortopts,
                                const struct option *__longopts,
                                int *__longind,





reply via email to

[Prev in Thread] Current Thread [Next in Thread]