X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/73042aae5b0ba34286a425d313806def79d891d7..b5ae4e25c26f006e686dcefde9fe7d489f840248:/popt/popthelp.c diff --git a/popt/popthelp.c b/popt/popthelp.c index 154e2c5a..ba8d0243 100644 --- a/popt/popthelp.c +++ b/popt/popthelp.c @@ -1,20 +1,31 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/*@-type@*/ /** \ingroup popt * \file popt/popthelp.c */ -/* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING +/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING file accompanying popt source distributions, available from ftp://ftp.rpm.org/pub/rpm/dist. */ #include "system.h" + +/*#define POPT_WCHAR_HACK*/ +#ifdef POPT_WCHAR_HACK +#include /* for mbsrtowcs */ +/*@access mbstate_t @*/ +#endif #include "poptint.h" +/*@access poptContext@*/ + /** + * Display arguments. * @param con context + * @param foo (unused) * @param key option(s) + * @param arg (unused) + * @param data (unused) */ static void displayArgs(poptContext con, /*@unused@*/ UNUSED(enum poptCallbackReason foo), @@ -49,6 +60,17 @@ struct poptOption poptAliasOptions[] = { /*@-castfcnptr@*/ /*@observer@*/ /*@unchecked@*/ struct poptOption poptHelpOptions[] = { + { NULL, '\0', POPT_ARG_CALLBACK, (void *)&displayArgs, '\0', NULL, NULL }, + { "help", '?', 0, NULL, '?', N_("Show this help message"), NULL }, + { "usage", '\0', 0, NULL, 'u', N_("Display brief usage message"), NULL }, + POPT_TABLEEND +} ; + +/*@observer@*/ /*@unchecked@*/ +static struct poptOption poptHelpOptions2[] = { +/*@-readonlytrans@*/ + { NULL, '\0', POPT_ARG_INTL_DOMAIN, PACKAGE, 0, NULL, NULL}, +/*@=readonlytrans@*/ { NULL, '\0', POPT_ARG_CALLBACK, (void *)&displayArgs, '\0', NULL, NULL }, { "help", '?', 0, NULL, '?', N_("Show this help message"), NULL }, { "usage", '\0', 0, NULL, 'u', N_("Display brief usage message"), NULL }, @@ -58,6 +80,9 @@ struct poptOption poptHelpOptions[] = { #endif POPT_TABLEEND } ; + +/*@observer@*/ /*@unchecked@*/ +struct poptOption * poptHelpOptionsI18N = poptHelpOptions2; /*@=castfcnptr@*/ /** @@ -83,8 +108,8 @@ getTableTranslationDomain(/*@null@*/ const struct poptOption *table) */ /*@observer@*/ /*@null@*/ static const char * getArgDescrip(const struct poptOption * opt, - /*@-paramuse@*/ /* FIX: wazzup? */ - /*@null@*/ const char * translation_domain) + /*@-paramuse@*/ /* FIX: i18n macros disabled with lclint */ + /*@null@*/ UNUSED(const char * translation_domain)) /*@=paramuse@*/ /*@*/ { @@ -97,7 +122,11 @@ getArgDescrip(const struct poptOption * opt, switch (opt->argInfo & POPT_ARG_MASK) { case POPT_ARG_NONE: return POPT_("NONE"); +#ifdef DYING case POPT_ARG_VAL: return POPT_("VAL"); +#else + case POPT_ARG_VAL: return NULL; +#endif case POPT_ARG_INT: return POPT_("INT"); case POPT_ARG_LONG: return POPT_("LONG"); case POPT_ARG_STRING: return POPT_("STRING"); @@ -108,61 +137,65 @@ getArgDescrip(const struct poptOption * opt, } /** + * Display default value for an option. + * @param lineLength display positions remaining * @param opt option(s) * @param translation_domain translation domain + * @return */ static /*@only@*/ /*@null@*/ char * -singleOptionDefaultValue(int lineLength, +singleOptionDefaultValue(size_t lineLength, const struct poptOption * opt, - /*@-paramuse@*/ /* FIX: i18n macros disable with lclint */ - /*@null@*/ const char * translation_domain) + /*@-paramuse@*/ /* FIX: i18n macros disabled with lclint */ + /*@null@*/ UNUSED(const char * translation_domain)) /*@=paramuse@*/ /*@*/ { const char * defstr = D_(translation_domain, "default"); - char * le = malloc(4*lineLength + 1); + size_t limit, bufsize = 4*lineLength + 1; + char * le = malloc(bufsize); char * l = le; if (le == NULL) return NULL; /* XXX can't happen */ - *le = '\0'; +/*@-boundswrite@*/ *le++ = '('; - strcpy(le, defstr); le += strlen(le); + le += strlcpy(le, defstr, bufsize - 3); *le++ = ':'; *le++ = ' '; + limit = bufsize - (le - l) - 1; /* -1 for closing paren */ if (opt->arg) /* XXX programmer error */ switch (opt->argInfo & POPT_ARG_MASK) { case POPT_ARG_VAL: case POPT_ARG_INT: { long aLong = *((int *)opt->arg); - sprintf(le, "%ld", aLong); - le += strlen(le); + le += snprintf(le, limit, "%ld", aLong); } break; case POPT_ARG_LONG: { long aLong = *((long *)opt->arg); - sprintf(le, "%ld", aLong); - le += strlen(le); + le += snprintf(le, limit, "%ld", aLong); } break; case POPT_ARG_FLOAT: { double aDouble = *((float *)opt->arg); - sprintf(le, "%g", aDouble); - le += strlen(le); + le += snprintf(le, limit, "%g", aDouble); } break; case POPT_ARG_DOUBLE: { double aDouble = *((double *)opt->arg); - sprintf(le, "%g", aDouble); - le += strlen(le); + le += snprintf(le, limit, "%g", aDouble); } break; case POPT_ARG_STRING: { const char * s = *(const char **)opt->arg; if (s == NULL) { - strcpy(le, "null"); le += strlen(le); + le += strlcpy(le, "null", limit); } else { - size_t slen = 4*lineLength - (le - l) - sizeof("\"...\")"); + size_t len; + limit -= 2; /* make room for quotes */ *le++ = '"'; - strncpy(le, s, slen); le[slen] = '\0'; le += strlen(le); - if (slen < strlen(s)) { - strcpy(le, "..."); le += strlen(le); - } + len = strlcpy(le, s, limit); + if (len >= limit) { + le += limit - 3 - 1; + *le++ = '.'; *le++ = '.'; *le++ = '.'; + } else + le += len; *le++ = '"'; } } break; @@ -174,50 +207,57 @@ singleOptionDefaultValue(int lineLength, } *le++ = ')'; *le = '\0'; +/*@=boundswrite@*/ return l; } /** + * Display help text for an option. * @param fp output file handle + * @param maxLeftCol largest argument display width * @param opt option(s) * @param translation_domain translation domain */ -static void singleOptionHelp(FILE * fp, int maxLeftCol, +static void singleOptionHelp(FILE * fp, size_t maxLeftCol, const struct poptOption * opt, - /*@null@*/ const char * translation_domain) + /*@null@*/ UNUSED(const char * translation_domain)) /*@globals fileSystem @*/ /*@modifies *fp, fileSystem @*/ { - int indentLength = maxLeftCol + 5; - int lineLength = 79 - indentLength; - const unsigned char * help = D_(translation_domain, opt->descrip); + size_t indentLength = maxLeftCol + 5; + size_t lineLength = 79 - indentLength; + const char * help = D_(translation_domain, opt->descrip); const char * argDescrip = getArgDescrip(opt, translation_domain); - int helpLength; - unsigned char * defs = NULL; - unsigned char * left; - int nb = maxLeftCol + 1; + size_t helpLength; + char * defs = NULL; + char * left; + size_t lelen, limit; + size_t nb = maxLeftCol + 1; + int displaypad = 0; /* Make sure there's more than enough room in target buffer. */ if (opt->longName) nb += strlen(opt->longName); if (argDescrip) nb += strlen(argDescrip); +/*@-boundswrite@*/ left = malloc(nb); if (left == NULL) return; /* XXX can't happen */ left[0] = '\0'; left[maxLeftCol] = '\0'; if (opt->longName && opt->shortName) - sprintf(left, "-%c, %s%s", opt->shortName, + snprintf(left, nb, "-%c, %s%s", opt->shortName, ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"), opt->longName); else if (opt->shortName != '\0') - sprintf(left, "-%c", opt->shortName); + snprintf(left, nb, "-%c", opt->shortName); else if (opt->longName) - sprintf(left, "%s%s", + snprintf(left, nb, "%s%s", ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"), opt->longName); if (!*left) goto out; + if (argDescrip) { char * le = left + strlen(left); @@ -229,16 +269,10 @@ static void singleOptionHelp(FILE * fp, int maxLeftCol, if (opt->argInfo & POPT_ARGFLAG_SHOW_DEFAULT) { defs = singleOptionDefaultValue(lineLength, opt, translation_domain); if (defs) { - char * t = malloc((help ? strlen(help) : 0) + - strlen(defs) + sizeof(" ")); + size_t bufsize = (help ? strlen(help) : 0) + sizeof " " + strlen(defs); + char * t = malloc(bufsize); if (t) { - char * te = t; - *te = '\0'; - if (help) { - strcpy(te, help); te += strlen(te); - } - *te++ = ' '; - strcpy(te, defs); + snprintf(t, bufsize, "%s %s", help ? help : "", defs); defs = _free(defs); } defs = t; @@ -251,6 +285,7 @@ static void singleOptionHelp(FILE * fp, int maxLeftCol, case POPT_ARG_NONE: break; case POPT_ARG_VAL: +#ifdef NOTNOW /* XXX pug ugly nerdy output */ { long aLong = opt->val; int ops = (opt->argInfo & POPT_ARGFLAG_LOGICALOPS); int negate = (opt->argInfo & POPT_ARGFLAG_NOT); @@ -272,65 +307,94 @@ static void singleOptionHelp(FILE * fp, int maxLeftCol, default: /*@innerbreak@*/ break; } - *le++ = '='; + *le++ = (opt->longName != NULL ? '=' : ' '); if (negate) *le++ = '~'; /*@-formatconst@*/ - sprintf(le, (ops ? "0x%lx" : "%ld"), aLong); - le += strlen(le); + limit = nb - (le - left); + lelen = snprintf(le, limit, (ops ? "0x%lx" : "%ld"), aLong); + le += lelen >= limit ? limit - 1 : lelen; /*@=formatconst@*/ *le++ = ']'; - } break; + } +#endif + break; case POPT_ARG_INT: case POPT_ARG_LONG: case POPT_ARG_FLOAT: case POPT_ARG_DOUBLE: case POPT_ARG_STRING: - *le++ = '='; - strcpy(le, argDescrip); le += strlen(le); + *le++ = (opt->longName != NULL ? '=' : ' '); + limit = nb - (le - left); + lelen = strlcpy(le, argDescrip, limit); + le += lelen >= limit ? limit - 1 : lelen; break; default: break; } } else { + *le++ = '='; - strcpy(le, argDescrip); le += strlen(le); + limit = nb - (le - left); + lelen = strlcpy(le, argDescrip, limit); + if (lelen >= limit) + lelen = limit - 1; + le += lelen; + +#ifdef POPT_WCHAR_HACK + { const char * scopy = argDescrip; + mbstate_t t; + size_t n; + + memset ((void *)&t, '\0', sizeof (t)); /* In initial state. */ + /* Determine number of characters. */ + n = mbsrtowcs (NULL, &scopy, strlen(scopy), &t); + + displaypad = (int) (lelen-n); + } +#endif } if (opt->argInfo & POPT_ARGFLAG_OPTIONAL) *le++ = ']'; *le = '\0'; } +/*@=boundswrite@*/ if (help) - fprintf(fp," %-*s ", maxLeftCol, left); + fprintf(fp," %-*s ", (int)maxLeftCol+displaypad, left); else { fprintf(fp," %s\n", left); goto out; } left = _free(left); +/*@-branchstate@*/ if (defs) { - help = defs; defs = NULL; + help = defs; + defs = NULL; } +/*@=branchstate@*/ helpLength = strlen(help); +/*@-boundsread@*/ while (helpLength > lineLength) { - const unsigned char * ch; - char format[10]; + const char * ch; + char format[16]; ch = help + lineLength - 1; - while (ch > help && !isspace(*ch)) ch--; + while (ch > help && !isSpace(ch)) ch--; if (ch == help) break; /* give up */ - while (ch > (help + 1) && isspace(*ch)) ch--; + while (ch > (help + 1) && isSpace(ch)) ch--; ch++; - sprintf(format, "%%.%ds\n%%%ds", (int) (ch - help), indentLength); + snprintf(format, sizeof format, "%%.%ds\n%%%ds", (int) (ch - help), (int) indentLength); /*@-formatconst@*/ fprintf(fp, format, help, " "); /*@=formatconst@*/ help = ch; - while (isspace(*help) && *help) help++; + while (isSpace(help) && *help) help++; helpLength = strlen(help); } +/*@=boundsread@*/ if (helpLength) fprintf(fp, "%s\n", help); @@ -342,15 +406,17 @@ out: } /** + * Find display width for longest argument string. * @param opt option(s) * @param translation_domain translation domain + * @return display width */ -static int maxArgWidth(const struct poptOption * opt, - /*@null@*/ const char * translation_domain) +static size_t maxArgWidth(const struct poptOption * opt, + /*@null@*/ UNUSED(const char * translation_domain)) /*@*/ { - int max = 0; - int len = 0; + size_t max = 0; + size_t len = 0; const char * s; if (opt != NULL) @@ -370,8 +436,26 @@ static int maxArgWidth(const struct poptOption * opt, } s = getArgDescrip(opt, translation_domain); + +#ifdef POPT_WCHAR_HACK + /* XXX Calculate no. of display characters. */ + if (s) { + const char * scopy = s; + mbstate_t t; + size_t n; + +/*@-boundswrite@*/ + memset ((void *)&t, '\0', sizeof (t)); /* In initial state. */ +/*@=boundswrite@*/ + /* Determine number of characters. */ + n = mbsrtowcs (NULL, &scopy, strlen(scopy), &t); + len += sizeof("=")-1 + n; + } +#else if (s) len += sizeof("=")-1 + strlen(s); +#endif + if (opt->argInfo & POPT_ARGFLAG_OPTIONAL) len += sizeof("[]")-1; if (len > max) max = len; } @@ -387,11 +471,12 @@ static int maxArgWidth(const struct poptOption * opt, * @param fp output file handle * @param items alias/exec array * @param nitems no. of alias/exec entries + * @param left largest argument display width * @param translation_domain translation domain */ static void itemHelp(FILE * fp, - /*@null@*/ poptItem items, int nitems, int left, - /*@null@*/ const char * translation_domain) + /*@null@*/ poptItem items, int nitems, size_t left, + /*@null@*/ UNUSED(const char * translation_domain)) /*@globals fileSystem @*/ /*@modifies *fp, fileSystem @*/ { @@ -409,13 +494,16 @@ static void itemHelp(FILE * fp, } /** + * Display help text for a table of options. + * @param con context * @param fp output file handle * @param table option(s) + * @param left largest argument display width * @param translation_domain translation domain */ static void singleTableHelp(poptContext con, FILE * fp, - /*@null@*/ const struct poptOption * table, int left, - /*@null@*/ const char * translation_domain) + /*@null@*/ const struct poptOption * table, size_t left, + /*@null@*/ UNUSED(const char * translation_domain)) /*@globals fileSystem @*/ /*@modifies *fp, fileSystem @*/ { @@ -463,9 +551,11 @@ static int showHelpIntro(poptContext con, FILE * fp) fprintf(fp, POPT_("Usage:")); if (!(con->flags & POPT_CONTEXT_KEEP_FIRST)) { - /*@-nullderef@*/ /* LCL: wazzup? */ +/*@-boundsread@*/ + /*@-nullderef -type@*/ /* LCL: wazzup? */ fn = con->optionStack->argv[0]; - /*@=nullderef@*/ + /*@=nullderef =type@*/ +/*@=boundsread@*/ if (fn == NULL) return len; if (strchr(fn, '/')) fn = strrchr(fn, '/') + 1; fprintf(fp, " %s", fn); @@ -477,7 +567,7 @@ static int showHelpIntro(poptContext con, FILE * fp) void poptPrintHelp(poptContext con, FILE * fp, /*@unused@*/ UNUSED(int flags)) { - int leftColWidth; + size_t leftColWidth; (void) showHelpIntro(con, fp); if (con->otherHelp) @@ -490,47 +580,76 @@ void poptPrintHelp(poptContext con, FILE * fp, /*@unused@*/ UNUSED(int flags)) } /** + * Display usage text for an option. * @param fp output file handle + * @param cursor current display position * @param opt option(s) * @param translation_domain translation domain */ -static int singleOptionUsage(FILE * fp, int cursor, +static size_t singleOptionUsage(FILE * fp, size_t cursor, const struct poptOption * opt, /*@null@*/ const char *translation_domain) /*@globals fileSystem @*/ /*@modifies *fp, fileSystem @*/ { - int len = 3; + size_t len = 4; char shortStr[2] = { '\0', '\0' }; const char * item = shortStr; const char * argDescrip = getArgDescrip(opt, translation_domain); - if (opt->shortName!= '\0' ) { - if (!(opt->argInfo & POPT_ARG_MASK)) - return cursor; /* we did these already */ + if (opt->shortName != '\0' && opt->longName != NULL) { + len += 2; + if (!(opt->argInfo & POPT_ARGFLAG_ONEDASH)) len++; + len += strlen(opt->longName); + } else if (opt->shortName != '\0') { len++; shortStr[0] = opt->shortName; shortStr[1] = '\0'; } else if (opt->longName) { - len += 1 + strlen(opt->longName); + len += strlen(opt->longName); + if (!(opt->argInfo & POPT_ARGFLAG_ONEDASH)) len++; item = opt->longName; } - if (len == 3) return cursor; + if (len == 4) return cursor; +#ifdef POPT_WCHAR_HACK + /* XXX Calculate no. of display characters. */ + if (argDescrip) { + const char * scopy = argDescrip; + mbstate_t t; + size_t n; + +/*@-boundswrite@*/ + memset ((void *)&t, '\0', sizeof (t)); /* In initial state. */ +/*@=boundswrite@*/ + /* Determine number of characters. */ + n = mbsrtowcs (NULL, &scopy, strlen(scopy), &t); + len += sizeof("=")-1 + n; + } +#else if (argDescrip) - len += strlen(argDescrip) + 1; + len += sizeof("=")-1 + strlen(argDescrip); +#endif if ((cursor + len) > 79) { fprintf(fp, "\n "); cursor = 7; } - fprintf(fp, " [-%s%s%s%s]", - ((opt->shortName || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) ? "" : "-"), - item, - (argDescrip ? (opt->shortName != '\0' ? " " : "=") : ""), - (argDescrip ? argDescrip : "")); + if (opt->longName && opt->shortName) { + fprintf(fp, " [-%c|-%s%s%s%s]", + opt->shortName, ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "" : "-"), + opt->longName, + (argDescrip ? " " : ""), + (argDescrip ? argDescrip : "")); + } else { + fprintf(fp, " [-%s%s%s%s]", + ((opt->shortName || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) ? "" : "-"), + item, + (argDescrip ? (opt->shortName != '\0' ? " " : "=") : ""), + (argDescrip ? argDescrip : "")); + } return cursor + len + 1; } @@ -538,12 +657,14 @@ static int singleOptionUsage(FILE * fp, int cursor, /** * Display popt alias and exec usage. * @param fp output file handle + * @param cursor current display position * @param item alias/exec array * @param nitems no. of ara/exec entries * @param translation_domain translation domain */ -static int itemUsage(FILE * fp, int cursor, poptItem item, int nitems, - /*@null@*/ const char * translation_domain) +static size_t itemUsage(FILE * fp, size_t cursor, + /*@null@*/ poptItem item, int nitems, + /*@null@*/ UNUSED(const char * translation_domain)) /*@globals fileSystem @*/ /*@modifies *fp, fileSystem @*/ { @@ -567,15 +688,30 @@ static int itemUsage(FILE * fp, int cursor, poptItem item, int nitems, } /** + * Keep track of option tables already processed. + */ +typedef struct poptDone_s { + int nopts; + int maxopts; + const void ** opts; +} * poptDone; + +/** + * Display usage text for a table of options. + * @param con context * @param fp output file handle + * @param cursor current display position * @param opt option(s) * @param translation_domain translation domain + * @param done tables already processed + * @return */ -static int singleTableUsage(poptContext con, FILE * fp, - int cursor, const struct poptOption * opt, - /*@null@*/ const char * translation_domain) +static size_t singleTableUsage(poptContext con, FILE * fp, size_t cursor, + /*@null@*/ const struct poptOption * opt, + /*@null@*/ UNUSED(const char * translation_domain), + /*@null@*/ poptDone done) /*@globals fileSystem @*/ - /*@modifies *fp, fileSystem @*/ + /*@modifies *fp, done, fileSystem @*/ { /*@-branchstate@*/ /* FIX: W2DO? */ if (opt != NULL) @@ -583,9 +719,26 @@ static int singleTableUsage(poptContext con, FILE * fp, if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INTL_DOMAIN) { translation_domain = (const char *)opt->arg; } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) { - if (opt->arg) /* XXX program error */ + if (done) { + int i = 0; + for (i = 0; i < done->nopts; i++) { +/*@-boundsread@*/ + const void * that = done->opts[i]; +/*@=boundsread@*/ + if (that == NULL || that != opt->arg) + /*@innercontinue@*/ continue; + /*@innerbreak@*/ break; + } + /* Skip if this table has already been processed. */ + if (opt->arg == NULL || i < done->nopts) + continue; +/*@-boundswrite@*/ + if (done->nopts < done->maxopts) + done->opts[done->nopts++] = (const void *) opt->arg; +/*@=boundswrite@*/ + } cursor = singleTableUsage(con, fp, cursor, opt->arg, - translation_domain); + translation_domain, done); } else if ((opt->longName || opt->shortName) && !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) { cursor = singleOptionUsage(fp, cursor, opt, translation_domain); @@ -598,6 +751,7 @@ static int singleTableUsage(poptContext con, FILE * fp, /** * Return concatenated short options for display. + * @todo Sub-tables should be recursed. * @param opt option(s) * @param fp output file handle * @retval str concatenation of short options @@ -607,42 +761,51 @@ static int showShortOptions(const struct poptOption * opt, FILE * fp, /*@null@*/ char * str) /*@globals fileSystem @*/ /*@modifies *str, *fp, fileSystem @*/ + /*@requires maxRead(str) >= 0 @*/ { - char * s = alloca(300); /* larger then the ascii set */ - - s[0] = '\0'; - /*@-branchstate@*/ /* FIX: W2DO? */ - if (str == NULL) { - memset(s, 0, sizeof(s)); - str = s; - } - /*@=branchstate@*/ + /* bufsize larger then the ascii set, lazy alloca on top level call. */ + char * s = (str != NULL ? str : memset(alloca(300), 0, 300)); + int len = 0; +/*@-boundswrite@*/ if (opt != NULL) for (; (opt->longName || opt->shortName || opt->arg); opt++) { if (opt->shortName && !(opt->argInfo & POPT_ARG_MASK)) - str[strlen(str)] = opt->shortName; + s[strlen(s)] = opt->shortName; else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) if (opt->arg) /* XXX program error */ - (void) showShortOptions(opt->arg, fp, str); + len = showShortOptions(opt->arg, fp, s); } +/*@=boundswrite@*/ - if (s != str || *s != '\0') - return 0; - - fprintf(fp, " [-%s]", s); - return strlen(s) + 4; + /* On return to top level, print the short options, return print length. */ + if (s == str && *s != '\0') { + fprintf(fp, " [-%s]", s); + len = strlen(s) + sizeof(" [-]")-1; + } + return len; } void poptPrintUsage(poptContext con, FILE * fp, /*@unused@*/ UNUSED(int flags)) { - int cursor; + poptDone done = memset(alloca(sizeof(*done)), 0, sizeof(*done)); + size_t cursor; + + done->nopts = 0; + done->maxopts = 64; + cursor = done->maxopts * sizeof(*done->opts); +/*@-boundswrite@*/ + done->opts = memset(alloca(cursor), 0, cursor); + /*@-keeptrans@*/ + done->opts[done->nopts++] = (const void *) con->options; + /*@=keeptrans@*/ +/*@=boundswrite@*/ cursor = showHelpIntro(con, fp); cursor += showShortOptions(con->options, fp, NULL); - (void) singleTableUsage(con, fp, cursor, con->options, NULL); - (void) itemUsage(fp, cursor, con->aliases, con->numAliases, NULL); - (void) itemUsage(fp, cursor, con->execs, con->numExecs, NULL); + cursor = singleTableUsage(con, fp, cursor, con->options, NULL, done); + cursor = itemUsage(fp, cursor, con->aliases, con->numAliases, NULL); + cursor = itemUsage(fp, cursor, con->execs, con->numExecs, NULL); if (con->otherHelp) { cursor += strlen(con->otherHelp) + 1; @@ -658,4 +821,3 @@ void poptSetOtherOptionHelp(poptContext con, const char * text) con->otherHelp = _free(con->otherHelp); con->otherHelp = xstrdup(text); } -/*@=type@*/