1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
4 * \file popt/popthelp.c
7 /* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
8 file accompanying popt source distributions, available from
9 ftp://ftp.rpm.org/pub/rpm/dist. */
13 #define POPT_USE_TIOCGWINSZ
14 #ifdef POPT_USE_TIOCGWINSZ
15 #include <sys/ioctl.h>
18 #define POPT_WCHAR_HACK
19 #ifdef POPT_WCHAR_HACK
20 #include <wchar.h> /* for mbsrtowcs */
21 /*@access mbstate_t @*/
25 /*@access poptContext@*/
31 * @param key option(s)
33 * @param data (unused)
36 static void displayArgs(poptContext con
,
37 /*@unused@*/ UNUSED(enum poptCallbackReason foo
),
38 struct poptOption
* key
,
39 /*@unused@*/ UNUSED(const char * arg
),
40 /*@unused@*/ UNUSED(void * data
))
41 /*@globals fileSystem@*/
42 /*@modifies fileSystem@*/
44 if (key
->shortName
== '?')
45 poptPrintHelp(con
, stdout
, 0);
47 poptPrintUsage(con
, stdout
, 0);
49 #if !defined(__LCLINT__) /* XXX keep both splint & valgrind happy */
50 con
= poptFreeContext(con
);
57 static int show_option_defaults
= 0;
61 * Empty table marker to enable displaying popt alias/exec options.
63 /*@observer@*/ /*@unchecked@*/
64 struct poptOption poptAliasOptions
[] = {
69 * Auto help table options.
72 /*@observer@*/ /*@unchecked@*/
73 struct poptOption poptHelpOptions
[] = {
74 { NULL
, '\0', POPT_ARG_CALLBACK
, (void *)displayArgs
, 0, NULL
, NULL
},
75 { "help", '?', 0, NULL
, (int)'?', N_("Show this help message"), NULL
},
76 { "usage", '\0', 0, NULL
, (int)'u', N_("Display brief usage message"), NULL
},
80 /*@observer@*/ /*@unchecked@*/
81 static struct poptOption poptHelpOptions2
[] = {
83 { NULL
, '\0', POPT_ARG_INTL_DOMAIN
, PACKAGE
, 0, NULL
, NULL
},
85 { NULL
, '\0', POPT_ARG_CALLBACK
, (void *)displayArgs
, 0, NULL
, NULL
},
86 { "help", '?', 0, NULL
, (int)'?', N_("Show this help message"), NULL
},
87 { "usage", '\0', 0, NULL
, (int)'u', N_("Display brief usage message"), NULL
},
89 { "defaults", '\0', POPT_ARG_NONE
, &show_option_defaults
, 0,
90 N_("Display option defaults in message"), NULL
},
92 { "", '\0', 0, NULL
, 0, N_("Terminate options"), NULL
},
96 /*@observer@*/ /*@unchecked@*/
97 struct poptOption
* poptHelpOptionsI18N
= poptHelpOptions2
;
100 #define _POPTHELP_MAXLINE ((size_t)79)
102 typedef struct columns_s
{
108 * Return no. of columns in output window.
110 * @return no. of columns
112 static size_t maxColumnWidth(FILE *fp
)
115 size_t maxcols
= _POPTHELP_MAXLINE
;
116 #if defined(TIOCGWINSZ)
118 int fdno
= fileno(fp
? fp
: stdout
);
120 memset(&ws
, 0, sizeof(ws
));
121 if (fdno
>= 0 && !ioctl(fdno
, (unsigned long)TIOCGWINSZ
, &ws
)) {
122 size_t ws_col
= (size_t)ws
.ws_col
;
123 if (ws_col
> maxcols
&& ws_col
< (size_t)256)
124 maxcols
= ws_col
- 1;
131 * Determine number of display characters in a string.
133 * @return no. of display characters.
135 static inline size_t stringDisplayWidth(const char *s
)
138 size_t n
= strlen(s
);
139 #ifdef POPT_WCHAR_HACK
142 memset ((void *)&t
, 0, sizeof (t
)); /* In initial state. */
143 /* Determine number of display characters. */
144 n
= mbsrtowcs (NULL
, &s
, n
, &t
);
147 for (; *s
; s
= POPT_next_char(s
))
155 * @param opt option(s)
157 /*@observer@*/ /*@null@*/ static const char *
158 getTableTranslationDomain(/*@null@*/ const struct poptOption
*opt
)
162 for (; opt
->longName
|| opt
->shortName
|| opt
->arg
; opt
++) {
163 if (opt
->argInfo
== POPT_ARG_INTL_DOMAIN
)
170 * @param opt option(s)
171 * @param translation_domain translation domain
173 /*@observer@*/ /*@null@*/ static const char *
174 getArgDescrip(const struct poptOption
* opt
,
175 /*@-paramuse@*/ /* FIX: i18n macros disabled with lclint */
176 /*@null@*/ const char * translation_domain
)
180 if (!poptArgType(opt
)) return NULL
;
182 if (poptArgType(opt
) == POPT_ARG_MAINCALL
)
183 return opt
->argDescrip
;
184 if (poptArgType(opt
) == POPT_ARG_ARGV
)
185 return opt
->argDescrip
;
187 if (opt
->argDescrip
) {
188 /* Some strings need popt library, not application, i18n domain. */
189 if (opt
== (poptHelpOptions
+ 1)
190 || opt
== (poptHelpOptions
+ 2)
191 || !strcmp(opt
->argDescrip
, N_("Help options:"))
192 || !strcmp(opt
->argDescrip
, N_("Options implemented via popt alias/exec:")))
193 return POPT_(opt
->argDescrip
);
195 /* Use the application i18n domain. */
196 return D_(translation_domain
, opt
->argDescrip
);
199 switch (poptArgType(opt
)) {
200 case POPT_ARG_NONE
: return POPT_("NONE");
202 case POPT_ARG_VAL
: return POPT_("VAL");
204 case POPT_ARG_VAL
: return NULL
;
206 case POPT_ARG_INT
: return POPT_("INT");
207 case POPT_ARG_SHORT
: return POPT_("SHORT");
208 case POPT_ARG_LONG
: return POPT_("LONG");
209 case POPT_ARG_LONGLONG
: return POPT_("LONGLONG");
210 case POPT_ARG_STRING
: return POPT_("STRING");
211 case POPT_ARG_FLOAT
: return POPT_("FLOAT");
212 case POPT_ARG_DOUBLE
: return POPT_("DOUBLE");
213 case POPT_ARG_MAINCALL
: return NULL
;
214 case POPT_ARG_ARGV
: return NULL
;
215 default: return POPT_("ARG");
220 * Display default value for an option.
221 * @param lineLength display positions remaining
222 * @param opt option(s)
223 * @param translation_domain translation domain
226 static /*@only@*/ /*@null@*/ char *
227 singleOptionDefaultValue(size_t lineLength
,
228 const struct poptOption
* opt
,
229 /*@-paramuse@*/ /* FIX: i18n macros disabled with lclint */
230 /*@null@*/ const char * translation_domain
)
234 const char * defstr
= D_(translation_domain
, "default");
235 char * le
= malloc(4*lineLength
+ 1);
238 if (le
== NULL
) return NULL
; /* XXX can't happen */
241 le
= stpcpy(le
, defstr
);
244 if (opt
->arg
) { /* XXX programmer error */
245 poptArg arg
= { .ptr
= opt
->arg
};
246 switch (poptArgType(opt
)) {
249 le
+= sprintf(le
, "%d", arg
.intp
[0]);
252 le
+= sprintf(le
, "%hd", arg
.shortp
[0]);
255 le
+= sprintf(le
, "%ld", arg
.longp
[0]);
257 case POPT_ARG_LONGLONG
:
258 le
+= sprintf(le
, "%lld", arg
.longlongp
[0]);
261 { double aDouble
= (double) arg
.floatp
[0];
262 le
+= sprintf(le
, "%g", aDouble
);
264 case POPT_ARG_DOUBLE
:
265 le
+= sprintf(le
, "%g", arg
.doublep
[0]);
267 case POPT_ARG_MAINCALL
:
268 le
+= sprintf(le
, "%p", opt
->arg
);
271 le
+= sprintf(le
, "%p", opt
->arg
);
273 case POPT_ARG_STRING
:
274 { const char * s
= arg
.argv
[0];
276 le
= stpcpy(le
, "null");
278 size_t limit
= 4*lineLength
- (le
- l
) - sizeof("\"\")");
281 strncpy(le
, s
, limit
); le
[limit
] = '\0'; le
+= (slen
= strlen(le
));
282 if (slen
== limit
&& s
[limit
])
283 le
[-1] = le
[-2] = le
[-3] = '.';
291 /*@notreached@*/ break;
301 * Display help text for an option.
302 * @param fp output file handle
303 * @param columns output display width control
304 * @param opt option(s)
305 * @param translation_domain translation domain
307 static void singleOptionHelp(FILE * fp
, columns_t columns
,
308 const struct poptOption
* opt
,
309 /*@null@*/ const char * translation_domain
)
310 /*@globals fileSystem @*/
311 /*@modifies fp, fileSystem @*/
313 size_t maxLeftCol
= columns
->cur
;
314 size_t indentLength
= maxLeftCol
+ 5;
315 size_t lineLength
= columns
->max
- indentLength
;
316 const char * help
= D_(translation_domain
, opt
->descrip
);
317 const char * argDescrip
= getArgDescrip(opt
, translation_domain
);
318 /* Display shortName iff printable non-space. */
319 int prtshort
= (int)(isprint((int)opt
->shortName
) && opt
->shortName
!= ' ');
323 size_t nb
= maxLeftCol
+ 1;
327 /* Make sure there's more than enough room in target buffer. */
328 if (opt
->longName
) nb
+= strlen(opt
->longName
);
329 if (F_ISSET(opt
, TOGGLE
)) nb
+= sizeof("[no]") - 1;
330 if (argDescrip
) nb
+= strlen(argDescrip
);
333 if (left
== NULL
) return; /* XXX can't happen */
335 left
[maxLeftCol
] = '\0';
337 #define prtlong (opt->longName != NULL) /* XXX splint needs a clue */
338 if (!(prtshort
|| prtlong
))
340 if (prtshort
&& prtlong
) {
341 char *dash
= F_ISSET(opt
, ONEDASH
) ? "-" : "--";
343 left
[1] = opt
->shortName
;
344 (void) stpcpy(stpcpy(stpcpy(left
+2, ", "), dash
), opt
->longName
);
345 } else if (prtshort
) {
347 left
[1] = opt
->shortName
;
349 } else if (prtlong
) {
350 /* XXX --long always padded for alignment with/without "-X, ". */
351 char *dash
= poptArgType(opt
) == POPT_ARG_MAINCALL
? ""
352 : (F_ISSET(opt
, ONEDASH
) ? "-" : "--");
353 const char *longName
= opt
->longName
;
355 if (F_ISSET(opt
, TOGGLE
)) {
357 if (longName
[0] == 'n' && longName
[1] == 'o') {
358 longName
+= sizeof("no") - 1;
359 if (longName
[0] == '-')
364 (void) stpcpy(stpcpy(stpcpy(stpcpy(left
, " "), dash
), toggle
), longName
);
369 char * le
= left
+ strlen(left
);
371 if (F_ISSET(opt
, OPTIONAL
))
374 /* Choose type of output */
375 if (F_ISSET(opt
, SHOW_DEFAULT
)) {
376 defs
= singleOptionDefaultValue(lineLength
, opt
, translation_domain
);
378 char * t
= malloc((help
? strlen(help
) : 0) +
379 strlen(defs
) + sizeof(" "));
383 te
= stpcpy(te
, help
);
392 if (opt
->argDescrip
== NULL
) {
393 switch (poptArgType(opt
)) {
397 #ifdef NOTNOW /* XXX pug ugly nerdy output */
398 { long aLong
= opt
->val
;
399 int ops
= F_ISSET(opt
, LOGICALOPS
);
400 int negate
= F_ISSET(opt
, NOT
);
402 /* Don't bother displaying typical values */
403 if (!ops
&& (aLong
== 0L || aLong
== 1L || aLong
== -1L))
407 case POPT_ARGFLAG_OR
:
409 /*@innerbreak@*/ break;
410 case POPT_ARGFLAG_AND
:
412 /*@innerbreak@*/ break;
413 case POPT_ARGFLAG_XOR
:
415 /*@innerbreak@*/ break;
417 /*@innerbreak@*/ break;
419 *le
++ = (opt
->longName
!= NULL
? '=' : ' ');
420 if (negate
) *le
++ = '~';
422 le
+= sprintf(le
, (ops
? "0x%lx" : "%ld"), aLong
);
431 case POPT_ARG_LONGLONG
:
433 case POPT_ARG_DOUBLE
:
434 case POPT_ARG_STRING
:
435 *le
++ = (opt
->longName
!= NULL
? '=' : ' ');
436 le
= stpcpy(le
, argDescrip
);
444 /* XXX argDescrip[0] determines "--foo=bar" or "--foo bar". */
445 if (!strchr(" =(", argDescrip
[0]))
446 *le
++ = ((poptArgType(opt
) == POPT_ARG_MAINCALL
) ? ' ' :
447 (poptArgType(opt
) == POPT_ARG_ARGV
) ? ' ' : '=');
448 le
= stpcpy(leo
= le
, argDescrip
);
450 /* Adjust for (possible) wide characters. */
451 displaypad
= (int)((le
- leo
) - stringDisplayWidth(argDescrip
));
453 if (F_ISSET(opt
, OPTIONAL
))
459 xx
= POPT_fprintf(fp
," %-*s ", (int)(maxLeftCol
+displaypad
), left
);
461 xx
= POPT_fprintf(fp
," %s\n", left
);
469 helpLength
= strlen(help
);
470 while (helpLength
> lineLength
) {
474 ch
= help
+ lineLength
- 1;
475 while (ch
> help
&& !_isspaceptr(ch
))
476 ch
= POPT_prev_char(ch
);
477 if (ch
== help
) break; /* give up */
478 while (ch
> (help
+ 1) && _isspaceptr(ch
))
479 ch
= POPT_prev_char (ch
);
480 ch
= POPT_next_char(ch
);
483 * XXX strdup is necessary to add NUL terminator so that an unknown
484 * no. of (possible) multi-byte characters can be displayed.
486 { char * fmthelp
= xstrdup(help
);
488 fmthelp
[ch
- help
] = '\0';
489 sprintf(format
, "%%s\n%%%ds", (int) indentLength
);
491 xx
= POPT_fprintf(fp
, format
, fmthelp
, " ");
498 while (_isspaceptr(help
) && *help
)
499 help
= POPT_next_char(help
);
500 helpLength
= strlen(help
);
503 if (helpLength
) fprintf(fp
, "%s\n", help
);
507 /*@-dependenttrans@*/
509 /*@=dependenttrans@*/
514 * Find display width for longest argument string.
515 * @param opt option(s)
516 * @param translation_domain translation domain
517 * @return display width
519 static size_t maxArgWidth(const struct poptOption
* opt
,
520 /*@null@*/ const char * translation_domain
)
525 const char * argDescrip
;
528 while (opt
->longName
|| opt
->shortName
|| opt
->arg
) {
529 if (poptArgType(opt
) == POPT_ARG_INCLUDE_TABLE
) {
530 if (opt
->arg
) /* XXX program error */
531 len
= maxArgWidth(opt
->arg
, translation_domain
);
532 if (len
> max
) max
= len
;
533 } else if (!F_ISSET(opt
, DOC_HIDDEN
)) {
535 /* XXX --long always padded for alignment with/without "-X, ". */
536 len
+= sizeof("-X, ")-1;
538 len
+= (F_ISSET(opt
, ONEDASH
) ? sizeof("-") : sizeof("--")) - 1;
539 len
+= strlen(opt
->longName
);
542 argDescrip
= getArgDescrip(opt
, translation_domain
);
546 /* XXX argDescrip[0] determines "--foo=bar" or "--foo bar". */
547 if (!strchr(" =(", argDescrip
[0])) len
+= sizeof("=")-1;
549 /* Adjust for (possible) wide characters. */
550 len
+= stringDisplayWidth(argDescrip
);
553 if (F_ISSET(opt
, OPTIONAL
)) len
+= sizeof("[]")-1;
554 if (len
> max
) max
= len
;
563 * Display popt alias and exec help.
564 * @param fp output file handle
565 * @param items alias/exec array
566 * @param nitems no. of alias/exec entries
567 * @param columns output display width control
568 * @param translation_domain translation domain
570 static void itemHelp(FILE * fp
,
571 /*@null@*/ poptItem items
, int nitems
,
573 /*@null@*/ const char * translation_domain
)
574 /*@globals fileSystem @*/
575 /*@modifies fp, fileSystem @*/
581 for (i
= 0, item
= items
; i
< nitems
; i
++, item
++) {
582 const struct poptOption
* opt
;
584 if ((opt
->longName
|| opt
->shortName
) && !F_ISSET(opt
, DOC_HIDDEN
))
585 singleOptionHelp(fp
, columns
, opt
, translation_domain
);
590 * Display help text for a table of options.
592 * @param fp output file handle
593 * @param table option(s)
594 * @param columns output display width control
595 * @param translation_domain translation domain
597 static void singleTableHelp(poptContext con
, FILE * fp
,
598 /*@null@*/ const struct poptOption
* table
,
600 /*@null@*/ const char * translation_domain
)
601 /*@globals fileSystem @*/
602 /*@modifies fp, columns->cur, fileSystem @*/
604 const struct poptOption
* opt
;
605 const char *sub_transdom
;
608 if (table
== poptAliasOptions
) {
609 itemHelp(fp
, con
->aliases
, con
->numAliases
, columns
, NULL
);
610 itemHelp(fp
, con
->execs
, con
->numExecs
, columns
, NULL
);
615 for (opt
= table
; opt
->longName
|| opt
->shortName
|| opt
->arg
; opt
++) {
616 if ((opt
->longName
|| opt
->shortName
) && !F_ISSET(opt
, DOC_HIDDEN
))
617 singleOptionHelp(fp
, columns
, opt
, translation_domain
);
621 for (opt
= table
; opt
->longName
|| opt
->shortName
|| opt
->arg
; opt
++) {
622 if (poptArgType(opt
) != POPT_ARG_INCLUDE_TABLE
)
624 sub_transdom
= getTableTranslationDomain(opt
->arg
);
625 if (sub_transdom
== NULL
)
626 sub_transdom
= translation_domain
;
628 /* If no popt aliases/execs, skip poptAliasOption processing. */
629 if (opt
->arg
== poptAliasOptions
&& !(con
->numAliases
|| con
->numExecs
))
632 xx
= POPT_fprintf(fp
, "\n%s\n", D_(sub_transdom
, opt
->descrip
));
634 singleTableHelp(con
, fp
, opt
->arg
, columns
, sub_transdom
);
640 * @param fp output file handle
642 static size_t showHelpIntro(poptContext con
, FILE * fp
)
643 /*@globals fileSystem @*/
644 /*@modifies fp, fileSystem @*/
646 size_t len
= (size_t)6;
649 xx
= POPT_fprintf(fp
, POPT_("Usage:"));
650 if (!(con
->flags
& POPT_CONTEXT_KEEP_FIRST
)) {
651 struct optionStackEntry
* os
= con
->optionStack
;
652 const char * fn
= (os
->argv
? os
->argv
[0] : NULL
);
653 if (fn
== NULL
) return len
;
654 if (strchr(fn
, '/')) fn
= strrchr(fn
, '/') + 1;
655 /* XXX POPT_fprintf not needed for argv[0] display. */
656 fprintf(fp
, " %s", fn
);
657 len
+= strlen(fn
) + 1;
663 void poptPrintHelp(poptContext con
, FILE * fp
, /*@unused@*/ UNUSED(int flags
))
665 columns_t columns
= calloc((size_t)1, sizeof(*columns
));
668 (void) showHelpIntro(con
, fp
);
670 xx
= POPT_fprintf(fp
, " %s\n", con
->otherHelp
);
672 xx
= POPT_fprintf(fp
, " %s\n", POPT_("[OPTION...]"));
675 columns
->cur
= maxArgWidth(con
->options
, NULL
);
676 columns
->max
= maxColumnWidth(fp
);
677 singleTableHelp(con
, fp
, con
->options
, columns
, NULL
);
683 * Display usage text for an option.
684 * @param fp output file handle
685 * @param columns output display width control
686 * @param opt option(s)
687 * @param translation_domain translation domain
689 static size_t singleOptionUsage(FILE * fp
, columns_t columns
,
690 const struct poptOption
* opt
,
691 /*@null@*/ const char *translation_domain
)
692 /*@globals fileSystem @*/
693 /*@modifies fp, columns->cur, fileSystem @*/
695 size_t len
= sizeof(" []")-1;
696 const char * argDescrip
= getArgDescrip(opt
, translation_domain
);
697 /* Display shortName iff printable non-space. */
698 int prtshort
= (int)(isprint((int)opt
->shortName
) && opt
->shortName
!= ' ');
700 #define prtlong (opt->longName != NULL) /* XXX splint needs a clue */
701 if (!(prtshort
|| prtlong
))
704 len
= sizeof(" []")-1;
706 len
+= sizeof("-c")-1;
708 if (prtshort
) len
+= sizeof("|")-1;
709 len
+= (F_ISSET(opt
, ONEDASH
) ? sizeof("-") : sizeof("--")) - 1;
710 len
+= strlen(opt
->longName
);
715 /* XXX argDescrip[0] determines "--foo=bar" or "--foo bar". */
716 if (!strchr(" =(", argDescrip
[0])) len
+= sizeof("=")-1;
718 /* Adjust for (possible) wide characters. */
719 len
+= stringDisplayWidth(argDescrip
);
722 if ((columns
->cur
+ len
) > columns
->max
) {
724 columns
->cur
= (size_t)7;
729 fprintf(fp
, "-%c", opt
->shortName
);
731 fprintf(fp
, "%s%s%s",
732 (prtshort
? "|" : ""),
733 (F_ISSET(opt
, ONEDASH
) ? "-" : "--"),
738 /* XXX argDescrip[0] determines "--foo=bar" or "--foo bar". */
739 if (!strchr(" =(", argDescrip
[0])) fprintf(fp
, "=");
740 fprintf(fp
, "%s", argDescrip
);
744 return columns
->cur
+ len
+ 1;
748 * Display popt alias and exec usage.
749 * @param fp output file handle
750 * @param columns output display width control
751 * @param item alias/exec array
752 * @param nitems no. of ara/exec entries
753 * @param translation_domain translation domain
755 static size_t itemUsage(FILE * fp
, columns_t columns
,
756 /*@null@*/ poptItem item
, int nitems
,
757 /*@null@*/ const char * translation_domain
)
758 /*@globals fileSystem @*/
759 /*@modifies fp, columns->cur, fileSystem @*/
764 for (i
= 0; i
< nitems
; i
++, item
++) {
765 const struct poptOption
* opt
;
767 if (poptArgType(opt
) == POPT_ARG_INTL_DOMAIN
) {
768 translation_domain
= (const char *)opt
->arg
;
770 if ((opt
->longName
|| opt
->shortName
) && !F_ISSET(opt
, DOC_HIDDEN
)) {
771 columns
->cur
= singleOptionUsage(fp
, columns
, opt
, translation_domain
);
779 * Keep track of option tables already processed.
781 typedef struct poptDone_s
{
789 * Display usage text for a table of options.
791 * @param fp output file handle
792 * @param columns output display width control
793 * @param opt option(s)
794 * @param translation_domain translation domain
795 * @param done tables already processed
798 static size_t singleTableUsage(poptContext con
, FILE * fp
, columns_t columns
,
799 /*@null@*/ const struct poptOption
* opt
,
800 /*@null@*/ const char * translation_domain
,
801 /*@null@*/ poptDone done
)
802 /*@globals fileSystem @*/
803 /*@modifies fp, columns->cur, done, fileSystem @*/
806 for (; (opt
->longName
|| opt
->shortName
|| opt
->arg
) ; opt
++) {
807 if (poptArgType(opt
) == POPT_ARG_INTL_DOMAIN
) {
808 translation_domain
= (const char *)opt
->arg
;
810 if (poptArgType(opt
) == POPT_ARG_INCLUDE_TABLE
) {
813 if (done
->opts
!= NULL
)
814 for (i
= 0; i
< done
->nopts
; i
++) {
815 const void * that
= done
->opts
[i
];
816 if (that
== NULL
|| that
!= opt
->arg
)
817 /*@innercontinue@*/ continue;
818 /*@innerbreak@*/ break;
820 /* Skip if this table has already been processed. */
821 if (opt
->arg
== NULL
|| i
< done
->nopts
)
823 if (done
->opts
!= NULL
&& done
->nopts
< done
->maxopts
)
824 done
->opts
[done
->nopts
++] = (const void *) opt
->arg
;
826 columns
->cur
= singleTableUsage(con
, fp
, columns
, opt
->arg
,
827 translation_domain
, done
);
829 if ((opt
->longName
|| opt
->shortName
) && !F_ISSET(opt
, DOC_HIDDEN
)) {
830 columns
->cur
= singleOptionUsage(fp
, columns
, opt
, translation_domain
);
838 * Return concatenated short options for display.
839 * @todo Sub-tables should be recursed.
840 * @param opt option(s)
841 * @param fp output file handle
842 * @retval str concatenation of short options
843 * @return length of display string
845 static size_t showShortOptions(const struct poptOption
* opt
, FILE * fp
,
846 /*@null@*/ char * str
)
847 /*@globals fileSystem @*/
848 /*@modifies str, *fp, fileSystem @*/
849 /*@requires maxRead(str) >= 0 @*/
851 /* bufsize larger then the ascii set, lazy allocation on top level call. */
852 size_t nb
= (size_t)300;
853 char * s
= (str
!= NULL
? str
: calloc((size_t)1, nb
));
854 size_t len
= (size_t)0;
860 for (; (opt
->longName
|| opt
->shortName
|| opt
->arg
); opt
++) {
861 if (!F_ISSET(opt
, DOC_HIDDEN
) && opt
->shortName
&& !poptArgType(opt
))
863 /* Display shortName iff unique printable non-space. */
864 if (!strchr(s
, opt
->shortName
) && isprint((int)opt
->shortName
)
865 && opt
->shortName
!= ' ')
866 s
[strlen(s
)] = opt
->shortName
;
867 } else if (poptArgType(opt
) == POPT_ARG_INCLUDE_TABLE
)
868 if (opt
->arg
) /* XXX program error */
869 len
= showShortOptions(opt
->arg
, fp
, s
);
872 /* On return to top level, print the short options, return print length. */
873 if (s
!= str
&& *s
!= '\0') {
874 fprintf(fp
, " [-%s]", s
);
875 len
= strlen(s
) + sizeof(" [-]")-1;
877 /*@-temptrans@*/ /* LCL: local s, not str arg, is being freed. */
884 void poptPrintUsage(poptContext con
, FILE * fp
, /*@unused@*/ UNUSED(int flags
))
886 columns_t columns
= calloc((size_t)1, sizeof(*columns
));
887 struct poptDone_s done_buf
;
888 poptDone done
= &done_buf
;
890 memset(done
, 0, sizeof(*done
));
894 columns
->cur
= done
->maxopts
* sizeof(*done
->opts
);
895 columns
->max
= maxColumnWidth(fp
);
896 done
->opts
= calloc((size_t)1, columns
->cur
);
898 if (done
->opts
!= NULL
)
899 done
->opts
[done
->nopts
++] = (const void *) con
->options
;
902 columns
->cur
= showHelpIntro(con
, fp
);
903 columns
->cur
+= showShortOptions(con
->options
, fp
, NULL
);
904 columns
->cur
= singleTableUsage(con
, fp
, columns
, con
->options
, NULL
, done
);
905 columns
->cur
= itemUsage(fp
, columns
, con
->aliases
, con
->numAliases
, NULL
);
906 columns
->cur
= itemUsage(fp
, columns
, con
->execs
, con
->numExecs
, NULL
);
908 if (con
->otherHelp
) {
909 columns
->cur
+= strlen(con
->otherHelp
) + 1;
910 if (columns
->cur
> columns
->max
) fprintf(fp
, "\n ");
911 fprintf(fp
, " %s", con
->otherHelp
);
915 if (done
->opts
!= NULL
)
921 void poptSetOtherOptionHelp(poptContext con
, const char * text
)
923 con
->otherHelp
= _free(con
->otherHelp
);
924 con
->otherHelp
= xstrdup(text
);