diff options
-rw-r--r-- | CHANGES | 3 | ||||
-rw-r--r-- | popt.c | 170 | ||||
-rw-r--r-- | popt.h | 4 | ||||
-rw-r--r-- | popthelp.c | 55 | ||||
-rw-r--r-- | poptint.h | 5 |
5 files changed, 120 insertions, 117 deletions
@@ -1,4 +1,7 @@ 1.13 -> 1.14: + - jbj: free aliases/execs with common code. + - jbj: rewrite the callback logic using a switch for simplicity. + - jbj: hide bit field structure behind F_ISSET/LF_ISSET/CBF_ISSET macros. - jbj: expose poptSaveLongLong and poptSaveString in the loader map. - jbj: add POPT_ARG_ARGV, starting with the poptSaveString() method. - jbj: add help for POPT_ARG_LONGLONG. @@ -68,18 +68,19 @@ static void invokeCallbacksPRE(poptContext con, const struct poptOption * opt) if (opt != NULL) for (; opt->longName || opt->shortName || opt->arg; opt++) { poptArg arg = { .ptr = opt->arg }; - if (arg.ptr == NULL) continue; /* XXX program error. */ - if (poptArgType(opt) == POPT_ARG_INCLUDE_TABLE) { + if (arg.ptr) + switch (poptArgType(opt)) { + case POPT_ARG_INCLUDE_TABLE: /* Recurse on included sub-tables. */ poptSubstituteHelpI18N(arg.opt); /* XXX side effects */ - /* Recurse on included sub-tables. */ invokeCallbacksPRE(con, arg.opt); - } else if (poptArgType(opt) == POPT_ARG_CALLBACK && - (opt->argInfo & POPT_CBFLAG_PRE)) - { - /* Perform callback. */ + /*@switchbreak@*/ break; + case POPT_ARG_CALLBACK: /* Perform callback. */ + if (!CBF_ISSET(opt, PRE)) + /*@switchbreak@*/ break; /*@-noeffectuncon @*/ arg.cb(con, POPT_CALLBACK_REASON_PRE, NULL, NULL, opt->descrip); /*@=noeffectuncon @*/ + /*@switchbreak@*/ break; } } } @@ -91,26 +92,27 @@ static void invokeCallbacksPOST(poptContext con, const struct poptOption * opt) if (opt != NULL) for (; opt->longName || opt->shortName || opt->arg; opt++) { poptArg arg = { .ptr = opt->arg }; - if (arg.ptr == NULL) continue; /* XXX program error. */ - if (poptArgType(opt) == POPT_ARG_INCLUDE_TABLE) { + if (arg.ptr) + switch (poptArgType(opt)) { + case POPT_ARG_INCLUDE_TABLE: /* Recurse on included sub-tables. */ poptSubstituteHelpI18N(arg.opt); /* XXX side effects */ - /* Recurse on included sub-tables. */ invokeCallbacksPOST(con, arg.opt); - } else if (poptArgType(opt) == POPT_ARG_CALLBACK && - (opt->argInfo & POPT_CBFLAG_POST)) - { - /* Perform callback. */ + /*@switchbreak@*/ break; + case POPT_ARG_CALLBACK: /* Perform callback. */ + if (!CBF_ISSET(opt, POST)) + /*@switchbreak@*/ break; /*@-noeffectuncon @*/ arg.cb(con, POPT_CALLBACK_REASON_POST, NULL, NULL, opt->descrip); /*@=noeffectuncon @*/ + /*@switchbreak@*/ break; } } } static void invokeCallbacksOPTION(poptContext con, - const struct poptOption * opt, - const struct poptOption * myOpt, - /*@null@*/ const void * myData, int shorty) + const struct poptOption * opt, + const struct poptOption * myOpt, + /*@null@*/ const void * myData, int shorty) /*@globals internalState@*/ /*@modifies internalState@*/ { @@ -120,40 +122,41 @@ static void invokeCallbacksOPTION(poptContext con, if (opt != NULL) for (; opt->longName || opt->shortName || opt->arg; opt++) { poptArg arg = { .ptr = opt->arg }; - if (poptArgType(opt) == POPT_ARG_INCLUDE_TABLE) { + switch (poptArgType(opt)) { + case POPT_ARG_INCLUDE_TABLE: /* Recurse on included sub-tables. */ poptSubstituteHelpI18N(arg.opt); /* XXX side effects */ - /* Recurse on included sub-tables. */ - if (opt->arg != NULL) /* XXX program error */ + if (opt->arg != NULL) invokeCallbacksOPTION(con, opt->arg, myOpt, myData, shorty); - } else if (poptArgType(opt) == POPT_ARG_CALLBACK && - !(opt->argInfo & POPT_CBFLAG_SKIPOPTION)) { - /* Save callback info. */ + /*@switchbreak@*/ break; + case POPT_ARG_CALLBACK: /* Save callback info. */ + if (CBF_ISSET(opt, SKIPOPTION)) + /*@switchbreak@*/ break; cbopt = opt; cbarg.ptr = opt->arg; - } else if (cbopt != NULL && - ((myOpt->shortName && opt->shortName && shorty && - myOpt->shortName == opt->shortName) || - (myOpt->longName != NULL && opt->longName != NULL && + /*@switchbreak@*/ break; + default: /* Perform callback on matching option. */ + if (cbopt == NULL || cbarg.cb == NULL) + /*@switchbreak@*/ break; + if ((myOpt->shortName && opt->shortName && shorty && + myOpt->shortName == opt->shortName) + || (myOpt->longName != NULL && opt->longName != NULL && !strcmp(myOpt->longName, opt->longName))) - ) - { - const void * cbData = (cbopt->descrip ? cbopt->descrip : myData); - /* Perform callback. */ - if (cbarg.cb != NULL) { /* XXX program error */ + { const void *cbData = (cbopt->descrip ? cbopt->descrip : myData); /*@-noeffectuncon @*/ - cbarg.cb(con, POPT_CALLBACK_REASON_OPTION, myOpt, - con->os->nextArg, cbData); + cbarg.cb(con, POPT_CALLBACK_REASON_OPTION, + myOpt, con->os->nextArg, cbData); /*@=noeffectuncon @*/ + /* Terminate (unless explcitly continuing). */ + if (!CBF_ISSET(cbopt, CONTINUE)) + return; } - /* Terminate (unless explcitly continuing). */ - if (!(cbopt->argInfo & POPT_CBFLAG_CONTINUE)) - return; + /*@switchbreak@*/ break; } } } poptContext poptGetContext(const char * name, int argc, const char ** argv, - const struct poptOption * options, unsigned int flags) + const struct poptOption * options, unsigned int flags) { poptContext con = malloc(sizeof(*con)); @@ -490,7 +493,7 @@ findOption(const struct poptOption * opt, /*@null@*/ const char * longName, int cb = opt; cbarg.ptr = opt->arg; } else if (longName != NULL && opt->longName != NULL && - (!singleDash || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) && + (!singleDash || F_ISSET(opt, ONEDASH)) && (!strncmp(longName, opt->longName, longNameLen) && strlen(opt->longName) == longNameLen)) { break; @@ -507,8 +510,7 @@ findOption(const struct poptOption * opt, /*@null@*/ const char * longName, int *callback = (cb ? cbarg.cb : NULL); if (callbackData) /*@-observertrans@*/ /* FIX: typedef double indirection. */ - *callbackData = (cb && !(cb->argInfo & POPT_CBFLAG_INC_DATA) - ? cb->descrip : NULL); + *callbackData = (cb && !CBF_ISSET(cb, INC_DATA) ? cb->descrip : NULL); /*@=observertrans@*/ /*@=modobserver =mods @*/ @@ -657,7 +659,7 @@ int poptSaveLongLong(long long * arg, unsigned int argInfo, long long aLongLong) ) return POPT_ERROR_NULLARG; - if (aLongLong != 0 && argInfo & POPT_ARGFLAG_RANDOM) { + if (aLongLong != 0 && LF_ISSET(RANDOM)) { if (!seed) { srandom((unsigned)getpid()); srandom((unsigned)random()); @@ -665,9 +667,9 @@ int poptSaveLongLong(long long * arg, unsigned int argInfo, long long aLongLong) aLongLong = random() % (aLongLong > 0 ? aLongLong : -aLongLong); aLongLong++; } - if (argInfo & POPT_ARGFLAG_NOT) + if (LF_ISSET(NOT)) aLongLong = ~aLongLong; - switch (argInfo & POPT_ARGFLAG_LOGICALOPS) { + switch (LF_ISSET(LOGICALOPS)) { case 0: *arg = aLongLong; break; @@ -695,7 +697,7 @@ int poptSaveLong(long * arg, unsigned int argInfo, long aLong) if (arg == NULL || (((unsigned long)arg) & (sizeof(*arg)-1))) return POPT_ERROR_NULLARG; - if (aLong != 0 && argInfo & POPT_ARGFLAG_RANDOM) { + if (aLong != 0 && LF_ISSET(RANDOM)) { if (!seed) { srandom((unsigned)getpid()); srandom((unsigned)random()); @@ -703,9 +705,9 @@ int poptSaveLong(long * arg, unsigned int argInfo, long aLong) aLong = random() % (aLong > 0 ? aLong : -aLong); aLong++; } - if (argInfo & POPT_ARGFLAG_NOT) + if (LF_ISSET(NOT)) aLong = ~aLong; - switch (argInfo & POPT_ARGFLAG_LOGICALOPS) { + switch (LF_ISSET(LOGICALOPS)) { case 0: *arg = aLong; break; @@ -733,7 +735,7 @@ int poptSaveInt(/*@null@*/ int * arg, unsigned int argInfo, long aLong) if (arg == NULL || (((unsigned long)arg) & (sizeof(*arg)-1))) return POPT_ERROR_NULLARG; - if (aLong != 0 && argInfo & POPT_ARGFLAG_RANDOM) { + if (aLong != 0 && LF_ISSET(RANDOM)) { if (!seed) { srandom((unsigned)getpid()); srandom((unsigned)random()); @@ -741,9 +743,9 @@ int poptSaveInt(/*@null@*/ int * arg, unsigned int argInfo, long aLong) aLong = random() % (aLong > 0 ? aLong : -aLong); aLong++; } - if (argInfo & POPT_ARGFLAG_NOT) + if (LF_ISSET(NOT)) aLong = ~aLong; - switch (argInfo & POPT_ARGFLAG_LOGICALOPS) { + switch (LF_ISSET(LOGICALOPS)) { case 0: *arg = aLong; break; @@ -873,8 +875,7 @@ int poptGetNextOpt(poptContext con) if (!opt) { con->os->nextCharArg = origOptString + 1; } else { - if (con->os == con->optionStack && - opt->argInfo & POPT_ARGFLAG_STRIP) + if (con->os == con->optionStack && F_ISSET(opt, STRIP)) { canstrip = 1; poptStripArg(con, thisopt); @@ -931,11 +932,12 @@ int poptGetNextOpt(poptContext con) con->os->nextCharArg = NULL; } else { while (con->os->next == con->os->argc && - con->os > con->optionStack) { + con->os > con->optionStack) + { cleanOSE(con->os--); } if (con->os->next == con->os->argc) { - if (!(opt->argInfo & POPT_ARGFLAG_OPTIONAL)) + if (!F_ISSET(opt, OPTIONAL)) return POPT_ERROR_NOARG; con->os->nextArg = NULL; } else { @@ -944,14 +946,14 @@ int poptGetNextOpt(poptContext con) * Make sure this isn't part of a short arg or the * result of an alias expansion. */ - if (con->os == con->optionStack && - (opt->argInfo & POPT_ARGFLAG_STRIP) && - canstrip) { + if (con->os == con->optionStack + && F_ISSET(opt, STRIP) && canstrip) + { poptStripArg(con, con->os->next); } if (con->os->argv != NULL) { /* XXX can't happen */ - if (opt->argInfo & POPT_ARGFLAG_OPTIONAL && + if (F_ISSET(opt, OPTIONAL) && con->os->argv[con->os->next][0] == '-') { con->os->nextArg = NULL; } else { @@ -1074,8 +1076,7 @@ int poptGetNextOpt(poptContext con) { char *s = malloc((opt->longName ? strlen(opt->longName) : 0) + 3); if (s != NULL) { /* XXX can't happen */ if (opt->longName) - sprintf(s, "%s%s", - ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"), + sprintf(s, "%s%s", (F_ISSET(opt, ONEDASH) ? "-" : "--"), opt->longName); else sprintf(s, "-%c", opt->shortName); @@ -1138,38 +1139,37 @@ const char ** poptGetArgs(poptContext con) /*@=nullret =nullstate @*/ } -poptContext poptFreeContext(poptContext con) +static /*@null@*/ +poptItem poptFreeItems(/*@only@*/ /*@null@*/ poptItem items, int nitems) + /*@modifies items @*/ { - poptItem item; - int i; + if (items != NULL) { + poptItem item = items; + while (--nitems >= 0) { +/*@-modobserver -observertrans -dependenttrans@*/ + item->option.longName = _free(item->option.longName); + item->option.descrip = _free(item->option.descrip); + item->option.argDescrip = _free(item->option.argDescrip); +/*@=modobserver =observertrans =dependenttrans@*/ + item->argv = _free(item->argv); + item++; + } + items = _free(items); + } + return NULL; +} +poptContext poptFreeContext(poptContext con) +{ if (con == NULL) return con; poptResetContext(con); con->os->argb = _free(con->os->argb); - if (con->aliases != NULL) - for (i = 0; i < con->numAliases; i++) { - item = con->aliases + i; -/*@-modobserver -observertrans -dependenttrans@*/ - item->option.longName = _free(item->option.longName); - item->option.descrip = _free(item->option.descrip); - item->option.argDescrip = _free(item->option.argDescrip); -/*@=modobserver =observertrans =dependenttrans@*/ - item->argv = _free(item->argv); - } - con->aliases = _free(con->aliases); + con->aliases = poptFreeItems(con->aliases, con->numAliases); + con->numAliases = 0; - if (con->execs != NULL) - for (i = 0; i < con->numExecs; i++) { - item = con->execs + i; -/*@-modobserver -observertrans -dependenttrans@*/ - item->option.longName = _free(item->option.longName); - item->option.descrip = _free(item->option.descrip); - item->option.argDescrip = _free(item->option.argDescrip); -/*@=modobserver =observertrans =dependenttrans@*/ - item->argv = _free(item->argv); - } - con->execs = _free(con->execs); + con->execs = poptFreeItems(con->execs, con->numExecs); + con->numExecs = 0; con->leftovers = _free(con->leftovers); con->finalArgv = _free(con->finalArgv); @@ -35,8 +35,8 @@ #define POPT_ARG_DOUBLE 9U /*!< arg ==> double */ #define POPT_ARG_LONGLONG 10U /*!< arg ==> long long */ -#define POPT_ARG_MAINCALL 256+11U /*!< EXPERIMENTAL: return (*arg) (argc, argv) */ -#define POPT_ARG_ARGV 256+12U /*!< (unimplemented): dupe'd arg appended to realloc'd argv array. */ +#define POPT_ARG_MAINCALL 16+11U /*!< EXPERIMENTAL: return (*arg) (argc, argv) */ +#define POPT_ARG_ARGV 16+12U /*!< (unimplemented): dupe'd arg appended to realloc'd argv array. */ #define POPT_ARG_MASK 0x0000FFFFU /*@}*/ @@ -310,7 +310,7 @@ static void singleOptionHelp(FILE * fp, columns_t columns, goto out; if (prtshort && prtlong) sprintf(left, "-%c, %s%s", opt->shortName, - ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"), + (F_ISSET(opt, ONEDASH) ? "-" : "--"), opt->longName); else if (prtshort) sprintf(left, "-%c", opt->shortName); @@ -319,18 +319,18 @@ static void singleOptionHelp(FILE * fp, columns_t columns, sprintf(left, " %s%s", (poptArgType(opt) == POPT_ARG_MAINCALL ? "" : (poptArgType(opt) == POPT_ARG_ARGV ? "" : - ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"))), + (F_ISSET(opt, ONEDASH) ? "-" : "--"))), opt->longName); #undef prtlong if (argDescrip) { char * le = left + strlen(left); - if (opt->argInfo & POPT_ARGFLAG_OPTIONAL) + if (F_ISSET(opt, OPTIONAL)) *le++ = '['; /* Choose type of output */ - if (opt->argInfo & POPT_ARGFLAG_SHOW_DEFAULT) { + if (F_ISSET(opt, SHOW_DEFAULT)) { defs = singleOptionDefaultValue(lineLength, opt, translation_domain); if (defs) { char * t = malloc((help ? strlen(help) : 0) + @@ -356,8 +356,8 @@ static void singleOptionHelp(FILE * fp, columns_t columns, 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); + int ops = F_ISSET(opt, LOGICALOPS); + int negate = F_ISSET(opt, NOT); /* Don't bother displaying typical values */ if (!ops && (aLong == 0L || aLong == 1L || aLong == -1L)) @@ -421,7 +421,7 @@ static void singleOptionHelp(FILE * fp, columns_t columns, } #endif } - if (opt->argInfo & POPT_ARGFLAG_OPTIONAL) + if (F_ISSET(opt, OPTIONAL)) *le++ = ']'; *le = '\0'; } @@ -489,13 +489,12 @@ static size_t maxArgWidth(const struct poptOption * opt, if (opt->arg) /* XXX program error */ len = maxArgWidth(opt->arg, translation_domain); if (len > max) max = len; - } else if (!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) { + } else if (!F_ISSET(opt, DOC_HIDDEN)) { len = sizeof(" ")-1; /* XXX --long always padded for alignment with/without "-X, ". */ len += sizeof("-X, ")-1; if (opt->longName) { - len += ((opt->argInfo & POPT_ARGFLAG_ONEDASH) - ? sizeof("-")-1 : sizeof("--")-1); + len += (F_ISSET(opt, ONEDASH) ? sizeof("-") : sizeof("--")) - 1; len += strlen(opt->longName); } @@ -508,7 +507,7 @@ static size_t maxArgWidth(const struct poptOption * opt, const char * scopy = s; mbstate_t t; - memset ((void *)&t, 0, sizeof (t)); /* In initial state. */ + memset ((void *)&t, 0, sizeof(t)); /* In initial state. */ /* Determine number of display characters. */ n = mbsrtowcs (NULL, &scopy, strlen(scopy), &t); #else @@ -519,7 +518,7 @@ static size_t maxArgWidth(const struct poptOption * opt, len += n; } - if (opt->argInfo & POPT_ARGFLAG_OPTIONAL) len += sizeof("[]")-1; + if (F_ISSET(opt, OPTIONAL)) len += sizeof("[]")-1; if (len > max) max = len; } opt++; @@ -550,8 +549,7 @@ static void itemHelp(FILE * fp, for (i = 0, item = items; i < nitems; i++, item++) { const struct poptOption * opt; opt = &item->option; - if ((opt->longName || opt->shortName) && - !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) + if ((opt->longName || opt->shortName) && !F_ISSET(opt, DOC_HIDDEN)) singleOptionHelp(fp, columns, opt, translation_domain); } } @@ -583,8 +581,7 @@ static void singleTableHelp(poptContext con, FILE * fp, if (table != NULL) for (opt = table; opt->longName || opt->shortName || opt->arg; opt++) { - if ((opt->longName || opt->shortName) && - !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) + if ((opt->longName || opt->shortName) && !F_ISSET(opt, DOC_HIDDEN)) singleOptionHelp(fp, columns, opt, translation_domain); } @@ -662,7 +659,7 @@ static size_t singleOptionUsage(FILE * fp, columns_t columns, /*@globals fileSystem @*/ /*@modifies fp, columns->cur, fileSystem @*/ { - size_t len = sizeof(" []") - 1; + size_t len = sizeof(" []")-1; const char * argDescrip = getArgDescrip(opt, translation_domain); /* Display shortName iff printable non-space. */ int prtshort = (int)(isprint((int)opt->shortName) && opt->shortName != ' '); @@ -671,13 +668,12 @@ static size_t singleOptionUsage(FILE * fp, columns_t columns, if (!(prtshort || prtlong)) return columns->cur; - len = sizeof(" []") - 1; + len = sizeof(" []")-1; if (prtshort) - len += sizeof("-c") - 1; + len += sizeof("-c")-1; if (prtlong) { - if (prtshort) len += sizeof("|") - 1; - len += ((opt->argInfo & POPT_ARGFLAG_ONEDASH) - ? sizeof("-") : sizeof("--")) - 1; + if (prtshort) len += sizeof("|")-1; + len += (F_ISSET(opt, ONEDASH) ? sizeof("-") : sizeof("--")) - 1; len += strlen(opt->longName); } @@ -688,7 +684,7 @@ static size_t singleOptionUsage(FILE * fp, columns_t columns, const char * scopy = argDescrip; mbstate_t t; - memset ((void *)&t, 0, sizeof (t)); /* In initial state. */ + memset ((void *)&t, 0, sizeof(t)); /* In initial state. */ /* Determine number of display characters. */ n = mbsrtowcs (NULL, &scopy, strlen(scopy), &t); #else @@ -710,7 +706,7 @@ static size_t singleOptionUsage(FILE * fp, columns_t columns, if (prtlong) fprintf(fp, "%s%s%s", (prtshort ? "|" : ""), - ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"), + (F_ISSET(opt, ONEDASH) ? "-" : "--"), opt->longName); #undef prtlong @@ -746,8 +742,8 @@ static size_t itemUsage(FILE * fp, columns_t columns, opt = &item->option; if (poptArgType(opt) == POPT_ARG_INTL_DOMAIN) { translation_domain = (const char *)opt->arg; - } else if ((opt->longName || opt->shortName) && - !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) { + } else + if ((opt->longName || opt->shortName) && !F_ISSET(opt, DOC_HIDDEN)) { columns->cur = singleOptionUsage(fp, columns, opt, translation_domain); } } @@ -786,7 +782,8 @@ static size_t singleTableUsage(poptContext con, FILE * fp, columns_t columns, for (; (opt->longName || opt->shortName || opt->arg) ; opt++) { if (poptArgType(opt) == POPT_ARG_INTL_DOMAIN) { translation_domain = (const char *)opt->arg; - } else if (poptArgType(opt) == POPT_ARG_INCLUDE_TABLE) { + } else + if (poptArgType(opt) == POPT_ARG_INCLUDE_TABLE) { if (done) { int i = 0; if (done->opts != NULL) @@ -804,8 +801,8 @@ static size_t singleTableUsage(poptContext con, FILE * fp, columns_t columns, } columns->cur = singleTableUsage(con, fp, columns, opt->arg, translation_domain, done); - } else if ((opt->longName || opt->shortName) && - !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) { + } else + if ((opt->longName || opt->shortName) && !F_ISSET(opt, DOC_HIDDEN)) { columns->cur = singleOptionUsage(fp, columns, opt, translation_domain); } } @@ -69,7 +69,10 @@ typedef union poptArg_u { } poptArg; /*@=exporttype =fielduse@*/ -#define poptArgType(opt) ((opt)->argInfo & POPT_ARG_MASK) +#define poptArgType(_opt) ((_opt)->argInfo & POPT_ARG_MASK) +#define F_ISSET(_opt, _FLAG) ((_opt)->argInfo & POPT_ARGFLAG_##_FLAG) +#define LF_ISSET(_FLAG) (argInfo & POPT_ARGFLAG_##_FLAG) +#define CBF_ISSET(_opt, _FLAG) ((_opt)->argInfo & POPT_CBFLAG_##_FLAG) /* XXX sick hack to preserve pretense of a popt-1.x ABI. */ #define poptSubstituteHelpI18N(opt) \ |