Back to index

glibc  2.9
argp-help.c
Go to the documentation of this file.
00001 /* Hierarchial argument parsing help output
00002    Copyright (C) 1995-2003, 2004, 2005, 2006, 2007
00003    Free Software Foundation, Inc.
00004    This file is part of the GNU C Library.
00005    Written by Miles Bader <miles@gnu.ai.mit.edu>.
00006 
00007    The GNU C Library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Lesser General Public
00009    License as published by the Free Software Foundation; either
00010    version 2.1 of the License, or (at your option) any later version.
00011 
00012    The GNU C Library is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015    Lesser General Public License for more details.
00016 
00017    You should have received a copy of the GNU Lesser General Public
00018    License along with the GNU C Library; if not, write to the Free
00019    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00020    02111-1307 USA.  */
00021 
00022 #ifndef _GNU_SOURCE
00023 # define _GNU_SOURCE 1
00024 #endif
00025 
00026 #ifdef HAVE_CONFIG_H
00027 #include <config.h>
00028 #endif
00029 
00030 /* AIX requires this to be the first thing in the file.  */
00031 #ifndef __GNUC__
00032 # if HAVE_ALLOCA_H || defined _LIBC
00033 #  include <alloca.h>
00034 # else
00035 #  ifdef _AIX
00036 #pragma alloca
00037 #  else
00038 #   ifndef alloca /* predefined by HP cc +Olibcalls */
00039 char *alloca ();
00040 #   endif
00041 #  endif
00042 # endif
00043 #endif
00044 
00045 #include <stddef.h>
00046 #include <stdlib.h>
00047 #include <string.h>
00048 #include <assert.h>
00049 #include <stdarg.h>
00050 #include <ctype.h>
00051 #include <limits.h>
00052 #ifdef _LIBC
00053 # include <../libio/libioP.h>
00054 # include <wchar.h>
00055 #endif
00056 
00057 #ifndef _
00058 /* This is for other GNU distributions with internationalized messages.  */
00059 # if defined HAVE_LIBINTL_H || defined _LIBC
00060 #  include <libintl.h>
00061 #  ifdef _LIBC
00062 #   undef dgettext
00063 #   define dgettext(domain, msgid) \
00064   INTUSE(__dcgettext) (domain, msgid, LC_MESSAGES)
00065 #  endif
00066 # else
00067 #  define dgettext(domain, msgid) (msgid)
00068 # endif
00069 #endif
00070 
00071 #ifndef _LIBC
00072 # if HAVE_STRERROR_R
00073 #  if !HAVE_DECL_STRERROR_R
00074 char *strerror_r (int errnum, char *buf, size_t buflen);
00075 #  endif
00076 # else
00077 #  if !HAVE_DECL_STRERROR
00078 char *strerror (int errnum);
00079 #  endif
00080 # endif
00081 #endif
00082 
00083 #include "argp.h"
00084 #include "argp-fmtstream.h"
00085 #include "argp-namefrob.h"
00086 
00087 #ifndef SIZE_MAX
00088 # define SIZE_MAX ((size_t) -1)
00089 #endif
00090 
00091 /* User-selectable (using an environment variable) formatting parameters.
00092 
00093    These may be specified in an environment variable called `ARGP_HELP_FMT',
00094    with a contents like:  VAR1=VAL1,VAR2=VAL2,BOOLVAR2,no-BOOLVAR2
00095    Where VALn must be a positive integer.  The list of variables is in the
00096    UPARAM_NAMES vector, below.  */
00097 
00098 /* Default parameters.  */
00099 #define DUP_ARGS      0            /* True if option argument can be duplicated. */
00100 #define DUP_ARGS_NOTE 1            /* True to print a note about duplicate args. */
00101 #define SHORT_OPT_COL 2            /* column in which short options start */
00102 #define LONG_OPT_COL  6            /* column in which long options start */
00103 #define DOC_OPT_COL   2            /* column in which doc options start */
00104 #define OPT_DOC_COL  29            /* column in which option text starts */
00105 #define HEADER_COL    1            /* column in which group headers are printed */
00106 #define USAGE_INDENT 12            /* indentation of wrapped usage lines */
00107 #define RMARGIN      79            /* right margin used for wrapping */
00108 
00109 /* User-selectable (using an environment variable) formatting parameters.
00110    They must all be of type `int' for the parsing code to work.  */
00111 struct uparams
00112 {
00113   /* If true, arguments for an option are shown with both short and long
00114      options, even when a given option has both, e.g. `-x ARG, --longx=ARG'.
00115      If false, then if an option has both, the argument is only shown with
00116      the long one, e.g., `-x, --longx=ARG', and a message indicating that
00117      this really means both is printed below the options.  */
00118   int dup_args;
00119 
00120   /* This is true if when DUP_ARGS is false, and some duplicate arguments have
00121      been suppressed, an explanatory message should be printed.  */
00122   int dup_args_note;
00123 
00124   /* Various output columns.  */
00125   int short_opt_col;
00126   int long_opt_col;
00127   int doc_opt_col;
00128   int opt_doc_col;
00129   int header_col;
00130   int usage_indent;
00131   int rmargin;
00132 };
00133 
00134 /* This is a global variable, as user options are only ever read once.  */
00135 static struct uparams uparams = {
00136   DUP_ARGS, DUP_ARGS_NOTE,
00137   SHORT_OPT_COL, LONG_OPT_COL, DOC_OPT_COL, OPT_DOC_COL, HEADER_COL,
00138   USAGE_INDENT, RMARGIN
00139 };
00140 
00141 /* A particular uparam, and what the user name is.  */
00142 struct uparam_name
00143 {
00144   const char name[14];             /* User name.  */
00145   bool is_bool;                    /* Whether it's `boolean'.  */
00146   uint8_t uparams_offs;            /* Location of the (int) field in UPARAMS.  */
00147 };
00148 
00149 /* The name-field mappings we know about.  */
00150 static const struct uparam_name uparam_names[] =
00151 {
00152   { "dup-args",       true, offsetof (struct uparams, dup_args) },
00153   { "dup-args-note",  true, offsetof (struct uparams, dup_args_note) },
00154   { "short-opt-col",  false, offsetof (struct uparams, short_opt_col) },
00155   { "long-opt-col",   false, offsetof (struct uparams, long_opt_col) },
00156   { "doc-opt-col",    false, offsetof (struct uparams, doc_opt_col) },
00157   { "opt-doc-col",    false, offsetof (struct uparams, opt_doc_col) },
00158   { "header-col",     false, offsetof (struct uparams, header_col) },
00159   { "usage-indent",   false, offsetof (struct uparams, usage_indent) },
00160   { "rmargin",        false, offsetof (struct uparams, rmargin) }
00161 };
00162 #define nuparam_names (sizeof (uparam_names) / sizeof (uparam_names[0]))
00163 
00164 /* Read user options from the environment, and fill in UPARAMS appropiately.  */
00165 static void
00166 fill_in_uparams (const struct argp_state *state)
00167 {
00168   const char *var = getenv ("ARGP_HELP_FMT");
00169 
00170 #define SKIPWS(p) do { while (isspace (*p)) p++; } while (0);
00171 
00172   if (var)
00173     /* Parse var. */
00174     while (*var)
00175       {
00176        SKIPWS (var);
00177 
00178        if (isalpha (*var))
00179          {
00180            size_t var_len;
00181            const struct uparam_name *un;
00182            int unspec = 0, val = 0;
00183            const char *arg = var;
00184 
00185            while (isalnum (*arg) || *arg == '-' || *arg == '_')
00186              arg++;
00187            var_len = arg - var;
00188 
00189            SKIPWS (arg);
00190 
00191            if (*arg == '\0' || *arg == ',')
00192              unspec = 1;
00193            else if (*arg == '=')
00194              {
00195               arg++;
00196               SKIPWS (arg);
00197              }
00198 
00199            if (unspec)
00200              {
00201               if (var[0] == 'n' && var[1] == 'o' && var[2] == '-')
00202                 {
00203                   val = 0;
00204                   var += 3;
00205                   var_len -= 3;
00206                 }
00207               else
00208                 val = 1;
00209              }
00210            else if (isdigit (*arg))
00211              {
00212               val = atoi (arg);
00213               while (isdigit (*arg))
00214                 arg++;
00215               SKIPWS (arg);
00216              }
00217 
00218            un = uparam_names;
00219            size_t u;
00220            for (u = 0; u < nuparam_names; ++un, ++u)
00221              if (strlen (un->name) == var_len
00222                 && strncmp (var, un->name, var_len) == 0)
00223               {
00224                 if (unspec && !un->is_bool)
00225                   __argp_failure (state, 0, 0,
00226                                 dgettext (state == NULL ? NULL
00227                                          : state->root_argp->argp_domain,
00228                                          "\
00229 %.*s: ARGP_HELP_FMT parameter requires a value"),
00230                                 (int) var_len, var);
00231                 else
00232                   *(int *)((char *)&uparams + un->uparams_offs) = val;
00233                 break;
00234               }
00235            if (u == nuparam_names)
00236              __argp_failure (state, 0, 0,
00237                            dgettext (state == NULL ? NULL
00238                                    : state->root_argp->argp_domain, "\
00239 %.*s: Unknown ARGP_HELP_FMT parameter"),
00240                            (int) var_len, var);
00241 
00242            var = arg;
00243            if (*var == ',')
00244              var++;
00245          }
00246        else if (*var)
00247          {
00248            __argp_failure (state, 0, 0,
00249                          dgettext (state == NULL ? NULL
00250                                   : state->root_argp->argp_domain,
00251                                   "Garbage in ARGP_HELP_FMT: %s"), var);
00252            break;
00253          }
00254       }
00255 }
00256 
00257 /* Returns true if OPT hasn't been marked invisible.  Visibility only affects
00258    whether OPT is displayed or used in sorting, not option shadowing.  */
00259 #define ovisible(opt) (! ((opt)->flags & OPTION_HIDDEN))
00260 
00261 /* Returns true if OPT is an alias for an earlier option.  */
00262 #define oalias(opt) ((opt)->flags & OPTION_ALIAS)
00263 
00264 /* Returns true if OPT is an documentation-only entry.  */
00265 #define odoc(opt) ((opt)->flags & OPTION_DOC)
00266 
00267 /* Returns true if OPT is the end-of-list marker for a list of options.  */
00268 #define oend(opt) __option_is_end (opt)
00269 
00270 /* Returns true if OPT has a short option.  */
00271 #define oshort(opt) __option_is_short (opt)
00272 
00273 /*
00274    The help format for a particular option is like:
00275 
00276      -xARG, -yARG, --long1=ARG, --long2=ARG        Documentation...
00277 
00278    Where ARG will be omitted if there's no argument, for this option, or
00279    will be surrounded by "[" and "]" appropiately if the argument is
00280    optional.  The documentation string is word-wrapped appropiately, and if
00281    the list of options is long enough, it will be started on a separate line.
00282    If there are no short options for a given option, the first long option is
00283    indented slighly in a way that's supposed to make most long options appear
00284    to be in a separate column.
00285 
00286    For example, the following output (from ps):
00287 
00288      -p PID, --pid=PID          List the process PID
00289         --pgrp=PGRP            List processes in the process group PGRP
00290      -P, -x, --no-parent        Include processes without parents
00291      -Q, --all-fields           Don't elide unusable fields (normally if there's
00292                             some reason ps can't print a field for any
00293                             process, it's removed from the output entirely)
00294      -r, --reverse, --gratuitously-long-reverse-option
00295                             Reverse the order of any sort
00296         --session[=SID]        Add the processes from the session SID (which
00297                             defaults to the sid of the current process)
00298 
00299     Here are some more options:
00300      -f ZOT, --foonly=ZOT       Glork a foonly
00301      -z, --zaza                 Snit a zar
00302 
00303      -?, --help                 Give this help list
00304         --usage                Give a short usage message
00305      -V, --version              Print program version
00306 
00307    The struct argp_option array for the above could look like:
00308 
00309    {
00310      {"pid",       'p',      "PID",  0, "List the process PID"},
00311      {"pgrp",      OPT_PGRP, "PGRP", 0, "List processes in the process group PGRP"},
00312      {"no-parent", 'P',           0,     0, "Include processes without parents"},
00313      {0,           'x',       0,     OPTION_ALIAS},
00314      {"all-fields",'Q',       0,     0, "Don't elide unusable fields (normally"
00315                                         " if there's some reason ps can't"
00316                                    " print a field for any process, it's"
00317                                         " removed from the output entirely)" },
00318      {"reverse",   'r',       0,     0, "Reverse the order of any sort"},
00319      {"gratuitously-long-reverse-option", 0, 0, OPTION_ALIAS},
00320      {"session",   OPT_SESS,  "SID", OPTION_ARG_OPTIONAL,
00321                                         "Add the processes from the session"
00322                                    " SID (which defaults to the sid of"
00323                                    " the current process)" },
00324 
00325      {0,0,0,0, "Here are some more options:"},
00326      {"foonly", 'f', "ZOT", 0, "Glork a foonly"},
00327      {"zaza", 'z', 0, 0, "Snit a zar"},
00328 
00329      {0}
00330    }
00331 
00332    Note that the last three options are automatically supplied by argp_parse,
00333    unless you tell it not to with ARGP_NO_HELP.
00334 
00335 */
00336 
00337 /* Returns true if CH occurs between BEG and END.  */
00338 static int
00339 find_char (char ch, char *beg, char *end)
00340 {
00341   while (beg < end)
00342     if (*beg == ch)
00343       return 1;
00344     else
00345       beg++;
00346   return 0;
00347 }
00348 
00349 struct hol_cluster;         /* fwd decl */
00350 
00351 struct hol_entry
00352 {
00353   /* First option.  */
00354   const struct argp_option *opt;
00355   /* Number of options (including aliases).  */
00356   unsigned num;
00357 
00358   /* A pointers into the HOL's short_options field, to the first short option
00359      letter for this entry.  The order of the characters following this point
00360      corresponds to the order of options pointed to by OPT, and there are at
00361      most NUM.  A short option recorded in a option following OPT is only
00362      valid if it occurs in the right place in SHORT_OPTIONS (otherwise it's
00363      probably been shadowed by some other entry).  */
00364   char *short_options;
00365 
00366   /* Entries are sorted by their group first, in the order:
00367        1, 2, ..., n, 0, -m, ..., -2, -1
00368      and then alphabetically within each group.  The default is 0.  */
00369   int group;
00370 
00371   /* The cluster of options this entry belongs to, or 0 if none.  */
00372   struct hol_cluster *cluster;
00373 
00374   /* The argp from which this option came.  */
00375   const struct argp *argp;
00376 };
00377 
00378 /* A cluster of entries to reflect the argp tree structure.  */
00379 struct hol_cluster
00380 {
00381   /* A descriptive header printed before options in this cluster.  */
00382   const char *header;
00383 
00384   /* Used to order clusters within the same group with the same parent,
00385      according to the order in which they occurred in the parent argp's child
00386      list.  */
00387   int index;
00388 
00389   /* How to sort this cluster with respect to options and other clusters at the
00390      same depth (clusters always follow options in the same group).  */
00391   int group;
00392 
00393   /* The cluster to which this cluster belongs, or 0 if it's at the base
00394      level.  */
00395   struct hol_cluster *parent;
00396 
00397   /* The argp from which this cluster is (eventually) derived.  */
00398   const struct argp *argp;
00399 
00400   /* The distance this cluster is from the root.  */
00401   int depth;
00402 
00403   /* Clusters in a given hol are kept in a linked list, to make freeing them
00404      possible.  */
00405   struct hol_cluster *next;
00406 };
00407 
00408 /* A list of options for help.  */
00409 struct hol
00410 {
00411   /* An array of hol_entry's.  */
00412   struct hol_entry *entries;
00413   /* The number of entries in this hol.  If this field is zero, the others
00414      are undefined.  */
00415   unsigned num_entries;
00416 
00417   /* A string containing all short options in this HOL.  Each entry contains
00418      pointers into this string, so the order can't be messed with blindly.  */
00419   char *short_options;
00420 
00421   /* Clusters of entries in this hol.  */
00422   struct hol_cluster *clusters;
00423 };
00424 
00425 /* Create a struct hol from the options in ARGP.  CLUSTER is the
00426    hol_cluster in which these entries occur, or 0, if at the root.  */
00427 static struct hol *
00428 make_hol (const struct argp *argp, struct hol_cluster *cluster)
00429 {
00430   char *so;
00431   const struct argp_option *o;
00432   const struct argp_option *opts = argp->options;
00433   struct hol_entry *entry;
00434   unsigned num_short_options = 0;
00435   struct hol *hol = malloc (sizeof (struct hol));
00436 
00437   assert (hol);
00438 
00439   hol->num_entries = 0;
00440   hol->clusters = 0;
00441 
00442   if (opts)
00443     {
00444       int cur_group = 0;
00445 
00446       /* The first option must not be an alias.  */
00447       assert (! oalias (opts));
00448 
00449       /* Calculate the space needed.  */
00450       for (o = opts; ! oend (o); o++)
00451        {
00452          if (! oalias (o))
00453            hol->num_entries++;
00454          if (oshort (o))
00455            num_short_options++;    /* This is an upper bound.  */
00456        }
00457 
00458       hol->entries = malloc (sizeof (struct hol_entry) * hol->num_entries);
00459       hol->short_options = malloc (num_short_options + 1);
00460 
00461       assert (hol->entries && hol->short_options);
00462 #if SIZE_MAX <= UINT_MAX
00463       assert (hol->num_entries <= SIZE_MAX / sizeof (struct hol_entry));
00464 #endif
00465 
00466       /* Fill in the entries.  */
00467       so = hol->short_options;
00468       for (o = opts, entry = hol->entries; ! oend (o); entry++)
00469        {
00470          entry->opt = o;
00471          entry->num = 0;
00472          entry->short_options = so;
00473          entry->group = cur_group =
00474            o->group
00475            ? o->group
00476            : ((!o->name && !o->key)
00477               ? cur_group + 1
00478               : cur_group);
00479          entry->cluster = cluster;
00480          entry->argp = argp;
00481 
00482          do
00483            {
00484              entry->num++;
00485              if (oshort (o) && ! find_char (o->key, hol->short_options, so))
00486               /* O has a valid short option which hasn't already been used.*/
00487               *so++ = o->key;
00488              o++;
00489            }
00490          while (! oend (o) && oalias (o));
00491        }
00492       *so = '\0';           /* null terminated so we can find the length */
00493     }
00494 
00495   return hol;
00496 }
00497 
00498 /* Add a new cluster to HOL, with the given GROUP and HEADER (taken from the
00499    associated argp child list entry), INDEX, and PARENT, and return a pointer
00500    to it.  ARGP is the argp that this cluster results from.  */
00501 static struct hol_cluster *
00502 hol_add_cluster (struct hol *hol, int group, const char *header, int index,
00503                struct hol_cluster *parent, const struct argp *argp)
00504 {
00505   struct hol_cluster *cl = malloc (sizeof (struct hol_cluster));
00506   if (cl)
00507     {
00508       cl->group = group;
00509       cl->header = header;
00510 
00511       cl->index = index;
00512       cl->parent = parent;
00513       cl->argp = argp;
00514       cl->depth = parent ? parent->depth + 1 : 0;
00515 
00516       cl->next = hol->clusters;
00517       hol->clusters = cl;
00518     }
00519   return cl;
00520 }
00521 
00522 /* Free HOL and any resources it uses.  */
00523 static void
00524 hol_free (struct hol *hol)
00525 {
00526   struct hol_cluster *cl = hol->clusters;
00527 
00528   while (cl)
00529     {
00530       struct hol_cluster *next = cl->next;
00531       free (cl);
00532       cl = next;
00533     }
00534 
00535   if (hol->num_entries > 0)
00536     {
00537       free (hol->entries);
00538       free (hol->short_options);
00539     }
00540 
00541   free (hol);
00542 }
00543 
00544 static int
00545 hol_entry_short_iterate (const struct hol_entry *entry,
00546                       int (*func)(const struct argp_option *opt,
00547                                  const struct argp_option *real,
00548                                  const char *domain, void *cookie),
00549                       const char *domain, void *cookie)
00550 {
00551   unsigned nopts;
00552   int val = 0;
00553   const struct argp_option *opt, *real = entry->opt;
00554   char *so = entry->short_options;
00555 
00556   for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--)
00557     if (oshort (opt) && *so == opt->key)
00558       {
00559        if (!oalias (opt))
00560          real = opt;
00561        if (ovisible (opt))
00562          val = (*func)(opt, real, domain, cookie);
00563        so++;
00564       }
00565 
00566   return val;
00567 }
00568 
00569 static inline int
00570 __attribute__ ((always_inline))
00571 hol_entry_long_iterate (const struct hol_entry *entry,
00572                      int (*func)(const struct argp_option *opt,
00573                                 const struct argp_option *real,
00574                                 const char *domain, void *cookie),
00575                      const char *domain, void *cookie)
00576 {
00577   unsigned nopts;
00578   int val = 0;
00579   const struct argp_option *opt, *real = entry->opt;
00580 
00581   for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--)
00582     if (opt->name)
00583       {
00584        if (!oalias (opt))
00585          real = opt;
00586        if (ovisible (opt))
00587          val = (*func)(opt, real, domain, cookie);
00588       }
00589 
00590   return val;
00591 }
00592 
00593 /* Iterator that returns true for the first short option.  */
00594 static inline int
00595 until_short (const struct argp_option *opt, const struct argp_option *real,
00596             const char *domain, void *cookie)
00597 {
00598   return oshort (opt) ? opt->key : 0;
00599 }
00600 
00601 /* Returns the first valid short option in ENTRY, or 0 if there is none.  */
00602 static char
00603 hol_entry_first_short (const struct hol_entry *entry)
00604 {
00605   return hol_entry_short_iterate (entry, until_short,
00606                               entry->argp->argp_domain, 0);
00607 }
00608 
00609 /* Returns the first valid long option in ENTRY, or 0 if there is none.  */
00610 static const char *
00611 hol_entry_first_long (const struct hol_entry *entry)
00612 {
00613   const struct argp_option *opt;
00614   unsigned num;
00615   for (opt = entry->opt, num = entry->num; num > 0; opt++, num--)
00616     if (opt->name && ovisible (opt))
00617       return opt->name;
00618   return 0;
00619 }
00620 
00621 /* Returns the entry in HOL with the long option name NAME, or 0 if there is
00622    none.  */
00623 static struct hol_entry *
00624 hol_find_entry (struct hol *hol, const char *name)
00625 {
00626   struct hol_entry *entry = hol->entries;
00627   unsigned num_entries = hol->num_entries;
00628 
00629   while (num_entries-- > 0)
00630     {
00631       const struct argp_option *opt = entry->opt;
00632       unsigned num_opts = entry->num;
00633 
00634       while (num_opts-- > 0)
00635        if (opt->name && ovisible (opt) && strcmp (opt->name, name) == 0)
00636          return entry;
00637        else
00638          opt++;
00639 
00640       entry++;
00641     }
00642 
00643   return 0;
00644 }
00645 
00646 /* If an entry with the long option NAME occurs in HOL, set it's special
00647    sort position to GROUP.  */
00648 static void
00649 hol_set_group (struct hol *hol, const char *name, int group)
00650 {
00651   struct hol_entry *entry = hol_find_entry (hol, name);
00652   if (entry)
00653     entry->group = group;
00654 }
00655 
00656 /* Order by group:  0, 1, 2, ..., n, -m, ..., -2, -1.
00657    EQ is what to return if GROUP1 and GROUP2 are the same.  */
00658 static int
00659 group_cmp (int group1, int group2, int eq)
00660 {
00661   if (group1 == group2)
00662     return eq;
00663   else if ((group1 < 0 && group2 < 0) || (group1 >= 0 && group2 >= 0))
00664     return group1 - group2;
00665   else
00666     return group2 - group1;
00667 }
00668 
00669 /* Compare clusters CL1 & CL2 by the order that they should appear in
00670    output.  */
00671 static int
00672 hol_cluster_cmp (const struct hol_cluster *cl1, const struct hol_cluster *cl2)
00673 {
00674   /* If one cluster is deeper than the other, use its ancestor at the same
00675      level, so that finding the common ancestor is straightforward.  */
00676   while (cl1->depth > cl2->depth)
00677     cl1 = cl1->parent;
00678   while (cl2->depth > cl1->depth)
00679     cl2 = cl2->parent;
00680 
00681   /* Now reduce both clusters to their ancestors at the point where both have
00682      a common parent; these can be directly compared.  */
00683   while (cl1->parent != cl2->parent)
00684     cl1 = cl1->parent, cl2 = cl2->parent;
00685 
00686   return group_cmp (cl1->group, cl2->group, cl2->index - cl1->index);
00687 }
00688 
00689 /* Return the ancestor of CL that's just below the root (i.e., has a parent
00690    of 0).  */
00691 static struct hol_cluster *
00692 hol_cluster_base (struct hol_cluster *cl)
00693 {
00694   while (cl->parent)
00695     cl = cl->parent;
00696   return cl;
00697 }
00698 
00699 /* Return true if CL1 is a child of CL2.  */
00700 static int
00701 hol_cluster_is_child (const struct hol_cluster *cl1,
00702                     const struct hol_cluster *cl2)
00703 {
00704   while (cl1 && cl1 != cl2)
00705     cl1 = cl1->parent;
00706   return cl1 == cl2;
00707 }
00708 
00709 /* Given the name of a OPTION_DOC option, modifies NAME to start at the tail
00710    that should be used for comparisons, and returns true iff it should be
00711    treated as a non-option.  */
00712 static int
00713 canon_doc_option (const char **name)
00714 {
00715   int non_opt;
00716   /* Skip initial whitespace.  */
00717   while (isspace (**name))
00718     (*name)++;
00719   /* Decide whether this looks like an option (leading `-') or not.  */
00720   non_opt = (**name != '-');
00721   /* Skip until part of name used for sorting.  */
00722   while (**name && !isalnum (**name))
00723     (*name)++;
00724   return non_opt;
00725 }
00726 
00727 /* Order ENTRY1 & ENTRY2 by the order which they should appear in a help
00728    listing.  */
00729 static int
00730 hol_entry_cmp (const struct hol_entry *entry1,
00731               const struct hol_entry *entry2)
00732 {
00733   /* The group numbers by which the entries should be ordered; if either is
00734      in a cluster, then this is just the group within the cluster.  */
00735   int group1 = entry1->group, group2 = entry2->group;
00736 
00737   if (entry1->cluster != entry2->cluster)
00738     {
00739       /* The entries are not within the same cluster, so we can't compare them
00740         directly, we have to use the appropiate clustering level too.  */
00741       if (! entry1->cluster)
00742        /* ENTRY1 is at the `base level', not in a cluster, so we have to
00743           compare it's group number with that of the base cluster in which
00744           ENTRY2 resides.  Note that if they're in the same group, the
00745           clustered option always comes laster.  */
00746        return group_cmp (group1, hol_cluster_base (entry2->cluster)->group, -1);
00747       else if (! entry2->cluster)
00748        /* Likewise, but ENTRY2's not in a cluster.  */
00749        return group_cmp (hol_cluster_base (entry1->cluster)->group, group2, 1);
00750       else
00751        /* Both entries are in clusters, we can just compare the clusters.  */
00752        return hol_cluster_cmp (entry1->cluster, entry2->cluster);
00753     }
00754   else if (group1 == group2)
00755     /* The entries are both in the same cluster and group, so compare them
00756        alphabetically.  */
00757     {
00758       int short1 = hol_entry_first_short (entry1);
00759       int short2 = hol_entry_first_short (entry2);
00760       int doc1 = odoc (entry1->opt);
00761       int doc2 = odoc (entry2->opt);
00762       const char *long1 = hol_entry_first_long (entry1);
00763       const char *long2 = hol_entry_first_long (entry2);
00764 
00765       if (doc1)
00766        doc1 = long1 != NULL && canon_doc_option (&long1);
00767       if (doc2)
00768        doc2 = long2 != NULL && canon_doc_option (&long2);
00769 
00770       if (doc1 != doc2)
00771        /* `documentation' options always follow normal options (or
00772           documentation options that *look* like normal options).  */
00773        return doc1 - doc2;
00774       else if (!short1 && !short2 && long1 && long2)
00775        /* Only long options.  */
00776        return __strcasecmp (long1, long2);
00777       else
00778        /* Compare short/short, long/short, short/long, using the first
00779           character of long options.  Entries without *any* valid
00780           options (such as options with OPTION_HIDDEN set) will be put
00781           first, but as they're not displayed, it doesn't matter where
00782           they are.  */
00783        {
00784          char first1 = short1 ? short1 : long1 ? *long1 : 0;
00785          char first2 = short2 ? short2 : long2 ? *long2 : 0;
00786 #ifdef _tolower
00787          int lower_cmp = _tolower (first1) - _tolower (first2);
00788 #else
00789          int lower_cmp = tolower (first1) - tolower (first2);
00790 #endif
00791          /* Compare ignoring case, except when the options are both the
00792             same letter, in which case lower-case always comes first.  */
00793          return lower_cmp ? lower_cmp : first2 - first1;
00794        }
00795     }
00796   else
00797     /* Within the same cluster, but not the same group, so just compare
00798        groups.  */
00799     return group_cmp (group1, group2, 0);
00800 }
00801 
00802 /* Version of hol_entry_cmp with correct signature for qsort.  */
00803 static int
00804 hol_entry_qcmp (const void *entry1_v, const void *entry2_v)
00805 {
00806   return hol_entry_cmp (entry1_v, entry2_v);
00807 }
00808 
00809 /* Sort HOL by group and alphabetically by option name (with short options
00810    taking precedence over long).  Since the sorting is for display purposes
00811    only, the shadowing of options isn't effected.  */
00812 static void
00813 hol_sort (struct hol *hol)
00814 {
00815   if (hol->num_entries > 0)
00816     qsort (hol->entries, hol->num_entries, sizeof (struct hol_entry),
00817           hol_entry_qcmp);
00818 }
00819 
00820 /* Append MORE to HOL, destroying MORE in the process.  Options in HOL shadow
00821    any in MORE with the same name.  */
00822 static void
00823 hol_append (struct hol *hol, struct hol *more)
00824 {
00825   struct hol_cluster **cl_end = &hol->clusters;
00826 
00827   /* Steal MORE's cluster list, and add it to the end of HOL's.  */
00828   while (*cl_end)
00829     cl_end = &(*cl_end)->next;
00830   *cl_end = more->clusters;
00831   more->clusters = 0;
00832 
00833   /* Merge entries.  */
00834   if (more->num_entries > 0)
00835     {
00836       if (hol->num_entries == 0)
00837        {
00838          hol->num_entries = more->num_entries;
00839          hol->entries = more->entries;
00840          hol->short_options = more->short_options;
00841          more->num_entries = 0;    /* Mark MORE's fields as invalid.  */
00842        }
00843       else
00844        /* Append the entries in MORE to those in HOL, taking care to only add
00845           non-shadowed SHORT_OPTIONS values.  */
00846        {
00847          unsigned left;
00848          char *so, *more_so;
00849          struct hol_entry *e;
00850          unsigned num_entries = hol->num_entries + more->num_entries;
00851          struct hol_entry *entries =
00852            malloc (num_entries * sizeof (struct hol_entry));
00853          unsigned hol_so_len = strlen (hol->short_options);
00854          char *short_options =
00855            malloc (hol_so_len + strlen (more->short_options) + 1);
00856 
00857          assert (entries && short_options);
00858 #if SIZE_MAX <= UINT_MAX
00859          assert (num_entries <= SIZE_MAX / sizeof (struct hol_entry));
00860 #endif
00861 
00862          __mempcpy (__mempcpy (entries, hol->entries,
00863                             hol->num_entries * sizeof (struct hol_entry)),
00864                    more->entries,
00865                    more->num_entries * sizeof (struct hol_entry));
00866 
00867          __mempcpy (short_options, hol->short_options, hol_so_len);
00868 
00869          /* Fix up the short options pointers from HOL.  */
00870          for (e = entries, left = hol->num_entries; left > 0; e++, left--)
00871            e->short_options += (short_options - hol->short_options);
00872 
00873          /* Now add the short options from MORE, fixing up its entries
00874             too.  */
00875          so = short_options + hol_so_len;
00876          more_so = more->short_options;
00877          for (left = more->num_entries; left > 0; e++, left--)
00878            {
00879              int opts_left;
00880              const struct argp_option *opt;
00881 
00882              e->short_options = so;
00883 
00884              for (opts_left = e->num, opt = e->opt; opts_left; opt++, opts_left--)
00885               {
00886                 int ch = *more_so;
00887                 if (oshort (opt) && ch == opt->key)
00888                   /* The next short option in MORE_SO, CH, is from OPT.  */
00889                   {
00890                     if (! find_char (ch, short_options,
00891                                    short_options + hol_so_len))
00892                      /* The short option CH isn't shadowed by HOL's options,
00893                         so add it to the sum.  */
00894                      *so++ = ch;
00895                     more_so++;
00896                   }
00897               }
00898            }
00899 
00900          *so = '\0';
00901 
00902          free (hol->entries);
00903          free (hol->short_options);
00904 
00905          hol->entries = entries;
00906          hol->num_entries = num_entries;
00907          hol->short_options = short_options;
00908        }
00909     }
00910 
00911   hol_free (more);
00912 }
00913 
00914 /* Inserts enough spaces to make sure STREAM is at column COL.  */
00915 static void
00916 indent_to (argp_fmtstream_t stream, unsigned col)
00917 {
00918   int needed = col - __argp_fmtstream_point (stream);
00919   while (needed-- > 0)
00920     __argp_fmtstream_putc (stream, ' ');
00921 }
00922 
00923 /* Output to STREAM either a space, or a newline if there isn't room for at
00924    least ENSURE characters before the right margin.  */
00925 static void
00926 space (argp_fmtstream_t stream, size_t ensure)
00927 {
00928   if (__argp_fmtstream_point (stream) + ensure
00929       >= __argp_fmtstream_rmargin (stream))
00930     __argp_fmtstream_putc (stream, '\n');
00931   else
00932     __argp_fmtstream_putc (stream, ' ');
00933 }
00934 
00935 /* If the option REAL has an argument, we print it in using the printf
00936    format REQ_FMT or OPT_FMT depending on whether it's a required or
00937    optional argument.  */
00938 static void
00939 arg (const struct argp_option *real, const char *req_fmt, const char *opt_fmt,
00940      const char *domain, argp_fmtstream_t stream)
00941 {
00942   if (real->arg)
00943     {
00944       if (real->flags & OPTION_ARG_OPTIONAL)
00945        __argp_fmtstream_printf (stream, opt_fmt,
00946                              dgettext (domain, real->arg));
00947       else
00948        __argp_fmtstream_printf (stream, req_fmt,
00949                              dgettext (domain, real->arg));
00950     }
00951 }
00952 
00953 /* Helper functions for hol_entry_help.  */
00954 
00955 /* State used during the execution of hol_help.  */
00956 struct hol_help_state
00957 {
00958   /* PREV_ENTRY should contain the previous entry printed, or 0.  */
00959   struct hol_entry *prev_entry;
00960 
00961   /* If an entry is in a different group from the previous one, and SEP_GROUPS
00962      is true, then a blank line will be printed before any output. */
00963   int sep_groups;
00964 
00965   /* True if a duplicate option argument was suppressed (only ever set if
00966      UPARAMS.dup_args is false).  */
00967   int suppressed_dup_arg;
00968 };
00969 
00970 /* Some state used while printing a help entry (used to communicate with
00971    helper functions).  See the doc for hol_entry_help for more info, as most
00972    of the fields are copied from its arguments.  */
00973 struct pentry_state
00974 {
00975   const struct hol_entry *entry;
00976   argp_fmtstream_t stream;
00977   struct hol_help_state *hhstate;
00978 
00979   /* True if nothing's been printed so far.  */
00980   int first;
00981 
00982   /* If non-zero, the state that was used to print this help.  */
00983   const struct argp_state *state;
00984 };
00985 
00986 /* If a user doc filter should be applied to DOC, do so.  */
00987 static const char *
00988 filter_doc (const char *doc, int key, const struct argp *argp,
00989            const struct argp_state *state)
00990 {
00991   if (argp && argp->help_filter)
00992     /* We must apply a user filter to this output.  */
00993     {
00994       void *input = __argp_input (argp, state);
00995       return (*argp->help_filter) (key, doc, input);
00996     }
00997   else
00998     /* No filter.  */
00999     return doc;
01000 }
01001 
01002 /* Prints STR as a header line, with the margin lines set appropiately, and
01003    notes the fact that groups should be separated with a blank line.  ARGP is
01004    the argp that should dictate any user doc filtering to take place.  Note
01005    that the previous wrap margin isn't restored, but the left margin is reset
01006    to 0.  */
01007 static void
01008 print_header (const char *str, const struct argp *argp,
01009              struct pentry_state *pest)
01010 {
01011   const char *tstr = dgettext (argp->argp_domain, str);
01012   const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_HEADER, argp, pest->state);
01013 
01014   if (fstr)
01015     {
01016       if (*fstr)
01017        {
01018          if (pest->hhstate->prev_entry)
01019            /* Precede with a blank line.  */
01020            __argp_fmtstream_putc (pest->stream, '\n');
01021          indent_to (pest->stream, uparams.header_col);
01022          __argp_fmtstream_set_lmargin (pest->stream, uparams.header_col);
01023          __argp_fmtstream_set_wmargin (pest->stream, uparams.header_col);
01024          __argp_fmtstream_puts (pest->stream, fstr);
01025          __argp_fmtstream_set_lmargin (pest->stream, 0);
01026          __argp_fmtstream_putc (pest->stream, '\n');
01027        }
01028 
01029       pest->hhstate->sep_groups = 1; /* Separate subsequent groups. */
01030     }
01031 
01032   if (fstr != tstr)
01033     free ((char *) fstr);
01034 }
01035 
01036 /* Inserts a comma if this isn't the first item on the line, and then makes
01037    sure we're at least to column COL.  If this *is* the first item on a line,
01038    prints any pending whitespace/headers that should precede this line. Also
01039    clears FIRST.  */
01040 static void
01041 comma (unsigned col, struct pentry_state *pest)
01042 {
01043   if (pest->first)
01044     {
01045       const struct hol_entry *pe = pest->hhstate->prev_entry;
01046       const struct hol_cluster *cl = pest->entry->cluster;
01047 
01048       if (pest->hhstate->sep_groups && pe && pest->entry->group != pe->group)
01049        __argp_fmtstream_putc (pest->stream, '\n');
01050 
01051       if (cl && cl->header && *cl->header
01052          && (!pe
01053              || (pe->cluster != cl
01054                 && !hol_cluster_is_child (pe->cluster, cl))))
01055        /* If we're changing clusters, then this must be the start of the
01056           ENTRY's cluster unless that is an ancestor of the previous one
01057           (in which case we had just popped into a sub-cluster for a bit).
01058           If so, then print the cluster's header line.  */
01059        {
01060          int old_wm = __argp_fmtstream_wmargin (pest->stream);
01061          print_header (cl->header, cl->argp, pest);
01062          __argp_fmtstream_set_wmargin (pest->stream, old_wm);
01063        }
01064 
01065       pest->first = 0;
01066     }
01067   else
01068     __argp_fmtstream_puts (pest->stream, ", ");
01069 
01070   indent_to (pest->stream, col);
01071 }
01072 
01073 /* Print help for ENTRY to STREAM.  */
01074 static void
01075 hol_entry_help (struct hol_entry *entry, const struct argp_state *state,
01076               argp_fmtstream_t stream, struct hol_help_state *hhstate)
01077 {
01078   unsigned num;
01079   const struct argp_option *real = entry->opt, *opt;
01080   char *so = entry->short_options;
01081   int have_long_opt = 0;    /* We have any long options.  */
01082   /* Saved margins.  */
01083   int old_lm = __argp_fmtstream_set_lmargin (stream, 0);
01084   int old_wm = __argp_fmtstream_wmargin (stream);
01085   /* PEST is a state block holding some of our variables that we'd like to
01086      share with helper functions.  */
01087   struct pentry_state pest = { entry, stream, hhstate, 1, state };
01088 
01089   if (! odoc (real))
01090     for (opt = real, num = entry->num; num > 0; opt++, num--)
01091       if (opt->name && ovisible (opt))
01092        {
01093          have_long_opt = 1;
01094          break;
01095        }
01096 
01097   /* First emit short options.  */
01098   __argp_fmtstream_set_wmargin (stream, uparams.short_opt_col); /* For truly bizarre cases. */
01099   for (opt = real, num = entry->num; num > 0; opt++, num--)
01100     if (oshort (opt) && opt->key == *so)
01101       /* OPT has a valid (non shadowed) short option.  */
01102       {
01103        if (ovisible (opt))
01104          {
01105            comma (uparams.short_opt_col, &pest);
01106            __argp_fmtstream_putc (stream, '-');
01107            __argp_fmtstream_putc (stream, *so);
01108            if (!have_long_opt || uparams.dup_args)
01109              arg (real, " %s", "[%s]",
01110                  state == NULL ? NULL : state->root_argp->argp_domain,
01111                  stream);
01112            else if (real->arg)
01113              hhstate->suppressed_dup_arg = 1;
01114          }
01115        so++;
01116       }
01117 
01118   /* Now, long options.  */
01119   if (odoc (real))
01120     /* A `documentation' option.  */
01121     {
01122       __argp_fmtstream_set_wmargin (stream, uparams.doc_opt_col);
01123       for (opt = real, num = entry->num; num > 0; opt++, num--)
01124        if (opt->name && ovisible (opt))
01125          {
01126            comma (uparams.doc_opt_col, &pest);
01127            /* Calling gettext here isn't quite right, since sorting will
01128               have been done on the original; but documentation options
01129               should be pretty rare anyway...  */
01130            __argp_fmtstream_puts (stream,
01131                                dgettext (state == NULL ? NULL
01132                                         : state->root_argp->argp_domain,
01133                                         opt->name));
01134          }
01135     }
01136   else
01137     /* A real long option.  */
01138     {
01139       __argp_fmtstream_set_wmargin (stream, uparams.long_opt_col);
01140       for (opt = real, num = entry->num; num > 0; opt++, num--)
01141        if (opt->name && ovisible (opt))
01142          {
01143            comma (uparams.long_opt_col, &pest);
01144            __argp_fmtstream_printf (stream, "--%s", opt->name);
01145            arg (real, "=%s", "[=%s]",
01146                state == NULL ? NULL : state->root_argp->argp_domain, stream);
01147          }
01148     }
01149 
01150   /* Next, documentation strings.  */
01151   __argp_fmtstream_set_lmargin (stream, 0);
01152 
01153   if (pest.first)
01154     {
01155       /* Didn't print any switches, what's up?  */
01156       if (!oshort (real) && !real->name)
01157        /* This is a group header, print it nicely.  */
01158        print_header (real->doc, entry->argp, &pest);
01159       else
01160        /* Just a totally shadowed option or null header; print nothing.  */
01161        goto cleanup;        /* Just return, after cleaning up.  */
01162     }
01163   else
01164     {
01165       const char *tstr = real->doc ? dgettext (state == NULL ? NULL
01166                                           : state->root_argp->argp_domain,
01167                                           real->doc) : 0;
01168       const char *fstr = filter_doc (tstr, real->key, entry->argp, state);
01169       if (fstr && *fstr)
01170        {
01171          unsigned int col = __argp_fmtstream_point (stream);
01172 
01173          __argp_fmtstream_set_lmargin (stream, uparams.opt_doc_col);
01174          __argp_fmtstream_set_wmargin (stream, uparams.opt_doc_col);
01175 
01176          if (col > (unsigned int) (uparams.opt_doc_col + 3))
01177            __argp_fmtstream_putc (stream, '\n');
01178          else if (col >= (unsigned int) uparams.opt_doc_col)
01179            __argp_fmtstream_puts (stream, "   ");
01180          else
01181            indent_to (stream, uparams.opt_doc_col);
01182 
01183          __argp_fmtstream_puts (stream, fstr);
01184        }
01185       if (fstr && fstr != tstr)
01186        free ((char *) fstr);
01187 
01188       /* Reset the left margin.  */
01189       __argp_fmtstream_set_lmargin (stream, 0);
01190       __argp_fmtstream_putc (stream, '\n');
01191     }
01192 
01193   hhstate->prev_entry = entry;
01194 
01195 cleanup:
01196   __argp_fmtstream_set_lmargin (stream, old_lm);
01197   __argp_fmtstream_set_wmargin (stream, old_wm);
01198 }
01199 
01200 /* Output a long help message about the options in HOL to STREAM.  */
01201 static void
01202 hol_help (struct hol *hol, const struct argp_state *state,
01203          argp_fmtstream_t stream)
01204 {
01205   unsigned num;
01206   struct hol_entry *entry;
01207   struct hol_help_state hhstate = { 0, 0, 0 };
01208 
01209   for (entry = hol->entries, num = hol->num_entries; num > 0; entry++, num--)
01210     hol_entry_help (entry, state, stream, &hhstate);
01211 
01212   if (hhstate.suppressed_dup_arg && uparams.dup_args_note)
01213     {
01214       const char *tstr = dgettext (state == NULL ? NULL
01215                                : state->root_argp->argp_domain, "\
01216 Mandatory or optional arguments to long options are also mandatory or \
01217 optional for any corresponding short options.");
01218       const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_DUP_ARGS_NOTE,
01219                                  state ? state->root_argp : 0, state);
01220       if (fstr && *fstr)
01221        {
01222          __argp_fmtstream_putc (stream, '\n');
01223          __argp_fmtstream_puts (stream, fstr);
01224          __argp_fmtstream_putc (stream, '\n');
01225        }
01226       if (fstr && fstr != tstr)
01227        free ((char *) fstr);
01228     }
01229 }
01230 
01231 /* Helper functions for hol_usage.  */
01232 
01233 /* If OPT is a short option without an arg, append its key to the string
01234    pointer pointer to by COOKIE, and advance the pointer.  */
01235 static int
01236 add_argless_short_opt (const struct argp_option *opt,
01237                      const struct argp_option *real,
01238                      const char *domain, void *cookie)
01239 {
01240   char **snao_end = cookie;
01241   if (!(opt->arg || real->arg)
01242       && !((opt->flags | real->flags) & OPTION_NO_USAGE))
01243     *(*snao_end)++ = opt->key;
01244   return 0;
01245 }
01246 
01247 /* If OPT is a short option with an arg, output a usage entry for it to the
01248    stream pointed at by COOKIE.  */
01249 static int
01250 usage_argful_short_opt (const struct argp_option *opt,
01251                      const struct argp_option *real,
01252                      const char *domain, void *cookie)
01253 {
01254   argp_fmtstream_t stream = cookie;
01255   const char *arg = opt->arg;
01256   int flags = opt->flags | real->flags;
01257 
01258   if (! arg)
01259     arg = real->arg;
01260 
01261   if (arg && !(flags & OPTION_NO_USAGE))
01262     {
01263       arg = dgettext (domain, arg);
01264 
01265       if (flags & OPTION_ARG_OPTIONAL)
01266        __argp_fmtstream_printf (stream, " [-%c[%s]]", opt->key, arg);
01267       else
01268        {
01269          /* Manually do line wrapping so that it (probably) won't
01270             get wrapped at the embedded space.  */
01271          space (stream, 6 + strlen (arg));
01272          __argp_fmtstream_printf (stream, "[-%c %s]", opt->key, arg);
01273        }
01274     }
01275 
01276   return 0;
01277 }
01278 
01279 /* Output a usage entry for the long option opt to the stream pointed at by
01280    COOKIE.  */
01281 static int
01282 usage_long_opt (const struct argp_option *opt,
01283               const struct argp_option *real,
01284               const char *domain, void *cookie)
01285 {
01286   argp_fmtstream_t stream = cookie;
01287   const char *arg = opt->arg;
01288   int flags = opt->flags | real->flags;
01289 
01290   if (! arg)
01291     arg = real->arg;
01292 
01293   if (! (flags & OPTION_NO_USAGE))
01294     {
01295       if (arg)
01296        {
01297          arg = dgettext (domain, arg);
01298          if (flags & OPTION_ARG_OPTIONAL)
01299            __argp_fmtstream_printf (stream, " [--%s[=%s]]", opt->name, arg);
01300          else
01301            __argp_fmtstream_printf (stream, " [--%s=%s]", opt->name, arg);
01302        }
01303       else
01304        __argp_fmtstream_printf (stream, " [--%s]", opt->name);
01305     }
01306 
01307   return 0;
01308 }
01309 
01310 /* Print a short usage description for the arguments in HOL to STREAM.  */
01311 static void
01312 hol_usage (struct hol *hol, argp_fmtstream_t stream)
01313 {
01314   if (hol->num_entries > 0)
01315     {
01316       unsigned nentries;
01317       struct hol_entry *entry;
01318       char *short_no_arg_opts = alloca (strlen (hol->short_options) + 1);
01319       char *snao_end = short_no_arg_opts;
01320 
01321       /* First we put a list of short options without arguments.  */
01322       for (entry = hol->entries, nentries = hol->num_entries
01323           ; nentries > 0
01324           ; entry++, nentries--)
01325        hol_entry_short_iterate (entry, add_argless_short_opt,
01326                              entry->argp->argp_domain, &snao_end);
01327       if (snao_end > short_no_arg_opts)
01328        {
01329          *snao_end++ = 0;
01330          __argp_fmtstream_printf (stream, " [-%s]", short_no_arg_opts);
01331        }
01332 
01333       /* Now a list of short options *with* arguments.  */
01334       for (entry = hol->entries, nentries = hol->num_entries
01335           ; nentries > 0
01336           ; entry++, nentries--)
01337        hol_entry_short_iterate (entry, usage_argful_short_opt,
01338                              entry->argp->argp_domain, stream);
01339 
01340       /* Finally, a list of long options (whew!).  */
01341       for (entry = hol->entries, nentries = hol->num_entries
01342           ; nentries > 0
01343           ; entry++, nentries--)
01344        hol_entry_long_iterate (entry, usage_long_opt,
01345                             entry->argp->argp_domain, stream);
01346     }
01347 }
01348 
01349 /* Make a HOL containing all levels of options in ARGP.  CLUSTER is the
01350    cluster in which ARGP's entries should be clustered, or 0.  */
01351 static struct hol *
01352 argp_hol (const struct argp *argp, struct hol_cluster *cluster)
01353 {
01354   const struct argp_child *child = argp->children;
01355   struct hol *hol = make_hol (argp, cluster);
01356   if (child)
01357     while (child->argp)
01358       {
01359        struct hol_cluster *child_cluster =
01360          ((child->group || child->header)
01361           /* Put CHILD->argp within its own cluster.  */
01362           ? hol_add_cluster (hol, child->group, child->header,
01363                            child - argp->children, cluster, argp)
01364           /* Just merge it into the parent's cluster.  */
01365           : cluster);
01366        hol_append (hol, argp_hol (child->argp, child_cluster)) ;
01367        child++;
01368       }
01369   return hol;
01370 }
01371 
01372 /* Calculate how many different levels with alternative args strings exist in
01373    ARGP.  */
01374 static size_t
01375 argp_args_levels (const struct argp *argp)
01376 {
01377   size_t levels = 0;
01378   const struct argp_child *child = argp->children;
01379 
01380   if (argp->args_doc && strchr (argp->args_doc, '\n'))
01381     levels++;
01382 
01383   if (child)
01384     while (child->argp)
01385       levels += argp_args_levels ((child++)->argp);
01386 
01387   return levels;
01388 }
01389 
01390 /* Print all the non-option args documented in ARGP to STREAM.  Any output is
01391    preceded by a space.  LEVELS is a pointer to a byte vector the length
01392    returned by argp_args_levels; it should be initialized to zero, and
01393    updated by this routine for the next call if ADVANCE is true.  True is
01394    returned as long as there are more patterns to output.  */
01395 static int
01396 argp_args_usage (const struct argp *argp, const struct argp_state *state,
01397                char **levels, int advance, argp_fmtstream_t stream)
01398 {
01399   char *our_level = *levels;
01400   int multiple = 0;
01401   const struct argp_child *child = argp->children;
01402   const char *tdoc = dgettext (argp->argp_domain, argp->args_doc), *nl = 0;
01403   const char *fdoc = filter_doc (tdoc, ARGP_KEY_HELP_ARGS_DOC, argp, state);
01404 
01405   if (fdoc)
01406     {
01407       const char *cp = fdoc;
01408       nl = __strchrnul (cp, '\n');
01409       if (*nl != '\0')
01410        /* This is a `multi-level' args doc; advance to the correct position
01411           as determined by our state in LEVELS, and update LEVELS.  */
01412        {
01413          int i;
01414          multiple = 1;
01415          for (i = 0; i < *our_level; i++)
01416            cp = nl + 1, nl = __strchrnul (cp, '\n');
01417          (*levels)++;
01418        }
01419 
01420       /* Manually do line wrapping so that it (probably) won't get wrapped at
01421         any embedded spaces.  */
01422       space (stream, 1 + nl - cp);
01423 
01424       __argp_fmtstream_write (stream, cp, nl - cp);
01425     }
01426   if (fdoc && fdoc != tdoc)
01427     free ((char *)fdoc);    /* Free user's modified doc string.  */
01428 
01429   if (child)
01430     while (child->argp)
01431       advance = !argp_args_usage ((child++)->argp, state, levels, advance, stream);
01432 
01433   if (advance && multiple)
01434     {
01435       /* Need to increment our level.  */
01436       if (*nl)
01437        /* There's more we can do here.  */
01438        {
01439          (*our_level)++;
01440          advance = 0;              /* Our parent shouldn't advance also. */
01441        }
01442       else if (*our_level > 0)
01443        /* We had multiple levels, but used them up; reset to zero.  */
01444        *our_level = 0;
01445     }
01446 
01447   return !advance;
01448 }
01449 
01450 /* Print the documentation for ARGP to STREAM; if POST is false, then
01451    everything preceeding a `\v' character in the documentation strings (or
01452    the whole string, for those with none) is printed, otherwise, everything
01453    following the `\v' character (nothing for strings without).  Each separate
01454    bit of documentation is separated a blank line, and if PRE_BLANK is true,
01455    then the first is as well.  If FIRST_ONLY is true, only the first
01456    occurrence is output.  Returns true if anything was output.  */
01457 static int
01458 argp_doc (const struct argp *argp, const struct argp_state *state,
01459          int post, int pre_blank, int first_only,
01460          argp_fmtstream_t stream)
01461 {
01462   const char *text;
01463   const char *inp_text;
01464   void *input = 0;
01465   int anything = 0;
01466   size_t inp_text_limit = 0;
01467   const char *doc = dgettext (argp->argp_domain, argp->doc);
01468   const struct argp_child *child = argp->children;
01469 
01470   if (doc)
01471     {
01472       char *vt = strchr (doc, '\v');
01473       inp_text = post ? (vt ? vt + 1 : 0) : doc;
01474       inp_text_limit = (!post && vt) ? (vt - doc) : 0;
01475     }
01476   else
01477     inp_text = 0;
01478 
01479   if (argp->help_filter)
01480     /* We have to filter the doc strings.  */
01481     {
01482       if (inp_text_limit)
01483        /* Copy INP_TEXT so that it's nul-terminated.  */
01484        inp_text = __strndup (inp_text, inp_text_limit);
01485       input = __argp_input (argp, state);
01486       text =
01487        (*argp->help_filter) (post
01488                            ? ARGP_KEY_HELP_POST_DOC
01489                            : ARGP_KEY_HELP_PRE_DOC,
01490                            inp_text, input);
01491     }
01492   else
01493     text = (const char *) inp_text;
01494 
01495   if (text)
01496     {
01497       if (pre_blank)
01498        __argp_fmtstream_putc (stream, '\n');
01499 
01500       if (text == inp_text && inp_text_limit)
01501        __argp_fmtstream_write (stream, inp_text, inp_text_limit);
01502       else
01503        __argp_fmtstream_puts (stream, text);
01504 
01505       if (__argp_fmtstream_point (stream) > __argp_fmtstream_lmargin (stream))
01506        __argp_fmtstream_putc (stream, '\n');
01507 
01508       anything = 1;
01509     }
01510 
01511   if (text && text != inp_text)
01512     free ((char *) text);   /* Free TEXT returned from the help filter.  */
01513   if (inp_text && inp_text_limit && argp->help_filter)
01514     free ((char *) inp_text);      /* We copied INP_TEXT, so free it now.  */
01515 
01516   if (post && argp->help_filter)
01517     /* Now see if we have to output a ARGP_KEY_HELP_EXTRA text.  */
01518     {
01519       text = (*argp->help_filter) (ARGP_KEY_HELP_EXTRA, 0, input);
01520       if (text)
01521        {
01522          if (anything || pre_blank)
01523            __argp_fmtstream_putc (stream, '\n');
01524          __argp_fmtstream_puts (stream, text);
01525          free ((char *) text);
01526          if (__argp_fmtstream_point (stream)
01527              > __argp_fmtstream_lmargin (stream))
01528            __argp_fmtstream_putc (stream, '\n');
01529          anything = 1;
01530        }
01531     }
01532 
01533   if (child)
01534     while (child->argp && !(first_only && anything))
01535       anything |=
01536        argp_doc ((child++)->argp, state,
01537                 post, anything || pre_blank, first_only,
01538                 stream);
01539 
01540   return anything;
01541 }
01542 
01543 /* Output a usage message for ARGP to STREAM.  If called from
01544    argp_state_help, STATE is the relevent parsing state.  FLAGS are from the
01545    set ARGP_HELP_*.  NAME is what to use wherever a `program name' is
01546    needed. */
01547 static void
01548 _help (const struct argp *argp, const struct argp_state *state, FILE *stream,
01549        unsigned flags, char *name)
01550 {
01551   int anything = 0;         /* Whether we've output anything.  */
01552   struct hol *hol = 0;
01553   argp_fmtstream_t fs;
01554 
01555   if (! stream)
01556     return;
01557 
01558 #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
01559   __flockfile (stream);
01560 #endif
01561 
01562   fill_in_uparams (state);
01563 
01564   fs = __argp_make_fmtstream (stream, 0, uparams.rmargin, 0);
01565   if (! fs)
01566     {
01567 #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
01568       __funlockfile (stream);
01569 #endif
01570       return;
01571     }
01572 
01573   if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG))
01574     {
01575       hol = argp_hol (argp, 0);
01576 
01577       /* If present, these options always come last.  */
01578       hol_set_group (hol, "help", -1);
01579       hol_set_group (hol, "version", -1);
01580 
01581       hol_sort (hol);
01582     }
01583 
01584   if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE))
01585     /* Print a short `Usage:' message.  */
01586     {
01587       int first_pattern = 1, more_patterns;
01588       size_t num_pattern_levels = argp_args_levels (argp);
01589       char *pattern_levels = alloca (num_pattern_levels);
01590 
01591       memset (pattern_levels, 0, num_pattern_levels);
01592 
01593       do
01594        {
01595          int old_lm;
01596          int old_wm = __argp_fmtstream_set_wmargin (fs, uparams.usage_indent);
01597          char *levels = pattern_levels;
01598 
01599          if (first_pattern)
01600            __argp_fmtstream_printf (fs, "%s %s",
01601                                  dgettext (argp->argp_domain, "Usage:"),
01602                                  name);
01603          else
01604            __argp_fmtstream_printf (fs, "%s %s",
01605                                  dgettext (argp->argp_domain, "  or: "),
01606                                  name);
01607 
01608          /* We set the lmargin as well as the wmargin, because hol_usage
01609             manually wraps options with newline to avoid annoying breaks.  */
01610          old_lm = __argp_fmtstream_set_lmargin (fs, uparams.usage_indent);
01611 
01612          if (flags & ARGP_HELP_SHORT_USAGE)
01613            /* Just show where the options go.  */
01614            {
01615              if (hol->num_entries > 0)
01616               __argp_fmtstream_puts (fs, dgettext (argp->argp_domain,
01617                                                " [OPTION...]"));
01618            }
01619          else
01620            /* Actually print the options.  */
01621            {
01622              hol_usage (hol, fs);
01623              flags |= ARGP_HELP_SHORT_USAGE; /* But only do so once.  */
01624            }
01625 
01626          more_patterns = argp_args_usage (argp, state, &levels, 1, fs);
01627 
01628          __argp_fmtstream_set_wmargin (fs, old_wm);
01629          __argp_fmtstream_set_lmargin (fs, old_lm);
01630 
01631          __argp_fmtstream_putc (fs, '\n');
01632          anything = 1;
01633 
01634          first_pattern = 0;
01635        }
01636       while (more_patterns);
01637     }
01638 
01639   if (flags & ARGP_HELP_PRE_DOC)
01640     anything |= argp_doc (argp, state, 0, 0, 1, fs);
01641 
01642   if (flags & ARGP_HELP_SEE)
01643     {
01644       __argp_fmtstream_printf (fs, dgettext (argp->argp_domain, "\
01645 Try `%s --help' or `%s --usage' for more information.\n"),
01646                             name, name);
01647       anything = 1;
01648     }
01649 
01650   if (flags & ARGP_HELP_LONG)
01651     /* Print a long, detailed help message.  */
01652     {
01653       /* Print info about all the options.  */
01654       if (hol->num_entries > 0)
01655        {
01656          if (anything)
01657            __argp_fmtstream_putc (fs, '\n');
01658          hol_help (hol, state, fs);
01659          anything = 1;
01660        }
01661     }
01662 
01663   if (flags & ARGP_HELP_POST_DOC)
01664     /* Print any documentation strings at the end.  */
01665     anything |= argp_doc (argp, state, 1, anything, 0, fs);
01666 
01667   if ((flags & ARGP_HELP_BUG_ADDR) && argp_program_bug_address)
01668     {
01669       if (anything)
01670        __argp_fmtstream_putc (fs, '\n');
01671       __argp_fmtstream_printf (fs, dgettext (argp->argp_domain,
01672                                         "Report bugs to %s.\n"),
01673                             argp_program_bug_address);
01674       anything = 1;
01675     }
01676 
01677 #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
01678   __funlockfile (stream);
01679 #endif
01680 
01681   if (hol)
01682     hol_free (hol);
01683 
01684   __argp_fmtstream_free (fs);
01685 }
01686 
01687 /* Output a usage message for ARGP to STREAM.  FLAGS are from the set
01688    ARGP_HELP_*.  NAME is what to use wherever a `program name' is needed. */
01689 void __argp_help (const struct argp *argp, FILE *stream,
01690                 unsigned flags, char *name)
01691 {
01692   _help (argp, 0, stream, flags, name);
01693 }
01694 #ifdef weak_alias
01695 weak_alias (__argp_help, argp_help)
01696 #endif
01697 
01698 #ifndef _LIBC
01699 char *__argp_basename (char *name)
01700 {
01701   char *short_name = strrchr (name, '/');
01702   return short_name ? short_name + 1 : name;
01703 }
01704 
01705 char *
01706 __argp_short_program_name (void)
01707 {
01708 # if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
01709   return program_invocation_short_name;
01710 # elif HAVE_DECL_PROGRAM_INVOCATION_NAME
01711   return __argp_basename (program_invocation_name);
01712 # else
01713   /* FIXME: What now? Miles suggests that it is better to use NULL,
01714      but currently the value is passed on directly to fputs_unlocked,
01715      so that requires more changes. */
01716 # if __GNUC__
01717 #  warning No reasonable value to return
01718 # endif /* __GNUC__ */
01719   return "";
01720 # endif
01721 }
01722 #endif
01723 
01724 /* Output, if appropriate, a usage message for STATE to STREAM.  FLAGS are
01725    from the set ARGP_HELP_*.  */
01726 void
01727 __argp_state_help (const struct argp_state *state, FILE *stream, unsigned flags)
01728 {
01729   if ((!state || ! (state->flags & ARGP_NO_ERRS)) && stream)
01730     {
01731       if (state && (state->flags & ARGP_LONG_ONLY))
01732        flags |= ARGP_HELP_LONG_ONLY;
01733 
01734       _help (state ? state->root_argp : 0, state, stream, flags,
01735             state ? state->name : __argp_short_program_name ());
01736 
01737       if (!state || ! (state->flags & ARGP_NO_EXIT))
01738        {
01739          if (flags & ARGP_HELP_EXIT_ERR)
01740            exit (argp_err_exit_status);
01741          if (flags & ARGP_HELP_EXIT_OK)
01742            exit (0);
01743        }
01744   }
01745 }
01746 #ifdef weak_alias
01747 weak_alias (__argp_state_help, argp_state_help)
01748 #endif
01749 
01750 /* If appropriate, print the printf string FMT and following args, preceded
01751    by the program name and `:', to stderr, and followed by a `Try ... --help'
01752    message, then exit (1).  */
01753 void
01754 __argp_error (const struct argp_state *state, const char *fmt, ...)
01755 {
01756   if (!state || !(state->flags & ARGP_NO_ERRS))
01757     {
01758       FILE *stream = state ? state->err_stream : stderr;
01759 
01760       if (stream)
01761        {
01762          va_list ap;
01763 
01764 #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
01765          __flockfile (stream);
01766 #endif
01767 
01768          va_start (ap, fmt);
01769 
01770 #ifdef _LIBC
01771          char *buf;
01772 
01773          if (_IO_vasprintf (&buf, fmt, ap) < 0)
01774            buf = NULL;
01775 
01776          __fxprintf (stream, "%s: %s\n",
01777                     state ? state->name : __argp_short_program_name (), buf);
01778 
01779          free (buf);
01780 #else
01781          fputs_unlocked (state ? state->name : __argp_short_program_name (),
01782                        stream);
01783          putc_unlocked (':', stream);
01784          putc_unlocked (' ', stream);
01785 
01786          vfprintf (stream, fmt, ap);
01787 
01788          putc_unlocked ('\n', stream);
01789 #endif
01790 
01791          __argp_state_help (state, stream, ARGP_HELP_STD_ERR);
01792 
01793          va_end (ap);
01794 
01795 #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
01796          __funlockfile (stream);
01797 #endif
01798        }
01799     }
01800 }
01801 #ifdef weak_alias
01802 weak_alias (__argp_error, argp_error)
01803 #endif
01804 
01805 /* Similar to the standard gnu error-reporting function error(), but will
01806    respect the ARGP_NO_EXIT and ARGP_NO_ERRS flags in STATE, and will print
01807    to STATE->err_stream.  This is useful for argument parsing code that is
01808    shared between program startup (when exiting is desired) and runtime
01809    option parsing (when typically an error code is returned instead).  The
01810    difference between this function and argp_error is that the latter is for
01811    *parsing errors*, and the former is for other problems that occur during
01812    parsing but don't reflect a (syntactic) problem with the input.  */
01813 void
01814 __argp_failure (const struct argp_state *state, int status, int errnum,
01815               const char *fmt, ...)
01816 {
01817   if (!state || !(state->flags & ARGP_NO_ERRS))
01818     {
01819       FILE *stream = state ? state->err_stream : stderr;
01820 
01821       if (stream)
01822        {
01823 #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
01824          __flockfile (stream);
01825 #endif
01826 
01827 #ifdef _LIBC
01828          __fxprintf (stream, "%s",
01829                     state ? state->name : __argp_short_program_name ());
01830 #else
01831          fputs_unlocked (state ? state->name : __argp_short_program_name (),
01832                        stream);
01833 #endif
01834 
01835          if (fmt)
01836            {
01837              va_list ap;
01838 
01839              va_start (ap, fmt);
01840 #ifdef _LIBC
01841              char *buf;
01842 
01843              if (_IO_vasprintf (&buf, fmt, ap) < 0)
01844               buf = NULL;
01845 
01846              __fxprintf (stream, ": %s", buf);
01847 
01848              free (buf);
01849 #else
01850              putc_unlocked (':', stream);
01851              putc_unlocked (' ', stream);
01852 
01853              vfprintf (stream, fmt, ap);
01854 #endif
01855 
01856              va_end (ap);
01857            }
01858 
01859          if (errnum)
01860            {
01861              char buf[200];
01862 
01863 #ifdef _LIBC
01864              __fxprintf (stream, ": %s",
01865                        __strerror_r (errnum, buf, sizeof (buf)));
01866 #else
01867              putc_unlocked (':', stream);
01868              putc_unlocked (' ', stream);
01869 # ifdef HAVE_STRERROR_R
01870              fputs (__strerror_r (errnum, buf, sizeof (buf)), stream);
01871 # else
01872              fputs (strerror (errnum), stream);
01873 # endif
01874 #endif
01875            }
01876 
01877 #ifdef USE_IN_LIBIO
01878          if (_IO_fwide (stream, 0) > 0)
01879            putwc_unlocked (L'\n', stream);
01880          else
01881 #endif
01882            putc_unlocked ('\n', stream);
01883 
01884 #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
01885          __funlockfile (stream);
01886 #endif
01887 
01888          if (status && (!state || !(state->flags & ARGP_NO_EXIT)))
01889            exit (status);
01890        }
01891     }
01892 }
01893 #ifdef weak_alias
01894 weak_alias (__argp_failure, argp_failure)
01895 #endif