Doc.
[rsync/rsync.git] / popt-1.2 / popthelp.c
CommitLineData
62402cb1
MP
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#include <ctype.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13
14#include "popt.h"
15#include "poptint.h"
16
17static 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);
22 else
23 poptPrintUsage(con, stderr, 0);
24 exit(0);
25}
26
27struct 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 }
32} ;
33
34static const char * getArgDescrip(const struct poptOption * opt) {
35 if (!(opt->argInfo & POPT_ARG_MASK)) return NULL;
36
37 if (opt == (poptHelpOptions + 1) || opt == (poptHelpOptions + 2))
38 if (opt->argDescrip) return POPT_(opt->argDescrip);
39
40 if (opt->argDescrip) return _(opt->argDescrip);
41 return POPT_("ARG");
42}
43
44static 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);
49 int helpLength;
50 const char * ch;
51 char format[10];
52 char * left = alloca(maxLeftCol + 1);
53 const char * argDescrip = getArgDescrip(opt);
54
55 *left = '\0';
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);
62 if (!*left) return ;
63 if (argDescrip) {
64 strcat(left, "=");
65 strcat(left, argDescrip);
66 }
67
68 if (help)
69 fprintf(f," %-*s ", maxLeftCol, left);
70 else {
71 fprintf(f," %s\n", left);
72 return;
73 }
74
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--;
81 ch++;
82
83 sprintf(format, "%%.%ds\n%%%ds", (int) (ch - help), indentLength);
84 fprintf(f, format, help, " ");
85 help = ch;
86 while (isspace(*help) && *help) help++;
87 helpLength = strlen(help);
88 }
89
90 if (helpLength) fprintf(f, "%s\n", help);
91}
92
93static int maxArgWidth(const struct poptOption * opt) {
94 int max = 0;
95 int this;
96 const char * s;
97
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;
104 if (opt->longName) {
105 if (this) this += 2;
106 this += strlen(opt->longName) + 2;
107 }
108
109 s = getArgDescrip(opt);
110 if (s)
111 this += strlen(s) + 1;
112 if (this > max) max = this;
113 }
114
115 opt++;
116 }
117
118 return max;
119}
120
121static void singleTableHelp(FILE * f, const struct poptOption * table,
122 int left) {
123 const struct poptOption * opt;
124
125 opt = table;
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);
130 opt++;
131 }
132
133 opt = table;
134 while (opt->longName || opt->shortName || opt->arg) {
135 if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
136 if (opt->descrip)
137 fprintf(f, "\n%s\n", _(opt->descrip));
138 singleTableHelp(f, opt->arg, left);
139 }
140 opt++;
141 }
142}
143
144static int showHelpIntro(poptContext con, FILE * f) {
145 int len = 6;
146 char * fn;
147
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;
154 }
155
156 return len;
157}
158
159void poptPrintHelp(poptContext con, FILE * f, int flags) {
160 int leftColWidth;
161
162 showHelpIntro(con, f);
163 if (con->otherHelp)
164 fprintf(f, " %s\n", con->otherHelp);
165 else
166 fprintf(f, " %s\n", POPT_("[OPTION...]"));
167
168 leftColWidth = maxArgWidth(con->options);
169 singleTableHelp(f, con->options, leftColWidth);
170}
171
172static int singleOptionUsage(FILE * f, int cursor,
173 const struct poptOption * opt) {
174 int len = 3;
175 char shortStr[2];
176 const char * item = shortStr;
177 const char * argDescrip = getArgDescrip(opt);
178
179 if (opt->shortName) {
180 if (!(opt->argInfo & POPT_ARG_MASK))
181 return cursor; /* we did these already */
182 len++;
183 *shortStr = opt->shortName;
184 shortStr[1] = '\0';
185 } else if (opt->longName) {
186 len += 1 + strlen(opt->longName);
187 item = opt->longName;
188 }
189
190 if (len == 3) return cursor;
191
192 if (argDescrip)
193 len += strlen(argDescrip) + 1;
194
195 if ((cursor + len) > 79) {
196 fprintf(f, "\n ");
197 cursor = 7;
198 }
199
200 fprintf(f, " [-%s%s%s%s]", opt->shortName ? "" : "-", item,
201 argDescrip ? (opt->shortName ? " " : "=") : "",
202 argDescrip ? argDescrip : "");
203
204 return cursor + len + 1;
205}
206
207int singleTableUsage(FILE * f, int cursor, const struct poptOption * table) {
208 const struct poptOption * opt;
209
210 opt = table;
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);
217 opt++;
218 }
219
220 return cursor;
221}
222
223static int showShortOptions(const struct poptOption * opt, FILE * f,
224 char * str) {
225 char s[300]; /* this is larger then the ascii set, so
226 it should do just fine */
227
228 if (!str) {
229 str = s;
230 memset(str, 0, sizeof(str));
231 }
232
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);
238
239 opt++;
240 }
241
242 if (s != str || !*s)
243 return 0;
244
245 fprintf(f, " [-%s]", s);
246 return strlen(s) + 4;
247}
248
249void poptPrintUsage(poptContext con, FILE * f, int flags) {
250 int cursor;
251
252 cursor = showHelpIntro(con, f);
253 cursor += showShortOptions(con->options, f, NULL);
254 singleTableUsage(f, cursor, con->options);
255
256 if (con->otherHelp) {
257 cursor += strlen(con->otherHelp) + 1;
258 if (cursor > 79) fprintf(f, "\n ");
259 fprintf(f, " %s", con->otherHelp);
260 }
261
262 fprintf(f, "\n");
263}
264
265void poptSetOtherOptionHelp(poptContext con, const char * text) {
266 if (con->otherHelp) free(con->otherHelp);
267 con->otherHelp = strdup(text);
268}