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

« back to all changes in this revision

Viewing changes to third_party/popt/popthelp.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
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 
2
 
 
3
/*@-type@*/
 
4
/** \ingroup popt
 
5
 * \file popt/popthelp.c
 
6
 */
 
7
 
 
8
/* (C) 1998-2002 Red Hat, Inc. -- Licensing details are in the COPYING
 
9
   file accompanying popt source distributions, available from 
 
10
   ftp://ftp.rpm.org/pub/rpm/dist. */
 
11
 
 
12
#include "system.h"
 
13
#include "poptint.h"
 
14
 
 
15
/**
 
16
 * Display arguments.
 
17
 * @param con           context
 
18
 * @param foo           (unused)
 
19
 * @param key           option(s)
 
20
 * @param arg           (unused)
 
21
 * @param data          (unused)
 
22
 */
 
23
static void displayArgs(poptContext con,
 
24
                /*@unused@*/ enum poptCallbackReason foo,
 
25
                struct poptOption * key, 
 
26
                /*@unused@*/ const char * arg, /*@unused@*/ void * data)
 
27
        /*@globals fileSystem@*/
 
28
        /*@modifies fileSystem@*/
 
29
{
 
30
    if (key->shortName == '?')
 
31
        poptPrintHelp(con, stdout, 0);
 
32
    else
 
33
        poptPrintUsage(con, stdout, 0);
 
34
    exit(0);
 
35
}
 
36
 
 
37
#ifdef  NOTYET
 
38
/*@unchecked@*/
 
39
static int show_option_defaults = 0;
 
40
#endif
 
41
 
 
42
/**
 
43
 * Empty table marker to enable displaying popt alias/exec options.
 
44
 */
 
45
/*@observer@*/ /*@unchecked@*/
 
46
struct poptOption poptAliasOptions[] = {
 
47
    POPT_TABLEEND
 
48
};
 
49
 
 
50
/**
 
51
 * Auto help table options.
 
52
 */
 
53
/*@-castfcnptr@*/
 
54
/*@observer@*/ /*@unchecked@*/
 
55
struct poptOption poptHelpOptions[] = {
 
56
  { NULL, '\0', POPT_ARG_CALLBACK, (void *)&displayArgs, '\0', NULL, NULL },
 
57
  { "help", '?', 0, NULL, '?', N_("Show this help message"), NULL },
 
58
  { "usage", '\0', 0, NULL, 'u', N_("Display brief usage message"), NULL },
 
59
#ifdef  NOTYET
 
60
  { "defaults", '\0', POPT_ARG_NONE, &show_option_defaults, 0,
 
61
        N_("Display option defaults in message"), NULL },
 
62
#endif
 
63
    POPT_TABLEEND
 
64
} ;
 
65
/*@=castfcnptr@*/
 
66
 
 
67
/**
 
68
 * @param table         option(s)
 
69
 */
 
70
/*@observer@*/ /*@null@*/ static const char *
 
71
getTableTranslationDomain(/*@null@*/ const struct poptOption *table)
 
72
        /*@*/
 
73
{
 
74
    const struct poptOption *opt;
 
75
 
 
76
    if (table != NULL)
 
77
    for (opt = table; opt->longName || opt->shortName || opt->arg; opt++) {
 
78
        if (opt->argInfo == POPT_ARG_INTL_DOMAIN)
 
79
            return (char *)opt->arg;
 
80
    }
 
81
    return NULL;
 
82
}
 
83
 
 
84
/**
 
85
 * @param opt           option(s)
 
86
 * @param translation_domain    translation domain
 
87
 */
 
88
/*@observer@*/ /*@null@*/ static const char *
 
89
getArgDescrip(const struct poptOption * opt,
 
90
                /*@-paramuse@*/ /* FIX: i18n macros disabled with lclint */
 
91
                /*@null@*/ const char * translation_domain)
 
92
                /*@=paramuse@*/
 
93
        /*@*/
 
