]> Savannah Git Hosting - gnulib.git/commitdiff
argp: merge changes from glibc
authorPaul Eggert <eggert@cs.ucla.edu>
Sun, 3 Apr 2016 23:37:13 +0000 (16:37 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Sun, 3 Apr 2016 23:39:36 +0000 (16:39 -0700)
Among other things, this should fix problems found by a Coverity
scan and reported by Andrei Borzenkov:
http://lists.gnu.org/archive/html/bug-gnulib/2016-01/msg00015.html
http://lists.gnu.org/archive/html/bug-gnulib/2016-01/msg00016.html
* lib/argp-ba.c, lib/argp-fmtstream.c, lib/argp-fmtstream.h:
* lib/argp-fs-xinl.c, lib/argp-help.c, lib/argp-namefrob.h:
* lib/argp-parse.c, lib/argp-pv.c, lib/argp-pvh.c, lib/argp-xinl.c:
* lib/argp.h:
Merge changes from glibc.
* tests/test-argp-2.sh: Adjust to match new behavior.

13 files changed:
ChangeLog
lib/argp-ba.c
lib/argp-fmtstream.c
lib/argp-fmtstream.h
lib/argp-fs-xinl.c
lib/argp-help.c
lib/argp-namefrob.h
lib/argp-parse.c
lib/argp-pv.c
lib/argp-pvh.c
lib/argp-xinl.c
lib/argp.h
tests/test-argp-2.sh

index 8e87922904584b33e29f00f5b10b16f0928511f4..0bdbf57406534f0e2f009506da8bf3c8449e903a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2016-04-03  Paul Eggert  <eggert@cs.ucla.edu>
+
+       argp: merge changes from glibc
+       Among other things, this should fix problems found by a Coverity
+       scan and reported by Andrei Borzenkov:
+       http://lists.gnu.org/archive/html/bug-gnulib/2016-01/msg00015.html
+       http://lists.gnu.org/archive/html/bug-gnulib/2016-01/msg00016.html
+       * lib/argp-ba.c, lib/argp-fmtstream.c, lib/argp-fmtstream.h:
+       * lib/argp-fs-xinl.c, lib/argp-help.c, lib/argp-namefrob.h:
+       * lib/argp-parse.c, lib/argp-pv.c, lib/argp-pvh.c, lib/argp-xinl.c:
+       * lib/argp.h:
+       Merge changes from glibc.
+       * tests/test-argp-2.sh: Adjust to match new behavior.
+
 2016-04-01  Paul Eggert  <eggert@cs.ucla.edu>
 
        stddef: support configuring with g++
index 23a3ebe5de3e08a37adff88ec7cff0417692aea9..3c474fbcd10b33fc7d4fe950b8b6b179599fbd7e 100644 (file)
@@ -1,5 +1,5 @@
 /* Default definition for ARGP_PROGRAM_BUG_ADDRESS.
-   Copyright (C) 1996-1997, 1999, 2009-2016 Free Software Foundation, Inc.
+   Copyright (C) 1996-2016 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Miles Bader <miles@gnu.ai.mit.edu>.
 
index 16a706c942d8b4b4dafd89df1def85707721261c..e73f0b5ab512b2949cff6b339e3339475eba9fdc 100644 (file)
@@ -1,6 +1,5 @@
 /* Word-wrapping and line-truncating streams
-   Copyright (C) 1997-1999, 2001-2003, 2005, 2009-2016 Free Software
-   Foundation, Inc.
+   Copyright (C) 1997-2016 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Miles Bader <miles@gnu.ai.mit.edu>.
 
@@ -39,7 +38,7 @@
 #define isblank(ch) ((ch)==' ' || (ch)=='\t')
 #endif
 
-#if defined _LIBC && defined USE_IN_LIBIO
+#ifdef _LIBC
 # include <wchar.h>
 # include <libio/libioP.h>
 # define __vsnprintf(s, l, f, a) _IO_vsnprintf (s, l, f, a)
@@ -100,7 +99,7 @@ __argp_fmtstream_free (argp_fmtstream_t fs)
   __argp_fmtstream_update (fs);
   if (fs->p > fs->buf)
     {
-#ifdef USE_IN_LIBIO
+#ifdef _LIBC
       __fxprintf (fs->stream, "%.*s", (int) (fs->p - fs->buf), fs->buf);
 #else
       fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream);
@@ -149,7 +148,7 @@ __argp_fmtstream_update (argp_fmtstream_t fs)
               size_t i;
               for (i = 0; i < pad; i++)
                 {
-#ifdef USE_IN_LIBIO
+#ifdef _LIBC
                   if (_IO_fwide (fs->stream, 0) > 0)
                     putwc_unlocked (L' ', fs->stream);
                   else
@@ -315,7 +314,7 @@ __argp_fmtstream_update (argp_fmtstream_t fs)
               *nl++ = ' ';
           else
             for (i = 0; i < fs->wmargin; ++i)
-#ifdef USE_IN_LIBIO
+#ifdef _LIBC
               if (_IO_fwide (fs->stream, 0) > 0)
                 putwc_unlocked (L' ', fs->stream);
               else
index e5dfade3d14bd74106bbf7a1b0b8c6f90527e621..087d329fb150194c91794789d1dee415e4a45dbd 100644 (file)
@@ -1,5 +1,5 @@
 /* Word-wrapping and line-truncating streams.
-   Copyright (C) 1997, 2006-2016 Free Software Foundation, Inc.
+   Copyright (C) 1997-2016 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Miles Bader <miles@gnu.ai.mit.edu>.
 
@@ -40,8 +40,7 @@
 # define _GL_ATTRIBUTE_FORMAT(spec) /* empty */
 #endif
 
-#if    (_LIBC - 0 && !defined (USE_IN_LIBIO)) \
-    || (defined (__GNU_LIBRARY__) && defined (HAVE_LINEWRAP_H))
+#if defined (__GNU_LIBRARY__) && defined (HAVE_LINEWRAP_H)
 /* line_wrap_stream is available, so use that.  */
 #define ARGP_FMTSTREAM_USE_LINEWRAP
 #endif
@@ -87,6 +86,7 @@ typedef FILE *argp_fmtstream_t;
 
 #else /* !ARGP_FMTSTREAM_USE_LINEWRAP */
 /* Guess we have to define our own version.  */
+
 \f
 struct argp_fmtstream
 {
@@ -207,63 +207,11 @@ _GL_INLINE_HEADER_BEGIN
 #endif
 
 #ifndef ARGP_FS_EI
-# ifdef __GNUC__
-   /* GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99
-      inline semantics, unless -fgnu89-inline is used.  It defines a macro
-      __GNUC_STDC_INLINE__ to indicate this situation or a macro
-      __GNUC_GNU_INLINE__ to indicate the opposite situation.
-
-      GCC 4.2 with -std=c99 or -std=gnu99 implements the GNU C inline
-      semantics but warns, unless -fgnu89-inline is used:
-        warning: C99 inline functions are not supported; using GNU89
-        warning: to disable this warning use -fgnu89-inline or the gnu_inline function attribute
-      It defines a macro __GNUC_GNU_INLINE__ to indicate this situation.
-
-      Whereas Apple GCC 4.0.1 build 5479 without -std=c99 or -std=gnu99
-      implements the GNU C inline semantics and defines the macro
-      __GNUC_GNU_INLINE__, but it does not warn and does not support
-      __attribute__ ((__gnu_inline__)).
-
-      All in all, these are the possible combinations.  For every compiler,
-      we need to choose ARGP_FS_EI so that the corresponding table cell
-      contains an "ok".
-
-        \    ARGP_FS_EI                      inline   extern    extern
-          \                                           inline    inline
-      CC    \                                                   __attribute__
-                                                                ((gnu_inline))
-
-      gcc 4.3.0                              error    ok        ok
-      gcc 4.3.0 -std=gnu99 -fgnu89-inline    error    ok        ok
-      gcc 4.3.0 -std=gnu99                   ok       error     ok
-
-      gcc 4.2.2                              error    ok        ok
-      gcc 4.2.2 -std=gnu99 -fgnu89-inline    error    ok        ok
-      gcc 4.2.2 -std=gnu99                   error    warning   ok
-
-      gcc 4.1.2                              error    ok        warning
-      gcc 4.1.2 -std=gnu99                   error    ok        warning
-
-      Apple gcc 4.0.1                        error    ok        warning
-      Apple gcc 4.0.1 -std=gnu99             ok       error     warning
-    */
-#  if defined __GNUC_STDC_INLINE__
-#   define ARGP_FS_EI inline
-#  elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)
-#   define ARGP_FS_EI extern inline __attribute__ ((__gnu_inline__))
-#  else
-#   define ARGP_FS_EI extern inline
-#  endif
-# else
-   /* With other compilers, assume the ISO C99 meaning of 'inline', if
-      the compiler supports 'inline' at all.  */
-#  define ARGP_FS_EI inline
-# endif
+#define ARGP_FS_EI extern inline
 #endif
 
 ARGP_FS_EI size_t
-__argp_fmtstream_write (argp_fmtstream_t __fs,
-                        const char *__str, size_t __len)
+__argp_fmtstream_write (argp_fmtstream_t __fs, const char *__str, size_t __len)
 {
   if (__fs->p + __len <= __fs->end || __argp_fmtstream_ensure (__fs, __len))
     {
index 77cd02735a0ec915f7f6018583669fbb67b646cf..2c92b4e294fccf9d1d210d88fcff7b2be250e3aa 100644 (file)
@@ -1,5 +1,5 @@
 /* Real definitions for extern inline functions in argp-fmtstream.h
-   Copyright (C) 1997, 2003-2004, 2009-2016 Free Software Foundation, Inc.
+   Copyright (C) 1997-2016 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Miles Bader <miles@gnu.ai.mit.edu>.
 
index 2afc91b31da6623e6a5b91499255e0ba02024637..5e7d482889a26de1ddbe39f88a9993a2013a88a6 100644 (file)
@@ -1,5 +1,5 @@
 /* Hierarchical argument parsing help output
-   Copyright (C) 1995-2005, 2007, 2009-2016 Free Software Foundation, Inc.
+   Copyright (C) 1995-2016 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Miles Bader <miles@gnu.ai.mit.edu>.
 
 
 #include <alloca.h>
 #include <errno.h>
+#include <stdbool.h>
 #include <stddef.h>
 #include <stdlib.h>
 #include <string.h>
-#include <strings.h>
 #include <assert.h>
 #include <stdarg.h>
 #include <ctype.h>
 #include <limits.h>
-#ifdef USE_IN_LIBIO
+#ifdef _LIBC
+# include <../libio/libioP.h>
 # include <wchar.h>
 #endif
 
@@ -42,7 +43,7 @@
 # include <libintl.h>
 # undef dgettext
 # define dgettext(domain, msgid) \
-   INTUSE(__dcgettext) (domain, msgid, LC_MESSAGES)
+   __dcgettext (domain, msgid, LC_MESSAGES)
 #else
 # include "gettext.h"
 #endif
@@ -104,39 +105,38 @@ struct uparams
 static struct uparams uparams = {
   DUP_ARGS, DUP_ARGS_NOTE,
   SHORT_OPT_COL, LONG_OPT_COL, DOC_OPT_COL, OPT_DOC_COL, HEADER_COL,
-  USAGE_INDENT, RMARGIN,
-  0
+  USAGE_INDENT, RMARGIN
 };
 
 /* A particular uparam, and what the user name is.  */
 struct uparam_name
 {
-  const char *name;             /* User name.  */
-  int is_bool;                  /* Whether it's 'boolean'.  */
-  size_t uparams_offs;          /* Location of the (int) field in UPARAMS.  */
+  const char name[14];          /* User name.  */
+  bool is_bool;                 /* Whether it's 'boolean'.  */
+  unsigned char uparams_offs;   /* Location of the (int) field in UPARAMS.  */
 };
 
 /* The name-field mappings we know about.  */
 static const struct uparam_name uparam_names[] =
 {
-  { "dup-args",       1, offsetof (struct uparams, dup_args) },
-  { "dup-args-note",  1, offsetof (struct uparams, dup_args_note) },
-  { "short-opt-col",  0, offsetof (struct uparams, short_opt_col) },
-  { "long-opt-col",   0, offsetof (struct uparams, long_opt_col) },
-  { "doc-opt-col",    0, offsetof (struct uparams, doc_opt_col) },
-  { "opt-doc-col",    0, offsetof (struct uparams, opt_doc_col) },
-  { "header-col",     0, offsetof (struct uparams, header_col) },
-  { "usage-indent",   0, offsetof (struct uparams, usage_indent) },
-  { "rmargin",        0, offsetof (struct uparams, rmargin) },
-  { 0 }
+  { "dup-args",       true, offsetof (struct uparams, dup_args) },
+  { "dup-args-note",  true, offsetof (struct uparams, dup_args_note) },
+  { "short-opt-col",  false, offsetof (struct uparams, short_opt_col) },
+  { "long-opt-col",   false, offsetof (struct uparams, long_opt_col) },
+  { "doc-opt-col",    false, offsetof (struct uparams, doc_opt_col) },
+  { "opt-doc-col",    false, offsetof (struct uparams, opt_doc_col) },
+  { "header-col",     false, offsetof (struct uparams, header_col) },
+  { "usage-indent",   false, offsetof (struct uparams, usage_indent) },
+  { "rmargin",        false, offsetof (struct uparams, rmargin) }
 };
+#define nuparam_names (sizeof (uparam_names) / sizeof (uparam_names[0]))
 
 static void
 validate_uparams (const struct argp_state *state, struct uparams *upptr)
 {
   const struct uparam_name *up;
 
-  for (up = uparam_names; up->name; up++)
+  for (up = uparam_names; up < uparam_names + nuparam_names; up++)
     {
       if (up->is_bool
           || up->uparams_offs == offsetof (struct uparams, rmargin))
@@ -155,7 +155,7 @@ ARGP_HELP_FMT: %s value is less than or equal to %s"),
   uparams.valid = 1;
 }
 
-/* Read user options from the environment, and fill in UPARAMS appropriately. */
+/* Read user options from the environment, and fill in UPARAMS appropriately.  */
 static void
 fill_in_uparams (const struct argp_state *state)
 {
@@ -211,29 +211,27 @@ fill_in_uparams (const struct argp_state *state)
                   SKIPWS (arg);
                 }
 
-              for (un = uparam_names; un->name; un++)
+              for (un = uparam_names;
+                   un < uparam_names + nuparam_names;
+                   un++)
                 if (strlen (un->name) == var_len
                     && strncmp (var, un->name, var_len) == 0)
                   {
                     if (unspec && !un->is_bool)
                       __argp_failure (state, 0, 0,
-                                      dgettext (state->root_argp->argp_domain,
+                                      dgettext (state == NULL ? NULL
+                                                : state->root_argp->argp_domain,
                                                 "\
 %.*s: ARGP_HELP_FMT parameter requires a value"),
                                       (int) var_len, var);
-                    else if (val < 0)
-                      __argp_failure (state, 0, 0,
-                                      dgettext (state->root_argp->argp_domain,
-                                                "\
-%.*s: ARGP_HELP_FMT parameter must be positive"),
-                                      (int) var_len, var);
                     else
                       *(int *)((char *)&new_params + un->uparams_offs) = val;
                     break;
                   }
-              if (! un->name)
+              if (un == uparam_names + nuparam_names)
                 __argp_failure (state, 0, 0,
-                                dgettext (state->root_argp->argp_domain, "\
+                                dgettext (state == NULL ? NULL
+                                          : state->root_argp->argp_domain, "\
 %.*s: Unknown ARGP_HELP_FMT parameter"),
                                 (int) var_len, var);
 
@@ -244,7 +242,8 @@ fill_in_uparams (const struct argp_state *state)
           else if (*var)
             {
               __argp_failure (state, 0, 0,
-                              dgettext (state->root_argp->argp_domain,
+                              dgettext (state == NULL ? NULL
+                                        : state->root_argp->argp_domain,
                                         "Garbage in ARGP_HELP_FMT: %s"), var);
               break;
             }
@@ -678,9 +677,7 @@ static int
 hol_cluster_cmp (const struct hol_cluster *cl1, const struct hol_cluster *cl2)
 {
   /* If one cluster is deeper than the other, use its ancestor at the same
-     level, so that finding the common ancestor is straightforward.
-
-     clN->depth > 0 means that clN->parent != NULL (see hol_add_cluster) */
+     level, so that finding the common ancestor is straightforward.  */
   while (cl1->depth > cl2->depth)
     cl1 = cl1->parent;
   while (cl2->depth > cl1->depth)
@@ -721,20 +718,14 @@ static int
 canon_doc_option (const char **name)
 {
   int non_opt;
-
-  if (!*name)
-    non_opt = 1;
-  else
-    {
-      /* Skip initial whitespace.  */
-      while (isspace ((unsigned char) **name))
-        (*name)++;
-      /* Decide whether this looks like an option (leading '-') or not.  */
-      non_opt = (**name != '-');
-      /* Skip until part of name used for sorting.  */
-      while (**name && !isalnum ((unsigned char) **name))
-        (*name)++;
-    }
+  /* Skip initial whitespace.  */
+  while (isspace (**name))
+    (*name)++;
+  /* Decide whether this looks like an option (leading '-') or not.  */
+  non_opt = (**name != '-');
+  /* Skip until part of name used for sorting.  */
+  while (**name && !isalnum (**name))
+    (*name)++;
   return non_opt;
 }
 
@@ -749,25 +740,23 @@ hol_entry_cmp (const struct hol_entry *entry1,
   /* The group numbers by which the entries should be ordered; if either is
      in a cluster, then this is just the group within the cluster.  */
   int group1 = entry1->group, group2 = entry2->group;
-  int rc;
 
   if (entry1->cluster != entry2->cluster)
     {
       /* The entries are not within the same cluster, so we can't compare them
          directly, we have to use the appropriate clustering level too.  */
       if (! entry1->cluster)
-        /* ENTRY1 is at the "base level", not in a cluster, so we have to
+        /* ENTRY1 is at the 'base level', not in a cluster, so we have to
            compare it's group number with that of the base cluster in which
            ENTRY2 resides.  Note that if they're in the same group, the
-           clustered option always comes laster.  */
+           clustered option always comes last.  */
         return group_cmp (group1, hol_cluster_base (entry2->cluster)->group, -1);
       else if (! entry2->cluster)
         /* Likewise, but ENTRY2's not in a cluster.  */
         return group_cmp (hol_cluster_base (entry1->cluster)->group, group2, 1);
       else
         /* Both entries are in clusters, we can just compare the clusters.  */
-        return (rc = hol_cluster_cmp (entry1->cluster, entry2->cluster)) ?
-               rc : HOL_ENTRY_PTRCMP (entry1, entry2);
+        return hol_cluster_cmp (entry1->cluster, entry2->cluster);
     }
   else if (group1 == group2)
     /* The entries are both in the same cluster and group, so compare them
@@ -781,18 +770,17 @@ hol_entry_cmp (const struct hol_entry *entry1,
       const char *long2 = hol_entry_first_long (entry2);
 
       if (doc1)
-        doc1 = canon_doc_option (&long1);
+        doc1 = long1 != NULL && canon_doc_option (&long1);
       if (doc2)
-        doc2 = canon_doc_option (&long2);
+        doc2 = long2 != NULL && canon_doc_option (&long2);
 
       if (doc1 != doc2)
-        /* "documentation" options always follow normal options (or
+        /* 'documentation' options always follow normal options (or
            documentation options that *look* like normal options).  */
         return doc1 - doc2;
       else if (!short1 && !short2 && long1 && long2)
         /* Only long options.  */
-        return (rc = __strcasecmp (long1, long2)) ?
-               rc : HOL_ENTRY_PTRCMP (entry1, entry2);
+        return __strcasecmp (long1, long2);
       else
         /* Compare short/short, long/short, short/long, using the first
            character of long options.  Entries without *any* valid
@@ -800,22 +788,22 @@ hol_entry_cmp (const struct hol_entry *entry1,
            first, but as they're not displayed, it doesn't matter where
            they are.  */
         {
-          unsigned char first1 = short1 ? short1 : long1 ? *long1 : 0;
-          unsigned char first2 = short2 ? short2 : long2 ? *long2 : 0;
-          /* Use tolower, not _tolower, since only the former is
-             guaranteed to work on something already lower case.  */
+          char first1 = short1 ? short1 : long1 ? *long1 : 0;
+          char first2 = short2 ? short2 : long2 ? *long2 : 0;
+#ifdef _tolower
+          int lower_cmp = _tolower (first1) - _tolower (first2);
+#else
           int lower_cmp = tolower (first1) - tolower (first2);
+#endif
           /* Compare ignoring case, except when the options are both the
              same letter, in which case lower-case always comes first.  */
-          return lower_cmp ? lower_cmp :
-                 (rc = first2 - first1) ?
-                 rc : HOL_ENTRY_PTRCMP (entry1, entry2);
+          return lower_cmp ? lower_cmp : first2 - first1;
         }
     }
   else
     /* Within the same cluster, but not the same group, so just compare
        groups.  */
-    return group_cmp (group1, group2, HOL_ENTRY_PTRCMP (entry1, entry2));
+    return group_cmp (group1, group2, 0);
 }
 
 /* Version of hol_entry_cmp with correct signature for qsort.  */
@@ -892,8 +880,7 @@ hol_append (struct hol *hol, struct hol *more)
 
           /* Fix up the short options pointers from HOL.  */
           for (e = entries, left = hol->num_entries; left > 0; e++, left--)
-            e->short_options =
-              short_options + (e->short_options - hol->short_options);
+            e->short_options += (short_options - hol->short_options);
 
           /* Now add the short options from MORE, fixing up its entries
              too.  */
@@ -1013,7 +1000,7 @@ static const char *
 filter_doc (const char *doc, int key, const struct argp *argp,
             const struct argp_state *state)
 {
-  if (argp->help_filter)
+  if (argp && argp->help_filter)
     /* We must apply a user filter to this output.  */
     {
       void *input = __argp_input (argp, state);
@@ -1109,13 +1096,7 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state,
   int old_wm = __argp_fmtstream_wmargin (stream);
   /* PEST is a state block holding some of our variables that we'd like to
      share with helper functions.  */
-  struct pentry_state pest;
-
-  pest.entry = entry;
-  pest.stream = stream;
-  pest.hhstate = hhstate;
-  pest.first = 1;
-  pest.state = state;
+  struct pentry_state pest = { entry, stream, hhstate, 1, state };
 
   if (! odoc (real))
     for (opt = real, num = entry->num; num > 0; opt++, num--)
@@ -1137,7 +1118,9 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state,
             __argp_fmtstream_putc (stream, '-');
             __argp_fmtstream_putc (stream, *so);
             if (!have_long_opt || uparams.dup_args)
-              arg (real, " %s", "[%s]", state->root_argp->argp_domain, stream);
+              arg (real, " %s", "[%s]",
+                   state == NULL ? NULL : state->root_argp->argp_domain,
+                   stream);
             else if (real->arg)
               hhstate->suppressed_dup_arg = 1;
           }
@@ -1150,35 +1133,29 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state,
     {
       __argp_fmtstream_set_wmargin (stream, uparams.doc_opt_col);
       for (opt = real, num = entry->num; num > 0; opt++, num--)
-        if (opt->name && *opt->name && ovisible (opt))
+        if (opt->name && ovisible (opt))
           {
             comma (uparams.doc_opt_col, &pest);
             /* Calling dgettext here isn't quite right, since sorting will
                have been done on the original; but documentation options
                should be pretty rare anyway...  */
             __argp_fmtstream_puts (stream,
-                                   onotrans (opt) ?
-                                             opt->name :
-                                   dgettext (state->root_argp->argp_domain,
+                                   dgettext (state == NULL ? NULL
+                                             : state->root_argp->argp_domain,
                                              opt->name));
           }
     }
   else
     /* A real long option.  */
     {
-      int first_long_opt = 1;
-
       __argp_fmtstream_set_wmargin (stream, uparams.long_opt_col);
       for (opt = real, num = entry->num; num > 0; opt++, num--)
         if (opt->name && ovisible (opt))
           {
             comma (uparams.long_opt_col, &pest);
             __argp_fmtstream_printf (stream, "--%s", opt->name);
-            if (first_long_opt || uparams.dup_args)
-              arg (real, "=%s", "[=%s]", state->root_argp->argp_domain,
-                   stream);
-            else if (real->arg)
-              hhstate->suppressed_dup_arg = 1;
+            arg (real, "=%s", "[=%s]",
+                 state == NULL ? NULL : state->root_argp->argp_domain, stream);
           }
     }
 
@@ -1197,7 +1174,8 @@ hol_entry_help (struct hol_entry *entry, const struct argp_state *state,
     }
   else
     {
-      const char *tstr = real->doc ? dgettext (state->root_argp->argp_domain,
+      const char *tstr = real->doc ? dgettext (state == NULL ? NULL
+                                               : state->root_argp->argp_domain,
                                                real->doc) : 0;
       const char *fstr = filter_doc (tstr, real->key, entry->argp, state);
       if (fstr && *fstr)
@@ -1245,7 +1223,8 @@ hol_help (struct hol *hol, const struct argp_state *state,
 
   if (hhstate.suppressed_dup_arg && uparams.dup_args_note)
     {
-      const char *tstr = dgettext (state->root_argp->argp_domain, "\
+      const char *tstr = dgettext (state == NULL ? NULL
+                                   : state->root_argp->argp_domain, "\
 Mandatory or optional arguments to long options are also mandatory or \
 optional for any corresponding short options.");
       const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_DUP_ARGS_NOTE,
@@ -1323,7 +1302,7 @@ usage_long_opt (const struct argp_option *opt,
   if (! arg)
     arg = real->arg;
 
-  if (! (flags & OPTION_NO_USAGE) && !odoc (opt))
+  if (! (flags & OPTION_NO_USAGE))
     {
       if (arg)
         {
@@ -1440,7 +1419,7 @@ argp_args_usage (const struct argp *argp, const struct argp_state *state,
       const char *cp = fdoc;
       nl = __strchrnul (cp, '\n');
       if (*nl != '\0')
-        /* This is a "multi-level" args doc; advance to the correct position
+        /* This is a 'multi-level' args doc; advance to the correct position
            as determined by our state in LEVELS, and update LEVELS.  */
         {
           int i;
@@ -1481,7 +1460,7 @@ argp_args_usage (const struct argp *argp, const struct argp_state *state,
 }
 \f
 /* Print the documentation for ARGP to STREAM; if POST is false, then
-   everything preceding a '\v' character in the documentation strings (or
+   everything preceeding a '\v' character in the documentation strings (or
    the whole string, for those with none) is printed, otherwise, everything
    following the '\v' character (nothing for strings without).  Each separate
    bit of documentation is separated a blank line, and if PRE_BLANK is true,
@@ -1494,55 +1473,46 @@ argp_doc (const struct argp *argp, const struct argp_state *state,
 {
   const char *text;
   const char *inp_text;
-  size_t inp_text_len = 0;
-  const char *trans_text;
   void *input = 0;
   int anything = 0;
+  size_t inp_text_limit = 0;
+  const char *doc = dgettext (argp->argp_domain, argp->doc);
   const struct argp_child *child = argp->children;
 
-  if (argp->doc)
+  if (doc)
     {
-      char *vt = strchr (argp->doc, '\v');
-      if (vt)
-        {
-          if (post)
-            {
-              inp_text = vt + 1;
-              if (! *inp_text)
-                inp_text = 0;
-            }
-          else
-            {
-              inp_text_len = vt - argp->doc;
-              inp_text = inp_text_len ? __strndup (argp->doc, inp_text_len) : 0;
-            }
-        }
-      else
-        inp_text = post ? 0 : argp->doc;
-      trans_text = inp_text ? dgettext (argp->argp_domain, inp_text) : NULL;
+      char *vt = strchr (doc, '\v');
+      inp_text = post ? (vt ? vt + 1 : 0) : doc;
+      inp_text_limit = (!post && vt) ? (vt - doc) : 0;
     }
   else
-    trans_text = inp_text = 0;
+    inp_text = 0;
 
   if (argp->help_filter)
     /* We have to filter the doc strings.  */
     {
+      if (inp_text_limit)
+        /* Copy INP_TEXT so that it's nul-terminated.  */
+        inp_text = __strndup (inp_text, inp_text_limit);
       input = __argp_input (argp, state);
       text =
         (*argp->help_filter) (post
                               ? ARGP_KEY_HELP_POST_DOC
                               : ARGP_KEY_HELP_PRE_DOC,
-                              trans_text, input);
+                              inp_text, input);
     }
   else
-    text = (const char *) trans_text;
+    text = (const char *) inp_text;
 
   if (text)
     {
       if (pre_blank)
         __argp_fmtstream_putc (stream, '\n');
 
-      __argp_fmtstream_puts (stream, text);
+      if (text == inp_text && inp_text_limit)
+        __argp_fmtstream_write (stream, inp_text, inp_text_limit);
+      else
+        __argp_fmtstream_puts (stream, text);
 
       if (__argp_fmtstream_point (stream) > __argp_fmtstream_lmargin (stream))
         __argp_fmtstream_putc (stream, '\n');
@@ -1550,14 +1520,13 @@ argp_doc (const struct argp *argp, const struct argp_state *state,
       anything = 1;
     }
 
-  if (text && text != trans_text)
+  if (text && text != inp_text)
     free ((char *) text);       /* Free TEXT returned from the help filter.  */
-
-  if (inp_text && inp_text_len)
+  if (inp_text && inp_text_limit && argp->help_filter)
     free ((char *) inp_text);   /* We copied INP_TEXT, so free it now.  */
 
   if (post && argp->help_filter)
-    /* Now see if we have to output an ARGP_KEY_HELP_EXTRA text.  */
+    /* Now see if we have to output a ARGP_KEY_HELP_EXTRA text.  */
     {
       text = (*argp->help_filter) (ARGP_KEY_HELP_EXTRA, 0, input);
       if (text)
@@ -1584,8 +1553,8 @@ argp_doc (const struct argp *argp, const struct argp_state *state,
 }
 \f
 /* Output a usage message for ARGP to STREAM.  If called from
-   argp_state_help, STATE is the relevant parsing state.  FLAGS are from the
-   set ARGP_HELP_*.  NAME is what to use wherever a "program name" is
+   argp_state_help, STATE is the relevent parsing state.  FLAGS are from the
+   set ARGP_HELP_*.  NAME is what to use wherever a 'program name' is
    needed. */
 static void
 _help (const struct argp *argp, const struct argp_state *state, FILE *stream,
@@ -1729,14 +1698,11 @@ Try '%s --help' or '%s --usage' for more information.\n"),
 }
 \f
 /* Output a usage message for ARGP to STREAM.  FLAGS are from the set
-   ARGP_HELP_*.  NAME is what to use wherever a "program name" is needed. */
+   ARGP_HELP_*.  NAME is what to use wherever a 'program name' is needed. */
 void __argp_help (const struct argp *argp, FILE *stream,
                   unsigned flags, char *name)
 {
-  struct argp_state state;
-  memset (&state, 0, sizeof state);
-  state.root_argp = argp;
-  _help (argp, &state, stream, flags, name);
+  _help (argp, 0, stream, flags, name);
 }
 #ifdef weak_alias
 weak_alias (__argp_help, argp_help)
@@ -1747,7 +1713,8 @@ char *
 __argp_short_program_name (void)
 {
 # if HAVE_DECL_PROGRAM_INVOCATION_NAME
-  return __argp_base_name (program_invocation_name);
+  char *name = strrchr (program_invocation_name, '/');
+  return name ? name + 1 : program_invocation_name;
 # else
   /* FIXME: What now? Miles suggests that it is better to use NULL,
      but currently the value is passed on directly to fputs_unlocked,
@@ -1806,33 +1773,26 @@ __argp_error (const struct argp_state *state, const char *fmt, ...)
 
           va_start (ap, fmt);
 
-#ifdef USE_IN_LIBIO
-          if (_IO_fwide (stream, 0) > 0)
-            {
-              char *buf;
+#ifdef _LIBC
+          char *buf;
 
-              if (__asprintf (&buf, fmt, ap) < 0)
-                buf = NULL;
+          if (_IO_vasprintf (&buf, fmt, ap) < 0)
+            buf = NULL;
 
-              __fwprintf (stream, L"%s: %s\n",
-                          state ? state->name : __argp_short_program_name (),
-                          buf);
+          __fxprintf (stream, "%s: %s\n",
+                      state ? state->name : __argp_short_program_name (), buf);
 
-              free (buf);
-            }
-          else
-#endif
-            {
-              fputs_unlocked (state
-                              ? state->name : __argp_short_program_name (),
-                              stream);
-              putc_unlocked (':', stream);
-              putc_unlocked (' ', stream);
+          free (buf);
+#else
+          fputs_unlocked (state ? state->name : __argp_short_program_name (),
+                          stream);
+          putc_unlocked (':', stream);
+          putc_unlocked (' ', stream);
 
-              vfprintf (stream, fmt, ap);
+          vfprintf (stream, fmt, ap);
 
-              putc_unlocked ('\n', stream);
-            }
+          putc_unlocked ('\n', stream);
+#endif
 
           __argp_state_help (state, stream, ARGP_HELP_STD_ERR);
 
@@ -1870,41 +1830,34 @@ __argp_failure (const struct argp_state *state, int status, int errnum,
           __flockfile (stream);
 #endif
 
-#ifdef USE_IN_LIBIO
-          if (_IO_fwide (stream, 0) > 0)
-            __fwprintf (stream, L"%s",
-                        state ? state->name : __argp_short_program_name ());
-          else
+#ifdef _LIBC
+          __fxprintf (stream, "%s",
+                      state ? state->name : __argp_short_program_name ());
+#else
+          fputs_unlocked (state ? state->name : __argp_short_program_name (),
+                          stream);
 #endif
-            fputs_unlocked (state
-                            ? state->name : __argp_short_program_name (),
-                            stream);
 
           if (fmt)
             {
               va_list ap;
 
               va_start (ap, fmt);
-#ifdef USE_IN_LIBIO
-              if (_IO_fwide (stream, 0) > 0)
-                {
-                  char *buf;
+#ifdef _LIBC
+              char *buf;
 
-                  if (__asprintf (&buf, fmt, ap) < 0)
-                    buf = NULL;
+              if (_IO_vasprintf (&buf, fmt, ap) < 0)
+                buf = NULL;
 
-                  __fwprintf (stream, L": %s", buf);
+              __fxprintf (stream, ": %s", buf);
 
-                  free (buf);
-                }
-              else
-#endif
-                {
-                  putc_unlocked (':', stream);
-                  putc_unlocked (' ', stream);
+              free (buf);
+#else
+              putc_unlocked (':', stream);
+              putc_unlocked (' ', stream);
 
-                  vfprintf (stream, fmt, ap);
-                }
+              vfprintf (stream, fmt, ap);
+#endif
 
               va_end (ap);
             }
@@ -1913,32 +1866,29 @@ __argp_failure (const struct argp_state *state, int status, int errnum,
             {
               char buf[200];
 
-#ifdef USE_IN_LIBIO
-              if (_IO_fwide (stream, 0) > 0)
-                __fwprintf (stream, L": %s",
-                            __strerror_r (errnum, buf, sizeof (buf)));
-              else
-#endif
-                {
-                  char const *s = NULL;
-                  putc_unlocked (':', stream);
-                  putc_unlocked (' ', stream);
-#if _LIBC || (HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P && !defined strerror_r)
-                  s = __strerror_r (errnum, buf, sizeof buf);
-#elif HAVE_DECL_STRERROR_R
-                  if (__strerror_r (errnum, buf, sizeof buf) == 0)
-                    s = buf;
-#endif
-#if !_LIBC
-                  if (! s && ! (s = strerror (errnum)))
-                    s = dgettext (state->root_argp->argp_domain,
-                                  "Unknown system error");
+#ifdef _LIBC
+              __fxprintf (stream, ": %s",
+                          __strerror_r (errnum, buf, sizeof (buf)));
+#else
+              char const *s = NULL;
+              putc_unlocked (':', stream);
+              putc_unlocked (' ', stream);
+# if HAVE_DECL_STRERROR_R
+#  if STRERROR_R_CHAR_P
+              s = __strerror_r (errnum, buf, sizeof buf);
+#  else
+              if (__strerror_r (errnum, buf, sizeof buf) == 0)
+                s = buf;
+#  endif
+# endif
+              if (! s && ! (s = strerror (errnum)))
+                s = dgettext (state->root_argp->argp_domain,
+                              "Unknown system error");
+              fputs_unlocked (s, stream);
 #endif
-                  fputs (s, stream);
-                }
             }
 
-#ifdef USE_IN_LIBIO
+#if _LIBC
           if (_IO_fwide (stream, 0) > 0)
             putwc_unlocked (L'\n', stream);
           else
index c3be636bd5565e0d0993166837e6d7fcd8bd9aaf..b4db71280e67ae0fe021d555e23e53b81fe16c08 100644 (file)
@@ -1,5 +1,5 @@
 /* Name frobnication for compiling argp outside of glibc
-   Copyright (C) 1997, 2003, 2007, 2009-2016 Free Software Foundation, Inc.
+   Copyright (C) 1997-2016 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Miles Bader <miles@gnu.ai.mit.edu>.
 
 #endif /* !_LIBC */
 
 #ifndef __set_errno
-# define __set_errno(e) (errno = (e))
+#define __set_errno(e) (errno = (e))
 #endif
 
 #if defined GNULIB_ARGP_DISABLE_DIRNAME
index a6fc0080a9dc2ab3a8510f84491b40d4bf5333d0..01d83b8ef71887b01a26790ca94c65083e4d6e92 100644 (file)
@@ -1,5 +1,5 @@
 /* Hierarchical argument parsing, layered over getopt
-   Copyright (C) 1995-2000, 2002-2004, 2009-2016 Free Software Foundation, Inc.
+   Copyright (C) 1995-2016 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Miles Bader <miles@gnu.ai.mit.edu>.
 
@@ -34,7 +34,7 @@
 # include <libintl.h>
 # undef dgettext
 # define dgettext(domain, msgid) \
-   INTUSE(__dcgettext) (domain, msgid, LC_MESSAGES)
+   __dcgettext (domain, msgid, LC_MESSAGES)
 #else
 # include "gettext.h"
 #endif
@@ -80,9 +80,10 @@ static const struct argp_option argp_default_options[] =
 {
   {"help",        '?',          0, 0,  N_("give this help list"), -1},
   {"usage",       OPT_USAGE,    0, 0,  N_("give a short usage message"), 0},
-  {"program-name",OPT_PROGNAME,N_("NAME"), OPTION_HIDDEN, N_("set the program name"), 0},
+  {"program-name",OPT_PROGNAME, N_("NAME"), OPTION_HIDDEN,
+   N_("set the program name"), 0},
   {"HANG",        OPT_HANG,    N_("SECS"), OPTION_ARG_OPTIONAL | OPTION_HIDDEN,
-     N_("hang for SECS seconds (default 3600)"), 0},
+   N_("hang for SECS seconds (default 3600)"), 0},
   {NULL, 0, 0, 0, NULL, 0}
 };
 
index a5c3582d8f050298bb2ea215fd0bb8de2baf14c7..53564ae362b0727e694d5780b86b82db822b8e7b 100644 (file)
@@ -1,6 +1,5 @@
 /* Default definition for ARGP_PROGRAM_VERSION.
-   Copyright (C) 1996-1997, 1999, 2006, 2009-2016 Free Software Foundation,
-   Inc.
+   Copyright (C) 1996-2016 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Miles Bader <miles@gnu.ai.mit.edu>.
 
index 2c1683ca1629d2a4f6eedbac67d4d657342b4d61..255c50823f0ed8ae99734379db439708c20a789a 100644 (file)
@@ -1,6 +1,5 @@
 /* Default definition for ARGP_PROGRAM_VERSION_HOOK.
-   Copyright (C) 1996-1997, 1999, 2004, 2009-2016 Free Software Foundation,
-   Inc.
+   Copyright (C) 1996-2016 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Miles Bader <miles@gnu.ai.mit.edu>.
 
index 20c18d869998ab3274bdb1ad08b9eeb3ea06126e..d27f959a33cfe3e3127dfc94d03c41f7709fe6ee 100644 (file)
@@ -1,5 +1,5 @@
 /* Real definitions for extern inline functions in argp.h
-   Copyright (C) 1997-1998, 2004, 2009-2016 Free Software Foundation, Inc.
+   Copyright (C) 1997-2016 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Miles Bader <miles@gnu.ai.mit.edu>.
 
index c1fe240531ac959a3fca18c2097a96621af59b90..a7e02b96573569dcca561f5914d14eb68154923d 100644 (file)
@@ -1,5 +1,5 @@
 /* Hierarchical argument parsing, layered over getopt.
-   Copyright (C) 1995-1999, 2003-2016 Free Software Foundation, Inc.
+   Copyright (C) 1995-2016 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Written by Miles Bader <miles@gnu.ai.mit.edu>.
 
@@ -146,15 +146,14 @@ struct argp_option
 /* Valid only in conjunction with OPTION_DOC. This option disables translation
    of option name. */
 #define OPTION_NO_TRANS         0x20
-
 \f
 struct argp;                    /* fwd declare this type */
 struct argp_state;              /* " */
 struct argp_child;              /* " */
 
 /* The type of a pointer to an argp parsing function.  */
-typedef error_t (*argp_parser_t) (int key, char *arg,
-                                  struct argp_state *state);
+typedef error_t (*argp_parser_t) (int __key, char *__arg,
+                                  struct argp_state *__state);
 
 /* What to return for unrecognized keys.  For special ARGP_KEY_ keys, such
    returns will simply be ignored.  For user keys, this error will be turned
@@ -589,28 +588,7 @@ _GL_INLINE_HEADER_BEGIN
 # endif
 
 # ifndef ARGP_EI
-#  ifdef __GNUC__
-    /* GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99
-       inline semantics, unless -fgnu89-inline is used.  It defines a macro
-       __GNUC_STDC_INLINE__ to indicate this situation or a macro
-       __GNUC_GNU_INLINE__ to indicate the opposite situation.
-       GCC 4.2 with -std=c99 or -std=gnu99 implements the GNU C inline
-       semantics but warns, unless -fgnu89-inline is used:
-         warning: C99 inline functions are not supported; using GNU89
-         warning: to disable this warning use -fgnu89-inline or the gnu_inline function attribute
-       It defines a macro __GNUC_GNU_INLINE__ to indicate this situation.  */
-#   if defined __GNUC_STDC_INLINE__
-#    define ARGP_EI __inline__
-#   elif defined __GNUC_GNU_INLINE__
-#    define ARGP_EI extern __inline__ __attribute__ ((__gnu_inline__))
-#   else
-#    define ARGP_EI extern __inline__
-#   endif
-#  else
-    /* With other compilers, assume the ISO C99 meaning of 'inline', if
-       the compiler supports 'inline' at all.  */
-#   define ARGP_EI inline
-#  endif
+#  define ARGP_EI __extern_inline
 # endif
 
 ARGP_EI void
index 406dbc019afc8a7250ff86f483e00787a1757034..3f8922c07d2c034ecf4d0a80f983cdd862d2cfba 100755 (executable)
@@ -35,8 +35,8 @@ func_compare() {
 cat > $TMP <<EOT
 Usage: test-argp [-tvCSOlp?V] [-f FILE] [-r FILE] [-o[ARG]] [--test]
             [--file=FILE] [--input=FILE] [--read=FILE] [--verbose] [--cantiga]
-            [--sonet] [--option] [--optional[=ARG]] [--limerick] [--poem]
-            [--help] [--usage] [--version] ARGS...
+            [--sonet] [--option] [--optional[=ARG]] [--many] [--one] [--two]
+            [--limerick] [--poem] [--help] [--usage] [--version] ARGS...
 EOT
 
 ./test-argp$EXEEXT --usage | func_compare || ERR=1
@@ -47,8 +47,8 @@ EOT
 cat > $TMP <<EOT
 Usage: test-argp [-tvCSOlp?V] [-f FILE] [-r FILE] [-o[ARG]] [--test]
 [--file=FILE] [--input=FILE] [--read=FILE] [--verbose] [--cantiga] [--sonet]
-[--option] [--optional[=ARG]] [--limerick] [--poem] [--help] [--usage]
-[--version] ARGS...
+[--option] [--optional[=ARG]] [--many] [--one] [--two] [--limerick] [--poem]
+[--help] [--usage] [--version] ARGS...
 EOT
 
 ARGP_HELP_FMT='usage-indent=0' ./test-argp$EXEEXT --usage | func_compare || ERR=1