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