94
{
 
95
    if (!(opt->argInfo & POPT_ARG_MASK)) return NULL;
 
96
 
 
97
    if (opt == (poptHelpOptions + 1) || opt == (poptHelpOptions + 2))
 
98
        if (opt->argDescrip) return POPT_(opt->argDescrip);
 
99
 
 
100
    if (opt->argDescrip) return D_(translation_domain, opt->argDescrip);
 
101
 
 
102
    switch (opt->argInfo & POPT_ARG_MASK) {
 
103
    case POPT_ARG_NONE:         return POPT_("NONE");
 
104
#ifdef  DYING
 
105
    case POPT_ARG_VAL:          return POPT_("VAL");
 
106
#else
 
107
    case POPT_ARG_VAL:          return NULL;
 
108
#endif
 
109
    case POPT_ARG_INT:          return POPT_("INT");
 
110
    case POPT_ARG_LONG:         return POPT_("LONG");
 
111
    case POPT_ARG_STRING:       return POPT_("STRING");
 
112
    case POPT_ARG_FLOAT:        return POPT_("FLOAT");
 
113
    case POPT_ARG_DOUBLE:       return POPT_("DOUBLE");
 
114
    default:                    return POPT_("ARG");
 
115
    }
 
116
}
 
117
 
 
118
/**
 
119
 * Display default value for an option.
 
120
 * @param lineLength
 
121
 * @param opt           option(s)
 
122
 * @param translation_domain    translation domain
 
123
 * @return
 
124
 */
 
125
static /*@only@*/ /*@null@*/ char *
 
126
singleOptionDefaultValue(int lineLength,
 
127
                const struct poptOption * opt,
 
128
                /*@-paramuse@*/ /* FIX: i18n macros disabled with lclint */
 
129
                /*@null@*/ const char * translation_domain)
 
130
                /*@=paramuse@*/
 
131
        /*@*/
 
132
{
 
133
    const char * defstr = D_(translation_domain, "default");
 
134
    char * le = (char *)malloc(4*lineLength + 1);
 
135
    char * l = le;
 
136
 
 
137
    if (le == NULL) return NULL;        /* XXX can't happen */
 
138
/*@-boundswrite@*/
 
139
    *le = '\0';
 
140
    *le++ = '(';
 
141
    strcpy(le, defstr); le += strlen(le);
 
142
    *le++ = ':';
 
143
    *le++ = ' ';
 
144
    if (opt->arg)       /* XXX programmer error */
 
145
    switch (opt->argInfo & POPT_ARG_MASK) {
 
146
    case POPT_ARG_VAL:
 
147
    case POPT_ARG_INT:
 
148
    {   long aLong = *((int *)opt->arg);
 
149
        le += sprintf(le, "%ld", aLong);
 
150
    }   break;
 
151
    case POPT_ARG_LONG:
 
152
    {   long aLong = *((long *)opt->arg);
 
153
        le += sprintf(le, "%ld", aLong);
 
154
    }   break;
 
155
    case POPT_ARG_FLOAT:
 
156
    {   double aDouble = *((float *)opt->arg);
 
157
        le += sprintf(le, "%g", aDouble);
 
158
    }   break;
 
159
    case POPT_ARG_DOUBLE:
 
160
    {   double aDouble = *((double *)opt->arg);
 
161
        le += sprintf(le, "%g", aDouble);
 
162
    }   break;
 
163
    case POPT_ARG_STRING:
 
164
    {   const char * s = *(const char **)opt->arg;
 
165
        if (s == NULL) {
 
166
            strcpy(le, "null"); le += strlen(le);
 
167
        } else {
 
168
            size_t slen = 4*lineLength - (le - l) - sizeof("\"...\")");
 
169
            *le++ = '"';
 
170
            strncpy(le, s, slen); le[slen] = '\0'; le += strlen(le);
 
171
            if (slen < strlen(s)) {
 
172
                strcpy(le, "...");      le += strlen(le);
 
173
            }
 
174
            *le++ = '"';
 
175
        }
 
176
    }   break;
 
177
    case POPT_ARG_NONE:
 
178
    default:
 
179
        l = (char *)_free(l);
 
180
        return NULL;
 
181
        /*@notreached@*/ break;
 
182
    }
 
183
    *le++ = ')';
 
184
    *le = '\0';
 
185
/*@=boundswrite@*/
 
186
 
 
187
    return l;
 
188
}
 
