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 */
10 static void displayArgs(poptContext con
,
11 /*@unused@*/ enum poptCallbackReason foo
,
12 struct poptOption
* key
,
13 /*@unused@*/ const char * arg
, /*@unused@*/ void * data
) {
14 if (key
->shortName
== '?')
15 poptPrintHelp(con
, stdout
, 0);
17 poptPrintUsage(con
, stdout
, 0);
21 struct poptOption poptHelpOptions
[] = {
22 { NULL
, '\0', POPT_ARG_CALLBACK
, (void *)&displayArgs
, '\0', NULL
, NULL
},
23 { "help", '?', 0, NULL
, '?', N_("Show this help message"), NULL
},
24 { "usage", '\0', 0, NULL
, 'u', N_("Display brief usage message"), NULL
},
25 { NULL
, '\0', 0, NULL
, 0, NULL
, NULL
}
29 /*@observer@*/ /*@null@*/ static const char *
30 getTableTranslationDomain(const struct poptOption
*table
)
32 const struct poptOption
*opt
;
35 opt
->longName
|| opt
->shortName
|| opt
->arg
;
37 if(opt
->argInfo
== POPT_ARG_INTL_DOMAIN
)
44 /*@observer@*/ /*@null@*/ static const char *
45 getArgDescrip(const struct poptOption
* opt
, const char *translation_domain
)
47 if (!(opt
->argInfo
& POPT_ARG_MASK
)) return NULL
;
49 if (opt
== (poptHelpOptions
+ 1) || opt
== (poptHelpOptions
+ 2))
50 if (opt
->argDescrip
) return POPT_(opt
->argDescrip
);
52 if (opt
->argDescrip
) return D_(translation_domain
, opt
->argDescrip
);
56 static void singleOptionHelp(FILE * f
, int maxLeftCol
,
57 const struct poptOption
* opt
,
58 const char *translation_domain
) {
59 int indentLength
= maxLeftCol
+ 5;
60 int lineLength
= 79 - indentLength
;
61 const char * help
= D_(translation_domain
, opt
->descrip
);
66 const char * argDescrip
= getArgDescrip(opt
, translation_domain
);
68 left
= malloc(maxLeftCol
+ 1);
71 if (opt
->longName
&& opt
->shortName
)
72 sprintf(left
, "-%c, --%s", opt
->shortName
, opt
->longName
);
73 else if (opt
->shortName
)
74 sprintf(left
, "-%c", opt
->shortName
);
75 else if (opt
->longName
)
76 sprintf(left
, "--%s", opt
->longName
);
80 strcat(left
, argDescrip
);
84 fprintf(f
," %-*s ", maxLeftCol
, left
);
86 fprintf(f
," %s\n", left
);
90 helpLength
= strlen(help
);
91 while (helpLength
> lineLength
) {
92 ch
= help
+ lineLength
- 1;
93 while (ch
> help
&& !isspace(*ch
)) ch
--;
94 if (ch
== help
) break; /* give up */
95 while (ch
> (help
+ 1) && isspace(*ch
)) ch
--;
98 sprintf(format
, "%%.%ds\n%%%ds", (int) (ch
- help
), indentLength
);
99 fprintf(f
, format
, help
, " ");
101 while (isspace(*help
) && *help
) help
++;
102 helpLength
= strlen(help
);
105 if (helpLength
) fprintf(f
, "%s\n", help
);
111 static int maxArgWidth(const struct poptOption
* opt
,
112 const char * translation_domain
) {
117 while (opt
->longName
|| opt
->shortName
|| opt
->arg
) {
118 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INCLUDE_TABLE
) {
119 this = maxArgWidth(opt
->arg
, translation_domain
);
120 if (this > max
) max
= this;
121 } else if (!(opt
->argInfo
& POPT_ARGFLAG_DOC_HIDDEN
)) {
122 this = opt
->shortName
? 2 : 0;
125 this += strlen(opt
->longName
) + 2;
128 s
= getArgDescrip(opt
, translation_domain
);
130 this += strlen(s
) + 1;
131 if (this > max
) max
= this;
140 static void singleTableHelp(FILE * f
, const struct poptOption
* table
,
142 const char *translation_domain
) {
143 const struct poptOption
* opt
;
144 const char *sub_transdom
;
147 while (opt
->longName
|| opt
->shortName
|| opt
->arg
) {
148 if ((opt
->longName
|| opt
->shortName
) &&
149 !(opt
->argInfo
& POPT_ARGFLAG_DOC_HIDDEN
))
150 singleOptionHelp(f
, left
, opt
, translation_domain
);
155 while (opt
->longName
|| opt
->shortName
|| opt
->arg
) {
156 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INCLUDE_TABLE
) {
157 sub_transdom
= getTableTranslationDomain(opt
->arg
);
159 sub_transdom
= translation_domain
;
162 fprintf(f
, "\n%s\n", D_(sub_transdom
, opt
->descrip
));
164 singleTableHelp(f
, opt
->arg
, left
, sub_transdom
);
170 static int showHelpIntro(poptContext con
, FILE * f
) {
174 fprintf(f
, POPT_("Usage:"));
175 if (!(con
->flags
& POPT_CONTEXT_KEEP_FIRST
)) {
176 fn
= con
->optionStack
->argv
[0];
177 if (strchr(fn
, '/')) fn
= strchr(fn
, '/') + 1;
178 fprintf(f
, " %s", fn
);
179 len
+= strlen(fn
) + 1;
185 void poptPrintHelp(poptContext con
, FILE * f
, /*@unused@*/ int flags
) {
188 showHelpIntro(con
, f
);
190 fprintf(f
, " %s\n", con
->otherHelp
);
192 fprintf(f
, " %s\n", POPT_("[OPTION...]"));
194 leftColWidth
= maxArgWidth(con
->options
, NULL
);
195 singleTableHelp(f
, con
->options
, leftColWidth
, NULL
);
198 static int singleOptionUsage(FILE * f
, int cursor
,
199 const struct poptOption
* opt
,
200 const char *translation_domain
) {
202 char shortStr
[2] = { '\0', '\0' };
203 const char * item
= shortStr
;
204 const char * argDescrip
= getArgDescrip(opt
, translation_domain
);
206 if (opt
->shortName
) {
207 if (!(opt
->argInfo
& POPT_ARG_MASK
))
208 return cursor
; /* we did these already */
210 *shortStr
= opt
->shortName
;
212 } else if (opt
->longName
) {
213 len
+= 1 + strlen(opt
->longName
);
214 item
= opt
->longName
;
217 if (len
== 3) return cursor
;
220 len
+= strlen(argDescrip
) + 1;
222 if ((cursor
+ len
) > 79) {
227 fprintf(f
, " [-%s%s%s%s]", opt
->shortName
? "" : "-", item
,
228 argDescrip
? (opt
->shortName
? " " : "=") : "",
229 argDescrip
? argDescrip
: "");
231 return cursor
+ len
+ 1;
234 static int singleTableUsage(FILE * f
, int cursor
, const struct poptOption
* table
,
235 const char *translation_domain
) {
236 const struct poptOption
* opt
;
239 while (opt
->longName
|| opt
->shortName
|| opt
->arg
) {
240 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INTL_DOMAIN
)
241 translation_domain
= (const char *)opt
->arg
;
242 else if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INCLUDE_TABLE
)
243 cursor
= singleTableUsage(f
, cursor
, opt
->arg
,
245 else if ((opt
->longName
|| opt
->shortName
) &&
246 !(opt
->argInfo
& POPT_ARGFLAG_DOC_HIDDEN
))
247 cursor
= singleOptionUsage(f
, cursor
, opt
, translation_domain
);
255 static int showShortOptions(const struct poptOption
* opt
, FILE * f
,
257 char s
[300]; /* this is larger then the ascii set, so
258 it should do just fine */
262 memset(s
, 0, sizeof(s
));
266 while (opt
->longName
|| opt
->shortName
|| opt
->arg
) {
267 if (opt
->shortName
&& !(opt
->argInfo
& POPT_ARG_MASK
))
268 str
[strlen(str
)] = opt
->shortName
;
269 else if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INCLUDE_TABLE
)
270 showShortOptions(opt
->arg
, f
, str
);
278 fprintf(f
, " [-%s]", s
);
279 return strlen(s
) + 4;
282 void poptPrintUsage(poptContext con
, FILE * f
, /*@unused@*/ int flags
) {
285 cursor
= showHelpIntro(con
, f
);
286 cursor
+= showShortOptions(con
->options
, f
, NULL
);
287 singleTableUsage(f
, cursor
, con
->options
, NULL
);
289 if (con
->otherHelp
) {
290 cursor
+= strlen(con
->otherHelp
) + 1;
291 if (cursor
> 79) fprintf(f
, "\n ");
292 fprintf(f
, " %s", con
->otherHelp
);
298 void poptSetOtherOptionHelp(poptContext con
, const char * text
) {
299 if (con
->otherHelp
) xfree(con
->otherHelp
);
300 con
->otherHelp
= xstrdup(text
);