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