source: trunk/third/pkgconfig/popthelp.c @ 17209

Revision 17209, 6.9 KB checked in by ghudson, 23 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r17208, which included commits to RCS files with non-trunk default branches.
Line 
1/* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
2   file accompanying popt source distributions, available from
3   ftp://ftp.redhat.com/pub/code/popt */
4
5#ifdef HAVE_CONFIG_H
6#include "config.h"
7#endif
8
9#ifdef HAVE_ALLOCA_H
10# include <alloca.h>
11#else
12# ifdef _AIX
13#  pragma alloca
14# endif
15#endif
16
17#include <ctype.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21
22#include "popt.h"
23#include "poptint.h"
24
25#ifdef _WIN32
26#define SLASH '\\'
27#else
28#define SLASH '/'
29#endif
30
31static void displayArgs(poptContext con, enum poptCallbackReason foo,
32                        struct poptOption * key,
33                        const char * arg, void * data) {
34    if (key->shortName== '?')
35        poptPrintHelp(con, stderr, 0);
36    else
37        poptPrintUsage(con, stderr, 0);
38    exit(0);
39}
40
41struct poptOption poptHelpOptions[] = {
42    { NULL, '\0', POPT_ARG_CALLBACK, &displayArgs, '\0', NULL },
43    { "help", '?', 0, NULL, '?', N_("Show this help message") },
44    { "usage", '\0', 0, NULL, 'u', N_("Display brief usage message") },
45    { NULL, '\0', 0, NULL, 0 }
46} ;
47
48static const char * getArgDescrip(const struct poptOption * opt) {
49    if (!(opt->argInfo & POPT_ARG_MASK)) return NULL;
50
51    if (opt == (poptHelpOptions + 1) || opt == (poptHelpOptions + 2))
52        if (opt->argDescrip) return POPT_(opt->argDescrip);
53
54    if (opt->argDescrip) return _(opt->argDescrip);
55    return POPT_("ARG");
56}
57
58static void singleOptionHelp(FILE * f, int maxLeftCol,
59                             const struct poptOption * opt) {
60    int indentLength = maxLeftCol + 5;
61    int lineLength = 79 - indentLength;
62    const char * help = _(opt->descrip);
63    int helpLength;
64    const char * ch;
65    char format[10];
66    char * left = alloca(maxLeftCol + 1);
67    const char * argDescrip = getArgDescrip(opt);
68
69    *left = '\0';
70    if (opt->longName && opt->shortName)
71        sprintf(left, "-%c, --%s", opt->shortName, opt->longName);
72    else if (opt->shortName)
73        sprintf(left, "-%c", opt->shortName);
74    else if (opt->longName)
75        sprintf(left, "--%s", opt->longName);
76    if (!*left) return ;
77    if (argDescrip) {
78        strcat(left, "=");
79        strcat(left, argDescrip);
80    }
81
82    if (help)
83        fprintf(f,"  %-*s   ", maxLeftCol, left);
84    else {
85        fprintf(f,"  %s\n", left);
86        return;
87    }
88
89    helpLength = strlen(help);
90    while (helpLength > lineLength) {
91        ch = help + lineLength - 1;
92        while (ch > help && !isspace(*ch)) ch--;
93        if (ch == help) break;          /* give up */
94        while (ch > (help + 1) && isspace(*ch)) ch--;
95        ch++;
96
97        sprintf(format, "%%.%ds\n%%%ds", (int) (ch - help), indentLength);
98        fprintf(f, format, help, " ");
99        help = ch;
100        while (isspace(*help) && *help) help++;
101        helpLength = strlen(help);
102    }
103
104    if (helpLength) fprintf(f, "%s\n", help);
105}
106
107static int maxArgWidth(const struct poptOption * opt) {
108    int max = 0;
109    int this;
110    const char * s;
111   
112    while (opt->longName || opt->shortName || opt->arg) {
113        if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
114            this = maxArgWidth(opt->arg);
115            if (this > max) max = this;
116        } else if (!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) {
117            this = opt->shortName ? 2 : 0;
118            if (opt->longName) {
119                if (this) this += 2;
120                this += strlen(opt->longName) + 2;
121            }
122
123            s = getArgDescrip(opt);
124            if (s)
125                this += strlen(s) + 1;
126            if (this > max) max = this;
127        }
128
129        opt++;
130    }
131   
132    return max;
133}
134
135static void singleTableHelp(FILE * f, const struct poptOption * table,
136                            int left) {
137    const struct poptOption * opt;
138
139    opt = table;
140    while (opt->longName || opt->shortName || opt->arg) {
141        if ((opt->longName || opt->shortName) &&
142            !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN))
143            singleOptionHelp(f, left, opt);
144        opt++;
145    }
146
147    opt = table;
148    while (opt->longName || opt->shortName || opt->arg) {
149        if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
150            if (opt->descrip)
151                fprintf(f, "\n%s\n", _(opt->descrip));
152            singleTableHelp(f, opt->arg, left);
153        }
154        opt++;
155    }
156}
157
158static int showHelpIntro(poptContext con, FILE * f) {
159    int len = 6;
160    char * fn;
161
162    fprintf(f, POPT_("Usage:"));
163    if (!(con->flags & POPT_CONTEXT_KEEP_FIRST)) {
164        fn = con->optionStack->argv[0];
165        if (strchr(fn, SLASH)) fn = strchr(fn, SLASH) + 1;
166        fprintf(f, " %s", fn);
167        len += strlen(fn) + 1;
168    }
169
170    return len;
171}
172
173void poptPrintHelp(poptContext con, FILE * f, int flags) {
174    int leftColWidth;
175
176    showHelpIntro(con, f);
177    if (con->otherHelp)
178        fprintf(f, " %s\n", con->otherHelp);
179    else
180        fprintf(f, " %s\n", POPT_("[OPTION...]"));
181
182    leftColWidth = maxArgWidth(con->options);
183    singleTableHelp(f, con->options, leftColWidth);
184}
185
186static int singleOptionUsage(FILE * f, int cursor,
187                              const struct poptOption * opt) {
188    int len = 3;
189    char shortStr[2];
190    const char * item = shortStr;
191    const char * argDescrip = getArgDescrip(opt);
192
193    if (opt->shortName) {
194        if (!(opt->argInfo & POPT_ARG_MASK))
195            return cursor;      /* we did these already */
196        len++;
197        *shortStr = opt->shortName;
198        shortStr[1] = '\0';
199    } else if (opt->longName) {
200        len += 1 + strlen(opt->longName);
201        item = opt->longName;
202    }
203
204    if (len == 3) return cursor;
205
206    if (argDescrip)
207        len += strlen(argDescrip) + 1;
208
209    if ((cursor + len) > 79) {
210        fprintf(f, "\n       ");
211        cursor = 7;
212    }
213
214    fprintf(f, " [-%s%s%s%s]", opt->shortName ? "" : "-", item,
215            argDescrip ? (opt->shortName ? " " : "=") : "",
216            argDescrip ? argDescrip : "");
217
218    return cursor + len + 1;
219}
220
221int singleTableUsage(FILE * f, int cursor, const struct poptOption * table) {
222    const struct poptOption * opt;
223   
224    opt = table;
225    while (opt->longName || opt->shortName || opt->arg) {
226        if ((opt->longName || opt->shortName) &&
227            !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN))
228            cursor = singleOptionUsage(f, cursor, opt);
229        else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE)
230            cursor = singleTableUsage(f, cursor, opt->arg);
231        opt++;
232    }
233
234    return cursor;
235}
236
237static int showShortOptions(const struct poptOption * opt, FILE * f,
238                            char * str) {
239    char s[300];                /* this is larger then the ascii set, so
240                                   it should do just fine */
241
242    if (!str) {
243        str = s;
244        memset(str, 0, sizeof(str));
245    }
246
247    while (opt->longName || opt->shortName || opt->arg) {
248        if (opt->shortName && !(opt->argInfo & POPT_ARG_MASK))
249            str[strlen(str)] = opt->shortName;
250        else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE)
251            showShortOptions(opt->arg, f, str);
252
253        opt++;
254    }
255
256    if (s != str || !*s)
257        return 0;
258
259    fprintf(f, " [-%s]", s);
260    return strlen(s) + 4;
261}
262
263void poptPrintUsage(poptContext con, FILE * f, int flags) {
264    int cursor;
265
266    cursor = showHelpIntro(con, f);
267    cursor += showShortOptions(con->options, f, NULL);
268    singleTableUsage(f, cursor, con->options);
269
270    if (con->otherHelp) {
271        cursor += strlen(con->otherHelp) + 1;
272        if (cursor > 79) fprintf(f, "\n       ");
273        fprintf(f, " %s", con->otherHelp);
274    }
275
276    fprintf(f, "\n");
277}
278
279void poptSetOtherOptionHelp(poptContext con, const char * text) {
280    if (con->otherHelp) free(con->otherHelp);
281    con->otherHelp = strdup(text);
282}
Note: See TracBrowser for help on using the repository browser.