OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [tags/] [gnu-src/] [newlib-1.18.0/] [newlib-1.18.0-or32-1.0rc2/] [newlib/] [libc/] [sys/] [linux/] [argp/] [argp-help.c] - Blame information for rev 520

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.