189
 
 
190
/**
 
191
 * Display help text for an option.
 
192
 * @param fp            output file handle
 
193
 * @param maxLeftCol
 
194
 * @param opt           option(s)
 
195
 * @param translation_domain    translation domain
 
196
 */
 
197
static void singleOptionHelp(FILE * fp, int maxLeftCol,
 
198
                const struct poptOption * opt,
 
199
                /*@null@*/ const char * translation_domain)
 
200
        /*@globals fileSystem @*/
 
201
        /*@modifies *fp, fileSystem @*/
 
202
{
 
203
    int indentLength = maxLeftCol + 5;
 
204
    int lineLength = 79 - indentLength;
 
205
    const char * help = D_(translation_domain, opt->descrip);
 
206
    const char * argDescrip = getArgDescrip(opt, translation_domain);
 
207
    int helpLength;
 
208
    char * defs = NULL;
 
209
    char * left;
 
210
    int nb = maxLeftCol + 1;
 
211
 
 
212
    /* Make sure there's more than enough room in target buffer. */
 
213
    if (opt->longName)  nb += strlen(opt->longName);
 
214
    if (argDescrip)     nb += strlen(argDescrip);
 
215
 
 
216
/*@-boundswrite@*/
 
217
    left = (char *)malloc(nb);
 
218
    if (left == NULL) return;   /* XXX can't happen */
 
219
    left[0] = '\0';
 
220
    left[maxLeftCol] = '\0';
 
221
 
 
222
    if (opt->longName && opt->shortName)
 
223
        sprintf(left, "-%c, %s%s", opt->shortName,
 
224
                ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"),
 
225
                opt->longName);
 
226
    else if (opt->shortName != '\0')
 
227
        sprintf(left, "-%c", opt->shortName);
 
228
    else if (opt->longName)
 
229
        sprintf(left, "%s%s",
 
230
                ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"),
 
231
                opt->longName);
 
232
    if (!*left) goto out;
 
233
 
 
234
    if (argDescrip) {
 
235
        char * le = left + strlen(left);
 
236
 
 
237
        if (opt->argInfo & POPT_ARGFLAG_OPTIONAL)
 
238
            *le++ = '[';
 
239
 
 
240
        /* Choose type of output */
 
241
        /*@-branchstate@*/
 
242
        if (opt->argInfo & POPT_ARGFLAG_SHOW_DEFAULT) {
 
243
                defs = singleOptionDefaultValue(lineLength, opt, translation_domain);
 
244
                if (defs) {
 
245
                        char * t = (char *)malloc((help ? strlen(help) : 0) +
 
246
                                strlen(defs) + sizeof(" "));
 
247
                        if (t) {
 
248
                                char * te = t;
 
249
                                *te = '\0';
 
250
                                if (help) {
 
251
                                        strcpy(te, help);
 
252
                                        te += strlen(te);
 
253
                                }
 
254
                                *te++ = ' ';
 
255
                                strcpy(te, defs);
 
256
                        }
 
257
                        defs = (char *)_free(defs);
 
258
                        defs = t;
 
259
                }
 
260
        }
 
261
        /*@=branchstate@*/
 
262
 
 
263
        if (opt->argDescrip == NULL) {
 
264
            switch (opt->argInfo & POPT_ARG_MASK) {
 
265
            case POPT_ARG_NONE:
 
266
                break;
 
267
            case POPT_ARG_VAL:
 
268
#ifdef  NOTNOW  /* XXX pug ugly nerdy output */
 
269
            {   long aLong = opt->val;
 
270
                int ops = (opt->argInfo & POPT_ARGFLAG_LOGICALOPS);
 
271
                int negate = (opt->argInfo & POPT_ARGFLAG_NOT);
 
272
 
 
273
                /* Don't bother displaying typical values */
 
274
                if (!ops && (aLong == 0L || aLong == 1L || aLong == -1L))
 
275
                    break;
 
276
                *le++ = '[';
 
277
                switch (ops) {
 
278
                case POPT_ARGFLAG_OR:
 
279
                    *le++ = '|';
 
280
                    /*@innerbreak@*/ break;
 
281
                case POPT_ARGFLAG_AND:
 
282
                    *le++ = '&';
 
283
                    /*@innerbreak@*/ break;
 
284
                case POPT_ARGFLAG_XOR:
 
285
                    *le++ = '^';
 
286
                    /*@innerbreak@*/ break;
 
287
                default:
 
288
                    /*@innerbreak@*/ break;
 
289
                }
 
290
                *le++ = '=';
 
291
                if (negate) *le++ = '~';
 
292
                /*@-formatconst@*/
 
293
                le += sprintf(le, (ops ? "0x%lx" : "%ld"), aLong);
 
294
                /*@=formatconst@*/
 
295
                *le++ = ']';
 
296
            }
 
297
#endif
 
298
                break;
 
299
            case POPT_ARG_INT:
 
300
            case POPT_ARG_LONG:
 
301
            case POPT_ARG_FLOAT:
 
302
            case POPT_ARG_DOUBLE:
 
303
            case POPT_ARG_STRING:
 
304
                *le++ = '=';
 
305
                strcpy(le, argDescrip);         le += strlen(le);
 
306
                break;
 
307
            default:
 
308
                break;
 
309
            }
 
310
        } else {
 
311
            *le++ = '=';
 
312
            strcpy(le, argDescrip);             le += strlen(le);
 
313
        }
 
314
        if (opt->argInfo & POPT_ARGFLAG_OPTIONAL)
 
315
            *le++ = ']';
 
316
        *le = '\0';
 
317
    }
 
318
/*@=boundswrite@*/
 
319
 
 
320
    if (help)
 
321
        fprintf(fp,"  %-*s   ", maxLeftCol, left);
 
322
    else {
 
323
        fprintf(fp,"  %s\n", left);
 
324
        goto out;
 
325
    }
 
326
 
 
327
    left = (char *)_free(left);
 
328
    if (defs) {
 
329
        help = defs;
 
330
    }
 
331
 
 
332
    helpLength = strlen(help);
 
333
/*@-boundsread@*/
 
334
    while (helpLength > lineLength) {
 
335
        const char * ch;
 
336
        char format[16];
 
337
 
 
338
        ch = help + lineLength - 1;
 
339
        while (ch > help && !isspace(*ch)) ch--;
 
340
        if (ch == help) break;          /* give up */
 
341
        while (ch > (help + 1) && isspace(*ch)) ch--;
 
342
        ch++;
 
343
 
 
344
        sprintf(format, "%%.%ds\n%%%ds", (int) (ch - help), indentLength);
 
345
        /*@-formatconst@*/
 
346
        fprintf(fp, format, help, " ");
 
347
        /*@=formatconst@*/
 
348
        help = ch;
 
349
        while (isspace(*help) && *help) help++;
 
350
        helpLength = strlen(help);
 
351
    }
 
352
/*@=boundsread@*/
 
353
 
 
354
    if (helpLength) fprintf(fp, "%s\n", help);
 
355
 
 
356
out:
 
357
    /*@-dependenttrans@*/
 
358
    defs = (char *)_free(defs);
 
359
    /*@=dependenttrans@*/
 
360
    left = (char *)_free(left);
 
361
}
 
