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 */
8 * \brief Source: popt helper module
24 static void displayArgs(poptContext con
, enum poptCallbackReason foo
,
25 struct poptOption
* key
,
26 const char * arg
, void * data
)
32 if (key
->shortName
== '?')
33 poptPrintHelp(con
, stdout
, 0);
35 poptPrintUsage(con
, stdout
, 0);
42 getTableTranslationDomain(const struct poptOption
*table
)
44 const struct poptOption
*opt
;
47 opt
->longName
|| opt
->shortName
|| opt
->arg
.p
;
49 if(opt
->argInfo
== POPT_ARG_INTL_DOMAIN
)
56 static const char * getArgDescrip(const struct poptOption
* opt
,
57 const char *translation_domain
) {
58 struct poptOption
*poptHelpOptions
;
60 (void) translation_domain
;
62 poptHelpOptions
= g_malloc(sizeof(struct poptOption
)*4);
64 poptHelpOptions
[0].longName
= NULL
;
65 poptHelpOptions
[0].shortName
= '\0';
66 poptHelpOptions
[0].argInfo
= POPT_ARG_CALLBACK
;
67 poptHelpOptions
[0].arg
.f1
= &displayArgs
;
68 poptHelpOptions
[0].val
= '\0';
69 poptHelpOptions
[0].descrip
= NULL
;
70 poptHelpOptions
[0].argDescrip
= NULL
;
72 poptHelpOptions
[1].longName
= "help";
73 poptHelpOptions
[1].shortName
= '?';
74 poptHelpOptions
[1].argInfo
= 0;
75 poptHelpOptions
[1].arg
.p
= NULL
;
76 poptHelpOptions
[1].val
= '?';
77 poptHelpOptions
[1].descrip
= _("Show this help message");
78 poptHelpOptions
[1].argDescrip
= NULL
;
80 poptHelpOptions
[2].longName
= "usage";
81 poptHelpOptions
[2].shortName
= '\0';
82 poptHelpOptions
[2].argInfo
= 0;
83 poptHelpOptions
[2].arg
.p
= NULL
;
84 poptHelpOptions
[2].val
= 'u';
85 poptHelpOptions
[2].descrip
= _("Display brief usage message");
86 poptHelpOptions
[2].argDescrip
= NULL
;
88 poptHelpOptions
[3].longName
= NULL
;
89 poptHelpOptions
[3].shortName
= '\0';
90 poptHelpOptions
[3].argInfo
= 0;
91 poptHelpOptions
[3].arg
.p
= NULL
;
92 poptHelpOptions
[3].val
= 0;
93 poptHelpOptions
[3].descrip
= NULL
;
94 poptHelpOptions
[3].argDescrip
= NULL
;
96 if (!(opt
->argInfo
& POPT_ARG_MASK
)){
97 g_free(poptHelpOptions
);
101 if (opt
== (poptHelpOptions
+ 1) || opt
== (poptHelpOptions
+ 2))
104 g_free(poptHelpOptions
);
105 return POPT_(opt
->argDescrip
);
110 g_free(poptHelpOptions
);
111 return D_(translation_domain
, opt
->argDescrip
);
113 g_free(poptHelpOptions
);
117 static void singleOptionHelp(FILE * f
, int maxLeftCol
,
118 const struct poptOption
* opt
,
119 const char *translation_domain
) {
120 int indentLength
= maxLeftCol
+ 5;
121 int lineLength
= 79 - indentLength
;
122 const char * help
= D_(translation_domain
, opt
->descrip
);
126 const char * argDescrip
= getArgDescrip(opt
, translation_domain
);
128 left
= malloc(maxLeftCol
+ 1);
131 if (opt
->longName
&& opt
->shortName
)
132 sprintf(left
, "-%c, --%s", opt
->shortName
, opt
->longName
);
133 else if (opt
->shortName
)
134 sprintf(left
, "-%c", opt
->shortName
);
135 else if (opt
->longName
)
136 sprintf(left
, "--%s", opt
->longName
);
140 strcat(left
, argDescrip
);
144 fprintf(f
," %-*s ", maxLeftCol
, left
);
146 fprintf(f
," %s\n", left
);
150 helpLength
= strlen(help
);
151 while (helpLength
> lineLength
) {
152 ch
= help
+ lineLength
- 1;
153 while (ch
> help
&& !isspace((unsigned char) *ch
)) ch
--;
154 if (ch
== help
) break; /* give up */
155 while (ch
> (help
+ 1) && isspace((unsigned char) *ch
)) ch
--;
158 fprintf(f
, "%.*s\n%*s", (int) (ch
- help
), help
, indentLength
, " ");
160 while (isspace((unsigned char) *help
) && *help
) help
++;
161 helpLength
= strlen(help
);
164 if (helpLength
) fprintf(f
, "%s\n", help
);
170 static int maxArgWidth(const struct poptOption
* opt
,
171 const char * translation_domain
) {
176 while (opt
->longName
|| opt
->shortName
|| opt
->arg
.p
) {
177 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INCLUDE_TABLE
) {
178 this = maxArgWidth(opt
->arg
.p
, translation_domain
);
179 if (this > max
) max
= this;
180 } else if (!(opt
->argInfo
& POPT_ARGFLAG_DOC_HIDDEN
)) {
181 this = opt
->shortName
? 2 : 0;
184 this += strlen(opt
->longName
) + 2;
187 s
= getArgDescrip(opt
, translation_domain
);
189 this += strlen(s
) + 1;
190 if (this > max
) max
= this;
199 static void singleTableHelp(FILE * f
, const struct poptOption
* table
,
201 const char *translation_domain
) {
202 const struct poptOption
* opt
;
203 const char *sub_transdom
;
206 while (opt
->longName
|| opt
->shortName
|| opt
->arg
.p
) {
207 if ((opt
->longName
|| opt
->shortName
) &&
208 !(opt
->argInfo
& POPT_ARGFLAG_DOC_HIDDEN
))
209 singleOptionHelp(f
, left
, opt
, translation_domain
);
214 while (opt
->longName
|| opt
->shortName
|| opt
->arg
.p
) {
215 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INCLUDE_TABLE
) {
216 sub_transdom
= getTableTranslationDomain(opt
->arg
.p
);
218 sub_transdom
= translation_domain
;
221 fprintf(f
, "\n%s\n", D_(sub_transdom
, opt
->descrip
));
223 singleTableHelp(f
, opt
->arg
.p
, left
, sub_transdom
);
229 static int showHelpIntro(poptContext con
, FILE * f
) {
233 fprintf(f
, _("Usage:"));
234 if (!(con
->flags
& POPT_CONTEXT_KEEP_FIRST
)) {
235 fn
= con
->optionStack
->argv
[0];
236 if (strrchr(fn
, '/')) fn
= strrchr(fn
, '/') + 1;
237 fprintf(f
, " %s", fn
);
238 len
+= strlen(fn
) + 1;
244 int poptPrintHelp(poptContext con
, FILE * f
, int flags
) {
249 showHelpIntro(con
, f
);
251 fprintf(f
, " %s\n", con
->otherHelp
);
253 fprintf(f
, " %s\n", POPT_("[OPTION...]"));
255 leftColWidth
= maxArgWidth(con
->options
, NULL
);
256 singleTableHelp(f
, con
->options
, leftColWidth
, NULL
);
260 static int singleOptionUsage(FILE * f
, int cursor
,
261 const struct poptOption
* opt
,
262 const char *translation_domain
) {
265 const char * item
= shortStr
;
266 const char * argDescrip
= getArgDescrip(opt
, translation_domain
);
268 if (opt
->shortName
) {
269 if (!(opt
->argInfo
& POPT_ARG_MASK
))
270 return cursor
; /* we did these already */
272 *shortStr
= opt
->shortName
;
274 } else if (opt
->longName
) {
275 len
+= 1 + strlen(opt
->longName
);
276 item
= opt
->longName
;
279 if (len
== 3) return cursor
;
282 len
+= strlen(argDescrip
) + 1;
284 if ((cursor
+ len
) > 79) {
289 fprintf(f
, " [-%s%s%s%s]", opt
->shortName
? "" : "-", item
,
290 argDescrip
? (opt
->shortName
? " " : "=") : "",
291 argDescrip
? argDescrip
: "");
293 return cursor
+ len
+ 1;
296 static int singleTableUsage(FILE * f
, int cursor
, const struct poptOption
* table
,
297 const char *translation_domain
) {
298 const struct poptOption
* opt
;
301 while (opt
->longName
|| opt
->shortName
|| opt
->arg
.p
) {
302 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INTL_DOMAIN
)
303 translation_domain
= (const char *)opt
->arg
.p
;
304 else if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INCLUDE_TABLE
)
305 cursor
= singleTableUsage(f
, cursor
, opt
->arg
.p
,
307 else if ((opt
->longName
|| opt
->shortName
) &&
308 !(opt
->argInfo
& POPT_ARGFLAG_DOC_HIDDEN
))
309 cursor
= singleOptionUsage(f
, cursor
, opt
, translation_domain
);
317 static int showShortOptions(const struct poptOption
* opt
, FILE * f
,
319 char s
[300]; /* this is larger then the ascii set, so
320 it should do just fine */
324 memset(str
, 0, sizeof(s
));
327 while (opt
->longName
|| opt
->shortName
|| opt
->arg
.p
) {
328 if (opt
->shortName
&& !(opt
->argInfo
& POPT_ARG_MASK
))
329 str
[strlen(str
)] = opt
->shortName
;
330 else if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INCLUDE_TABLE
)
331 showShortOptions(opt
->arg
.p
, f
, str
);
339 fprintf(f
, " [-%s]", s
);
340 return strlen(s
) + 4;
343 void poptPrintUsage(poptContext con
, FILE * f
, int flags
) {
348 cursor
= showHelpIntro(con
, f
);
349 cursor
+= showShortOptions(con
->options
, f
, NULL
);
350 singleTableUsage(f
, cursor
, con
->options
, NULL
);
352 if (con
->otherHelp
) {
353 cursor
+= strlen(con
->otherHelp
) + 1;
354 if (cursor
> 79) fprintf(f
, "\n ");
355 fprintf(f
, " %s", con
->otherHelp
);
361 void poptSetOtherOptionHelp(poptContext con
, const char * text
) {
362 if (con
->otherHelp
) free(con
->otherHelp
);
363 con
->otherHelp
= strdup(text
);