source: vendor/glibc/current/argp/argp-help.c

Last change on this file was 2141, checked in by bird, 20 years ago

Initial revision

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