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