(root)/
tar-1.35/
gnu/
argp-help.c
       1  /* Hierarchical argument parsing help output
       2     Copyright (C) 1995-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4     Written by Miles Bader <miles@gnu.ai.mit.edu>.
       5  
       6     This file is free software: you can redistribute it and/or modify
       7     it under the terms of the GNU Lesser General Public License as
       8     published by the Free Software Foundation, either version 3 of the
       9     License, or (at your option) any later version.
      10  
      11     This file is distributed in the hope that it will be useful,
      12     but WITHOUT ANY WARRANTY; without even the implied warranty of
      13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14     GNU Lesser General Public License for more details.
      15  
      16     You should have received a copy of the GNU Lesser General Public License
      17     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      18  
      19  #ifndef _GNU_SOURCE
      20  # define _GNU_SOURCE    1
      21  #endif
      22  
      23  #ifdef HAVE_CONFIG_H
      24  # include <config.h>
      25  #endif
      26  
      27  #include <alloca.h>
      28  #include <errno.h>
      29  #include <stddef.h>
      30  #include <stdlib.h>
      31  #include <string.h>
      32  #include <strings.h>
      33  #include <assert.h>
      34  #include <stdarg.h>
      35  #include <ctype.h>
      36  #include <limits.h>
      37  #ifdef _LIBC
      38  # include <../libio/libioP.h>
      39  # include <wchar.h>
      40  #endif
      41  
      42  #ifdef _LIBC
      43  # include <libintl.h>
      44  # undef dgettext
      45  # define dgettext(domain, msgid) \
      46     __dcgettext (domain, msgid, LC_MESSAGES)
      47  #else
      48  # include "gettext.h"
      49  #endif
      50  
      51  #include "argp.h"
      52  #include "argp-fmtstream.h"
      53  #include "argp-namefrob.h"
      54  
      55  #ifndef SIZE_MAX
      56  # define SIZE_MAX ((size_t) -1)
      57  #endif
      58  
      59  /* ========================================================================== */
      60  
      61  /* User-selectable (using an environment variable) formatting parameters.
      62  
      63     These may be specified in an environment variable called 'ARGP_HELP_FMT',
      64     with a contents like:  VAR1=VAL1,VAR2=VAL2,BOOLVAR2,no-BOOLVAR2
      65     Where VALn must be a positive integer.  The list of variables is in the
      66     UPARAM_NAMES vector, below.  */
      67  
      68  /* Default parameters.  */
      69  #define DUP_ARGS      0         /* True if option argument can be duplicated. */
      70  #define DUP_ARGS_NOTE 1         /* True to print a note about duplicate args. */
      71  #define SHORT_OPT_COL 2         /* column in which short options start */
      72  #define LONG_OPT_COL  6         /* column in which long options start */
      73  #define DOC_OPT_COL   2         /* column in which doc options start */
      74  #define OPT_DOC_COL  29         /* column in which option text starts */
      75  #define HEADER_COL    1         /* column in which group headers are printed */
      76  #define USAGE_INDENT 12         /* indentation of wrapped usage lines */
      77  #define RMARGIN      79         /* right margin used for wrapping */
      78  
      79  /* User-selectable (using an environment variable) formatting parameters.
      80     They must all be of type 'int' for the parsing code to work.  */
      81  struct uparams
      82  {
      83    /* If true, arguments for an option are shown with both short and long
      84       options, even when a given option has both, e.g. '-x ARG, --longx=ARG'.
      85       If false, then if an option has both, the argument is only shown with
      86       the long one, e.g., '-x, --longx=ARG', and a message indicating that
      87       this really means both is printed below the options.  */
      88    int dup_args;
      89  
      90    /* This is true if when DUP_ARGS is false, and some duplicate arguments have
      91       been suppressed, an explanatory message should be printed.  */
      92    int dup_args_note;
      93  
      94    /* Various output columns.  */
      95    int short_opt_col;      /* column in which short options start */
      96    int long_opt_col;       /* column in which long options start */
      97    int doc_opt_col;        /* column in which doc options start */
      98    int opt_doc_col;        /* column in which option text starts */
      99    int header_col;         /* column in which group headers are printed */
     100    int usage_indent;       /* indentation of wrapped usage lines */
     101    int rmargin;            /* right margin used for wrapping */
     102  
     103    int valid;              /* True when the values in here are valid.  */
     104  };
     105  
     106  /* This is a global variable, as user options are only ever read once.  */
     107  static struct uparams uparams = {
     108    DUP_ARGS, DUP_ARGS_NOTE,
     109    SHORT_OPT_COL, LONG_OPT_COL, DOC_OPT_COL, OPT_DOC_COL, HEADER_COL,
     110    USAGE_INDENT, RMARGIN
     111  };
     112  
     113  /* A particular uparam, and what the user name is.  */
     114  struct uparam_name
     115  {
     116    const char name[14];          /* User name.  */
     117    bool is_bool;                 /* Whether it's 'boolean'.  */
     118    unsigned char uparams_offs;   /* Location of the (int) field in UPARAMS.  */
     119  };
     120  
     121  /* The name-field mappings we know about.  */
     122  static const struct uparam_name uparam_names[] =
     123  {
     124    { "dup-args",       true, offsetof (struct uparams, dup_args) },
     125    { "dup-args-note",  true, offsetof (struct uparams, dup_args_note) },
     126    { "short-opt-col",  false, offsetof (struct uparams, short_opt_col) },
     127    { "long-opt-col",   false, offsetof (struct uparams, long_opt_col) },
     128    { "doc-opt-col",    false, offsetof (struct uparams, doc_opt_col) },
     129    { "opt-doc-col",    false, offsetof (struct uparams, opt_doc_col) },
     130    { "header-col",     false, offsetof (struct uparams, header_col) },
     131    { "usage-indent",   false, offsetof (struct uparams, usage_indent) },
     132    { "rmargin",        false, offsetof (struct uparams, rmargin) }
     133  };
     134  #define nuparam_names (sizeof (uparam_names) / sizeof (uparam_names[0]))
     135  
     136  static void
     137  validate_uparams (const struct argp_state *state, struct uparams *upptr)
     138  {
     139    const struct uparam_name *up;
     140  
     141    for (up = uparam_names; up < uparam_names + nuparam_names; up++)
     142      {
     143        if (up->is_bool
     144            || up->uparams_offs == offsetof (struct uparams, rmargin))
     145          continue;
     146        if (*(int *)((char *)upptr + up->uparams_offs) >= upptr->rmargin)
     147          {
     148            __argp_failure (state, 0, 0,
     149                            dgettext (state == NULL ? NULL
     150                                      : state->root_argp->argp_domain,
     151                                      "\
     152  ARGP_HELP_FMT: %s value is less than or equal to %s"),
     153                            "rmargin", up->name);
     154            return;
     155          }
     156      }
     157    uparams = *upptr;
     158    uparams.valid = 1;
     159  }
     160  
     161  /* Read user options from the environment, and fill in UPARAMS appropriately.  */
     162  static void
     163  fill_in_uparams (const struct argp_state *state)
     164  {
     165    const char *var = getenv ("ARGP_HELP_FMT");
     166    struct uparams new_params = uparams;
     167  
     168  #define SKIPWS(p) do { while (isspace ((unsigned char) *p)) p++; } while (0);
     169  
     170    if (var)
     171      {
     172        /* Parse var. */
     173        while (*var)
     174          {
     175            SKIPWS (var);
     176  
     177            if (isalpha ((unsigned char) *var))
     178              {
     179                size_t var_len;
     180                const struct uparam_name *un;
     181                int unspec = 0, val = 0;
     182                const char *arg = var;
     183  
     184                while (isalnum ((unsigned char) *arg) || *arg == '-' || *arg == '_')
     185                  arg++;
     186                var_len = arg - var;
     187  
     188                SKIPWS (arg);
     189  
     190                if (*arg == '\0' || *arg == ',')
     191                  unspec = 1;
     192                else if (*arg == '=')
     193                  {
     194                    arg++;
     195                    SKIPWS (arg);
     196                  }
     197  
     198                if (unspec)
     199                  {
     200                    if (var[0] == 'n' && var[1] == 'o' && var[2] == '-')
     201                      {
     202                        val = 0;
     203                        var += 3;
     204                        var_len -= 3;
     205                      }
     206                    else
     207                      val = 1;
     208                  }
     209                else if (isdigit ((unsigned char) *arg))
     210                  {
     211                    val = atoi (arg);
     212                    while (isdigit ((unsigned char) *arg))
     213                      arg++;
     214                    SKIPWS (arg);
     215                  }
     216  
     217                for (un = uparam_names;
     218                     un < uparam_names + nuparam_names;
     219                     un++)
     220                  if (strlen (un->name) == var_len
     221                      && strncmp (var, un->name, var_len) == 0)
     222                    {
     223                      if (unspec && !un->is_bool)
     224                        __argp_failure (state, 0, 0,
     225                                        dgettext (state == NULL ? NULL
     226                                                  : state->root_argp->argp_domain,
     227                                                  "\
     228  %.*s: ARGP_HELP_FMT parameter requires a value"),
     229                                        (int) var_len, var);
     230                      else
     231                        *(int *)((char *)&new_params + un->uparams_offs) = val;
     232                      break;
     233                    }
     234                if (un == uparam_names + nuparam_names)
     235                  __argp_failure (state, 0, 0,
     236                                  dgettext (state == NULL ? NULL
     237                                            : state->root_argp->argp_domain, "\
     238  %.*s: Unknown ARGP_HELP_FMT parameter"),
     239                                  (int) var_len, var);
     240  
     241                var = arg;
     242                if (*var == ',')
     243                  var++;
     244              }
     245            else if (*var)
     246              {
     247                __argp_failure (state, 0, 0,
     248                                dgettext (state == NULL ? NULL
     249                                          : state->root_argp->argp_domain,
     250                                          "Garbage in ARGP_HELP_FMT: %s"), var);
     251                break;
     252              }
     253          }
     254        validate_uparams (state, &new_params);
     255      }
     256  }
     257  
     258  /* ========================================================================== */
     259  
     260  /* Returns true if OPT hasn't been marked invisible.  Visibility only affects
     261     whether OPT is displayed or used in sorting, not option shadowing.  */
     262  #define ovisible(opt) (! ((opt)->flags & OPTION_HIDDEN))
     263  
     264  /* Returns true if OPT is an alias for an earlier option.  */
     265  #define oalias(opt) ((opt)->flags & OPTION_ALIAS)
     266  
     267  /* Returns true if OPT is a documentation-only entry.  */
     268  #define odoc(opt) ((opt)->flags & OPTION_DOC)
     269  
     270  /* Returns true if OPT should not be translated */
     271  #define onotrans(opt) ((opt)->flags & OPTION_NO_TRANS)
     272  
     273  /* Returns true if OPT is the end-of-list marker for a list of options.  */
     274  #define oend(opt) __option_is_end (opt)
     275  
     276  /* Returns true if OPT has a short option.  */
     277  #define oshort(opt) __option_is_short (opt)
     278  
     279  /*
     280     The help format for a particular option is like:
     281  
     282       -xARG, -yARG, --long1=ARG, --long2=ARG        Documentation...
     283  
     284     Where ARG will be omitted if there's no argument, for this option, or
     285     will be surrounded by "[" and "]" appropriately if the argument is
     286     optional.  The documentation string is word-wrapped appropriately, and if
     287     the list of options is long enough, it will be started on a separate line.
     288     If there are no short options for a given option, the first long option is
     289     indented slightly in a way that's supposed to make most long options appear
     290     to be in a separate column.
     291  
     292     For example, the following output (from ps):
     293  
     294       -p PID, --pid=PID          List the process PID
     295           --pgrp=PGRP            List processes in the process group PGRP
     296       -P, -x, --no-parent        Include processes without parents
     297       -Q, --all-fields           Don't elide unusable fields (normally if there's
     298                                  some reason ps can't print a field for any
     299                                  process, it's removed from the output entirely)
     300       -r, --reverse, --gratuitously-long-reverse-option
     301                                  Reverse the order of any sort
     302           --session[=SID]        Add the processes from the session SID (which
     303                                  defaults to the sid of the current process)
     304  
     305      Here are some more options:
     306       -f ZOT, --foonly=ZOT       Glork a foonly
     307       -z, --zaza                 Snit a zar
     308  
     309       -?, --help                 Give this help list
     310           --usage                Give a short usage message
     311       -V, --version              Print program version
     312  
     313     The struct argp_option array for the above could look like:
     314  
     315     {
     316       {"pid",       'p',      "PID",  0, "List the process PID"},
     317       {"pgrp",      OPT_PGRP, "PGRP", 0, "List processes in the process group PGRP"},
     318       {"no-parent", 'P',       0,     0, "Include processes without parents"},
     319       {0,           'x',       0,     OPTION_ALIAS},
     320       {"all-fields",'Q',       0,     0, "Don't elide unusable fields (normally"
     321                                          " if there's some reason ps can't"
     322                                          " print a field for any process, it's"
     323                                          " removed from the output entirely)" },
     324       {"reverse",   'r',       0,     0, "Reverse the order of any sort"},
     325       {"gratuitously-long-reverse-option", 0, 0, OPTION_ALIAS},
     326       {"session",   OPT_SESS,  "SID", OPTION_ARG_OPTIONAL,
     327                                          "Add the processes from the session"
     328                                          " SID (which defaults to the sid of"
     329                                          " the current process)" },
     330  
     331       {0,0,0,0, "Here are some more options:"},
     332       {"foonly", 'f', "ZOT", 0, "Glork a foonly"},
     333       {"zaza", 'z', 0, 0, "Snit a zar"},
     334  
     335       {0}
     336     }
     337  
     338     Note that the last three options are automatically supplied by argp_parse,
     339     unless you tell it not to with ARGP_NO_HELP.
     340  
     341  */
     342  
     343  /* Returns true if CH occurs between BEG and END.  */
     344  static int
     345  find_char (char ch, char *beg, char *end)
     346  {
     347    while (beg < end)
     348      if (*beg == ch)
     349        return 1;
     350      else
     351        beg++;
     352    return 0;
     353  }
     354  
     355  /* -------------------------------------------------------------------------- */
     356  /* Data structure: HOL = Help Option List                                     */
     357  
     358  struct hol_cluster;             /* fwd decl */
     359  
     360  struct hol_entry
     361  {
     362    /* First option.  */
     363    const struct argp_option *opt;
     364    /* Number of options (including aliases).  */
     365    unsigned num;
     366  
     367    /* A pointers into the HOL's short_options field, to the first short option
     368       letter for this entry.  The order of the characters following this point
     369       corresponds to the order of options pointed to by OPT, and there are at
     370       most NUM.  A short option recorded in an option following OPT is only
     371       valid if it occurs in the right place in SHORT_OPTIONS (otherwise it's
     372       probably been shadowed by some other entry).  */
     373    char *short_options;
     374  
     375    /* Entries are sorted by their group first, in the order:
     376         0, 1, 2, ..., n, -m, ..., -2, -1
     377       and then alphabetically within each group.  The default is 0.  */
     378    int group;
     379  
     380    /* The cluster of options this entry belongs to, or NULL if none.  */
     381    struct hol_cluster *cluster;
     382  
     383    /* The argp from which this option came.  */
     384    const struct argp *argp;
     385  
     386    /* Position in the array */
     387    unsigned ord;
     388  };
     389  
     390  /* A cluster of entries to reflect the argp tree structure.  */
     391  struct hol_cluster
     392  {
     393    /* A descriptive header printed before options in this cluster.  */
     394    const char *header;
     395  
     396    /* Used to order clusters within the same group with the same parent,
     397       according to the order in which they occurred in the parent argp's child
     398       list.  */
     399    int index;
     400  
     401    /* How to sort this cluster with respect to options and other clusters at the
     402       same depth (clusters always follow options in the same group).  */
     403    int group;
     404  
     405    /* The cluster to which this cluster belongs, or NULL if it's at the base
     406       level.  */
     407    struct hol_cluster *parent;
     408  
     409    /* The argp from which this cluster is (eventually) derived.  */
     410    const struct argp *argp;
     411  
     412    /* The distance this cluster is from the root.  */
     413    int depth;
     414  
     415    /* Clusters in a given hol are kept in a linked list, to make freeing them
     416       possible.  */
     417    struct hol_cluster *next;
     418  };
     419  
     420  /* A list of options for help.  */
     421  struct hol
     422  {
     423    /* An array of hol_entry's.  */
     424    struct hol_entry *entries;
     425    /* The number of entries in this hol.  If this field is zero, the others
     426       are undefined.  */
     427    unsigned num_entries;
     428  
     429    /* A string containing all short options in this HOL.  Each entry contains
     430       pointers into this string, so the order can't be messed with blindly.  */
     431    char *short_options;
     432  
     433    /* Clusters of entries in this hol.  */
     434    struct hol_cluster *clusters;
     435  };
     436  
     437  /* Create a struct hol from the options in ARGP.  CLUSTER is the
     438     hol_cluster in which these entries occur, or NULL if at the root.  */
     439  static struct hol *
     440  make_hol (const struct argp *argp, struct hol_cluster *cluster)
     441  {
     442    char *so;
     443    const struct argp_option *o;
     444    const struct argp_option *opts = argp->options;
     445    struct hol_entry *entry;
     446    unsigned num_short_options = 0;
     447    struct hol *hol = malloc (sizeof (struct hol));
     448  
     449    assert (hol);
     450  
     451    hol->num_entries = 0;
     452    hol->clusters = 0;
     453  
     454    if (opts)
     455      {
     456        int cur_group = 0;
     457  
     458        /* The first option must not be an alias.  */
     459        assert (! oalias (opts));
     460  
     461        /* Calculate the space needed.  */
     462        for (o = opts; ! oend (o); o++)
     463          {
     464            if (! oalias (o))
     465              hol->num_entries++;
     466            if (oshort (o))
     467              num_short_options++;        /* This is an upper bound.  */
     468          }
     469  
     470        hol->entries = malloc (sizeof (struct hol_entry) * hol->num_entries);
     471        hol->short_options = malloc (num_short_options + 1);
     472  
     473        assert (hol->entries && hol->short_options);
     474        if (SIZE_MAX <= UINT_MAX)
     475          assert (hol->num_entries <= SIZE_MAX / sizeof (struct hol_entry));
     476  
     477        /* Fill in the entries.  */
     478        so = hol->short_options;
     479        for (o = opts, entry = hol->entries; ! oend (o); entry++)
     480          {
     481            entry->opt = o;
     482            entry->num = 0;
     483            entry->short_options = so;
     484            entry->group = cur_group =
     485              o->group
     486              ? o->group
     487              : ((!o->name && !o->key)
     488                 ? cur_group + 1
     489                 : cur_group);
     490            entry->cluster = cluster;
     491            entry->argp = argp;
     492  
     493            do
     494              {
     495                entry->num++;
     496                if (oshort (o) && ! find_char (o->key, hol->short_options, so))
     497                  /* O has a valid short option which hasn't already been used.*/
     498                  *so++ = o->key;
     499                o++;
     500              }
     501            while (! oend (o) && oalias (o));
     502          }
     503        *so = '\0';               /* null terminated so we can find the length */
     504      }
     505  
     506    return hol;
     507  }
     508  
     509  /* Add a new cluster to HOL, with the given GROUP and HEADER (taken from the
     510     associated argp child list entry), INDEX, and PARENT, and return a pointer
     511     to it.  ARGP is the argp that this cluster results from.  */
     512  static struct hol_cluster *
     513  hol_add_cluster (struct hol *hol, int group, const char *header, int index,
     514                   struct hol_cluster *parent, const struct argp *argp)
     515  {
     516    struct hol_cluster *cl = malloc (sizeof (struct hol_cluster));
     517    if (cl)
     518      {
     519        cl->group = group;
     520        cl->header = header;
     521  
     522        cl->index = index;
     523        cl->parent = parent;
     524        cl->argp = argp;
     525        cl->depth = parent ? parent->depth + 1 : 0;
     526  
     527        cl->next = hol->clusters;
     528        hol->clusters = cl;
     529      }
     530    return cl;
     531  }
     532  
     533  /* Free HOL and any resources it uses.  */
     534  static void
     535  hol_free (struct hol *hol)
     536  {
     537    struct hol_cluster *cl = hol->clusters;
     538  
     539    while (cl)
     540      {
     541        struct hol_cluster *next = cl->next;
     542        free (cl);
     543        cl = next;
     544      }
     545  
     546    if (hol->num_entries > 0)
     547      {
     548        free (hol->entries);
     549        free (hol->short_options);
     550      }
     551  
     552    free (hol);
     553  }
     554  
     555  /* Iterate across the short_options of the given ENTRY.  Call FUNC for each.
     556     Stop when such a call returns a non-zero value, and return this value.
     557     If all FUNC invocations returned 0, return 0.  */
     558  static int
     559  hol_entry_short_iterate (const struct hol_entry *entry,
     560                           int (*func)(const struct argp_option *opt,
     561                                       const struct argp_option *real,
     562                                       const char *domain, void *cookie),
     563                           const char *domain, void *cookie)
     564  {
     565    unsigned nopts;
     566    int val = 0;
     567    const struct argp_option *opt, *real = entry->opt;
     568    char *so = entry->short_options;
     569  
     570    for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--)
     571      if (oshort (opt) && *so == opt->key)
     572        {
     573          if (!oalias (opt))
     574            real = opt;
     575          if (ovisible (opt))
     576            val = (*func)(opt, real, domain, cookie);
     577          so++;
     578        }
     579  
     580    return val;
     581  }
     582  
     583  /* Iterate across the long options of the given ENTRY.  Call FUNC for each.
     584     Stop when such a call returns a non-zero value, and return this value.
     585     If all FUNC invocations returned 0, return 0.  */
     586  static inline int
     587  #if (__GNUC__ >= 3) || (__clang_major__ >= 4)
     588  __attribute__ ((always_inline))
     589  #endif
     590  hol_entry_long_iterate (const struct hol_entry *entry,
     591                          int (*func)(const struct argp_option *opt,
     592                                      const struct argp_option *real,
     593                                      const char *domain, void *cookie),
     594                          const char *domain, void *cookie)
     595  {
     596    unsigned nopts;
     597    int val = 0;
     598    const struct argp_option *opt, *real = entry->opt;
     599  
     600    for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--)
     601      if (opt->name)
     602        {
     603          if (!oalias (opt))
     604            real = opt;
     605          if (ovisible (opt))
     606            val = (*func)(opt, real, domain, cookie);
     607        }
     608  
     609    return val;
     610  }
     611  
     612  /* A filter that returns true for the first short option of a given ENTRY.  */
     613  static int
     614  until_short (const struct argp_option *opt, const struct argp_option *real,
     615               const char *domain, void *cookie)
     616  {
     617    return oshort (opt) ? opt->key : 0;
     618  }
     619  
     620  /* Returns the first valid short option in ENTRY, or 0 if there is none.  */
     621  static char
     622  hol_entry_first_short (const struct hol_entry *entry)
     623  {
     624    return hol_entry_short_iterate (entry, until_short,
     625                                    entry->argp->argp_domain, 0);
     626  }
     627  
     628  /* Returns the first valid long option in ENTRY, or NULL if there is none.  */
     629  static const char *
     630  hol_entry_first_long (const struct hol_entry *entry)
     631  {
     632    const struct argp_option *opt;
     633    unsigned num;
     634    for (opt = entry->opt, num = entry->num; num > 0; opt++, num--)
     635      if (opt->name && ovisible (opt))
     636        return opt->name;
     637    return 0;
     638  }
     639  
     640  /* Returns the entry in HOL with the long option name NAME, or NULL if there is
     641     none.  */
     642  static struct hol_entry *
     643  hol_find_entry (struct hol *hol, const char *name)
     644  {
     645    struct hol_entry *entry = hol->entries;
     646    unsigned num_entries = hol->num_entries;
     647  
     648    while (num_entries-- > 0)
     649      {
     650        const struct argp_option *opt = entry->opt;
     651        unsigned num_opts = entry->num;
     652  
     653        while (num_opts-- > 0)
     654          if (opt->name && ovisible (opt) && strcmp (opt->name, name) == 0)
     655            return entry;
     656          else
     657            opt++;
     658  
     659        entry++;
     660      }
     661  
     662    return 0;
     663  }
     664  
     665  /* If an entry with the long option NAME occurs in HOL, set its special
     666     sort position to GROUP.  */
     667  static void
     668  hol_set_group (struct hol *hol, const char *name, int group)
     669  {
     670    struct hol_entry *entry = hol_find_entry (hol, name);
     671    if (entry)
     672      entry->group = group;
     673  }
     674  
     675  /* -------------------------------------------------------------------------- */
     676  /* Sorting the entries in a HOL.                                              */
     677  
     678  /* Order by group:  0, 1, 2, ..., n, -m, ..., -2, -1.  */
     679  static int
     680  group_cmp (int group1, int group2)
     681  {
     682    if ((group1 < 0 && group2 < 0) || (group1 >= 0 && group2 >= 0))
     683      return group1 - group2;
     684    else
     685      /* Return > 0 if group1 < 0 <= group2.
     686         Return < 0 if group2 < 0 <= group1.  */
     687      return group2 - group1;
     688  }
     689  
     690  /* Compare clusters CL1 and CL2 by the order that they should appear in
     691     output.  Assume CL1 and CL2 have the same parent.  */
     692  static int
     693  hol_sibling_cluster_cmp (const struct hol_cluster *cl1,
     694                           const struct hol_cluster *cl2)
     695  {
     696    /* Compare by group first.  */
     697    int cmp = group_cmp (cl1->group, cl2->group);
     698    if (cmp != 0)
     699      return cmp;
     700  
     701    /* Within a group, compare by index within the group.  */
     702    return cl2->index - cl1->index;
     703  }
     704  
     705  /* Compare clusters CL1 and CL2 by the order that they should appear in
     706     output.  Assume CL1 and CL2 are at the same depth.  */
     707  static int
     708  hol_cousin_cluster_cmp (const struct hol_cluster *cl1,
     709                          const struct hol_cluster *cl2)
     710  {
     711    if (cl1->parent == cl2->parent)
     712      return hol_sibling_cluster_cmp (cl1, cl2);
     713    else
     714      {
     715        /* Compare the parent clusters first.  */
     716        int cmp = hol_cousin_cluster_cmp (cl1->parent, cl2->parent);
     717        if (cmp != 0)
     718          return cmp;
     719  
     720        /* Next, compare by group.  */
     721        cmp = group_cmp (cl1->group, cl2->group);
     722        if (cmp != 0)
     723          return cmp;
     724  
     725        /* Next, within a group, compare by index within the group.  */
     726        return cl2->index - cl1->index;
     727      }
     728  }
     729  
     730  /* Compare clusters CL1 and CL2 by the order that they should appear in
     731     output.  */
     732  static int
     733  hol_cluster_cmp (const struct hol_cluster *cl1, const struct hol_cluster *cl2)
     734  {
     735    /* If one cluster is deeper than the other, use its ancestor at the same
     736       level.  Then, go by the rule that entries that are not in a sub-cluster
     737       come before entries in a sub-cluster.  */
     738    if (cl1->depth > cl2->depth)
     739      {
     740        do
     741          cl1 = cl1->parent;
     742        while (cl1->depth > cl2->depth);
     743        int cmp = hol_cousin_cluster_cmp (cl1, cl2);
     744        if (cmp != 0)
     745          return cmp;
     746  
     747        return 1;
     748      }
     749    else if (cl1->depth < cl2->depth)
     750      {
     751        do
     752          cl2 = cl2->parent;
     753        while (cl1->depth < cl2->depth);
     754        int cmp = hol_cousin_cluster_cmp (cl1, cl2);
     755        if (cmp != 0)
     756          return cmp;
     757  
     758        return -1;
     759      }
     760    else
     761      return hol_cousin_cluster_cmp (cl1, cl2);
     762  }
     763  
     764  /* Return the ancestor of CL that's just below the root (i.e., has a parent
     765     of 0).  */
     766  static struct hol_cluster *
     767  hol_cluster_base (struct hol_cluster *cl)
     768  {
     769    while (cl->parent)
     770      cl = cl->parent;
     771    return cl;
     772  }
     773  
     774  /* Given the name of an OPTION_DOC option, modifies *NAME to start at the tail
     775     that should be used for comparisons, and returns true iff it should be
     776     treated as a non-option.  */
     777  static int
     778  canon_doc_option (const char **name)
     779  {
     780    int non_opt;
     781    /* Skip initial whitespace.  */
     782    while (isspace ((unsigned char) **name))
     783      (*name)++;
     784    /* Decide whether this looks like an option (leading '-') or not.  */
     785    non_opt = (**name != '-');
     786    /* Skip until part of name used for sorting.  */
     787    while (**name && !isalnum ((unsigned char) **name))
     788      (*name)++;
     789    return non_opt;
     790  }
     791  
     792  /* Order ENTRY1 and ENTRY2 by the order which they should appear in a help
     793     listing.
     794     This function implements a total order, that is:
     795       - if cmp (entry1, entry2) < 0 and cmp (entry2, entry3) < 0,
     796         then cmp (entry1, entry3) < 0.
     797       - if cmp (entry1, entry2) < 0 and cmp (entry2, entry3) == 0,
     798         then cmp (entry1, entry3) < 0.
     799       - if cmp (entry1, entry2) == 0 and cmp (entry2, entry3) < 0,
     800         then cmp (entry1, entry3) < 0.
     801       - if cmp (entry1, entry2) == 0 and cmp (entry2, entry3) == 0,
     802         then cmp (entry1, entry3) == 0.  */
     803  static int
     804  hol_entry_cmp (const struct hol_entry *entry1,
     805                 const struct hol_entry *entry2)
     806  {
     807    /* First, compare the group numbers.  For entries within a cluster, what
     808       matters is the group number of the base cluster in which the entry
     809       resides.  */
     810    int group1 = (entry1->cluster
     811                  ? hol_cluster_base (entry1->cluster)->group
     812                  : entry1->group);
     813    int group2 = (entry2->cluster
     814                  ? hol_cluster_base (entry2->cluster)->group
     815                  : entry2->group);
     816    int cmp = group_cmp (group1, group2);
     817    if (cmp != 0)
     818      return cmp;
     819  
     820    /* The group numbers are the same.  */
     821  
     822    /* Entries that are not in a cluster come before entries in a cluster.  */
     823    cmp = (entry1->cluster != NULL) - (entry2->cluster != NULL);
     824    if (cmp != 0)
     825      return cmp;
     826  
     827    /* Compare the clusters.  */
     828    if (entry1->cluster != NULL)
     829      {
     830        cmp = hol_cluster_cmp (entry1->cluster, entry2->cluster);
     831        if (cmp != 0)
     832          return cmp;
     833      }
     834  
     835    /* For entries in the same cluster, compare also the group numbers
     836       within the cluster.  */
     837    cmp = group_cmp (entry1->group, entry2->group);
     838    if (cmp != 0)
     839      return cmp;
     840  
     841    /* The entries are both in the same group and the same cluster.  */
     842  
     843    /* 'documentation' options always follow normal options (or documentation
     844       options that *look* like normal options).  */
     845    const char *long1 = hol_entry_first_long (entry1);
     846    const char *long2 = hol_entry_first_long (entry2);
     847    int doc1 =
     848      (odoc (entry1->opt) ? long1 != NULL && canon_doc_option (&long1) : 0);
     849    int doc2 =
     850      (odoc (entry2->opt) ? long2 != NULL && canon_doc_option (&long2) : 0);
     851    cmp = doc1 - doc2;
     852    if (cmp != 0)
     853      return cmp;
     854  
     855    /* Compare the entries alphabetically.  */
     856  
     857    /* First, compare the first character of the options.
     858       Put entries without *any* valid options (such as options with
     859       OPTION_HIDDEN set) first.  But as they're not displayed, it doesn't
     860       matter where they are.  */
     861    int short1 = hol_entry_first_short (entry1);
     862    int short2 = hol_entry_first_short (entry2);
     863    unsigned char first1 = short1 ? short1 : long1 != NULL ? *long1 : 0;
     864    unsigned char first2 = short2 ? short2 : long2 != NULL ? *long2 : 0;
     865    /* Compare ignoring case.  */
     866    /* Use tolower, not _tolower, since the latter has undefined behaviour
     867       for characters that are not uppercase letters.  */
     868    cmp = tolower (first1) - tolower (first2);
     869    if (cmp != 0)
     870      return cmp;
     871    /* When the options start with the same letter (ignoring case), lower-case
     872       comes first.  */
     873    cmp = first2 - first1;
     874    if (cmp != 0)
     875      return cmp;
     876  
     877    /* The first character of the options agree.  */
     878  
     879    /* Put entries with a short option before entries without a short option.  */
     880    cmp = (short1 != 0) - (short2 != 0);
     881    if (cmp != 0)
     882      return cmp;
     883  
     884    /* Compare entries without a short option by comparing the long option.  */
     885    if (short1 == 0)
     886      {
     887        cmp = (long1 != NULL) - (long2 != NULL);
     888        if (cmp != 0)
     889          return cmp;
     890  
     891        if (long1 != NULL)
     892          {
     893            cmp = __strcasecmp (long1, long2);
     894            if (cmp != 0)
     895              return cmp;
     896          }
     897      }
     898  
     899    /* We're out of comparison criteria.  At this point, if ENTRY1 != ENTRY2,
     900       the order of these entries will be unpredictable.  */
     901    return 0;
     902  }
     903  
     904  /* Variant of hol_entry_cmp with correct signature for qsort.  */
     905  static int
     906  hol_entry_qcmp (const void *entry1_v, const void *entry2_v)
     907  {
     908    return hol_entry_cmp (entry1_v, entry2_v);
     909  }
     910  
     911  /* Sort HOL by group and alphabetically by option name (with short options
     912     taking precedence over long).  Since the sorting is for display purposes
     913     only, the shadowing of options isn't effected.  */
     914  static void
     915  hol_sort (struct hol *hol)
     916  {
     917    if (hol->num_entries > 0)
     918      {
     919        unsigned i;
     920        struct hol_entry *e;
     921        for (i = 0, e = hol->entries; i < hol->num_entries; i++, e++)
     922          e->ord = i;
     923  
     924        qsort (hol->entries, hol->num_entries, sizeof (struct hol_entry),
     925               hol_entry_qcmp);
     926      }
     927  }
     928  
     929  /* -------------------------------------------------------------------------- */
     930  /* Constructing the HOL.                                                      */
     931  
     932  /* Append MORE to HOL, destroying MORE in the process.  Options in HOL shadow
     933     any in MORE with the same name.  */
     934  static void
     935  hol_append (struct hol *hol, struct hol *more)
     936  {
     937    struct hol_cluster **cl_end = &hol->clusters;
     938  
     939    /* Steal MORE's cluster list, and add it to the end of HOL's.  */
     940    while (*cl_end)
     941      cl_end = &(*cl_end)->next;
     942    *cl_end = more->clusters;
     943    more->clusters = 0;
     944  
     945    /* Merge entries.  */
     946    if (more->num_entries > 0)
     947      {
     948        if (hol->num_entries == 0)
     949          {
     950            hol->num_entries = more->num_entries;
     951            hol->entries = more->entries;
     952            hol->short_options = more->short_options;
     953            more->num_entries = 0;        /* Mark MORE's fields as invalid.  */
     954          }
     955        else
     956          /* Append the entries in MORE to those in HOL, taking care to only add
     957             non-shadowed SHORT_OPTIONS values.  */
     958          {
     959            unsigned left;
     960            char *so, *more_so;
     961            struct hol_entry *e;
     962            unsigned num_entries = hol->num_entries + more->num_entries;
     963            struct hol_entry *entries =
     964              malloc (num_entries * sizeof (struct hol_entry));
     965            unsigned hol_so_len = strlen (hol->short_options);
     966            char *short_options =
     967              malloc (hol_so_len + strlen (more->short_options) + 1);
     968  
     969            assert (entries && short_options);
     970            if (SIZE_MAX <= UINT_MAX)
     971              assert (num_entries <= SIZE_MAX / sizeof (struct hol_entry));
     972  
     973            __mempcpy (__mempcpy (entries, hol->entries,
     974                                  hol->num_entries * sizeof (struct hol_entry)),
     975                       more->entries,
     976                       more->num_entries * sizeof (struct hol_entry));
     977  
     978            __mempcpy (short_options, hol->short_options, hol_so_len);
     979  
     980            /* Fix up the short options pointers from HOL.  */
     981            for (e = entries, left = hol->num_entries; left > 0; e++, left--)
     982              e->short_options
     983                = short_options + (e->short_options - hol->short_options);
     984  
     985            /* Now add the short options from MORE, fixing up its entries
     986               too.  */
     987            so = short_options + hol_so_len;
     988            more_so = more->short_options;
     989            for (left = more->num_entries; left > 0; e++, left--)
     990              {
     991                int opts_left;
     992                const struct argp_option *opt;
     993  
     994                e->short_options = so;
     995  
     996                for (opts_left = e->num, opt = e->opt; opts_left; opt++, opts_left--)
     997                  {
     998                    int ch = *more_so;
     999                    if (oshort (opt) && ch == opt->key)
    1000                      /* The next short option in MORE_SO, CH, is from OPT.  */
    1001                      {
    1002                        if (! find_char (ch, short_options,
    1003                                         short_options + hol_so_len))
    1004                          /* The short option CH isn't shadowed by HOL's options,
    1005                             so add it to the sum.  */
    1006                          *so++ = ch;
    1007                        more_so++;
    1008                      }
    1009                  }
    1010              }
    1011  
    1012            *so = '\0';
    1013  
    1014            free (hol->entries);
    1015            free (hol->short_options);
    1016  
    1017            hol->entries = entries;
    1018            hol->num_entries = num_entries;
    1019            hol->short_options = short_options;
    1020          }
    1021      }
    1022  
    1023    hol_free (more);
    1024  }
    1025  
    1026  /* Make a HOL containing all levels of options in ARGP.  CLUSTER is the
    1027     cluster in which ARGP's entries should be clustered, or NULL.  */
    1028  static struct hol *
    1029  argp_hol (const struct argp *argp, struct hol_cluster *cluster)
    1030  {
    1031    const struct argp_child *child = argp->children;
    1032    struct hol *hol = make_hol (argp, cluster);
    1033    if (child)
    1034      while (child->argp)
    1035        {
    1036          struct hol_cluster *child_cluster =
    1037            ((child->group || child->header)
    1038             /* Put CHILD->argp within its own cluster.  */
    1039             ? hol_add_cluster (hol, child->group, child->header,
    1040                                child - argp->children, cluster, argp)
    1041             /* Just merge it into the parent's cluster.  */
    1042             : cluster);
    1043          hol_append (hol, argp_hol (child->argp, child_cluster)) ;
    1044          child++;
    1045        }
    1046    return hol;
    1047  }
    1048  
    1049  /* -------------------------------------------------------------------------- */
    1050  /* Printing the HOL.                                                          */
    1051  
    1052  /* Inserts enough spaces to make sure STREAM is at column COL.  */
    1053  static void
    1054  indent_to (argp_fmtstream_t stream, unsigned col)
    1055  {
    1056    int needed = col - __argp_fmtstream_point (stream);
    1057    while (needed-- > 0)
    1058      __argp_fmtstream_putc (stream, ' ');
    1059  }
    1060  
    1061  /* Output to STREAM either a space, or a newline if there isn't room for at
    1062     least ENSURE characters before the right margin.  */
    1063  static void
    1064  space (argp_fmtstream_t stream, size_t ensure)
    1065  {
    1066    if (__argp_fmtstream_point (stream) + ensure
    1067        >= __argp_fmtstream_rmargin (stream))
    1068      __argp_fmtstream_putc (stream, '\n');
    1069    else
    1070      __argp_fmtstream_putc (stream, ' ');
    1071  }
    1072  
    1073  /* If the option REAL has an argument, we print it in using the printf
    1074     format REQ_FMT or OPT_FMT depending on whether it's a required or
    1075     optional argument.  */
    1076  static void
    1077  arg (const struct argp_option *real, const char *req_fmt, const char *opt_fmt,
    1078       const char *domain, argp_fmtstream_t stream)
    1079  {
    1080    if (real->arg)
    1081      {
    1082        if (real->flags & OPTION_ARG_OPTIONAL)
    1083          __argp_fmtstream_printf (stream, opt_fmt,
    1084                                   dgettext (domain, real->arg));
    1085        else
    1086          __argp_fmtstream_printf (stream, req_fmt,
    1087                                   dgettext (domain, real->arg));
    1088      }
    1089  }
    1090  
    1091  /* Helper functions for hol_entry_help.  */
    1092  
    1093  /* State used during the execution of hol_help.  */
    1094  struct hol_help_state
    1095  {
    1096    /* PREV_ENTRY should contain the previous entry printed, or NULL.  */
    1097    struct hol_entry *prev_entry;
    1098  
    1099    /* If an entry is in a different group from the previous one, and SEP_GROUPS
    1100       is true, then a blank line will be printed before any output. */
    1101    int sep_groups;
    1102  
    1103    /* True if a duplicate option argument was suppressed (only ever set if
    1104       UPARAMS.dup_args is false).  */
    1105    int suppressed_dup_arg;
    1106  };
    1107  
    1108  /* Some state used while printing a help entry (used to communicate with
    1109     helper functions).  See the doc for hol_entry_help for more info, as most
    1110     of the fields are copied from its arguments.  */
    1111  struct pentry_state
    1112  {
    1113    const struct hol_entry *entry;
    1114    argp_fmtstream_t stream;
    1115    struct hol_help_state *hhstate;
    1116  
    1117    /* True if nothing's been printed so far.  */
    1118    int first;
    1119  
    1120    /* If non-zero, the state that was used to print this help.  */
    1121    const struct argp_state *state;
    1122  };
    1123  
    1124  /* If a user doc filter should be applied to DOC, do so.  */
    1125  static const char *
    1126  filter_doc (const char *doc, int key, const struct argp *argp,
    1127              const struct argp_state *state)
    1128  {
    1129    if (argp && argp->help_filter)
    1130      /* We must apply a user filter to this output.  */
    1131      {
    1132        void *input = __argp_input (argp, state);
    1133        return (*argp->help_filter) (key, doc, input);
    1134      }
    1135    else
    1136      /* No filter.  */
    1137      return doc;
    1138  }
    1139  
    1140  /* Prints STR as a header line, with the margin lines set appropriately, and
    1141     notes the fact that groups should be separated with a blank line.  ARGP is
    1142     the argp that should dictate any user doc filtering to take place.  Note
    1143     that the previous wrap margin isn't restored, but the left margin is reset
    1144     to 0.  */
    1145  static void
    1146  print_header (const char *str, const struct argp *argp,
    1147                struct pentry_state *pest)
    1148  {
    1149    const char *tstr = str ? dgettext (argp->argp_domain, str) : NULL;
    1150    const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_HEADER, argp, pest->state);
    1151  
    1152    if (fstr)
    1153      {
    1154        if (*fstr)
    1155          {
    1156            if (pest->hhstate->prev_entry)
    1157              /* Precede with a blank line.  */
    1158              __argp_fmtstream_putc (pest->stream, '\n');
    1159            indent_to (pest->stream, uparams.header_col);
    1160            __argp_fmtstream_set_lmargin (pest->stream, uparams.header_col);
    1161            __argp_fmtstream_set_wmargin (pest->stream, uparams.header_col);
    1162            __argp_fmtstream_puts (pest->stream, fstr);
    1163            __argp_fmtstream_set_lmargin (pest->stream, 0);
    1164            __argp_fmtstream_putc (pest->stream, '\n');
    1165          }
    1166  
    1167        pest->hhstate->sep_groups = 1; /* Separate subsequent groups. */
    1168      }
    1169  
    1170    if (fstr != tstr)
    1171      free ((char *) fstr);
    1172  }
    1173  
    1174  /* Return true if CL1 is a child of CL2.  */
    1175  static int
    1176  hol_cluster_is_child (const struct hol_cluster *cl1,
    1177                        const struct hol_cluster *cl2)
    1178  {
    1179    while (cl1 && cl1 != cl2)
    1180      cl1 = cl1->parent;
    1181    return cl1 == cl2;
    1182  }
    1183  
    1184  /* Inserts a comma if this isn't the first item on the line, and then makes
    1185     sure we're at least to column COL.  If this *is* the first item on a line,
    1186     prints any pending whitespace/headers that should precede this line. Also
    1187     clears FIRST.  */
    1188  static void
    1189  comma (unsigned col, struct pentry_state *pest)
    1190  {
    1191    if (pest->first)
    1192      {
    1193        const struct hol_entry *pe = pest->hhstate->prev_entry;
    1194        const struct hol_cluster *cl = pest->entry->cluster;
    1195  
    1196        if (pest->hhstate->sep_groups && pe && pest->entry->group != pe->group)
    1197          __argp_fmtstream_putc (pest->stream, '\n');
    1198  
    1199        if (cl && cl->header && *cl->header
    1200            && (!pe
    1201                || (pe->cluster != cl
    1202                    && !hol_cluster_is_child (pe->cluster, cl))))
    1203          /* If we're changing clusters, then this must be the start of the
    1204             ENTRY's cluster unless that is an ancestor of the previous one
    1205             (in which case we had just popped into a sub-cluster for a bit).
    1206             If so, then print the cluster's header line.  */
    1207          {
    1208            int old_wm = __argp_fmtstream_wmargin (pest->stream);
    1209            print_header (cl->header, cl->argp, pest);
    1210            __argp_fmtstream_set_wmargin (pest->stream, old_wm);
    1211          }
    1212  
    1213        pest->first = 0;
    1214      }
    1215    else
    1216      __argp_fmtstream_puts (pest->stream, ", ");
    1217  
    1218    indent_to (pest->stream, col);
    1219  }
    1220  
    1221  /* Print help for ENTRY to STREAM.  */
    1222  static void
    1223  hol_entry_help (struct hol_entry *entry, const struct argp_state *state,
    1224                  argp_fmtstream_t stream, struct hol_help_state *hhstate)
    1225  {
    1226    unsigned num;
    1227    const struct argp_option *real = entry->opt, *opt;
    1228    char *so = entry->short_options;
    1229    int have_long_opt = 0;        /* We have any long options.  */
    1230    /* Saved margins.  */
    1231    int old_lm = __argp_fmtstream_set_lmargin (stream, 0);
    1232    int old_wm = __argp_fmtstream_wmargin (stream);
    1233    /* PEST is a state block holding some of our variables that we'd like to
    1234       share with helper functions.  */
    1235    struct pentry_state pest = { entry, stream, hhstate, 1, state };
    1236  
    1237    if (! odoc (real))
    1238      for (opt = real, num = entry->num; num > 0; opt++, num--)
    1239        if (opt->name && ovisible (opt))
    1240          {
    1241            have_long_opt = 1;
    1242            break;
    1243          }
    1244  
    1245    /* First emit short options.  */
    1246    __argp_fmtstream_set_wmargin (stream, uparams.short_opt_col); /* For truly bizarre cases. */
    1247    for (opt = real, num = entry->num; num > 0; opt++, num--)
    1248      if (oshort (opt) && opt->key == *so)
    1249        /* OPT has a valid (non shadowed) short option.  */
    1250        {
    1251          if (ovisible (opt))
    1252            {
    1253              comma (uparams.short_opt_col, &pest);
    1254              __argp_fmtstream_putc (stream, '-');
    1255              __argp_fmtstream_putc (stream, *so);
    1256              if (!have_long_opt || uparams.dup_args)
    1257                arg (real, " %s", "[%s]",
    1258                     state == NULL ? NULL : state->root_argp->argp_domain,
    1259                     stream);
    1260              else if (real->arg)
    1261                hhstate->suppressed_dup_arg = 1;
    1262            }
    1263          so++;
    1264        }
    1265  
    1266    /* Now, long options.  */
    1267    if (odoc (real))
    1268      /* A "documentation" option.  */
    1269      {
    1270        __argp_fmtstream_set_wmargin (stream, uparams.doc_opt_col);
    1271        for (opt = real, num = entry->num; num > 0; opt++, num--)
    1272          if (opt->name && ovisible (opt))
    1273            {
    1274              comma (uparams.doc_opt_col, &pest);
    1275              /* Calling dgettext here isn't quite right, since sorting will
    1276                 have been done on the original; but documentation options
    1277                 should be pretty rare anyway...  */
    1278              __argp_fmtstream_puts (stream,
    1279                                     dgettext (state == NULL ? NULL
    1280                                               : state->root_argp->argp_domain,
    1281                                               opt->name));
    1282            }
    1283      }
    1284    else
    1285      /* A real long option.  */
    1286      {
    1287        __argp_fmtstream_set_wmargin (stream, uparams.long_opt_col);
    1288        for (opt = real, num = entry->num; num > 0; opt++, num--)
    1289          if (opt->name && ovisible (opt))
    1290            {
    1291              comma (uparams.long_opt_col, &pest);
    1292              __argp_fmtstream_printf (stream, "--%s", opt->name);
    1293              arg (real, "=%s", "[=%s]",
    1294                   state == NULL ? NULL : state->root_argp->argp_domain, stream);
    1295            }
    1296      }
    1297  
    1298    /* Next, documentation strings.  */
    1299    __argp_fmtstream_set_lmargin (stream, 0);
    1300  
    1301    if (pest.first)
    1302      {
    1303        /* Didn't print any switches, what's up?  */
    1304        if (!oshort (real) && !real->name)
    1305          /* This is a group header, print it nicely.  */
    1306          print_header (real->doc, entry->argp, &pest);
    1307        else
    1308          /* Just a totally shadowed option or null header; print nothing.  */
    1309          goto cleanup;           /* Just return, after cleaning up.  */
    1310      }
    1311    else
    1312      {
    1313        const char *tstr = real->doc ? dgettext (state == NULL ? NULL
    1314                                                 : state->root_argp->argp_domain,
    1315                                                 real->doc) : 0;
    1316        const char *fstr = filter_doc (tstr, real->key, entry->argp, state);
    1317        if (fstr && *fstr)
    1318          {
    1319            unsigned int col = __argp_fmtstream_point (stream);
    1320  
    1321            __argp_fmtstream_set_lmargin (stream, uparams.opt_doc_col);
    1322            __argp_fmtstream_set_wmargin (stream, uparams.opt_doc_col);
    1323  
    1324            if (col > (unsigned int) (uparams.opt_doc_col + 3))
    1325              __argp_fmtstream_putc (stream, '\n');
    1326            else if (col >= (unsigned int) uparams.opt_doc_col)
    1327              __argp_fmtstream_puts (stream, "   ");
    1328            else
    1329              indent_to (stream, uparams.opt_doc_col);
    1330  
    1331            __argp_fmtstream_puts (stream, fstr);
    1332          }
    1333        if (fstr && fstr != tstr)
    1334          free ((char *) fstr);
    1335  
    1336        /* Reset the left margin.  */
    1337        __argp_fmtstream_set_lmargin (stream, 0);
    1338        __argp_fmtstream_putc (stream, '\n');
    1339      }
    1340  
    1341    hhstate->prev_entry = entry;
    1342  
    1343  cleanup:
    1344    __argp_fmtstream_set_lmargin (stream, old_lm);
    1345    __argp_fmtstream_set_wmargin (stream, old_wm);
    1346  }
    1347  
    1348  /* Output a long help message about the options in HOL to STREAM.  */
    1349  static void
    1350  hol_help (struct hol *hol, const struct argp_state *state,
    1351            argp_fmtstream_t stream)
    1352  {
    1353    unsigned num;
    1354    struct hol_entry *entry;
    1355    struct hol_help_state hhstate = { 0, 0, 0 };
    1356  
    1357    for (entry = hol->entries, num = hol->num_entries; num > 0; entry++, num--)
    1358      hol_entry_help (entry, state, stream, &hhstate);
    1359  
    1360    if (hhstate.suppressed_dup_arg && uparams.dup_args_note)
    1361      {
    1362        const char *tstr = dgettext (state == NULL ? NULL
    1363                                     : state->root_argp->argp_domain, "\
    1364  Mandatory or optional arguments to long options are also mandatory or \
    1365  optional for any corresponding short options.");
    1366        const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_DUP_ARGS_NOTE,
    1367                                       state ? state->root_argp : 0, state);
    1368        if (fstr && *fstr)
    1369          {
    1370            __argp_fmtstream_putc (stream, '\n');
    1371            __argp_fmtstream_puts (stream, fstr);
    1372            __argp_fmtstream_putc (stream, '\n');
    1373          }
    1374        if (fstr && fstr != tstr)
    1375          free ((char *) fstr);
    1376      }
    1377  }
    1378  
    1379  /* Helper functions for hol_usage.  */
    1380  
    1381  /* If OPT is a short option without an arg, append its key to the string
    1382     pointer pointer to by COOKIE, and advance the pointer.  */
    1383  static int
    1384  add_argless_short_opt (const struct argp_option *opt,
    1385                         const struct argp_option *real,
    1386                         const char *domain, void *cookie)
    1387  {
    1388    char **snao_end = cookie;
    1389    if (!(opt->arg || real->arg)
    1390        && !((opt->flags | real->flags) & OPTION_NO_USAGE))
    1391      *(*snao_end)++ = opt->key;
    1392    return 0;
    1393  }
    1394  
    1395  /* If OPT is a short option with an arg, output a usage entry for it to the
    1396     stream pointed at by COOKIE.  */
    1397  static int
    1398  usage_argful_short_opt (const struct argp_option *opt,
    1399                          const struct argp_option *real,
    1400                          const char *domain, void *cookie)
    1401  {
    1402    argp_fmtstream_t stream = cookie;
    1403    const char *arg = opt->arg;
    1404    int flags = opt->flags | real->flags;
    1405  
    1406    if (! arg)
    1407      arg = real->arg;
    1408  
    1409    if (arg && !(flags & OPTION_NO_USAGE))
    1410      {
    1411        arg = dgettext (domain, arg);
    1412  
    1413        if (flags & OPTION_ARG_OPTIONAL)
    1414          __argp_fmtstream_printf (stream, " [-%c[%s]]", opt->key, arg);
    1415        else
    1416          {
    1417            /* Manually do line wrapping so that it (probably) won't
    1418               get wrapped at the embedded space.  */
    1419            space (stream, 6 + strlen (arg));
    1420            __argp_fmtstream_printf (stream, "[-%c %s]", opt->key, arg);
    1421          }
    1422      }
    1423  
    1424    return 0;
    1425  }
    1426  
    1427  /* Output a usage entry for the long option opt to the stream pointed at by
    1428     COOKIE.  */
    1429  static int
    1430  usage_long_opt (const struct argp_option *opt,
    1431                  const struct argp_option *real,
    1432                  const char *domain, void *cookie)
    1433  {
    1434    argp_fmtstream_t stream = cookie;
    1435    const char *arg = opt->arg;
    1436    int flags = opt->flags | real->flags;
    1437  
    1438    if (! arg)
    1439      arg = real->arg;
    1440  
    1441    if (! (flags & OPTION_NO_USAGE))
    1442      {
    1443        if (arg)
    1444          {
    1445            arg = dgettext (domain, arg);
    1446            if (flags & OPTION_ARG_OPTIONAL)
    1447              __argp_fmtstream_printf (stream, " [--%s[=%s]]", opt->name, arg);
    1448            else
    1449              __argp_fmtstream_printf (stream, " [--%s=%s]", opt->name, arg);
    1450          }
    1451        else
    1452          __argp_fmtstream_printf (stream, " [--%s]", opt->name);
    1453      }
    1454  
    1455    return 0;
    1456  }
    1457  
    1458  /* Print a short usage description for the arguments in HOL to STREAM.  */
    1459  static void
    1460  hol_usage (struct hol *hol, argp_fmtstream_t stream)
    1461  {
    1462    if (hol->num_entries > 0)
    1463      {
    1464        unsigned nentries;
    1465        struct hol_entry *entry;
    1466        char *short_no_arg_opts = alloca (strlen (hol->short_options) + 1);
    1467        char *snao_end = short_no_arg_opts;
    1468  
    1469        /* First we put a list of short options without arguments.  */
    1470        for (entry = hol->entries, nentries = hol->num_entries
    1471             ; nentries > 0
    1472             ; entry++, nentries--)
    1473          hol_entry_short_iterate (entry, add_argless_short_opt,
    1474                                   entry->argp->argp_domain, &snao_end);
    1475        if (snao_end > short_no_arg_opts)
    1476          {
    1477            *snao_end++ = 0;
    1478            __argp_fmtstream_printf (stream, " [-%s]", short_no_arg_opts);
    1479          }
    1480  
    1481        /* Now a list of short options *with* arguments.  */
    1482        for (entry = hol->entries, nentries = hol->num_entries
    1483             ; nentries > 0
    1484             ; entry++, nentries--)
    1485          hol_entry_short_iterate (entry, usage_argful_short_opt,
    1486                                   entry->argp->argp_domain, stream);
    1487  
    1488        /* Finally, a list of long options (whew!).  */
    1489        for (entry = hol->entries, nentries = hol->num_entries
    1490             ; nentries > 0
    1491             ; entry++, nentries--)
    1492          hol_entry_long_iterate (entry, usage_long_opt,
    1493                                  entry->argp->argp_domain, stream);
    1494      }
    1495  }
    1496  
    1497  /* Calculate how many different levels with alternative args strings exist in
    1498     ARGP.  */
    1499  static size_t
    1500  argp_args_levels (const struct argp *argp)
    1501  {
    1502    size_t levels = 0;
    1503    const struct argp_child *child = argp->children;
    1504  
    1505    if (argp->args_doc && strchr (argp->args_doc, '\n'))
    1506      levels++;
    1507  
    1508    if (child)
    1509      while (child->argp)
    1510        levels += argp_args_levels ((child++)->argp);
    1511  
    1512    return levels;
    1513  }
    1514  
    1515  /* Print all the non-option args documented in ARGP to STREAM.  Any output is
    1516     preceded by a space.  LEVELS is a pointer to a byte vector the length
    1517     returned by argp_args_levels; it should be initialized to zero, and
    1518     updated by this routine for the next call if ADVANCE is true.  True is
    1519     returned as long as there are more patterns to output.  */
    1520  static int
    1521  argp_args_usage (const struct argp *argp, const struct argp_state *state,
    1522                   char **levels, int advance, argp_fmtstream_t stream)
    1523  {
    1524    char *our_level = *levels;
    1525    int multiple = 0;
    1526    const struct argp_child *child = argp->children;
    1527    const char *tdoc =
    1528      argp->args_doc ? dgettext (argp->argp_domain, argp->args_doc) : NULL;
    1529    const char *fdoc = filter_doc (tdoc, ARGP_KEY_HELP_ARGS_DOC, argp, state);
    1530    const char *nl = NULL;
    1531  
    1532    if (fdoc)
    1533      {
    1534        const char *cp = fdoc;
    1535        nl = __strchrnul (cp, '\n');
    1536        if (*nl != '\0')
    1537          /* This is a 'multi-level' args doc; advance to the correct position
    1538             as determined by our state in LEVELS, and update LEVELS.  */
    1539          {
    1540            int i;
    1541            multiple = 1;
    1542            for (i = 0; i < *our_level; i++)
    1543              cp = nl + 1, nl = __strchrnul (cp, '\n');
    1544            (*levels)++;
    1545          }
    1546  
    1547        /* Manually do line wrapping so that it (probably) won't get wrapped at
    1548           any embedded spaces.  */
    1549        space (stream, 1 + nl - cp);
    1550  
    1551        __argp_fmtstream_write (stream, cp, nl - cp);
    1552      }
    1553    if (fdoc && fdoc != tdoc)
    1554      free ((char *)fdoc);        /* Free user's modified doc string.  */
    1555  
    1556    if (child)
    1557      while (child->argp)
    1558        advance = !argp_args_usage ((child++)->argp, state, levels, advance, stream);
    1559  
    1560    if (advance && multiple)
    1561      {
    1562        /* Need to increment our level.  */
    1563        if (*nl)
    1564          /* There's more we can do here.  */
    1565          {
    1566            (*our_level)++;
    1567            advance = 0;          /* Our parent shouldn't advance also. */
    1568          }
    1569        else if (*our_level > 0)
    1570          /* We had multiple levels, but used them up; reset to zero.  */
    1571          *our_level = 0;
    1572      }
    1573  
    1574    return !advance;
    1575  }
    1576  
    1577  /* Print the documentation for ARGP to STREAM; if POST is false, then
    1578     everything preceding a '\v' character in the documentation strings (or
    1579     the whole string, for those with none) is printed, otherwise, everything
    1580     following the '\v' character (nothing for strings without).  Each separate
    1581     bit of documentation is separated a blank line, and if PRE_BLANK is true,
    1582     then the first is as well.  If FIRST_ONLY is true, only the first
    1583     occurrence is output.  Returns true if anything was output.  */
    1584  static int
    1585  argp_doc (const struct argp *argp, const struct argp_state *state,
    1586            int post, int pre_blank, int first_only,
    1587            argp_fmtstream_t stream)
    1588  {
    1589    const char *text;
    1590    const char *inp_text;
    1591    void *input = 0;
    1592    int anything = 0;
    1593    size_t inp_text_limit = 0;
    1594    const char *doc = argp->doc ? dgettext (argp->argp_domain, argp->doc) : NULL;
    1595    const struct argp_child *child = argp->children;
    1596  
    1597    if (doc)
    1598      {
    1599        char *vt = strchr (doc, '\v');
    1600        inp_text = post ? (vt ? vt + 1 : 0) : doc;
    1601        inp_text_limit = (!post && vt) ? (vt - doc) : 0;
    1602      }
    1603    else
    1604      inp_text = 0;
    1605  
    1606    if (argp->help_filter)
    1607      /* We have to filter the doc strings.  */
    1608      {
    1609        if (inp_text_limit)
    1610          /* Copy INP_TEXT so that it's nul-terminated.  */
    1611          inp_text = __strndup (inp_text, inp_text_limit);
    1612        input = __argp_input (argp, state);
    1613        text =
    1614          (*argp->help_filter) (post
    1615                                ? ARGP_KEY_HELP_POST_DOC
    1616                                : ARGP_KEY_HELP_PRE_DOC,
    1617                                inp_text, input);
    1618      }
    1619    else
    1620      text = (const char *) inp_text;
    1621  
    1622    if (text)
    1623      {
    1624        if (pre_blank)
    1625          __argp_fmtstream_putc (stream, '\n');
    1626  
    1627        if (text == inp_text && inp_text_limit)
    1628          __argp_fmtstream_write (stream, inp_text, inp_text_limit);
    1629        else
    1630          __argp_fmtstream_puts (stream, text);
    1631  
    1632        if (__argp_fmtstream_point (stream) > __argp_fmtstream_lmargin (stream))
    1633          __argp_fmtstream_putc (stream, '\n');
    1634  
    1635        anything = 1;
    1636      }
    1637  
    1638    if (text && text != inp_text)
    1639      free ((char *) text);       /* Free TEXT returned from the help filter.  */
    1640    if (inp_text && inp_text_limit && argp->help_filter)
    1641      free ((char *) inp_text);   /* We copied INP_TEXT, so free it now.  */
    1642  
    1643    if (post && argp->help_filter)
    1644      /* Now see if we have to output a ARGP_KEY_HELP_EXTRA text.  */
    1645      {
    1646        text = (*argp->help_filter) (ARGP_KEY_HELP_EXTRA, 0, input);
    1647        if (text)
    1648          {
    1649            if (anything || pre_blank)
    1650              __argp_fmtstream_putc (stream, '\n');
    1651            __argp_fmtstream_puts (stream, text);
    1652            free ((char *) text);
    1653            if (__argp_fmtstream_point (stream)
    1654                > __argp_fmtstream_lmargin (stream))
    1655              __argp_fmtstream_putc (stream, '\n');
    1656            anything = 1;
    1657          }
    1658      }
    1659  
    1660    if (child)
    1661      while (child->argp && !(first_only && anything))
    1662        anything |=
    1663          argp_doc ((child++)->argp, state,
    1664                    post, anything || pre_blank, first_only,
    1665                    stream);
    1666  
    1667    return anything;
    1668  }
    1669  
    1670  /* Output a usage message for ARGP to STREAM.  If called from
    1671     argp_state_help, STATE is the relevant parsing state.  FLAGS are from the
    1672     set ARGP_HELP_*.  NAME is what to use wherever a 'program name' is
    1673     needed. */
    1674  static void
    1675  _help (const struct argp *argp, const struct argp_state *state, FILE *stream,
    1676         unsigned flags, char *name)
    1677  {
    1678    int anything = 0;             /* Whether we've output anything.  */
    1679    struct hol *hol = 0;
    1680    argp_fmtstream_t fs;
    1681  
    1682    if (! stream)
    1683      return;
    1684  
    1685  #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
    1686    __flockfile (stream);
    1687  #endif
    1688  
    1689    if (! uparams.valid)
    1690      fill_in_uparams (state);
    1691  
    1692    fs = __argp_make_fmtstream (stream, 0, uparams.rmargin, 0);
    1693    if (! fs)
    1694      {
    1695  #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
    1696        __funlockfile (stream);
    1697  #endif
    1698        return;
    1699      }
    1700  
    1701    if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG))
    1702      {
    1703        hol = argp_hol (argp, 0);
    1704  
    1705        /* If present, these options always come last.  */
    1706        hol_set_group (hol, "help", -1);
    1707        hol_set_group (hol, "version", -1);
    1708  
    1709        hol_sort (hol);
    1710      }
    1711  
    1712    if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE))
    1713      /* Print a short "Usage:" message.  */
    1714      {
    1715        int first_pattern = 1, more_patterns;
    1716        size_t num_pattern_levels = argp_args_levels (argp);
    1717        char *pattern_levels = alloca (num_pattern_levels);
    1718  
    1719        memset (pattern_levels, 0, num_pattern_levels);
    1720  
    1721        do
    1722          {
    1723            int old_lm;
    1724            int old_wm = __argp_fmtstream_set_wmargin (fs, uparams.usage_indent);
    1725            char *levels = pattern_levels;
    1726  
    1727            if (first_pattern)
    1728              __argp_fmtstream_printf (fs, "%s %s",
    1729                                       dgettext (argp->argp_domain, "Usage:"),
    1730                                       name);
    1731            else
    1732              __argp_fmtstream_printf (fs, "%s %s",
    1733                                       dgettext (argp->argp_domain, "  or: "),
    1734                                       name);
    1735  
    1736            /* We set the lmargin as well as the wmargin, because hol_usage
    1737               manually wraps options with newline to avoid annoying breaks.  */
    1738            old_lm = __argp_fmtstream_set_lmargin (fs, uparams.usage_indent);
    1739  
    1740            if (flags & ARGP_HELP_SHORT_USAGE)
    1741              /* Just show where the options go.  */
    1742              {
    1743                if (hol->num_entries > 0)
    1744                  __argp_fmtstream_puts (fs, dgettext (argp->argp_domain,
    1745                                                       " [OPTION...]"));
    1746              }
    1747            else
    1748              /* Actually print the options.  */
    1749              {
    1750                hol_usage (hol, fs);
    1751                flags |= ARGP_HELP_SHORT_USAGE; /* But only do so once.  */
    1752              }
    1753  
    1754            more_patterns = argp_args_usage (argp, state, &levels, 1, fs);
    1755  
    1756            __argp_fmtstream_set_wmargin (fs, old_wm);
    1757            __argp_fmtstream_set_lmargin (fs, old_lm);
    1758  
    1759            __argp_fmtstream_putc (fs, '\n');
    1760            anything = 1;
    1761  
    1762            first_pattern = 0;
    1763          }
    1764        while (more_patterns);
    1765      }
    1766  
    1767    if (flags & ARGP_HELP_PRE_DOC)
    1768      anything |= argp_doc (argp, state, 0, 0, 1, fs);
    1769  
    1770    if (flags & ARGP_HELP_SEE)
    1771      {
    1772        __argp_fmtstream_printf (fs, dgettext (argp->argp_domain, "\
    1773  Try '%s --help' or '%s --usage' for more information.\n"),
    1774                                 name, name);
    1775        anything = 1;
    1776      }
    1777  
    1778    if (flags & ARGP_HELP_LONG)
    1779      /* Print a long, detailed help message.  */
    1780      {
    1781        /* Print info about all the options.  */
    1782        if (hol->num_entries > 0)
    1783          {
    1784            if (anything)
    1785              __argp_fmtstream_putc (fs, '\n');
    1786            hol_help (hol, state, fs);
    1787            anything = 1;
    1788          }
    1789      }
    1790  
    1791    if (flags & ARGP_HELP_POST_DOC)
    1792      /* Print any documentation strings at the end.  */
    1793      anything |= argp_doc (argp, state, 1, anything, 0, fs);
    1794  
    1795    if ((flags & ARGP_HELP_BUG_ADDR) && argp_program_bug_address)
    1796      {
    1797        if (anything)
    1798          __argp_fmtstream_putc (fs, '\n');
    1799        __argp_fmtstream_printf (fs, dgettext (argp->argp_domain,
    1800                                               "Report bugs to %s.\n"),
    1801                                 argp_program_bug_address);
    1802        anything = 1;
    1803      }
    1804  
    1805  #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
    1806    __funlockfile (stream);
    1807  #endif
    1808  
    1809    if (hol)
    1810      hol_free (hol);
    1811  
    1812    __argp_fmtstream_free (fs);
    1813  }
    1814  
    1815  /* Output a usage message for ARGP to STREAM.  FLAGS are from the set
    1816     ARGP_HELP_*.  NAME is what to use wherever a 'program name' is needed. */
    1817  void __argp_help (const struct argp *argp, FILE *stream,
    1818                    unsigned flags, char *name)
    1819  {
    1820    _help (argp, 0, stream, flags, name);
    1821  }
    1822  #ifdef weak_alias
    1823  weak_alias (__argp_help, argp_help)
    1824  #endif
    1825  
    1826  #if ! (defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME)
    1827  char *
    1828  __argp_short_program_name (void)
    1829  {
    1830  # if HAVE_DECL_PROGRAM_INVOCATION_NAME
    1831    char *name = strrchr (program_invocation_name, '/');
    1832    return name ? name + 1 : program_invocation_name;
    1833  # else
    1834    /* FIXME: What now? Miles suggests that it is better to use NULL,
    1835       but currently the value is passed on directly to fputs_unlocked,
    1836       so that requires more changes. */
    1837  # if __GNUC__ || (__clang_major__ >= 4)
    1838  #  warning No reasonable value to return
    1839  # endif /* __GNUC__ */
    1840    return "";
    1841  # endif
    1842  }
    1843  #endif
    1844  
    1845  /* Output, if appropriate, a usage message for STATE to STREAM.  FLAGS are
    1846     from the set ARGP_HELP_*.  */
    1847  void
    1848  __argp_state_help (const struct argp_state *state, FILE *stream, unsigned flags)
    1849  {
    1850    if ((!state || ! (state->flags & ARGP_NO_ERRS)) && stream)
    1851      {
    1852        if (state && (state->flags & ARGP_LONG_ONLY))
    1853          flags |= ARGP_HELP_LONG_ONLY;
    1854  
    1855        _help (state ? state->root_argp : 0, state, stream, flags,
    1856               state ? state->name : __argp_short_program_name ());
    1857  
    1858        if (!state || ! (state->flags & ARGP_NO_EXIT))
    1859          {
    1860            if (flags & ARGP_HELP_EXIT_ERR)
    1861              exit (argp_err_exit_status);
    1862            if (flags & ARGP_HELP_EXIT_OK)
    1863              exit (0);
    1864          }
    1865    }
    1866  }
    1867  #ifdef weak_alias
    1868  weak_alias (__argp_state_help, argp_state_help)
    1869  #endif
    1870  
    1871  /* If appropriate, print the printf string FMT and following args, preceded
    1872     by the program name and ':', to stderr, and followed by a "Try ... --help"
    1873     message, then exit (1).  */
    1874  void
    1875  __argp_error (const struct argp_state *state, const char *fmt, ...)
    1876  {
    1877    if (!state || !(state->flags & ARGP_NO_ERRS))
    1878      {
    1879        FILE *stream = state ? state->err_stream : stderr;
    1880  
    1881        if (stream)
    1882          {
    1883            va_list ap;
    1884  
    1885  #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
    1886            __flockfile (stream);
    1887  #endif
    1888  
    1889            va_start (ap, fmt);
    1890  
    1891  #ifdef _LIBC
    1892            char *buf;
    1893  
    1894            if (_IO_vasprintf (&buf, fmt, ap) < 0)
    1895              buf = NULL;
    1896  
    1897            __fxprintf (stream, "%s: %s\n",
    1898                        state ? state->name : __argp_short_program_name (), buf);
    1899  
    1900            free (buf);
    1901  #else
    1902            fputs_unlocked (state ? state->name : __argp_short_program_name (),
    1903                            stream);
    1904            putc_unlocked (':', stream);
    1905            putc_unlocked (' ', stream);
    1906  
    1907            vfprintf (stream, fmt, ap);
    1908  
    1909            putc_unlocked ('\n', stream);
    1910  #endif
    1911  
    1912            __argp_state_help (state, stream, ARGP_HELP_STD_ERR);
    1913  
    1914            va_end (ap);
    1915  
    1916  #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
    1917            __funlockfile (stream);
    1918  #endif
    1919          }
    1920      }
    1921  }
    1922  #ifdef weak_alias
    1923  weak_alias (__argp_error, argp_error)
    1924  #endif
    1925  
    1926  /* Similar to the standard gnu error-reporting function error(), but will
    1927     respect the ARGP_NO_EXIT and ARGP_NO_ERRS flags in STATE, and will print
    1928     to STATE->err_stream.  This is useful for argument parsing code that is
    1929     shared between program startup (when exiting is desired) and runtime
    1930     option parsing (when typically an error code is returned instead).  The
    1931     difference between this function and argp_error is that the latter is for
    1932     *parsing errors*, and the former is for other problems that occur during
    1933     parsing but don't reflect a (syntactic) problem with the input.  */
    1934  void
    1935  __argp_failure (const struct argp_state *state, int status, int errnum,
    1936                  const char *fmt, ...)
    1937  {
    1938    if (!state || !(state->flags & ARGP_NO_ERRS))
    1939      {
    1940        FILE *stream = state ? state->err_stream : stderr;
    1941  
    1942        if (stream)
    1943          {
    1944  #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
    1945            __flockfile (stream);
    1946  #endif
    1947  
    1948  #ifdef _LIBC
    1949            __fxprintf (stream, "%s",
    1950                        state ? state->name : __argp_short_program_name ());
    1951  #else
    1952            fputs_unlocked (state ? state->name : __argp_short_program_name (),
    1953                            stream);
    1954  #endif
    1955  
    1956            if (fmt)
    1957              {
    1958                va_list ap;
    1959  
    1960                va_start (ap, fmt);
    1961  #ifdef _LIBC
    1962                char *buf;
    1963  
    1964                if (_IO_vasprintf (&buf, fmt, ap) < 0)
    1965                  buf = NULL;
    1966  
    1967                __fxprintf (stream, ": %s", buf);
    1968  
    1969                free (buf);
    1970  #else
    1971                putc_unlocked (':', stream);
    1972                putc_unlocked (' ', stream);
    1973  
    1974                vfprintf (stream, fmt, ap);
    1975  #endif
    1976  
    1977                va_end (ap);
    1978              }
    1979  
    1980            if (errnum)
    1981              {
    1982                char buf[200];
    1983  
    1984  #ifdef _LIBC
    1985                __fxprintf (stream, ": %s",
    1986                            __strerror_r (errnum, buf, sizeof (buf)));
    1987  #else
    1988                char const *s = NULL;
    1989                putc_unlocked (':', stream);
    1990                putc_unlocked (' ', stream);
    1991  # if GNULIB_STRERROR_R_POSIX || HAVE_DECL_STRERROR_R
    1992  #  if !GNULIB_STRERROR_R_POSIX && STRERROR_R_CHAR_P
    1993                s = __strerror_r (errnum, buf, sizeof buf);
    1994  #  else
    1995                if (__strerror_r (errnum, buf, sizeof buf) == 0)
    1996                  s = buf;
    1997  #  endif
    1998  # endif
    1999                if (! s && ! (s = strerror (errnum)))
    2000                  s = dgettext (state->root_argp->argp_domain,
    2001                                "Unknown system error");
    2002                fputs_unlocked (s, stream);
    2003  #endif
    2004              }
    2005  
    2006  #if _LIBC
    2007            if (_IO_fwide (stream, 0) > 0)
    2008              putwc_unlocked (L'\n', stream);
    2009            else
    2010  #endif
    2011              putc_unlocked ('\n', stream);
    2012  
    2013  #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
    2014            __funlockfile (stream);
    2015  #endif
    2016  
    2017            if (status && (!state || !(state->flags & ARGP_NO_EXIT)))
    2018              exit (status);
    2019          }
    2020      }
    2021  }
    2022  #ifdef weak_alias
    2023  weak_alias (__argp_failure, argp_failure)
    2024  #endif