~ubuntu-branches/debian/jessie/ldb/jessie

« back to all changes in this revision

Viewing changes to third_party/popt/popt.c

  • Committer: Package Import Robot
  • Author(s): Jelmer Vernooij
  • Date: 2014-07-05 23:32:23 UTC
  • mfrom: (1.3.16)
  • Revision ID: package-import@ubuntu.com-20140705233223-dss2i2wmfksxbivh
Tags: 1:1.1.18-1
* New upstream release.
 + Depend on tdb >= 1.3.2.
 + Fixes __attribute__((visibility)) check to not use nested functions.
   Closes: #749987
* Use canonical URL in Vcs-Git field.
* Specify branch in Vcs-Git field.
* Add 02_hurd: link against pthread on the Hurd, to fix ldb module
  loading. Closes: #749095

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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) {
 
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)
 
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)
 
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)
 
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)
 
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,
 
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,
 
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)
 
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)
 
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,
 
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,
 
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)
 
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,
 
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,
 
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)
 
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)
 
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)
 
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)
 
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)
 
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)
 
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)
 
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)
 
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)
 
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)
 
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,
 
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)
 
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)
 
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)
 
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)
 
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)
 
1221
{
 
1222
    return (con->os->argv ? con->os->argv[0] : "");
 
1223
}
 
1224
 
 
1225
/*@-boundswrite@*/
 
1226
int poptStrippedArgv(poptContext con, int argc, char ** argv)
 
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@*/