This is the mail archive of the glibc-cvs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

GNU C Library master sources branch master updated. glibc-2.25-196-g893ba3e


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, master has been updated
       via  893ba3eac9b07d0d5feac232c551af0e163f939c (commit)
       via  06576cbf4eae13324985df1a690afa2705c992cc (commit)
       via  10a33cf8b403e3c031c5dd10a06b4a2a6489e48c (commit)
       via  0f3be8721a86299600eae2d266934f661bf7c990 (commit)
       via  aeacb9f9127cff0ed099026156ca35c025f343b7 (commit)
       via  dfbea09f96ce9e7a56f88c47d1593f07dc55c53c (commit)
       via  c1af8775f2de694bd567813af51164e2d978a78d (commit)
       via  7a7be6c9a2a89ac5783d4f27d67b0fae3218228f (commit)
       via  544ce845def4540de11d9484df888df94876b14e (commit)
       via  7e161bef0bc9d5ea5e6f3dd490ecd5da6f642671 (commit)
       via  7f71f9c1d6735e713de193faf03edb37c4bcb563 (commit)
       via  7784135eb0de2d083bf3460c1386aee1c056e96e (commit)
       via  bf079e19f50d64aa5e05b5e17ec29afab9aabb20 (commit)
      from  e4e794841e3140875f2aa86b90e2ada3d61e1244 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=893ba3eac9b07d0d5feac232c551af0e163f939c

commit 893ba3eac9b07d0d5feac232c551af0e163f939c
Author: Paul Eggert <eggert@cs.ucla.edu>
Date:   Fri Apr 7 07:54:57 2017 -0400

    getopt: merge from gnulib: use angle-bracket includes consistently
    
    	* posix/getopt1.c: Include <config.h>, not "config.h".

diff --git a/ChangeLog b/ChangeLog
index fcd1cbd..848530c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2017-04-07  Paul Eggert  <eggert@cs.ucla.edu>
+
+	* posix/getopt1.c: Include <config.h>, not "config.h".
+
 2017-04-07  Zack Weinberg  <zackw@panix.com>
 
 	* posix/bits/getopt_core.h, posix/bits/getopt_ext.h
diff --git a/posix/getopt1.c b/posix/getopt1.c
index a1fab22..526dc31 100644
--- a/posix/getopt1.c
+++ b/posix/getopt1.c
@@ -18,7 +18,7 @@
    <http://www.gnu.org/licenses/>.  */
 
 #ifndef _LIBC
-#include "config.h"
+# include <config.h>
 #endif
 
 #include "getopt.h"

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=06576cbf4eae13324985df1a690afa2705c992cc

commit 06576cbf4eae13324985df1a690afa2705c992cc
Author: Zack Weinberg <zackw@panix.com>
Date:   Wed Apr 5 11:04:35 2017 -0400

    getopt: annotate files with relationship to gnulib.
    
    As the final act in this patchset, adjust the "This file is part of
    the GNU C Library" message at the top of each file to indicate which
    files are synced with gnulib.
    
    	* posix/bits/getopt_core.h, posix/bits/getopt_ext.h
    	* posix/getopt.c, posix/getopt1.c, posix/getopt_int.h:
    	Mention in top-of-file boilerplate that these files are shared
    	with gnulib.
    	* posix/getopt.h, posix/bits/getopt_posix.h:
    	Mention in top-of-file boilerplate that these files are NOT shared
    	with gnulib, unlike the rest of the getopt implementation.

diff --git a/ChangeLog b/ChangeLog
index 4637ffb..fcd1cbd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2017-04-07  Zack Weinberg  <zackw@panix.com>
 
+	* posix/bits/getopt_core.h, posix/bits/getopt_ext.h
+	* posix/getopt.c, posix/getopt1.c, posix/getopt_int.h:
+	Mention in top-of-file boilerplate that these files are shared
+	with gnulib.
+	* posix/getopt.h, posix/bits/getopt_posix.h:
+	Mention in top-of-file boilerplate that these files are NOT shared
+	with gnulib, unlike the rest of the getopt implementation.
+
 	* posix/bits/getopt_core.h, posix/bits/getopt_ext.h:
 	New files, intended to be shared with gnulib.
 	* posix/bits/getopt_posix.h:
diff --git a/posix/bits/getopt_core.h b/posix/bits/getopt_core.h
index 1e4dc25..1744c29 100644
--- a/posix/bits/getopt_core.h
+++ b/posix/bits/getopt_core.h
@@ -1,6 +1,7 @@
 /* Declarations for getopt (basic, portable features only).
    Copyright (C) 1989-2017 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
+   This file is part of the GNU C Library and is also part of gnulib.
+   Patches to this file should be submitted to both projects.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
diff --git a/posix/bits/getopt_ext.h b/posix/bits/getopt_ext.h
index 2382f88..c1a58da 100644
--- a/posix/bits/getopt_ext.h
+++ b/posix/bits/getopt_ext.h
@@ -1,6 +1,7 @@
 /* Declarations for getopt (GNU extensions).
    Copyright (C) 1989-2017 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
+   This file is part of the GNU C Library and is also part of gnulib.
+   Patches to this file should be submitted to both projects.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
diff --git a/posix/bits/getopt_posix.h b/posix/bits/getopt_posix.h
index 9436bb9..f9f3265 100644
--- a/posix/bits/getopt_posix.h
+++ b/posix/bits/getopt_posix.h
@@ -1,6 +1,7 @@
 /* Declarations for getopt (POSIX compatibility shim).
    Copyright (C) 1989-2017 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
+   Unlike the bulk of the getopt implementation, this file is NOT part
+   of gnulib.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
diff --git a/posix/getopt.c b/posix/getopt.c
index 6671787..543c8e7 100644
--- a/posix/getopt.c
+++ b/posix/getopt.c
@@ -1,9 +1,7 @@
 /* Getopt for GNU.
-   NOTE: getopt is 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-2017 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
+   This file is part of the GNU C Library and is also part of gnulib.
+   Patches to this file should be submitted to both projects.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
diff --git a/posix/getopt.h b/posix/getopt.h
index 2b63865..d9db3a6 100644
--- a/posix/getopt.h
+++ b/posix/getopt.h
@@ -1,6 +1,8 @@
 /* Declarations for getopt.
    Copyright (C) 1989-2017 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
+   Unlike the bulk of the getopt implementation, this file is NOT part
+   of gnulib; gnulib also has a getopt.h but it is different.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
diff --git a/posix/getopt1.c b/posix/getopt1.c
index b967d24..a1fab22 100644
--- a/posix/getopt1.c
+++ b/posix/getopt1.c
@@ -1,6 +1,7 @@
 /* getopt_long and getopt_long_only entry points for GNU getopt.
    Copyright (C) 1987-2017 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
+   This file is part of the GNU C Library and is also part of gnulib.
+   Patches to this file should be submitted to both projects.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
diff --git a/posix/getopt_int.h b/posix/getopt_int.h
index 6a02954..9a18d5d 100644
--- a/posix/getopt_int.h
+++ b/posix/getopt_int.h
@@ -1,6 +1,7 @@
 /* Internal declarations for getopt.
    Copyright (C) 1989-2017 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
+   This file is part of the GNU C Library and is also part of gnulib.
+   Patches to this file should be submitted to both projects.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=10a33cf8b403e3c031c5dd10a06b4a2a6489e48c

commit 10a33cf8b403e3c031c5dd10a06b4a2a6489e48c
Author: Zack Weinberg <zackw@panix.com>
Date:   Sat Mar 25 11:24:24 2017 -0400

    getopt: eliminate __need_getopt by splitting up getopt.h.
    
    __need_getopt is misnamed; what it really means is "we want only the
    getopt features specified in POSIX, not the GNU extensions".  Because
    this code is shared with gnulib, it winds up being cleanest to split
    getopt.h into *four* headers.  getopt_core.h and getopt_ext.h will
    be shared with gnulib, getopt_posix.h will be just for glibc, and
    each project will have its own copy of getopt.h.
    
    	* posix/bits/getopt_core.h, posix/bits/getopt_ext.h:
    	New files, intended to be shared with gnulib.
    	* posix/bits/getopt_posix.h:
    	New file, not intended to be shared with gnulib.
    	* posix/getopt.h: Now just includes features.h,
    	bits/getopt_core.h, and bits/getopt_ext.h.  Will
    	no longer be shared with gnulib.
    	* include/bits/getopt_core.h, include/bits/getopt_ext.h
    	* include/bits/getopt_posix.h: New wrappers.
    	* posix/Makefile: Install new headers.
    	* posix/unistd.h, libio/stdio.h:
    	Include bits/getopt_posix.h instead of getopt.h.

diff --git a/ChangeLog b/ChangeLog
index 7c0f6e9..4637ffb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
 2017-04-07  Zack Weinberg  <zackw@panix.com>
 
+	* posix/bits/getopt_core.h, posix/bits/getopt_ext.h:
+	New files, intended to be shared with gnulib.
+	* posix/bits/getopt_posix.h:
+	New file, not intended to be shared with gnulib.
+	* posix/getopt.h: Now just includes features.h,
+	bits/getopt_core.h, and bits/getopt_ext.h.  Will
+	no longer be shared with gnulib.
+	* include/bits/getopt_core.h, include/bits/getopt_ext.h
+	* include/bits/getopt_posix.h: New wrappers.
+	* posix/Makefile: Install new headers.
+	* posix/unistd.h, libio/stdio.h:
+	Include bits/getopt_posix.h instead of getopt.h.
+
 	* include/libc-symbols.h: For gnulib compatibility, define
 	_GL_UNUSED, _GL_UNUSED_LABEL, _GL_ATTRIBUTE_PURE, and
 	_GL_ATTRIBUTE_CONST.
diff --git a/include/bits/getopt_core.h b/include/bits/getopt_core.h
new file mode 100644
index 0000000..1200de8
--- /dev/null
+++ b/include/bits/getopt_core.h
@@ -0,0 +1 @@
+#include <posix/bits/getopt_core.h>
diff --git a/include/bits/getopt_ext.h b/include/bits/getopt_ext.h
new file mode 100644
index 0000000..31b9983
--- /dev/null
+++ b/include/bits/getopt_ext.h
@@ -0,0 +1 @@
+#include <posix/bits/getopt_ext.h>
diff --git a/include/bits/getopt_posix.h b/include/bits/getopt_posix.h
new file mode 100644
index 0000000..e3b70c8
--- /dev/null
+++ b/include/bits/getopt_posix.h
@@ -0,0 +1 @@
+#include <posix/bits/getopt_posix.h>
diff --git a/libio/stdio.h b/libio/stdio.h
index 3e01d54..422f39d 100644
--- a/libio/stdio.h
+++ b/libio/stdio.h
@@ -875,12 +875,10 @@ extern void funlockfile (FILE *__stream) __THROW;
 #endif /* POSIX */
 
 #if defined __USE_XOPEN && !defined __USE_XOPEN2K && !defined __USE_GNU
-/* The X/Open standard requires some functions and variables to be
-   declared here which do not belong into this header.  But we have to
-   follow.  In GNU mode we don't do this nonsense.  */
-# define __need_getopt
-# include <getopt.h>
-#endif	/* X/Open, but not issue 6 and not for GNU.  */
+/*  X/Open Issues 1-5 required getopt to be declared in this
+   header.  It was removed in Issue 6.  GNU follows Issue 6.  */
+# include <bits/getopt_posix.h>
+#endif
 
 /* If we are compiling with optimizing read this file.  It contains
    several optimizing inline functions and macros.  */
diff --git a/posix/Makefile b/posix/Makefile
index 8e29eea..a6586ea 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -23,7 +23,8 @@ subdir	:= posix
 include ../Makeconfig
 
 headers	:= sys/utsname.h sys/times.h sys/wait.h sys/types.h unistd.h	      \
-	   glob.h regex.h wordexp.h fnmatch.h getopt.h			      \
+	   glob.h regex.h wordexp.h fnmatch.h 				      \
+	   getopt.h bits/getopt_core.h bits/getopt_ext.h bits/getopt_posix.h  \
 	   bits/types.h bits/typesizes.h bits/pthreadtypes.h		      \
 	   bits/posix1_lim.h bits/posix2_lim.h bits/posix_opt.h		      \
 	   bits/local_lim.h tar.h bits/utsname.h bits/confname.h	      \