362
 
 
363
/**
 
364
 * @param opt           option(s)
 
365
 * @param translation_domain    translation domain
 
366
 */
 
367
static int maxArgWidth(const struct poptOption * opt,
 
368
                       /*@null@*/ const char * translation_domain)
 
369
        /*@*/
 
370
{
 
371
    int max = 0;
 
372
    int len = 0;
 
373
    const char * s;
 
374
    
 
375
    if (opt != NULL)
 
376
    while (opt->longName || opt->shortName || opt->arg) {
 
377
        if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
 
378
            if (opt->arg)       /* XXX program error */
 
379
            len = maxArgWidth((const struct poptOption *)opt->arg, translation_domain);
 
380
            if (len > max) max = len;
 
381
        } else if (!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) {
 
382
            len = sizeof("  ")-1;
 
383
            if (opt->shortName != '\0') len += sizeof("-X")-1;
 
384
            if (opt->shortName != '\0' && opt->longName) len += sizeof(", ")-1;
 
385
            if (opt->longName) {
 
386
                len += ((opt->argInfo & POPT_ARGFLAG_ONEDASH)
 
387
                        ? sizeof("-")-1 : sizeof("--")-1);
 
388
                len += strlen(opt->longName);
 
389
            }
 
390
 
 
391
            s = getArgDescrip(opt, translation_domain);
 
392
            if (s)
 
393
                len += sizeof("=")-1 + strlen(s);
 
394
            if (opt->argInfo & POPT_ARGFLAG_OPTIONAL) len += sizeof("[]")-1;
 
395
            if (len > max) max = len;
 
396
        }
 
397
 
 
398
        opt++;
 
399
    }
 
