1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
3 /* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
4 file accompanying popt source distributions, available from
5 ftp://ftp.redhat.com/pub/code/popt */
19 static void displayArgs(poptContext con
, enum poptCallbackReason foo
,
20 struct poptOption
* key
,
21 const char * arg
, void * data
) {
22 if (key
->shortName
== '?')
23 poptPrintHelp(con
, stdout
, 0);
25 poptPrintUsage(con
, stdout
, 0);
29 struct poptOption
const poptHelpOptions
[] = {
30 { NULL
, '\0', POPT_ARG_CALLBACK
, (void *)&displayArgs
, '\0', NULL
},
31 { "help", '?', 0, NULL
, '?', N_("Show this help message") },
32 { "usage", '\0', 0, NULL
, 'u', N_("Display brief usage message") },
33 { NULL
, '\0', 0, NULL
, 0 }
38 getTableTranslationDomain(const struct poptOption
*table
)
40 const struct poptOption
*opt
;
43 opt
->longName
|| opt
->shortName
|| opt
->arg
;
45 if(opt
->argInfo
== POPT_ARG_INTL_DOMAIN
)
52 static const char * getArgDescrip(const struct poptOption
* opt
,
53 const char *translation_domain
) {
54 if (!(opt
->argInfo
& POPT_ARG_MASK
)) return NULL
;
56 if (opt
== (poptHelpOptions
+ 1) || opt
== (poptHelpOptions
+ 2))
57 if (opt
->argDescrip
) return POPT_(opt
->argDescrip
);
59 if (opt
->argDescrip
) return D_(translation_domain
, opt
->argDescrip
);
63 static void singleOptionHelp(FILE * f
, int maxLeftCol
,
64 const struct poptOption
* opt
,
65 const char *translation_domain
) {
66 int indentLength
= maxLeftCol
+ 5;
67 int lineLength
= 79 - indentLength
;
68 const unsigned char * help
= D_(translation_domain
, opt
->descrip
);
70 const unsigned char * ch
;
72 const char * argDescrip
= getArgDescrip(opt
, translation_domain
);
74 left
= malloc(maxLeftCol
+ 1);
77 if (opt
->longName
&& opt
->shortName
)
78 sprintf(left
, "-%c, --%s", opt
->shortName
, opt
->longName
);
79 else if (opt
->shortName
)
80 sprintf(left
, "-%c", opt
->shortName
);
81 else if (opt
->longName
)
82 sprintf(left
, "--%s", opt
->longName
);
86 strcat(left
, argDescrip
);
90 fprintf(f
," %-*s ", maxLeftCol
, left
);
92 fprintf(f
," %s\n", left
);
96 helpLength
= strlen(help
);
97 while (helpLength
> lineLength
) {
98 ch
= help
+ lineLength
- 1;
99 while (ch
> help
&& !isspace(*ch
)) ch
--;
100 if (ch
== help
) break; /* give up */
101 while (ch
> (help
+ 1) && isspace(*ch
)) ch
--;
104 fprintf(f
, "%.*s\n%*s", (int) (ch
- help
), help
, indentLength
, " ");
106 while (isspace(*help
) && *help
) help
++;
107 helpLength
= strlen(help
);
110 if (helpLength
) fprintf(f
, "%s\n", help
);
116 static int maxArgWidth(const struct poptOption
* opt
,
117 const char * translation_domain
) {
122 while (opt
->longName
|| opt
->shortName
|| opt
->arg
) {
123 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INCLUDE_TABLE
) {
124 this = maxArgWidth(opt
->arg
, translation_domain
);
125 if (this > max
) max
= this;
126 } else if (!(opt
->argInfo
& POPT_ARGFLAG_DOC_HIDDEN
)) {
127 this = opt
->shortName
? 2 : 0;
130 this += strlen(opt
->longName
) + 2;
133 s
= getArgDescrip(opt
, translation_domain
);
135 this += strlen(s
) + 1;
136 if (this > max
) max
= this;
145 static void singleTableHelp(FILE * f
, const struct poptOption
* table
,
147 const char *translation_domain
) {
148 const struct poptOption
* opt
;
149 const char *sub_transdom
;
152 while (opt
->longName
|| opt
->shortName
|| opt
->arg
) {
153 if ((opt
->longName
|| opt
->shortName
) &&
154 !(opt
->argInfo
& POPT_ARGFLAG_DOC_HIDDEN
))
155 singleOptionHelp(f
, left
, opt
, translation_domain
);
160 while (opt
->longName
|| opt
->shortName
|| opt
->arg
) {
161 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INCLUDE_TABLE
) {
162 sub_transdom
= getTableTranslationDomain(opt
->arg
);
164 sub_transdom
= translation_domain
;
167 fprintf(f
, "\n%s\n", D_(sub_transdom
, opt
->descrip
));
169 singleTableHelp(f
, opt
->arg
, left
, sub_transdom
);
175 static int showHelpIntro(poptContext con
, FILE * f
) {
179 fprintf(f
, _("Usage:"));
180 if (!(con
->flags
& POPT_CONTEXT_KEEP_FIRST
)) {
181 fn
= con
->optionStack
->argv
[0];
182 if (strchr(fn
, '/')) fn
= strchr(fn
, '/') + 1;
183 fprintf(f
, " %s", fn
);
184 len
+= strlen(fn
) + 1;
190 int poptPrintHelp(poptContext con
, FILE * f
, int flags
) {
193 showHelpIntro(con
, f
);
195 fprintf(f
, " %s\n", con
->otherHelp
);
197 fprintf(f
, " %s\n", POPT_("[OPTION...]"));
199 leftColWidth
= maxArgWidth(con
->options
, NULL
);
200 singleTableHelp(f
, con
->options
, leftColWidth
, NULL
);
204 static int singleOptionUsage(FILE * f
, int cursor
,
205 const struct poptOption
* opt
,
206 const char *translation_domain
) {
209 const char * item
= shortStr
;
210 const char * argDescrip
= getArgDescrip(opt
, translation_domain
);
212 if (opt
->shortName
) {
213 if (!(opt
->argInfo
& POPT_ARG_MASK
))
214 return cursor
; /* we did these already */
216 *shortStr
= opt
->shortName
;
218 } else if (opt
->longName
) {
219 len
+= 1 + strlen(opt
->longName
);
220 item
= opt
->longName
;
223 if (len
== 3) return cursor
;
226 len
+= strlen(argDescrip
) + 1;
228 if ((cursor
+ len
) > 79) {
233 fprintf(f
, " [-%s%s%s%s]", opt
->shortName
? "" : "-", item
,
234 argDescrip
? (opt
->shortName
? " " : "=") : "",
235 argDescrip
? argDescrip
: "");
237 return cursor
+ len
+ 1;
240 static int singleTableUsage(FILE * f
, int cursor
, const struct poptOption
* table
,
241 const char *translation_domain
) {
242 const struct poptOption
* opt
;
245 while (opt
->longName
|| opt
->shortName
|| opt
->arg
) {
246 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INTL_DOMAIN
)
247 translation_domain
= (const char *)opt
->arg
;
248 else if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INCLUDE_TABLE
)
249 cursor
= singleTableUsage(f
, cursor
, opt
->arg
,
251 else if ((opt
->longName
|| opt
->shortName
) &&
252 !(opt
->argInfo
& POPT_ARGFLAG_DOC_HIDDEN
))
253 cursor
= singleOptionUsage(f
, cursor
, opt
, translation_domain
);
261 static int showShortOptions(const struct poptOption
* opt
, FILE * f
,
263 char s
[300]; /* this is larger then the ascii set, so
264 it should do just fine */
268 memset(str
, 0, sizeof(s
));
271 while (opt
->longName
|| opt
->shortName
|| opt
->arg
) {
272 if (opt
->shortName
&& !(opt
->argInfo
& POPT_ARG_MASK
))
273 str
[strlen(str
)] = opt
->shortName
;
274 else if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INCLUDE_TABLE
)
275 showShortOptions(opt
->arg
, f
, str
);
283 fprintf(f
, " [-%s]", s
);
284 return strlen(s
) + 4;
287 void poptPrintUsage(poptContext con
, FILE * f
, int flags
) {
290 cursor
= showHelpIntro(con
, f
);
291 cursor
+= showShortOptions(con
->options
, f
, NULL
);
292 singleTableUsage(f
, cursor
, con
->options
, NULL
);
294 if (con
->otherHelp
) {
295 cursor
+= strlen(con
->otherHelp
) + 1;
296 if (cursor
> 79) fprintf(f
, "\n ");
297 fprintf(f
, " %s", con
->otherHelp
);
303 void poptSetOtherOptionHelp(poptContext con
, const char * text
) {
304 if (con
->otherHelp
) free(con
->otherHelp
);
305 con
->otherHelp
= strdup(text
);