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