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 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 char * help
= D_(translation_domain
, opt
->descrip
);
73 const char * argDescrip
= getArgDescrip(opt
, translation_domain
);
75 left
= malloc(maxLeftCol
+ 1);
78 if (opt
->longName
&& opt
->shortName
)
79 sprintf(left
, "-%c, --%s", opt
->shortName
, opt
->longName
);
80 else if (opt
->shortName
)
81 sprintf(left
, "-%c", opt
->shortName
);
82 else if (opt
->longName
)
83 sprintf(left
, "--%s", opt
->longName
);
87 strcat(left
, argDescrip
);
91 fprintf(f
," %-*s ", maxLeftCol
, left
);
93 fprintf(f
," %s\n", left
);
97 helpLength
= strlen(help
);
98 while (helpLength
> lineLength
) {
99 ch
= help
+ lineLength
- 1;
100 while (ch
> help
&& !isspace(*ch
)) ch
--;
101 if (ch
== help
) break; /* give up */
102 while (ch
> (help
+ 1) && isspace(*ch
)) ch
--;
105 sprintf(format
, "%%.%ds\n%%%ds", (int) (ch
- help
), indentLength
);
106 fprintf(f
, format
, help
, " ");
108 while (isspace(*help
) && *help
) help
++;
109 helpLength
= strlen(help
);
112 if (helpLength
) fprintf(f
, "%s\n", help
);
118 static int maxArgWidth(const struct poptOption
* opt
,
119 const char * translation_domain
) {
124 while (opt
->longName
|| opt
->shortName
|| opt
->arg
) {
125 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INCLUDE_TABLE
) {
126 this = maxArgWidth(opt
->arg
, translation_domain
);
127 if (this > max
) max
= this;
128 } else if (!(opt
->argInfo
& POPT_ARGFLAG_DOC_HIDDEN
)) {
129 this = opt
->shortName
? 2 : 0;
132 this += strlen(opt
->longName
) + 2;
135 s
= getArgDescrip(opt
, translation_domain
);
137 this += strlen(s
) + 1;
138 if (this > max
) max
= this;
147 static void singleTableHelp(FILE * f
, const struct poptOption
* table
,
149 const char *translation_domain
) {
150 const struct poptOption
* opt
;
151 const char *sub_transdom
;
154 while (opt
->longName
|| opt
->shortName
|| opt
->arg
) {
155 if ((opt
->longName
|| opt
->shortName
) &&
156 !(opt
->argInfo
& POPT_ARGFLAG_DOC_HIDDEN
))
157 singleOptionHelp(f
, left
, opt
, translation_domain
);
162 while (opt
->longName
|| opt
->shortName
|| opt
->arg
) {
163 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INCLUDE_TABLE
) {
164 sub_transdom
= getTableTranslationDomain(opt
->arg
);
166 sub_transdom
= translation_domain
;
169 fprintf(f
, "\n%s\n", D_(sub_transdom
, opt
->descrip
));
171 singleTableHelp(f
, opt
->arg
, left
, sub_transdom
);
177 static int showHelpIntro(poptContext con
, FILE * f
) {
181 fprintf(f
, POPT_("Usage:"));
182 if (!(con
->flags
& POPT_CONTEXT_KEEP_FIRST
)) {
183 fn
= con
->optionStack
->argv
[0];
184 if (strchr(fn
, '/')) fn
= strchr(fn
, '/') + 1;
185 fprintf(f
, " %s", fn
);
186 len
+= strlen(fn
) + 1;
192 void poptPrintHelp(poptContext con
, FILE * f
, int flags
) {
195 showHelpIntro(con
, f
);
197 fprintf(f
, " %s\n", con
->otherHelp
);
199 fprintf(f
, " %s\n", POPT_("[OPTION...]"));
201 leftColWidth
= maxArgWidth(con
->options
, NULL
);
202 singleTableHelp(f
, con
->options
, leftColWidth
, NULL
);
205 static int singleOptionUsage(FILE * f
, int cursor
,
206 const struct poptOption
* opt
,
207 const char *translation_domain
) {
210 const char * item
= shortStr
;
211 const char * argDescrip
= getArgDescrip(opt
, translation_domain
);
213 if (opt
->shortName
) {
214 if (!(opt
->argInfo
& POPT_ARG_MASK
))
215 return cursor
; /* we did these already */
217 *shortStr
= opt
->shortName
;
219 } else if (opt
->longName
) {
220 len
+= 1 + strlen(opt
->longName
);
221 item
= opt
->longName
;
224 if (len
== 3) return cursor
;
227 len
+= strlen(argDescrip
) + 1;
229 if ((cursor
+ len
) > 79) {
234 fprintf(f
, " [-%s%s%s%s]", opt
->shortName
? "" : "-", item
,
235 argDescrip
? (opt
->shortName
? " " : "=") : "",
236 argDescrip
? argDescrip
: "");
238 return cursor
+ len
+ 1;
241 static int singleTableUsage(FILE * f
, int cursor
, const struct poptOption
* table
,
242 const char *translation_domain
) {
243 const struct poptOption
* opt
;
246 while (opt
->longName
|| opt
->shortName
|| opt
->arg
) {
247 if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INTL_DOMAIN
)
248 translation_domain
= (const char *)opt
->arg
;
249 else if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INCLUDE_TABLE
)
250 cursor
= singleTableUsage(f
, cursor
, opt
->arg
,
252 else if ((opt
->longName
|| opt
->shortName
) &&
253 !(opt
->argInfo
& POPT_ARGFLAG_DOC_HIDDEN
))
254 cursor
= singleOptionUsage(f
, cursor
, opt
, translation_domain
);
262 static int showShortOptions(const struct poptOption
* opt
, FILE * f
,
264 char s
[300]; /* this is larger then the ascii set, so
265 it should do just fine */
269 memset(str
, 0, sizeof(s
));
272 while (opt
->longName
|| opt
->shortName
|| opt
->arg
) {
273 if (opt
->shortName
&& !(opt
->argInfo
& POPT_ARG_MASK
))
274 str
[strlen(str
)] = opt
->shortName
;
275 else if ((opt
->argInfo
& POPT_ARG_MASK
) == POPT_ARG_INCLUDE_TABLE
)
276 showShortOptions(opt
->arg
, f
, str
);
284 fprintf(f
, " [-%s]", s
);
285 return strlen(s
) + 4;
288 void poptPrintUsage(poptContext con
, FILE * f
, int flags
) {
291 cursor
= showHelpIntro(con
, f
);
292 cursor
+= showShortOptions(con
->options
, f
, NULL
);
293 singleTableUsage(f
, cursor
, con
->options
, NULL
);
295 if (con
->otherHelp
) {
296 cursor
+= strlen(con
->otherHelp
) + 1;
297 if (cursor
> 79) fprintf(f
, "\n ");
298 fprintf(f
, " %s", con
->otherHelp
);
304 void poptSetOtherOptionHelp(poptContext con
, const char * text
) {
305 if (con
->otherHelp
) free(con
->otherHelp
);
306 con
->otherHelp
= strdup(text
);