This source file includes following definitions.
- validate_uparams
- fill_in_uparams
- find_char
- make_hol
- hol_add_cluster
- hol_free
- hol_entry_short_iterate
- hol_entry_long_iterate
- until_short
- hol_entry_first_short
- hol_entry_first_long
- hol_find_entry
- hol_set_group
- group_cmp
- hol_sibling_cluster_cmp
- hol_cousin_cluster_cmp
- hol_cluster_cmp
- hol_cluster_base
- canon_doc_option
- hol_entry_cmp
- hol_entry_qcmp
- hol_sort
- hol_append
- argp_hol
- indent_to
- space
- arg
- filter_doc
- print_header
- hol_cluster_is_child
- comma
- hol_entry_help
- hol_help
- add_argless_short_opt
- usage_argful_short_opt
- usage_long_opt
- hol_usage
- argp_args_levels
- argp_args_usage
- argp_doc
- _help
- __argp_help
- weak_alias
- __argp_state_help
- weak_alias
- weak_alias
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #ifndef _GNU_SOURCE
20 # define _GNU_SOURCE 1
21 #endif
22
23 #ifdef HAVE_CONFIG_H
24 # include <config.h>
25 #endif
26
27 #include <alloca.h>
28 #include <errno.h>
29 #include <stdbool.h>
30 #include <stddef.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <strings.h>
34 #include <assert.h>
35 #include <stdarg.h>
36 #include <ctype.h>
37 #include <limits.h>
38 #ifdef _LIBC
39 # include <../libio/libioP.h>
40 # include <wchar.h>
41 #endif
42
43 #ifdef _LIBC
44 # include <libintl.h>
45 # undef dgettext
46 # define dgettext(domain, msgid) \
47 __dcgettext (domain, msgid, LC_MESSAGES)
48 #else
49 # include "gettext.h"
50 #endif
51
52 #include "argp.h"
53 #include "argp-fmtstream.h"
54 #include "argp-namefrob.h"
55
56 #ifndef SIZE_MAX
57 # define SIZE_MAX ((size_t) -1)
58 #endif
59
60
61
62
63
64
65
66
67
68
69
70 #define DUP_ARGS 0
71 #define DUP_ARGS_NOTE 1
72 #define SHORT_OPT_COL 2
73 #define LONG_OPT_COL 6
74 #define DOC_OPT_COL 2
75 #define OPT_DOC_COL 29
76 #define HEADER_COL 1
77 #define USAGE_INDENT 12
78 #define RMARGIN 79
79
80
81
82 struct uparams
83 {
84
85
86
87
88
89 int dup_args;
90
91
92
93 int dup_args_note;
94
95
96 int short_opt_col;
97 int long_opt_col;
98 int doc_opt_col;
99 int opt_doc_col;
100 int header_col;
101 int usage_indent;
102 int rmargin;
103
104 int valid;
105 };
106
107
108 static struct uparams uparams = {
109 DUP_ARGS, DUP_ARGS_NOTE,
110 SHORT_OPT_COL, LONG_OPT_COL, DOC_OPT_COL, OPT_DOC_COL, HEADER_COL,
111 USAGE_INDENT, RMARGIN
112 };
113
114
115 struct uparam_name
116 {
117 const char name[14];
118 bool is_bool;
119 unsigned char uparams_offs;
120 };
121
122
123 static const struct uparam_name uparam_names[] =
124 {
125 { "dup-args", true, offsetof (struct uparams, dup_args) },
126 { "dup-args-note", true, offsetof (struct uparams, dup_args_note) },
127 { "short-opt-col", false, offsetof (struct uparams, short_opt_col) },
128 { "long-opt-col", false, offsetof (struct uparams, long_opt_col) },
129 { "doc-opt-col", false, offsetof (struct uparams, doc_opt_col) },
130 { "opt-doc-col", false, offsetof (struct uparams, opt_doc_col) },
131 { "header-col", false, offsetof (struct uparams, header_col) },
132 { "usage-indent", false, offsetof (struct uparams, usage_indent) },
133 { "rmargin", false, offsetof (struct uparams, rmargin) }
134 };
135 #define nuparam_names (sizeof (uparam_names) / sizeof (uparam_names[0]))
136
137 static void
138 validate_uparams (const struct argp_state *state, struct uparams *upptr)
139 {
140 const struct uparam_name *up;
141
142 for (up = uparam_names; up < uparam_names + nuparam_names; up++)
143 {
144 if (up->is_bool
145 || up->uparams_offs == offsetof (struct uparams, rmargin))
146 continue;
147 if (*(int *)((char *)upptr + up->uparams_offs) >= upptr->rmargin)
148 {
149 __argp_failure (state, 0, 0,
150 dgettext (state == NULL ? NULL
151 : state->root_argp->argp_domain,
152 "\
153 ARGP_HELP_FMT: %s value is less than or equal to %s"),
154 "rmargin", up->name);
155 return;
156 }
157 }
158 uparams = *upptr;
159 uparams.valid = 1;
160 }
161
162
163 static void
164 fill_in_uparams (const struct argp_state *state)
165 {
166 const char *var = getenv ("ARGP_HELP_FMT");
167 struct uparams new_params = uparams;
168
169 #define SKIPWS(p) do { while (isspace ((unsigned char) *p)) p++; } while (0);
170
171 if (var)
172 {
173
174 while (*var)
175 {
176 SKIPWS (var);
177
178 if (isalpha ((unsigned char) *var))
179 {
180 size_t var_len;
181 const struct uparam_name *un;
182 int unspec = 0, val = 0;
183 const char *arg = var;
184
185 while (isalnum ((unsigned char) *arg) || *arg == '-' || *arg == '_')
186 arg++;
187 var_len = arg - var;
188
189 SKIPWS (arg);
190
191 if (*arg == '\0' || *arg == ',')
192 unspec = 1;
193 else if (*arg == '=')
194 {
195 arg++;
196 SKIPWS (arg);
197 }
198
199 if (unspec)
200 {
201 if (var[0] == 'n' && var[1] == 'o' && var[2] == '-')
202 {
203 val = 0;
204 var += 3;
205 var_len -= 3;
206 }
207 else
208 val = 1;
209 }
210 else if (isdigit ((unsigned char) *arg))
211 {
212 val = atoi (arg);
213 while (isdigit ((unsigned char) *arg))
214 arg++;
215 SKIPWS (arg);
216 }
217
218 for (un = uparam_names;
219 un < uparam_names + nuparam_names;
220 un++)
221 if (strlen (un->name) == var_len
222 && strncmp (var, un->name, var_len) == 0)
223 {
224 if (unspec && !un->is_bool)
225 __argp_failure (state, 0, 0,
226 dgettext (state == NULL ? NULL
227 : state->root_argp->argp_domain,
228 "\
229 %.*s: ARGP_HELP_FMT parameter requires a value"),
230 (int) var_len, var);
231 else
232 *(int *)((char *)&new_params + un->uparams_offs) = val;
233 break;
234 }
235 if (un == uparam_names + nuparam_names)
236 __argp_failure (state, 0, 0,
237 dgettext (state == NULL ? NULL
238 : state->root_argp->argp_domain, "\
239 %.*s: Unknown ARGP_HELP_FMT parameter"),
240 (int) var_len, var);
241
242 var = arg;
243 if (*var == ',')
244 var++;
245 }
246 else if (*var)
247 {
248 __argp_failure (state, 0, 0,
249 dgettext (state == NULL ? NULL
250 : state->root_argp->argp_domain,
251 "Garbage in ARGP_HELP_FMT: %s"), var);
252 break;
253 }
254 }
255 validate_uparams (state, &new_params);
256 }
257 }
258
259
260
261
262
263 #define ovisible(opt) (! ((opt)->flags & OPTION_HIDDEN))
264
265
266 #define oalias(opt) ((opt)->flags & OPTION_ALIAS)
267
268
269 #define odoc(opt) ((opt)->flags & OPTION_DOC)
270
271
272 #define onotrans(opt) ((opt)->flags & OPTION_NO_TRANS)
273
274
275 #define oend(opt) __option_is_end (opt)
276
277
278 #define oshort(opt) __option_is_short (opt)
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345 static int
346 find_char (char ch, char *beg, char *end)
347 {
348 while (beg < end)
349 if (*beg == ch)
350 return 1;
351 else
352 beg++;
353 return 0;
354 }
355
356
357
358
359 struct hol_cluster;
360
361 struct hol_entry
362 {
363
364 const struct argp_option *opt;
365
366 unsigned num;
367
368
369
370
371
372
373
374 char *short_options;
375
376
377
378
379 int group;
380
381
382 struct hol_cluster *cluster;
383
384
385 const struct argp *argp;
386
387
388 unsigned ord;
389 };
390
391
392 struct hol_cluster
393 {
394
395 const char *header;
396
397
398
399
400 int index;
401
402
403
404 int group;
405
406
407
408 struct hol_cluster *parent;
409
410
411 const struct argp *argp;
412
413
414 int depth;
415
416
417
418 struct hol_cluster *next;
419 };
420
421
422 struct hol
423 {
424
425 struct hol_entry *entries;
426
427
428 unsigned num_entries;
429
430
431
432 char *short_options;
433
434
435 struct hol_cluster *clusters;
436 };
437
438
439
440 static struct hol *
441 make_hol (const struct argp *argp, struct hol_cluster *cluster)
442 {
443 char *so;
444 const struct argp_option *o;
445 const struct argp_option *opts = argp->options;
446 struct hol_entry *entry;
447 unsigned num_short_options = 0;
448 struct hol *hol = malloc (sizeof (struct hol));
449
450 assert (hol);
451
452 hol->num_entries = 0;
453 hol->clusters = 0;
454
455 if (opts)
456 {
457 int cur_group = 0;
458
459
460 assert (! oalias (opts));
461
462
463 for (o = opts; ! oend (o); o++)
464 {
465 if (! oalias (o))
466 hol->num_entries++;
467 if (oshort (o))
468 num_short_options++;
469 }
470
471 hol->entries = malloc (sizeof (struct hol_entry) * hol->num_entries);
472 hol->short_options = malloc (num_short_options + 1);
473
474 assert (hol->entries && hol->short_options);
475 if (SIZE_MAX <= UINT_MAX)
476 assert (hol->num_entries <= SIZE_MAX / sizeof (struct hol_entry));
477
478
479 so = hol->short_options;
480 for (o = opts, entry = hol->entries; ! oend (o); entry++)
481 {
482 entry->opt = o;
483 entry->num = 0;
484 entry->short_options = so;
485 entry->group = cur_group =
486 o->group
487 ? o->group
488 : ((!o->name && !o->key)
489 ? cur_group + 1
490 : cur_group);
491 entry->cluster = cluster;
492 entry->argp = argp;
493
494 do
495 {
496 entry->num++;
497 if (oshort (o) && ! find_char (o->key, hol->short_options, so))
498
499 *so++ = o->key;
500 o++;
501 }
502 while (! oend (o) && oalias (o));
503 }
504 *so = '\0';
505 }
506
507 return hol;
508 }
509
510
511
512
513 static struct hol_cluster *
514 hol_add_cluster (struct hol *hol, int group, const char *header, int index,
515 struct hol_cluster *parent, const struct argp *argp)
516 {
517 struct hol_cluster *cl = malloc (sizeof (struct hol_cluster));
518 if (cl)
519 {
520 cl->group = group;
521 cl->header = header;
522
523 cl->index = index;
524 cl->parent = parent;
525 cl->argp = argp;
526 cl->depth = parent ? parent->depth + 1 : 0;
527
528 cl->next = hol->clusters;
529 hol->clusters = cl;
530 }
531 return cl;
532 }
533
534
535 static void
536 hol_free (struct hol *hol)
537 {
538 struct hol_cluster *cl = hol->clusters;
539
540 while (cl)
541 {
542 struct hol_cluster *next = cl->next;
543 free (cl);
544 cl = next;
545 }
546
547 if (hol->num_entries > 0)
548 {
549 free (hol->entries);
550 free (hol->short_options);
551 }
552
553 free (hol);
554 }
555
556
557
558
559 static int
560 hol_entry_short_iterate (const struct hol_entry *entry,
561 int (*func)(const struct argp_option *opt,
562 const struct argp_option *real,
563 const char *domain, void *cookie),
564 const char *domain, void *cookie)
565 {
566 unsigned nopts;
567 int val = 0;
568 const struct argp_option *opt, *real = entry->opt;
569 char *so = entry->short_options;
570
571 for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--)
572 if (oshort (opt) && *so == opt->key)
573 {
574 if (!oalias (opt))
575 real = opt;
576 if (ovisible (opt))
577 val = (*func)(opt, real, domain, cookie);
578 so++;
579 }
580
581 return val;
582 }
583
584
585
586
587 static inline int
588 #if (__GNUC__ >= 3) || (__clang_major__ >= 4)
589 __attribute__ ((always_inline))
590 #endif
591 hol_entry_long_iterate (const struct hol_entry *entry,
592 int (*func)(const struct argp_option *opt,
593 const struct argp_option *real,
594 const char *domain, void *cookie),
595 const char *domain, void *cookie)
596 {
597 unsigned nopts;
598 int val = 0;
599 const struct argp_option *opt, *real = entry->opt;
600
601 for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--)
602 if (opt->name)
603 {
604 if (!oalias (opt))
605 real = opt;
606 if (ovisible (opt))
607 val = (*func)(opt, real, domain, cookie);
608 }
609
610 return val;
611 }
612
613
614 static int
615 until_short (const struct argp_option *opt, const struct argp_option *real,
616 const char *domain, void *cookie)
617 {
618 return oshort (opt) ? opt->key : 0;
619 }
620
621
622 static char
623 hol_entry_first_short (const struct hol_entry *entry)
624 {
625 return hol_entry_short_iterate (entry, until_short,
626 entry->argp->argp_domain, 0);
627 }
628
629
630 static const char *
631 hol_entry_first_long (const struct hol_entry *entry)
632 {
633 const struct argp_option *opt;
634 unsigned num;
635 for (opt = entry->opt, num = entry->num; num > 0; opt++, num--)
636 if (opt->name && ovisible (opt))
637 return opt->name;
638 return 0;
639 }
640
641
642
643 static struct hol_entry *
644 hol_find_entry (struct hol *hol, const char *name)
645 {
646 struct hol_entry *entry = hol->entries;
647 unsigned num_entries = hol->num_entries;
648
649 while (num_entries-- > 0)
650 {
651 const struct argp_option *opt = entry->opt;
652 unsigned num_opts = entry->num;
653
654 while (num_opts-- > 0)
655 if (opt->name && ovisible (opt) && strcmp (opt->name, name) == 0)
656 return entry;
657 else
658 opt++;
659
660 entry++;
661 }
662
663 return 0;
664 }
665
666
667
668 static void
669 hol_set_group (struct hol *hol, const char *name, int group)
670 {
671 struct hol_entry *entry = hol_find_entry (hol, name);
672 if (entry)
673 entry->group = group;
674 }
675
676
677
678
679
680 static int
681 group_cmp (int group1, int group2)
682 {
683 if ((group1 < 0 && group2 < 0) || (group1 >= 0 && group2 >= 0))
684 return group1 - group2;
685 else
686
687
688 return group2 - group1;
689 }
690
691
692
693 static int
694 hol_sibling_cluster_cmp (const struct hol_cluster *cl1,
695 const struct hol_cluster *cl2)
696 {
697
698 int cmp = group_cmp (cl1->group, cl2->group);
699 if (cmp != 0)
700 return cmp;
701
702
703 return cl2->index - cl1->index;
704 }
705
706
707
708 static int
709 hol_cousin_cluster_cmp (const struct hol_cluster *cl1,
710 const struct hol_cluster *cl2)
711 {
712 if (cl1->parent == cl2->parent)
713 return hol_sibling_cluster_cmp (cl1, cl2);
714 else
715 {
716
717 int cmp = hol_cousin_cluster_cmp (cl1->parent, cl2->parent);
718 if (cmp != 0)
719 return cmp;
720
721
722 cmp = group_cmp (cl1->group, cl2->group);
723 if (cmp != 0)
724 return cmp;
725
726
727 return cl2->index - cl1->index;
728 }
729 }
730
731
732
733 static int
734 hol_cluster_cmp (const struct hol_cluster *cl1, const struct hol_cluster *cl2)
735 {
736
737
738
739 if (cl1->depth > cl2->depth)
740 {
741 do
742 cl1 = cl1->parent;
743 while (cl1->depth > cl2->depth);
744 int cmp = hol_cousin_cluster_cmp (cl1, cl2);
745 if (cmp != 0)
746 return cmp;
747
748 return 1;
749 }
750 else if (cl1->depth < cl2->depth)
751 {
752 do
753 cl2 = cl2->parent;
754 while (cl1->depth < cl2->depth);
755 int cmp = hol_cousin_cluster_cmp (cl1, cl2);
756 if (cmp != 0)
757 return cmp;
758
759 return -1;
760 }
761 else
762 return hol_cousin_cluster_cmp (cl1, cl2);
763 }
764
765
766
767 static struct hol_cluster *
768 hol_cluster_base (struct hol_cluster *cl)
769 {
770 while (cl->parent)
771 cl = cl->parent;
772 return cl;
773 }
774
775
776
777
778 static int
779 canon_doc_option (const char **name)
780 {
781 int non_opt;
782
783 while (isspace ((unsigned char) **name))
784 (*name)++;
785
786 non_opt = (**name != '-');
787
788 while (**name && !isalnum ((unsigned char) **name))
789 (*name)++;
790 return non_opt;
791 }
792
793
794
795
796
797
798
799
800
801
802
803
804 static int
805 hol_entry_cmp (const struct hol_entry *entry1,
806 const struct hol_entry *entry2)
807 {
808
809
810
811 int group1 = (entry1->cluster
812 ? hol_cluster_base (entry1->cluster)->group
813 : entry1->group);
814 int group2 = (entry2->cluster
815 ? hol_cluster_base (entry2->cluster)->group
816 : entry2->group);
817 int cmp = group_cmp (group1, group2);
818 if (cmp != 0)
819 return cmp;
820
821
822
823
824 cmp = (entry1->cluster != NULL) - (entry2->cluster != NULL);
825 if (cmp != 0)
826 return cmp;
827
828
829 if (entry1->cluster != NULL)
830 {
831 cmp = hol_cluster_cmp (entry1->cluster, entry2->cluster);
832 if (cmp != 0)
833 return cmp;
834 }
835
836
837
838 cmp = group_cmp (entry1->group, entry2->group);
839 if (cmp != 0)
840 return cmp;
841
842
843
844
845
846 const char *long1 = hol_entry_first_long (entry1);
847 const char *long2 = hol_entry_first_long (entry2);
848 int doc1 =
849 (odoc (entry1->opt) ? long1 != NULL && canon_doc_option (&long1) : 0);
850 int doc2 =
851 (odoc (entry2->opt) ? long2 != NULL && canon_doc_option (&long2) : 0);
852 cmp = doc1 - doc2;
853 if (cmp != 0)
854 return cmp;
855
856
857
858
859
860
861
862 int short1 = hol_entry_first_short (entry1);
863 int short2 = hol_entry_first_short (entry2);
864 unsigned char first1 = short1 ? short1 : long1 != NULL ? *long1 : 0;
865 unsigned char first2 = short2 ? short2 : long2 != NULL ? *long2 : 0;
866
867
868
869 cmp = tolower (first1) - tolower (first2);
870 if (cmp != 0)
871 return cmp;
872
873
874 cmp = first2 - first1;
875 if (cmp != 0)
876 return cmp;
877
878
879
880
881 cmp = (short1 != 0) - (short2 != 0);
882 if (cmp != 0)
883 return cmp;
884
885
886 if (short1 == 0)
887 {
888 cmp = (long1 != NULL) - (long2 != NULL);
889 if (cmp != 0)
890 return cmp;
891
892 if (long1 != NULL)
893 {
894 cmp = __strcasecmp (long1, long2);
895 if (cmp != 0)
896 return cmp;
897 }
898 }
899
900
901
902 return 0;
903 }
904
905
906 static int
907 hol_entry_qcmp (const void *entry1_v, const void *entry2_v)
908 {
909 return hol_entry_cmp (entry1_v, entry2_v);
910 }
911
912
913
914
915 static void
916 hol_sort (struct hol *hol)
917 {
918 if (hol->num_entries > 0)
919 {
920 unsigned i;
921 struct hol_entry *e;
922 for (i = 0, e = hol->entries; i < hol->num_entries; i++, e++)
923 e->ord = i;
924
925 qsort (hol->entries, hol->num_entries, sizeof (struct hol_entry),
926 hol_entry_qcmp);
927 }
928 }
929
930
931
932
933
934
935 static void
936 hol_append (struct hol *hol, struct hol *more)
937 {
938 struct hol_cluster **cl_end = &hol->clusters;
939
940
941 while (*cl_end)
942 cl_end = &(*cl_end)->next;
943 *cl_end = more->clusters;
944 more->clusters = 0;
945
946
947 if (more->num_entries > 0)
948 {
949 if (hol->num_entries == 0)
950 {
951 hol->num_entries = more->num_entries;
952 hol->entries = more->entries;
953 hol->short_options = more->short_options;
954 more->num_entries = 0;
955 }
956 else
957
958
959 {
960 unsigned left;
961 char *so, *more_so;
962 struct hol_entry *e;
963 unsigned num_entries = hol->num_entries + more->num_entries;
964 struct hol_entry *entries =
965 malloc (num_entries * sizeof (struct hol_entry));
966 unsigned hol_so_len = strlen (hol->short_options);
967 char *short_options =
968 malloc (hol_so_len + strlen (more->short_options) + 1);
969
970 assert (entries && short_options);
971 if (SIZE_MAX <= UINT_MAX)
972 assert (num_entries <= SIZE_MAX / sizeof (struct hol_entry));
973
974 __mempcpy (__mempcpy (entries, hol->entries,
975 hol->num_entries * sizeof (struct hol_entry)),
976 more->entries,
977 more->num_entries * sizeof (struct hol_entry));
978
979 __mempcpy (short_options, hol->short_options, hol_so_len);
980
981
982 for (e = entries, left = hol->num_entries; left > 0; e++, left--)
983 e->short_options
984 = short_options + (e->short_options - hol->short_options);
985
986
987
988 so = short_options + hol_so_len;
989 more_so = more->short_options;
990 for (left = more->num_entries; left > 0; e++, left--)
991 {
992 int opts_left;
993 const struct argp_option *opt;
994
995 e->short_options = so;
996
997 for (opts_left = e->num, opt = e->opt; opts_left; opt++, opts_left--)
998 {
999 int ch = *more_so;
1000 if (oshort (opt) && ch == opt->key)
1001
1002 {
1003 if (! find_char (ch, short_options,
1004 short_options + hol_so_len))
1005
1006
1007 *so++ = ch;
1008 more_so++;
1009 }
1010 }
1011 }
1012
1013 *so = '\0';
1014
1015 free (hol->entries);
1016 free (hol->short_options);
1017
1018 hol->entries = entries;
1019 hol->num_entries = num_entries;
1020 hol->short_options = short_options;
1021 }
1022 }
1023
1024 hol_free (more);
1025 }
1026
1027
1028
1029 static struct hol *
1030 argp_hol (const struct argp *argp, struct hol_cluster *cluster)
1031 {
1032 const struct argp_child *child = argp->children;
1033 struct hol *hol = make_hol (argp, cluster);
1034 if (child)
1035 while (child->argp)
1036 {
1037 struct hol_cluster *child_cluster =
1038 ((child->group || child->header)
1039
1040 ? hol_add_cluster (hol, child->group, child->header,
1041 child - argp->children, cluster, argp)
1042
1043 : cluster);
1044 hol_append (hol, argp_hol (child->argp, child_cluster)) ;
1045 child++;
1046 }
1047 return hol;
1048 }
1049
1050
1051
1052
1053
1054 static void
1055 indent_to (argp_fmtstream_t stream, unsigned col)
1056 {
1057 int needed = col - __argp_fmtstream_point (stream);
1058 while (needed-- > 0)
1059 __argp_fmtstream_putc (stream, ' ');
1060 }
1061
1062
1063
1064 static void
1065 space (argp_fmtstream_t stream, size_t ensure)
1066 {
1067 if (__argp_fmtstream_point (stream) + ensure
1068 >= __argp_fmtstream_rmargin (stream))
1069 __argp_fmtstream_putc (stream, '\n');
1070 else
1071 __argp_fmtstream_putc (stream, ' ');
1072 }
1073
1074
1075
1076
1077 static void
1078 arg (const struct argp_option *real, const char *req_fmt, const char *opt_fmt,
1079 const char *domain, argp_fmtstream_t stream)
1080 {
1081 if (real->arg)
1082 {
1083 if (real->flags & OPTION_ARG_OPTIONAL)
1084 __argp_fmtstream_printf (stream, opt_fmt,
1085 dgettext (domain, real->arg));
1086 else
1087 __argp_fmtstream_printf (stream, req_fmt,
1088 dgettext (domain, real->arg));
1089 }
1090 }
1091
1092
1093
1094
1095 struct hol_help_state
1096 {
1097
1098 struct hol_entry *prev_entry;
1099
1100
1101
1102 int sep_groups;
1103
1104
1105
1106 int suppressed_dup_arg;
1107 };
1108
1109
1110
1111
1112 struct pentry_state
1113 {
1114 const struct hol_entry *entry;
1115 argp_fmtstream_t stream;
1116 struct hol_help_state *hhstate;
1117
1118
1119 int first;
1120
1121
1122 const struct argp_state *state;
1123 };
1124
1125
1126 static const char *
1127 filter_doc (const char *doc, int key, const struct argp *argp,
1128 const struct argp_state *state)
1129 {
1130 if (argp && argp->help_filter)
1131
1132 {
1133 void *input = __argp_input (argp, state);
1134 return (*argp->help_filter) (key, doc, input);
1135 }
1136 else
1137
1138 return doc;
1139 }
1140
1141
1142
1143
1144
1145
1146 static void
1147 print_header (const char *str, const struct argp *argp,
1148 struct pentry_state *pest)
1149 {
1150 const char *tstr = str ? dgettext (argp->argp_domain, str) : NULL;
1151 const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_HEADER, argp, pest->state);
1152
1153 if (fstr)
1154 {
1155 if (*fstr)
1156 {
1157 if (pest->hhstate->prev_entry)
1158
1159 __argp_fmtstream_putc (pest->stream, '\n');
1160 indent_to (pest->stream, uparams.header_col);
1161 __argp_fmtstream_set_lmargin (pest->stream, uparams.header_col);
1162 __argp_fmtstream_set_wmargin (pest->stream, uparams.header_col);
1163 __argp_fmtstream_puts (pest->stream, fstr);
1164 __argp_fmtstream_set_lmargin (pest->stream, 0);
1165 __argp_fmtstream_putc (pest->stream, '\n');
1166 }
1167
1168 pest->hhstate->sep_groups = 1;
1169 }
1170
1171 if (fstr != tstr)
1172 free ((char *) fstr);
1173 }
1174
1175
1176 static int
1177 hol_cluster_is_child (const struct hol_cluster *cl1,
1178 const struct hol_cluster *cl2)
1179 {
1180 while (cl1 && cl1 != cl2)
1181 cl1 = cl1->parent;
1182 return cl1 == cl2;
1183 }
1184
1185
1186
1187
1188
1189 static void
1190 comma (unsigned col, struct pentry_state *pest)
1191 {
1192 if (pest->first)
1193 {
1194 const struct hol_entry *pe = pest->hhstate->prev_entry;
1195 const struct hol_cluster *cl = pest->entry->cluster;
1196
1197 if (pest->hhstate->sep_groups && pe && pest->entry->group != pe->group)
1198 __argp_fmtstream_putc (pest->stream, '\n');
1199
1200 if (cl && cl->header && *cl->header
1201 && (!pe
1202 || (pe->cluster != cl
1203 && !hol_cluster_is_child (pe->cluster, cl))))
1204
1205
1206
1207
1208 {
1209 int old_wm = __argp_fmtstream_wmargin (pest->stream);
1210 print_header (cl->header, cl->argp, pest);
1211 __argp_fmtstream_set_wmargin (pest->stream, old_wm);
1212 }
1213
1214 pest->first = 0;
1215 }
1216 else
1217 __argp_fmtstream_puts (pest->stream, ", ");
1218
1219 indent_to (pest->stream, col);
1220 }
1221
1222
1223 static void
1224 hol_entry_help (struct hol_entry *entry, const struct argp_state *state,
1225 argp_fmtstream_t stream, struct hol_help_state *hhstate)
1226 {
1227 unsigned num;
1228 const struct argp_option *real = entry->opt, *opt;
1229 char *so = entry->short_options;
1230 int have_long_opt = 0;
1231
1232 int old_lm = __argp_fmtstream_set_lmargin (stream, 0);
1233 int old_wm = __argp_fmtstream_wmargin (stream);
1234
1235
1236 struct pentry_state pest = { entry, stream, hhstate, 1, state };
1237
1238 if (! odoc (real))
1239 for (opt = real, num = entry->num; num > 0; opt++, num--)
1240 if (opt->name && ovisible (opt))
1241 {
1242 have_long_opt = 1;
1243 break;
1244 }
1245
1246
1247 __argp_fmtstream_set_wmargin (stream, uparams.short_opt_col);
1248 for (opt = real, num = entry->num; num > 0; opt++, num--)
1249 if (oshort (opt) && opt->key == *so)
1250
1251 {
1252 if (ovisible (opt))
1253 {
1254 comma (uparams.short_opt_col, &pest);
1255 __argp_fmtstream_putc (stream, '-');
1256 __argp_fmtstream_putc (stream, *so);
1257 if (!have_long_opt || uparams.dup_args)
1258 arg (real, " %s", "[%s]",
1259 state == NULL ? NULL : state->root_argp->argp_domain,
1260 stream);
1261 else if (real->arg)
1262 hhstate->suppressed_dup_arg = 1;
1263 }
1264 so++;
1265 }
1266
1267
1268 if (odoc (real))
1269
1270 {
1271 __argp_fmtstream_set_wmargin (stream, uparams.doc_opt_col);
1272 for (opt = real, num = entry->num; num > 0; opt++, num--)
1273 if (opt->name && ovisible (opt))
1274 {
1275 comma (uparams.doc_opt_col, &pest);
1276
1277
1278
1279 __argp_fmtstream_puts (stream,
1280 dgettext (state == NULL ? NULL
1281 : state->root_argp->argp_domain,
1282 opt->name));
1283 }
1284 }
1285 else
1286
1287 {
1288 __argp_fmtstream_set_wmargin (stream, uparams.long_opt_col);
1289 for (opt = real, num = entry->num; num > 0; opt++, num--)
1290 if (opt->name && ovisible (opt))
1291 {
1292 comma (uparams.long_opt_col, &pest);
1293 __argp_fmtstream_printf (stream, "--%s", opt->name);
1294 arg (real, "=%s", "[=%s]",
1295 state == NULL ? NULL : state->root_argp->argp_domain, stream);
1296 }
1297 }
1298
1299
1300 __argp_fmtstream_set_lmargin (stream, 0);
1301
1302 if (pest.first)
1303 {
1304
1305 if (!oshort (real) && !real->name)
1306
1307 print_header (real->doc, entry->argp, &pest);
1308 else
1309
1310 goto cleanup;
1311 }
1312 else
1313 {
1314 const char *tstr = real->doc ? dgettext (state == NULL ? NULL
1315 : state->root_argp->argp_domain,
1316 real->doc) : 0;
1317 const char *fstr = filter_doc (tstr, real->key, entry->argp, state);
1318 if (fstr && *fstr)
1319 {
1320 unsigned int col = __argp_fmtstream_point (stream);
1321
1322 __argp_fmtstream_set_lmargin (stream, uparams.opt_doc_col);
1323 __argp_fmtstream_set_wmargin (stream, uparams.opt_doc_col);
1324
1325 if (col > (unsigned int) (uparams.opt_doc_col + 3))
1326 __argp_fmtstream_putc (stream, '\n');
1327 else if (col >= (unsigned int) uparams.opt_doc_col)
1328 __argp_fmtstream_puts (stream, " ");
1329 else
1330 indent_to (stream, uparams.opt_doc_col);
1331
1332 __argp_fmtstream_puts (stream, fstr);
1333 }
1334 if (fstr && fstr != tstr)
1335 free ((char *) fstr);
1336
1337
1338 __argp_fmtstream_set_lmargin (stream, 0);
1339 __argp_fmtstream_putc (stream, '\n');
1340 }
1341
1342 hhstate->prev_entry = entry;
1343
1344 cleanup:
1345 __argp_fmtstream_set_lmargin (stream, old_lm);
1346 __argp_fmtstream_set_wmargin (stream, old_wm);
1347 }
1348
1349
1350 static void
1351 hol_help (struct hol *hol, const struct argp_state *state,
1352 argp_fmtstream_t stream)
1353 {
1354 unsigned num;
1355 struct hol_entry *entry;
1356 struct hol_help_state hhstate = { 0, 0, 0 };
1357
1358 for (entry = hol->entries, num = hol->num_entries; num > 0; entry++, num--)
1359 hol_entry_help (entry, state, stream, &hhstate);
1360
1361 if (hhstate.suppressed_dup_arg && uparams.dup_args_note)
1362 {
1363 const char *tstr = dgettext (state == NULL ? NULL
1364 : state->root_argp->argp_domain, "\
1365 Mandatory or optional arguments to long options are also mandatory or \
1366 optional for any corresponding short options.");
1367 const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_DUP_ARGS_NOTE,
1368 state ? state->root_argp : 0, state);
1369 if (fstr && *fstr)
1370 {
1371 __argp_fmtstream_putc (stream, '\n');
1372 __argp_fmtstream_puts (stream, fstr);
1373 __argp_fmtstream_putc (stream, '\n');
1374 }
1375 if (fstr && fstr != tstr)
1376 free ((char *) fstr);
1377 }
1378 }
1379
1380
1381
1382
1383
1384 static int
1385 add_argless_short_opt (const struct argp_option *opt,
1386 const struct argp_option *real,
1387 const char *domain, void *cookie)
1388 {
1389 char **snao_end = cookie;
1390 if (!(opt->arg || real->arg)
1391 && !((opt->flags | real->flags) & OPTION_NO_USAGE))
1392 *(*snao_end)++ = opt->key;
1393 return 0;
1394 }
1395
1396
1397
1398 static int
1399 usage_argful_short_opt (const struct argp_option *opt,
1400 const struct argp_option *real,
1401 const char *domain, void *cookie)
1402 {
1403 argp_fmtstream_t stream = cookie;
1404 const char *arg = opt->arg;
1405 int flags = opt->flags | real->flags;
1406
1407 if (! arg)
1408 arg = real->arg;
1409
1410 if (arg && !(flags & OPTION_NO_USAGE))
1411 {
1412 arg = dgettext (domain, arg);
1413
1414 if (flags & OPTION_ARG_OPTIONAL)
1415 __argp_fmtstream_printf (stream, " [-%c[%s]]", opt->key, arg);
1416 else
1417 {
1418
1419
1420 space (stream, 6 + strlen (arg));
1421 __argp_fmtstream_printf (stream, "[-%c %s]", opt->key, arg);
1422 }
1423 }
1424
1425 return 0;
1426 }
1427
1428
1429
1430 static int
1431 usage_long_opt (const struct argp_option *opt,
1432 const struct argp_option *real,
1433 const char *domain, void *cookie)
1434 {
1435 argp_fmtstream_t stream = cookie;
1436 const char *arg = opt->arg;
1437 int flags = opt->flags | real->flags;
1438
1439 if (! arg)
1440 arg = real->arg;
1441
1442 if (! (flags & OPTION_NO_USAGE))
1443 {
1444 if (arg)
1445 {
1446 arg = dgettext (domain, arg);
1447 if (flags & OPTION_ARG_OPTIONAL)
1448 __argp_fmtstream_printf (stream, " [--%s[=%s]]", opt->name, arg);
1449 else
1450 __argp_fmtstream_printf (stream, " [--%s=%s]", opt->name, arg);
1451 }
1452 else
1453 __argp_fmtstream_printf (stream, " [--%s]", opt->name);
1454 }
1455
1456 return 0;
1457 }
1458
1459
1460 static void
1461 hol_usage (struct hol *hol, argp_fmtstream_t stream)
1462 {
1463 if (hol->num_entries > 0)
1464 {
1465 unsigned nentries;
1466 struct hol_entry *entry;
1467 char *short_no_arg_opts = alloca (strlen (hol->short_options) + 1);
1468 char *snao_end = short_no_arg_opts;
1469
1470
1471 for (entry = hol->entries, nentries = hol->num_entries
1472 ; nentries > 0
1473 ; entry++, nentries--)
1474 hol_entry_short_iterate (entry, add_argless_short_opt,
1475 entry->argp->argp_domain, &snao_end);
1476 if (snao_end > short_no_arg_opts)
1477 {
1478 *snao_end++ = 0;
1479 __argp_fmtstream_printf (stream, " [-%s]", short_no_arg_opts);
1480 }
1481
1482
1483 for (entry = hol->entries, nentries = hol->num_entries
1484 ; nentries > 0
1485 ; entry++, nentries--)
1486 hol_entry_short_iterate (entry, usage_argful_short_opt,
1487 entry->argp->argp_domain, stream);
1488
1489
1490 for (entry = hol->entries, nentries = hol->num_entries
1491 ; nentries > 0
1492 ; entry++, nentries--)
1493 hol_entry_long_iterate (entry, usage_long_opt,
1494 entry->argp->argp_domain, stream);
1495 }
1496 }
1497
1498
1499
1500 static size_t
1501 argp_args_levels (const struct argp *argp)
1502 {
1503 size_t levels = 0;
1504 const struct argp_child *child = argp->children;
1505
1506 if (argp->args_doc && strchr (argp->args_doc, '\n'))
1507 levels++;
1508
1509 if (child)
1510 while (child->argp)
1511 levels += argp_args_levels ((child++)->argp);
1512
1513 return levels;
1514 }
1515
1516
1517
1518
1519
1520
1521 static int
1522 argp_args_usage (const struct argp *argp, const struct argp_state *state,
1523 char **levels, int advance, argp_fmtstream_t stream)
1524 {
1525 char *our_level = *levels;
1526 int multiple = 0;
1527 const struct argp_child *child = argp->children;
1528 const char *tdoc =
1529 argp->args_doc ? dgettext (argp->argp_domain, argp->args_doc) : NULL;
1530 const char *fdoc = filter_doc (tdoc, ARGP_KEY_HELP_ARGS_DOC, argp, state);
1531 const char *nl = NULL;
1532
1533 if (fdoc)
1534 {
1535 const char *cp = fdoc;
1536 nl = __strchrnul (cp, '\n');
1537 if (*nl != '\0')
1538
1539
1540 {
1541 int i;
1542 multiple = 1;
1543 for (i = 0; i < *our_level; i++)
1544 cp = nl + 1, nl = __strchrnul (cp, '\n');
1545 (*levels)++;
1546 }
1547
1548
1549
1550 space (stream, 1 + nl - cp);
1551
1552 __argp_fmtstream_write (stream, cp, nl - cp);
1553 }
1554 if (fdoc && fdoc != tdoc)
1555 free ((char *)fdoc);
1556
1557 if (child)
1558 while (child->argp)
1559 advance = !argp_args_usage ((child++)->argp, state, levels, advance, stream);
1560
1561 if (advance && multiple)
1562 {
1563
1564 if (*nl)
1565
1566 {
1567 (*our_level)++;
1568 advance = 0;
1569 }
1570 else if (*our_level > 0)
1571
1572 *our_level = 0;
1573 }
1574
1575 return !advance;
1576 }
1577
1578
1579
1580
1581
1582
1583
1584
1585 static int
1586 argp_doc (const struct argp *argp, const struct argp_state *state,
1587 int post, int pre_blank, int first_only,
1588 argp_fmtstream_t stream)
1589 {
1590 const char *text;
1591 const char *inp_text;
1592 void *input = 0;
1593 int anything = 0;
1594 size_t inp_text_limit = 0;
1595 const char *doc = argp->doc ? dgettext (argp->argp_domain, argp->doc) : NULL;
1596 const struct argp_child *child = argp->children;
1597
1598 if (doc)
1599 {
1600 char *vt = strchr (doc, '\v');
1601 inp_text = post ? (vt ? vt + 1 : 0) : doc;
1602 inp_text_limit = (!post && vt) ? (vt - doc) : 0;
1603 }
1604 else
1605 inp_text = 0;
1606
1607 if (argp->help_filter)
1608
1609 {
1610 if (inp_text_limit)
1611
1612 inp_text = __strndup (inp_text, inp_text_limit);
1613 input = __argp_input (argp, state);
1614 text =
1615 (*argp->help_filter) (post
1616 ? ARGP_KEY_HELP_POST_DOC
1617 : ARGP_KEY_HELP_PRE_DOC,
1618 inp_text, input);
1619 }
1620 else
1621 text = (const char *) inp_text;
1622
1623 if (text)
1624 {
1625 if (pre_blank)
1626 __argp_fmtstream_putc (stream, '\n');
1627
1628 if (text == inp_text && inp_text_limit)
1629 __argp_fmtstream_write (stream, inp_text, inp_text_limit);
1630 else
1631 __argp_fmtstream_puts (stream, text);
1632
1633 if (__argp_fmtstream_point (stream) > __argp_fmtstream_lmargin (stream))
1634 __argp_fmtstream_putc (stream, '\n');
1635
1636 anything = 1;
1637 }
1638
1639 if (text && text != inp_text)
1640 free ((char *) text);
1641 if (inp_text && inp_text_limit && argp->help_filter)
1642 free ((char *) inp_text);
1643
1644 if (post && argp->help_filter)
1645
1646 {
1647 text = (*argp->help_filter) (ARGP_KEY_HELP_EXTRA, 0, input);
1648 if (text)
1649 {
1650 if (anything || pre_blank)
1651 __argp_fmtstream_putc (stream, '\n');
1652 __argp_fmtstream_puts (stream, text);
1653 free ((char *) text);
1654 if (__argp_fmtstream_point (stream)
1655 > __argp_fmtstream_lmargin (stream))
1656 __argp_fmtstream_putc (stream, '\n');
1657 anything = 1;
1658 }
1659 }
1660
1661 if (child)
1662 while (child->argp && !(first_only && anything))
1663 anything |=
1664 argp_doc ((child++)->argp, state,
1665 post, anything || pre_blank, first_only,
1666 stream);
1667
1668 return anything;
1669 }
1670
1671
1672
1673
1674
1675 static void
1676 _help (const struct argp *argp, const struct argp_state *state, FILE *stream,
1677 unsigned flags, char *name)
1678 {
1679 int anything = 0;
1680 struct hol *hol = 0;
1681 argp_fmtstream_t fs;
1682
1683 if (! stream)
1684 return;
1685
1686 #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
1687 __flockfile (stream);
1688 #endif
1689
1690 if (! uparams.valid)
1691 fill_in_uparams (state);
1692
1693 fs = __argp_make_fmtstream (stream, 0, uparams.rmargin, 0);
1694 if (! fs)
1695 {
1696 #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
1697 __funlockfile (stream);
1698 #endif
1699 return;
1700 }
1701
1702 if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG))
1703 {
1704 hol = argp_hol (argp, 0);
1705
1706
1707 hol_set_group (hol, "help", -1);
1708 hol_set_group (hol, "version", -1);
1709
1710 hol_sort (hol);
1711 }
1712
1713 if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE))
1714
1715 {
1716 int first_pattern = 1, more_patterns;
1717 size_t num_pattern_levels = argp_args_levels (argp);
1718 char *pattern_levels = alloca (num_pattern_levels);
1719
1720 memset (pattern_levels, 0, num_pattern_levels);
1721
1722 do
1723 {
1724 int old_lm;
1725 int old_wm = __argp_fmtstream_set_wmargin (fs, uparams.usage_indent);
1726 char *levels = pattern_levels;
1727
1728 if (first_pattern)
1729 __argp_fmtstream_printf (fs, "%s %s",
1730 dgettext (argp->argp_domain, "Usage:"),
1731 name);
1732 else
1733 __argp_fmtstream_printf (fs, "%s %s",
1734 dgettext (argp->argp_domain, " or: "),
1735 name);
1736
1737
1738
1739 old_lm = __argp_fmtstream_set_lmargin (fs, uparams.usage_indent);
1740
1741 if (flags & ARGP_HELP_SHORT_USAGE)
1742
1743 {
1744 if (hol->num_entries > 0)
1745 __argp_fmtstream_puts (fs, dgettext (argp->argp_domain,
1746 " [OPTION...]"));
1747 }
1748 else
1749
1750 {
1751 hol_usage (hol, fs);
1752 flags |= ARGP_HELP_SHORT_USAGE;
1753 }
1754
1755 more_patterns = argp_args_usage (argp, state, &levels, 1, fs);
1756
1757 __argp_fmtstream_set_wmargin (fs, old_wm);
1758 __argp_fmtstream_set_lmargin (fs, old_lm);
1759
1760 __argp_fmtstream_putc (fs, '\n');
1761 anything = 1;
1762
1763 first_pattern = 0;
1764 }
1765 while (more_patterns);
1766 }
1767
1768 if (flags & ARGP_HELP_PRE_DOC)
1769 anything |= argp_doc (argp, state, 0, 0, 1, fs);
1770
1771 if (flags & ARGP_HELP_SEE)
1772 {
1773 __argp_fmtstream_printf (fs, dgettext (argp->argp_domain, "\
1774 Try '%s --help' or '%s --usage' for more information.\n"),
1775 name, name);
1776 anything = 1;
1777 }
1778
1779 if (flags & ARGP_HELP_LONG)
1780
1781 {
1782
1783 if (hol->num_entries > 0)
1784 {
1785 if (anything)
1786 __argp_fmtstream_putc (fs, '\n');
1787 hol_help (hol, state, fs);
1788 anything = 1;
1789 }
1790 }
1791
1792 if (flags & ARGP_HELP_POST_DOC)
1793
1794 anything |= argp_doc (argp, state, 1, anything, 0, fs);
1795
1796 if ((flags & ARGP_HELP_BUG_ADDR) && argp_program_bug_address)
1797 {
1798 if (anything)
1799 __argp_fmtstream_putc (fs, '\n');
1800 __argp_fmtstream_printf (fs, dgettext (argp->argp_domain,
1801 "Report bugs to %s.\n"),
1802 argp_program_bug_address);
1803 anything = 1;
1804 }
1805
1806 #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
1807 __funlockfile (stream);
1808 #endif
1809
1810 if (hol)
1811 hol_free (hol);
1812
1813 __argp_fmtstream_free (fs);
1814 }
1815
1816
1817
1818 void __argp_help (const struct argp *argp, FILE *stream,
1819 unsigned flags, char *name)
1820 {
1821 _help (argp, 0, stream, flags, name);
1822 }
1823 #ifdef weak_alias
1824 weak_alias (__argp_help, argp_help)
1825 #endif
1826
1827 #if ! (defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME)
1828 char *
1829 __argp_short_program_name (void)
1830 {
1831 # if HAVE_DECL_PROGRAM_INVOCATION_NAME
1832 char *name = strrchr (program_invocation_name, '/');
1833 return name ? name + 1 : program_invocation_name;
1834 # else
1835
1836
1837
1838 # if __GNUC__ || (__clang_major__ >= 4)
1839 # warning No reasonable value to return
1840 # endif
1841 return "";
1842 # endif
1843 }
1844 #endif
1845
1846
1847
1848 void
1849 __argp_state_help (const struct argp_state *state, FILE *stream, unsigned flags)
1850 {
1851 if ((!state || ! (state->flags & ARGP_NO_ERRS)) && stream)
1852 {
1853 if (state && (state->flags & ARGP_LONG_ONLY))
1854 flags |= ARGP_HELP_LONG_ONLY;
1855
1856 _help (state ? state->root_argp : 0, state, stream, flags,
1857 state ? state->name : __argp_short_program_name ());
1858
1859 if (!state || ! (state->flags & ARGP_NO_EXIT))
1860 {
1861 if (flags & ARGP_HELP_EXIT_ERR)
1862 exit (argp_err_exit_status);
1863 if (flags & ARGP_HELP_EXIT_OK)
1864 exit (0);
1865 }
1866 }
1867 }
1868 #ifdef weak_alias
1869 weak_alias (__argp_state_help, argp_state_help)
1870 #endif
1871
1872
1873
1874
1875 void
1876 __argp_error (const struct argp_state *state, const char *fmt, ...)
1877 {
1878 if (!state || !(state->flags & ARGP_NO_ERRS))
1879 {
1880 FILE *stream = state ? state->err_stream : stderr;
1881
1882 if (stream)
1883 {
1884 va_list ap;
1885
1886 #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
1887 __flockfile (stream);
1888 #endif
1889
1890 va_start (ap, fmt);
1891
1892 #ifdef _LIBC
1893 char *buf;
1894
1895 if (_IO_vasprintf (&buf, fmt, ap) < 0)
1896 buf = NULL;
1897
1898 __fxprintf (stream, "%s: %s\n",
1899 state ? state->name : __argp_short_program_name (), buf);
1900
1901 free (buf);
1902 #else
1903 fputs_unlocked (state ? state->name : __argp_short_program_name (),
1904 stream);
1905 putc_unlocked (':', stream);
1906 putc_unlocked (' ', stream);
1907
1908 vfprintf (stream, fmt, ap);
1909
1910 putc_unlocked ('\n', stream);
1911 #endif
1912
1913 __argp_state_help (state, stream, ARGP_HELP_STD_ERR);
1914
1915 va_end (ap);
1916
1917 #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
1918 __funlockfile (stream);
1919 #endif
1920 }
1921 }
1922 }
1923 #ifdef weak_alias
1924 weak_alias (__argp_error, argp_error)
1925 #endif
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935 void
1936 __argp_failure (const struct argp_state *state, int status, int errnum,
1937 const char *fmt, ...)
1938 {
1939 if (!state || !(state->flags & ARGP_NO_ERRS))
1940 {
1941 FILE *stream = state ? state->err_stream : stderr;
1942
1943 if (stream)
1944 {
1945 #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
1946 __flockfile (stream);
1947 #endif
1948
1949 #ifdef _LIBC
1950 __fxprintf (stream, "%s",
1951 state ? state->name : __argp_short_program_name ());
1952 #else
1953 fputs_unlocked (state ? state->name : __argp_short_program_name (),
1954 stream);
1955 #endif
1956
1957 if (fmt)
1958 {
1959 va_list ap;
1960
1961 va_start (ap, fmt);
1962 #ifdef _LIBC
1963 char *buf;
1964
1965 if (_IO_vasprintf (&buf, fmt, ap) < 0)
1966 buf = NULL;
1967
1968 __fxprintf (stream, ": %s", buf);
1969
1970 free (buf);
1971 #else
1972 putc_unlocked (':', stream);
1973 putc_unlocked (' ', stream);
1974
1975 vfprintf (stream, fmt, ap);
1976 #endif
1977
1978 va_end (ap);
1979 }
1980
1981 if (errnum)
1982 {
1983 char buf[200];
1984
1985 #ifdef _LIBC
1986 __fxprintf (stream, ": %s",
1987 __strerror_r (errnum, buf, sizeof (buf)));
1988 #else
1989 char const *s = NULL;
1990 putc_unlocked (':', stream);
1991 putc_unlocked (' ', stream);
1992 # if GNULIB_STRERROR_R_POSIX || HAVE_DECL_STRERROR_R
1993 # if !GNULIB_STRERROR_R_POSIX && STRERROR_R_CHAR_P
1994 s = __strerror_r (errnum, buf, sizeof buf);
1995 # else
1996 if (__strerror_r (errnum, buf, sizeof buf) == 0)
1997 s = buf;
1998 # endif
1999 # endif
2000 if (! s && ! (s = strerror (errnum)))
2001 s = dgettext (state->root_argp->argp_domain,
2002 "Unknown system error");
2003 fputs_unlocked (s, stream);
2004 #endif
2005 }
2006
2007 #if _LIBC
2008 if (_IO_fwide (stream, 0) > 0)
2009 putwc_unlocked (L'\n', stream);
2010 else
2011 #endif
2012 putc_unlocked ('\n', stream);
2013
2014 #if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE)
2015 __funlockfile (stream);
2016 #endif
2017
2018 if (status && (!state || !(state->flags & ARGP_NO_EXIT)))
2019 exit (status);
2020 }
2021 }
2022 }
2023 #ifdef weak_alias
2024 weak_alias (__argp_failure, argp_failure)
2025 #endif