400
    
 
401
    return max;
 
402
}
 
403
 
 
404
/**
 
405
 * Display popt alias and exec help.
 
406
 * @param fp            output file handle
 
407
 * @param items         alias/exec array
 
408
 * @param nitems        no. of alias/exec entries
 
409
 * @param left
 
410
 * @param translation_domain    translation domain
 
411
 */
 
412
static void itemHelp(FILE * fp,
 
413
                /*@null@*/ poptItem items, int nitems, int left,
 
414
                /*@null@*/ const char * translation_domain)
 
415
        /*@globals fileSystem @*/
 
416
        /*@modifies *fp, fileSystem @*/
 
417
{
 
418
    poptItem item;
 
419
    int i;
 
420
 
 
421
    if (items != NULL)
 
422
    for (i = 0, item = items; i < nitems; i++, item++) {
 
423
        const struct poptOption * opt;
 
424
        opt = &item->option;
 
425
        if ((opt->longName || opt->shortName) &&
 
426
            !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN))
 
427
            singleOptionHelp(fp, left, opt, translation_domain);
 
428
    }
 
429
}
 
430
 
 
431
/**
 
432
 * Display help text for a table of options.
 
433
 * @param con           context
 
434
 * @param fp            output file handle
 
435
 * @param table         option(s)
 
436
 * @param left
 
437
 * @param translation_domain    translation domain
 
438
 */
 
439
static void singleTableHelp(poptContext con, FILE * fp,
 
440
                /*@null@*/ const struct poptOption * table, int left,
 
441
                /*@null@*/ const char * translation_domain)
 
442
        /*@globals fileSystem @*/
 
443
        /*@modifies *fp, fileSystem @*/
 
444
{
 
445
    const struct poptOption * opt;
 
446
    const char *sub_transdom;
 
447
 
 
448
    if (table == poptAliasOptions) {
 
449
        itemHelp(fp, con->aliases, con->numAliases, left, NULL);
 
450
        itemHelp(fp, con->execs, con->numExecs, left, NULL);
 
451
        return;
 
452
    }
 
453
 
 
454
    if (table != NULL)
 
455
    for (opt = table; (opt->longName || opt->shortName || opt->arg); opt++) {
 
456
        if ((opt->longName || opt->shortName) && 
 
457
            !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN))
 
458
            singleOptionHelp(fp, left, opt, translation_domain);
 
459
    }
 
460
 
 
461
    if (table != NULL)
 
