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