diff --git a/posix/bits/getopt_core.h b/posix/bits/getopt_core.h
new file mode 100644
index 0000000..1e4dc25
--- /dev/null
+++ b/posix/bits/getopt_core.h
@@ -0,0 +1,95 @@
+/* Declarations for getopt (basic, portable features only).
+   Copyright (C) 1989-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _GETOPT_CORE_H
+#define _GETOPT_CORE_H 1
+
+/* This header should not be used directly; include getopt.h or
+   unistd.h instead.  Unlike most bits headers, it does not have
+   a protective #error, because the guard macro for getopt.h in
+   gnulib is not fixed.  */
+
+__BEGIN_DECLS
+
+/* For communication from 'getopt' to the caller.
+   When 'getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when 'ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to 'getopt'.
+
+   On entry to 'getopt', zero means this is the first call; initialize.
+
+   When 'getopt' returns -1, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, 'optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message 'getopt' prints
+   for unrecognized options.  */
+
+extern int opterr;
+
+/* Set to an option character which was unrecognized.  */
+
+extern int optopt;
+
+/* Get definitions and prototypes for functions to process the
+   arguments in ARGV (ARGC of them, minus the program name) for
+   options given in OPTS.
+
+   Return the option character from OPTS just read.  Return -1 when
+   there are no more options.  For unrecognized options, or options
+   missing arguments, 'optopt' is set to the option letter, and '?' is
+   returned.
+
+   The OPTS string is a list of characters which are recognized option
+   letters, optionally followed by colons, specifying that that letter
+   takes an argument, to be placed in 'optarg'.
+
+   If a letter in OPTS is followed by two colons, its argument is
+   optional.  This behavior is specific to the GNU 'getopt'.
+
+   The argument '--' causes premature termination of argument
+   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 '\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.  */
+
+extern int getopt (int ___argc, char *const *___argv, const char *__shortopts)
+       __THROW __nonnull ((2, 3));
+
+__END_DECLS
+
+#endif /* getopt_core.h */
diff --git a/posix/bits/getopt_ext.h b/posix/bits/getopt_ext.h
new file mode 100644
index 0000000..2382f88
--- /dev/null
+++ b/posix/bits/getopt_ext.h
@@ -0,0 +1,76 @@
+/* Declarations for getopt (GNU extensions).
+   Copyright (C) 1989-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _GETOPT_EXT_H
+#define _GETOPT_EXT_H 1
+
+/* This header should not be used directly; include getopt.h instead.
+   Unlike most bits headers, it does not have a protective #error,
+   because the guard macro for getopt.h in gnulib is not fixed.  */
+
+__BEGIN_DECLS
+
+/* Describe the long-named options requested by the application.
+   The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+   of 'struct option' terminated by an element containing a name which is
+   zero.
+
+   The field 'has_arg' is:
+   no_argument		(or 0) if the option does not take an argument,
+   required_argument	(or 1) if the option requires an argument,
+   optional_argument 	(or 2) if the option takes an optional argument.
+
+   If the field 'flag' is not NULL, it points to a variable that is set
+   to the value given in the field 'val' when the option is found, but
+   left unchanged if the option is not found.
+
+   To have a long-named option do something other than set an 'int' to
+   a compiled-in constant, such as set a value from 'optarg', set the
+   option's 'flag' field to zero and its 'val' field to a nonzero
+   value (the equivalent single-letter option character, if there is
+   one).  For long options that have a zero 'flag' field, 'getopt'
+   returns the contents of the 'val' field.  */
+
+struct option
+{
+  const char *name;
+  /* has_arg can't be an enum because some compilers complain about
+     type mismatches in all the code that assumes it is an int.  */
+  int has_arg;
+  int *flag;
+  int val;
+};
+
+/* Names for the values of the 'has_arg' field of 'struct option'.  */
+
+#define no_argument		0
+#define required_argument	1
+#define optional_argument	2
+
+extern int getopt_long (int ___argc, char *__getopt_argv_const *___argv,
+			const char *__shortopts,
+		        const struct option *__longopts, int *__longind)
+       __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 __nonnull ((2, 3));
+
+__END_DECLS
+
+#endif /* getopt_ext.h */
diff --git a/posix/bits/getopt_posix.h b/posix/bits/getopt_posix.h
new file mode 100644
index 0000000..9436bb9
--- /dev/null
+++ b/posix/bits/getopt_posix.h
@@ -0,0 +1,50 @@
+/* Declarations for getopt (POSIX compatibility shim).
+   Copyright (C) 1989-2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _GETOPT_POSIX_H
+#define _GETOPT_POSIX_H 1
+
+#if !defined _UNISTD_H && !defined _STDIO_H
+#error "Never include getopt_posix.h directly; use unistd.h instead."
+#endif
+
+#include <bits/getopt_core.h>
+
+__BEGIN_DECLS
+
+#if defined __USE_POSIX2 && !defined __USE_POSIX_IMPLICITLY \
+    && !defined __USE_GNU && !defined _GETOPT_H
+/* GNU getopt has more functionality than POSIX getopt.  When we are
+   explicitly conforming to POSIX and not GNU, and getopt.h (which is
+   not part of POSIX) has not been included, the extra functionality
+   is disabled.  */
+# ifdef __REDIRECT
+extern int __REDIRECT_NTH (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 __nonnull ((2, 3));
+#  define getopt __posix_getopt
+# endif
+#endif
+
+__END_DECLS
+
+#endif /* getopt_posix.h */
diff --git a/posix/getopt.h b/posix/getopt.h
index fa6aa6b..2b63865 100644
--- a/posix/getopt.h
+++ b/posix/getopt.h
@@ -17,168 +17,9 @@
    <http://www.gnu.org/licenses/>.  */
 
 #ifndef _GETOPT_H
+#define _GETOPT_H 1
 
-#ifndef __need_getopt
-# define _GETOPT_H 1
-#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
-   that does not exist if we are standalone.  So: if __GNU_LIBRARY__ is
-   not defined, include <ctype.h>, which will pull in <features.h> for us
-   if it's from glibc.  (Why ctype.h?  It's guaranteed to exist and it
-   doesn't flood the namespace with stuff the way some other headers do.)  */
-#if !defined __GNU_LIBRARY__
-# include <ctype.h>
-#endif
-
-#ifndef __GNUC_PREREQ
-# define __GNUC_PREREQ(maj, min) (0)
-#endif
-
-#ifndef __THROW
-# if defined __cplusplus && __GNUC_PREREQ (2,8)
-#  define __THROW	throw ()
-# else
-#  define __THROW
-# 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
-
-/* For communication from 'getopt' to the caller.
-   When 'getopt' finds an option that takes an argument,
-   the argument value is returned here.
-   Also, when 'ordering' is RETURN_IN_ORDER,
-   each non-option ARGV-element is returned here.  */
-
-extern char *optarg;
-
-/* Index in ARGV of the next element to be scanned.
-   This is used for communication to and from the caller
-   and for communication between successive calls to 'getopt'.
-
-   On entry to 'getopt', zero means this is the first call; initialize.
-
-   When 'getopt' returns -1, this is the index of the first of the
-   non-option elements that the caller should itself scan.
-
-   Otherwise, 'optind' communicates from one call to the next
-   how much of ARGV has been scanned so far.  */
-
-extern int optind;
-
-/* Callers store zero here to inhibit the error message 'getopt' prints
-   for unrecognized options.  */
-
-extern int opterr;
-
-/* Set to an option character which was unrecognized.  */
-
-extern int optopt;
-
-#ifndef __need_getopt
-/* Describe the long-named options requested by the application.
-   The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
-   of 'struct option' terminated by an element containing a name which is
-   zero.
-
-   The field 'has_arg' is:
-   no_argument		(or 0) if the option does not take an argument,
-   required_argument	(or 1) if the option requires an argument,
-   optional_argument 	(or 2) if the option takes an optional argument.
-
-   If the field 'flag' is not NULL, it points to a variable that is set
-   to the value given in the field 'val' when the option is found, but
-   left unchanged if the option is not found.
-
-   To have a long-named option do something other than set an 'int' to
-   a compiled-in constant, such as set a value from 'optarg', set the
-   option's 'flag' field to zero and its 'val' field to a nonzero
-   value (the equivalent single-letter option character, if there is
-   one).  For long options that have a zero 'flag' field, 'getopt'
-   returns the contents of the 'val' field.  */
-
-struct option
-{
-  const char *name;
-  /* has_arg can't be an enum because some compilers complain about
-     type mismatches in all the code that assumes it is an int.  */
-  int has_arg;
-  int *flag;
-  int val;
-};
-
-/* Names for the values of the 'has_arg' field of 'struct option'.  */
-
-# define no_argument		0
-# define required_argument	1
-# define optional_argument	2
-#endif	/* need getopt */
-
-
-/* Get definitions and prototypes for functions to process the
-   arguments in ARGV (ARGC of them, minus the program name) for
-   options given in OPTS.
-
-   Return the option character from OPTS just read.  Return -1 when
-   there are no more options.  For unrecognized options, or options
-   missing arguments, 'optopt' is set to the option letter, and '?' is
-   returned.
-
-   The OPTS string is a list of characters which are recognized option
-   letters, optionally followed by colons, specifying that that letter
-   takes an argument, to be placed in 'optarg'.
-
-   If a letter in OPTS is followed by two colons, its argument is
-   optional.  This behavior is specific to the GNU 'getopt'.
-
-   The argument '--' causes premature termination of argument
-   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 '\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.  */
-
-extern int getopt (int ___argc, char *const *___argv, const char *__shortopts)
-       __THROW __nonnull ((2, 3));
-
-#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
-  extern int __REDIRECT_NTH (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 __nonnull ((2, 3));
-#  define getopt __posix_getopt
-# endif
-#endif
-
-#ifndef __need_getopt
+#include <features.h>
 
 /* The type of the 'argv' argument to getopt_long and getopt_long_only
    is properly 'char **', since both functions may write to the array
@@ -189,22 +30,7 @@ extern int __posix_getopt (int ___argc, char *const *___argv,
 # 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 __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 __nonnull ((2, 3));
-
-#endif
-
-#ifdef	__cplusplus
-}
-#endif
-
-/* Make sure we later can get all the definitions and declarations.  */
-#undef __need_getopt
+#include <bits/getopt_core.h>
+#include <bits/getopt_ext.h>
 
 #endif /* getopt.h */
diff --git a/posix/unistd.h b/posix/unistd.h
index fa2492e..32b0f48 100644
--- a/posix/unistd.h
+++ b/posix/unistd.h
@@ -869,8 +869,7 @@ extern int setlogin (const char *__name) __THROW __nonnull ((1));
 /* Get definitions and prototypes for functions to process the
    arguments in ARGV (ARGC of them, minus the program name) for
    options given in OPTS.  */
-# define __need_getopt
-# include <getopt.h>
+# include <bits/getopt_posix.h>
 #endif
 
 

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=0f3be8721a86299600eae2d266934f661bf7c990

commit 0f3be8721a86299600eae2d266934f661bf7c990
Author: Zack Weinberg <zackw@panix.com>
Date:   Mon Apr 3 08:45:41 2017 -0400

    getopt: merge _GL_UNUSED annotations from gnulib
    
    gnulib now has annotations on at least some functions to cater to
    compilation with -Wunused-parameter.  In order to follow suit cleanly,
    I've added to libc-symbols.h some of the _GL_* macros that
    gnulib-common.m4 puts into config.h.  (I don't think they belong in
    sys/cdefs.h, at least not without further thought.)
    
    At this point all gnulib-side changes to getopt.c have been merged.
    
    	* include/libc-symbols.h: For gnulib compatibility, define
    	_GL_UNUSED, _GL_UNUSED_LABEL, _GL_ATTRIBUTE_PURE, and
    	_GL_ATTRIBUTE_CONST.
    	* posix/getopt.c (_getopt_initialize): Mark argc and argv
    	parameters with _GL_UNUSED.

diff --git a/ChangeLog b/ChangeLog
index 4b8371a..7c0f6e9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2017-04-07  Zack Weinberg  <zackw@panix.com>
 
+	* include/libc-symbols.h: For gnulib compatibility, define
+	_GL_UNUSED, _GL_UNUSED_LABEL, _GL_ATTRIBUTE_PURE, and
+	_GL_ATTRIBUTE_CONST.
+	* posix/getopt.c (_getopt_initialize): Mark argc and argv
+	parameters with _GL_UNUSED.
+
 	* posix/getopt.c: When used standalone, define __libc_use_alloca
 	as always false and alloca to abort if called.
 	(process_long_option): Rewrite handling of ambiguous long options
diff --git a/include/libc-symbols.h b/include/libc-symbols.h
index 0783ade..18f26b2 100644
--- a/include/libc-symbols.h
+++ b/include/libc-symbols.h
@@ -892,5 +892,48 @@ for linking")
 #else
 # define inhibit_loop_to_libcall
 #endif
+
+/* These macros facilitate sharing source files with gnulib.
+
+   They are here instead of sys/cdefs.h because they should not be
+   used in public header files.
+
+   Their definitions should be kept consistent with the definitions in
+   gnulib-common.m4, but it is not necessary to cater to old non-GCC
+   compilers, since they will only be used while building glibc itself.
+   (Note that _GNUC_PREREQ cannot be used in this file.)  */
+
+/* Define as a marker that can be attached to declarations that might not
+    be used.  This helps to reduce warnings, such as from
+    GCC -Wunused-parameter.  */
+#if __GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
+# define _GL_UNUSED __attribute__ ((__unused__))
+#else
+# define _GL_UNUSED
+#endif
+
+/* gcc supports the "unused" attribute on possibly unused labels, and
+   g++ has since version 4.5.  Note to support C++ as well as C,
+   _GL_UNUSED_LABEL should be used with a trailing ;  */
+#if !defined __cplusplus || __GNUC__ > 4 \
+    || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
+# define _GL_UNUSED_LABEL _GL_UNUSED
+#else
+# define _GL_UNUSED_LABEL
+#endif
+
+/* The __pure__ attribute was added in gcc 2.96.  */
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
+# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
+#else
+# define _GL_ATTRIBUTE_PURE /* empty */
+#endif
+
+/* The __const__ attribute was added in gcc 2.95.  */
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
+# define _GL_ATTRIBUTE_CONST __attribute__ ((__const__))
+#else
+# define _GL_ATTRIBUTE_CONST /* empty */
+#endif
 
 #endif /* libc-symbols.h */
diff --git a/posix/getopt.c b/posix/getopt.c
index 79c81ae..6671787 100644
--- a/posix/getopt.c
+++ b/posix/getopt.c
@@ -379,7 +379,8 @@ process_long_option (int argc, char **argv, const char *optstring,
 /* Initialize internal data upon the first call to getopt.  */
 
 static const char *
-_getopt_initialize (int argc, char **argv, const char *optstring,
+_getopt_initialize (int argc _GL_UNUSED,
+		    char **argv _GL_UNUSED, const char *optstring,
 		    struct _getopt_data *d, int posixly_correct)
 {
   /* Start processing options with ARGV-element 1 (since ARGV-element 0

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=aeacb9f9127cff0ed099026156ca35c025f343b7

commit aeacb9f9127cff0ed099026156ca35c025f343b7
Author: Zack Weinberg <zackw@panix.com>
Date:   Sat Apr 1 17:13:45 2017 -0400

    getopt: merge from gnulib: alloca avoidance
    
    In one place, glibc's getopt uses alloca to construct a linked list of
    possibilities for an "ambiguous" long option.  In gnulib, malloc
    should be used instead.  Providing for both cases complicates things a
    fair bit.  Instead of merging straight across, therefore, I have
    chosen to rewrite it using a boolean vector instead of a linked list.
    There is then only one allocation that might need freeing; in glibc it
    can honor __libc_use_alloca as usual, and in gnulib we define
    __libc_use_alloca to always be false, so we don't need ifdefs in the
    middle of the function.  This should also be slightly more efficient
    in the normal case of long options being fully spelled out -- I think
    most people aren't even aware they _can_ sometimes abbreviate long
    options.
    
    One interesting consequence is that the list of possibilities is now
    printed in exactly the order they appear in the list of long options,
    instead of the first possibility being shuffled to the end.  This
    shouldn't be a big deal but it did break one test that relied on the
    exact text of this error message.
    
    (The reason the previous patch was "in aid of" merging from gnulib is
    I didn't want to have to make this change in two places.)
    
    (The patch looks bigger than it really is because there's a fair bit
    of reindentation and code rearrangement.)
    
    	* posix/getopt.c: When used standalone, define __libc_use_alloca
    	as always false and alloca to abort if called.
    	(process_long_option): Rewrite handling of ambiguous long options
    	to use a single boolean vector, not a linked list; use
    	__libc_use_alloca to decide whether to allocate this using alloca.
    
    	* posix/tst-getopt_long1.c: Adjust text of expected error message.

diff --git a/ChangeLog b/ChangeLog
index cf663d1..4b8371a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2017-04-07  Zack Weinberg  <zackw@panix.com>
 
+	* posix/getopt.c: When used standalone, define __libc_use_alloca
+	as always false and alloca to abort if called.
+	(process_long_option): Rewrite handling of ambiguous long options
+	to use a single boolean vector, not a linked list; use
+	__libc_use_alloca to decide whether to allocate this using alloca.
+	* posix/tst-getopt_long1.c: Adjust text of expected error message.
+
 	* posix/getopt.c (process_long_option): New function split out
 	from _getopt_internal_r.
 	(_getopt_internal_r): Replace both copies of the long-option
diff --git a/posix/getopt.c b/posix/getopt.c
index ecb9923..79c81ae 100644
--- a/posix/getopt.c
+++ b/posix/getopt.c
@@ -51,6 +51,10 @@
 #  define flockfile(fp) /* nop */
 #  define funlockfile(fp) /* nop */
 # endif
+/* When used standalone, do not attempt to use alloca.  */
+# define __libc_use_alloca(size) 0
+# undef alloca
+# define alloca(size) (abort (), (void *)0)
 #endif
 
 /* This implementation of 'getopt' has three modes for handling
@@ -197,150 +201,179 @@ process_long_option (int argc, char **argv, const char *optstring,
   size_t namelen;
   const struct option *p;
   const struct option *pfound = NULL;
-  struct option_list
-  {
-    const struct option *p;
-    struct option_list *next;
-  } *ambig_list = NULL;
-  int exact = 0;
-  int indfound = -1;
+  int n_options;
   int option_index;
 
   for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++)
     /* Do nothing.  */ ;
   namelen = nameend - d->__nextchar;
 
-  /* Test all long options for either exact match
-     or abbreviated matches.  */
-  for (p = longopts, option_index = 0; p->name; p++, option_index++)
-    if (!strncmp (p->name, d->__nextchar, namelen))
+  /* First look for an exact match, counting the options as a side
+     effect.  */
+  for (p = longopts, n_options = 0; p->name; p++, n_options++)
+    if (!strncmp (p->name, d->__nextchar, namelen)
+	&& namelen == strlen (p->name))
       {
-        if (namelen == strlen (p->name))
-          {
-            /* Exact match found.  */
-            pfound = p;
-            indfound = option_index;
-            exact = 1;
-            break;
-          }
-        else if (pfound == NULL)
-          {
-            /* First nonexact match found.  */
-            pfound = p;
-            indfound = option_index;
-          }
-        else if (long_only
-                 || pfound->has_arg != p->has_arg
-                 || pfound->flag != p->flag
-                 || pfound->val != p->val)
-          {
-            /* Second or later nonexact match found.  */
-            struct option_list *newp = alloca (sizeof (*newp));
-            newp->p = p;
-            newp->next = ambig_list;
-            ambig_list = newp;
-          }
+	/* Exact match found.  */
+	pfound = p;
+	option_index = n_options;
+	break;
       }
 
-  if (ambig_list != NULL && !exact)
+  if (pfound == NULL)
     {
-      if (print_errors)
-        {
-          struct option_list first;
-          first.p = pfound;
-          first.next = ambig_list;
-          ambig_list = &first;
-
-          flockfile (stderr);
-
-          fprintf (stderr, _("%s: option '%s' is ambiguous; possibilities:"),
-                   argv[0], argv[d->optind]);
-          do
-            {
-              fprintf (stderr, " '--%s'", ambig_list->p->name);
-              ambig_list = ambig_list->next;
-            }
-          while (ambig_list != NULL);
-
-          /* This must use 'fprintf' even though it's only printing a
-             single character, so that it goes through __fxprintf_nocancel
-             when compiled as part of glibc.  */
-          fprintf (stderr, "\n");
-          funlockfile (stderr);
-        }
-      d->__nextchar += strlen (d->__nextchar);
-      d->optind++;
-      d->optopt = 0;
-      return '?';
+      /* Didn't find an exact match, so look for abbreviations.  */
+      unsigned char *ambig_set = NULL;
+      int ambig_malloced = 0;
+      int ambig_fallback = 0;
+      int indfound = -1;
+
+      for (p = longopts, option_index = 0; p->name; p++, option_index++)
+	if (!strncmp (p->name, d->__nextchar, namelen))
+	  {
+	    if (pfound == NULL)
+	      {
+		/* First nonexact match found.  */
+		pfound = p;
+		indfound = option_index;
+	      }
+	    else if (long_only
+		     || pfound->has_arg != p->has_arg
+		     || pfound->flag != p->flag
+		     || pfound->val != p->val)
+	      {
+		/* Second or later nonexact match found.  */
+		if (!ambig_fallback)
+		  {
+		    if (!print_errors)
+		      /* Don't waste effort tracking the ambig set if
+			 we're not going to print it anyway.  */
+		      ambig_fallback = 1;
+		    else if (!ambig_set)
+		      {
+			if (__libc_use_alloca (n_options))
+			  ambig_set = alloca (n_options);
+			else if ((ambig_set = malloc (n_options)) == NULL)
+			  /* Fall back to simpler error message.  */
+			  ambig_fallback = 1;
+			else
+			  ambig_malloced = 1;
+
+			if (ambig_set)
+			  {
+			    memset (ambig_set, 0, n_options);
+			    ambig_set[indfound] = 1;
+			  }
+		      }
+		    if (ambig_set)
+		      ambig_set[option_index] = 1;
+		  }
+	      }
+	  }
+
+      if (ambig_set || ambig_fallback)
+	{
+	  if (print_errors)
+	    {
+	      if (ambig_fallback)
+		fprintf (stderr, _("%s: option '%s%s' is ambiguous\n"),
+			 argv[0], prefix, d->__nextchar);
+	      else
+		{
+		  flockfile (stderr);
+		  fprintf (stderr,
+			   _("%s: option '%s%s' is ambiguous; possibilities:"),
+			   argv[0], prefix, d->__nextchar);
+
+		  for (option_index = 0; option_index < n_options; option_index++)
+		    if (ambig_set[option_index])
+		      fprintf (stderr, " '%s%s'",
+			       prefix, longopts[option_index].name);
+
+		  /* This must use 'fprintf' even though it's only
+		     printing a single character, so that it goes through
+		     __fxprintf_nocancel when compiled as part of glibc.  */
+		  fprintf (stderr, "\n");
+		  funlockfile (stderr);
+		}
+	    }
+	  if (ambig_malloced)
+	    free (ambig_set);
+	  d->__nextchar += strlen (d->__nextchar);
+	  d->optind++;
+	  d->optopt = 0;
+	  return '?';
+	}
+
+      option_index = indfound;
     }
 
-  if (pfound != NULL)
+  if (pfound == NULL)
     {
-      option_index = indfound;
-      d->optind++;
-      if (*nameend)
-        {
-          /* Don't test has_arg with >, because some C compilers don't
-             allow it to be used on enums.  */
-          if (pfound->has_arg)
-            d->optarg = nameend + 1;
-          else
-            {
-              if (print_errors)
-                fprintf (stderr,
-                         _("%s: option '%s%s' doesn't allow an argument\n"),
-                         argv[0], prefix, pfound->name);
-
-              d->__nextchar += strlen (d->__nextchar);
-              d->optopt = pfound->val;
-              return '?';
-            }
-        }
-      else if (pfound->has_arg == 1)
-        {
-          if (d->optind < argc)
-            d->optarg = argv[d->optind++];
-          else
-            {
-              if (print_errors)
-                fprintf (stderr,
-                         _("%s: option '%s%s' requires an argument\n"),
-                         argv[0], prefix, pfound->name);
-
-              d->__nextchar += strlen (d->__nextchar);
-              d->optopt = pfound->val;
-              return optstring[0] == ':' ? ':' : '?';
-            }
-        }
-      d->__nextchar += strlen (d->__nextchar);
-      if (longind != NULL)
-        *longind = option_index;
-      if (pfound->flag)
-        {
-          *(pfound->flag) = pfound->val;
-          return 0;
-        }
-      return pfound->val;
+      /* Can't find it as a long option.  If this is not getopt_long_only,
+	 or the option starts with '--' or is not a valid short option,
+	 then it's an error.  */
+      if (!long_only || argv[d->optind][1] == '-'
+	  || strchr (optstring, *d->__nextchar) == NULL)
+	{
+	  if (print_errors)
+	    fprintf (stderr, _("%s: unrecognized option '%s%s'\n"),
+		     argv[0], prefix, d->__nextchar);
+
+	  d->__nextchar = NULL;
+	  d->optind++;
+	  d->optopt = 0;
+	  return '?';
+	}
+
+      /* Otherwise interpret it as a short option.  */
+      return -1;
     }
 
-  /* Can't find it as a long option.  If this is not getopt_long_only,
-     or the option starts with '--' or is not a valid short option,
-     then it's an error.  */
-  if (!long_only || argv[d->optind][1] == '-'
-      || strchr (optstring, *d->__nextchar) == NULL)
+  /* We have found a matching long option.  Consume it.  */
+  d->optind++;
+  d->__nextchar = NULL;
+  if (*nameend)
+    {
+      /* Don't test has_arg with >, because some C compilers don't
+	 allow it to be used on enums.  */
+      if (pfound->has_arg)
+	d->optarg = nameend + 1;
+      else
+	{
+	  if (print_errors)
+	    fprintf (stderr,
+		     _("%s: option '%s%s' doesn't allow an argument\n"),
+		     argv[0], prefix, pfound->name);
+
+	  d->optopt = pfound->val;
+	  return '?';
+	}
+    }
+  else if (pfound->has_arg == 1)
     {
-      if (print_errors)
-        fprintf (stderr, _("%s: unrecognized option '%s%s'\n"),
-                 argv[0], prefix, d->__nextchar);
-
-      d->__nextchar = NULL;
-      d->optind++;
-      d->optopt = 0;
-      return '?';
+      if (d->optind < argc)
+	d->optarg = argv[d->optind++];
+      else
+	{
+	  if (print_errors)
+	    fprintf (stderr,
+		     _("%s: option '%s%s' requires an argument\n"),
+		     argv[0], prefix, pfound->name);
+
+	  d->optopt = pfound->val;
+	  return optstring[0] == ':' ? ':' : '?';
+	}
     }
 
-  /* Otherwise interpret it as a short option.  */
-  return -1;
+  if (longind != NULL)
+    *longind = option_index;
+  if (pfound->flag)
+    {
+      *(pfound->flag) = pfound->val;
+      return 0;
+    }
+  return pfound->val;
 }
 
 /* Initialize internal data upon the first call to getopt.  */
diff --git a/posix/tst-getopt_long1.c b/posix/tst-getopt_long1.c
index 3895ebd..6d8ef02 100644
--- a/posix/tst-getopt_long1.c
+++ b/posix/tst-getopt_long1.c
@@ -56,7 +56,7 @@ do_test (void)
   printf ("message = \"%s\"\n", line);
 
   static const char expected[] = "\
-program: option '--on' is ambiguous; possibilities: '--one' '--onto' '--one-one'\n";
+program: option '--on' is ambiguous; possibilities: '--one' '--one-one' '--onto'\n";
 
   return c != '?' || strcmp (line, expected) != 0;
 }

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=dfbea09f96ce9e7a56f88c47d1593f07dc55c53c

commit dfbea09f96ce9e7a56f88c47d1593f07dc55c53c
Author: Zack Weinberg <zackw@panix.com>
Date:   Sat Apr 1 16:19:50 2017 -0400

    getopt: refactor long-option handling
    
    There were two copies of the bulk of the code to handle long options.
    Now there is only one.  (Yes, this is in aid of merging from gnulib.)
    
    The change to bug-getopt4.c clarifies the error messages when the test
    fails.
    
    	* posix/getopt.c (process_long_option): New function split out
    	from _getopt_internal_r.
    	(_getopt_internal_r): Replace both copies of the long-option
    	processing code with calls to process_long_option.
    	* posix/bug-getopt4.c (one_test): Print argv[0] in error messages.
    	(do_test): Differentiate argv[0] in the two subtests.

diff --git a/ChangeLog b/ChangeLog
index 5e9c79d..cf663d1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2017-04-07  Zack Weinberg  <zackw@panix.com>
 
+	* posix/getopt.c (process_long_option): New function split out
+	from _getopt_internal_r.
+	(_getopt_internal_r): Replace both copies of the long-option
+	processing code with calls to process_long_option.
+	* posix/bug-getopt4.c (one_test): Print argv[0] in error messages.
+	(do_test): Differentiate argv[0] in the two subtests.
+
 	* posix/getopt_int.h (_getopt_data): Remove __posixly_correct field.
 	* posix/getopt.c (_getopt_internal_r): Move some initialization code...
 	(_getopt_initialize): ...here. Don't set d->__posixly_correct.
diff --git a/posix/bug-getopt4.c b/posix/bug-getopt4.c
index 1daffd1..0956ca5 100644
--- a/posix/bug-getopt4.c
+++ b/posix/bug-getopt4.c
@@ -27,20 +27,20 @@ one_test (const char *fmt, int argc, char *argv[], int n, int expected[n])
       int c = getopt_long (argc, argv, fmt, opts, NULL);
       if (c != expected[i])
 	{
-	  printf ("format '%s' test %d failed: expected '%c', got '%c'\n",
-		  fmt, i, expected[i], c);
+	  printf ("%s: format '%s' test %d failed: expected '%c', got '%c'\n",
+		  argv[0], fmt, i, expected[i], c);
 	  res = 1;
 	}
       else if (optarg != NULL)
 	{
-	  printf ("format '%s' test %d failed: optarg is \"%s\", not NULL\n",
-		  fmt, i, optarg);
+	  printf ("%s: format '%s' test %d failed: optarg is \"%s\", not NULL\n",
+		  argv[0], fmt, i, optarg);
 	  res = 1;
 	}
       if (ftell (stderr) != 0)
 	{
-	  printf ("format '%s' test %d failed: printed to stderr\n",
-		  fmt, i);
+	  printf ("%s: format '%s' test %d failed: printed to stderr\n",
+		  argv[0], fmt, i);
 	  res = 1;
 	}
     }
@@ -68,11 +68,11 @@ do_test (void)
   remove (fname);
 
   int ret = one_test ("W;", 2,
-		      (char *[2]) { (char *) "bug-getopt4", (char *) "--a" },
+		      (char *[2]) { (char *) "bug-getopt4a", (char *) "--a" },
 		      1, (int [1]) { 'a' });
 
   ret |= one_test ("W;", 3,
-		   (char *[3]) { (char *) "bug-getopt4", (char *) "-W",
+		   (char *[3]) { (char *) "bug-getopt4b", (char *) "-W",
 				 (char *) "a" },
 		   1, (int [1]) { 'a' });
 
diff --git a/posix/getopt.c b/posix/getopt.c
index 609638c..ecb9923 100644
--- a/posix/getopt.c
+++ b/posix/getopt.c
@@ -179,7 +179,171 @@ exchange (char **argv, struct _getopt_data *d)
   d->__last_nonopt = d->optind;
 }
 
-/* Initialize the internal data when the first call is made.  */
+/* Process the argument starting with d->__nextchar as a long option.
+   d->optind should *not* have been advanced over this argument.
+
+   If the value returned is -1, it was not actually a long option, the
+   state is unchanged, and the argument should be processed as a set
+   of short options (this can only happen when long_only is true).
+   Otherwise, the option (and its argument, if any) have been consumed
+   and the return value is the value to return from _getopt_internal_r.  */
+static int
+process_long_option (int argc, char **argv, const char *optstring,
+		     const struct option *longopts, int *longind,
+		     int long_only, struct _getopt_data *d,
+		     int print_errors, const char *prefix)
+{
+  char *nameend;
+  size_t namelen;
+  const struct option *p;
+  const struct option *pfound = NULL;
+  struct option_list
+  {
+    const struct option *p;
+    struct option_list *next;
+  } *ambig_list = NULL;
+  int exact = 0;
+  int indfound = -1;
+  int option_index;
+
+  for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++)
+    /* Do nothing.  */ ;
+  namelen = nameend - d->__nextchar;
+
+  /* Test all long options for either exact match
+     or abbreviated matches.  */
+  for (p = longopts, option_index = 0; p->name; p++, option_index++)
+    if (!strncmp (p->name, d->__nextchar, namelen))
+      {
+        if (namelen == strlen (p->name))
+          {
+            /* Exact match found.  */
+            pfound = p;
+            indfound = option_index;
+            exact = 1;
+            break;
+          }
+        else if (pfound == NULL)
+          {
+            /* First nonexact match found.  */
+            pfound = p;
+            indfound = option_index;
+          }
+        else if (long_only
+                 || pfound->has_arg != p->has_arg
+                 || pfound->flag != p->flag
+                 || pfound->val != p->val)
+          {
+            /* Second or later nonexact match found.  */
+            struct option_list *newp = alloca (sizeof (*newp));
+            newp->p = p;
+            newp->next = ambig_list;
+            ambig_list = newp;
+          }
+      }
+
+  if (ambig_list != NULL && !exact)
+    {
+      if (print_errors)
+        {
+          struct option_list first;
+          first.p = pfound;
+          first.next = ambig_list;
+          ambig_list = &first;
+
+          flockfile (stderr);
+
+          fprintf (stderr, _("%s: option '%s' is ambiguous; possibilities:"),
+                   argv[0], argv[d->optind]);
+          do
+            {
+              fprintf (stderr, " '--%s'", ambig_list->p->name);
+              ambig_list = ambig_list->next;
+            }
+          while (ambig_list != NULL);
+
+          /* This must use 'fprintf' even though it's only printing a
+             single character, so that it goes through __fxprintf_nocancel
+             when compiled as part of glibc.  */
+          fprintf (stderr, "\n");
+          funlockfile (stderr);
+        }
+      d->__nextchar += strlen (d->__nextchar);
+      d->optind++;
+      d->optopt = 0;
+      return '?';
+    }
+
+  if (pfound != NULL)
+    {
+      option_index = indfound;
+      d->optind++;
+      if (*nameend)
+        {
+          /* Don't test has_arg with >, because some C compilers don't
+             allow it to be used on enums.  */
+          if (pfound->has_arg)
+            d->optarg = nameend + 1;
+          else
+            {
+              if (print_errors)
+                fprintf (stderr,
+                         _("%s: option '%s%s' doesn't allow an argument\n"),
+                         argv[0], prefix, pfound->name);
+
+              d->__nextchar += strlen (d->__nextchar);
+              d->optopt = pfound->val;
+              return '?';
+            }
+        }
+      else if (pfound->has_arg == 1)
+        {
+          if (d->optind < argc)
+            d->optarg = argv[d->optind++];
+          else
+            {
+              if (print_errors)
+                fprintf (stderr,
+                         _("%s: option '%s%s' requires an argument\n"),
+                         argv[0], prefix, pfound->name);
+
+              d->__nextchar += strlen (d->__nextchar);
+              d->optopt = pfound->val;
+              return optstring[0] == ':' ? ':' : '?';
+            }
+        }
+      d->__nextchar += strlen (d->__nextchar);
+      if (longind != NULL)
+        *longind = option_index;
+      if (pfound->flag)
+        {
+          *(pfound->flag) = pfound->val;
+          return 0;
+        }
+      return pfound->val;
+    }
+
+  /* Can't find it as a long option.  If this is not getopt_long_only,
+     or the option starts with '--' or is not a valid short option,
+     then it's an error.  */
+  if (!long_only || argv[d->optind][1] == '-'
+      || strchr (optstring, *d->__nextchar) == NULL)
+    {
+      if (print_errors)
+        fprintf (stderr, _("%s: unrecognized option '%s%s'\n"),
+                 argv[0], prefix, d->__nextchar);
+
+      d->__nextchar = NULL;
+      d->optind++;
+      d->optopt = 0;
+      return '?';
+    }
+
+  /* Otherwise interpret it as a short option.  */
+  return -1;
+}
+
+/* Initialize internal data upon the first call to getopt.  */
 
 static const char *
 _getopt_initialize (int argc, char **argv, const char *optstring,
@@ -366,197 +530,46 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
 	}
 
       /* We have found another option-ARGV-element.
-	 Skip the initial punctuation.  */
-
-      d->__nextchar = (argv[d->optind] + 1
-		  + (longopts != NULL && argv[d->optind][1] == '-'));
-    }
-
-  /* Decode the current option-ARGV-element.  */
-
-  /* Check whether the ARGV-element is a long option.
-
-     If long_only and the ARGV-element has the form "-f", where f is
-     a valid short option, don't consider it an abbreviated form of
-     a long option that starts with f.  Otherwise there would be no
-     way to give the -f short option.
-
-     On the other hand, if there's a long option "fubar" and
-     the ARGV-element is "-fu", do consider that an abbreviation of
-     the long option, just like "--fu", and not "-f" with arg "u".
-
-     This distinction seems to be the most useful approach.  */
-
-  if (longopts != NULL
-      && (argv[d->optind][1] == '-'
-	  || (long_only && (argv[d->optind][2]
-			    || !strchr (optstring, argv[d->optind][1])))))
-    {
-      char *nameend;
-      unsigned int namelen;
-      const struct option *p;
-      const struct option *pfound = NULL;
-      struct option_list
-      {
-	const struct option *p;
-	struct option_list *next;
-      } *ambig_list = NULL;
-      int exact = 0;
-      int indfound = -1;
-      int option_index;
-
-      for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++)
-	/* Do nothing.  */ ;
-      namelen = nameend - d->__nextchar;
-
-      /* Test all long options for either exact match
-	 or abbreviated matches.  */
-      for (p = longopts, option_index = 0; p->name; p++, option_index++)
-	if (!strncmp (p->name, d->__nextchar, namelen))
-	  {
-	    if (namelen == (unsigned int) strlen (p->name))
-	      {
-		/* Exact match found.  */
-		pfound = p;
-		indfound = option_index;
-		exact = 1;
-		break;
-	      }
-	    else if (pfound == NULL)
-	      {
-		/* First nonexact match found.  */
-		pfound = p;
-		indfound = option_index;
-	      }
-	    else if (long_only
-		     || pfound->has_arg != p->has_arg
-		     || pfound->flag != p->flag
-		     || pfound->val != p->val)
-	      {
-		/* Second or later nonexact match found.  */
-		struct option_list *newp = alloca (sizeof (*newp));
-		newp->p = p;
-		newp->next = ambig_list;
-		ambig_list = newp;
-	      }
-	  }
-
-      if (ambig_list != NULL && !exact)
+	 Check whether it might be a long option.  */
+      if (longopts)
 	{
-	  if (print_errors)
+	  if (argv[d->optind][1] == '-')
 	    {
-	      struct option_list first;
-	      first.p = pfound;
-	      first.next = ambig_list;
-	      ambig_list = &first;
+	      /* "--foo" is always a long option.  The special option
+		 "--" was handled above.  */
+	      d->__nextchar = argv[d->optind] + 2;
+	      return process_long_option (argc, argv, optstring, longopts,
+					  longind, long_only, d,
+					  print_errors, "--");
+	    }
 
-	      flockfile (stderr);
+	  /* If long_only and the ARGV-element has the form "-f",
+	     where f is a valid short option, don't consider it an
+	     abbreviated form of a long option that starts with f.
+	     Otherwise there would be no way to give the -f short
+	     option.
 
-	      fprintf (stderr,
-		       _("%s: option '%s' is ambiguous; possibilities:"),
-		       argv[0], argv[d->optind]);
-	      do
-		{
-		  fprintf (stderr, " '--%s'", ambig_list->p->name);
-		  ambig_list = ambig_list->next;
-		}
-	      while (ambig_list != NULL);
-
-	      /* This must use 'fprintf' even though it's only printing a
-		 single character, so that it goes through __fxprintf_nocancel
-		 when compiled as part of glibc.  */
-	      fprintf (stderr, "\n");
-	      funlockfile (stderr);
-	    }
-	  d->__nextchar += strlen (d->__nextchar);
-	  d->optind++;
-	  d->optopt = 0;
-	  return '?';
-	}
+	     On the other hand, if there's a long option "fubar" and
+	     the ARGV-element is "-fu", do consider that an
+	     abbreviation of the long option, just like "--fu", and
+	     not "-f" with arg "u".
 
