Return to usage.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / sntp / libopts |
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 */