source: trunk/libs/newlib/src/newlib/libc/sys/linux/argp/argp-help.c @ 444

Last change on this file since 444 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

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