462
    for (opt = table; (opt->longName || opt->shortName || opt->arg); opt++) {
 
463
        if ((opt->argInfo & POPT_ARG_MASK) != POPT_ARG_INCLUDE_TABLE)
 
464
            continue;
 
465
        sub_transdom = getTableTranslationDomain(
 
466
            (const struct poptOption *)opt->arg);
 
467
        if (sub_transdom == NULL)
 
468
            sub_transdom = translation_domain;
 
469
            
 
470
        if (opt->descrip)
 
471
            fprintf(fp, "\n%s\n", D_(sub_transdom, opt->descrip));
 
472
 
 
473
        singleTableHelp(con, fp, (const struct poptOption *)opt->arg, left, sub_transdom);
 
474
    }
 
475
}
 
476
 
 
477
/**
 
478
 * @param con           context
 
479
 * @param fp            output file handle
 
480
 */
 
481
static int showHelpIntro(poptContext con, FILE * fp)
 
482
        /*@globals fileSystem @*/
 
483
        /*@modifies *fp, fileSystem @*/
 
484
{
 
485
    int len = 6;
 
486
    const char * fn;
 
487
 
 
488
    fprintf(fp, POPT_("Usage:"));
 
489
    if (!(con->flags & POPT_CONTEXT_KEEP_FIRST)) {
 
490
/*@-boundsread@*/
 
491
        /*@-nullderef@*/        /* LCL: wazzup? */
 
492
        fn = con->optionStack->argv[0];
 
493
        /*@=nullderef@*/
 
494
/*@=boundsread@*/
 
495
        if (fn == NULL) return len;
 
496
        if (strchr(fn, '/')) fn = strrchr(fn, '/') + 1;
 
497
        fprintf(fp, " %s", fn);
 
498
        len += strlen(fn) + 1;
 
499
    }
 
500
 
 
501
    return len;
 
502
}
 
503
 
 
504
void poptPrintHelp(poptContext con, FILE * fp, /*@unused@*/ int flags)
 
505
{
 
506
    int leftColWidth;
 
507
 
 
508
    (void) showHelpIntro(con, fp);
 
509
    if (con->otherHelp)
 
510
        fprintf(fp, " %s\n", con->otherHelp);
 
511
    else
 
512
        fprintf(fp, " %s\n", POPT_("[OPTION...]"));
 
513
 
 
514
    leftColWidth = maxArgWidth(con->options, NULL);
 
515
    singleTableHelp(con, fp, con->options, leftColWidth, NULL);
 
516
}
 
517
 
 
518
/**
 
519
 * @param fp            output file handle
 
520
 * @param cursor
 
521
 * @param opt           option(s)
 
522
 * @param translation_domain    translation domain
 
523
 */
 
524
static int singleOptionUsage(FILE * fp, int cursor,
 
525
                const struct poptOption * opt,
 
526
                /*@null@*/ const char *translation_domain)
 
527
        /*@globals fileSystem @*/
 
528
        /*@modifies *fp, fileSystem @*/
 
529
{
 
530
    int len = 4;
 
531
    char shortStr[2] = { '\0', '\0' };
 
532
    const char * item = shortStr;
 
533
    const char * argDescrip = getArgDescrip(opt, translation_domain);
 
534
 
 
535
    if (opt->shortName != '\0' && opt->longName != NULL) {
 
536
        len += 2;
 
537
        if (!(opt->argInfo & POPT_ARGFLAG_ONEDASH)) len++;
 
538
        len += strlen(opt->longName);
 
539
    } else if (opt->shortName != '\0') {
 
540
        len++;
 
541
        shortStr[0] = opt->shortName;
 
542
        shortStr[1] = '\0';
 
543
    } else if (opt->longName) {
 
544
        len += strlen(opt->longName);
 
545
        if (!(opt->argInfo & POPT_ARGFLAG_ONEDASH)) len++;
 
546
        item = opt->longName;
 
547
    }
 
548
 
 
549
    if (len == 4) return cursor;
 
550
 
 
551
    if (argDescrip) 
 
552
        len += strlen(argDescrip) + 1;
 
553
 
 
554
    if ((cursor + len) > 79) {
 
555
        fprintf(fp, "\n       ");
 
556
        cursor = 7;
 
557
    } 
 
558
 
 
559
    if (opt->longName && opt->shortName) {
 
560
        fprintf(fp, " [-%c|-%s%s%s%s]",
 
561
            opt->shortName, ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "" : "-"),
 
562
            opt->longName,
 
563
            (argDescrip ? " " : ""),
 
564
            (argDescrip ? argDescrip : ""));
 
565
    } else {
 
566
        fprintf(fp, " [-%s%s%s%s]",
 
567
            ((opt->shortName || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) ? "" : "-"),
 
568
            item,
 
569
            (argDescrip ? (opt->shortName != '\0' ? " " : "=") : ""),
 
570
            (argDescrip ? argDescrip : ""));
 
571
    }
 
