root/maint/gnulib/lib/argp-help.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. validate_uparams
  2. fill_in_uparams
  3. find_char
  4. make_hol
  5. hol_add_cluster
  6. hol_free
  7. hol_entry_short_iterate
  8. hol_entry_long_iterate
  9. until_short
  10. hol_entry_first_short
  11. hol_entry_first_long
  12. hol_find_entry
  13. hol_set_group
  14. group_cmp
  15. hol_sibling_cluster_cmp
  16. hol_cousin_cluster_cmp
  17. hol_cluster_cmp
  18. hol_cluster_base
  19. canon_doc_option
  20. hol_entry_cmp
  21. hol_entry_qcmp
  22. hol_sort
  23. hol_append
  24. argp_hol
  25. indent_to
  26. space
  27. arg
  28. filter_doc
  29. print_header
  30. hol_cluster_is_child
  31. comma
  32. hol_entry_help
  33. hol_help
  34. add_argless_short_opt
  35. usage_argful_short_opt
  36. usage_long_opt
  37. hol_usage
  38. argp_args_levels
  39. argp_args_usage
  40. argp_doc
  41. _help
  42. __argp_help
  43. weak_alias
  44. __argp_state_help
  45. weak_alias
  46. weak_alias

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

/* [previous][next][first][last][top][bottom][index][help] */