Annotation of embedaddon/ntp/sntp/libopts/usage.c, revision 1.1.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>