-      if (pfound != NULL)
-	{
-	  option_index = indfound;
-	  d->optind++;
-	  if (*nameend)
-	    {
-	      /* Don't test has_arg with >, because some C compilers don't
-		 allow it to be used on enums.  */
-	      if (pfound->has_arg)
-		d->optarg = nameend + 1;
-	      else
-		{
-		  if (print_errors)
-		    {
-		      if (argv[d->optind - 1][1] == '-')
-			/* --option */
-			fprintf (stderr, _("\
-%s: option '--%s' doesn't allow an argument\n"),
-				 argv[0], pfound->name);
-		      else
-			/* +option or -option */
-			fprintf (stderr, _("\
-%s: option '%c%s' doesn't allow an argument\n"),
-				 argv[0], argv[d->optind - 1][0],
-				 pfound->name);
-		    }
-
-		  d->__nextchar += strlen (d->__nextchar);
-
-		  d->optopt = pfound->val;
-		  return '?';
-		}
-	    }
-	  else if (pfound->has_arg == 1)
-	    {
-	      if (d->optind < argc)
-		d->optarg = argv[d->optind++];
-	      else
-		{
-		  if (print_errors)
-		    fprintf (stderr,
-			     _("%s: option '--%s' requires an argument\n"),
-			     argv[0], pfound->name);
-
-		  d->__nextchar += strlen (d->__nextchar);
-		  d->optopt = pfound->val;
-		  return optstring[0] == ':' ? ':' : '?';
-		}
-	    }
-	  d->__nextchar += strlen (d->__nextchar);
-	  if (longind != NULL)
-	    *longind = option_index;
-	  if (pfound->flag)
+	     This distinction seems to be the most useful approach.  */
+	  if (long_only && (argv[d->optind][2]
+			    || !strchr (optstring, argv[d->optind][1])))
 	    {
-	      *(pfound->flag) = pfound->val;
-	      return 0;
+	      int code;
+	      d->__nextchar = argv[d->optind] + 1;
+	      code = process_long_option (argc, argv, optstring, longopts,
+					  longind, long_only, d,
+					  print_errors, "-");
+	      if (code != -1)
+		return code;
 	    }
-	  return pfound->val;
 	}
 
