Annotation of embedaddon/rsync/popt/popt.c, revision 1.1

1.1     ! misho       1: /** \ingroup popt
        !             2:  * \file popt/popt.c
        !             3:  */
        !             4: 
        !             5: /* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
        !             6:    file accompanying popt source distributions, available from
        !             7:    ftp://ftp.rpm.org/pub/rpm/dist */
        !             8: 
        !             9: #undef MYDEBUG
        !            10: 
        !            11: #include "system.h"
        !            12: 
        !            13: #if HAVE_FLOAT_H
        !            14: #include <float.h>
        !            15: #endif
        !            16: #include <math.h>
        !            17: 
        !            18: #include "findme.h"
        !            19: #include "poptint.h"
        !            20: 
        !            21: #ifndef DBL_EPSILON
        !            22: #define DBL_EPSILON 2.2204460492503131e-16
        !            23: #endif
        !            24: 
        !            25: #ifdef MYDEBUG
        !            26: /*@unchecked@*/
        !            27: int _popt_debug = 0;
        !            28: #endif
        !            29: 
        !            30: #if !defined(HAVE_STRERROR) && !defined(__LCLINT__)
        !            31: static char * strerror(int errno)
        !            32: {
        !            33:     extern int sys_nerr;
        !            34:     extern char * sys_errlist[];
        !            35: 
        !            36:     if ((0 <= errno) && (errno < sys_nerr))
        !            37:        return sys_errlist[errno];
        !            38:     else
        !            39:        return POPT_("unknown errno");
        !            40: }
        !            41: #endif
        !            42: 
        !            43: #ifdef MYDEBUG
        !            44: /*@unused@*/
        !            45: static void prtcon(const char *msg, poptContext con)
        !            46: {
        !            47:     if (msg) fprintf(stderr, "%s", msg);
        !            48:     fprintf(stderr, "\tcon %p os %p nextCharArg \"%s\" nextArg \"%s\" argv[%d] \"%s\"\n",
        !            49:        con, con->os,
        !            50:        (con->os->nextCharArg ? con->os->nextCharArg : ""),
        !            51:        (con->os->nextArg ? con->os->nextArg : ""),
        !            52:        con->os->next,
        !            53:        (con->os->argv && con->os->argv[con->os->next]
        !            54:                ? con->os->argv[con->os->next] : ""));
        !            55: }
        !            56: #endif
        !            57: 
        !            58: void poptSetExecPath(poptContext con, const char * path, int allowAbsolute)
        !            59: {
        !            60:     con->execPath = _free(con->execPath);
        !            61:     con->execPath = xstrdup(path);
        !            62:     con->execAbsolute = allowAbsolute;
        !            63:     /*@-nullstate@*/ /* LCL: con->execPath not NULL */
        !            64:     return;
        !            65:     /*@=nullstate@*/
        !            66: }
        !            67: 
        !            68: static void invokeCallbacksPRE(poptContext con, const struct poptOption * opt)
        !            69:        /*@globals internalState@*/
        !            70:        /*@modifies internalState@*/
        !            71: {
        !            72:     if (opt != NULL)
        !            73:     for (; opt->longName || opt->shortName || opt->arg; opt++) {
        !            74:        if (opt->arg == NULL) continue;         /* XXX program error. */
        !            75:        if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
        !            76:            void * arg = opt->arg;
        !            77: /*@-branchstate@*/
        !            78:            /* XXX sick hack to preserve pretense of ABI. */
        !            79:            if (arg == poptHelpOptions) arg = poptHelpOptionsI18N;
        !            80: /*@=branchstate@*/
        !            81:            /* Recurse on included sub-tables. */
        !            82:            invokeCallbacksPRE(con, arg);
        !            83:        } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK &&
        !            84:                   (opt->argInfo & POPT_CBFLAG_PRE))
        !            85:        {   /*@-castfcnptr@*/
        !            86:            poptCallbackType cb = (poptCallbackType)opt->arg;
        !            87:            /*@=castfcnptr@*/
        !            88:            /* Perform callback. */
        !            89:            /*@-noeffectuncon @*/
        !            90:            cb(con, POPT_CALLBACK_REASON_PRE, NULL, NULL, opt->descrip);
        !            91:            /*@=noeffectuncon @*/
        !            92:        }
        !            93:     }
        !            94: }
        !            95: 
        !            96: static void invokeCallbacksPOST(poptContext con, const struct poptOption * opt)
        !            97:        /*@globals internalState@*/
        !            98:        /*@modifies internalState@*/
        !            99: {
        !           100:     if (opt != NULL)
        !           101:     for (; opt->longName || opt->shortName || opt->arg; opt++) {
        !           102:        if (opt->arg == NULL) continue;         /* XXX program error. */
        !           103:        if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
        !           104:            void * arg = opt->arg;
        !           105: /*@-branchstate@*/
        !           106:            /* XXX sick hack to preserve pretense of ABI. */
        !           107:            if (arg == poptHelpOptions) arg = poptHelpOptionsI18N;
        !           108: /*@=branchstate@*/
        !           109:            /* Recurse on included sub-tables. */
        !           110:            invokeCallbacksPOST(con, arg);
        !           111:        } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK &&
        !           112:                   (opt->argInfo & POPT_CBFLAG_POST))
        !           113:        {   /*@-castfcnptr@*/
        !           114:            poptCallbackType cb = (poptCallbackType)opt->arg;
        !           115:            /*@=castfcnptr@*/
        !           116:            /* Perform callback. */
        !           117:            /*@-noeffectuncon @*/
        !           118:            cb(con, POPT_CALLBACK_REASON_POST, NULL, NULL, opt->descrip);
        !           119:            /*@=noeffectuncon @*/
        !           120:        }
        !           121:     }
        !           122: }
        !           123: 
        !           124: static void invokeCallbacksOPTION(poptContext con,
        !           125:                                  const struct poptOption * opt,
        !           126:                                  const struct poptOption * myOpt,
        !           127:                                  /*@null@*/ const void * myData, int shorty)
        !           128:        /*@globals internalState@*/
        !           129:        /*@modifies internalState@*/
        !           130: {
        !           131:     const struct poptOption * cbopt = NULL;
        !           132: 
        !           133:     if (opt != NULL)
        !           134:     for (; opt->longName || opt->shortName || opt->arg; opt++) {
        !           135:        if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
        !           136:            void * arg = opt->arg;
        !           137: /*@-branchstate@*/
        !           138:            /* XXX sick hack to preserve pretense of ABI. */
        !           139:            if (arg == poptHelpOptions) arg = poptHelpOptionsI18N;
        !           140: /*@=branchstate@*/
        !           141:            /* Recurse on included sub-tables. */
        !           142:            if (opt->arg != NULL)       /* XXX program error */
        !           143:                invokeCallbacksOPTION(con, opt->arg, myOpt, myData, shorty);
        !           144:        } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK &&
        !           145:                  !(opt->argInfo & POPT_CBFLAG_SKIPOPTION)) {
        !           146:            /* Save callback info. */
        !           147:            cbopt = opt;
        !           148:        } else if (cbopt != NULL &&
        !           149:                   ((myOpt->shortName && opt->shortName && shorty &&
        !           150:                        myOpt->shortName == opt->shortName) ||
        !           151:                    (myOpt->longName && opt->longName &&
        !           152:                /*@-nullpass@*/         /* LCL: opt->longName != NULL */
        !           153:                        !strcmp(myOpt->longName, opt->longName)))
        !           154:                /*@=nullpass@*/
        !           155:                   )
        !           156:        {   /*@-castfcnptr@*/
        !           157:            poptCallbackType cb = (poptCallbackType)cbopt->arg;
        !           158:            /*@=castfcnptr@*/
        !           159:            const void * cbData = (cbopt->descrip ? cbopt->descrip : myData);
        !           160:            /* Perform callback. */
        !           161:            if (cb != NULL) {   /* XXX program error */
        !           162:                /*@-noeffectuncon @*/
        !           163:                cb(con, POPT_CALLBACK_REASON_OPTION, myOpt,
        !           164:                        con->os->nextArg, cbData);
        !           165:                /*@=noeffectuncon @*/
        !           166:            }
        !           167:            /* Terminate (unless explcitly continuing). */
        !           168:            if (!(cbopt->argInfo & POPT_CBFLAG_CONTINUE))
        !           169:                return;
        !           170:        }
        !           171:     }
        !           172: }
        !           173: 
        !           174: poptContext poptGetContext(const char * name, int argc, const char ** argv,
        !           175:                           const struct poptOption * options, int flags)
        !           176: {
        !           177:     poptContext con = malloc(sizeof(*con));
        !           178: 
        !           179:     if (con == NULL) return NULL;      /* XXX can't happen */
        !           180:     memset(con, 0, sizeof(*con));
        !           181: 
        !           182:     con->os = con->optionStack;
        !           183:     con->os->argc = argc;
        !           184:     /*@-dependenttrans -assignexpose@*/        /* FIX: W2DO? */
        !           185:     con->os->argv = argv;
        !           186:     /*@=dependenttrans =assignexpose@*/
        !           187:     con->os->argb = NULL;
        !           188: 
        !           189:     if (!(flags & POPT_CONTEXT_KEEP_FIRST))
        !           190:        con->os->next = 1;                      /* skip argv[0] */
        !           191: 
        !           192:     con->leftovers = calloc( (argc + 1), sizeof(*con->leftovers) );
        !           193:     /*@-dependenttrans -assignexpose@*/        /* FIX: W2DO? */
        !           194:     con->options = options;
        !           195:     /*@=dependenttrans =assignexpose@*/
        !           196:     con->aliases = NULL;
        !           197:     con->numAliases = 0;
        !           198:     con->flags = flags;
        !           199:     con->execs = NULL;
        !           200:     con->numExecs = 0;
        !           201:     con->finalArgvAlloced = argc * 2;
        !           202:     con->finalArgv = calloc( con->finalArgvAlloced, sizeof(*con->finalArgv) );
        !           203:     con->execAbsolute = 1;
        !           204:     con->arg_strip = NULL;
        !           205: 
        !           206:     if (getenv("POSIXLY_CORRECT") || getenv("POSIX_ME_HARDER"))
        !           207:        con->flags |= POPT_CONTEXT_POSIXMEHARDER;
        !           208: 
        !           209:     if (name) {
        !           210:        size_t bufsize = strlen(name) + 1;
        !           211:        char * t = malloc(bufsize);
        !           212:        if (t) {
        !           213:            strlcpy(t, name, bufsize);
        !           214:            con->appName = t;
        !           215:        }
        !           216:     }
        !           217: 
        !           218:     /*@-internalglobs@*/
        !           219:     invokeCallbacksPRE(con, con->options);
        !           220:     /*@=internalglobs@*/
        !           221: 
        !           222:     return con;
        !           223: }
        !           224: 
        !           225: static void cleanOSE(/*@special@*/ struct optionStackEntry *os)
        !           226:        /*@uses os @*/
        !           227:        /*@releases os->nextArg, os->argv, os->argb @*/
        !           228:        /*@modifies os @*/
        !           229: {
        !           230:     os->nextArg = _free(os->nextArg);
        !           231:     os->argv = _free(os->argv);
        !           232:     os->argb = PBM_FREE(os->argb);
        !           233: }
        !           234: 
        !           235: /*@-boundswrite@*/
        !           236: void poptResetContext(poptContext con)
        !           237: {
        !           238:     int i;
        !           239: 
        !           240:     if (con == NULL) return;
        !           241:     while (con->os > con->optionStack) {
        !           242:        cleanOSE(con->os--);
        !           243:     }
        !           244:     con->os->argb = PBM_FREE(con->os->argb);
        !           245:     con->os->currAlias = NULL;
        !           246:     con->os->nextCharArg = NULL;
        !           247:     con->os->nextArg = NULL;
        !           248:     con->os->next = 1;                 /* skip argv[0] */
        !           249: 
        !           250:     con->numLeftovers = 0;
        !           251:     con->nextLeftover = 0;
        !           252:     con->restLeftover = 0;
        !           253:     con->doExec = NULL;
        !           254: 
        !           255:     if (con->finalArgv != NULL)
        !           256:     for (i = 0; i < con->finalArgvCount; i++) {
        !           257:        /*@-unqualifiedtrans@*/         /* FIX: typedef double indirection. */
        !           258:        con->finalArgv[i] = _free(con->finalArgv[i]);
        !           259:        /*@=unqualifiedtrans@*/
        !           260:     }
        !           261: 
        !           262:     con->finalArgvCount = 0;
        !           263:     con->arg_strip = PBM_FREE(con->arg_strip);
        !           264:     /*@-nullstate@*/   /* FIX: con->finalArgv != NULL */
        !           265:     return;
        !           266:     /*@=nullstate@*/
        !           267: }
        !           268: /*@=boundswrite@*/
        !           269: 
        !           270: /* Only one of longName, shortName should be set, not both. */
        !           271: /*@-boundswrite@*/
        !           272: static int handleExec(/*@special@*/ poptContext con,
        !           273:                /*@null@*/ const char * longName, char shortName)
        !           274:        /*@uses con->execs, con->numExecs, con->flags, con->doExec,
        !           275:                con->finalArgv, con->finalArgvAlloced, con->finalArgvCount @*/
        !           276:        /*@modifies con @*/
        !           277: {
        !           278:     poptItem item;
        !           279:     int i;
        !           280: 
        !           281:     if (con->execs == NULL || con->numExecs <= 0) /* XXX can't happen */
        !           282:        return 0;
        !           283: 
        !           284:     for (i = con->numExecs - 1; i >= 0; i--) {
        !           285:        item = con->execs + i;
        !           286:        if (longName && !(item->option.longName &&
        !           287:                        !strcmp(longName, item->option.longName)))
        !           288:            continue;
        !           289:        else if (shortName != item->option.shortName)
        !           290:            continue;
        !           291:        break;
        !           292:     }
        !           293:     if (i < 0) return 0;
        !           294: 
        !           295: 
        !           296:     if (con->flags & POPT_CONTEXT_NO_EXEC)
        !           297:        return 1;
        !           298: 
        !           299:     if (con->doExec == NULL) {
        !           300:        con->doExec = con->execs + i;
        !           301:        return 1;
        !           302:     }
        !           303: 
        !           304:     /* We already have an exec to do; remember this option for next
        !           305:        time 'round */
        !           306:     if ((con->finalArgvCount + 1) >= (con->finalArgvAlloced)) {
        !           307:        con->finalArgvAlloced += 10;
        !           308:        con->finalArgv = realloc(con->finalArgv,
        !           309:                        sizeof(*con->finalArgv) * con->finalArgvAlloced);
        !           310:     }
        !           311: 
        !           312:     i = con->finalArgvCount++;
        !           313:     if (con->finalArgv != NULL)        /* XXX can't happen */
        !           314:     {  size_t bufsize = (longName ? strlen(longName) : 0) + 3;
        !           315:        char *s  = malloc(bufsize);
        !           316:        if (s != NULL) {        /* XXX can't happen */
        !           317:            if (longName)
        !           318:                snprintf(s, bufsize, "--%s", longName);
        !           319:            else
        !           320:                snprintf(s, bufsize, "-%c", shortName);
        !           321:            con->finalArgv[i] = s;
        !           322:        } else
        !           323:            con->finalArgv[i] = NULL;
        !           324:     }
        !           325: 
        !           326:     /*@-nullstate@*/   /* FIX: con->finalArgv[] == NULL */
        !           327:     return 1;
        !           328:     /*@=nullstate@*/
        !           329: }
        !           330: /*@=boundswrite@*/
        !           331: 
        !           332: /* Only one of longName, shortName may be set at a time */
        !           333: static int handleAlias(/*@special@*/ poptContext con,
        !           334:                /*@null@*/ const char * longName, char shortName,
        !           335:                /*@exposed@*/ /*@null@*/ const char * nextCharArg)
        !           336:        /*@uses con->aliases, con->numAliases, con->optionStack, con->os,
        !           337:                con->os->currAlias, con->os->currAlias->option.longName @*/
        !           338:        /*@modifies con @*/
        !           339: {
        !           340:     poptItem item = con->os->currAlias;
        !           341:     int rc;
        !           342:     int i;
        !           343: 
        !           344:     if (item) {
        !           345:        if (longName && (item->option.longName &&
        !           346:                !strcmp(longName, item->option.longName)))
        !           347:            return 0;
        !           348:        if (shortName && shortName == item->option.shortName)
        !           349:            return 0;
        !           350:     }
        !           351: 
        !           352:     if (con->aliases == NULL || con->numAliases <= 0) /* XXX can't happen */
        !           353:        return 0;
        !           354: 
        !           355:     for (i = con->numAliases - 1; i >= 0; i--) {
        !           356:        item = con->aliases + i;
        !           357:        if (longName && !(item->option.longName &&
        !           358:                        !strcmp(longName, item->option.longName)))
        !           359:            continue;
        !           360:        else if (shortName != item->option.shortName)
        !           361:            continue;
        !           362:        break;
        !           363:     }
        !           364:     if (i < 0) return 0;
        !           365: 
        !           366:     if ((con->os - con->optionStack + 1) == POPT_OPTION_DEPTH)
        !           367:        return POPT_ERROR_OPTSTOODEEP;
        !           368: 
        !           369: /*@-boundsread@*/
        !           370:     if (nextCharArg && *nextCharArg)
        !           371:        con->os->nextCharArg = nextCharArg;
        !           372: /*@=boundsread@*/
        !           373: 
        !           374:     con->os++;
        !           375:     con->os->next = 0;
        !           376:     con->os->stuffed = 0;
        !           377:     con->os->nextArg = NULL;
        !           378:     con->os->nextCharArg = NULL;
        !           379:     con->os->currAlias = con->aliases + i;
        !           380:     rc = poptDupArgv(con->os->currAlias->argc, con->os->currAlias->argv,
        !           381:                &con->os->argc, &con->os->argv);
        !           382:     con->os->argb = NULL;
        !           383: 
        !           384:     return (rc ? rc : 1);
        !           385: }
        !           386: 
        !           387: /*@-bounds -boundswrite @*/
        !           388: static int execCommand(poptContext con)
        !           389:        /*@globals internalState @*/
        !           390:        /*@modifies internalState @*/
        !           391: {
        !           392:     poptItem item = con->doExec;
        !           393:     const char ** argv;
        !           394:     int argc = 0;
        !           395: 
        !           396:     if (item == NULL) /*XXX can't happen*/
        !           397:        return POPT_ERROR_NOARG;
        !           398: 
        !           399:     if (item->argv == NULL || item->argc < 1 ||
        !           400:        (!con->execAbsolute && strchr(item->argv[0], '/')))
        !           401:            return POPT_ERROR_NOARG;
        !           402: 
        !           403:     argv = malloc(sizeof(*argv) *
        !           404:                        (6 + item->argc + con->numLeftovers + con->finalArgvCount));
        !           405:     if (argv == NULL) return POPT_ERROR_MALLOC;
        !           406: 
        !           407:     if (!strchr(item->argv[0], '/') && con->execPath != NULL) {
        !           408:        size_t bufsize = strlen(con->execPath) + strlen(item->argv[0]) + sizeof "/";
        !           409:        char *s = alloca(bufsize);
        !           410:        snprintf(s, bufsize, "%s/%s", con->execPath, item->argv[0]);
        !           411:        argv[argc] = s;
        !           412:     } else
        !           413:        argv[argc] = findProgramPath(item->argv[0]);
        !           414:     if (argv[argc++] == NULL) return POPT_ERROR_NOARG;
        !           415: 
        !           416:     if (item->argc > 1) {
        !           417:        memcpy(argv + argc, item->argv + 1, sizeof(*argv) * (item->argc - 1));
        !           418:        argc += (item->argc - 1);
        !           419:     }
        !           420: 
        !           421:     if (con->finalArgv != NULL && con->finalArgvCount > 0) {
        !           422:        memcpy(argv + argc, con->finalArgv,
        !           423:                sizeof(*argv) * con->finalArgvCount);
        !           424:        argc += con->finalArgvCount;
        !           425:     }
        !           426: 
        !           427:     if (con->leftovers != NULL && con->numLeftovers > 0) {
        !           428:        memcpy(argv + argc, con->leftovers, sizeof(*argv) * con->numLeftovers);
        !           429:        argc += con->numLeftovers;
        !           430:     }
        !           431: 
        !           432:     argv[argc] = NULL;
        !           433: 
        !           434:   {
        !           435: #ifdef __hpux
        !           436:     int rc = setresgid(getgid(), getgid(),-1);
        !           437:     if (rc) return POPT_ERROR_ERRNO;
        !           438:     rc = setresuid(getuid(), getuid(),-1);
        !           439:     if (rc) return POPT_ERROR_ERRNO;
        !           440: #else
        !           441: /*
        !           442:  * XXX " ... on BSD systems setuid() should be preferred over setreuid()"
        !           443:  * XXX         sez' Timur Bakeyev <mc@bat.ru>
        !           444:  * XXX from Norbert Warmuth <nwarmuth@privat.circular.de>
        !           445:  */
        !           446: #if defined(HAVE_SETUID)
        !           447:     int rc = setgid(getgid());
        !           448:     if (rc) return POPT_ERROR_ERRNO;
        !           449:     rc = setuid(getuid());
        !           450:     if (rc) return POPT_ERROR_ERRNO;
        !           451: #elif defined (HAVE_SETREUID)
        !           452:     int rc = setregid(getgid(), getgid());
        !           453:     if (rc) return POPT_ERROR_ERRNO;
        !           454:     rc = setreuid(getuid(), getuid());
        !           455:     if (rc) return POPT_ERROR_ERRNO;
        !           456: #else
        !           457:     ; /* Can't drop privileges */
        !           458: #endif
        !           459: #endif
        !           460:   }
        !           461: 
        !           462:     if (argv[0] == NULL)
        !           463:        return POPT_ERROR_NOARG;
        !           464: 
        !           465: #ifdef MYDEBUG
        !           466: if (_popt_debug)
        !           467:     {  const char ** avp;
        !           468:        fprintf(stderr, "==> execvp(%s) argv[%d]:", argv[0], argc);
        !           469:        for (avp = argv; *avp; avp++)
        !           470:            fprintf(stderr, " '%s'", *avp);
        !           471:        fprintf(stderr, "\n");
        !           472:     }
        !           473: #endif
        !           474: 
        !           475:     execvp(argv[0], (char *const *)argv);
        !           476: 
        !           477:     return POPT_ERROR_ERRNO;
        !           478: }
        !           479: /*@=bounds =boundswrite @*/
        !           480: 
        !           481: /*@-boundswrite@*/
        !           482: /*@observer@*/ /*@null@*/ static const struct poptOption *
        !           483: findOption(const struct poptOption * opt, /*@null@*/ const char * longName,
        !           484:                char shortName,
        !           485:                /*@null@*/ /*@out@*/ poptCallbackType * callback,
        !           486:                /*@null@*/ /*@out@*/ const void ** callbackData,
        !           487:                int singleDash)
        !           488:        /*@modifies *callback, *callbackData */
        !           489: {
        !           490:     const struct poptOption * cb = NULL;
        !           491: 
        !           492:     /* This happens when a single - is given */
        !           493:     if (singleDash && !shortName && (longName && *longName == '\0'))
        !           494:        shortName = '-';
        !           495: 
        !           496:     for (; opt->longName || opt->shortName || opt->arg; opt++) {
        !           497: 
        !           498:        if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
        !           499:            const struct poptOption * opt2;
        !           500:            void * arg = opt->arg;
        !           501: 
        !           502: /*@-branchstate@*/
        !           503:            /* XXX sick hack to preserve pretense of ABI. */
        !           504:            if (arg == poptHelpOptions) arg = poptHelpOptionsI18N;
        !           505: /*@=branchstate@*/
        !           506:            /* Recurse on included sub-tables. */
        !           507:            if (arg == NULL) continue;  /* XXX program error */
        !           508:            opt2 = findOption(arg, longName, shortName, callback,
        !           509:                              callbackData, singleDash);
        !           510:            if (opt2 == NULL) continue;
        !           511:            /* Sub-table data will be inheirited if no data yet. */
        !           512:            if (!(callback && *callback)) return opt2;
        !           513:            if (!(callbackData && *callbackData == NULL)) return opt2;
        !           514:            /*@-observertrans -dependenttrans @*/
        !           515:            *callbackData = opt->descrip;
        !           516:            /*@=observertrans =dependenttrans @*/
        !           517:            return opt2;
        !           518:        } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_CALLBACK) {
        !           519:            cb = opt;
        !           520:        } else if (longName && opt->longName &&
        !           521:                   (!singleDash || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) &&
        !           522:                /*@-nullpass@*/         /* LCL: opt->longName != NULL */
        !           523:                   !strcmp(longName, opt->longName))
        !           524:                /*@=nullpass@*/
        !           525:        {
        !           526:            break;
        !           527:        } else if (shortName && shortName == opt->shortName) {
        !           528:            break;
        !           529:        }
        !           530:     }
        !           531: 
        !           532:     if (!opt->longName && !opt->shortName)
        !           533:        return NULL;
        !           534:     /*@-modobserver -mods @*/
        !           535:     if (callback) *callback = NULL;
        !           536:     if (callbackData) *callbackData = NULL;
        !           537:     if (cb) {
        !           538:        if (callback)
        !           539:        /*@-castfcnptr@*/
        !           540:            *callback = (poptCallbackType)cb->arg;
        !           541:        /*@=castfcnptr@*/
        !           542:        if (!(cb->argInfo & POPT_CBFLAG_INC_DATA)) {
        !           543:            if (callbackData)
        !           544:                /*@-observertrans@*/    /* FIX: typedef double indirection. */
        !           545:                *callbackData = cb->descrip;
        !           546:                /*@=observertrans@*/
        !           547:        }
        !           548:     }
        !           549:     /*@=modobserver =mods @*/
        !           550: 
        !           551:     return opt;
        !           552: }
        !           553: /*@=boundswrite@*/
        !           554: 
        !           555: static const char * findNextArg(/*@special@*/ poptContext con,
        !           556:                unsigned argx, int delete_arg)
        !           557:        /*@uses con->optionStack, con->os,
        !           558:                con->os->next, con->os->argb, con->os->argc, con->os->argv @*/
        !           559:        /*@modifies con @*/
        !           560: {
        !           561:     struct optionStackEntry * os = con->os;
        !           562:     const char * arg;
        !           563: 
        !           564:     do {
        !           565:        int i;
        !           566:        arg = NULL;
        !           567:        while (os->next == os->argc && os > con->optionStack) os--;
        !           568:        if (os->next == os->argc && os == con->optionStack) break;
        !           569:        if (os->argv != NULL)
        !           570:        for (i = os->next; i < os->argc; i++) {
        !           571:            /*@-sizeoftype@*/
        !           572:            if (os->argb && PBM_ISSET(i, os->argb))
        !           573:                /*@innercontinue@*/ continue;
        !           574:            if (*os->argv[i] == '-')
        !           575:                /*@innercontinue@*/ continue;
        !           576:            if (--argx > 0)
        !           577:                /*@innercontinue@*/ continue;
        !           578:            arg = os->argv[i];
        !           579:            if (delete_arg) {
        !           580:                if (os->argb == NULL) os->argb = PBM_ALLOC(os->argc);
        !           581:                if (os->argb != NULL)   /* XXX can't happen */
        !           582:                PBM_SET(i, os->argb);
        !           583:            }
        !           584:            /*@innerbreak@*/ break;
        !           585:            /*@=sizeoftype@*/
        !           586:        }
        !           587:        if (os > con->optionStack) os--;
        !           588:     } while (arg == NULL);
        !           589:     return arg;
        !           590: }
        !           591: 
        !           592: /*@-boundswrite@*/
        !           593: static /*@only@*/ /*@null@*/ const char *
        !           594: expandNextArg(/*@special@*/ poptContext con, const char * s)
        !           595:        /*@uses con->optionStack, con->os,
        !           596:                con->os->next, con->os->argb, con->os->argc, con->os->argv @*/
        !           597:        /*@modifies con @*/
        !           598: {
        !           599:     const char * a = NULL;
        !           600:     size_t alen, pos;
        !           601:     char *t, *te;
        !           602:     size_t tn = strlen(s) + 1;
        !           603:     char c;
        !           604: 
        !           605:     te = t = malloc(tn);;
        !           606:     if (t == NULL) return NULL;                /* XXX can't happen */
        !           607:     while ((c = *s++) != '\0') {
        !           608:        switch (c) {
        !           609: #if 0  /* XXX can't do this */
        !           610:        case '\\':      /* escape */
        !           611:            c = *s++;
        !           612:            /*@switchbreak@*/ break;
        !           613: #endif
        !           614:        case '!':
        !           615:            if (!(s[0] == '#' && s[1] == ':' && s[2] == '+'))
        !           616:                /*@switchbreak@*/ break;
        !           617:            /* XXX Make sure that findNextArg deletes only next arg. */
        !           618:            if (a == NULL) {
        !           619:                if ((a = findNextArg(con, 1, 1)) == NULL)
        !           620:                    /*@switchbreak@*/ break;
        !           621:            }
        !           622:            s += 3;
        !           623: 
        !           624:            alen = strlen(a);
        !           625:            tn += alen;
        !           626:            pos = te - t;
        !           627:            t = realloc(t, tn);
        !           628:            te = t + pos;
        !           629:            strncpy(te, a, alen); te += alen;
        !           630:            continue;
        !           631:            /*@notreached@*/ /*@switchbreak@*/ break;
        !           632:        default:
        !           633:            /*@switchbreak@*/ break;
        !           634:        }
        !           635:        *te++ = c;
        !           636:     }
        !           637:     *te = '\0';
        !           638:     t = realloc(t, strlen(t) + 1);     /* XXX memory leak, hard to plug */
        !           639:     return t;
        !           640: }
        !           641: /*@=boundswrite@*/
        !           642: 
        !           643: static void poptStripArg(/*@special@*/ poptContext con, int which)
        !           644:        /*@uses con->arg_strip, con->optionStack @*/
        !           645:        /*@defines con->arg_strip @*/
        !           646:        /*@modifies con @*/
        !           647: {
        !           648:     /*@-sizeoftype@*/
        !           649:     if (con->arg_strip == NULL)
        !           650:        con->arg_strip = PBM_ALLOC(con->optionStack[0].argc);
        !           651:     if (con->arg_strip != NULL)                /* XXX can't happen */
        !           652:     PBM_SET(which, con->arg_strip);
        !           653:     /*@=sizeoftype@*/
        !           654:     /*@-compdef@*/ /* LCL: con->arg_strip udefined? */
        !           655:     return;
        !           656:     /*@=compdef@*/
        !           657: }
        !           658: 
        !           659: int poptSaveLong(long * arg, int argInfo, long aLong)
        !           660: {
        !           661:     /* XXX Check alignment, may fail on funky platforms. */
        !           662:     if (arg == NULL || (((unsigned long)arg) & (sizeof(*arg)-1)))
        !           663:        return POPT_ERROR_NULLARG;
        !           664: 
        !           665:     if (argInfo & POPT_ARGFLAG_NOT)
        !           666:        aLong = ~aLong;
        !           667:     switch (argInfo & POPT_ARGFLAG_LOGICALOPS) {
        !           668:     case 0:
        !           669:        *arg = aLong;
        !           670:        break;
        !           671:     case POPT_ARGFLAG_OR:
        !           672:        *arg |= aLong;
        !           673:        break;
        !           674:     case POPT_ARGFLAG_AND:
        !           675:        *arg &= aLong;
        !           676:        break;
        !           677:     case POPT_ARGFLAG_XOR:
        !           678:        *arg ^= aLong;
        !           679:        break;
        !           680:     default:
        !           681:        return POPT_ERROR_BADOPERATION;
        !           682:        /*@notreached@*/ break;
        !           683:     }
        !           684:     return 0;
        !           685: }
        !           686: 
        !           687: int poptSaveInt(/*@null@*/ int * arg, int argInfo, long aLong)
        !           688: {
        !           689:     /* XXX Check alignment, may fail on funky platforms. */
        !           690:     if (arg == NULL || (((unsigned long)arg) & (sizeof(*arg)-1)))
        !           691:        return POPT_ERROR_NULLARG;
        !           692: 
        !           693:     if (argInfo & POPT_ARGFLAG_NOT)
        !           694:        aLong = ~aLong;
        !           695:     switch (argInfo & POPT_ARGFLAG_LOGICALOPS) {
        !           696:     case 0:
        !           697:        *arg = aLong;
        !           698:        break;
        !           699:     case POPT_ARGFLAG_OR:
        !           700:        *arg |= aLong;
        !           701:        break;
        !           702:     case POPT_ARGFLAG_AND:
        !           703:        *arg &= aLong;
        !           704:        break;
        !           705:     case POPT_ARGFLAG_XOR:
        !           706:        *arg ^= aLong;
        !           707:        break;
        !           708:     default:
        !           709:        return POPT_ERROR_BADOPERATION;
        !           710:        /*@notreached@*/ break;
        !           711:     }
        !           712:     return 0;
        !           713: }
        !           714: 
        !           715: /*@-boundswrite@*/
        !           716: /* returns 'val' element, -1 on last item, POPT_ERROR_* on error */
        !           717: int poptGetNextOpt(poptContext con)
        !           718: {
        !           719:     const struct poptOption * opt = NULL;
        !           720:     int done = 0;
        !           721: 
        !           722:     if (con == NULL)
        !           723:        return -1;
        !           724:     while (!done) {
        !           725:        const char * origOptString = NULL;
        !           726:        poptCallbackType cb = NULL;
        !           727:        const void * cbData = NULL;
        !           728:        const char * longArg = NULL;
        !           729:        int canstrip = 0;
        !           730:        int shorty = 0;
        !           731: 
        !           732:        while (!con->os->nextCharArg && con->os->next == con->os->argc
        !           733:                && con->os > con->optionStack) {
        !           734:            cleanOSE(con->os--);
        !           735:        }
        !           736:        if (!con->os->nextCharArg && con->os->next == con->os->argc) {
        !           737:            /*@-internalglobs@*/
        !           738:            invokeCallbacksPOST(con, con->options);
        !           739:            /*@=internalglobs@*/
        !           740:            if (con->doExec) return execCommand(con);
        !           741:            return -1;
        !           742:        }
        !           743: 
        !           744:        /* Process next long option */
        !           745:        if (!con->os->nextCharArg) {
        !           746:            char * localOptString, * optString;
        !           747:            int thisopt;
        !           748: 
        !           749:            /*@-sizeoftype@*/
        !           750:            if (con->os->argb && PBM_ISSET(con->os->next, con->os->argb)) {
        !           751:                con->os->next++;
        !           752:                continue;
        !           753:            }
        !           754:            /*@=sizeoftype@*/
        !           755:            thisopt = con->os->next;
        !           756:            if (con->os->argv != NULL)  /* XXX can't happen */
        !           757:            origOptString = con->os->argv[con->os->next++];
        !           758: 
        !           759:            if (origOptString == NULL)  /* XXX can't happen */
        !           760:                return POPT_ERROR_BADOPT;
        !           761: 
        !           762:            if (con->restLeftover || *origOptString != '-') {
        !           763:                if (con->flags & POPT_CONTEXT_POSIXMEHARDER)
        !           764:                    con->restLeftover = 1;
        !           765:                if (con->flags & POPT_CONTEXT_ARG_OPTS) {
        !           766:                    con->os->nextArg = xstrdup(origOptString);
        !           767:                    return 0;
        !           768:                }
        !           769:                if (con->leftovers != NULL)     /* XXX can't happen */
        !           770:                    con->leftovers[con->numLeftovers++] = origOptString;
        !           771:                continue;
        !           772:            }
        !           773: 
        !           774:            /* Make a copy we can hack at */
        !           775:            {   size_t bufsize = strlen(origOptString) + 1;
        !           776:                localOptString = optString = alloca(bufsize);
        !           777:                if (optString == NULL) /* XXX can't happen */
        !           778:                    return POPT_ERROR_BADOPT;
        !           779:                strlcpy(optString, origOptString, bufsize);
        !           780:            }
        !           781: 
        !           782:            if (optString[0] == '\0')
        !           783:                return POPT_ERROR_BADOPT;
        !           784: 
        !           785:            if (optString[1] == '-' && !optString[2]) {
        !           786:                con->restLeftover = 1;
        !           787:                continue;
        !           788:            } else {
        !           789:                char *oe;
        !           790:                int singleDash;
        !           791: 
        !           792:                optString++;
        !           793:                if (*optString == '-')
        !           794:                    singleDash = 0, optString++;
        !           795:                else
        !           796:                    singleDash = 1;
        !           797: 
        !           798:                /* XXX aliases with arg substitution need "--alias=arg" */
        !           799:                if (handleAlias(con, optString, '\0', NULL))
        !           800:                    continue;
        !           801: 
        !           802:                if (handleExec(con, optString, '\0'))
        !           803:                    continue;
        !           804: 
        !           805:                /* Check for "--long=arg" option. */
        !           806:                for (oe = optString; *oe && *oe != '='; oe++)
        !           807:                    {};
        !           808:                if (*oe == '=') {
        !           809:                    *oe++ = '\0';
        !           810:                    /* XXX longArg is mapped back to persistent storage. */
        !           811:                    longArg = origOptString + (oe - localOptString);
        !           812:                } else
        !           813:                    oe = NULL;
        !           814: 
        !           815:                opt = findOption(con->options, optString, '\0', &cb, &cbData,
        !           816:                                 singleDash);
        !           817:                if (!opt && !singleDash)
        !           818:                    return POPT_ERROR_BADOPT;
        !           819:                if (!opt && oe)
        !           820:                    oe[-1] = '='; /* restore overwritten '=' */
        !           821:            }
        !           822: 
        !           823:            if (!opt) {
        !           824:                con->os->nextCharArg = origOptString + 1;
        !           825:                longArg = NULL;
        !           826:            } else {
        !           827:                if (con->os == con->optionStack &&
        !           828:                   opt->argInfo & POPT_ARGFLAG_STRIP)
        !           829:                {
        !           830:                    canstrip = 1;
        !           831:                    poptStripArg(con, thisopt);
        !           832:                }
        !           833:                shorty = 0;
        !           834:            }
        !           835:        }
        !           836: 
        !           837:        /* Process next short option */
        !           838:        /*@-branchstate@*/              /* FIX: W2DO? */
        !           839:        if (con->os->nextCharArg) {
        !           840:            origOptString = con->os->nextCharArg;
        !           841: 
        !           842:            con->os->nextCharArg = NULL;
        !           843: 
        !           844:            if (handleAlias(con, NULL, *origOptString, origOptString + 1))
        !           845:                continue;
        !           846: 
        !           847:            if (handleExec(con, NULL, *origOptString)) {
        !           848:                /* Restore rest of short options for further processing */
        !           849:                origOptString++;
        !           850:                if (*origOptString != '\0')
        !           851:                    con->os->nextCharArg = origOptString;
        !           852:                continue;
        !           853:            }
        !           854: 
        !           855:            opt = findOption(con->options, NULL, *origOptString, &cb,
        !           856:                             &cbData, 0);
        !           857:            if (!opt)
        !           858:                return POPT_ERROR_BADOPT;
        !           859:            shorty = 1;
        !           860: 
        !           861:            origOptString++;
        !           862:            if (*origOptString != '\0')
        !           863:                con->os->nextCharArg = origOptString;
        !           864:        }
        !           865:        /*@=branchstate@*/
        !           866: 
        !           867:        if (opt == NULL) return POPT_ERROR_BADOPT;      /* XXX can't happen */
        !           868:        if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE
        !           869:         || (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL) {
        !           870:            if (longArg || (con->os->nextCharArg && con->os->nextCharArg[0] == '='))
        !           871:                return POPT_ERROR_UNWANTEDARG;
        !           872:            if (opt->arg) {
        !           873:                long val = (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL ? opt->val : 1;
        !           874:                if (poptSaveInt((int *)opt->arg, opt->argInfo, val))
        !           875:                    return POPT_ERROR_BADOPERATION;
        !           876:            }
        !           877:        } else {
        !           878:            con->os->nextArg = _free(con->os->nextArg);
        !           879:            /*@-usedef@*/       /* FIX: W2DO? */
        !           880:            if (longArg) {
        !           881:            /*@=usedef@*/
        !           882:                longArg = expandNextArg(con, longArg);
        !           883:                con->os->nextArg = longArg;
        !           884:            } else if (con->os->nextCharArg) {
        !           885:                longArg = expandNextArg(con, con->os->nextCharArg + (con->os->nextCharArg[0] == '='));
        !           886:                con->os->nextArg = longArg;
        !           887:                con->os->nextCharArg = NULL;
        !           888:            } else {
        !           889:                while (con->os->next == con->os->argc &&
        !           890:                       con->os > con->optionStack) {
        !           891:                    cleanOSE(con->os--);
        !           892:                }
        !           893:                if (con->os->next == con->os->argc) {
        !           894:                    if (!(opt->argInfo & POPT_ARGFLAG_OPTIONAL))
        !           895:                        /*@-compdef@*/  /* FIX: con->os->argv not defined */
        !           896:                        return POPT_ERROR_NOARG;
        !           897:                        /*@=compdef@*/
        !           898:                    con->os->nextArg = NULL;
        !           899:                } else {
        !           900: 
        !           901:                    /*
        !           902:                     * Make sure this isn't part of a short arg or the
        !           903:                     * result of an alias expansion.
        !           904:                     */
        !           905:                    if (con->os == con->optionStack &&
        !           906:                        (opt->argInfo & POPT_ARGFLAG_STRIP) &&
        !           907:                        canstrip) {
        !           908:                        poptStripArg(con, con->os->next);
        !           909:                    }
        !           910:                
        !           911:                    if (con->os->argv != NULL) {        /* XXX can't happen */
        !           912:                        /* XXX watchout: subtle side-effects live here. */
        !           913:                        longArg = con->os->argv[con->os->next++];
        !           914:                        longArg = expandNextArg(con, longArg);
        !           915:                        con->os->nextArg = longArg;
        !           916:                    }
        !           917:                }
        !           918:            }
        !           919:            longArg = NULL;
        !           920: 
        !           921:            if (opt->arg) {
        !           922:                switch (opt->argInfo & POPT_ARG_MASK) {
        !           923:                case POPT_ARG_STRING:
        !           924:                    /* XXX memory leak, hard to plug */
        !           925:                    *((const char **) opt->arg) = (con->os->nextArg)
        !           926:                        ? xstrdup(con->os->nextArg) : NULL;
        !           927:                    /*@switchbreak@*/ break;
        !           928: 
        !           929:                case POPT_ARG_INT:
        !           930:                case POPT_ARG_LONG:
        !           931:                {   long aLong = 0;
        !           932:                    char *end;
        !           933: 
        !           934:                    if (con->os->nextArg) {
        !           935:                        aLong = strtol(con->os->nextArg, &end, 0);
        !           936:                        if (!(end && *end == '\0'))
        !           937:                            return POPT_ERROR_BADNUMBER;
        !           938:                    }
        !           939: 
        !           940:                    if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_LONG) {
        !           941:                        if (aLong == LONG_MIN || aLong == LONG_MAX)
        !           942:                            return POPT_ERROR_OVERFLOW;
        !           943:                        if (poptSaveLong((long *)opt->arg, opt->argInfo, aLong))
        !           944:                            return POPT_ERROR_BADOPERATION;
        !           945:                    } else {
        !           946:                        if (aLong > INT_MAX || aLong < INT_MIN)
        !           947:                            return POPT_ERROR_OVERFLOW;
        !           948:                        if (poptSaveInt((int *)opt->arg, opt->argInfo, aLong))
        !           949:                            return POPT_ERROR_BADOPERATION;
        !           950:                    }
        !           951:                }   /*@switchbreak@*/ break;
        !           952: 
        !           953:                case POPT_ARG_FLOAT:
        !           954:                case POPT_ARG_DOUBLE:
        !           955:                {   double aDouble = 0.0;
        !           956:                    char *end;
        !           957: 
        !           958:                    if (con->os->nextArg) {
        !           959:                        /*@-mods@*/
        !           960:                        int saveerrno = errno;
        !           961:                        errno = 0;
        !           962:                        aDouble = strtod(con->os->nextArg, &end);
        !           963:                        if (errno == ERANGE)
        !           964:                            return POPT_ERROR_OVERFLOW;
        !           965:                        errno = saveerrno;
        !           966:                        /*@=mods@*/
        !           967:                        if (*end != '\0')
        !           968:                            return POPT_ERROR_BADNUMBER;
        !           969:                    }
        !           970: 
        !           971:                    if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_DOUBLE) {
        !           972:                        *((double *) opt->arg) = aDouble;
        !           973:                    } else {
        !           974: #define MY_ABS(a) ((((a) - 0.0) < DBL_EPSILON) ? -(a) : (a))
        !           975:                        if ((MY_ABS(aDouble) - FLT_MAX) > DBL_EPSILON)
        !           976:                            return POPT_ERROR_OVERFLOW;
        !           977:                        if ((FLT_MIN - MY_ABS(aDouble)) > DBL_EPSILON)
        !           978:                            return POPT_ERROR_OVERFLOW;
        !           979:                        *((float *) opt->arg) = aDouble;
        !           980:                    }
        !           981:                }   /*@switchbreak@*/ break;
        !           982:                default:
        !           983:                    fprintf(stdout,
        !           984:                        POPT_("option type (%d) not implemented in popt\n"),
        !           985:                        (opt->argInfo & POPT_ARG_MASK));
        !           986:                    exit(EXIT_FAILURE);
        !           987:                    /*@notreached@*/ /*@switchbreak@*/ break;
        !           988:                }
        !           989:            }
        !           990:        }
        !           991: 
        !           992:        if (cb) {
        !           993:            /*@-internalglobs@*/
        !           994:            invokeCallbacksOPTION(con, con->options, opt, cbData, shorty);
        !           995:            /*@=internalglobs@*/
        !           996:        } else if (opt->val && ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_VAL))
        !           997:            done = 1;
        !           998: 
        !           999:        if ((con->finalArgvCount + 2) >= (con->finalArgvAlloced)) {
        !          1000:            con->finalArgvAlloced += 10;
        !          1001:            con->finalArgv = realloc(con->finalArgv,
        !          1002:                            sizeof(*con->finalArgv) * con->finalArgvAlloced);
        !          1003:        }
        !          1004: 
        !          1005:        if (con->finalArgv != NULL)
        !          1006:        {   ssize_t bufsize = (opt->longName ? strlen(opt->longName) : 0) + 3;
        !          1007:            char *s = malloc(bufsize);
        !          1008:            if (s != NULL) {    /* XXX can't happen */
        !          1009:                if (opt->longName)
        !          1010:                    snprintf(s, bufsize, "%s%s",
        !          1011:                        ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"),
        !          1012:                        opt->longName);
        !          1013:                else
        !          1014:                    snprintf(s, bufsize, "-%c", opt->shortName);
        !          1015:                con->finalArgv[con->finalArgvCount++] = s;
        !          1016:            } else
        !          1017:                con->finalArgv[con->finalArgvCount++] = NULL;
        !          1018:        }
        !          1019: 
        !          1020:        if (opt->arg && (opt->argInfo & POPT_ARG_MASK) == POPT_ARG_NONE)
        !          1021:            /*@-ifempty@*/ ; /*@=ifempty@*/
        !          1022:        else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_VAL)
        !          1023:            /*@-ifempty@*/ ; /*@=ifempty@*/
        !          1024:        else if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_NONE) {
        !          1025:            if (con->finalArgv != NULL && con->os->nextArg)
        !          1026:                con->finalArgv[con->finalArgvCount++] =
        !          1027:                        /*@-nullpass@*/ /* LCL: con->os->nextArg != NULL */
        !          1028:                        xstrdup(con->os->nextArg);
        !          1029:                        /*@=nullpass@*/
        !          1030:        }
        !          1031:     }
        !          1032: 
        !          1033:     return (opt ? opt->val : -1);      /* XXX can't happen */
        !          1034: }
        !          1035: /*@=boundswrite@*/
        !          1036: 
        !          1037: const char * poptGetOptArg(poptContext con)
        !          1038: {
        !          1039:     const char * ret = NULL;
        !          1040:     /*@-branchstate@*/
        !          1041:     if (con) {
        !          1042:        ret = con->os->nextArg;
        !          1043:        con->os->nextArg = NULL;
        !          1044:     }
        !          1045:     /*@=branchstate@*/
        !          1046:     return ret;
        !          1047: }
        !          1048: 
        !          1049: const char * poptGetArg(poptContext con)
        !          1050: {
        !          1051:     const char * ret = NULL;
        !          1052:     if (con && con->leftovers != NULL && con->nextLeftover < con->numLeftovers)
        !          1053:        ret = con->leftovers[con->nextLeftover++];
        !          1054:     return ret;
        !          1055: }
        !          1056: 
        !          1057: const char * poptPeekArg(poptContext con)
        !          1058: {
        !          1059:     const char * ret = NULL;
        !          1060:     if (con && con->leftovers != NULL && con->nextLeftover < con->numLeftovers)
        !          1061:        ret = con->leftovers[con->nextLeftover];
        !          1062:     return ret;
        !          1063: }
        !          1064: 
        !          1065: /*@-boundswrite@*/
        !          1066: const char ** poptGetArgs(poptContext con)
        !          1067: {
        !          1068:     if (con == NULL ||
        !          1069:        con->leftovers == NULL || con->numLeftovers == con->nextLeftover)
        !          1070:        return NULL;
        !          1071: 
        !          1072:     /* some apps like [like RPM ;-) ] need this NULL terminated */
        !          1073:     con->leftovers[con->numLeftovers] = NULL;
        !          1074: 
        !          1075:     /*@-nullret -nullstate @*/ /* FIX: typedef double indirection. */
        !          1076:     return (con->leftovers + con->nextLeftover);
        !          1077:     /*@=nullret =nullstate @*/
        !          1078: }
        !          1079: /*@=boundswrite@*/
        !          1080: 
        !          1081: poptContext poptFreeContext(poptContext con)
        !          1082: {
        !          1083:     poptItem item;
        !          1084:     int i;
        !          1085: 
        !          1086:     if (con == NULL) return con;
        !          1087:     poptResetContext(con);
        !          1088:     con->os->argb = _free(con->os->argb);
        !          1089: 
        !          1090:     if (con->aliases != NULL)
        !          1091:     for (i = 0; i < con->numAliases; i++) {
        !          1092:        item = con->aliases + i;
        !          1093:        /*@-modobserver -observertrans -dependenttrans@*/
        !          1094:        item->option.longName = _free(item->option.longName);
        !          1095:        item->option.descrip = _free(item->option.descrip);
        !          1096:        item->option.argDescrip = _free(item->option.argDescrip);
        !          1097:        /*@=modobserver =observertrans =dependenttrans@*/
        !          1098:        item->argv = _free(item->argv);
        !          1099:     }
        !          1100:     con->aliases = _free(con->aliases);
        !          1101: 
        !          1102:     if (con->execs != NULL)
        !          1103:     for (i = 0; i < con->numExecs; i++) {
        !          1104:        item = con->execs + i;
        !          1105:        /*@-modobserver -observertrans -dependenttrans@*/
        !          1106:        item->option.longName = _free(item->option.longName);
        !          1107:        item->option.descrip = _free(item->option.descrip);
        !          1108:        item->option.argDescrip = _free(item->option.argDescrip);
        !          1109:        /*@=modobserver =observertrans =dependenttrans@*/
        !          1110:        item->argv = _free(item->argv);
        !          1111:     }
        !          1112:     con->execs = _free(con->execs);
        !          1113: 
        !          1114:     con->leftovers = _free(con->leftovers);
        !          1115:     con->finalArgv = _free(con->finalArgv);
        !          1116:     con->appName = _free(con->appName);
        !          1117:     con->otherHelp = _free(con->otherHelp);
        !          1118:     con->execPath = _free(con->execPath);
        !          1119:     con->arg_strip = PBM_FREE(con->arg_strip);
        !          1120:     
        !          1121:     con = _free(con);
        !          1122:     return con;
        !          1123: }
        !          1124: 
        !          1125: int poptAddAlias(poptContext con, struct poptAlias alias,
        !          1126:                /*@unused@*/ UNUSED(int flags))
        !          1127: {
        !          1128:     poptItem item = (poptItem) alloca(sizeof(*item));
        !          1129:     memset(item, 0, sizeof(*item));
        !          1130:     item->option.longName = alias.longName;
        !          1131:     item->option.shortName = alias.shortName;
        !          1132:     item->option.argInfo = POPT_ARGFLAG_DOC_HIDDEN;
        !          1133:     item->option.arg = 0;
        !          1134:     item->option.val = 0;
        !          1135:     item->option.descrip = NULL;
        !          1136:     item->option.argDescrip = NULL;
        !          1137:     item->argc = alias.argc;
        !          1138:     item->argv = alias.argv;
        !          1139:     return poptAddItem(con, item, 0);
        !          1140: }
        !          1141: 
        !          1142: /*@-boundswrite@*/
        !          1143: /*@-mustmod@*/ /* LCL: con not modified? */
        !          1144: int poptAddItem(poptContext con, poptItem newItem, int flags)
        !          1145: {
        !          1146:     poptItem * items, item;
        !          1147:     int * nitems;
        !          1148: 
        !          1149:     switch (flags) {
        !          1150:     case 1:
        !          1151:        items = &con->execs;
        !          1152:        nitems = &con->numExecs;
        !          1153:        break;
        !          1154:     case 0:
        !          1155:        items = &con->aliases;
        !          1156:        nitems = &con->numAliases;
        !          1157:        break;
        !          1158:     default:
        !          1159:        return 1;
        !          1160:        /*@notreached@*/ break;
        !          1161:     }
        !          1162: 
        !          1163:     *items = realloc((*items), ((*nitems) + 1) * sizeof(**items));
        !          1164:     if ((*items) == NULL)
        !          1165:        return 1;
        !          1166: 
        !          1167:     item = (*items) + (*nitems);
        !          1168: 
        !          1169:     item->option.longName =
        !          1170:        (newItem->option.longName ? xstrdup(newItem->option.longName) : NULL);
        !          1171:     item->option.shortName = newItem->option.shortName;
        !          1172:     item->option.argInfo = newItem->option.argInfo;
        !          1173:     item->option.arg = newItem->option.arg;
        !          1174:     item->option.val = newItem->option.val;
        !          1175:     item->option.descrip =
        !          1176:        (newItem->option.descrip ? xstrdup(newItem->option.descrip) : NULL);
        !          1177:     item->option.argDescrip =
        !          1178:        (newItem->option.argDescrip ? xstrdup(newItem->option.argDescrip) : NULL);
        !          1179:     item->argc = newItem->argc;
        !          1180:     item->argv = newItem->argv;
        !          1181: 
        !          1182:     (*nitems)++;
        !          1183: 
        !          1184:     return 0;
        !          1185: }
        !          1186: /*@=mustmod@*/
        !          1187: /*@=boundswrite@*/
        !          1188: 
        !          1189: const char * poptBadOption(poptContext con, int flags)
        !          1190: {
        !          1191:     struct optionStackEntry * os = NULL;
        !          1192: 
        !          1193:     if (con != NULL)
        !          1194:        os = (flags & POPT_BADOPTION_NOALIAS) ? con->optionStack : con->os;
        !          1195: 
        !          1196:     /*@-nullderef@*/   /* LCL: os->argv != NULL */
        !          1197:     return (os && os->argv ? os->argv[os->next - 1] : NULL);
        !          1198:     /*@=nullderef@*/
        !          1199: }
        !          1200: 
        !          1201: const char * poptStrerror(const int error)
        !          1202: {
        !          1203:     switch (error) {
        !          1204:       case POPT_ERROR_NOARG:
        !          1205:        return POPT_("missing argument");
        !          1206:       case POPT_ERROR_UNWANTEDARG:
        !          1207:        return POPT_("option does not take an argument");
        !          1208:       case POPT_ERROR_BADOPT:
        !          1209:        return POPT_("unknown option");
        !          1210:       case POPT_ERROR_BADOPERATION:
        !          1211:        return POPT_("mutually exclusive logical operations requested");
        !          1212:       case POPT_ERROR_NULLARG:
        !          1213:        return POPT_("opt->arg should not be NULL");
        !          1214:       case POPT_ERROR_OPTSTOODEEP:
        !          1215:        return POPT_("aliases nested too deeply");
        !          1216:       case POPT_ERROR_BADQUOTE:
        !          1217:        return POPT_("error in parameter quoting");
        !          1218:       case POPT_ERROR_BADNUMBER:
        !          1219:        return POPT_("invalid numeric value");
        !          1220:       case POPT_ERROR_OVERFLOW:
        !          1221:        return POPT_("number too large or too small");
        !          1222:       case POPT_ERROR_MALLOC:
        !          1223:        return POPT_("memory allocation failed");
        !          1224:       case POPT_ERROR_ERRNO:
        !          1225:        return strerror(errno);
        !          1226:       default:
        !          1227:        return POPT_("unknown error");
        !          1228:     }
        !          1229: }
        !          1230: 
        !          1231: int poptStuffArgs(poptContext con, const char ** argv)
        !          1232: {
        !          1233:     int argc;
        !          1234:     int rc;
        !          1235: 
        !          1236:     if ((con->os - con->optionStack) == POPT_OPTION_DEPTH)
        !          1237:        return POPT_ERROR_OPTSTOODEEP;
        !          1238: 
        !          1239:     for (argc = 0; argv[argc]; argc++)
        !          1240:        {};
        !          1241: 
        !          1242:     con->os++;
        !          1243:     con->os->next = 0;
        !          1244:     con->os->nextArg = NULL;
        !          1245:     con->os->nextCharArg = NULL;
        !          1246:     con->os->currAlias = NULL;
        !          1247:     rc = poptDupArgv(argc, argv, &con->os->argc, &con->os->argv);
        !          1248:     con->os->argb = NULL;
        !          1249:     con->os->stuffed = 1;
        !          1250: 
        !          1251:     return rc;
        !          1252: }
        !          1253: 
        !          1254: const char * poptGetInvocationName(poptContext con)
        !          1255: {
        !          1256:     return (con->os->argv ? con->os->argv[0] : "");
        !          1257: }
        !          1258: 
        !          1259: /*@-boundswrite@*/
        !          1260: int poptStrippedArgv(poptContext con, int argc, char ** argv)
        !          1261: {
        !          1262:     int numargs = argc;
        !          1263:     int j = 1;
        !          1264:     int i;
        !          1265:     
        !          1266:     /*@-sizeoftype@*/
        !          1267:     if (con->arg_strip)
        !          1268:     for (i = 1; i < argc; i++) {
        !          1269:        if (PBM_ISSET(i, con->arg_strip))
        !          1270:            numargs--;
        !          1271:     }
        !          1272:     
        !          1273:     for (i = 1; i < argc; i++) {
        !          1274:        if (con->arg_strip && PBM_ISSET(i, con->arg_strip))
        !          1275:            continue;
        !          1276:        argv[j] = (j < numargs) ? argv[i] : NULL;
        !          1277:        j++;
        !          1278:     }
        !          1279:     /*@=sizeoftype@*/
        !          1280:     
        !          1281:     return numargs;
        !          1282: }
        !          1283: /*@=boundswrite@*/

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>