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