572
 
 
573
    return cursor + len + 1;
 
574
}
 
575
 
 
576
/**
 
577
 * Display popt alias and exec usage.
 
578
 * @param fp            output file handle
 
579
 * @param cursor
 
580
 * @param item          alias/exec array
 
581
 * @param nitems        no. of ara/exec entries
 
582
 * @param translation_domain    translation domain
 
583
 */
 
584
static int itemUsage(FILE * fp, int cursor, poptItem item, int nitems,
 
585
                /*@null@*/ const char * translation_domain)
 
586
        /*@globals fileSystem @*/
 
587
        /*@modifies *fp, fileSystem @*/
 
588
{
 
589
    int i;
 
590
 
 
591
    /*@-branchstate@*/          /* FIX: W2DO? */
 
592
    if (item != NULL)
 
593
    for (i = 0; i < nitems; i++, item++) {
 
594
        const struct poptOption * opt;
 
595
        opt = &item->option;
 
596
        if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INTL_DOMAIN) {
 
597
            translation_domain = (const char *)opt->arg;
 
598
        } else if ((opt->longName || opt->shortName) &&
 
599
                 !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) {
 
600
            cursor = singleOptionUsage(fp, cursor, opt, translation_domain);
 
601
        }
 
602
    }
 
603
    /*@=branchstate@*/
 
604
 
 
605
    return cursor;
 
606
}
 
607
 
 
608
/**
 
609
 * Keep track of option tables already processed.
 
610
 */
 
611
typedef struct poptDone_s {
 
612
    int nopts;
 
613
    int maxopts;
 
614
    const void ** opts;
 
615
} * poptDone;
 
616
 
 
617
/**
 
618
 * Display usage text for a table of options.
 
619
 * @param con           context
 
620
 * @param fp            output file handle
 
621
 * @param cursor
 
622
 * @param opt           option(s)
 
623
 * @param translation_domain    translation domain
 
624
 * @param done          tables already processed
 
625
 * @return
 
626
 */
 
627
static int singleTableUsage(poptContext con, FILE * fp, int cursor,
 
628
                /*@null@*/ const struct poptOption * opt,
 
629
                /*@null@*/ const char * translation_domain,
 
630
                /*@null@*/ poptDone done)
 
631
        /*@globals fileSystem @*/
 
632
        /*@modifies *fp, done, fileSystem @*/
 
633
{
 
634
    /*@-branchstate@*/          /* FIX: W2DO? */
 
635
    if (opt != NULL)
 
636
    for (; (opt->longName || opt->shortName || opt->arg) ; opt++) {
 
637
        if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INTL_DOMAIN) {
 
638
            translation_domain = (const char *)opt->arg;
 
639
        } else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
 
640
            if (done) {
 
641
                int i = 0;
 
642
                for (i = 0; i < done->nopts; i++) {
 
643
/*@-boundsread@*/
 
644
                    const void * that = done->opts[i];
 
645
/*@=boundsread@*/
 
646
                    if (that == NULL || that != opt->arg)
 
647
                        /*@innercontinue@*/ continue;
 
648
                    /*@innerbreak@*/ break;
 
649
                }
 
650
                /* Skip if this table has already been processed. */
 
651
                if (opt->arg == NULL || i < done->nopts)
 
652
                    continue;
 
653
/*@-boundswrite@*/
 
654
                if (done->nopts < done->maxopts)
 
655
                    done->opts[done->nopts++] = (const void *) opt->arg;
 
656
/*@=boundswrite@*/
 
657
            }
 
658
            cursor = singleTableUsage(con, fp, cursor, (const struct poptOption *)opt->arg,
 
659
                        translation_domain, done);
 
660
        } else if ((opt->longName || opt->shortName) &&
 
661
                 !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) {
 
662
            cursor = singleOptionUsage(fp, cursor, opt, translation_domain);
 
663
        }
 