-      /* Can't find it as a long option.  If this is not getopt_long_only,
-	 or the option starts with '--' or is not a valid short
-	 option, then it's an error.
-	 Otherwise interpret it as a short option.  */
-      if (!long_only || argv[d->optind][1] == '-'
-	  || strchr (optstring, *d->__nextchar) == NULL)
-	{
-	  if (print_errors)
-	    {
-	      if (argv[d->optind][1] == '-')
-		/* --option */
-		fprintf (stderr, _("%s: unrecognized option '--%s'\n"),
-			 argv[0], d->__nextchar);
-	      else
-		/* +option or -option */
-		fprintf (stderr, _("%s: unrecognized option '%c%s'\n"),
-			 argv[0], argv[d->optind][0], d->__nextchar);
-	    }
-	  d->__nextchar = (char *) "";
-	  d->optind++;
-	  d->optopt = 0;
-	  return '?';
-	}
+      /* It is not a long option.  Skip the initial punctuation.  */
+      d->__nextchar = argv[d->optind] + 1;
     }
 
   /* Look at and handle the next short option-character.  */
@@ -576,28 +589,13 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
 	d->optopt = c;
 	return '?';
       }
+
     /* Convenience. Treat POSIX -W foo same as long option --foo */
-    if (temp[0] == 'W' && temp[1] == ';')
+    if (temp[0] == 'W' && temp[1] == ';' && longopts != NULL)
       {
-	char *nameend;
-	const struct option *p;
-	const struct option *pfound = NULL;
-	int exact = 0;
-	int ambig = 0;
-	int indfound = 0;
-	int option_index;
-
-	if (longopts == NULL)
-	  goto no_longs;
-
 	/* This is an option that requires an argument.  */
 	if (*d->__nextchar != '\0')
-	  {
-	    d->optarg = d->__nextchar;
-	    /* If we end this ARGV-element by taking the rest as an arg,
-	       we must advance to the next element now.  */
-	    d->optind++;
-	  }
+	  d->optarg = d->__nextchar;
 	else if (d->optind == argc)
 	  {
 	    if (print_errors)
@@ -613,103 +611,12 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
 	    return c;
 	  }
 	else
-	  /* We already incremented 'd->optind' once;
-	     increment it again when taking next ARGV-elt as argument.  */
-	  d->optarg = argv[d->optind++];
-
-	/* optarg is now the argument, see if it's in the
-	   table of longopts.  */
-
-	for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '=';
-	     nameend++)
-	  /* Do nothing.  */ ;
-
-	/* Test all long options for either exact match
-	   or abbreviated matches.  */
-	for (p = longopts, option_index = 0; p->name; p++, option_index++)
-	  if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar))
-	    {
-	      if ((unsigned int) (nameend - d->__nextchar) == strlen (p->name))
-		{
-		  /* Exact match found.  */
-		  pfound = p;
-		  indfound = option_index;
-		  exact = 1;
-		  break;
-		}
-	      else if (pfound == NULL)
-		{
-		  /* First nonexact match found.  */
-		  pfound = p;
-		  indfound = option_index;
-		}
-	      else if (long_only
-		       || pfound->has_arg != p->has_arg
-		       || pfound->flag != p->flag
-		       || pfound->val != p->val)
-		/* Second or later nonexact match found.  */
-		ambig = 1;
-	    }
-	if (ambig && !exact)
-	  {
-	    if (print_errors)
-	      fprintf (stderr, _("%s: option '-W %s' is ambiguous\n"),
-		       argv[0], d->optarg);
-
-	    d->__nextchar += strlen (d->__nextchar);
-	    return '?';
-	  }
-	if (pfound != NULL)
-	  {
-	    option_index = indfound;
-	    if (*nameend)
-	      {
-		/* Don't test has_arg with >, because some C compilers don't
-		   allow it to be used on enums.  */
-		if (pfound->has_arg)
-		  d->optarg = nameend + 1;
-		else
-		  {
-		    if (print_errors)
-		      fprintf (stderr, _("\
-%s: option '-W %s' doesn't allow an argument\n"),
-			       argv[0], pfound->name);
-
-		    d->__nextchar += strlen (d->__nextchar);
-		    return '?';
-		  }
-	      }
-	    else if (pfound->has_arg == 1)
-	      {
-		if (d->optind < argc)
-		  d->optarg = argv[d->optind++];
-		else
-		  {
-		    if (print_errors)
-		      fprintf (stderr, _("\
-%s: option '-W %s' requires an argument\n"),
-			       argv[0], pfound->name);
-
-		    d->__nextchar += strlen (d->__nextchar);
-		    return optstring[0] == ':' ? ':' : '?';
-		  }
-	      }
-	    else
-	      d->optarg = NULL;
-	    d->__nextchar += strlen (d->__nextchar);
-	    if (longind != NULL)
-	      *longind = option_index;
-	    if (pfound->flag)
-	      {
-		*(pfound->flag) = pfound->val;
-		return 0;
-	      }
-	    return pfound->val;
-	  }
+	  d->optarg = argv[d->optind];
 
-      no_longs:
-	d->__nextchar = NULL;
-	return 'W';   /* Let the application handle it.  */
+	d->__nextchar = d->optarg;
+	d->optarg = NULL;
+	return process_long_option (argc, argv, optstring, longopts, longind,
+				    0 /* long_only */, d, print_errors, "-W ");
       }
     if (temp[1] == ':')
       {

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=c1af8775f2de694bd567813af51164e2d978a78d

commit c1af8775f2de694bd567813af51164e2d978a78d
Author: Zack Weinberg <zackw@panix.com>
Date:   Sat Apr 1 12:42:41 2017 -0400

    getopt: tidy up _getopt_initialize a bit
    
    _getopt_data.__posixly_correct is completely redundant to
    _getopt_data.__ordering, and some work that logically belongs in
    _getopt_initialize was being done by _getopt_internal_r, making the
    code harder to understand.
    
    As a side effect, getenv will no longer be called if the first
    character of the options string is '+' or '-', which is probably a
    Good Thing.  (Perhaps we should have a flag character that
    specifically asks for the permutation behavior?)
    
    	* posix/getopt_int.h (_getopt_data): Remove __posixly_correct field.
    	* posix/getopt.c (_getopt_internal_r): Move some initialization code...
    	(_getopt_initialize): ...here. Don't set d->__posixly_correct.

diff --git a/ChangeLog b/ChangeLog
index e258726..5e9c79d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2017-04-07  Zack Weinberg  <zackw@panix.com>
 
+	* posix/getopt_int.h (_getopt_data): Remove __posixly_correct field.
+	* posix/getopt.c (_getopt_internal_r): Move some initialization code...
+	(_getopt_initialize): ...here. Don't set d->__posixly_correct.
+
 	* posix/getopt.h: Add backup definition of __nonnull for
 	consistency with gnulib.  Define __getopt_argv_const to const
 	if not already defined.
diff --git a/posix/getopt.c b/posix/getopt.c
index f54bc2d..609638c 100644
--- a/posix/getopt.c
+++ b/posix/getopt.c
@@ -188,15 +188,13 @@ _getopt_initialize (int argc, char **argv, const char *optstring,
   /* Start processing options with ARGV-element 1 (since ARGV-element 0
      is the program name); the sequence of previously skipped
      non-option ARGV-elements is empty.  */
+  if (d->optind == 0)
+    d->optind = 1;
 
   d->__first_nonopt = d->__last_nonopt = d->optind;
-
   d->__nextchar = NULL;
 
-  d->__posixly_correct = posixly_correct || !!getenv ("POSIXLY_CORRECT");
-
   /* Determine how to handle the ordering of options and nonoptions.  */
-
   if (optstring[0] == '-')
     {
       d->__ordering = RETURN_IN_ORDER;
@@ -207,11 +205,12 @@ _getopt_initialize (int argc, char **argv, const char *optstring,
       d->__ordering = REQUIRE_ORDER;
       ++optstring;
     }
-  else if (d->__posixly_correct)
+  else if (posixly_correct || !!getenv ("POSIXLY_CORRECT"))
     d->__ordering = REQUIRE_ORDER;
   else
     d->__ordering = PERMUTE;
 
+  d->__initialized = 1;
   return optstring;
 }
 
@@ -284,15 +283,10 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
   d->optarg = NULL;
 
   if (d->optind == 0 || !d->__initialized)
-    {
-      if (d->optind == 0)
-	d->optind = 1;  /* Don't scan ARGV[0], the program name.  */
-      optstring = _getopt_initialize (argc, argv, optstring, d,
-				      posixly_correct);
-      d->__initialized = 1;
-    }
+    optstring = _getopt_initialize (argc, argv, optstring, d, posixly_correct);
   else if (optstring[0] == '-' || optstring[0] == '+')
     optstring++;
+
   if (optstring[0] == ':')
     print_errors = 0;
 
diff --git a/posix/getopt_int.h b/posix/getopt_int.h
index 762679a..6a02954 100644
--- a/posix/getopt_int.h
+++ b/posix/getopt_int.h
@@ -83,10 +83,6 @@ struct _getopt_data
   /* See __ord above.  */
   enum __ord __ordering;
 
-  /* True if behaving strictly as specified by POSIX.  */
-  int __posixly_correct;
-
-
   /* Handle permutation of arguments.  */
 
   /* Describe the part of ARGV that contains non-options that have

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=7a7be6c9a2a89ac5783d4f27d67b0fae3218228f

commit 7a7be6c9a2a89ac5783d4f27d67b0fae3218228f
Author: Zack Weinberg <zackw@panix.com>
Date:   Sat Apr 1 12:11:33 2017 -0400

    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 **'.

diff --git a/ChangeLog b/ChangeLog
index d45be5f..e258726 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 248fe5b..f54bc2d 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 c83a186..fa6aa6b 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 b4ae6e4..b967d24 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 9ac03bd..762679a 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,

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=544ce845def4540de11d9484df888df94876b14e

commit 544ce845def4540de11d9484df888df94876b14e
Author: Zack Weinberg <zackw@panix.com>
Date:   Sat Apr 1 10:17:44 2017 -0400

    getopt: clean up error reporting
    
    getopt can print a whole bunch of error messages, and when used
    standalone (from gnulib) it uses fprintf to do that.  But fprintf is a
    cancellation point and getopt isn't, and also applying fprintf to a
    stream in wide-character mode is not allowed.
    
    glibc has an internal function called __fxprintf that writes a narrow
    format string to a stream regardless of mode, but it only handles
    ASCII format strings, and it's still a cancellation point.  getopt's
    messages are translated, so they might not be ASCII.  So getopt has an
    error message to an asprintf buffer, monkeys with internal flag bits
    on stderr to disable cancellation, and then calls
    __fxprintf(stderr, "%s", buffer).  There isn't even a helper function,
    the code is duplicated every time.
    
    This patch fixes __fxprintf to handle arbitrary multibyte format
    strings, and adds a variant __fxprintf_nocancel that does the same
    thing but also isn't a cancellation point.  (It still _works_ by
    monkeying with internal flag bits on the FILE, but that's not really a
    layering violation for code in stdio-common.)  All of the #ifdef _LIBC
    blocks can then be reduced to their standalone versions with a little
    help from some macros at the top of the file.
    
    I also wrote a test case to verify that getopt really isn't a
    cancellation point, and I'm glad I did, because it found two bugs, one
    of which wasn't even to do with cancellation (see previous patch).
    
    	* stdio-common/fxprintf.c (__fxprintf_nocancel): New function.
    	(locked_vfxprintf): New helper function. Handle arbitrary
    	multibyte strings, not just ASCII.
    	* include/stdio.h: Declare __fxprintf_nocancel.
    
    	* posix/getopt.c: When _LIBC is defined, define fprintf to
    	__fxprintf_nocancel, flockfile to _IO_flockfile, and
    	funlockfile to _IO_funlockfile.  When neither _LIBC nor
    	_POSIX_THREAD_SAFE_FUNCTIONS is defined, define flockfile and
    	funlockfile as no-ops.  (_getopt_internal_r): Remove all
    	internal #ifdef _LIBC blocks; the standalone error-printing
    	code can now be used for libc as well.  Add an
    	flockfile/funlockfile pair around one case where the error
    	message is printed in several chunks.  Don't use fputc.
    
    	* posix/tst-getopt-cancel.c: New test.
    	* posix/Makefile: Run it.

diff --git a/ChangeLog b/ChangeLog
index 48e5b03..d45be5f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,21 @@
 2017-04-07  Zack Weinberg  <zackw@panix.com>
 
+	* stdio-common/fxprintf.c (__fxprintf_nocancel): New function.
+	(locked_vfxprintf): New helper function. Handle arbitrary
+	multibyte strings, not just ASCII.
+	* include/stdio.h: Declare __fxprintf_nocancel.
+	* posix/getopt.c: When _LIBC is defined, define fprintf to
+	__fxprintf_nocancel, flockfile to _IO_flockfile, and funlockfile
+	to _IO_funlockfile.  When neither _LIBC nor
+	_POSIX_THREAD_SAFE_FUNCTIONS is defined, define flockfile and
+	funlockfile as no-ops.
+	(_getopt_internal_r): Remove all internal #ifdef _LIBC blocks;
+	the standalone error-printing code can now be used for libc as
+	well.  Add an flockfile/funlockfile pair around one case where
+	the error message is printed in several chunks.  Don't use fputc.
+	* posix/tst-getopt-cancel.c: New test.
+	* posix/Makefile: Run it.
+
 	* posix/getopt.c (_getopt_internal_r): Don't increment
 	d->optind a second time when reporting ambiguous -W options.
 
diff --git a/include/stdio.h b/include/stdio.h
index 17b5a05..4e7cfa1 100644
--- a/include/stdio.h
+++ b/include/stdio.h
@@ -114,6 +114,8 @@ extern wint_t __getwc_unlocked (FILE *__fp);
 
 extern int __fxprintf (FILE *__fp, const char *__fmt, ...)
      __attribute__ ((__format__ (__printf__, 2, 3)));
+extern int __fxprintf_nocancel (FILE *__fp, const char *__fmt, ...)
+     __attribute__ ((__format__ (__printf__, 2, 3)));
 
 extern const char *const _sys_errlist_internal[] attribute_hidden;
 extern int _sys_nerr_internal attribute_hidden;
diff --git a/posix/Makefile b/posix/Makefile
index efcbeff..8e29eea 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -97,6 +97,9 @@ ifeq (yes,$(build-shared))
 test-srcs	:= globtest
 tests           += wordexp-test tst-exec tst-spawn tst-spawn2 tst-spawn3
 endif
+ifeq (yesyes,$(build-shared)$(have-thread-library))
+tests		+= tst-getopt-cancel
+endif
 tests-static	= tst-exec-static tst-spawn-static
 tests		+= $(tests-static)
 others		:= getconf
@@ -254,6 +257,8 @@ ptestcases.h: PTESTS PTESTS2C.sed
 	LC_ALL=C sed -f PTESTS2C.sed < $< > $@T
 	mv -f $@T $@
 
+$(objpfx)tst-getopt-cancel: $(shared-thread-library)
+
 test-xfail-annexc = yes
 $(objpfx)annexc.out: $(objpfx)annexc
 	$(dir $<)$(notdir $<) '$(CC)' \
diff --git a/posix/getopt.c b/posix/getopt.c
index e616aa6..248fe5b 100644
--- a/posix/getopt.c
+++ b/posix/getopt.c
@@ -27,14 +27,30 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <unistd.h>
 #include <string.h>
+#include <unistd.h>
 
 #ifdef _LIBC
+/* When used as part of glibc, error printing must be done differently
+   for standards compliance.  getopt is not a cancellation point, so
+   it must not call functions that are, and it is specified by an
+   older standard than stdio locking, so it must not refer to
+   functions in the "user namespace" related to stdio locking.
+   Finally, it must use glibc's internal message translation so that
+   the messages are looked up in the proper text domain.  */
 # include <libintl.h>
+# define fprintf __fxprintf_nocancel
+# define flockfile(fp) _IO_flockfile (fp)
+# define funlockfile(fp) _IO_funlockfile (fp)
 #else
 # include "gettext.h"
 # define _(msgid) gettext (msgid)
+/* When used standalone, flockfile and funlockfile might not be
+   available.  */
+# ifndef _POSIX_THREAD_SAFE_FUNCTIONS
+#  define flockfile(fp) /* nop */
+#  define funlockfile(fp) /* nop */
+# endif
 #endif
 
 /* This implementation of 'getopt' has three modes for handling
@@ -98,7 +114,6 @@ int optopt = '?';
 /* Keep a global copy of all internal members of getopt_data.  */
 
 static struct _getopt_data getopt_data;
-
 
 /* Exchange two adjacent subsequences of ARGV.
    One subsequence is elements [first_nonopt,last_nonopt)
@@ -271,7 +286,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
   if (d->optind == 0 || !d->__initialized)
     {
       if (d->optind == 0)
-	d->optind = 1;	/* Don't scan ARGV[0], the program name.  */
+	d->optind = 1;  /* Don't scan ARGV[0], the program name.  */
       optstring = _getopt_initialize (argc, argv, optstring, d,
 				      posixly_correct);
       d->__initialized = 1;
@@ -441,42 +456,8 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
 	      first.next = ambig_list;
 	      ambig_list = &first;
 
-#if defined _LIBC
-	      char *buf = NULL;
-	      size_t buflen = 0;
-
-	      FILE *fp = __open_memstream (&buf, &buflen);
-	      if (fp != NULL)
-		{
-		  fprintf (fp,
-			   _("%s: option '%s' is ambiguous; possibilities:"),
-			   argv[0], argv[d->optind]);
-
-		  do
-		    {
-		      fprintf (fp, " '--%s'", ambig_list->p->name);
-		      ambig_list = ambig_list->next;
-		    }
-		  while (ambig_list != NULL);
-
-		  fputc_unlocked ('\n', fp);
-
-		  if (__glibc_likely (fclose (fp) != EOF))
-		    {
-		      _IO_flockfile (stderr);
-
-		      int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
-		      ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+	      flockfile (stderr);
 
-		      __fxprintf (NULL, "%s", buf);
-
-		      ((_IO_FILE *) stderr)->_flags2 = old_flags2;
-		      _IO_funlockfile (stderr);
-
-		      free (buf);
-		    }
-		}
-#else
 	      fprintf (stderr,
 		       _("%s: option '%s' is ambiguous; possibilities:"),
 		       argv[0], argv[d->optind]);
@@ -487,8 +468,11 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
 		}
 	      while (ambig_list != NULL);
 
-	      fputc ('\n', stderr);
-#endif
+	      /* This must use 'fprintf' even though it's only printing a
+		 single character, so that it goes through __fxprintf_nocancel
+		 when compiled as part of glibc.  */
+	      fprintf (stderr, "\n");
+	      funlockfile (stderr);
 	    }
 	  d->__nextchar += strlen (d->__nextchar);
 	  d->optind++;
