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