root/lib/popt/popt.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. strerror
  2. prtcon
  3. poptSetExecPath
  4. invokeCallbacksPRE
  5. invokeCallbacksPOST
  6. invokeCallbacksOPTION
  7. poptGetContext
  8. cleanOSE
  9. poptResetContext
  10. handleExec
  11. handleAlias
  12. execCommand
  13. findOption
  14. findNextArg
  15. expandNextArg
  16. poptStripArg
  17. poptSaveLong
  18. poptSaveInt
  19. poptGetNextOpt
  20. poptGetOptArg
  21. poptGetArg
  22. poptPeekArg
  23. poptGetArgs
  24. poptFreeContext
  25. poptAddAlias
  26. poptAddItem
  27. poptBadOption
  28. poptStrerror
  29. poptStuffArgs
  30. poptGetInvocationName
  31. poptStrippedArgv

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

/* [<][>][^][v][top][bottom][index][help] */