Mixe for Privacy and Anonymity in the Internet
popthelp.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
00002 
00003 /* (C) 1998 Red Hat Software, Inc. -- Licensing details are in the COPYING
00004    file accompanying popt source distributions, available from 
00005    ftp://ftp.redhat.com/pub/code/popt */
00006 
00007 #include "../StdAfx.h"
00008 #include "poptint.h"
00009 
00010 static void displayArgs(poptContext con,
00011     /*@unused@*/ enum poptCallbackReason /*foo*/,
00012     struct poptOption * key, 
00013     /*@unused@*/ const char * /*arg*/, /*@unused@*/ void * /*data*/) {
00014     if (key->shortName== '?')
00015         poptPrintHelp(con, stdout, 0);
00016     else
00017         poptPrintUsage(con, stdout, 0);
00018     exit(0);
00019 }
00020 
00021 struct poptOption poptHelpOptions[] = {
00022     { NULL, '\0', POPT_ARG_CALLBACK, (void *)&displayArgs, '\0', NULL, NULL },
00023     { "help", '?', 0, NULL, '?', N_("Show this help message"), NULL },
00024     { "usage", 'u', 0, NULL, 'u', N_("Display brief usage message"), NULL },
00025     { NULL, '\0', 0, NULL, 0, NULL, NULL }
00026 } ;
00027 
00028 
00029 /*@observer@*/ /*@null@*/ static const char *const
00030 getTableTranslationDomain(const struct poptOption *table)
00031 {
00032   const struct poptOption *opt;
00033 
00034   for(opt = table;
00035       opt->longName || opt->shortName || opt->arg;
00036       opt++) {
00037     if(opt->argInfo == POPT_ARG_INTL_DOMAIN)
00038       return (const char* const)opt->arg;
00039   }
00040 
00041   return NULL;
00042 }
00043 
00044 /*@observer@*/ /*@null@*/ static const char *const
00045 getArgDescrip(const struct poptOption * opt, const char *translation_domain)
00046 {
00047     if (!(opt->argInfo & POPT_ARG_MASK)) return NULL;
00048 
00049     if (opt == (poptHelpOptions + 1) || opt == (poptHelpOptions + 2))
00050   if (opt->argDescrip) return POPT_(opt->argDescrip);
00051 
00052     if (opt->argDescrip) return D_(translation_domain, opt->argDescrip);
00053     return POPT_("ARG");
00054 }
00055 
00056 static void singleOptionHelp(FILE * f, int maxLeftCol, 
00057                              const struct poptOption * opt,
00058                              const char *translation_domain) {
00059     int indentLength = maxLeftCol + 5;
00060     int lineLength = 79 - indentLength;
00061     const char * help = D_(translation_domain, opt->descrip);
00062     int helpLength;
00063     const char * ch;
00064     char format[130];
00065     char * left;
00066     const char * argDescrip = getArgDescrip(opt, translation_domain);
00067     
00068     left = (char*)malloc(maxLeftCol + 1);
00069     *left = '\0';
00070     
00071     if (opt->longName && opt->shortName)
00072         sprintf(left, "-%c, --%s", opt->shortName, opt->longName);
00073     else if (opt->shortName) 
00074         sprintf(left, "-%c", opt->shortName);
00075     else if (opt->longName)
00076         sprintf(left, "--%s", opt->longName);
00077     if (!*left) return ;
00078     if (argDescrip) {
00079         strcat(left, "=");
00080         strcat(left, argDescrip);
00081     }
00082     
00083     if (help)
00084         fprintf(f,"  %-*s   ", maxLeftCol, left);
00085     else {
00086         fprintf(f,"  %s\n", left); 
00087         goto out;
00088     }
00089     
00090     helpLength = strlen(help);
00091     while (helpLength > lineLength) {
00092         ch = help + lineLength - 1;
00093         while (ch > help && !isspace(*ch)) ch--;
00094         if (ch == help) break;    /* give up */
00095             while (ch > (help + 1) && isspace(*ch)) ch--;
00096             ch++;
00097         
00098         sprintf(format, "%%.%ds\n%%%ds", (int) (ch - help), indentLength);
00099         fprintf(f, format, help, " ");
00100         help = ch;
00101         while (isspace(*help) && *help) help++;
00102         helpLength = strlen(help);
00103     }
00104     
00105     if (helpLength) fprintf(f, "%s\n", help);
00106     
00107     out:
00108     free(left);
00109 }
00110 
00111 static int maxArgWidth(const struct poptOption * opt,
00112            const char * translation_domain) {
00113     int max = 0;
00114     int thiS;
00115     const char * s;
00116     
00117     while (opt->longName || opt->shortName || opt->arg) {
00118   if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
00119       thiS = maxArgWidth((struct poptOption*)opt->arg, translation_domain);
00120       if (thiS > max) max = thiS;
00121   } else if (!(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN)) {
00122       thiS = opt->shortName ? 2 : 0;
00123       if (opt->longName) {
00124     if (thiS) thiS += 2;
00125     thiS += strlen(opt->longName) + 2;
00126       }
00127 
00128       s = getArgDescrip(opt, translation_domain);
00129       if (s)
00130     thiS += strlen(s) + 1;
00131       if (thiS > max) max = thiS;
00132   }
00133 
00134   opt++;
00135     }
00136     
00137     return max;
00138 }
00139 
00140 static void singleTableHelp(FILE * f, const struct poptOption * table, 
00141                             int left,
00142                             const char *translation_domain) {
00143     const struct poptOption * opt;
00144     const char *sub_transdom;
00145     
00146     opt = table;
00147     while (opt->longName || opt->shortName || opt->arg) {
00148         if ((opt->longName || opt->shortName) && 
00149             !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN))
00150             singleOptionHelp(f, left, opt, translation_domain);
00151         opt++;
00152     }
00153     
00154     opt = table;
00155     while (opt->longName || opt->shortName || opt->arg) {
00156     if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) {
00157         sub_transdom = getTableTranslationDomain((struct poptOption*)opt->arg);
00158         if(!sub_transdom)
00159         sub_transdom = translation_domain;
00160         
00161         if (opt->descrip)
00162         fprintf(f, "\n%s\n", D_(sub_transdom, opt->descrip));
00163 
00164         singleTableHelp(f, (struct poptOption*)opt->arg, left, sub_transdom);
00165     }
00166     opt++;
00167     }
00168     
00169 }
00170 
00171 static int showHelpIntro(poptContext con, FILE * f) {
00172     int len = 6;
00173     const char * fn;
00174 
00175     fprintf(f, POPT_("Usage:"));
00176     if (!(con->flags & POPT_CONTEXT_KEEP_FIRST)) {
00177   fn = con->optionStack->argv[0];
00178   if (strchr(fn, '/')) fn = strchr(fn, '/') + 1;
00179   fprintf(f, " %s", fn);
00180   len += strlen(fn) + 1;
00181     }
00182 
00183     return len;
00184 }
00185 
00186 void poptPrintHelp(poptContext con, FILE * f, /*@unused@*/ int /*flags*/) {
00187     int leftColWidth;
00188     
00189     showHelpIntro(con, f);
00190     if (con->otherHelp)
00191         fprintf(f, " %s\n", con->otherHelp);
00192     else
00193         fprintf(f, " %s\n", POPT_("[OPTION...]"));
00194     
00195     leftColWidth = maxArgWidth(con->options, NULL);
00196     singleTableHelp(f, con->options, leftColWidth, NULL);
00197 }
00198 
00199 static int singleOptionUsage(FILE * f, int cursor, 
00200            const struct poptOption * opt,
00201            const char *translation_domain) {
00202     int len = 3;
00203     char shortStr[2] = { '\0', '\0' };
00204     const char * item = shortStr;
00205     const char * argDescrip = getArgDescrip(opt, translation_domain);
00206 
00207     if (opt->shortName) {
00208   if (!(opt->argInfo & POPT_ARG_MASK)) 
00209       return cursor;  /* we did these already */
00210   len++;
00211   *shortStr = opt->shortName;
00212   shortStr[1] = '\0';
00213     } else if (opt->longName) {
00214   len += 1 + strlen(opt->longName);
00215   item = opt->longName;
00216     }
00217 
00218     if (len == 3) return cursor;
00219 
00220     if (argDescrip) 
00221   len += strlen(argDescrip) + 1;
00222 
00223     if ((cursor + len) > 79) {
00224   fprintf(f, "\n       ");
00225   cursor = 7;
00226     } 
00227 
00228     fprintf(f, " [-%s%s%s%s]", opt->shortName ? "" : "-", item,
00229       argDescrip ? (opt->shortName ? " " : "=") : "",
00230       argDescrip ? argDescrip : "");
00231 
00232     return cursor + len + 1;
00233 }
00234 
00235 static int singleTableUsage(FILE * f, int cursor, const struct poptOption * table,
00236          const char *translation_domain) {
00237     const struct poptOption * opt;
00238     
00239     opt = table;
00240     while (opt->longName || opt->shortName || opt->arg) {
00241         if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INTL_DOMAIN)
00242       translation_domain = (const char *)opt->arg;
00243   else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE) 
00244       cursor = singleTableUsage(f, cursor, (struct poptOption*)opt->arg,
00245               translation_domain);
00246   else if ((opt->longName || opt->shortName) && 
00247      !(opt->argInfo & POPT_ARGFLAG_DOC_HIDDEN))
00248     cursor = singleOptionUsage(f, cursor, opt, translation_domain);
00249 
00250   opt++;
00251     }
00252 
00253     return cursor;
00254 }
00255 
00256 static int showShortOptions(const struct poptOption * opt, FILE * f, 
00257           char * str) {
00258     char s[300];    /* this is larger then the ascii set, so
00259            it should do just fine */
00260 
00261     s[0] = '\0';
00262     if (str == NULL) {
00263   memset(s, 0, sizeof(s));
00264   str = s;
00265     }
00266 
00267     while (opt->longName || opt->shortName || opt->arg) {
00268   if (opt->shortName && !(opt->argInfo & POPT_ARG_MASK))
00269       str[strlen(str)] = opt->shortName;
00270   else if ((opt->argInfo & POPT_ARG_MASK) == POPT_ARG_INCLUDE_TABLE)
00271       showShortOptions((struct poptOption*)opt->arg, f, str);
00272 
00273   opt++;
00274     } 
00275 
00276     if (s != str || !*s)
00277   return 0;
00278 
00279     fprintf(f, " [-%s]", s);
00280     return strlen(s) + 4;
00281 }
00282 
00283 void poptPrintUsage(poptContext con, FILE * f, /*@unused@*/ int /*flags*/) {
00284     int cursor;
00285 
00286     cursor = showHelpIntro(con, f);
00287     cursor += showShortOptions(con->options, f, NULL);
00288     singleTableUsage(f, cursor, con->options, NULL);
00289 
00290     if (con->otherHelp) {
00291   cursor += strlen(con->otherHelp) + 1;
00292   if (cursor > 79) fprintf(f, "\n       ");
00293   fprintf(f, " %s", con->otherHelp);
00294     }
00295 
00296     fprintf(f, "\n");
00297 }
00298 
00299 void poptSetOtherOptionHelp(poptContext con, const char * text) {
00300     if (con->otherHelp) xfree(con->otherHelp);
00301     con->otherHelp = xstrdup(text);
00302 }