Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/preferences/src/lib/argp/argp-help.c @ 6396

Last change on this file since 6396 was 6393, checked in by rennerc, 19 years ago

added libargp to orxonox

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