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 */
17 static void displayArgs(poptContext con, enum poptCallbackReason foo,
18 struct poptOption * key,
19 const char * arg, void * data) {
20 if (key->shortName== '?')
21 poptPrintHelp(con, stderr, 0);
23 poptPrintUsage(con, stderr, 0);
27 struct poptOption poptHelpOptions[] = {
28 { NULL, '\0', POPT_ARG_CALLBACK, &displayArgs, '\0', NULL },
29 { "help", '?', 0, NULL, '?', N_("Show this help message") },
30 { "usage", '\0', 0, NULL, 'u', N_("Display brief usage message") },
31 { NULL, '\0', 0, NULL, 0 }
34 static const char * getArgDescrip(const struct poptOption * opt) {
35 if (!(opt->argInfo & POPT_ARG_MASK)) return NULL;
37 if (opt == (poptHelpOptions + 1) || opt == (poptHelpOptions + 2))
38 if (opt->argDescrip) return POPT_(opt->argDescrip);
40 if (opt->argDescrip) return _(opt->argDescrip);
44 static void singleOptionHelp(FILE * f, int maxLeftCol,
45 const struct poptOption * opt) {
46 int indentLength = maxLeftCol + 5;
47 int lineLength = 79 - indentLength;
48 const char * help = _(opt->descrip);
52 char * left = alloca(maxLeftCol + 1);
53 const char * argDescrip = getArgDescrip(opt);
56 if (opt->longName && opt->shortName)
57 sprintf(left, "-%c, --%s", opt->shortName, opt->longName);
58 else if (opt->shortName)
59 sprintf(left, "-%c", opt->shortName);
60 else if (opt->longName)
61 sprintf(left, "--%s", opt->longName);
65 strcat(left, argDescrip);
69 fprintf(f," %-*s ", maxLeftCol, left);
71 fprintf(f," %s\n", left);
75 helpLength = strlen(help);
76 while (helpLength > lineLength) {
77 ch = help + lineLength - 1;
78 while (ch > help && !isspace(*ch)) ch--;
79 if (ch == help) break; /* give up */
80 while (ch > (help + 1) && isspace(*ch)) ch--;
83 sprintf(format, "%%.%ds\n%%%ds", (int) (ch - help), indentLength);
84 fprintf(f, format, help, " ");
86 while (isspace(*help) && *help) help++;
87 helpLength = strlen(help);
90 if (helpLength) fprintf(f, "%s\n", help);
93 static int maxArgWidth(const struct poptOption * opt) {
98 while (opt->longName || opt->shortName || opt->arg) {
99 if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
100 this = maxArgWidth(opt->arg);
101 if (this > max) max = this;
102 } else if (!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) {
103 this = opt->shortName ? 2 : 0;
106 this += strlen(opt->longName) + 2;
109 s = getArgDescrip(opt);
111 this += strlen(s) + 1;
112 if (this > max) max = this;
121 static void singleTableHelp(FILE * f, const struct poptOption * table,
123 const struct poptOption * opt;
126 while (opt->longName || opt->shortName || opt->arg) {
127 if ((opt->longName || opt->shortName) &&
128 !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN))
129 singleOptionHelp(f, left, opt);
134 while (opt->longName || opt->shortName || opt->arg) {
135 if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
137 fprintf(f, "\n%s\n", _(opt->descrip));
138 singleTableHelp(f, opt->arg, left);
144 static int showHelpIntro(poptContext con, FILE * f) {
148 fprintf(f, POPT_("Usage:"));
149 if (!(con->flags & POPT_CONTEXT_KEEP_FIRST)) {
150 fn = con->optionStack->argv[0];
151 if (strchr(fn, '/')) fn = strchr(fn, '/') + 1;
152 fprintf(f, " %s", fn);
153 len += strlen(fn) + 1;
159 void poptPrintHelp(poptContext con, FILE * f, int flags) {
162 showHelpIntro(con, f);
164 fprintf(f, " %s\n", con->otherHelp);
166 fprintf(f, " %s\n", POPT_("[OPTION...]"));
168 leftColWidth = maxArgWidth(con->options);
169 singleTableHelp(f, con->options, leftColWidth);
172 static int singleOptionUsage(FILE * f, int cursor,
173 const struct poptOption * opt) {
176 const char * item = shortStr;
177 const char * argDescrip = getArgDescrip(opt);
179 if (opt->shortName) {
180 if (!(opt->argInfo & POPT_ARG_MASK))
181 return cursor; /* we did these already */
183 *shortStr = opt->shortName;
185 } else if (opt->longName) {
186 len += 1 + strlen(opt->longName);
187 item = opt->longName;
190 if (len == 3) return cursor;
193 len += strlen(argDescrip) + 1;
195 if ((cursor + len) > 79) {
200 fprintf(f, " [-%s%s%s%s]", opt->shortName ? "" : "-", item,
201 argDescrip ? (opt->shortName ? " " : "=") : "",
202 argDescrip ? argDescrip : "");
204 return cursor + len + 1;
207 int singleTableUsage(FILE * f, int cursor, const struct poptOption * table) {
208 const struct poptOption * opt;
211 while (opt->longName || opt->shortName || opt->arg) {
212 if ((opt->longName || opt->shortName) &&
213 !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN))
214 cursor = singleOptionUsage(f, cursor, opt);
215 else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE)
216 cursor = singleTableUsage(f, cursor, opt->arg);
223 static int showShortOptions(const struct poptOption * opt, FILE * f,
225 char s[300]; /* this is larger then the ascii set, so
226 it should do just fine */
230 memset(str, 0, sizeof(str));
233 while (opt->longName || opt->shortName || opt->arg) {
234 if (opt->shortName && !(opt->argInfo & POPT_ARG_MASK))
235 str[strlen(str)] = opt->shortName;
236 else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE)
237 showShortOptions(opt->arg, f, str);
245 fprintf(f, " [-%s]", s);
246 return strlen(s) + 4;
249 void poptPrintUsage(poptContext con, FILE * f, int flags) {
252 cursor = showHelpIntro(con, f);
253 cursor += showShortOptions(con->options, f, NULL);
254 singleTableUsage(f, cursor, con->options);
256 if (con->otherHelp) {
257 cursor += strlen(con->otherHelp) + 1;
258 if (cursor > 79) fprintf(f, "\n ");
259 fprintf(f, " %s", con->otherHelp);
265 void poptSetOtherOptionHelp(poptContext con, const char * text) {
266 if (con->otherHelp) free(con->otherHelp);
267 con->otherHelp = strdup(text);