source: trunk/essentials/app-arch/tar/lib/argp-help.c

Last change on this file was 3342, checked in by bird, 18 years ago

tar 1.16.1

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