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>