~darkmuggle-deactivatedaccount/ubuntu/quantal/grub2/fix-872244

« back to all changes in this revision

Viewing changes to grub-core/gnulib/argp-help.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Evan Broder, Mario Limonciello
  • Date: 2010-11-24 13:59:55 UTC
  • mfrom: (1.17.6 upstream) (17.6.15 experimental)
  • Revision ID: james.westby@ubuntu.com-20101124135955-r6ii5sepayr7jt53
Tags: 1.99~20101124-1ubuntu1
[ Colin Watson ]
* Resynchronise with Debian experimental.  Remaining changes:
  - Adjust for default Ubuntu boot options ("quiet splash").
  - Default to hiding the menu; holding down Shift at boot will show it.
  - Set a monochromatic theme for Ubuntu.
  - Apply Ubuntu GRUB Legacy changes to legacy update-grub script: title,
    recovery mode, quiet option, tweak how memtest86+ is displayed, and
    use UUIDs where appropriate.
  - Fix backslash-escaping in merge_debconf_into_conf.
  - Remove "GNU/Linux" from default distributor string.
  - Add crashkernel= options if kdump and makedumpfile are available.
  - If other operating systems are installed, then automatically unhide
    the menu.  Otherwise, if GRUB_HIDDEN_TIMEOUT is 0, then use keystatus
    if available to check whether Shift is pressed.  If it is, show the
    menu, otherwise boot immediately.  If keystatus is not available, then
    fall back to a short delay interruptible with Escape.
  - Allow Shift to interrupt 'sleep --interruptible'.
  - Don't display introductory message about line editing unless we're
    actually offering a shell prompt.  Don't clear the screen just before
    booting if we never drew the menu in the first place.
  - Remove some verbose messages printed before reading the configuration
    file.
  - Suppress progress messages as the kernel and initrd load for
    non-recovery kernel menu entries.
  - Change prepare_grub_to_access_device to handle filesystems
    loop-mounted on file images.
  - Ignore devices loop-mounted from files in 10_linux.
  - Show the boot menu if the previous boot failed, that is if it failed
    to get to the end of one of the normal runlevels.
  - Don't generate /boot/grub/device.map during grub-install or
    grub-mkconfig by default.
  - Adjust upgrade version checks for Ubuntu.
  - Don't display "GRUB loading" unless Shift is held down.
  - Adjust versions of grub-doc and grub-legacy-doc conflicts to tolerate
    our backport of the grub-doc split.
  - Fix LVM/RAID probing in the absence of /boot/grub/device.map.
  - Look for .mo files in /usr/share/locale-langpack as well, in
    preference.
  - Make sure GRUB_TIMEOUT isn't quoted unnecessarily.
  - Probe all devices in 'grub-probe --target=drive' if
    /boot/grub/device.map is missing.
  - Build-depend on qemu-kvm rather than qemu-system for grub-pc tests.
  - Use qemu rather than qemu-system-i386.
  - Program vesafb on BIOS systems rather than efifb.
  - Add a grub-rescue-efi-amd64 package containing a rescue CD-ROM image
    for EFI-AMD64.
  - On Wubi, don't ask for an install device, but just update wubildr
    using the diverted grub-install.
  - When embedding the core image in a post-MBR gap, check for and avoid
    sectors matching any of a list of known signatures.
  - Disable video_bochs and video_cirrus on PC BIOS systems, as probing
    PCI space seems to break on some systems.
* Downgrade "ACPI shutdown failed" error to a debug message, since it can
  cause spurious test failures.

[ Evan Broder ]
* Enable lua from grub-extras.
* Incorporate the bitop library into lua.
* Add enum_pci function to grub module in lua.
* Switch back to gfxpayload=keep by default, unless the video hardware
  is known to not support it.

[ Mario Limonciello ]
* Built part_msdos and vfat into bootx64.efi (LP: #677758)

Show diffs side-by-side

added added

removed removed

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