00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef _GNU_SOURCE
00022 # define _GNU_SOURCE 1
00023 #endif
00024
00025 #ifdef HAVE_CONFIG_H
00026 #include <config.h>
00027 #endif
00028
00029
00030 #ifndef __GNUC__
00031 # if HAVE_ALLOCA_H
00032 # include <alloca.h>
00033 # else
00034 # ifdef _AIX
00035 #pragma alloca
00036 # else
00037 # ifndef alloca
00038 char *alloca ();
00039 # endif
00040 # endif
00041 # endif
00042 #endif
00043
00044 #include <stddef.h>
00045 #include <stdlib.h>
00046 #include <string.h>
00047 #include <assert.h>
00048 #include <stdarg.h>
00049 #include <ctype.h>
00050
00051
00052 #ifdef _WIN32
00053 #include <malloc.h>
00054 #endif
00055
00056 #ifndef _
00057
00058 # if defined HAVE_LIBINTL_H || defined _LIBC
00059 # include <libintl.h>
00060 # ifdef _LIBC
00061 # undef dgettext
00062 # define dgettext(domain, msgid) __dcgettext (domain, msgid, LC_MESSAGES)
00063 # endif
00064 # else
00065 # define dgettext(domain, msgid) (msgid)
00066 # endif
00067 #endif
00068
00069 #include "argp.h"
00070 #include "argp-fmtstream.h"
00071 #include "argp-namefrob.h"
00072
00073
00074 #ifndef _LIBC
00075 # ifndef __strchrnul
00076 # define __strchrnul strchrnul
00077 # endif
00078 # ifndef __mempcpy
00079 # define __mempcpy mempcpy
00080 # endif
00081
00082 # define STRNDUP strndup
00083 # if HAVE_STRERROR
00084 # define STRERROR strerror
00085 # else
00086 # define STRERROR(x) (sys_errlist[x])
00087 # endif
00088 #else
00089 # define FLOCKFILE __flockfile
00090 # define FUNLOCKFILE __funlockfile
00091 # define STRNDUP __strndup
00092 # define STRERROR strerror
00093 #endif
00094
00095 #if !_LIBC
00096 # if !HAVE_STRNDUP
00097 char *strndup (const char *s, size_t size);
00098 # endif
00099
00100 # if !HAVE_MEMPCPY
00101 void *mempcpy (void *to, const void *from, size_t size);
00102 # endif
00103
00104 # if !HAVE_STRCHRNUL
00105 char *strchrnul(const char *s, int c);
00106 # endif
00107
00108 #endif
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119 #define DUP_ARGS 0
00120 #define DUP_ARGS_NOTE 1
00121 #define SHORT_OPT_COL 2
00122 #define LONG_OPT_COL 6
00123 #define DOC_OPT_COL 2
00124 #define OPT_DOC_COL 29
00125 #define HEADER_COL 1
00126 #define USAGE_INDENT 12
00127 #define RMARGIN 79
00128
00129
00130
00131 struct uparams
00132 {
00133
00134
00135
00136
00137
00138 int dup_args;
00139
00140
00141
00142 int dup_args_note;
00143
00144
00145 int short_opt_col;
00146 int long_opt_col;
00147 int doc_opt_col;
00148 int opt_doc_col;
00149 int header_col;
00150 int usage_indent;
00151 int rmargin;
00152
00153 int valid;
00154 };
00155
00156
00157 static struct uparams uparams = {
00158 DUP_ARGS, DUP_ARGS_NOTE,
00159 SHORT_OPT_COL, LONG_OPT_COL, DOC_OPT_COL, OPT_DOC_COL, HEADER_COL,
00160 USAGE_INDENT, RMARGIN,
00161 0
00162 };
00163
00164
00165 struct uparam_name
00166 {
00167 const char *name;
00168 int is_bool;
00169 size_t uparams_offs;
00170 };
00171
00172
00173 static const struct uparam_name uparam_names[] =
00174 {
00175 { "dup-args", 1, offsetof (struct uparams, dup_args) },
00176 { "dup-args-note", 1, offsetof (struct uparams, dup_args_note) },
00177 { "short-opt-col", 0, offsetof (struct uparams, short_opt_col) },
00178 { "long-opt-col", 0, offsetof (struct uparams, long_opt_col) },
00179 { "doc-opt-col", 0, offsetof (struct uparams, doc_opt_col) },
00180 { "opt-doc-col", 0, offsetof (struct uparams, opt_doc_col) },
00181 { "header-col", 0, offsetof (struct uparams, header_col) },
00182 { "usage-indent", 0, offsetof (struct uparams, usage_indent) },
00183 { "rmargin", 0, offsetof (struct uparams, rmargin) },
00184 { 0, 0, 0 }
00185 };
00186
00187
00188 static void
00189 fill_in_uparams (const struct argp_state *state)
00190 {
00191
00192 const unsigned char *var = (unsigned char *) getenv ("ARGP_HELP_FMT");
00193
00194 #define SKIPWS(p) do { while (isspace (*p)) p++; } while (0);
00195
00196 if (var)
00197
00198 while (*var)
00199 {
00200 SKIPWS (var);
00201
00202 if (isalpha (*var))
00203 {
00204 size_t var_len;
00205 const struct uparam_name *un;
00206 int unspec = 0, val = 0;
00207 const unsigned char *arg = var;
00208
00209 while (isalnum (*arg) || *arg == '-' || *arg == '_')
00210 arg++;
00211 var_len = arg - var;
00212
00213 SKIPWS (arg);
00214
00215 if (*arg == '\0' || *arg == ',')
00216 unspec = 1;
00217 else if (*arg == '=')
00218 {
00219 arg++;
00220 SKIPWS (arg);
00221 }
00222
00223 if (unspec)
00224 {
00225 if (var[0] == 'n' && var[1] == 'o' && var[2] == '-')
00226 {
00227 val = 0;
00228 var += 3;
00229 var_len -= 3;
00230 }
00231 else
00232 val = 1;
00233 }
00234 else if (isdigit (*arg))
00235 {
00236 val = atoi (arg);
00237 while (isdigit (*arg))
00238 arg++;
00239 SKIPWS (arg);
00240 }
00241
00242 for (un = uparam_names; un->name; un++)
00243 if (strlen (un->name) == var_len
00244 && strncmp (var, un->name, var_len) == 0)
00245 {
00246 if (unspec && !un->is_bool)
00247 __argp_failure (state, 0, 0,
00248 dgettext (state->root_argp->argp_domain, "\
00249 %.*s: ARGP_HELP_FMT parameter requires a value"),
00250 (int) var_len, var);
00251 else
00252 *(int *)((char *)&uparams + un->uparams_offs) = val;
00253 break;
00254 }
00255 if (! un->name)
00256 __argp_failure (state, 0, 0,
00257 dgettext (state->root_argp->argp_domain, "\
00258 %.*s: Unknown ARGP_HELP_FMT parameter"),
00259 (int) var_len, var);
00260
00261 var = arg;
00262 if (*var == ',')
00263 var++;
00264 }
00265 else if (*var)
00266 {
00267 __argp_failure (state, 0, 0,
00268 dgettext (state->root_argp->argp_domain,
00269 "Garbage in ARGP_HELP_FMT: %s"), var);
00270 break;
00271 }
00272 }
00273 }
00274
00275
00276
00277 #define ovisible(opt) (! ((opt)->flags & OPTION_HIDDEN))
00278
00279
00280 #define oalias(opt) ((opt)->flags & OPTION_ALIAS)
00281
00282
00283 #define odoc(opt) ((opt)->flags & OPTION_DOC)
00284
00285
00286 #define oend(opt) __option_is_end (opt)
00287
00288
00289 #define oshort(opt) __option_is_short (opt)
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356 static int
00357 find_char (char ch, char *beg, char *end)
00358 {
00359 while (beg < end)
00360 if (*beg == ch)
00361 return 1;
00362 else
00363 beg++;
00364 return 0;
00365 }
00366
00367 struct hol_cluster;
00368
00369 struct hol_entry
00370 {
00371
00372 const struct argp_option *opt;
00373
00374 unsigned num;
00375
00376
00377
00378
00379
00380
00381
00382 char *short_options;
00383
00384
00385
00386
00387 int group;
00388
00389
00390 struct hol_cluster *cluster;
00391
00392
00393 const struct argp *argp;
00394 };
00395
00396
00397 struct hol_cluster
00398 {
00399
00400 const char *header;
00401
00402
00403
00404
00405 int index;
00406
00407
00408
00409 int group;
00410
00411
00412
00413 struct hol_cluster *parent;
00414
00415
00416 const struct argp *argp;
00417
00418
00419 int depth;
00420
00421
00422
00423 struct hol_cluster *next;
00424 };
00425
00426
00427 struct hol
00428 {
00429
00430 struct hol_entry *entries;
00431
00432
00433 unsigned num_entries;
00434
00435
00436
00437 char *short_options;
00438
00439
00440 struct hol_cluster *clusters;
00441 };
00442
00443
00444
00445 static struct hol *
00446 make_hol (const struct argp *argp, struct hol_cluster *cluster)
00447 {
00448 char *so;
00449 const struct argp_option *o;
00450 const struct argp_option *opts = argp->options;
00451 struct hol_entry *entry;
00452 unsigned num_short_options = 0;
00453 struct hol *hol = malloc (sizeof (struct hol));
00454
00455 assert (hol);
00456
00457 hol->num_entries = 0;
00458 hol->clusters = 0;
00459
00460 if (opts)
00461 {
00462 int cur_group = 0;
00463
00464
00465 assert (! oalias (opts));
00466
00467
00468 for (o = opts; ! oend (o); o++)
00469 {
00470 if (! oalias (o))
00471 hol->num_entries++;
00472 if (oshort (o))
00473 num_short_options++;
00474 }
00475
00476 hol->entries = malloc (sizeof (struct hol_entry) * hol->num_entries);
00477 hol->short_options = malloc (num_short_options + 1);
00478
00479 assert (hol->entries && hol->short_options);
00480
00481
00482 so = hol->short_options;
00483 for (o = opts, entry = hol->entries; ! oend (o); entry++)
00484 {
00485 entry->opt = o;
00486 entry->num = 0;
00487 entry->short_options = so;
00488 entry->group = cur_group =
00489 o->group
00490 ? o->group
00491 : ((!o->name && !o->key)
00492 ? cur_group + 1
00493 : cur_group);
00494 entry->cluster = cluster;
00495 entry->argp = argp;
00496
00497 do
00498 {
00499 entry->num++;
00500 if (oshort (o) && ! find_char (o->key, hol->short_options, so))
00501
00502 *so++ = o->key;
00503 o++;
00504 }
00505 while (! oend (o) && oalias (o));
00506 }
00507 *so = '\0';
00508 }
00509
00510 return hol;
00511 }
00512
00513
00514
00515
00516 static struct hol_cluster *
00517 hol_add_cluster (struct hol *hol, int group, const char *header, int index,
00518 struct hol_cluster *parent, const struct argp *argp)
00519 {
00520 struct hol_cluster *cl = malloc (sizeof (struct hol_cluster));
00521 if (cl)
00522 {
00523 cl->group = group;
00524 cl->header = header;
00525
00526 cl->index = index;
00527 cl->parent = parent;
00528 cl->argp = argp;
00529 cl->depth = parent ? parent->depth + 1 : 0;
00530
00531 cl->next = hol->clusters;
00532 hol->clusters = cl;
00533 }
00534 return cl;
00535 }
00536
00537
00538 static void
00539 hol_free (struct hol *hol)
00540 {
00541 struct hol_cluster *cl = hol->clusters;
00542
00543 while (cl)
00544 {
00545 struct hol_cluster *next = cl->next;
00546 free (cl);
00547 cl = next;
00548 }
00549
00550 if (hol->num_entries > 0)
00551 {
00552 free (hol->entries);
00553 free (hol->short_options);
00554 }
00555
00556 free (hol);
00557 }
00558
00559 static inline int
00560 hol_entry_short_iterate (const struct hol_entry *entry,
00561 int (*func)(const struct argp_option *opt,
00562 const struct argp_option *real,
00563 const char *domain, void *cookie),
00564 const char *domain, void *cookie)
00565 {
00566 unsigned nopts;
00567 int val = 0;
00568 const struct argp_option *opt, *real = entry->opt;
00569 char *so = entry->short_options;
00570
00571 for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--)
00572 if (oshort (opt) && *so == opt->key)
00573 {
00574 if (!oalias (opt))
00575 real = opt;
00576 if (ovisible (opt))
00577 val = (*func)(opt, real, domain, cookie);
00578 so++;
00579 }
00580
00581 return val;
00582 }
00583
00584 static inline int
00585 hol_entry_long_iterate (const struct hol_entry *entry,
00586 int (*func)(const struct argp_option *opt,
00587 const struct argp_option *real,
00588 const char *domain, void *cookie),
00589 const char *domain, void *cookie)
00590 {
00591 unsigned nopts;
00592 int val = 0;
00593 const struct argp_option *opt, *real = entry->opt;
00594
00595 for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--)
00596 if (opt->name)
00597 {
00598 if (!oalias (opt))
00599 real = opt;
00600 if (ovisible (opt))
00601 val = (*func)(opt, real, domain, cookie);
00602 }
00603
00604 return val;
00605 }
00606
00607
00608 static inline int
00609 until_short (const struct argp_option *opt, const struct argp_option *real UNUSED,
00610 const char *domain UNUSED, void *cookie UNUSED)
00611 {
00612 return oshort (opt) ? opt->key : 0;
00613 }
00614
00615
00616 static char
00617 hol_entry_first_short (const struct hol_entry *entry)
00618 {
00619 return hol_entry_short_iterate (entry, until_short,
00620 entry->argp->argp_domain, 0);
00621 }
00622
00623
00624 static const char *
00625 hol_entry_first_long (const struct hol_entry *entry)
00626 {
00627 const struct argp_option *opt;
00628 unsigned num;
00629 for (opt = entry->opt, num = entry->num; num > 0; opt++, num--)
00630 if (opt->name && ovisible (opt))
00631 return opt->name;
00632 return 0;
00633 }
00634
00635
00636
00637 static struct hol_entry *
00638 hol_find_entry (struct hol *hol, const char *name)
00639 {
00640 struct hol_entry *entry = hol->entries;
00641 unsigned num_entries = hol->num_entries;
00642
00643 while (num_entries-- > 0)
00644 {
00645 const struct argp_option *opt = entry->opt;
00646 unsigned num_opts = entry->num;
00647
00648 while (num_opts-- > 0)
00649 if (opt->name && ovisible (opt) && strcmp (opt->name, name) == 0)
00650 return entry;
00651 else
00652 opt++;
00653
00654 entry++;
00655 }
00656
00657 return 0;
00658 }
00659
00660
00661
00662 static void
00663 hol_set_group (struct hol *hol, const char *name, int group)
00664 {
00665 struct hol_entry *entry = hol_find_entry (hol, name);
00666 if (entry)
00667 entry->group = group;
00668 }
00669
00670
00671
00672 static int
00673 group_cmp (int group1, int group2, int eq)
00674 {
00675 if (group1 == group2)
00676 return eq;
00677 else if ((group1 < 0 && group2 < 0) || (group1 >= 0 && group2 >= 0))
00678 return group1 - group2;
00679 else
00680 return group2 - group1;
00681 }
00682
00683
00684
00685 static int
00686 hol_cluster_cmp (const struct hol_cluster *cl1, const struct hol_cluster *cl2)
00687 {
00688
00689
00690 while (cl1->depth < cl2->depth)
00691 cl1 = cl1->parent;
00692 while (cl2->depth < cl1->depth)
00693 cl2 = cl2->parent;
00694
00695
00696
00697 while (cl1->parent != cl2->parent)
00698 cl1 = cl1->parent, cl2 = cl2->parent;
00699
00700 return group_cmp (cl1->group, cl2->group, cl2->index - cl1->index);
00701 }
00702
00703
00704
00705 static struct hol_cluster *
00706 hol_cluster_base (struct hol_cluster *cl)
00707 {
00708 while (cl->parent)
00709 cl = cl->parent;
00710 return cl;
00711 }
00712
00713
00714 static int
00715 hol_cluster_is_child (const struct hol_cluster *cl1,
00716 const struct hol_cluster *cl2)
00717 {
00718 while (cl1 && cl1 != cl2)
00719 cl1 = cl1->parent;
00720 return cl1 == cl2;
00721 }
00722
00723
00724
00725
00726
00727
00728 static int
00729 canon_doc_option (const char **name)
00730 {
00731 int non_opt;
00732
00733 while (isspace ( (unsigned char) **name))
00734 (*name)++;
00735
00736 non_opt = (**name != '-');
00737
00738 while (**name && !isalnum ( (unsigned char) **name))
00739 (*name)++;
00740 return non_opt;
00741 }
00742
00743
00744
00745 static int
00746 hol_entry_cmp (const struct hol_entry *entry1,
00747 const struct hol_entry *entry2)
00748 {
00749
00750
00751 int group1 = entry1->group, group2 = entry2->group;
00752
00753 if (entry1->cluster != entry2->cluster)
00754 {
00755
00756
00757 if (! entry1->cluster)
00758
00759
00760
00761
00762 return group_cmp (group1, hol_cluster_base (entry2->cluster)->group, -1);
00763 else if (! entry2->cluster)
00764
00765 return group_cmp (hol_cluster_base (entry1->cluster)->group, group2, 1);
00766 else
00767
00768 return hol_cluster_cmp (entry1->cluster, entry2->cluster);
00769 }
00770 else if (group1 == group2)
00771
00772
00773 {
00774 int short1 = hol_entry_first_short (entry1);
00775 int short2 = hol_entry_first_short (entry2);
00776 int doc1 = odoc (entry1->opt);
00777 int doc2 = odoc (entry2->opt);
00778
00779 const char *long1 = hol_entry_first_long (entry1);
00780 const char *long2 = hol_entry_first_long (entry2);
00781
00782 if (doc1)
00783 doc1 = canon_doc_option (&long1);
00784 if (doc2)
00785 doc2 = canon_doc_option (&long2);
00786
00787 if (doc1 != doc2)
00788
00789
00790 return doc1 - doc2;
00791 else if (!short1 && !short2 && long1 && long2)
00792
00793 return __strcasecmp (long1, long2);
00794 else
00795
00796
00797
00798
00799
00800 {
00801 unsigned char first1 = short1 ? short1 : long1 ? *long1 : 0;
00802 unsigned char first2 = short2 ? short2 : long2 ? *long2 : 0;
00803 #ifdef _tolower
00804 int lower_cmp = _tolower (first1) - _tolower (first2);
00805 #else
00806 int lower_cmp = tolower (first1) - tolower (first2);
00807 #endif
00808
00809
00810
00811
00812
00813 return lower_cmp ? lower_cmp : first2 - first1;
00814 }
00815 }
00816 else
00817
00818
00819 return group_cmp (group1, group2, 0);
00820 }
00821
00822
00823 static int
00824 hol_entry_qcmp (const void *entry1_v, const void *entry2_v)
00825 {
00826 return hol_entry_cmp (entry1_v, entry2_v);
00827 }
00828
00829
00830
00831
00832 static void
00833 hol_sort (struct hol *hol)
00834 {
00835 if (hol->num_entries > 0)
00836 qsort (hol->entries, hol->num_entries, sizeof (struct hol_entry),
00837 hol_entry_qcmp);
00838 }
00839
00840
00841
00842 static void
00843 hol_append (struct hol *hol, struct hol *more)
00844 {
00845 struct hol_cluster **cl_end = &hol->clusters;
00846
00847
00848 while (*cl_end)
00849 cl_end = &(*cl_end)->next;
00850 *cl_end = more->clusters;
00851 more->clusters = 0;
00852
00853
00854 if (more->num_entries > 0)
00855 {
00856 if (hol->num_entries == 0)
00857 {
00858 hol->num_entries = more->num_entries;
00859 hol->entries = more->entries;
00860 hol->short_options = more->short_options;
00861 more->num_entries = 0;
00862 }
00863 else
00864
00865
00866 {
00867 unsigned left;
00868 char *so, *more_so;
00869 struct hol_entry *e;
00870 unsigned num_entries = hol->num_entries + more->num_entries;
00871 struct hol_entry *entries =
00872 malloc (num_entries * sizeof (struct hol_entry));
00873 unsigned hol_so_len = strlen (hol->short_options);
00874 char *short_options =
00875 malloc (hol_so_len + strlen (more->short_options) + 1);
00876
00877 __mempcpy (__mempcpy (entries, hol->entries,
00878 hol->num_entries * sizeof (struct hol_entry)),
00879 more->entries,
00880 more->num_entries * sizeof (struct hol_entry));
00881
00882 __mempcpy (short_options, hol->short_options, hol_so_len);
00883
00884
00885 for (e = entries, left = hol->num_entries; left > 0; e++, left--)
00886 e->short_options += (short_options - hol->short_options);
00887
00888
00889
00890 so = short_options + hol_so_len;
00891 more_so = more->short_options;
00892 for (left = more->num_entries; left > 0; e++, left--)
00893 {
00894 int opts_left;
00895 const struct argp_option *opt;
00896
00897 e->short_options = so;
00898
00899 for (opts_left = e->num, opt = e->opt; opts_left; opt++, opts_left--)
00900 {
00901 int ch = *more_so;
00902 if (oshort (opt) && ch == opt->key)
00903
00904 {
00905 if (! find_char (ch, short_options,
00906 short_options + hol_so_len))
00907
00908
00909 *so++ = ch;
00910 more_so++;
00911 }
00912 }
00913 }
00914
00915 *so = '\0';
00916
00917 free (hol->entries);
00918 free (hol->short_options);
00919
00920 hol->entries = entries;
00921 hol->num_entries = num_entries;
00922 hol->short_options = short_options;
00923 }
00924 }
00925
00926 hol_free (more);
00927 }
00928
00929
00930 static void
00931 indent_to (argp_fmtstream_t stream, unsigned col)
00932 {
00933 int needed = col - __argp_fmtstream_point (stream);
00934 while (needed-- > 0)
00935 __argp_fmtstream_putc (stream, ' ');
00936 }
00937
00938
00939
00940 static void
00941 space (argp_fmtstream_t stream, size_t ensure)
00942 {
00943 if (__argp_fmtstream_point (stream) + ensure
00944 >= __argp_fmtstream_rmargin (stream))
00945 __argp_fmtstream_putc (stream, '\n');
00946 else
00947 __argp_fmtstream_putc (stream, ' ');
00948 }
00949
00950
00951
00952
00953 static void
00954 arg (const struct argp_option *real, const char *req_fmt, const char *opt_fmt,
00955 const char *domain UNUSED, argp_fmtstream_t stream)
00956 {
00957 if (real->arg)
00958 {
00959 if (real->flags & OPTION_ARG_OPTIONAL)
00960 __argp_fmtstream_printf (stream, opt_fmt,
00961 dgettext (domain, real->arg));
00962 else
00963 __argp_fmtstream_printf (stream, req_fmt,
00964 dgettext (domain, real->arg));
00965 }
00966 }
00967
00968
00969
00970
00971 struct hol_help_state
00972 {
00973
00974 struct hol_entry *prev_entry;
00975
00976
00977
00978 int sep_groups;
00979
00980
00981
00982 int suppressed_dup_arg;
00983 };
00984
00985
00986
00987
00988 struct pentry_state
00989 {
00990 const struct hol_entry *entry;
00991 argp_fmtstream_t stream;
00992 struct hol_help_state *hhstate;
00993
00994
00995 int first;
00996
00997
00998 const struct argp_state *state;
00999 };
01000
01001
01002 static const char *
01003 filter_doc (const char *doc, int key, const struct argp *argp,
01004 const struct argp_state *state)
01005 {
01006 if (argp->help_filter)
01007
01008 {
01009 void *input = __argp_input (argp, state);
01010 return (*argp->help_filter) (key, doc, input);
01011 }
01012 else
01013
01014 return doc;
01015 }
01016
01017
01018
01019
01020
01021
01022 static void
01023 print_header (const char *str, const struct argp *argp,
01024 struct pentry_state *pest)
01025 {
01026 const char *tstr = dgettext (argp->argp_domain, str);
01027 const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_HEADER, argp, pest->state);
01028
01029 if (fstr)
01030 {
01031 if (*fstr)
01032 {
01033 if (pest->hhstate->prev_entry)
01034
01035 __argp_fmtstream_putc (pest->stream, '\n');
01036 indent_to (pest->stream, uparams.header_col);
01037 __argp_fmtstream_set_lmargin (pest->stream, uparams.header_col);
01038 __argp_fmtstream_set_wmargin (pest->stream, uparams.header_col);
01039 __argp_fmtstream_puts (pest->stream, fstr);
01040 __argp_fmtstream_set_lmargin (pest->stream, 0);
01041 __argp_fmtstream_putc (pest->stream, '\n');
01042 }
01043
01044 pest->hhstate->sep_groups = 1;
01045 }
01046
01047 if (fstr != tstr)
01048 free ((char *) fstr);
01049 }
01050
01051
01052
01053
01054
01055 static void
01056 comma (unsigned col, struct pentry_state *pest)
01057 {
01058 if (pest->first)
01059 {
01060 const struct hol_entry *pe = pest->hhstate->prev_entry;
01061 const struct hol_cluster *cl = pest->entry->cluster;
01062
01063 if (pest->hhstate->sep_groups && pe && pest->entry->group != pe->group)
01064 __argp_fmtstream_putc (pest->stream, '\n');
01065
01066 if (cl && cl->header && *cl->header
01067 && (!pe
01068 || (pe->cluster != cl
01069 && !hol_cluster_is_child (pe->cluster, cl))))
01070
01071
01072
01073
01074 {
01075 int old_wm = __argp_fmtstream_wmargin (pest->stream);
01076 print_header (cl->header, cl->argp, pest);
01077 __argp_fmtstream_set_wmargin (pest->stream, old_wm);
01078 }
01079
01080 pest->first = 0;
01081 }
01082 else
01083 __argp_fmtstream_puts (pest->stream, ", ");
01084
01085 indent_to (pest->stream, col);
01086 }
01087
01088
01089 static void
01090 hol_entry_help (struct hol_entry *entry, const struct argp_state *state,
01091 argp_fmtstream_t stream, struct hol_help_state *hhstate)
01092 {
01093 unsigned num;
01094 const struct argp_option *real = entry->opt, *opt;
01095 char *so = entry->short_options;
01096 int have_long_opt = 0;
01097
01098 int old_lm = __argp_fmtstream_set_lmargin (stream, 0);
01099 int old_wm = __argp_fmtstream_wmargin (stream);
01100
01101
01102
01103
01104 struct pentry_state pest;
01105 pest.entry = entry;
01106 pest.stream = stream;
01107 pest.hhstate = hhstate;
01108 pest.first = 1;
01109 pest.state = state;
01110
01111 if (! odoc (real))
01112 for (opt = real, num = entry->num; num > 0; opt++, num--)
01113 if (opt->name && ovisible (opt))
01114 {
01115 have_long_opt = 1;
01116 break;
01117 }
01118
01119
01120 __argp_fmtstream_set_wmargin (stream, uparams.short_opt_col);
01121 for (opt = real, num = entry->num; num > 0; opt++, num--)
01122 if (oshort (opt) && opt->key == *so)
01123
01124 {
01125 if (ovisible (opt))
01126 {
01127 comma (uparams.short_opt_col, &pest);
01128 __argp_fmtstream_putc (stream, '-');
01129 __argp_fmtstream_putc (stream, *so);
01130 if (!have_long_opt || uparams.dup_args)
01131 arg (real, " %s", "[%s]", state->root_argp->argp_domain, stream);
01132 else if (real->arg)
01133 hhstate->suppressed_dup_arg = 1;
01134 }
01135 so++;
01136 }
01137
01138
01139 if (odoc (real))
01140
01141 {
01142 __argp_fmtstream_set_wmargin (stream, uparams.doc_opt_col);
01143 for (opt = real, num = entry->num; num > 0; opt++, num--)
01144 if (opt->name && ovisible (opt))
01145 {
01146 comma (uparams.doc_opt_col, &pest);
01147
01148
01149
01150 __argp_fmtstream_puts (stream,
01151 dgettext (state->root_argp->argp_domain,
01152 opt->name));
01153 }
01154 }
01155 else
01156
01157 {
01158 int first_long_opt = 1;
01159
01160 __argp_fmtstream_set_wmargin (stream, uparams.long_opt_col);
01161 for (opt = real, num = entry->num; num > 0; opt++, num--)
01162 if (opt->name && ovisible (opt))
01163 {
01164 comma (uparams.long_opt_col, &pest);
01165 __argp_fmtstream_printf (stream, "--%s", opt->name);
01166 if (first_long_opt || uparams.dup_args)
01167 arg (real, "=%s", "[=%s]", state->root_argp->argp_domain,
01168 stream);
01169 else if (real->arg)
01170 hhstate->suppressed_dup_arg = 1;
01171 }
01172 }
01173
01174
01175 __argp_fmtstream_set_lmargin (stream, 0);
01176
01177 if (pest.first)
01178 {
01179
01180 if (!oshort (real) && !real->name)
01181
01182 print_header (real->doc, entry->argp, &pest);
01183 else
01184
01185 goto cleanup;
01186 }
01187 else
01188 {
01189 const char *tstr = real->doc ? dgettext (state->root_argp->argp_domain,
01190 real->doc) : 0;
01191 const char *fstr = filter_doc (tstr, real->key, entry->argp, state);
01192 if (fstr && *fstr)
01193 {
01194 unsigned int col = __argp_fmtstream_point (stream);
01195
01196 __argp_fmtstream_set_lmargin (stream, uparams.opt_doc_col);
01197 __argp_fmtstream_set_wmargin (stream, uparams.opt_doc_col);
01198
01199 if (col > (unsigned int) (uparams.opt_doc_col + 3))
01200 __argp_fmtstream_putc (stream, '\n');
01201 else if (col >= (unsigned int) uparams.opt_doc_col)
01202 __argp_fmtstream_puts (stream, " ");
01203 else
01204 indent_to (stream, uparams.opt_doc_col);
01205
01206 __argp_fmtstream_puts (stream, fstr);
01207 }
01208 if (fstr && fstr != tstr)
01209 free ((char *) fstr);
01210
01211
01212 __argp_fmtstream_set_lmargin (stream, 0);
01213 __argp_fmtstream_putc (stream, '\n');
01214 }
01215
01216 hhstate->prev_entry = entry;
01217
01218 cleanup:
01219 __argp_fmtstream_set_lmargin (stream, old_lm);
01220 __argp_fmtstream_set_wmargin (stream, old_wm);
01221 }
01222
01223
01224 static void
01225 hol_help (struct hol *hol, const struct argp_state *state,
01226 argp_fmtstream_t stream)
01227 {
01228 unsigned num;
01229 struct hol_entry *entry;
01230 struct hol_help_state hhstate = { 0, 0, 0 };
01231
01232 for (entry = hol->entries, num = hol->num_entries; num > 0; entry++, num--)
01233 hol_entry_help (entry, state, stream, &hhstate);
01234
01235 if (hhstate.suppressed_dup_arg && uparams.dup_args_note)
01236 {
01237 const char *tstr = dgettext (state->root_argp->argp_domain, "\
01238 Mandatory or optional arguments to long options are also mandatory or \
01239 optional for any corresponding short options.");
01240 const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_DUP_ARGS_NOTE,
01241 state ? state->root_argp : 0, state);
01242 if (fstr && *fstr)
01243 {
01244 __argp_fmtstream_putc (stream, '\n');
01245 __argp_fmtstream_puts (stream, fstr);
01246 __argp_fmtstream_putc (stream, '\n');
01247 }
01248 if (fstr && fstr != tstr)
01249 free ((char *) fstr);
01250 }
01251 }
01252
01253
01254
01255
01256
01257 static int
01258 add_argless_short_opt (const struct argp_option *opt,
01259 const struct argp_option *real,
01260 const char *domain UNUSED, void *cookie)
01261 {
01262 char **snao_end = cookie;
01263 if (!(opt->arg || real->arg)
01264 && !((opt->flags | real->flags) & OPTION_NO_USAGE))
01265 *(*snao_end)++ = opt->key;
01266 return 0;
01267 }
01268
01269
01270
01271 static int
01272 usage_argful_short_opt (const struct argp_option *opt,
01273 const struct argp_option *real,
01274 const char *domain UNUSED, void *cookie)
01275 {
01276 argp_fmtstream_t stream = cookie;
01277 const char *arg = opt->arg;
01278 int flags = opt->flags | real->flags;
01279
01280 if (! arg)
01281 arg = real->arg;
01282
01283 if (arg && !(flags & OPTION_NO_USAGE))
01284 {
01285 arg = dgettext (domain, arg);
01286
01287 if (flags & OPTION_ARG_OPTIONAL)
01288 __argp_fmtstream_printf (stream, " [-%c[%s]]", opt->key, arg);
01289 else
01290 {
01291
01292
01293 space (stream, 6 + strlen (arg));
01294 __argp_fmtstream_printf (stream, "[-%c %s]", opt->key, arg);
01295 }
01296 }
01297
01298 return 0;
01299 }
01300
01301
01302
01303 static int
01304 usage_long_opt (const struct argp_option *opt,
01305 const struct argp_option *real,
01306 const char *domain UNUSED, void *cookie)
01307 {
01308 argp_fmtstream_t stream = cookie;
01309 const char *arg = opt->arg;
01310 int flags = opt->flags | real->flags;
01311
01312 if (! arg)
01313 arg = real->arg;
01314
01315 if (! (flags & OPTION_NO_USAGE))
01316 {
01317 if (arg)
01318 {
01319 arg = dgettext (domain, arg);
01320 if (flags & OPTION_ARG_OPTIONAL)
01321 __argp_fmtstream_printf (stream, " [--%s[=%s]]", opt->name, arg);
01322 else
01323 __argp_fmtstream_printf (stream, " [--%s=%s]", opt->name, arg);
01324 }
01325 else
01326 __argp_fmtstream_printf (stream, " [--%s]", opt->name);
01327 }
01328
01329 return 0;
01330 }
01331
01332
01333 static void
01334 hol_usage (struct hol *hol, argp_fmtstream_t stream)
01335 {
01336 if (hol->num_entries > 0)
01337 {
01338 unsigned nentries;
01339 struct hol_entry *entry;
01340 char *short_no_arg_opts = alloca (strlen (hol->short_options) + 1);
01341 char *snao_end = short_no_arg_opts;
01342
01343
01344 for (entry = hol->entries, nentries = hol->num_entries
01345 ; nentries > 0
01346 ; entry++, nentries--)
01347 hol_entry_short_iterate (entry, add_argless_short_opt,
01348 entry->argp->argp_domain, &snao_end);
01349 if (snao_end > short_no_arg_opts)
01350 {
01351 *snao_end++ = 0;
01352 __argp_fmtstream_printf (stream, " [-%s]", short_no_arg_opts);
01353 }
01354
01355
01356 for (entry = hol->entries, nentries = hol->num_entries
01357 ; nentries > 0
01358 ; entry++, nentries--)
01359 hol_entry_short_iterate (entry, usage_argful_short_opt,
01360 entry->argp->argp_domain, stream);
01361
01362
01363 for (entry = hol->entries, nentries = hol->num_entries
01364 ; nentries > 0
01365 ; entry++, nentries--)
01366 hol_entry_long_iterate (entry, usage_long_opt,
01367 entry->argp->argp_domain, stream);
01368 }
01369 }
01370
01371
01372
01373 static struct hol *
01374 argp_hol (const struct argp *argp, struct hol_cluster *cluster)
01375 {
01376 const struct argp_child *child = argp->children;
01377 struct hol *hol = make_hol (argp, cluster);
01378 if (child)
01379 while (child->argp)
01380 {
01381 struct hol_cluster *child_cluster =
01382 ((child->group || child->header)
01383
01384 ? hol_add_cluster (hol, child->group, child->header,
01385 child - argp->children, cluster, argp)
01386
01387 : cluster);
01388 hol_append (hol, argp_hol (child->argp, child_cluster)) ;
01389 child++;
01390 }
01391 return hol;
01392 }
01393
01394
01395
01396 static size_t
01397 argp_args_levels (const struct argp *argp)
01398 {
01399 size_t levels = 0;
01400 const struct argp_child *child = argp->children;
01401
01402 if (argp->args_doc && strchr (argp->args_doc, '\n'))
01403 levels++;
01404
01405 if (child)
01406 while (child->argp)
01407 levels += argp_args_levels ((child++)->argp);
01408
01409 return levels;
01410 }
01411
01412
01413
01414
01415
01416
01417 static int
01418 argp_args_usage (const struct argp *argp, const struct argp_state *state,
01419 char **levels, int advance, argp_fmtstream_t stream)
01420 {
01421 char *our_level = *levels;
01422 int multiple = 0;
01423 const struct argp_child *child = argp->children;
01424 const char *tdoc = dgettext (argp->argp_domain, argp->args_doc), *nl = 0;
01425 const char *fdoc = filter_doc (tdoc, ARGP_KEY_HELP_ARGS_DOC, argp, state);
01426
01427 if (fdoc)
01428 {
01429 const char *cp = fdoc;
01430 nl = __strchrnul (cp, '\n');
01431 if (*nl != '\0')
01432
01433
01434 {
01435 int i;
01436 multiple = 1;
01437 for (i = 0; i < *our_level; i++)
01438 cp = nl + 1, nl = __strchrnul (cp, '\n');
01439 (*levels)++;
01440 }
01441
01442
01443
01444 space (stream, 1 + nl - cp);
01445
01446 __argp_fmtstream_write (stream, cp, nl - cp);
01447 }
01448 if (fdoc && fdoc != tdoc)
01449 free ((char *)fdoc);
01450
01451 if (child)
01452 while (child->argp)
01453 advance = !argp_args_usage ((child++)->argp, state, levels, advance, stream);
01454
01455 if (advance && multiple)
01456 {
01457
01458 if (*nl)
01459
01460 {
01461 (*our_level)++;
01462 advance = 0;
01463 }
01464 else if (*our_level > 0)
01465
01466 *our_level = 0;
01467 }
01468
01469 return !advance;
01470 }
01471
01472
01473
01474
01475
01476
01477
01478
01479 static int
01480 argp_doc (const struct argp *argp, const struct argp_state *state,
01481 int post, int pre_blank, int first_only,
01482 argp_fmtstream_t stream)
01483 {
01484 const char *text;
01485 const char *inp_text;
01486 void *input = 0;
01487 int anything = 0;
01488 size_t inp_text_limit = 0;
01489 const char *doc = dgettext (argp->argp_domain, argp->doc);
01490 const struct argp_child *child = argp->children;
01491
01492 if (doc)
01493 {
01494 char *vt = strchr (doc, '\v');
01495 inp_text = post ? (vt ? vt + 1 : 0) : doc;
01496 inp_text_limit = (!post && vt) ? (vt - doc) : 0;
01497 }
01498 else
01499 inp_text = 0;
01500
01501 if (argp->help_filter)
01502
01503 {
01504 if (inp_text_limit)
01505
01506 inp_text = STRNDUP (inp_text, inp_text_limit);
01507 input = __argp_input (argp, state);
01508 text =
01509 (*argp->help_filter) (post
01510 ? ARGP_KEY_HELP_POST_DOC
01511 : ARGP_KEY_HELP_PRE_DOC,
01512 inp_text, input);
01513 }
01514 else
01515 text = (const char *) inp_text;
01516
01517 if (text)
01518 {
01519 if (pre_blank)
01520 __argp_fmtstream_putc (stream, '\n');
01521
01522 if (text == inp_text && inp_text_limit)
01523 __argp_fmtstream_write (stream, inp_text, inp_text_limit);
01524 else
01525 __argp_fmtstream_puts (stream, text);
01526
01527 if (__argp_fmtstream_point (stream) > __argp_fmtstream_lmargin (stream))
01528 __argp_fmtstream_putc (stream, '\n');
01529
01530 anything = 1;
01531 }
01532
01533 if (text && text != inp_text)
01534 free ((char *) text);
01535 if (inp_text && inp_text_limit && argp->help_filter)
01536 free ((char *) inp_text);
01537
01538 if (post && argp->help_filter)
01539
01540 {
01541 text = (*argp->help_filter) (ARGP_KEY_HELP_EXTRA, 0, input);
01542 if (text)
01543 {
01544 if (anything || pre_blank)
01545 __argp_fmtstream_putc (stream, '\n');
01546 __argp_fmtstream_puts (stream, text);
01547 free ((char *) text);
01548 if (__argp_fmtstream_point (stream)
01549 > __argp_fmtstream_lmargin (stream))
01550 __argp_fmtstream_putc (stream, '\n');
01551 anything = 1;
01552 }
01553 }
01554
01555 if (child)
01556 while (child->argp && !(first_only && anything))
01557 anything |=
01558 argp_doc ((child++)->argp, state,
01559 post, anything || pre_blank, first_only,
01560 stream);
01561
01562 return anything;
01563 }
01564
01565
01566
01567
01568
01569
01570 static void
01571 _help (const struct argp *argp, const struct argp_state *state, FILE *stream,
01572 unsigned flags, const char *name)
01573 {
01574 int anything = 0;
01575 struct hol *hol = 0;
01576 argp_fmtstream_t fs;
01577
01578 if (! stream)
01579 return;
01580
01581 FLOCKFILE (stream);
01582
01583 if (! uparams.valid)
01584 fill_in_uparams (state);
01585
01586 fs = __argp_make_fmtstream (stream, 0, uparams.rmargin, 0);
01587 if (! fs)
01588 {
01589 FUNLOCKFILE (stream);
01590 return;
01591 }
01592
01593 if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG))
01594 {
01595 hol = argp_hol (argp, 0);
01596
01597
01598 hol_set_group (hol, "help", -1);
01599 hol_set_group (hol, "version", -1);
01600
01601 hol_sort (hol);
01602 }
01603
01604 if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE))
01605
01606 {
01607 int first_pattern = 1, more_patterns;
01608 size_t num_pattern_levels = argp_args_levels (argp);
01609 char *pattern_levels = alloca (num_pattern_levels);
01610
01611 memset (pattern_levels, 0, num_pattern_levels);
01612
01613 do
01614 {
01615 int old_lm;
01616 int old_wm = __argp_fmtstream_set_wmargin (fs, uparams.usage_indent);
01617 char *levels = pattern_levels;
01618
01619 if (first_pattern)
01620 __argp_fmtstream_printf (fs, "%s %s",
01621 dgettext (argp->argp_domain, "Usage:"),
01622 name);
01623 else
01624 __argp_fmtstream_printf (fs, "%s %s",
01625 dgettext (argp->argp_domain, " or: "),
01626 name);
01627
01628
01629
01630 old_lm = __argp_fmtstream_set_lmargin (fs, uparams.usage_indent);
01631
01632 if (flags & ARGP_HELP_SHORT_USAGE)
01633
01634 {
01635 if (hol->num_entries > 0)
01636 __argp_fmtstream_puts (fs, dgettext (argp->argp_domain,
01637 " [OPTION...]"));
01638 }
01639 else
01640
01641 {
01642 hol_usage (hol, fs);
01643 flags |= ARGP_HELP_SHORT_USAGE;
01644 }
01645
01646 more_patterns = argp_args_usage (argp, state, &levels, 1, fs);
01647
01648 __argp_fmtstream_set_wmargin (fs, old_wm);
01649 __argp_fmtstream_set_lmargin (fs, old_lm);
01650
01651 __argp_fmtstream_putc (fs, '\n');
01652 anything = 1;
01653
01654 first_pattern = 0;
01655 }
01656 while (more_patterns);
01657 }
01658
01659 if (flags & ARGP_HELP_PRE_DOC)
01660 anything |= argp_doc (argp, state, 0, 0, 1, fs);
01661
01662 if (flags & ARGP_HELP_SEE)
01663 {
01664 __argp_fmtstream_printf (fs, dgettext (argp->argp_domain, "\
01665 Try `%s --help' or `%s --usage' for more information.\n"),
01666 name, name);
01667 anything = 1;
01668 }
01669
01670 if (flags & ARGP_HELP_LONG)
01671
01672 {
01673
01674 if (hol->num_entries > 0)
01675 {
01676 if (anything)
01677 __argp_fmtstream_putc (fs, '\n');
01678 hol_help (hol, state, fs);
01679 anything = 1;
01680 }
01681 }
01682
01683 if (flags & ARGP_HELP_POST_DOC)
01684
01685 anything |= argp_doc (argp, state, 1, anything, 0, fs);
01686
01687 if ((flags & ARGP_HELP_BUG_ADDR) && argp_program_bug_address)
01688 {
01689 if (anything)
01690 __argp_fmtstream_putc (fs, '\n');
01691 __argp_fmtstream_printf (fs, dgettext (argp->argp_domain,
01692 "Report bugs to %s.\n"),
01693 argp_program_bug_address);
01694 anything = 1;
01695 }
01696
01697 FUNLOCKFILE (stream);
01698
01699 if (hol)
01700 hol_free (hol);
01701
01702 __argp_fmtstream_free (fs);
01703 }
01704
01705
01706
01707 void __argp_help (const struct argp *argp, FILE *stream,
01708 unsigned flags, char *name)
01709 {
01710 _help (argp, 0, stream, flags, name);
01711 }
01712 #ifdef weak_alias
01713 weak_alias (__argp_help, argp_help)
01714 #endif
01715
01716 char *__argp_basename(char *name)
01717 {
01718 char *short_name = strrchr(name, '/');
01719 return short_name ? short_name + 1 : name;
01720 }
01721
01722 char *
01723 __argp_short_program_name(const struct argp_state *state)
01724 {
01725 if (state)
01726 return state->name;
01727 #if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
01728 return program_invocation_short_name;
01729 #elif HAVE_DECL_PROGRAM_INVOCATION_NAME
01730 return __argp_basename(program_invocation_name);
01731 #else
01732
01733
01734
01735 # if __GNUC__
01736 # warning No reasonable value to return
01737 return "";
01738 # endif
01739 #endif
01740 }
01741
01742
01743
01744 void
01745 __argp_state_help (const struct argp_state *state, FILE *stream, unsigned flags)
01746 {
01747 if ((!state || ! (state->flags & ARGP_NO_ERRS)) && stream)
01748 {
01749 if (state && (state->flags & ARGP_LONG_ONLY))
01750 flags |= ARGP_HELP_LONG_ONLY;
01751
01752 _help (state ? state->root_argp : 0, state, stream, flags,
01753 __argp_short_program_name(state));
01754
01755 if (!state || ! (state->flags & ARGP_NO_EXIT))
01756 {
01757 if (flags & ARGP_HELP_EXIT_ERR)
01758 exit (argp_err_exit_status);
01759 if (flags & ARGP_HELP_EXIT_OK)
01760 exit (0);
01761 }
01762 }
01763 }
01764 #ifdef weak_alias
01765 weak_alias (__argp_state_help, argp_state_help)
01766 #endif
01767
01768
01769
01770
01771 void
01772 __argp_error (const struct argp_state *state, const char *fmt, ...)
01773 {
01774 if (!state || !(state->flags & ARGP_NO_ERRS))
01775 {
01776 FILE *stream = state ? state->err_stream : stderr;
01777
01778 if (stream)
01779 {
01780 va_list ap;
01781
01782 FLOCKFILE (stream);
01783
01784 FPUTS_UNLOCKED (__argp_short_program_name(state),
01785 stream);
01786 PUTC_UNLOCKED (':', stream);
01787 PUTC_UNLOCKED (' ', stream);
01788
01789 va_start (ap, fmt);
01790 vfprintf (stream, fmt, ap);
01791 va_end (ap);
01792
01793 PUTC_UNLOCKED ('\n', stream);
01794
01795 __argp_state_help (state, stream, ARGP_HELP_STD_ERR);
01796
01797 FUNLOCKFILE (stream);
01798 }
01799 }
01800 }
01801 #ifdef weak_alias
01802 weak_alias (__argp_error, argp_error)
01803 #endif
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813 void
01814 __argp_failure (const struct argp_state *state, int status, int errnum,
01815 const char *fmt, ...)
01816 {
01817 if (!state || !(state->flags & ARGP_NO_ERRS))
01818 {
01819 FILE *stream = state ? state->err_stream : stderr;
01820
01821 if (stream)
01822 {
01823 FLOCKFILE (stream);
01824
01825 FPUTS_UNLOCKED (__argp_short_program_name(state),
01826 stream);
01827
01828 if (fmt)
01829 {
01830 va_list ap;
01831
01832 PUTC_UNLOCKED (':', stream);
01833 PUTC_UNLOCKED (' ', stream);
01834
01835 va_start (ap, fmt);
01836 vfprintf (stream, fmt, ap);
01837 va_end (ap);
01838 }
01839
01840 if (errnum)
01841 {
01842 PUTC_UNLOCKED (':', stream);
01843 PUTC_UNLOCKED (' ', stream);
01844 fputs (STRERROR (errnum), stream);
01845 }
01846
01847 PUTC_UNLOCKED ('\n', stream);
01848
01849 FUNLOCKFILE (stream);
01850
01851 if (status && (!state || !(state->flags & ARGP_NO_EXIT)))
01852 exit (status);
01853 }
01854 }
01855 }
01856 #ifdef weak_alias
01857 weak_alias (__argp_failure, argp_failure)
01858 #endif