664
    }
 
665
    /*@=branchstate@*/
 
666
 
 
667
    return cursor;
 
668
}
 
669
 
 
670
/**
 
671
 * Return concatenated short options for display.
 
672
 * @todo Sub-tables should be recursed.
 
673
 * @param opt           option(s)
 
674
 * @param fp            output file handle
 
675
 * @retval str          concatenation of short options
 
676
 * @return              length of display string
 
677
 */
 
678
static int showShortOptions(const struct poptOption * opt, FILE * fp,
 
679
                /*@null@*/ char * str)
 
680
        /*@globals fileSystem @*/
 
681
        /*@modifies *str, *fp, fileSystem @*/
 
682
        /*@requires maxRead(str) >= 0 @*/
 
683
{
 
684
    /* bufsize larger then the ascii set, lazy alloca on top level call. */
 
685
    char * s = (str != NULL ? str : (char *)memset(alloca(300), 0, 300));
 
686
    int len = 0;
 
687
 
 
688
/*@-boundswrite@*/
 
689
    if (opt != NULL)
 
690
    for (; (opt->longName || opt->shortName || opt->arg); opt++) {
 
691
        if (opt->shortName && !(opt->argInfo & POPT_ARG_MASK))
 
692
            s[strlen(s)] = opt->shortName;
 
693
        else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE)
 
694
            if (opt->arg)       /* XXX program error */
 
695
                len = showShortOptions(
 
696
                    (const struct poptOption *)opt->arg, fp, s);
 
697
    } 
 
698
/*@=boundswrite@*/
 
699
 
 
700
    /* On return to top level, print the short options, return print length. */
 
701
    if (s == str && *s != '\0') {
 
702
        fprintf(fp, " [-%s]", s);
 
703
        len = strlen(s) + sizeof(" [-]")-1;
 
704
    }
 
705
    return len;
 
706
}
 
707
 
 
708
void poptPrintUsage(poptContext con, FILE * fp, /*@unused@*/ int flags)
 
709
{
 
710
    poptDone done = (poptDone)memset(alloca(sizeof(*done)), 0, sizeof(*done));
 
711
    int cursor;
 
712
 
 
713
    done->nopts = 0;
 
714
    done->maxopts = 64;
 
715
    cursor = done->maxopts * sizeof(*done->opts);
 
716
/*@-boundswrite@*/
 
717
    done->opts = (const void **)memset(alloca(cursor), 0, cursor);
 
718
    done->opts[done->nopts++] = (const void *) con->options;
 
719
/*@=boundswrite@*/
 
720
 
 
721
    cursor = showHelpIntro(con, fp);
 
722
    cursor += showShortOptions(con->options, fp, NULL);
 
723
    cursor = singleTableUsage(con, fp, cursor, con->options, NULL, done);
 
724
    cursor = itemUsage(fp, cursor, con->aliases, con->numAliases, NULL);
 
725
    cursor = itemUsage(fp, cursor, con->execs, con->numExecs, NULL);
 
726
 
 
727
    if (con->otherHelp) {
 
728
        cursor += strlen(con->otherHelp) + 1;
 
729
        if (cursor > 79) fprintf(fp, "\n       ");
 
730
        fprintf(fp, " %s", con->otherHelp);
 
731
    }
 
732
 
 
733
    fprintf(fp, "\n");
 
734
}
 
735
 
 
736
void poptSetOtherOptionHelp(poptContext con, const char * text)
 
737
{
 
738
    con->otherHelp = (const char *)_free(con->otherHelp);
 
739
    con->otherHelp = xstrdup(text);
 
740
}
 
741
/*@=type@*/