* lib/argp-fmtstream.h (ARGP_FS_EI): Work around GCC 4.2.1 diagnostic
[gnulib.git] / lib / getopt.c
index 95b3604..3c23601 100644 (file)
@@ -2,48 +2,35 @@
    NOTE: getopt is now part of the C library, so if you don't know what
    "Keep this file name-space clean" means, talk to drepper@gnu.org
    before changing it!
-   Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002,2003,2004
-       Free Software Foundation, Inc.
+   Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002,2003,2004,2006
+       Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
-   This program is free software; you can redistribute it and/or modify
+   This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
-   You should have received a copy of the GNU General Public License along
-   with this program; if not, write to the Free Software Foundation,
-   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 \f
-/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
-   Ditto for AIX 3.2 and <stdlib.h>.  */
-#ifndef _NO_PROTO
-# define _NO_PROTO
-#endif
-
-#ifdef HAVE_CONFIG_H
+#ifndef _LIBC
 # include <config.h>
 #endif
 
-#include <stdio.h>
-
-/* 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 "getopt.h"
 
+#include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
-#ifdef VMS
+#ifdef __VMS
 # include <unixlib.h>
 #endif
 
 # 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.  */
 
-#include "getopt.h"
 #include "getopt_int.h"
 
 /* For communication from `getopt' to the caller.
@@ -118,16 +104,9 @@ int optopt = '?';
 static struct _getopt_data getopt_data;
 
 \f
-#ifndef __GNU_LIBRARY__
-
-/* Avoid depending on library functions or files
-   whose names are inconsistent.  */
-
-#ifndef getenv
+#if defined HAVE_DECL_GETENV && !HAVE_DECL_GETENV
 extern char *getenv ();
 #endif
-
-#endif /* not __GNU_LIBRARY__ */
 \f
 #ifdef _LIBC
 /* Stored original parameters.
@@ -250,8 +229,8 @@ 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,
-                   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 +240,7 @@ _getopt_initialize (int argc, char *const *argv, const char *optstring,
 
   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,10 +334,6 @@ _getopt_initialize (int argc, char *const *argv, const char *optstring,
    `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.
-   But we pretend they're const in the prototype to be compatible
-   with other systems.
-
    LONGOPTS is a vector of `struct option' terminated by an
    element containing a name which is zero.
 
@@ -367,12 +342,15 @@ _getopt_initialize (int argc, char *const *argv, const char *optstring,
    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 *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] == ':')
@@ -387,7 +365,8 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
     {
       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;
     }
 
@@ -556,10 +535,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
                  int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
                  ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
 
-                 if (_IO_fwide (stderr, 0) > 0)
-                   __fwprintf (stderr, L"%s", buf);
-                 else
-                   fputs (buf, stderr);
+                 __fxprintf (NULL, "%s", buf);
 
                  ((_IO_FILE *) stderr)->_flags2 = old_flags2;
                  _IO_funlockfile (stderr);
@@ -634,10 +610,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
                          ((_IO_FILE *) stderr)->_flags2
                            |= _IO_FLAGS2_NOTCANCEL;
 
-                         if (_IO_fwide (stderr, 0) > 0)
-                           __fwprintf (stderr, L"%s", buf);
-                         else
-                           fputs (buf, stderr);
+                         __fxprintf (NULL, "%s", buf);
 
                          ((_IO_FILE *) stderr)->_flags2 = old_flags2;
                          _IO_funlockfile (stderr);
@@ -674,10 +647,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
                          ((_IO_FILE *) stderr)->_flags2
                            |= _IO_FLAGS2_NOTCANCEL;
 
-                         if (_IO_fwide (stderr, 0) > 0)
-                           __fwprintf (stderr, L"%s", buf);
-                         else
-                           fputs (buf, stderr);
+                         __fxprintf (NULL, "%s", buf);
 
                          ((_IO_FILE *) stderr)->_flags2 = old_flags2;
                          _IO_funlockfile (stderr);
@@ -751,10 +721,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
                  int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
                  ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
 
-                 if (_IO_fwide (stderr, 0) > 0)
-                   __fwprintf (stderr, L"%s", buf);
-                 else
-                   fputs (buf, stderr);
+                 __fxprintf (NULL, "%s", buf);
 
                  ((_IO_FILE *) stderr)->_flags2 = old_flags2;
                  _IO_funlockfile (stderr);
@@ -817,10 +784,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
                int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
                ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
 
-               if (_IO_fwide (stderr, 0) > 0)
-                 __fwprintf (stderr, L"%s", buf);
-               else
-                 fputs (buf, stderr);
+               __fxprintf (NULL, "%s", buf);
 
                ((_IO_FILE *) stderr)->_flags2 = old_flags2;
                _IO_funlockfile (stderr);
@@ -868,10 +832,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
                    int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
                    ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
 
-                   if (_IO_fwide (stderr, 0) > 0)
-                     __fwprintf (stderr, L"%s", buf);
-                   else
-                     fputs (buf, stderr);
+                   __fxprintf (NULL, "%s", buf);
 
                    ((_IO_FILE *) stderr)->_flags2 = old_flags2;
                    _IO_funlockfile (stderr);
@@ -940,10 +901,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
                    int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
                    ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
 
-                   if (_IO_fwide (stderr, 0) > 0)
-                     __fwprintf (stderr, L"%s", buf);
-                   else
-                     fputs (buf, stderr);
+                   __fxprintf (NULL, "%s", buf);
 
                    ((_IO_FILE *) stderr)->_flags2 = old_flags2;
                    _IO_funlockfile (stderr);
@@ -985,10 +943,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
                            ((_IO_FILE *) stderr)->_flags2
                              |= _IO_FLAGS2_NOTCANCEL;
 
-                           if (_IO_fwide (stderr, 0) > 0)
-                             __fwprintf (stderr, L"%s", buf);
-                           else
-                             fputs (buf, stderr);
+                           __fxprintf (NULL, "%s", buf);
 
                            ((_IO_FILE *) stderr)->_flags2 = old_flags2;
                            _IO_funlockfile (stderr);
@@ -1027,10 +982,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
                            ((_IO_FILE *) stderr)->_flags2
                              |= _IO_FLAGS2_NOTCANCEL;
 
-                           if (_IO_fwide (stderr, 0) > 0)
-                             __fwprintf (stderr, L"%s", buf);
-                           else
-                             fputs (buf, stderr);
+                           __fxprintf (NULL, "%s", buf);
 
                            ((_IO_FILE *) stderr)->_flags2 = old_flags2;
                            _IO_funlockfile (stderr);
@@ -1101,10 +1053,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
                        int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
                        ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
 
-                       if (_IO_fwide (stderr, 0) > 0)
-                         __fwprintf (stderr, L"%s", buf);
-                       else
-                         fputs (buf, stderr);
+                       __fxprintf (NULL, "%s", buf);
 
                        ((_IO_FILE *) stderr)->_flags2 = old_flags2;
                        _IO_funlockfile (stderr);
@@ -1135,16 +1084,17 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
 }
 
 int
-_getopt_internal (int argc, char *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;
@@ -1153,13 +1103,19 @@ _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);
+  return _getopt_internal (argc, (char **) argv, optstring, NULL, NULL, 0,
+                          POSIXLY_CORRECT);
 }
 
 \f