~ubuntu-branches/ubuntu/lucid/popt/lucid

« back to all changes in this revision

Viewing changes to popthelp.c

  • Committer: Bazaar Package Importer
  • Author(s): Paul Martin
  • Date: 2004-08-29 16:36:43 UTC
  • mfrom: (2.1.1 warty)
  • Revision ID: james.westby@ubuntu.com-20040829163643-rirf1ycw80g3000b
Tags: 1.7-5
* The "I hate automake" release.
* Make sure configure.in and configure.ac are the same, including
  timestamp. This allows a compile if you have two different versions of
  automake installed. (Closes: #245819)
* Standards-Version: 3.6.1

Show diffs side-by-side

added added

removed removed

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