@@ -510,57 +494,17 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
 		{
 		  if (print_errors)
 		    {
-#if defined _LIBC
-		      char *buf;
-		      int n;
-#endif
-
 		      if (argv[d->optind - 1][1] == '-')
-			{
-			  /* --option */
-#if defined _LIBC
-			  n = __asprintf (&buf, _("\
-%s: option '--%s' doesn't allow an argument\n"),
-					  argv[0], pfound->name);
-#else
-			  fprintf (stderr, _("\
+			/* --option */
+			fprintf (stderr, _("\
 %s: option '--%s' doesn't allow an argument\n"),
-				   argv[0], pfound->name);
-#endif
-			}
+				 argv[0], pfound->name);
 		      else
-			{
-			  /* +option or -option */
-#if defined _LIBC
-			  n = __asprintf (&buf, _("\
-%s: option '%c%s' doesn't allow an argument\n"),
-					  argv[0], argv[d->optind - 1][0],
-					  pfound->name);
-#else
-			  fprintf (stderr, _("\
+			/* +option or -option */
+			fprintf (stderr, _("\
 %s: option '%c%s' doesn't allow an argument\n"),
-				   argv[0], argv[d->optind - 1][0],
-				   pfound->name);
-#endif
-			}
-
-#if defined _LIBC
-		      if (n >= 0)
-			{
-			  _IO_flockfile (stderr);
-
-			  int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
-			  ((_IO_FILE *) stderr)->_flags2
-			    |= _IO_FLAGS2_NOTCANCEL;
-
-			  __fxprintf (NULL, "%s", buf);
-
-			  ((_IO_FILE *) stderr)->_flags2 = old_flags2;
-			  _IO_funlockfile (stderr);
-
-			  free (buf);
-			}
-#endif
+				 argv[0], argv[d->optind - 1][0],
+				 pfound->name);
 		    }
 
 		  d->__nextchar += strlen (d->__nextchar);
@@ -576,33 +520,10 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
 	      else
 		{
 		  if (print_errors)
-		    {
-#if defined _LIBC
-		      char *buf;
-
-		      if (__asprintf (&buf, _("\
-%s: option '--%s' requires an argument\n"),
-				      argv[0], pfound->name) >= 0)
-			{
-			  _IO_flockfile (stderr);
-
-			  int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
-			  ((_IO_FILE *) stderr)->_flags2
-			    |= _IO_FLAGS2_NOTCANCEL;
-
-			  __fxprintf (NULL, "%s", buf);
-
-			  ((_IO_FILE *) stderr)->_flags2 = old_flags2;
-			  _IO_funlockfile (stderr);
+		    fprintf (stderr,
+			     _("%s: option '--%s' requires an argument\n"),
+			     argv[0], pfound->name);
 
-			  free (buf);
-			}
-#else
-		      fprintf (stderr,
-			       _("%s: option '--%s' requires an argument\n"),
-			       argv[0], pfound->name);
-#endif
-		    }
 		  d->__nextchar += strlen (d->__nextchar);
 		  d->optopt = pfound->val;
 		  return optstring[0] == ':' ? ':' : '?';
@@ -628,50 +549,14 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
 	{
 	  if (print_errors)
 	    {
-#if defined _LIBC
-	      char *buf;
-	      int n;
-#endif
-
 	      if (argv[d->optind][1] == '-')
-		{
-		  /* --option */
-#if defined _LIBC
-		  n = __asprintf (&buf, _("%s: unrecognized option '--%s'\n"),
-				  argv[0], d->__nextchar);
-#else
-		  fprintf (stderr, _("%s: unrecognized option '--%s'\n"),
-			   argv[0], d->__nextchar);
-#endif
-		}
+		/* --option */
+		fprintf (stderr, _("%s: unrecognized option '--%s'\n"),
+			 argv[0], d->__nextchar);
 	      else
-		{
-		  /* +option or -option */
-#if defined _LIBC
-		  n = __asprintf (&buf, _("%s: unrecognized option '%c%s'\n"),
-				  argv[0], argv[d->optind][0], d->__nextchar);
-#else
-		  fprintf (stderr, _("%s: unrecognized option '%c%s'\n"),
-			   argv[0], argv[d->optind][0], d->__nextchar);
-#endif
-		}
-
-#if defined _LIBC
-	      if (n >= 0)
-		{
-		  _IO_flockfile (stderr);
-
-		  int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
-		  ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
-
-		  __fxprintf (NULL, "%s", buf);
-
-		  ((_IO_FILE *) stderr)->_flags2 = old_flags2;
-		  _IO_funlockfile (stderr);
-
-		  free (buf);
-		}
-#endif
+		/* +option or -option */
+		fprintf (stderr, _("%s: unrecognized option '%c%s'\n"),
+			 argv[0], argv[d->optind][0], d->__nextchar);
 	    }
 	  d->__nextchar = (char *) "";
 	  d->optind++;
@@ -693,36 +578,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
     if (temp == NULL || c == ':' || c == ';')
       {
 	if (print_errors)
-	  {
-#if defined _LIBC
-	    char *buf;
-	    int n;
-#endif
-
-#if defined _LIBC
-	    n = __asprintf (&buf, _("%s: invalid option -- '%c'\n"),
-			    argv[0], c);
-#else
-	    fprintf (stderr, _("%s: invalid option -- '%c'\n"), argv[0], c);
-#endif
-
-#if defined _LIBC
-	    if (n >= 0)
-	      {
-		_IO_flockfile (stderr);
-
-		int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
-		((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
-
-		__fxprintf (NULL, "%s", buf);
-
-		((_IO_FILE *) stderr)->_flags2 = old_flags2;
-		_IO_funlockfile (stderr);
-
-		free (buf);
-	      }
-#endif
-	  }
+	  fprintf (stderr, _("%s: invalid option -- '%c'\n"), argv[0], c);
 	d->optopt = c;
 	return '?';
       }
@@ -751,32 +607,10 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
 	else if (d->optind == argc)
 	  {
 	    if (print_errors)
-	      {
-#if defined _LIBC
-		char *buf;
-
-		if (__asprintf (&buf,
-				_("%s: option requires an argument -- '%c'\n"),
-				argv[0], c) >= 0)
-		  {
-		    _IO_flockfile (stderr);
-
-		    int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
-		    ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
-
-		    __fxprintf (NULL, "%s", buf);
-
-		    ((_IO_FILE *) stderr)->_flags2 = old_flags2;
-		    _IO_funlockfile (stderr);
+	      fprintf (stderr,
+		       _("%s: option requires an argument -- '%c'\n"),
+		       argv[0], c);
 
-		    free (buf);
-		  }
-#else
-		fprintf (stderr,
-			 _("%s: option requires an argument -- '%c'\n"),
-			 argv[0], c);
-#endif
-	      }
 	    d->optopt = c;
 	    if (optstring[0] == ':')
 	      c = ':';
@@ -825,30 +659,9 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
 	if (ambig && !exact)
 	  {
 	    if (print_errors)
-	      {
-#if defined _LIBC
-		char *buf;
-
-		if (__asprintf (&buf, _("%s: option '-W %s' is ambiguous\n"),
-				argv[0], d->optarg) >= 0)
-		  {
-		    _IO_flockfile (stderr);
-
-		    int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
-		    ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+	      fprintf (stderr, _("%s: option '-W %s' is ambiguous\n"),
+		       argv[0], d->optarg);
 
-		    __fxprintf (NULL, "%s", buf);
-
-		    ((_IO_FILE *) stderr)->_flags2 = old_flags2;
-		    _IO_funlockfile (stderr);
-
-		    free (buf);
-		  }
-#else
-		fprintf (stderr, _("%s: option '-W %s' is ambiguous\n"),
-			 argv[0], d->optarg);
-#endif
-	      }
 	    d->__nextchar += strlen (d->__nextchar);
 	    return '?';
 	  }
@@ -864,33 +677,9 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
 		else
 		  {
 		    if (print_errors)
-		      {
-#if defined _LIBC
-			char *buf;
-
-			if (__asprintf (&buf, _("\
-%s: option '-W %s' doesn't allow an argument\n"),
-					argv[0], pfound->name) >= 0)
-			  {
-			    _IO_flockfile (stderr);
-
-			    int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
-			    ((_IO_FILE *) stderr)->_flags2
-			      |= _IO_FLAGS2_NOTCANCEL;
-
-			    __fxprintf (NULL, "%s", buf);
-
-			    ((_IO_FILE *) stderr)->_flags2 = old_flags2;
-			    _IO_funlockfile (stderr);
-
-			    free (buf);
-			  }
-#else
-			fprintf (stderr, _("\
+		      fprintf (stderr, _("\
 %s: option '-W %s' doesn't allow an argument\n"),
-				 argv[0], pfound->name);
-#endif
-		      }
+			       argv[0], pfound->name);
 
 		    d->__nextchar += strlen (d->__nextchar);
 		    return '?';
@@ -903,33 +692,10 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
 		else
 		  {
 		    if (print_errors)
-		      {
-#if defined _LIBC
-			char *buf;
-
-			if (__asprintf (&buf, _("\
+		      fprintf (stderr, _("\
 %s: option '-W %s' requires an argument\n"),
-					argv[0], pfound->name) >= 0)
-			  {
-			    _IO_flockfile (stderr);
-
-			    int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
-			    ((_IO_FILE *) stderr)->_flags2
-			      |= _IO_FLAGS2_NOTCANCEL;
-
-			    __fxprintf (NULL, "%s", buf);
-
-			    ((_IO_FILE *) stderr)->_flags2 = old_flags2;
-			    _IO_funlockfile (stderr);
+			       argv[0], pfound->name);
 
-			    free (buf);
-			  }
-#else
-			fprintf (stderr, _("\
-%s: option '-W %s' requires an argument\n"),
-				 argv[0], pfound->name);
-#endif
-		      }
 		    d->__nextchar += strlen (d->__nextchar);
 		    return optstring[0] == ':' ? ':' : '?';
 		  }
@@ -978,32 +744,10 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
 	    else if (d->optind == argc)
 	      {
 		if (print_errors)
-		  {
-#if defined _LIBC
-		    char *buf;
+		  fprintf (stderr,
+			   _("%s: option requires an argument -- '%c'\n"),
+			   argv[0], c);
 
-		    if (__asprintf (&buf, _("\
-%s: option requires an argument -- '%c'\n"),
-				    argv[0], c) >= 0)
-		      {
-			_IO_flockfile (stderr);
-
-			int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
-			((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
-
-			__fxprintf (NULL, "%s", buf);
-
-			((_IO_FILE *) stderr)->_flags2 = old_flags2;
-			_IO_funlockfile (stderr);
-
-			free (buf);
-		      }
-#else
-		    fprintf (stderr,
-			     _("%s: option requires an argument -- '%c'\n"),
-			     argv[0], c);
-#endif
-		  }
 		d->optopt = c;
 		if (optstring[0] == ':')
 		  c = ':';
diff --git a/posix/tst-getopt-cancel.c b/posix/tst-getopt-cancel.c
new file mode 100644
index 0000000..594596a
--- /dev/null
+++ b/posix/tst-getopt-cancel.c
@@ -0,0 +1,284 @@
+/* Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* fprintf is a cancellation point, but getopt is not supposed to be a
+   cancellation point, even when it prints error messages.  */
+
+/* Note: getopt.h must be included first in this file, so we get the
+   GNU getopt rather than the POSIX one.  */
+#include <getopt.h>
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <fcntl.h>
+#include <pthread.h>
+#include <unistd.h>
+
+#include <support/support.h>
+#include <support/temp_file.h>
+#include <support/xthread.h>
+
+static bool
+check_stderr (bool expect_errmsg, FILE *stderr_trapped)
+{
+  static char *lineptr = 0;
+  static size_t linesz = 0;
+
+  bool got_errmsg = false;
+  rewind (stderr_trapped);
+  while (getline (&lineptr, &linesz, stderr_trapped) > 0)
+    {
+      got_errmsg = true;
+      fputs (lineptr, stdout);
+    }
+  rewind (stderr_trapped);
+  ftruncate (fileno (stderr_trapped), 0);
+  return got_errmsg == expect_errmsg;
+}
+
+struct test_short
+{
+  const char *label;
+  const char *opts;
+  const char *const argv[8];
+  int argc;
+  bool expect_errmsg;
+};
+
+struct test_long
+{
+  const char *label;
+  const char *opts;
+  const struct option longopts[4];
+  const char *const argv[8];
+  int argc;
+  bool expect_errmsg;
+};
+
+#define DEFINE_TEST_DRIVER(test_type, getopt_call)			\
+  struct test_type##_tdata						\
+  {									\
+    pthread_mutex_t *sync;						\
+    const struct test_type *tcase;					\
+    bool ok;								\
+  };									\
+									\
+  static void *								\
+  test_type##_threadproc (void *data)					\
+  {									\
+    struct test_type##_tdata *tdata = data;				\
+    const struct test_type *tc = tdata->tcase;				\
+									\
+    xpthread_mutex_lock (tdata->sync);					\
+    xpthread_mutex_unlock (tdata->sync);				\
+									\
+    /* At this point, this thread has a cancellation pending.		\
+       We should still be able to get all the way through a getopt	\
+       loop without being cancelled.					\
+       Setting optind to 0 forces getopt to reinitialize itself.  */	\
+    optind = 0;								\
+    opterr = 1;								\
+    optopt = 0;								\
+    while (getopt_call != -1)						\
+      ;									\
+    tdata->ok = true;							\
+									\
+    pthread_testcancel();						\
+    return 0;								\
+  }									\
+									\
+  static bool								\
+  do_##test_type (const struct test_type *tcase, FILE *stderr_trapped)	\
+  {									\
+    pthread_mutex_t sync;						\
+    struct test_type##_tdata tdata;					\
+									\
+    printf("begin: %s\n", tcase->label);				\
+									\
+    xpthread_mutex_init (&sync, 0);					\
+    xpthread_mutex_lock (&sync);					\
+									\
+    tdata.sync = &sync;							\
+    tdata.tcase = tcase;						\
+    tdata.ok = false;							\
+									\
+    pthread_t thr = xpthread_create (0, test_type##_threadproc,		\
+				     (void *)&tdata);			\
+    xpthread_cancel (thr);						\
+    xpthread_mutex_unlock (&sync);					\
+    void *rv = xpthread_join (thr);					\
+									\
+    xpthread_mutex_destroy (&sync);					\
+									\
+    bool ok = true;							\
+    if (!check_stderr (tcase->expect_errmsg, stderr_trapped))		\
+      {									\
+	ok = false;							\
+	printf("FAIL: %s: stderr not as expected\n", tcase->label);	\
+      }									\
+    if (!tdata.ok)							\
+      {									\
+	ok = false;							\
+	printf("FAIL: %s: did not complete loop\n", tcase->label);	\
+      }									\
+    if (rv != PTHREAD_CANCELED)						\
+      {									\
+	ok = false;							\
+	printf("FAIL: %s: thread was not cancelled\n", tcase->label);	\
+      }									\
+    if (ok)								\
+      printf ("pass: %s\n", tcase->label);				\
+    return ok;								\
+  }
+
+DEFINE_TEST_DRIVER (test_short,
+		    getopt (tc->argc, (char *const *)tc->argv, tc->opts))
+DEFINE_TEST_DRIVER (test_long,
+		    getopt_long (tc->argc, (char *const *)tc->argv,
+				 tc->opts, tc->longopts, 0))
+
+/* Caution: all option strings must begin with a '+' or '-' so that
+   getopt does not attempt to permute the argument vector (which is in
+   read-only memory).  */
+const struct test_short tests_short[] = {
+  { "no errors",
+    "+ab:c", { "program", "-ac", "-b", "x", 0 }, 4, false },
+  { "invalid option",
+    "+ab:c", { "program", "-d", 0 },		 2, true },
+  { "missing argument",
+    "+ab:c", { "program", "-b", 0 },		 2, true },
+  { 0 }
+};
+
+const struct test_long tests_long[] = {
+  { "no errors (long)",
+    "+ab:c", { { "alpha",   no_argument,       0, 'a' },
+	       { "bravo",   required_argument, 0, 'b' },
+	       { "charlie", no_argument,       0, 'c' },
+	       { 0 } },
+    { "program", "-a", "--charlie", "--bravo=x", 0 }, 4, false },
+
+  { "invalid option (long)",
+    "+ab:c", { { "alpha",   no_argument,       0, 'a' },
+	       { "bravo",   required_argument, 0, 'b' },
+	       { "charlie", no_argument,       0, 'c' },
+	       { 0 } },
+    { "program", "-a", "--charlie", "--dingo", 0 }, 4, true },
+
+  { "unwanted argument",
+    "+ab:c", { { "alpha",   no_argument,       0, 'a' },
+	       { "bravo",   required_argument, 0, 'b' },
+	       { "charlie", no_argument,       0, 'c' },
+	       { 0 } },
+    { "program", "-a", "--charlie=dingo", "--bravo=x", 0 }, 4, true },
+
+  { "missing argument",
+    "+ab:c", { { "alpha",   no_argument,       0, 'a' },
+	       { "bravo",   required_argument, 0, 'b' },
+	       { "charlie", no_argument,       0, 'c' },
+	       { 0 } },
+    { "program", "-a", "--charlie", "--bravo", 0 }, 4, true },
+
+  { "ambiguous options",
+    "+uvw", { { "veni", no_argument, 0, 'u' },
+	      { "vedi", no_argument, 0, 'v' },
+	      { "veci", no_argument, 0, 'w' } },
+    { "program", "--ve", 0 }, 2, true },
+
+  { "no errors (long W)",
+    "+ab:cW;", { { "alpha",   no_argument,	 0, 'a' },
+		 { "bravo",   required_argument, 0, 'b' },
+		 { "charlie", no_argument,	 0, 'c' },
+		 { 0 } },
+    { "program", "-a", "-W", "charlie", "-W", "bravo=x", 0 }, 6, false },
+
+  { "missing argument (W itself)",
+    "+ab:cW;", { { "alpha",   no_argument,	 0, 'a' },
+		 { "bravo",   required_argument, 0, 'b' },
+		 { "charlie", no_argument,	 0, 'c' },
+		 { 0 } },
+    { "program", "-a", "-W", "charlie", "-W", 0 }, 5, true },
+
+  { "missing argument (W longopt)",
+    "+ab:cW;", { { "alpha",   no_argument,	 0, 'a' },
+		 { "bravo",   required_argument, 0, 'b' },
+		 { "charlie", no_argument,	 0, 'c' },
+		 { 0 } },
+    { "program", "-a", "-W", "charlie", "-W", "bravo", 0 }, 6, true },
+
+  { "unwanted argument (W longopt)",
+    "+ab:cW;", { { "alpha",   no_argument,	 0, 'a' },
+		 { "bravo",   required_argument, 0, 'b' },
+		 { "charlie", no_argument,	 0, 'c' },
+		 { 0 } },
+    { "program", "-a", "-W", "charlie=dingo", "-W", "bravo=x", 0 }, 6, true },
+
+  { "ambiguous options (W)",
+    "+uvwW;", { { "veni", no_argument, 0, 'u' },
+		{ "vedi", no_argument, 0, 'v' },
+		{ "veci", no_argument, 0, 'w' } },
+    { "program", "-W", "ve", 0 }, 3, true },
+
+  { 0 }
+};
+
+static int
+do_test (void)
+{
+  int stderr_trap = create_temp_file ("stderr", 0);
+  if (stderr_trap < 0)
+    {
+      perror ("create_temp_file");
+      return 1;
+    }
+  FILE *stderr_trapped = fdopen(stderr_trap, "r+");
+  if (!stderr_trapped)
+    {
+      perror ("fdopen");
+      return 1;
+    }
+  int old_stderr = dup (fileno (stderr));
+  if (old_stderr < 0)
+    {
+      perror ("dup");
+      return 1;
+    }
+  if (dup2 (stderr_trap, 2) < 0)
+    {
+      perror ("dup2");
+      return 1;
+    }
+  rewind (stderr);
+
+  bool success = true;
+
+  for (const struct test_short *tcase = tests_short; tcase->label; tcase++)
+    success = do_test_short (tcase, stderr_trapped) && success;
+
+  for (const struct test_long *tcase = tests_long; tcase->label; tcase++)
+    success = do_test_long (tcase, stderr_trapped) && success;
+
+  dup2 (old_stderr, 2);
+  close (old_stderr);
+  fclose (stderr_trapped);
+
+  return success ? 0 : 1;
+}
+
+#include <support/test-driver.c>
diff --git a/stdio-common/fxprintf.c b/stdio-common/fxprintf.c
index 5ed0bb0..82d4f2e 100644
--- a/stdio-common/fxprintf.c
+++ b/stdio-common/fxprintf.c
@@ -16,14 +16,50 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <assert.h>
-#include <ctype.h>
 #include <stdarg.h>
 #include <stdio.h>
-#include <wchar.h>
+#include <stdlib.h>
 #include <string.h>
+#include <wchar.h>
 #include <libioP.h>
 
+static int
+locked_vfxprintf (FILE *fp, const char *fmt, va_list ap)
+{
+  if (_IO_fwide (fp, 0) <= 0)
+    return _IO_vfprintf (fp, fmt, ap);
+
+  /* We must convert the narrow format string to a wide one.
+     Each byte can produce at most one wide character.  */
+  wchar_t *wfmt;
+  mbstate_t mbstate;
+  int res;
+  int used_malloc = 0;
+  size_t len = strlen (fmt) + 1;
+
+  if (__glibc_unlikely (len > SIZE_MAX / sizeof (wchar_t)))
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+  if (__libc_use_alloca (len * sizeof (wchar_t)))
+    wfmt = alloca (len * sizeof (wchar_t));
+  else if ((wfmt = malloc (len * sizeof (wchar_t))) == NULL)
+    return -1;
+  else
+    used_malloc = 1;
+
+  memset (&mbstate, 0, sizeof mbstate);
+  res = __mbsrtowcs (wfmt, &fmt, len, &mbstate);
+
+  if (res != -1)
+    res = _IO_vfwprintf (fp, wfmt, ap);
+
+  if (used_malloc)
+    free (wfmt);
+
+  return res;
+}
 
 int
 __fxprintf (FILE *fp, const char *fmt, ...)
@@ -33,23 +69,31 @@ __fxprintf (FILE *fp, const char *fmt, ...)
 
   va_list ap;
   va_start (ap, fmt);
+  _IO_flockfile (fp);
 
-  int res;
-  if (_IO_fwide (fp, 0) > 0)
-    {
-      size_t len = strlen (fmt) + 1;
-      wchar_t wfmt[len];
-      for (size_t i = 0; i < len; ++i)
-	{
-	  assert (isascii (fmt[i]));
-	  wfmt[i] = fmt[i];
-	}
-      res = __vfwprintf (fp, wfmt, ap);
-    }
-  else
-    res = _IO_vfprintf (fp, fmt, ap);
+  int res = locked_vfxprintf (fp, fmt, ap);
 
+  _IO_funlockfile (fp);
   va_end (ap);
+  return res;
+}
 
+int
+__fxprintf_nocancel (FILE *fp, const char *fmt, ...)
+{
+  if (fp == NULL)
+    fp = stderr;
+
+  va_list ap;
+  va_start (ap, fmt);
+  _IO_flockfile (fp);
+  int save_flags2 = ((_IO_FILE *)fp)->_flags2;
+  ((_IO_FILE *)fp)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+  int res = locked_vfxprintf (fp, fmt, ap);
+
+  ((_IO_FILE *)fp)->_flags2 = save_flags2;
+  _IO_funlockfile (fp);
+  va_end (ap);
   return res;
 }

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=7e161bef0bc9d5ea5e6f3dd490ecd5da6f642671

commit 7e161bef0bc9d5ea5e6f3dd490ecd5da6f642671
Author: Zack Weinberg <zackw@panix.com>
Date:   Sat Apr 1 10:01:40 2017 -0400

    getopt: fix fencepost error in ambiguous-W-option handling
    
    getopt_long contains an undocumented (AFAICT) feature in which, if you
    put "W;" in the short-options list, then '-W foo' and '-Wfoo' are
    treated as equivalent to '--foo'.  This is implemented with a partial
    second copy of the code for handling long options, and that code
    increments optind one too many times when recovering from an ambiguous
    abbreviated option, which can cause the main loop to walk past the end
    of argv and crash.
    
    I discovered this while writing a test case that tries to exercise all
    of getopt's error reporting paths; I wouldn't be surprised to learn
    that this feature is never used by real applications.
    
    	* posix/getopt.c (_getopt_internal_r): Don't increment
    	d->optind a second time when reporting ambiguous -W options.

diff --git a/ChangeLog b/ChangeLog
index ba702c0..48e5b03 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
 2017-04-07  Zack Weinberg  <zackw@panix.com>
 
+	* posix/getopt.c (_getopt_internal_r): Don't increment
+	d->optind a second time when reporting ambiguous -W options.
+
 	* posix/getopt_int.h: Include getopt.h.
 	Use impl-namespace names for all arguments to _getopt_internal and
 	_getopt_internal_r.
diff --git a/posix/getopt.c b/posix/getopt.c
index f1fa016..e616aa6 100644
--- a/posix/getopt.c
+++ b/posix/getopt.c
@@ -850,7 +850,6 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
 #endif
 	      }
 	    d->__nextchar += strlen (d->__nextchar);
-	    d->optind++;
 	    return '?';
 	  }
 	if (pfound != NULL)

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=7f71f9c1d6735e713de193faf03edb37c4bcb563

commit 7f71f9c1d6735e713de193faf03edb37c4bcb563
Author: Zack Weinberg <zackw@panix.com>
Date:   Fri Mar 31 07:58:07 2017 -0400

    getopt: merge straightforward changes from gnulib
    
    This covers changes with little or no consequences when the code is
    used in glibc.
    
    	* posix/getopt_int.h: Include getopt.h.
    	Use impl-namespace names for all arguments to _getopt_internal and
    	_getopt_internal_r.
    	Declare __ordering enum outside the struct.
    	Harmonize comments with gnulib.
    	* posix/getopt1.c: Simplify #ifdeffage at top of file. Remove
    	ELIDE_CODE logic entirely.  Move inclusion of stdlib.h to
    	#ifdef TEST block and make unconditional.  Do not define NULL.
    	* posix/getopt.c: Partial merge from gnulib, covering the
    	initial includes and global declarations, commentary, and
    	a couple of semantically-neutral code changes.

diff --git a/ChangeLog b/ChangeLog
index c53c80e..ba702c0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
 2017-04-07  Zack Weinberg  <zackw@panix.com>
 
+	* posix/getopt_int.h: Include getopt.h.
+	Use impl-namespace names for all arguments to _getopt_internal and
+	_getopt_internal_r.
+	Declare __ordering enum outside the struct.
+	Harmonize comments with gnulib.
+	* posix/getopt1.c: Simplify #ifdeffage at top of file. Remove
+	ELIDE_CODE logic entirely.  Move inclusion of stdlib.h to
+	#ifdef TEST block and make unconditional.  Do not define NULL.
+	* posix/getopt.c: Partial merge from gnulib, covering the
+	initial includes and global declarations, commentary, and
+	a couple of semantically-neutral code changes.
+
 	* posix/getopt.c, posix/getopt.h, posix/getopt1.c, posix/getopt_int.h:
 	Use '...' instead of `...' for quotation marks inside
 	comments and strings.
diff --git a/posix/getopt.c b/posix/getopt.c
index ac2b0cf..f1fa016 100644
--- a/posix/getopt.c
+++ b/posix/getopt.c
@@ -19,52 +19,17 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-/* 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>
-
-/* Comment out all this code if we are using the GNU C Library, and are not
-   actually compiling the library itself.  This code is part of the GNU C
-   Library, but also included in many other GNU distributions.  Compiling
-   and linking in this code is a waste when using the GNU C library
-   (especially if it is a shared library).  Rather than having every GNU
-   program understand 'configure --with-gnu-libc' and omit the object files,
-   it is simpler to just do this in the source for each such file.  */
-
-#define GETOPT_INTERFACE_VERSION 2
-#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
-# include <gnu-versions.h>
-# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
-#  define ELIDE_CODE
-# endif
-#endif
-
-#ifndef ELIDE_CODE
-
-
-/* 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 <unistd.h>
 #include <string.h>
 
-#ifdef VMS
-# include <unixlib.h>
-#endif
-
 #ifdef _LIBC
 # include <libintl.h>
 #else
@@ -72,29 +37,28 @@
 # define _(msgid) gettext (msgid)
 #endif
 
-#if defined _LIBC
-# include <wchar.h>
-#endif
-
-#ifndef attribute_hidden
-# 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.
-
-   As 'getopt' 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.
+/* This implementation of 'getopt' has three modes for handling
+   options interspersed with non-option arguments.  It can stop
+   scanning for options at the first non-option argument encountered,
+   as POSIX specifies.  It can continue scanning for options after the
+   first non-option argument, but permute 'argv' as it goes so that,
+   after 'getopt' is done, all the options precede all the non-option
+   arguments and 'optind' points to the first non-option argument.
+   Or, it can report non-option arguments as if they were arguments to
+   the option character '\x01'.
+
+   The default behavior of 'getopt_long' is to permute the argument list.
+   When this implementation is used standalone, the default behavior of
+   'getopt' is to stop at the first non-option argument, but when it is
+   used as part of GNU libc it also permutes the argument list.  In both
+   cases, setting the environment variable POSIXLY_CORRECT to any value
+   disables permutation.
+
+   If the first character of the OPTSTRING argument to 'getopt' or
+   'getopt_long' is '+', both functions will stop at the first
+   non-option argument.  If it is '-', both functions will report
+   non-option arguments as arguments to the option character '\x01'.  */
 
-   Setting the environment variable POSIXLY_CORRECT disables permutation.
-   Then the 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.
@@ -136,17 +100,6 @@ int optopt = '?';
 static struct _getopt_data getopt_data;
 
 
-#ifndef __GNU_LIBRARY__
-
-/* Avoid depending on library functions or files
-   whose names are inconsistent.  */
-
-#ifndef getenv
-extern char *getenv ();
-#endif
-
-#endif /* not __GNU_LIBRARY__ */
-
 /* Exchange two adjacent subsequences of ARGV.
    One subsequence is elements [first_nonopt,last_nonopt)
    which contains all the non-options that have been skipped so far.
@@ -225,7 +178,7 @@ _getopt_initialize (int argc, char *const *argv, const char *optstring,
 
   d->__nextchar = NULL;
 
-  d->__posixly_correct = posixly_correct | !!getenv ("POSIXLY_CORRECT");
+  d->__posixly_correct = posixly_correct || !!getenv ("POSIXLY_CORRECT");
 
   /* Determine how to handle the ordering of options and nonoptions.  */
 
@@ -731,7 +684,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
 
   {
     char c = *d->__nextchar++;
-    char *temp = strchr (optstring, c);
+    const char *temp = strchr (optstring, c);
 
     /* Increment 'optind' when we start to process its last character.  */
     if (*d->__nextchar == '\0')
@@ -776,9 +729,6 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
     /* Convenience. Treat POSIX -W foo same as long option --foo */
     if (temp[0] == 'W' && temp[1] == ';')
       {
-	if (longopts == NULL)
-	  goto no_longs;
-
 	char *nameend;
 	const struct option *p;
 	const struct option *pfound = NULL;
@@ -787,6 +737,9 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
 	int indfound = 0;
 	int option_index;
 
+	if (longopts == NULL)
+	  goto no_longs;
+
 	/* This is an option that requires an argument.  */
 	if (*d->__nextchar != '\0')
 	  {
@@ -997,7 +950,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
 
       no_longs:
 	d->__nextchar = NULL;
-	return 'W';	/* Let the application handle it.   */
+	return 'W';   /* Let the application handle it.  */
       }
     if (temp[1] == ':')
       {
@@ -1090,13 +1043,21 @@ _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, 0);
+			   0, POSIXLY_CORRECT);
 }
 
 #ifdef _LIBC
@@ -1110,7 +1071,6 @@ __posix_getopt (int argc, char *const *argv, const char *optstring)
 }
 #endif
 
-#endif	/* Not ELIDE_CODE.  */
 
 #ifdef TEST
 
diff --git a/posix/getopt1.c b/posix/getopt1.c
index b9a8538..b4ae6e4 100644
--- a/posix/getopt1.c
+++ b/posix/getopt1.c
@@ -16,48 +16,13 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
+#ifndef _LIBC
+#include "config.h"
 #endif
 
-#ifdef _LIBC
-# include <getopt.h>
-#else
-# include "getopt.h"
-#endif
+#include "getopt.h"
 #include "getopt_int.h"
 
-#include <stdio.h>
-
-/* Comment out all this code if we are using the GNU C Library, and are not
-   actually compiling the library itself.  This code is part of the GNU C
-   Library, but also included in many other GNU distributions.  Compiling
-   and linking in this code is a waste when using the GNU C library
-   (especially if it is a shared library).  Rather than having every GNU
-   program understand 'configure --with-gnu-libc' and omit the object files,
-   it is simpler to just do this in the source for each such file.  */
-
-#define GETOPT_INTERFACE_VERSION 2
-#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
-#include <gnu-versions.h>
-#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
-#define ELIDE_CODE
-#endif
-#endif
-
-#ifndef ELIDE_CODE
-
-
-/* This needs to come after some library #include
-   to get __GNU_LIBRARY__ defined.  */
-#ifdef __GNU_LIBRARY__
-#include <stdlib.h>
-#endif
-
-#ifndef	NULL
-#define NULL 0
-#endif
-
 int
 getopt_long (int argc, char *const *argv, const char *options,
 	     const struct option *long_options, int *opt_index)
@@ -95,11 +60,11 @@ _getopt_long_only_r (int argc, char *const *argv, const char *options,
 			     1, d, 0);
 }
 
-#endif	/* Not ELIDE_CODE.  */
 
 #ifdef TEST
 
 #include <stdio.h>
+#include <stdlib.h>
 
 int
 main (int argc, char **argv)
diff --git a/posix/getopt_int.h b/posix/getopt_int.h
index ac6ddef..9ac03bd 100644
--- a/posix/getopt_int.h
+++ b/posix/getopt_int.h
@@ -19,15 +19,43 @@
 #ifndef _GETOPT_INT_H
 #define _GETOPT_INT_H	1
 
+#include <getopt.h>
+
 extern int _getopt_internal (int ___argc, char *const *___argv,
 			     const char *__shortopts,
-		             const struct option *__longopts, int *__longind,
-			     int __long_only, int posixly_correct);
+			     const struct option *__longopts, int *__longind,
+			     int __long_only, int __posixly_correct);
 
 
 /* Reentrant versions which can handle parsing multiple argument
    vectors at the same time.  */
 
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+   REQUIRE_ORDER means don't recognize them as options; stop option
+   processing when the first non-option is seen.  This is what POSIX
+   specifies should happen.
+
+   PERMUTE means permute the contents of ARGV as we scan, so that
+   eventually all the non-options are at the end.  This allows options
+   to be given in any order, even with programs that were not written
+   to expect this.
+
+   RETURN_IN_ORDER is an option available to programs that were
+   written to expect options and other ARGV-elements in any order
+   and that care about the ordering of the two.  We describe each
+   non-option ARGV-element as if it were the argument of an option
+   with character code 1.
+
+   The special argument '--' forces an end of option-scanning regardless
+   of the value of 'ordering'.  In the case of RETURN_IN_ORDER, only
+   '--' can cause 'getopt' to return -1 with 'optind' != ARGC.  */
+
+enum __ord
+  {
+    REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+  };
+
 /* Data type for reentrant functions.  */
 struct _getopt_data
 {
@@ -52,41 +80,10 @@ struct _getopt_data
      by advancing to the next ARGV-element.  */
   char *__nextchar;
 
-  /* Describe how to deal with options that follow non-option ARGV-elements.
-
-     If the caller did not specify anything,
-     the default is REQUIRE_ORDER if the environment variable
-     POSIXLY_CORRECT is defined, PERMUTE otherwise.
-
-     REQUIRE_ORDER means don't recognize them as options;
-     stop option processing when the first non-option is seen.
-     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.
-
-     PERMUTE is the default.  We permute the contents of ARGV as we
-     scan, so that eventually all the non-options are at the end.
-     This allows options to be given in any order, even with programs
-     that were not written to expect this.
-
-     RETURN_IN_ORDER is an option available to programs that were
-     written to expect options and other ARGV-elements in any order
-     and that care about the ordering of the two.  We describe each
-     non-option ARGV-element as if it were the argument of an option
-     with character code 1.  Using '-' as the first character of the
-     list of option characters selects this mode of operation.
-
-     The special argument '--' forces an end of option-scanning regardless
-     of the value of 'ordering'.  In the case of RETURN_IN_ORDER, only
-     '--' can cause 'getopt' to return -1 with 'optind' != ARGC.  */
-
-  enum
-    {
-      REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
-    } __ordering;
-
-  /* If the POSIXLY_CORRECT environment variable is set.  */
+  /* See __ord above.  */
+  enum __ord __ordering;
+
+  /* True if behaving strictly as specified by POSIX.  */
   int __posixly_correct;
 
 
@@ -108,7 +105,7 @@ extern int _getopt_internal_r (int ___argc, char *const *___argv,
 			       const char *__shortopts,
 			       const struct option *__longopts, int *__longind,
 			       int __long_only, struct _getopt_data *__data,
-			       int posixly_correct);
+			       int __posixly_correct);
 
 extern int _getopt_long_r (int ___argc, char *const *___argv,
 			   const char *__shortopts,

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=7784135eb0de2d083bf3460c1386aee1c056e96e

commit 7784135eb0de2d083bf3460c1386aee1c056e96e
Author: Zack Weinberg <zackw@panix.com>
Date:   Fri Mar 31 07:39:55 2017 -0400

    getopt: merge from gnulib: don't use `...' quotes
    
    I'm not sure whether this is official GNU style now, but `...' quotes
    haven't looked properly balanced in most people's terminal fonts since
    2001ish? and gnulib has chosen to switch over to '...' quotes.
    I'm merging this separately from the other changes in gnulib because
    it's very mechanical.
    
    	* posix/getopt.c, posix/getopt.h, posix/getopt1.c, posix/getopt_int.h:
    	Use '...' instead of `...' for quotation marks inside
    	comments and strings.

diff --git a/ChangeLog b/ChangeLog
index aaa08df..c53c80e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2017-04-07  Zack Weinberg  <zackw@panix.com>
 
+	* posix/getopt.c, posix/getopt.h, posix/getopt1.c, posix/getopt_int.h:
+	Use '...' instead of `...' for quotation marks inside
+	comments and strings.
+
 	* config.h.in (USE_NONOPTION_FLAGS): Remove.
 	* csu/init-first.c: Remove all #ifdef USE_NONOPTION_FLAGS blocks.
 	* sysdeps/mach/hurd/i386/init-first.c: Likewise.
diff --git a/posix/getopt.c b/posix/getopt.c
index 6a28ed6..ac2b0cf 100644
--- a/posix/getopt.c
+++ b/posix/getopt.c
@@ -36,7 +36,7 @@
    Library, but also included in many other GNU distributions.  Compiling
    and linking in this code is a waste when using the GNU C library
    (especially if it is a shared library).  Rather than having every GNU
-   program understand `configure --with-gnu-libc' and omit the object files,
+   program understand 'configure --with-gnu-libc' and omit the object files,
    it is simpler to just do this in the source for each such file.  */
 
 #define GETOPT_INTERFACE_VERSION 2
@@ -80,11 +80,11 @@
 # define attribute_hidden
 #endif
 
-/* This version of `getopt' appears to the caller like standard Unix `getopt'
+/* 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.
 
-   As `getopt' works, it permutes the elements of ARGV so that,
+   As 'getopt' 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.
 
@@ -97,24 +97,24 @@
 #include "getopt.h"
 #include "getopt_int.h"
 
-/* For communication from `getopt' to the caller.
-   When `getopt' finds an option that takes an argument,
+/* For communication from 'getopt' to the caller.
+   When 'getopt' finds an option that takes an argument,
    the argument value is returned here.
-   Also, when `ordering' is RETURN_IN_ORDER,
+   Also, when 'ordering' is RETURN_IN_ORDER,
    each non-option ARGV-element is returned here.  */
 
 char *optarg;
 
 /* Index in ARGV of the next element to be scanned.
    This is used for communication to and from the caller
-   and for communication between successive calls to `getopt'.
+   and for communication between successive calls to 'getopt'.
 
-   On entry to `getopt', zero means this is the first call; initialize.
+   On entry to 'getopt', zero means this is the first call; initialize.
 
-   When `getopt' returns -1, this is the index of the first of the
+   When 'getopt' returns -1, this is the index of the first of the
    non-option elements that the caller should itself scan.
 
-   Otherwise, `optind' communicates from one call to the next
+   Otherwise, 'optind' communicates from one call to the next
    how much of ARGV has been scanned so far.  */
 
 /* 1003.2 says this must be 1 before any call.  */
@@ -153,7 +153,7 @@ extern char *getenv ();
    The other is elements [last_nonopt,optind), which contains all
    the options processed since those non-options were skipped.
 
-   `first_nonopt' and `last_nonopt' are relocated so that they describe
+   'first_nonopt' and 'last_nonopt' are relocated so that they describe
    the new indices of the non-options in ARGV after they are moved.  */
 
 static void
@@ -252,48 +252,48 @@ _getopt_initialize (int argc, char *const *argv, const char *optstring,
 
    If an element of ARGV starts with '-', and is not exactly "-" or "--",
    then it is an option element.  The characters of this element
-   (aside from the initial '-') are option characters.  If `getopt'
+   (aside from the initial '-') are option characters.  If 'getopt'
    is called repeatedly, it returns successively each of the option characters
    from each of the option elements.
 
-   If `getopt' finds another option character, it returns that character,
-   updating `optind' and `nextchar' so that the next call to `getopt' can
+   If 'getopt' finds another option character, it returns that character,
+   updating 'optind' and 'nextchar' so that the next call to 'getopt' can
    resume the scan with the following option character or ARGV-element.
 
-   If there are no more option characters, `getopt' returns -1.
-   Then `optind' is the index in ARGV of the first ARGV-element
+   If there are no more option characters, 'getopt' returns -1.
+   Then 'optind' is the index in ARGV of the first ARGV-element
    that is not an option.  (The ARGV-elements have been permuted
    so that those that are not options now come last.)
 
    OPTSTRING is a string containing the legitimate option characters.
    If an option character is seen that is not listed in OPTSTRING,
-   return '?' after printing an error message.  If you set `opterr' to
+   return '?' after printing an error message.  If you set 'opterr' to
    zero, the error message is suppressed but we still return '?'.
 
    If a char in OPTSTRING is followed by a colon, that means it wants an arg,
    so the following text in the same ARGV-element, or the text of the following
-   ARGV-element, is returned in `optarg'.  Two colons mean an option that
+   ARGV-element, is returned in 'optarg'.  Two colons mean an option that
    wants an optional arg; if there is text in the current ARGV-element,
-   it is returned in `optarg', otherwise `optarg' is set to zero.
+   it is returned in 'optarg', otherwise 'optarg' is set to zero.
 
-   If OPTSTRING starts with `-' or `+', it requests different methods of
+   If OPTSTRING starts with '-' or '+', it requests different methods of
    handling the non-option ARGV-elements.
    See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
 
-   Long-named options begin with `--' instead of `-'.
+   Long-named options begin with '--' instead of '-'.
    Their names may be abbreviated as long as the abbreviation is unique
    or is an exact match for some defined option.  If they have an
    argument, it follows the option name in the same ARGV-element, separated
-   from the option name by a `=', or else the in next ARGV-element.
-   When `getopt' finds a long-named option, it returns 0 if that option's
-   `flag' field is nonzero, the value of the option's `val' field
-   if the `flag' field is zero.
+   from the option name by a '=', or else the in next ARGV-element.
+   When 'getopt' finds a long-named option, it returns 0 if that option's
+   '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
+   LONGOPTS is a vector of 'struct option' terminated by an
    element containing a name which is zero.
 
    LONGIND returns the index in LONGOPT of the long-named option found.
@@ -361,7 +361,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
 	  d->__last_nonopt = d->optind;
 	}
 
-      /* The special ARGV-element `--' means premature end of options.
+      /* The special ARGV-element '--' means premature end of options.
 	 Skip it like a null option,
 	 then exchange with previous non-options as if it were an option,
 	 then skip everything else like a non-option.  */
@@ -733,7 +733,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
     char c = *d->__nextchar++;
     char *temp = strchr (optstring, c);
 
-    /* Increment `optind' when we start to process its last character.  */
+    /* Increment 'optind' when we start to process its last character.  */
     if (*d->__nextchar == '\0')
       ++d->optind;
 
@@ -832,7 +832,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
 	    return c;
 	  }
 	else
-	  /* We already incremented `d->optind' once;
+	  /* We already incremented 'd->optind' once;
 	     increment it again when taking next ARGV-elt as argument.  */
 	  d->optarg = argv[d->optind++];
 
@@ -1059,7 +1059,7 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
 		  c = '?';
 	      }
 	    else
-	      /* We already incremented `optind' once;
+	      /* We already incremented 'optind' once;
 		 increment it again when taking next ARGV-elt as argument.  */
 	      d->optarg = argv[d->optind++];
 	    d->__nextchar = NULL;
@@ -1115,7 +1115,7 @@ __posix_getopt (int argc, char *const *argv, const char *optstring)
 #ifdef TEST
 
 /* Compile with -DTEST to make an executable for use in testing
-   the above definition of `getopt'.  */
+   the above definition of 'getopt'.  */
 
 int
 main (int argc, char **argv)
diff --git a/posix/getopt.h b/posix/getopt.h
index 4353293..c83a186 100644
--- a/posix/getopt.h
+++ b/posix/getopt.h
@@ -48,29 +48,29 @@
 extern "C" {
 #endif
 
-/* For communication from `getopt' to the caller.
-   When `getopt' finds an option that takes an argument,
+/* For communication from 'getopt' to the caller.
+   When 'getopt' finds an option that takes an argument,
    the argument value is returned here.
-   Also, when `ordering' is RETURN_IN_ORDER,
+   Also, when 'ordering' is RETURN_IN_ORDER,
    each non-option ARGV-element is returned here.  */
 
 extern char *optarg;
 
 /* Index in ARGV of the next element to be scanned.
    This is used for communication to and from the caller
-   and for communication between successive calls to `getopt'.
+   and for communication between successive calls to 'getopt'.
 
-   On entry to `getopt', zero means this is the first call; initialize.
+   On entry to 'getopt', zero means this is the first call; initialize.
 
-   When `getopt' returns -1, this is the index of the first of the
+   When 'getopt' returns -1, this is the index of the first of the
    non-option elements that the caller should itself scan.
 
-   Otherwise, `optind' communicates from one call to the next
+   Otherwise, 'optind' communicates from one call to the next
    how much of ARGV has been scanned so far.  */
 
 extern int optind;
 
-/* Callers store zero here to inhibit the error message `getopt' prints
+/* Callers store zero here to inhibit the error message 'getopt' prints
    for unrecognized options.  */
 
 extern int opterr;
@@ -82,24 +82,24 @@ extern int optopt;
 #ifndef __need_getopt
 /* Describe the long-named options requested by the application.
    The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
-   of `struct option' terminated by an element containing a name which is
+   of 'struct option' terminated by an element containing a name which is
    zero.
 
-   The field `has_arg' is:
+   The field 'has_arg' is:
    no_argument		(or 0) if the option does not take an argument,
    required_argument	(or 1) if the option requires an argument,
    optional_argument 	(or 2) if the option takes an optional argument.
 
-   If the field `flag' is not NULL, it points to a variable that is set
-   to the value given in the field `val' when the option is found, but
+   If the field 'flag' is not NULL, it points to a variable that is set
+   to the value given in the field 'val' when the option is found, but
    left unchanged if the option is not found.
 
-   To have a long-named option do something other than set an `int' to
-   a compiled-in constant, such as set a value from `optarg', set the
-   option's `flag' field to zero and its `val' field to a nonzero
+   To have a long-named option do something other than set an 'int' to
+   a compiled-in constant, such as set a value from 'optarg', set the
+   option's 'flag' field to zero and its 'val' field to a nonzero
    value (the equivalent single-letter option character, if there is
-   one).  For long options that have a zero `flag' field, `getopt'
-   returns the contents of the `val' field.  */
+   one).  For long options that have a zero 'flag' field, 'getopt'
+   returns the contents of the 'val' field.  */
 
 struct option
 {
@@ -111,7 +111,7 @@ struct option
   int val;
 };
 
-/* Names for the values of the `has_arg' field of `struct option'.  */
+/* Names for the values of the 'has_arg' field of 'struct option'.  */
 
 # define no_argument		0
 # define required_argument	1
@@ -125,23 +125,23 @@ struct option
 
    Return the option character from OPTS just read.  Return -1 when
    there are no more options.  For unrecognized options, or options
-   missing arguments, `optopt' is set to the option letter, and '?' is
+   missing arguments, 'optopt' is set to the option letter, and '?' is
    returned.
 
    The OPTS string is a list of characters which are recognized option
    letters, optionally followed by colons, specifying that that letter
-   takes an argument, to be placed in `optarg'.
+   takes an argument, to be placed in 'optarg'.
 
    If a letter in OPTS is followed by two colons, its argument is
-   optional.  This behavior is specific to the GNU `getopt'.
+   optional.  This behavior is specific to the GNU 'getopt'.
 
-   The argument `--' causes premature termination of argument
-   scanning, explicitly telling `getopt' that there are no more
+   The argument '--' causes premature termination of argument
+   scanning, explicitly telling 'getopt' that there are no more
    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
-   `getopt'.  */
+   'getopt'.  */
 
 #ifdef __GNU_LIBRARY__
 /* Many other libraries have conflicting prototypes for getopt, with
diff --git a/posix/getopt1.c b/posix/getopt1.c
index 09c69fd..b9a8538 100644
--- a/posix/getopt1.c
+++ b/posix/getopt1.c
@@ -34,7 +34,7 @@
    Library, but also included in many other GNU distributions.  Compiling
    and linking in this code is a waste when using the GNU C library
    (especially if it is a shared library).  Rather than having every GNU
-   program understand `configure --with-gnu-libc' and omit the object files,
+   program understand 'configure --with-gnu-libc' and omit the object files,
    it is simpler to just do this in the source for each such file.  */
 
 #define GETOPT_INTERFACE_VERSION 2
@@ -161,11 +161,11 @@ main (int argc, char **argv)
 	  break;
 
 	case 'c':
-	  printf ("option c with value `%s'\n", optarg);
+	  printf ("option c with value '%s'\n", optarg);
 	  break;
 
 	case 'd':
-	  printf ("option d with value `%s'\n", optarg);
+	  printf ("option d with value '%s'\n", optarg);
 	  break;
 
 	case '?':
diff --git a/posix/getopt_int.h b/posix/getopt_int.h
index 71b9655..ac6ddef 100644
--- a/posix/getopt_int.h
+++ b/posix/getopt_int.h
@@ -62,7 +62,7 @@ struct _getopt_data
      stop option processing when the first non-option is seen.
      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
+     variable POSIXLY_CORRECT, or using '+' as the first character
      of the list of option characters.
 
      PERMUTE is the default.  We permute the contents of ARGV as we
@@ -74,12 +74,12 @@ struct _getopt_data
      written to expect options and other ARGV-elements in any order
      and that care about the ordering of the two.  We describe each
      non-option ARGV-element as if it were the argument of an option
-     with character code 1.  Using `-' as the first character of the
+     with character code 1.  Using '-' as the first character of the
      list of option characters selects this mode of operation.
 
-     The special argument `--' forces an end of option-scanning regardless
-     of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
-     `--' can cause `getopt' to return -1 with `optind' != ARGC.  */
+     The special argument '--' forces an end of option-scanning regardless
+     of the value of 'ordering'.  In the case of RETURN_IN_ORDER, only
+     '--' can cause 'getopt' to return -1 with 'optind' != ARGC.  */
 
   enum
     {
@@ -93,8 +93,8 @@ struct _getopt_data
   /* Handle permutation of arguments.  */
 
   /* Describe the part of ARGV that contains non-options that have
-     been skipped.  `first_nonopt' is the index in ARGV of the first
-     of them; `last_nonopt' is the index after the last of them.  */
+     been skipped.  'first_nonopt' is the index in ARGV of the first
+     of them; 'last_nonopt' is the index after the last of them.  */
 
   int __first_nonopt;
   int __last_nonopt;

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=bf079e19f50d64aa5e05b5e17ec29afab9aabb20

commit bf079e19f50d64aa5e05b5e17ec29afab9aabb20
Author: Zack Weinberg <zackw@panix.com>
Date:   Wed Mar 29 16:58:58 2017 -0400

    getopt: remove USE_NONOPTION_FLAGS
    
    glibc's implementation of getopt includes code to parse an environment
    variable named _XXX_GNU_nonoption_argv_flags_ (where XXX is the
    current process's PID in decimal); but all of it has been #ifdefed out
    since 2001, with no official way to turn it back on.
    
    According to commentary in our config.h.in, bash version 2.0 set this
    environment variable to indicate argv elements that were the result of
    glob expansion and therefore should not be treated as options, but the
    feature was "disabled later" because "it caused problems".  According
    to bash's CHANGES file, "later" was release 2.01; it gives no more
    detail about what the problems were.
    
    Version 2.0 of bash was released on the last day of 1996, and version
    2.01 in June of 1997.  Twenty years later, I think it is safe to
    assume that this environment variable isn't coming back.
    
    	* config.h.in (USE_NONOPTION_FLAGS): Remove.
    	* csu/init-first.c: Remove all #ifdef USE_NONOPTION_FLAGS blocks.
    	* sysdeps/mach/hurd/i386/init-first.c: Likewise.
    	* posix/getopt_int.h: Likewise.
    	* posix/getopt.c: Likewise. Also remove SWAP_FLAGS and the
    	__libc_argc and __libc_argv externs, which were only used by
    	#ifdef USE_NONOPTION_FLAGS blocks.
    	* posix/getopt_init.c: Remove file.
    	* posix/Makefile (routines): Remove getopt_init.
    	* include/getopt.h: Don't declare __getopt_initialize_environment.
    	* manual/getopt.texi: Remove mention of USE_NONOPTION_FLAGS in
    	a comment.

diff --git a/ChangeLog b/ChangeLog
index 9ae4706..aaa08df 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2017-04-07  Zack Weinberg  <zackw@panix.com>
+
+	* config.h.in (USE_NONOPTION_FLAGS): Remove.
+	* csu/init-first.c: Remove all #ifdef USE_NONOPTION_FLAGS blocks.
+	* sysdeps/mach/hurd/i386/init-first.c: Likewise.
+	* posix/getopt_int.h: Likewise.
+	* posix/getopt.c: Likewise. Also remove SWAP_FLAGS and the
+	__libc_argc and __libc_argv externs, which were only used by
+	#ifdef USE_NONOPTION_FLAGS blocks.
+	* posix/getopt_init.c: Remove file.
+	* posix/Makefile (routines): Remove getopt_init.
+	* include/getopt.h: Don't declare __getopt_initialize_environment.
+	* manual/getopt.texi: Remove mention of USE_NONOPTION_FLAGS in
+	a comment.
+
 2017-04-07  Florian Weimer  <fweimer@redhat.com>
 
 	* resolv/res_mkquery.c (res_nmkquery): Remove IQUERY support.
diff --git a/config.h.in b/config.h.in
index 4ce845d..2caa412 100644
--- a/config.h.in
+++ b/config.h.in
@@ -123,12 +123,6 @@
 /* Override abi-tags ABI version if necessary.  */
 #undef  __ABI_TAG_VERSION
 
-/* bash 2.0 introduced the _XXX_GNU_nonoption_argv_flags_ variable to help
-   getopt determine whether a parameter is a flag or not.  This features
-   was disabled later since it caused trouble.  We are by default therefore
-   disabling the support as well.  */
-#undef USE_NONOPTION_FLAGS
-
 /* Mach/Hurd specific: define if mig supports the `retcode' keyword.  */
 #undef	HAVE_MIG_RETCODE
 
diff --git a/csu/init-first.c b/csu/init-first.c
index 099e7bc..510ea2d 100644
--- a/csu/init-first.c
+++ b/csu/init-first.c
@@ -51,9 +51,6 @@ attribute_hidden
 _init (int argc, char **argv, char **envp)
 {
 #endif
-#ifdef USE_NONOPTION_FLAGS
-  extern void __getopt_clean_environment (char **);
-#endif
 
   __libc_multiple_libcs = &_dl_starting_up && !_dl_starting_up;
 
@@ -83,11 +80,6 @@ _init (int argc, char **argv, char **envp)
 
   __init_misc (argc, argv, envp);
 
-#ifdef USE_NONOPTION_FLAGS
-  /* This is a hack to make the special getopt in GNU libc working.  */
-  __getopt_clean_environment (envp);
-#endif
-
   /* Initialize ctype data.  */
   __ctype_init ();
 
diff --git a/include/getopt.h b/include/getopt.h
index c094972..74ca6d4 100644
--- a/include/getopt.h
+++ b/include/getopt.h
@@ -1,12 +1 @@
-#ifndef _GETOPT_H
-
-#include <features.h>		/* Get __GNU_LIBRARY__ defined now.  */
 #include <posix/getopt.h>
-
-# if defined _GETOPT_H && !defined _ISOMAC
-
-/* Now define the internal interfaces.  */
-extern void __getopt_clean_environment (char **__env);
-
-# endif /* _GETOPT_H && !_ISOMAC */
-#endif
diff --git a/manual/getopt.texi b/manual/getopt.texi
index 20e11ef..a71c373 100644
--- a/manual/getopt.texi
+++ b/manual/getopt.texi
@@ -70,15 +70,12 @@ option argument, for those options that accept arguments.
 @c leave (in case of cancellation) stderr in an inconsistent state.
 @c Various implicit, indirect uses of malloc, in uses of memstream and
 @c asprintf for error-printing, bring about the usual malloc issues.
-@c (The explicit use of malloc in a conditional situation in
-@c _getopt_initialize is never exercised in glibc.)
 @c
 @c _getopt_internal
 @c  _getopt_internal_r
 @c   gettext
 @c   _getopt_initialize
 @c    getenv
-@c    malloc if USE_NONOPTION_FLAGS, never defined in libc
 @c   open_memstream
 @c   lockfile, unlockfile, __fxprintf -> stderr
 @c   asprintf
diff --git a/posix/Makefile b/posix/Makefile
index ae17646..efcbeff 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -45,7 +45,7 @@ routines :=								      \
 	pathconf sysconf fpathconf					      \
 	glob glob64 fnmatch regex					      \
 	confstr								      \
-	getopt getopt1 getopt_init					      \
+	getopt getopt1 							      \
 	sched_setp sched_getp sched_sets sched_gets sched_yield sched_primax  \
 	sched_primin sched_rr_gi sched_getaffinity sched_setaffinity	      \
 	getaddrinfo gai_strerror wordexp				      \
diff --git a/posix/getopt.c b/posix/getopt.c
index 3d8c31c..6a28ed6 100644
--- a/posix/getopt.c
+++ b/posix/getopt.c
@@ -147,36 +147,6 @@ extern char *getenv ();
 
 #endif /* not __GNU_LIBRARY__ */
 
-#ifdef _LIBC
-/* Stored original parameters.
-   XXX This is no good solution.  We should rather copy the args so
-   that we can compare them later.  But we must not use malloc(3).  */
-extern int __libc_argc;
-extern char **__libc_argv;
-
-/* Bash 2.0 gives us an environment variable containing flags
-   indicating ARGV elements that should not be considered arguments.  */
-
-# ifdef USE_NONOPTION_FLAGS
-/* Defined in getopt_init.c  */
-extern char *__getopt_nonoption_flags;
-# endif
-
-# ifdef USE_NONOPTION_FLAGS
-#  define SWAP_FLAGS(ch1, ch2) \
-  if (d->__nonoption_flags_len > 0)					      \
-    {									      \
-      char __tmp = __getopt_nonoption_flags[ch1];			      \
-      __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2];	      \
-      __getopt_nonoption_flags[ch2] = __tmp;				      \
-    }
-# else
-#  define SWAP_FLAGS(ch1, ch2)
-# endif
-#else	/* !_LIBC */
-# define SWAP_FLAGS(ch1, ch2)
-#endif	/* _LIBC */
-
 /* Exchange two adjacent subsequences of ARGV.
    One subsequence is elements [first_nonopt,last_nonopt)
    which contains all the non-options that have been skipped so far.
@@ -199,28 +169,6 @@ exchange (char **argv, struct _getopt_data *d)
      It leaves the longer segment in the right place overall,
      but it consists of two parts that need to be swapped next.  */
 
-#if defined _LIBC && defined USE_NONOPTION_FLAGS
-  /* First make sure the handling of the `__getopt_nonoption_flags'
-     string can work normally.  Our top argument must be in the range
-     of the string.  */
-  if (d->__nonoption_flags_len > 0 && top >= d->__nonoption_flags_max_len)
-    {
-      /* We must extend the array.  The user plays games with us and
-	 presents new arguments.  */
-      char *new_str = malloc (top + 1);
-      if (new_str == NULL)
-	d->__nonoption_flags_len = d->__nonoption_flags_max_len = 0;
-      else
-	{
-	  memset (__mempcpy (new_str, __getopt_nonoption_flags,
-			     d->__nonoption_flags_max_len),
-		  '\0', top + 1 - d->__nonoption_flags_max_len);
-	  d->__nonoption_flags_max_len = top + 1;
-	  __getopt_nonoption_flags = new_str;
-	}
-    }
-#endif
-
   while (top > middle && middle > bottom)
     {
       if (top - middle > middle - bottom)
@@ -235,7 +183,6 @@ exchange (char **argv, struct _getopt_data *d)
 	      tem = argv[bottom + i];
 	      argv[bottom + i] = argv[top - (middle - bottom) + i];
 	      argv[top - (middle - bottom) + i] = tem;
-	      SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
 	    }
 	  /* Exclude the moved bottom segment from further swapping.  */
 	  top -= len;
@@ -252,7 +199,6 @@ exchange (char **argv, struct _getopt_data *d)
 	      tem = argv[bottom + i];
 	      argv[bottom + i] = argv[middle + i];
 	      argv[middle + i] = tem;
-	      SWAP_FLAGS (bottom + i, middle + i);
 	    }
 	  /* Exclude the moved top segment from further swapping.  */
 	  bottom += len;
@@ -298,36 +244,6 @@ _getopt_initialize (int argc, char *const *argv, const char *optstring,
   else
     d->__ordering = PERMUTE;
 
-#if defined _LIBC && defined USE_NONOPTION_FLAGS
-  if (!d->__posixly_correct
-      && argc == __libc_argc && argv == __libc_argv)
-    {
-      if (d->__nonoption_flags_max_len == 0)
-	{
-	  if (__getopt_nonoption_flags == NULL
-	      || __getopt_nonoption_flags[0] == '\0')
-	    d->__nonoption_flags_max_len = -1;
-	  else
-	    {
-	      const char *orig_str = __getopt_nonoption_flags;
-	      int len = d->__nonoption_flags_max_len = strlen (orig_str);
-	      if (d->__nonoption_flags_max_len < argc)
-		d->__nonoption_flags_max_len = argc;
-	      __getopt_nonoption_flags =
-		(char *) malloc (d->__nonoption_flags_max_len);
-	      if (__getopt_nonoption_flags == NULL)
-		d->__nonoption_flags_max_len = -1;
-	      else
-		memset (__mempcpy (__getopt_nonoption_flags, orig_str, len),
-			'\0', d->__nonoption_flags_max_len - len);
-	    }
-	}
-      d->__nonoption_flags_len = d->__nonoption_flags_max_len;
-    }
-  else
-    d->__nonoption_flags_len = 0;
-#endif
-
   return optstring;
 }
 
@@ -412,17 +328,8 @@ _getopt_internal_r (int argc, char *const *argv, const char *optstring,
   if (optstring[0] == ':')
     print_errors = 0;
 
-  /* Test whether ARGV[optind] points to a non-option argument.
-     Either it does not have option syntax, or there is an environment flag
-     from the shell indicating it is not an option.  The later information
-     is only used when the used in the GNU libc.  */
-#if defined _LIBC && defined USE_NONOPTION_FLAGS
-# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0' \
-		      || (d->optind < d->__nonoption_flags_len		      \
-			  && __getopt_nonoption_flags[d->optind] == '1'))
-#else
-# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0')
-#endif
+  /* Test whether ARGV[optind] points to a non-option argument.  */
+#define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0')
 
   if (d->__nextchar == NULL || *d->__nextchar == '\0')
     {
diff --git a/posix/getopt_init.c b/posix/getopt_init.c
deleted file mode 100644
index 498b301..0000000
--- a/posix/getopt_init.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/* Perform additional initialization for getopt functions in GNU libc.
-   Copyright (C) 1997-2017 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#ifdef USE_NONOPTION_FLAGS
-/* Attention: this file is *not* necessary when the GNU getopt functions
-   are used outside the GNU libc.  Some additional functionality of the
-   getopt functions in GNU libc require this additional work.  */
-
-#include <getopt.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-
-#include <_itoa.h>
-
-/* Variable to synchronize work.  */
-char *__getopt_nonoption_flags;
-
-
-/* Remove the environment variable "_<PID>_GNU_nonoption_argv_flags_" if
-   it is still available.  If the getopt functions are also used in the
-   application it does not exist anymore since it was saved for the use
-   in getopt.  */
-void
-__getopt_clean_environment (char **env)
-{
-  /* Bash 2.0 puts a special variable in the environment for each
-     command it runs, specifying which ARGV elements are the results
-     of file name wildcard expansion and therefore should not be
-     considered as options.  */
-  static const char envvar_tail[] = "_GNU_nonoption_argv_flags_=";
-  char var[50];
-  char *cp, **ep;
-  size_t len;
-
-  /* Construct the "_<PID>_GNU_nonoption_argv_flags_=" string.  We must
-     not use `sprintf'.  */
-  cp = memcpy (&var[sizeof (var) - sizeof (envvar_tail)], envvar_tail,
-	       sizeof (envvar_tail));
-  cp = _itoa_word (__getpid (), cp, 10, 0);
-  /* Note: we omit adding the leading '_' since we explicitly test for
-     it before calling strncmp.  */
-  len = (var + sizeof (var) - 1) - cp;
-
-  for (ep = env; *ep != NULL; ++ep)
-    if ((*ep)[0] == '_'
-	&& __builtin_expect (strncmp (*ep + 1, cp, len) == 0, 0))
-      {
-	/* Found it.  Store this pointer and move later ones back.  */
-	char **dp = ep;
-	__getopt_nonoption_flags = &(*ep)[len];
-	do
-	  dp[0] = dp[1];
-	while (*dp++);
-	/* Continue the loop in case the name appears again.  */
-      }
-}
-#endif	/* USE_NONOPTION_FLAGS */
diff --git a/posix/getopt_int.h b/posix/getopt_int.h
index e9eb513..71b9655 100644
--- a/posix/getopt_int.h
+++ b/posix/getopt_int.h
@@ -98,11 +98,6 @@ struct _getopt_data
 
   int __first_nonopt;
   int __last_nonopt;
-
-#if defined _LIBC && defined USE_NONOPTION_FLAGS
-  int __nonoption_flags_max_len;
-  int __nonoption_flags_len;
-# endif
 };
 
 /* The initializer is necessary to set OPTIND and OPTERR to their
diff --git a/sysdeps/mach/hurd/i386/init-first.c b/sysdeps/mach/hurd/i386/init-first.c
index 3e5555c..6a6a694 100644
--- a/sysdeps/mach/hurd/i386/init-first.c
+++ b/sysdeps/mach/hurd/i386/init-first.c
@@ -33,9 +33,6 @@
 
 extern void __mach_init (void);
 extern void __init_misc (int, char **, char **);
-#ifdef USE_NONOPTION_FLAGS
-extern void __getopt_clean_environment (char **);
-#endif
 extern void __libc_global_ctors (void);
 
 unsigned int __hurd_threadvar_max;
@@ -88,11 +85,6 @@ posixland_init (int argc, char **argv, char **envp)
 #endif
   __init_misc (argc, argv, envp);
 
-#ifdef USE_NONOPTION_FLAGS
-  /* This is a hack to make the special getopt in GNU libc working.  */
-  __getopt_clean_environment (envp);
-#endif
-
   /* Initialize ctype data.  */
   __ctype_init ();
 

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog                           |  123 ++++
 config.h.in                         |    6 -
 csu/init-first.c                    |    8 -
 include/bits/getopt_core.h          |    1 +
 include/bits/getopt_ext.h           |    1 +
 include/bits/getopt_posix.h         |    1 +
 include/getopt.h                    |   11 -
 include/libc-symbols.h              |   43 ++
 include/stdio.h                     |    2 +
 libio/stdio.h                       |   10 +-
 manual/getopt.texi                  |    3 -
 posix/Makefile                      |   10 +-
 posix/bits/getopt_core.h            |   96 +++
 posix/bits/getopt_ext.h             |   77 +++
 posix/bits/getopt_posix.h           |   51 ++
 posix/bug-getopt4.c                 |   16 +-
 posix/getopt.c                      | 1154 +++++++++++------------------------
 posix/getopt.h                      |  179 +-----
 posix/getopt1.c                     |   67 +--
 posix/getopt_init.c                 |   74 ---
 posix/getopt_int.h                  |   93 ++--
 posix/tst-getopt-cancel.c           |  284 +++++++++
 posix/tst-getopt_long1.c            |    2 +-
 posix/unistd.h                      |    3 +-
 stdio-common/fxprintf.c             |   78 ++-
 sysdeps/mach/hurd/i386/init-first.c |    8 -
 26 files changed, 1178 insertions(+), 1223 deletions(-)
 create mode 100644 include/bits/getopt_core.h
 create mode 100644 include/bits/getopt_ext.h
 create mode 100644 include/bits/getopt_posix.h
 create mode 100644 posix/bits/getopt_core.h
 create mode 100644 posix/bits/getopt_ext.h
 create mode 100644 posix/bits/getopt_posix.h
 delete mode 100644 posix/getopt_init.c
 create mode 100644 posix/tst-getopt-cancel.c


hooks/post-receive
-- 
GNU C Library master sources


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]