This is the mail archive of the
glibc-cvs@sourceware.org
mailing list for the glibc project.
GNU C Library master sources branch master updated. glibc-2.25-196-g893ba3e
- From: zack at sourceware dot org
- To: glibc-cvs at sourceware dot org
- Date: 7 Apr 2017 11:59:16 -0000
- Subject: 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