00001
00002
00007
00008
00009
00010
00011 #include "system.h"
00012 #include "poptint.h"
00013
00014 static void displayArgs(poptContext con,
00015 enum poptCallbackReason foo,
00016 struct poptOption * key,
00017 const char * arg, void * data)
00018 {
00019 if (key->shortName == '?')
00020 poptPrintHelp(con, stdout, 0);
00021 else
00022 poptPrintUsage(con, stdout, 0);
00023 exit(0);
00024 }
00025
00026 struct poptOption poptHelpOptions[] = {
00027 { NULL, '\0', POPT_ARG_CALLBACK, (void *)&displayArgs, '\0', NULL, NULL },
00028 { "help", '?', 0, NULL, '?', N_("Show this help message"), NULL },
00029 { "usage", '\0', 0, NULL, 'u', N_("Display brief usage message"), NULL },
00030 POPT_TABLEEND
00031 } ;
00032
00033
00034 static const char *const
00035 getTableTranslationDomain(const struct poptOption *table)
00036 {
00037 const struct poptOption *opt;
00038
00039 for(opt = table;
00040 opt->longName || opt->shortName || opt->arg;
00041 opt++) {
00042 if(opt->argInfo == POPT_ARG_INTL_DOMAIN)
00043 return opt->arg;
00044 }
00045
00046 return NULL;
00047 }
00048
00049 static const char *const
00050 getArgDescrip(const struct poptOption * opt, const char *translation_domain)
00051 {
00052 if (!(opt->argInfo & POPT_ARG_MASK)) return NULL;
00053
00054 if (opt == (poptHelpOptions + 1) || opt == (poptHelpOptions + 2))
00055 if (opt->argDescrip) return POPT_(opt->argDescrip);
00056
00057 if (opt->argDescrip) return D_(translation_domain, opt->argDescrip);
00058
00059 switch (opt->argInfo & POPT_ARG_MASK) {
00060 case POPT_ARG_NONE: return POPT_("NONE");
00061 case POPT_ARG_VAL: return POPT_("VAL");
00062 case POPT_ARG_INT: return POPT_("INT");
00063 case POPT_ARG_LONG: return POPT_("LONG");
00064 case POPT_ARG_STRING: return POPT_("STRING");
00065 case POPT_ARG_FLOAT: return POPT_("FLOAT");
00066 case POPT_ARG_DOUBLE: return POPT_("DOUBLE");
00067 default: return POPT_("ARG");
00068 }
00069 }
00070
00071 static void singleOptionHelp(FILE * f, int maxLeftCol,
00072 const struct poptOption * opt,
00073 const char *translation_domain)
00074 {
00075 int indentLength = maxLeftCol + 5;
00076 int lineLength = 79 - indentLength;
00077 const char * help = D_(translation_domain, opt->descrip);
00078 const char * argDescrip = getArgDescrip(opt, translation_domain);
00079 int helpLength;
00080 char * left;
00081 int nb = maxLeftCol + 1;
00082
00083
00084 if (opt->longName) nb += strlen(opt->longName);
00085 if (argDescrip) nb += strlen(argDescrip);
00086
00087 left = malloc(nb);
00088 left[0] = left[maxLeftCol] = '\0';
00089
00090 if (opt->longName && opt->shortName)
00091 sprintf(left, "-%c, %s%s", opt->shortName,
00092 ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"),
00093 opt->longName);
00094 else if (opt->shortName)
00095 sprintf(left, "-%c", opt->shortName);
00096 else if (opt->longName)
00097 sprintf(left, "%s%s",
00098 ((opt->argInfo & POPT_ARGFLAG_ONEDASH) ? "-" : "--"),
00099 opt->longName);
00100 if (!*left) goto out;
00101 if (argDescrip) {
00102 char * le = left + strlen(left);
00103 if (opt->argInfo & POPT_ARGFLAG_OPTIONAL)
00104 *le++ = '[';
00105 if (opt->argDescrip == NULL) {
00106 switch (opt->argInfo & POPT_ARG_MASK) {
00107 case POPT_ARG_NONE:
00108 sprintf(le, "[true]");
00109 break;
00110 case POPT_ARG_VAL:
00111 { long aLong = opt->val;
00112
00113 if (opt->argInfo & POPT_ARGFLAG_NOT) aLong = ~aLong;
00114 switch (opt->argInfo & POPT_ARGFLAG_LOGICALOPS) {
00115 case POPT_ARGFLAG_OR:
00116 sprintf(le, "[|=0x%lx]", aLong); break;
00117 case POPT_ARGFLAG_AND:
00118 sprintf(le, "[&=0x%lx]", aLong); break;
00119 case POPT_ARGFLAG_XOR:
00120 sprintf(le, "[^=0x%lx]", aLong); break;
00121 default:
00122 if (!(aLong == 0L || aLong == 1L || aLong == -1L))
00123 sprintf(le, "[=%ld]", aLong);
00124 break;
00125 }
00126 } break;
00127 case POPT_ARG_INT:
00128 case POPT_ARG_LONG:
00129 case POPT_ARG_STRING:
00130 case POPT_ARG_FLOAT:
00131 case POPT_ARG_DOUBLE:
00132 sprintf(le, "=%s", argDescrip);
00133 break;
00134 }
00135 } else {
00136 sprintf(le, "=%s", argDescrip);
00137 }
00138 le += strlen(le);
00139 if (opt->argInfo & POPT_ARGFLAG_OPTIONAL)
00140 *le++ = ']';
00141 *le = '\0';
00142 }
00143
00144 if (help)
00145 fprintf(f," %-*s ", maxLeftCol, left);
00146 else {
00147 fprintf(f," %s\n", left);
00148 goto out;
00149 }
00150
00151 helpLength = strlen(help);
00152 while (helpLength > lineLength) {
00153 const char * ch;
00154 char format[10];
00155
00156 ch = help + lineLength - 1;
00157 while (ch > help && !isspace(*ch)) ch--;
00158 if (ch == help) break;
00159 while (ch > (help + 1) && isspace(*ch)) ch--;
00160 ch++;
00161
00162 sprintf(format, "%%.%ds\n%%%ds", (int) (ch - help), indentLength);
00163 fprintf(f, format, help, " ");
00164 help = ch;
00165 while (isspace(*help) && *help) help++;
00166 helpLength = strlen(help);
00167 }
00168
00169 if (helpLength) fprintf(f, "%s\n", help);
00170
00171 out:
00172 free(left);
00173 }
00174
00175 static int maxArgWidth(const struct poptOption * opt,
00176 const char * translation_domain)
00177 {
00178 int max = 0;
00179 int this;
00180 const char * s;
00181
00182 while (opt->longName || opt->shortName || opt->arg) {
00183 if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
00184 this = maxArgWidth(opt->arg, translation_domain);
00185 if (this > max) max = this;
00186 } else if (!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) {
00187 this = sizeof(" ")-1;
00188 if (opt->shortName) this += sizeof("-X")-1;
00189 if (opt->shortName && opt->longName) this += sizeof(", ")-1;
00190 if (opt->longName) {
00191 this += ((opt->argInfo & POPT_ARGFLAG_ONEDASH)
00192 ? sizeof("-")-1 : sizeof("--")-1);
00193 this += strlen(opt->longName);
00194 }
00195
00196 s = getArgDescrip(opt, translation_domain);
00197 if (s)
00198 this += sizeof("=")-1 + strlen(s);
00199 if (opt->argInfo & POPT_ARGFLAG_OPTIONAL) this += sizeof("[]")-1;
00200 if (this > max) max = this;
00201 }
00202
00203 opt++;
00204 }
00205
00206 return max;
00207 }
00208
00209 static void singleTableHelp(FILE * f, const struct poptOption * table,
00210 int left,
00211 const char *translation_domain)
00212 {
00213 const struct poptOption * opt;
00214 const char *sub_transdom;
00215
00216 for (opt = table; (opt->longName || opt->shortName || opt->arg); opt++) {
00217 if ((opt->longName || opt->shortName) &&
00218 !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN))
00219 singleOptionHelp(f, left, opt, translation_domain);
00220 }
00221
00222 for (opt = table; (opt->longName || opt->shortName || opt->arg); opt++) {
00223 if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
00224 sub_transdom = getTableTranslationDomain(opt->arg);
00225 if(!sub_transdom)
00226 sub_transdom = translation_domain;
00227
00228 if (opt->descrip)
00229 fprintf(f, "\n%s\n", D_(sub_transdom, opt->descrip));
00230
00231 singleTableHelp(f, opt->arg, left, sub_transdom);
00232 }
00233 }
00234 }
00235
00236 static int showHelpIntro(poptContext con, FILE * f)
00237 {
00238 int len = 6;
00239 const char * fn;
00240
00241 fprintf(f, POPT_("Usage:"));
00242 if (!(con->flags & POPT_CONTEXT_KEEP_FIRST)) {
00243 fn = con->optionStack->argv[0];
00244 if (strchr(fn, '/')) fn = strrchr(fn, '/') + 1;
00245 fprintf(f, " %s", fn);
00246 len += strlen(fn) + 1;
00247 }
00248
00249 return len;
00250 }
00251
00252 void poptPrintHelp(poptContext con, FILE * f, int flags)
00253 {
00254 int leftColWidth;
00255
00256 showHelpIntro(con, f);
00257 if (con->otherHelp)
00258 fprintf(f, " %s\n", con->otherHelp);
00259 else
00260 fprintf(f, " %s\n", POPT_("[OPTION...]"));
00261
00262 leftColWidth = maxArgWidth(con->options, NULL);
00263 singleTableHelp(f, con->options, leftColWidth, NULL);
00264 }
00265
00266 static int singleOptionUsage(FILE * f, int cursor,
00267 const struct poptOption * opt,
00268 const char *translation_domain)
00269 {
00270 int len = 3;
00271 char shortStr[2] = { '\0', '\0' };
00272 const char * item = shortStr;
00273 const char * argDescrip = getArgDescrip(opt, translation_domain);
00274
00275 if (opt->shortName) {
00276 if (!(opt->argInfo & POPT_ARG_MASK))
00277 return cursor;
00278 len++;
00279 shortStr[0] = opt->shortName;
00280 shortStr[1] = '\0';
00281 } else if (opt->longName) {
00282 len += 1 + strlen(opt->longName);
00283 item = opt->longName;
00284 }
00285
00286 if (len == 3) return cursor;
00287
00288 if (argDescrip)
00289 len += strlen(argDescrip) + 1;
00290
00291 if ((cursor + len) > 79) {
00292 fprintf(f, "\n ");
00293 cursor = 7;
00294 }
00295
00296 fprintf(f, " [-%s%s%s%s]",
00297 ((opt->shortName || (opt->argInfo & POPT_ARGFLAG_ONEDASH)) ? "" : "-"),
00298 item,
00299 (argDescrip ? (opt->shortName ? " " : "=") : ""),
00300 (argDescrip ? argDescrip : ""));
00301
00302 return cursor + len + 1;
00303 }
00304
00305 static int singleTableUsage(FILE * f, int cursor,
00306 const struct poptOption * opt, const char * translation_domain)
00307 {
00308 for (; (opt->longName || opt->shortName || opt->arg) ; opt++) {
00309 if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INTL_DOMAIN)
00310 translation_domain = (const char *)opt->arg;
00311 else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE)
00312 cursor = singleTableUsage(f, cursor, opt->arg, translation_domain);
00313 else if ((opt->longName || opt->shortName) &&
00314 !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN))
00315 cursor = singleOptionUsage(f, cursor, opt, translation_domain);
00316 }
00317
00318 return cursor;
00319 }
00320
00321 static int showShortOptions(const struct poptOption * opt, FILE * f, char * str)
00322 {
00323 char s[300];
00324
00325
00326 s[0] = '\0';
00327 if (str == NULL) {
00328 memset(s, 0, sizeof(s));
00329 str = s;
00330 }
00331
00332 for (; (opt->longName || opt->shortName || opt->arg); opt++) {
00333 if (opt->shortName && !(opt->argInfo & POPT_ARG_MASK))
00334 str[strlen(str)] = opt->shortName;
00335 else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE)
00336 showShortOptions(opt->arg, f, str);
00337 }
00338
00339 if (s != str || !*s)
00340 return 0;
00341
00342 fprintf(f, " [-%s]", s);
00343 return strlen(s) + 4;
00344 }
00345
00346 void poptPrintUsage(poptContext con, FILE * f, int flags)
00347 {
00348 int cursor;
00349
00350 cursor = showHelpIntro(con, f);
00351 cursor += showShortOptions(con->options, f, NULL);
00352 singleTableUsage(f, cursor, con->options, NULL);
00353
00354 if (con->otherHelp) {
00355 cursor += strlen(con->otherHelp) + 1;
00356 if (cursor > 79) fprintf(f, "\n ");
00357 fprintf(f, " %s", con->otherHelp);
00358 }
00359
00360 fprintf(f, "\n");
00361 }
00362
00363 void poptSetOtherOptionHelp(poptContext con, const char * text) {
00364 if (con->otherHelp) free((void *)con->otherHelp);
00365 con->otherHelp = xstrdup(text);
00366 }