Annotation of embedaddon/ntp/sntp/libopts/usage.c, revision 1.1

1.1     ! misho       1: 
        !             2: /*
        !             3:  * \file usage.c
        !             4:  *
        !             5:  * Time-stamp:      "2011-02-01 14:42:37 bkorb"
        !             6:  *
        !             7:  *  This module implements the default usage procedure for
        !             8:  *  Automated Options.  It may be overridden, of course.
        !             9:  *
        !            10:  *  Sort options:
        !            11:     --start=END-[S]TATIC-FORWARD --patt='^/\*($|[^:])' \
        !            12:     --out=xx.c key='^[a-zA-Z0-9_]+\(' --trail='^/\*:' \
        !            13:     --spac=2 --input=usage.c
        !            14:  */
        !            15: 
        !            16: /*
        !            17:  *  This file is part of AutoOpts, a companion to AutoGen.
        !            18:  *  AutoOpts is free software.
        !            19:  *  AutoOpts is Copyright (c) 1992-2011 by Bruce Korb - all rights reserved
        !            20:  *
        !            21:  *  AutoOpts is available under any one of two licenses.  The license
        !            22:  *  in use must be one of these two and the choice is under the control
        !            23:  *  of the user of the license.
        !            24:  *
        !            25:  *   The GNU Lesser General Public License, version 3 or later
        !            26:  *      See the files "COPYING.lgplv3" and "COPYING.gplv3"
        !            27:  *
        !            28:  *   The Modified Berkeley Software Distribution License
        !            29:  *      See the file "COPYING.mbsd"
        !            30:  *
        !            31:  *  These files have the following md5sums:
        !            32:  *
        !            33:  *  43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3
        !            34:  *  06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3
        !            35:  *  66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd
        !            36:  */
        !            37: 
        !            38: #define OPTPROC_L_N_S  (OPTPROC_LONGOPT | OPTPROC_SHORTOPT)
        !            39: 
        !            40: /* = = = START-STATIC-FORWARD = = = */
        !            41: static void
        !            42: set_usage_flags(tOptions * opts, char const * flg_txt);
        !            43: 
        !            44: static inline ag_bool
        !            45: do_gnu_usage(tOptions * pOpts);
        !            46: 
        !            47: static inline ag_bool
        !            48: skip_misuse_usage(tOptions * pOpts);
        !            49: 
        !            50: static void
        !            51: print_usage_details(tOptions * opts, int exit_code);
        !            52: 
        !            53: static void
        !            54: prt_extd_usage(tOptions * pOptions, tOptDesc * pOD, arg_types_t * pAT);
        !            55: 
        !            56: static void
        !            57: prt_ini_list(char const * const * papz, ag_bool * pInitIntro,
        !            58:              char const * pzRc, char const * pzPN);
        !            59: 
        !            60: static void
        !            61: prt_preamble(tOptions * pOptions, tOptDesc * pOD, arg_types_t * pAT);
        !            62: 
        !            63: static void
        !            64: prt_one_usage(tOptions * pOptions, tOptDesc * pOD, arg_types_t * pAT);
        !            65: 
        !            66: static void
        !            67: prt_opt_usage(tOptions * pOpts, int ex_code, char const * pOptTitle);
        !            68: 
        !            69: static void
        !            70: prt_prog_detail(tOptions* pOptions);
        !            71: 
        !            72: static int
        !            73: setGnuOptFmts(tOptions* pOpts, tCC** ppT);
        !            74: 
        !            75: static int
        !            76: setStdOptFmts(tOptions* pOpts, tCC** ppT);
        !            77: /* = = = END-STATIC-FORWARD = = = */
        !            78: 
        !            79: /*
        !            80:  *  NB: no entry may be a prefix of another entry
        !            81:  */
        !            82: #define AOFLAG_TABLE                            \
        !            83:     _aof_(gnu,             OPTPROC_GNUUSAGE )   \
        !            84:     _aof_(autoopts,        ~OPTPROC_GNUUSAGE)   \
        !            85:     _aof_(no_misuse_usage, OPTPROC_MISUSE   )   \
        !            86:     _aof_(misuse_usage,    ~OPTPROC_MISUSE  )
        !            87: 
        !            88: static void
        !            89: set_usage_flags(tOptions * opts, char const * flg_txt)
        !            90: {
        !            91:     typedef struct {
        !            92:         size_t          fnm_len;
        !            93:         uint32_t        fnm_mask;
        !            94:         char const *    fnm_name;
        !            95:     } ao_flag_names_t;
        !            96: 
        !            97: #   define _aof_(_n, _f)   AOUF_ ## _n ## _ID,
        !            98:     typedef enum { AOFLAG_TABLE AOUF_COUNT } ao_flag_id_t;
        !            99: #   undef  _aof_
        !           100: 
        !           101: #   define _aof_(_n, _f)   AOUF_ ## _n = (1 << AOUF_ ## _n ## _ID),
        !           102:     typedef enum { AOFLAG_TABLE } ao_flags_t;
        !           103: #   undef  _aof_
        !           104: 
        !           105: #   define _aof_(_n, _f)   { sizeof(#_n)-1, _f, #_n },
        !           106:     static ao_flag_names_t const fn_table[AOUF_COUNT] = {
        !           107:         AOFLAG_TABLE
        !           108:     };
        !           109: #   undef  _aof_
        !           110: 
        !           111:     ao_flags_t flg = 0;
        !           112: 
        !           113:     if (flg_txt == NULL) {
        !           114:         flg_txt = getenv("AUTOOPTS_USAGE");
        !           115:         if (flg_txt == NULL)
        !           116:             return;
        !           117:     }
        !           118: 
        !           119:     while (IS_WHITESPACE_CHAR(*flg_txt))  flg_txt++;
        !           120:     if (*flg_txt == NUL)
        !           121:         return;
        !           122: 
        !           123:     for (;;) {
        !           124:         int ix = 0;
        !           125:         ao_flag_names_t const * fnt = fn_table;
        !           126: 
        !           127:         for (;;) {
        !           128:             if (strneqvcmp(flg_txt, fnt->fnm_name, fnt->fnm_len) == 0)
        !           129:                 break;
        !           130:             if (++ix >= AOUF_COUNT)
        !           131:                 return;
        !           132:             fnt++;
        !           133:         }
        !           134: 
        !           135:         /*
        !           136:          *  Make sure we have a full match.  Look for whitespace,
        !           137:          *  a comma, or a NUL byte.
        !           138:          */
        !           139:         if (! IS_END_LIST_ENTRY_CHAR(flg_txt[fnt->fnm_len]))
        !           140:             return;
        !           141: 
        !           142:         flg |= 1 << ix;
        !           143:         flg_txt  += fnt->fnm_len;
        !           144:         while (IS_WHITESPACE_CHAR(*flg_txt))  flg_txt++;
        !           145: 
        !           146:         if (*flg_txt == NUL)
        !           147:             break;
        !           148: 
        !           149:         if (*flg_txt == ',') {
        !           150:             /*
        !           151:              *  skip the comma and following white space
        !           152:              */
        !           153:             while (IS_WHITESPACE_CHAR(*++flg_txt))  ;
        !           154:             if (*flg_txt == NUL)
        !           155:                 break;
        !           156:         }
        !           157:     }
        !           158: 
        !           159:     {
        !           160:         ao_flag_names_t const * fnm = fn_table;
        !           161: 
        !           162:         while (flg != 0) {
        !           163:             if ((flg & 1) != 0) {
        !           164:                 if ((fnm->fnm_mask & OPTPROC_LONGOPT) != 0)
        !           165:                      opts->fOptSet &= fnm->fnm_mask;
        !           166:                 else opts->fOptSet |= fnm->fnm_mask;
        !           167:             }
        !           168:             flg >>= 1;
        !           169:             fnm++;
        !           170:         }
        !           171:     }
        !           172: }
        !           173: 
        !           174: /*
        !           175:  *  Figure out if we should try to format usage text sort-of like
        !           176:  *  the way many GNU programs do.
        !           177:  */
        !           178: static inline ag_bool
        !           179: do_gnu_usage(tOptions * pOpts)
        !           180: {
        !           181:     return (pOpts->fOptSet & OPTPROC_GNUUSAGE) ? AG_TRUE : AG_FALSE;
        !           182: }
        !           183: 
        !           184: /*
        !           185:  *  Figure out if we should try to format usage text sort-of like
        !           186:  *  the way many GNU programs do.
        !           187:  */
        !           188: static inline ag_bool
        !           189: skip_misuse_usage(tOptions * pOpts)
        !           190: {
        !           191:     return (pOpts->fOptSet & OPTPROC_MISUSE) ? AG_TRUE : AG_FALSE;
        !           192: }
        !           193: 
        !           194: 
        !           195: /*=export_func  optionOnlyUsage
        !           196:  *
        !           197:  * what:  Print usage text for just the options
        !           198:  * arg:   + tOptions*   + pOpts    + program options descriptor +
        !           199:  * arg:   + int         + ex_code  + exit code for calling exit(3) +
        !           200:  *
        !           201:  * doc:
        !           202:  *  This routine will print only the usage for each option.
        !           203:  *  This function may be used when the emitted usage must incorporate
        !           204:  *  information not available to AutoOpts.
        !           205: =*/
        !           206: void
        !           207: optionOnlyUsage(tOptions * pOpts, int ex_code)
        !           208: {
        !           209:     char const * pOptTitle = NULL;
        !           210: 
        !           211:     set_usage_flags(pOpts, NULL);
        !           212:     if ((ex_code != EXIT_SUCCESS) &&
        !           213:         skip_misuse_usage(pOpts))
        !           214:         return;
        !           215: 
        !           216:     /*
        !           217:      *  Determine which header and which option formatting strings to use
        !           218:      */
        !           219:     if (do_gnu_usage(pOpts)) {
        !           220:         (void)setGnuOptFmts(pOpts, &pOptTitle);
        !           221:     }
        !           222:     else {
        !           223:         (void)setStdOptFmts(pOpts, &pOptTitle);
        !           224:     }
        !           225: 
        !           226:     prt_opt_usage(pOpts, ex_code, pOptTitle);
        !           227: 
        !           228:     fflush(option_usage_fp);
        !           229:     if (ferror(option_usage_fp) != 0) {
        !           230:         fputs(zOutputFail, stderr);
        !           231:         exit(EXIT_FAILURE);
        !           232:     }
        !           233: }
        !           234: 
        !           235: static void
        !           236: print_usage_details(tOptions * opts, int exit_code)
        !           237: {
        !           238:     {
        !           239:         char const * pOptTitle = NULL;
        !           240: 
        !           241:         /*
        !           242:          *  Determine which header and which option formatting strings to use
        !           243:          */
        !           244:         if (do_gnu_usage(opts)) {
        !           245:             int flen = setGnuOptFmts(opts, &pOptTitle);
        !           246:             sprintf(zOptFmtLine, zFmtFmt, flen);
        !           247:             fputc('\n', option_usage_fp);
        !           248:         }
        !           249:         else {
        !           250:             int flen = setStdOptFmts(opts, &pOptTitle);
        !           251:             sprintf(zOptFmtLine, zFmtFmt, flen);
        !           252: 
        !           253:             /*
        !           254:              *  When we exit with EXIT_SUCCESS and the first option is a doc
        !           255:              *  option, we do *NOT* want to emit the column headers.
        !           256:              *  Otherwise, we do.
        !           257:              */
        !           258:             if (  (exit_code != EXIT_SUCCESS)
        !           259:                || ((opts->pOptDesc->fOptState & OPTST_DOCUMENT) == 0) )
        !           260: 
        !           261:                 fputs(pOptTitle, option_usage_fp);
        !           262:         }
        !           263: 
        !           264:         prt_opt_usage(opts, exit_code, pOptTitle);
        !           265:     }
        !           266: 
        !           267:     /*
        !           268:      *  Describe the mechanics of denoting the options
        !           269:      */
        !           270:     switch (opts->fOptSet & OPTPROC_L_N_S) {
        !           271:     case OPTPROC_L_N_S:     fputs(zFlagOkay, option_usage_fp); break;
        !           272:     case OPTPROC_SHORTOPT:  break;
        !           273:     case OPTPROC_LONGOPT:   fputs(zNoFlags,  option_usage_fp); break;
        !           274:     case 0:                 fputs(zOptsOnly, option_usage_fp); break;
        !           275:     }
        !           276: 
        !           277:     if ((opts->fOptSet & OPTPROC_NUM_OPT) != 0)
        !           278:         fputs(zNumberOpt, option_usage_fp);
        !           279: 
        !           280:     if ((opts->fOptSet & OPTPROC_REORDER) != 0)
        !           281:         fputs(zReorder, option_usage_fp);
        !           282: 
        !           283:     if (opts->pzExplain != NULL)
        !           284:         fputs(opts->pzExplain, option_usage_fp);
        !           285: 
        !           286:     /*
        !           287:      *  IF the user is asking for help (thus exiting with SUCCESS),
        !           288:      *  THEN see what additional information we can provide.
        !           289:      */
        !           290:     if (exit_code == EXIT_SUCCESS)
        !           291:         prt_prog_detail(opts);
        !           292: 
        !           293:     /*
        !           294:      * Give bug notification preference to the packager information
        !           295:      */
        !           296:     if (HAS_pzPkgDataDir(opts) && (opts->pzPackager != NULL))
        !           297:         fputs(opts->pzPackager, option_usage_fp);
        !           298: 
        !           299:     else if (opts->pzBugAddr != NULL)
        !           300:         fprintf(option_usage_fp, zPlsSendBugs, opts->pzBugAddr);
        !           301: 
        !           302:     fflush(option_usage_fp);
        !           303: 
        !           304:     if (ferror(option_usage_fp) != 0) {
        !           305:         fputs(zOutputFail, stderr);
        !           306:         exit(EXIT_FAILURE);
        !           307:     }
        !           308: }
        !           309: 
        !           310: 
        !           311: /*=export_func  optionUsage
        !           312:  * private:
        !           313:  *
        !           314:  * what:  Print usage text
        !           315:  * arg:   + tOptions* + pOptions + program options descriptor +
        !           316:  * arg:   + int       + exitCode + exit code for calling exit(3) +
        !           317:  *
        !           318:  * doc:
        !           319:  *  This routine will print usage in both GNU-standard and AutoOpts-expanded
        !           320:  *  formats.  The descriptor specifies the default, but AUTOOPTS_USAGE will
        !           321:  *  over-ride this, providing the value of it is set to either "gnu" or
        !           322:  *  "autoopts".  This routine will @strong{not} return.
        !           323:  *
        !           324:  *  If "exitCode" is "EX_USAGE" (normally 64), then output will to to stdout
        !           325:  *  and the actual exit code will be "EXIT_SUCCESS".
        !           326: =*/
        !           327: void
        !           328: optionUsage(tOptions * pOptions, int usage_exit_code)
        !           329: {
        !           330:     int exit_code =
        !           331:         (usage_exit_code == EX_USAGE) ? EXIT_SUCCESS : usage_exit_code;
        !           332: 
        !           333:     displayEnum = AG_FALSE;
        !           334: 
        !           335:     /*
        !           336:      *  Paged usage will preset option_usage_fp to an output file.
        !           337:      *  If it hasn't already been set, then set it to standard output
        !           338:      *  on successful exit (help was requested), otherwise error out.
        !           339:      *
        !           340:      *  Test the version before obtaining pzFullUsage or pzShortUsage.
        !           341:      *  These fields do not exist before revision 30.
        !           342:      */
        !           343:     {
        !           344:         char const * pz;
        !           345: 
        !           346:         if (exit_code == EXIT_SUCCESS) {
        !           347:             pz = (pOptions->structVersion >= 30 * 4096)
        !           348:                 ? pOptions->pzFullUsage : NULL;
        !           349: 
        !           350:             if (option_usage_fp == NULL)
        !           351:                 option_usage_fp = stdout;
        !           352:         } else {
        !           353:             pz = (pOptions->structVersion >= 30 * 4096)
        !           354:                 ? pOptions->pzShortUsage : NULL;
        !           355: 
        !           356:             if (option_usage_fp == NULL)
        !           357:                 option_usage_fp = stderr;
        !           358:         }
        !           359: 
        !           360:         if (pz != NULL) {
        !           361:             fputs(pz, option_usage_fp);
        !           362:             exit(exit_code);
        !           363:         }
        !           364:     }
        !           365: 
        !           366:     fprintf(option_usage_fp, pOptions->pzUsageTitle, pOptions->pzProgName);
        !           367:     set_usage_flags(pOptions, NULL);
        !           368: 
        !           369:     if ((exit_code == EXIT_SUCCESS) ||
        !           370:         (! skip_misuse_usage(pOptions)))
        !           371: 
        !           372:         print_usage_details(pOptions, usage_exit_code);
        !           373: 
        !           374:     exit(exit_code);
        !           375: }
        !           376: 
        !           377: 
        !           378: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
        !           379:  *
        !           380:  *   PER OPTION TYPE USAGE INFORMATION
        !           381:  */
        !           382: static void
        !           383: prt_extd_usage(tOptions * pOptions, tOptDesc * pOD, arg_types_t * pAT)
        !           384: {
        !           385:     /*
        !           386:      *  IF there are option conflicts or dependencies,
        !           387:      *  THEN print them here.
        !           388:      */
        !           389:     if (  (pOD->pOptMust != NULL)
        !           390:        || (pOD->pOptCant != NULL) ) {
        !           391: 
        !           392:         fputs(zTabHyp, option_usage_fp);
        !           393: 
        !           394:         /*
        !           395:          *  DEPENDENCIES:
        !           396:          */
        !           397:         if (pOD->pOptMust != NULL) {
        !           398:             const int* pOptNo = pOD->pOptMust;
        !           399: 
        !           400:             fputs(zReqThese, option_usage_fp);
        !           401:             for (;;) {
        !           402:                 fprintf(option_usage_fp, zTabout,
        !           403:                         pOptions->pOptDesc[*pOptNo].pz_Name);
        !           404:                 if (*++pOptNo == NO_EQUIVALENT)
        !           405:                     break;
        !           406:             }
        !           407: 
        !           408:             if (pOD->pOptCant != NULL)
        !           409:                 fputs(zTabHypAnd, option_usage_fp);
        !           410:         }
        !           411: 
        !           412:         /*
        !           413:          *  CONFLICTS:
        !           414:          */
        !           415:         if (pOD->pOptCant != NULL) {
        !           416:             const int* pOptNo = pOD->pOptCant;
        !           417: 
        !           418:             fputs(zProhib, option_usage_fp);
        !           419:             for (;;) {
        !           420:                 fprintf(option_usage_fp, zTabout,
        !           421:                         pOptions->pOptDesc[*pOptNo].pz_Name);
        !           422:                 if (*++pOptNo == NO_EQUIVALENT)
        !           423:                     break;
        !           424:             }
        !           425:         }
        !           426:     }
        !           427: 
        !           428:     /*
        !           429:      *  IF there is a disablement string
        !           430:      *  THEN print the disablement info
        !           431:      */
        !           432:     if (pOD->pz_DisableName != NULL )
        !           433:         fprintf(option_usage_fp, zDis, pOD->pz_DisableName);
        !           434: 
        !           435:     /*
        !           436:      *  Check for argument types that have callbacks with magical properties
        !           437:      */
        !           438:     switch (OPTST_GET_ARGTYPE(pOD->fOptState)) {
        !           439:     case OPARG_TYPE_NUMERIC:
        !           440:         /*
        !           441:          *  IF the numeric option has a special callback,
        !           442:          *  THEN call it, requesting the range or other special info
        !           443:          */
        !           444:         if (  (pOD->pOptProc != NULL)
        !           445:            && (pOD->pOptProc != optionNumericVal) ) {
        !           446:             (*(pOD->pOptProc))(OPTPROC_EMIT_USAGE, pOD);
        !           447:         }
        !           448:         break;
        !           449: 
        !           450:     case OPARG_TYPE_FILE:
        !           451:         (*(pOD->pOptProc))(OPTPROC_EMIT_USAGE, pOD);
        !           452:         break;
        !           453:     }
        !           454: 
        !           455:     /*
        !           456:      *  IF the option defaults to being enabled,
        !           457:      *  THEN print that out
        !           458:      */
        !           459:     if (pOD->fOptState & OPTST_INITENABLED)
        !           460:         fputs(zEnab, option_usage_fp);
        !           461: 
        !           462:     /*
        !           463:      *  IF  the option is in an equivalence class
        !           464:      *        AND not the designated lead
        !           465:      *  THEN print equivalence and leave it at that.
        !           466:      */
        !           467:     if (  (pOD->optEquivIndex != NO_EQUIVALENT)
        !           468:        && (pOD->optEquivIndex != pOD->optActualIndex )  )  {
        !           469:         fprintf(option_usage_fp, zAlt,
        !           470:                  pOptions->pOptDesc[ pOD->optEquivIndex ].pz_Name);
        !           471:         return;
        !           472:     }
        !           473: 
        !           474:     /*
        !           475:      *  IF this particular option can NOT be preset
        !           476:      *    AND some form of presetting IS allowed,
        !           477:      *    AND it is not an auto-managed option (e.g. --help, et al.)
        !           478:      *  THEN advise that this option may not be preset.
        !           479:      */
        !           480:     if (  ((pOD->fOptState & OPTST_NO_INIT) != 0)
        !           481:        && (  (pOptions->papzHomeList != NULL)
        !           482:           || (pOptions->pzPROGNAME != NULL)
        !           483:           )
        !           484:        && (pOD->optIndex < pOptions->presetOptCt)
        !           485:        )
        !           486: 
        !           487:         fputs(zNoPreset, option_usage_fp);
        !           488: 
        !           489:     /*
        !           490:      *  Print the appearance requirements.
        !           491:      */
        !           492:     if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP)
        !           493:         fputs(zMembers, option_usage_fp);
        !           494: 
        !           495:     else switch (pOD->optMinCt) {
        !           496:     case 1:
        !           497:     case 0:
        !           498:         switch (pOD->optMaxCt) {
        !           499:         case 0:       fputs(zPreset, option_usage_fp); break;
        !           500:         case NOLIMIT: fputs(zNoLim, option_usage_fp);  break;
        !           501:         case 1:       break;
        !           502:             /*
        !           503:              * IF the max is more than one but limited, print "UP TO" message
        !           504:              */
        !           505:         default:      fprintf(option_usage_fp, zUpTo, pOD->optMaxCt);  break;
        !           506:         }
        !           507:         break;
        !           508: 
        !           509:     default:
        !           510:         /*
        !           511:          *  More than one is required.  Print the range.
        !           512:          */
        !           513:         fprintf(option_usage_fp, zMust, pOD->optMinCt, pOD->optMaxCt);
        !           514:     }
        !           515: 
        !           516:     if (  NAMED_OPTS(pOptions)
        !           517:        && (pOptions->specOptIdx.default_opt == pOD->optIndex))
        !           518:         fputs(zDefaultOpt, option_usage_fp);
        !           519: }
        !           520: 
        !           521: 
        !           522: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
        !           523:  *
        !           524:  *   Figure out where all the initialization files might live.
        !           525:  *   This requires translating some environment variables and
        !           526:  *   testing to see if a name is a directory or a file.  It's
        !           527:  *   squishy, but important to tell users how to find these files.
        !           528:  */
        !           529: static void
        !           530: prt_ini_list(char const * const * papz, ag_bool * pInitIntro,
        !           531:              char const * pzRc, char const * pzPN)
        !           532: {
        !           533:     char zPath[AG_PATH_MAX+1];
        !           534: 
        !           535:     if (papz == NULL)
        !           536:         return;
        !           537: 
        !           538:     fputs(zPresetIntro, option_usage_fp);
        !           539:     *pInitIntro = AG_FALSE;
        !           540: 
        !           541:     for (;;) {
        !           542:         char const * pzPath = *(papz++);
        !           543:         char const * pzReal = zPath;
        !           544: 
        !           545:         if (pzPath == NULL)
        !           546:             break;
        !           547: 
        !           548:         /*
        !           549:          * Ignore any invalid paths
        !           550:          */
        !           551:         if (! optionMakePath(zPath, (int)sizeof(zPath), pzPath, pzPN))
        !           552:             pzReal = pzPath;
        !           553: 
        !           554:         /*
        !           555:          * Expand paths that are relative to the executable or installation
        !           556:          * directories.  Leave alone paths that use environment variables.
        !           557:          */
        !           558:         else if ((*pzPath == '$')
        !           559:                  && ((pzPath[1] == '$') || (pzPath[1] == '@')))
        !           560:             pzPath = pzReal;
        !           561: 
        !           562:         /*
        !           563:          *  Print the name of the "homerc" file.  If the "rcfile" name is
        !           564:          *  not empty, we may or may not print that, too...
        !           565:          */
        !           566:         fprintf(option_usage_fp, zPathFmt, pzPath);
        !           567:         if (*pzRc != NUL) {
        !           568:             struct stat sb;
        !           569: 
        !           570:             /*
        !           571:              *  IF the "homerc" file is a directory,
        !           572:              *  then append the "rcfile" name.
        !           573:              */
        !           574:             if ((stat(pzReal, &sb) == 0) && S_ISDIR(sb.st_mode)) {
        !           575:                 fputc(DIRCH, option_usage_fp);
        !           576:                 fputs(pzRc,  option_usage_fp);
        !           577:             }
        !           578:         }
        !           579: 
        !           580:         fputc('\n', option_usage_fp);
        !           581:     }
        !           582: }
        !           583: 
        !           584: 
        !           585: static void
        !           586: prt_preamble(tOptions * pOptions, tOptDesc * pOD, arg_types_t * pAT)
        !           587: {
        !           588:     /*
        !           589:      *  Flag prefix: IF no flags at all, then omit it.  If not printable
        !           590:      *  (not allowed for this option), then blank, else print it.
        !           591:      *  Follow it with a comma if we are doing GNU usage and long
        !           592:      *  opts are to be printed too.
        !           593:      */
        !           594:     if ((pOptions->fOptSet & OPTPROC_SHORTOPT) == 0)
        !           595:         fputs(pAT->pzSpc, option_usage_fp);
        !           596: 
        !           597:     else if (! IS_GRAPHIC_CHAR(pOD->optValue)) {
        !           598:         if (  (pOptions->fOptSet & (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
        !           599:            == (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
        !           600:             fputc(' ', option_usage_fp);
        !           601:         fputs(pAT->pzNoF, option_usage_fp);
        !           602: 
        !           603:     } else {
        !           604:         fprintf(option_usage_fp, "   -%c", pOD->optValue);
        !           605:         if (  (pOptions->fOptSet & (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
        !           606:            == (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
        !           607:             fputs(", ", option_usage_fp);
        !           608:     }
        !           609: }
        !           610: 
        !           611: /*
        !           612:  *  Print the usage information for a single option.
        !           613:  */
        !           614: static void
        !           615: prt_one_usage(tOptions * pOptions, tOptDesc * pOD, arg_types_t * pAT)
        !           616: {
        !           617:     prt_preamble(pOptions, pOD, pAT);
        !           618: 
        !           619:     {
        !           620:         char z[ 80 ];
        !           621:         char const *  pzArgType;
        !           622: 
        !           623:         /*
        !           624:          *  Determine the argument type string first on its usage, then,
        !           625:          *  when the option argument is required, base the type string on the
        !           626:          *  argument type.
        !           627:          */
        !           628:         if (pOD->fOptState & OPTST_ARG_OPTIONAL) {
        !           629:             pzArgType = pAT->pzOpt;
        !           630: 
        !           631:         } else switch (OPTST_GET_ARGTYPE(pOD->fOptState)) {
        !           632:         case OPARG_TYPE_NONE:        pzArgType = pAT->pzNo;   break;
        !           633:         case OPARG_TYPE_ENUMERATION: pzArgType = pAT->pzKey;  break;
        !           634:         case OPARG_TYPE_FILE:        pzArgType = pAT->pzFile; break;
        !           635:         case OPARG_TYPE_MEMBERSHIP:  pzArgType = pAT->pzKeyL; break;
        !           636:         case OPARG_TYPE_BOOLEAN:     pzArgType = pAT->pzBool; break;
        !           637:         case OPARG_TYPE_NUMERIC:     pzArgType = pAT->pzNum;  break;
        !           638:         case OPARG_TYPE_HIERARCHY:   pzArgType = pAT->pzNest; break;
        !           639:         case OPARG_TYPE_STRING:      pzArgType = pAT->pzStr;  break;
        !           640:         case OPARG_TYPE_TIME:        pzArgType = pAT->pzTime; break;
        !           641:         default:                     goto bogus_desc;
        !           642:         }
        !           643: 
        !           644:         snprintf(z, sizeof(z), pAT->pzOptFmt, pzArgType, pOD->pz_Name,
        !           645:                  (pOD->optMinCt != 0) ? pAT->pzReq : pAT->pzOpt);
        !           646: 
        !           647:         fprintf(option_usage_fp, zOptFmtLine, z, pOD->pzText);
        !           648: 
        !           649:         switch (OPTST_GET_ARGTYPE(pOD->fOptState)) {
        !           650:         case OPARG_TYPE_ENUMERATION:
        !           651:         case OPARG_TYPE_MEMBERSHIP:
        !           652:             displayEnum = (pOD->pOptProc != NULL) ? AG_TRUE : displayEnum;
        !           653:         }
        !           654:     }
        !           655:     return;
        !           656: 
        !           657:  bogus_desc:
        !           658:     fprintf(stderr, zInvalOptDesc, pOD->pz_Name);
        !           659:     exit(EX_SOFTWARE);
        !           660: }
        !           661: 
        !           662: 
        !           663: /*
        !           664:  *  Print out the usage information for just the options.
        !           665:  */
        !           666: static void
        !           667: prt_opt_usage(tOptions * pOpts, int ex_code, char const * pOptTitle)
        !           668: {
        !           669:     int         ct     = pOpts->optCt;
        !           670:     int         optNo  = 0;
        !           671:     tOptDesc *  pOD    = pOpts->pOptDesc;
        !           672:     int         docCt  = 0;
        !           673: 
        !           674:     do  {
        !           675:         if ((pOD->fOptState & OPTST_NO_USAGE_MASK) != 0) {
        !           676: 
        !           677:             /*
        !           678:              * IF      this is a compiled-out option
        !           679:              *   *AND* usage was requested with "omitted-usage"
        !           680:              *   *AND* this is NOT abbreviated usage
        !           681:              * THEN display this option.
        !           682:              */
        !           683:             if (  (pOD->fOptState == (OPTST_OMITTED | OPTST_NO_INIT))
        !           684:                && (pOD->pz_Name != NULL)
        !           685:                && (ex_code == EXIT_SUCCESS))  {
        !           686: 
        !           687:                 char const * why_pz =
        !           688:                     (pOD->pzText == NULL) ? zDisabledWhy : pOD->pzText;
        !           689:                 prt_preamble(pOpts, pOD, &argTypes);
        !           690:                 fprintf(option_usage_fp, zDisabledOpt, pOD->pz_Name, why_pz);
        !           691:             }
        !           692: 
        !           693:             continue;
        !           694:         }
        !           695: 
        !           696:         if ((pOD->fOptState & OPTST_DOCUMENT) != 0) {
        !           697:             if (ex_code == EXIT_SUCCESS) {
        !           698:                 fprintf(option_usage_fp, argTypes.pzBrk, pOD->pzText,
        !           699:                         pOptTitle);
        !           700:                 docCt++;
        !           701:             }
        !           702: 
        !           703:             continue;
        !           704:         }
        !           705: 
        !           706:         /*
        !           707:          *  IF       this is the first auto-opt maintained option
        !           708:          *    *AND*  we are doing a full help
        !           709:          *    *AND*  there are documentation options
        !           710:          *    *AND*  the last one was not a doc option,
        !           711:          *  THEN document that the remaining options are not user opts
        !           712:          */
        !           713:         if (  (pOpts->presetOptCt == optNo)
        !           714:            && (ex_code == EXIT_SUCCESS)
        !           715:            && (docCt > 0)
        !           716:            && ((pOD[-1].fOptState & OPTST_DOCUMENT) == 0) )
        !           717:             fprintf(option_usage_fp, argTypes.pzBrk, zAuto, pOptTitle);
        !           718: 
        !           719:         prt_one_usage(pOpts, pOD, &argTypes);
        !           720: 
        !           721:         /*
        !           722:          *  IF we were invoked because of the --help option,
        !           723:          *  THEN print all the extra info
        !           724:          */
        !           725:         if (ex_code == EXIT_SUCCESS)
        !           726:             prt_extd_usage(pOpts, pOD, &argTypes);
        !           727: 
        !           728:     }  while (pOD++, optNo++, (--ct > 0));
        !           729: 
        !           730:     fputc('\n', option_usage_fp);
        !           731: }
        !           732: 
        !           733: 
        !           734: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
        !           735:  *
        !           736:  *   PROGRAM DETAILS
        !           737:  */
        !           738: static void
        !           739: prt_prog_detail(tOptions* pOptions)
        !           740: {
        !           741:     ag_bool  initIntro = AG_TRUE;
        !           742: 
        !           743:     /*
        !           744:      *  Display all the places we look for config files
        !           745:      */
        !           746:     prt_ini_list(pOptions->papzHomeList, &initIntro,
        !           747:                  pOptions->pzRcName, pOptions->pzProgPath);
        !           748: 
        !           749:     /*
        !           750:      *  Let the user know about environment variable settings
        !           751:      */
        !           752:     if ((pOptions->fOptSet & OPTPROC_ENVIRON) != 0) {
        !           753:         if (initIntro)
        !           754:             fputs(zPresetIntro, option_usage_fp);
        !           755: 
        !           756:         fprintf(option_usage_fp, zExamineFmt, pOptions->pzPROGNAME);
        !           757:     }
        !           758: 
        !           759:     /*
        !           760:      *  IF we found an enumeration,
        !           761:      *  THEN hunt for it again.  Call the handler proc with a NULL
        !           762:      *       option struct pointer.  That tells it to display the keywords.
        !           763:      */
        !           764:     if (displayEnum) {
        !           765:         int        ct     = pOptions->optCt;
        !           766:         int        optNo  = 0;
        !           767:         tOptDesc*  pOD    = pOptions->pOptDesc;
        !           768: 
        !           769:         fputc('\n', option_usage_fp);
        !           770:         fflush(option_usage_fp);
        !           771:         do  {
        !           772:             switch (OPTST_GET_ARGTYPE(pOD->fOptState)) {
        !           773:             case OPARG_TYPE_ENUMERATION:
        !           774:             case OPARG_TYPE_MEMBERSHIP:
        !           775:                 (*(pOD->pOptProc))(OPTPROC_EMIT_USAGE, pOD);
        !           776:             }
        !           777:         }  while (pOD++, optNo++, (--ct > 0));
        !           778:     }
        !           779: 
        !           780:     /*
        !           781:      *  If there is a detail string, now is the time for that.
        !           782:      */
        !           783:     if (pOptions->pzDetail != NULL)
        !           784:         fputs(pOptions->pzDetail, option_usage_fp);
        !           785: }
        !           786: 
        !           787: 
        !           788: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
        !           789:  *
        !           790:  *   OPTION LINE FORMATTING SETUP
        !           791:  *
        !           792:  *  The "OptFmt" formats receive three arguments:
        !           793:  *  1.  the type of the option's argument
        !           794:  *  2.  the long name of the option
        !           795:  *  3.  "YES" or "no ", depending on whether or not the option must appear
        !           796:  *      on the command line.
        !           797:  *  These formats are used immediately after the option flag (if used) has
        !           798:  *  been printed.
        !           799:  *
        !           800:  *  Set up the formatting for GNU-style output
        !           801:  */
        !           802: static int
        !           803: setGnuOptFmts(tOptions* pOpts, tCC** ppT)
        !           804: {
        !           805:     int  flen = 22;
        !           806:     *ppT = zNoRq_ShrtTtl;
        !           807: 
        !           808:     argTypes.pzStr  = zGnuStrArg;
        !           809:     argTypes.pzReq  = zOneSpace;
        !           810:     argTypes.pzNum  = zGnuNumArg;
        !           811:     argTypes.pzKey  = zGnuKeyArg;
        !           812:     argTypes.pzKeyL = zGnuKeyLArg;
        !           813:     argTypes.pzTime = zGnuTimeArg;
        !           814:     argTypes.pzFile = zGnuFileArg;
        !           815:     argTypes.pzBool = zGnuBoolArg;
        !           816:     argTypes.pzNest = zGnuNestArg;
        !           817:     argTypes.pzOpt  = zGnuOptArg;
        !           818:     argTypes.pzNo   = zOneSpace;
        !           819:     argTypes.pzBrk  = zGnuBreak;
        !           820:     argTypes.pzNoF  = zSixSpaces;
        !           821:     argTypes.pzSpc  = zThreeSpaces;
        !           822: 
        !           823:     switch (pOpts->fOptSet & OPTPROC_L_N_S) {
        !           824:     case OPTPROC_L_N_S:    argTypes.pzOptFmt = zGnuOptFmt;     break;
        !           825:     case OPTPROC_LONGOPT:  argTypes.pzOptFmt = zGnuOptFmt;     break;
        !           826:     case 0:                argTypes.pzOptFmt = zGnuOptFmt + 2; break;
        !           827:     case OPTPROC_SHORTOPT:
        !           828:         argTypes.pzOptFmt = zShrtGnuOptFmt;
        !           829:         zGnuStrArg[0] = zGnuNumArg[0] = zGnuKeyArg[0] = zGnuBoolArg[0] = ' ';
        !           830:         argTypes.pzOpt = " [arg]";
        !           831:         flen = 8;
        !           832:         break;
        !           833:     }
        !           834: 
        !           835:     return flen;
        !           836: }
        !           837: 
        !           838: 
        !           839: /*
        !           840:  *  Standard (AutoOpts normal) option line formatting
        !           841:  */
        !           842: static int
        !           843: setStdOptFmts(tOptions* pOpts, tCC** ppT)
        !           844: {
        !           845:     int  flen = 0;
        !           846: 
        !           847:     argTypes.pzStr  = zStdStrArg;
        !           848:     argTypes.pzReq  = zStdReqArg;
        !           849:     argTypes.pzNum  = zStdNumArg;
        !           850:     argTypes.pzKey  = zStdKeyArg;
        !           851:     argTypes.pzKeyL = zStdKeyLArg;
        !           852:     argTypes.pzTime = zStdTimeArg;
        !           853:     argTypes.pzFile = zStdFileArg;
        !           854:     argTypes.pzBool = zStdBoolArg;
        !           855:     argTypes.pzNest = zStdNestArg;
        !           856:     argTypes.pzOpt  = zStdOptArg;
        !           857:     argTypes.pzNo   = zStdNoArg;
        !           858:     argTypes.pzBrk  = zStdBreak;
        !           859:     argTypes.pzNoF  = zFiveSpaces;
        !           860:     argTypes.pzSpc  = zTwoSpaces;
        !           861: 
        !           862:     switch (pOpts->fOptSet & (OPTPROC_NO_REQ_OPT | OPTPROC_SHORTOPT)) {
        !           863:     case (OPTPROC_NO_REQ_OPT | OPTPROC_SHORTOPT):
        !           864:         *ppT = zNoRq_ShrtTtl;
        !           865:         argTypes.pzOptFmt = zNrmOptFmt;
        !           866:         flen = 19;
        !           867:         break;
        !           868: 
        !           869:     case OPTPROC_NO_REQ_OPT:
        !           870:         *ppT = zNoRq_NoShrtTtl;
        !           871:         argTypes.pzOptFmt = zNrmOptFmt;
        !           872:         flen = 19;
        !           873:         break;
        !           874: 
        !           875:     case OPTPROC_SHORTOPT:
        !           876:         *ppT = zReq_ShrtTtl;
        !           877:         argTypes.pzOptFmt = zReqOptFmt;
        !           878:         flen = 24;
        !           879:         break;
        !           880: 
        !           881:     case 0:
        !           882:         *ppT = zReq_NoShrtTtl;
        !           883:         argTypes.pzOptFmt = zReqOptFmt;
        !           884:         flen = 24;
        !           885:     }
        !           886: 
        !           887:     return flen;
        !           888: }
        !           889: 
        !           890: 
        !           891: /*:
        !           892:  * Local Variables:
        !           893:  * mode: C
        !           894:  * c-file-style: "stroustrup"
        !           895:  * indent-tabs-mode: nil
        !           896:  * End:
        !           897:  * end of autoopts/usage.c */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>