>From 89d3d7a3786f0eebc22155e833b17c6d09e4d6c8 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sun, 3 Apr 2016 16:37:13 -0700 Subject: [PATCH] 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. --- ChangeLog | 14 +++ lib/argp-ba.c | 2 +- lib/argp-fmtstream.c | 11 +- lib/argp-fmtstream.h | 62 +-------- lib/argp-fs-xinl.c | 2 +- lib/argp-help.c | 350 ++++++++++++++++++++++----------------------------- lib/argp-namefrob.h | 4 +- lib/argp-parse.c | 9 +- lib/argp-pv.c | 3 +- lib/argp-pvh.c | 3 +- lib/argp-xinl.c | 2 +- lib/argp.h | 30 +---- tests/test-argp-2.sh | 8 +- 13 files changed, 194 insertions(+), 306 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8e87922..0bdbf57 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2016-04-03 Paul Eggert + + 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 stddef: support configuring with g++ diff --git a/lib/argp-ba.c b/lib/argp-ba.c index 23a3ebe..3c474fb 100644 --- a/lib/argp-ba.c +++ b/lib/argp-ba.c @@ -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 . diff --git a/lib/argp-fmtstream.c b/lib/argp-fmtstream.c index 16a706c..e73f0b5 100644 --- a/lib/argp-fmtstream.c +++ b/lib/argp-fmtstream.c @@ -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 . @@ -39,7 +38,7 @@ #define isblank(ch) ((ch)==' ' || (ch)=='\t') #endif -#if defined _LIBC && defined USE_IN_LIBIO +#ifdef _LIBC # include # include # 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 diff --git a/lib/argp-fmtstream.h b/lib/argp-fmtstream.h index e5dfade..087d329 100644 --- a/lib/argp-fmtstream.h +++ b/lib/argp-fmtstream.h @@ -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 . @@ -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. */ + 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)) { diff --git a/lib/argp-fs-xinl.c b/lib/argp-fs-xinl.c index 77cd027..2c92b4e 100644 --- a/lib/argp-fs-xinl.c +++ b/lib/argp-fs-xinl.c @@ -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 . diff --git a/lib/argp-help.c b/lib/argp-help.c index 2afc91b..5e7d482 100644 --- a/lib/argp-help.c +++ b/lib/argp-help.c @@ -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 . @@ -26,15 +26,16 @@ #include #include +#include #include #include #include -#include #include #include #include #include -#ifdef USE_IN_LIBIO +#ifdef _LIBC +# include <../libio/libioP.h> # include #endif @@ -42,7 +43,7 @@ # include # 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, } /* 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, } /* 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"), } /* 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 diff --git a/lib/argp-namefrob.h b/lib/argp-namefrob.h index c3be636..b4db712 100644 --- a/lib/argp-namefrob.h +++ b/lib/argp-namefrob.h @@ -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 . @@ -138,7 +138,7 @@ #endif /* !_LIBC */ #ifndef __set_errno -# define __set_errno(e) (errno = (e)) +#define __set_errno(e) (errno = (e)) #endif #if defined GNULIB_ARGP_DISABLE_DIRNAME diff --git a/lib/argp-parse.c b/lib/argp-parse.c index a6fc008..01d83b8 100644 --- a/lib/argp-parse.c +++ b/lib/argp-parse.c @@ -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 . @@ -34,7 +34,7 @@ # include # 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} }; diff --git a/lib/argp-pv.c b/lib/argp-pv.c index a5c3582..53564ae 100644 --- a/lib/argp-pv.c +++ b/lib/argp-pv.c @@ -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 . diff --git a/lib/argp-pvh.c b/lib/argp-pvh.c index 2c1683c..255c508 100644 --- a/lib/argp-pvh.c +++ b/lib/argp-pvh.c @@ -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 . diff --git a/lib/argp-xinl.c b/lib/argp-xinl.c index 20c18d8..d27f959 100644 --- a/lib/argp-xinl.c +++ b/lib/argp-xinl.c @@ -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 . diff --git a/lib/argp.h b/lib/argp.h index c1fe240..a7e02b9 100644 --- a/lib/argp.h +++ b/lib/argp.h @@ -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 . @@ -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 - 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 diff --git a/tests/test-argp-2.sh b/tests/test-argp-2.sh index 406dbc0..3f8922c 100755 --- a/tests/test-argp-2.sh +++ b/tests/test-argp-2.sh @@ -35,8 +35,8 @@ func_compare() { cat > $TMP < $TMP <