Main Page   Modules   Compound List   File List   Compound Members   File Members   Related Pages  

popt/popthelp.c

Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
00002 
00007 /* (C) 1998-2000 Red Hat, Inc. -- Licensing details are in the COPYING
00008    file accompanying popt source distributions, available from 
00009    ftp://ftp.rpm.org/pub/rpm/dist. */
00010 
00011 #include "system.h"
00012 #include "poptint.h"
00013 
00014 static void displayArgs(poptContext con,
00015                 /*@unused@*/ enum poptCallbackReason foo,
00016                 struct poptOption * key, 
00017                 /*@unused@*/ const char * arg, /*@unused@*/ 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 /*@observer@*/ /*@null@*/ 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 /*@observer@*/ /*@null@*/ 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     /* Make sure there's more than enough room in target buffer. */
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;          /* give up */
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, /*@unused@*/ 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;      /* we did these already */
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];                /* this is larger then the ascii set, so
00324                                    it should do just fine */
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, /*@unused@*/ 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 }

Generated at Mon May 21 08:53:40 2001 for rpm by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001