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