1181834Sroberto 2181834Sroberto/* 3181834Sroberto * usage.c $Id: usage.c,v 4.15 2007/04/28 22:19:23 bkorb Exp $ 4181834Sroberto * Time-stamp: "2007-04-15 11:02:46 bkorb" 5181834Sroberto * 6181834Sroberto * This module implements the default usage procedure for 7181834Sroberto * Automated Options. It may be overridden, of course. 8181834Sroberto * 9181834Sroberto * Sort options: 10181834Sroberto --start=END-[S]TATIC-FORWARD --patt='^/\*($|[^:])' \ 11181834Sroberto --out=xx.c key='^[a-zA-Z0-9_]+\(' --trail='^/\*:' \ 12181834Sroberto --spac=2 --input=usage.c 13181834Sroberto */ 14181834Sroberto 15181834Sroberto/* 16181834Sroberto * Automated Options copyright 1992-2007 Bruce Korb 17181834Sroberto * 18181834Sroberto * Automated Options is free software. 19181834Sroberto * You may redistribute it and/or modify it under the terms of the 20181834Sroberto * GNU General Public License, as published by the Free Software 21181834Sroberto * Foundation; either version 2, or (at your option) any later version. 22181834Sroberto * 23181834Sroberto * Automated Options is distributed in the hope that it will be useful, 24181834Sroberto * but WITHOUT ANY WARRANTY; without even the implied warranty of 25181834Sroberto * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26181834Sroberto * GNU General Public License for more details. 27181834Sroberto * 28181834Sroberto * You should have received a copy of the GNU General Public License 29181834Sroberto * along with Automated Options. See the file "COPYING". If not, 30181834Sroberto * write to: The Free Software Foundation, Inc., 31181834Sroberto * 51 Franklin Street, Fifth Floor, 32181834Sroberto * Boston, MA 02110-1301, USA. 33181834Sroberto * 34181834Sroberto * As a special exception, Bruce Korb gives permission for additional 35181834Sroberto * uses of the text contained in his release of AutoOpts. 36181834Sroberto * 37181834Sroberto * The exception is that, if you link the AutoOpts library with other 38181834Sroberto * files to produce an executable, this does not by itself cause the 39181834Sroberto * resulting executable to be covered by the GNU General Public License. 40181834Sroberto * Your use of that executable is in no way restricted on account of 41181834Sroberto * linking the AutoOpts library code into it. 42181834Sroberto * 43181834Sroberto * This exception does not however invalidate any other reasons why 44181834Sroberto * the executable file might be covered by the GNU General Public License. 45181834Sroberto * 46181834Sroberto * This exception applies only to the code released by Bruce Korb under 47181834Sroberto * the name AutoOpts. If you copy code from other sources under the 48181834Sroberto * General Public License into a copy of AutoOpts, as the General Public 49181834Sroberto * License permits, the exception does not apply to the code that you add 50181834Sroberto * in this way. To avoid misleading anyone as to the status of such 51181834Sroberto * modified files, you must delete this exception notice from them. 52181834Sroberto * 53181834Sroberto * If you write modifications of your own for AutoOpts, it is your choice 54181834Sroberto * whether to permit this exception to apply to your modifications. 55181834Sroberto * If you do not wish that, delete this exception notice. 56181834Sroberto */ 57181834Sroberto 58181834Sroberto#define OPTPROC_L_N_S (OPTPROC_LONGOPT | OPTPROC_SHORTOPT) 59181834Sroberto 60181834Srobertostatic arg_types_t argTypes; 61181834Sroberto 62181834SrobertoFILE* option_usage_fp = NULL; 63181834Srobertostatic char zOptFmtLine[ 16 ]; 64181834Srobertostatic ag_bool displayEnum; 65181834Sroberto 66181834Sroberto/* = = = START-STATIC-FORWARD = = = */ 67181834Sroberto/* static forward declarations maintained by :mkfwd */ 68181834Srobertostatic ag_bool 69181834SrobertocheckGNUUsage( tOptions* pOpts ); 70181834Sroberto 71181834Srobertostatic void 72181834SrobertoprintExtendedUsage( 73181834Sroberto tOptions* pOptions, 74181834Sroberto tOptDesc* pOD, 75181834Sroberto arg_types_t* pAT ); 76181834Sroberto 77181834Srobertostatic void 78181834SrobertoprintInitList( 79181834Sroberto tCC* const* papz, 80181834Sroberto ag_bool* pInitIntro, 81181834Sroberto tCC* pzRc, 82181834Sroberto tCC* pzPN ); 83181834Sroberto 84181834Srobertostatic void 85181834SrobertoprintOneUsage( 86181834Sroberto tOptions* pOptions, 87181834Sroberto tOptDesc* pOD, 88181834Sroberto arg_types_t* pAT ); 89181834Sroberto 90181834Srobertostatic void 91181834SrobertoprintOptionUsage( 92181834Sroberto tOptions* pOpts, 93181834Sroberto int ex_code, 94181834Sroberto tCC* pOptTitle ); 95181834Sroberto 96181834Srobertostatic void 97181834SrobertoprintProgramDetails( tOptions* pOptions ); 98181834Sroberto 99181834Srobertostatic int 100181834SrobertosetGnuOptFmts( tOptions* pOpts, tCC** ppT ); 101181834Sroberto 102181834Srobertostatic int 103181834SrobertosetStdOptFmts( tOptions* pOpts, tCC** ppT ); 104181834Sroberto/* = = = END-STATIC-FORWARD = = = */ 105181834Sroberto 106181834Sroberto 107181834Sroberto/* 108181834Sroberto * Figure out if we should try to format usage text sort-of like 109181834Sroberto * the way many GNU programs do. 110181834Sroberto */ 111181834Srobertostatic ag_bool 112181834SrobertocheckGNUUsage( tOptions* pOpts ) 113181834Sroberto{ 114181834Sroberto char* pz = getenv( "AUTOOPTS_USAGE" ); 115181834Sroberto if (pz == NULL) 116181834Sroberto ; 117181834Sroberto 118181834Sroberto else if (streqvcmp( pz, "gnu" ) == 0) 119181834Sroberto pOpts->fOptSet |= OPTPROC_GNUUSAGE; 120181834Sroberto 121181834Sroberto else if (streqvcmp( pz, "autoopts" ) == 0) 122181834Sroberto pOpts->fOptSet &= ~OPTPROC_GNUUSAGE; 123181834Sroberto 124181834Sroberto return (pOpts->fOptSet & OPTPROC_GNUUSAGE) ? AG_TRUE : AG_FALSE; 125181834Sroberto} 126181834Sroberto 127181834Sroberto 128181834Sroberto/*=export_func optionOnlyUsage 129181834Sroberto * 130181834Sroberto * what: Print usage text for just the options 131181834Sroberto * arg: + tOptions* + pOpts + program options descriptor + 132181834Sroberto * arg: + int + ex_code + exit code for calling exit(3) + 133181834Sroberto * 134181834Sroberto * doc: 135181834Sroberto * This routine will print only the usage for each option. 136181834Sroberto * This function may be used when the emitted usage must incorporate 137181834Sroberto * information not available to AutoOpts. 138181834Sroberto=*/ 139181834Srobertovoid 140181834SrobertooptionOnlyUsage( 141181834Sroberto tOptions* pOpts, 142181834Sroberto int ex_code ) 143181834Sroberto{ 144181834Sroberto tCC* pOptTitle = NULL; 145181834Sroberto 146181834Sroberto /* 147181834Sroberto * Determine which header and which option formatting strings to use 148181834Sroberto */ 149181834Sroberto if (checkGNUUsage(pOpts)) { 150181834Sroberto (void)setGnuOptFmts( pOpts, &pOptTitle ); 151181834Sroberto } 152181834Sroberto else { 153181834Sroberto (void)setStdOptFmts( pOpts, &pOptTitle ); 154181834Sroberto } 155181834Sroberto 156181834Sroberto printOptionUsage( pOpts, ex_code, pOptTitle ); 157181834Sroberto} 158181834Sroberto 159181834Sroberto 160181834Sroberto/*=export_func optionUsage 161181834Sroberto * private: 162181834Sroberto * 163181834Sroberto * what: Print usage text 164181834Sroberto * arg: + tOptions* + pOptions + program options descriptor + 165181834Sroberto * arg: + int + exitCode + exit code for calling exit(3) + 166181834Sroberto * 167181834Sroberto * doc: 168181834Sroberto * This routine will print usage in both GNU-standard and AutoOpts-expanded 169181834Sroberto * formats. The descriptor specifies the default, but AUTOOPTS_USAGE will 170181834Sroberto * over-ride this, providing the value of it is set to either "gnu" or 171181834Sroberto * "autoopts". This routine will @strong{not} return. 172181834Sroberto * 173181834Sroberto * If "exitCode" is "EX_USAGE" (normally 64), then output will to to stdout 174181834Sroberto * and the actual exit code will be "EXIT_SUCCESS". 175181834Sroberto=*/ 176181834Srobertovoid 177181834SrobertooptionUsage( 178181834Sroberto tOptions* pOptions, 179181834Sroberto int usage_exit_code ) 180181834Sroberto{ 181181834Sroberto int actual_exit_code = 182181834Sroberto (usage_exit_code == EX_USAGE) ? EXIT_SUCCESS : usage_exit_code; 183181834Sroberto 184181834Sroberto displayEnum = AG_FALSE; 185181834Sroberto 186181834Sroberto /* 187181834Sroberto * Paged usage will preset option_usage_fp to an output file. 188181834Sroberto * If it hasn't already been set, then set it to standard output 189181834Sroberto * on successful exit (help was requested), otherwise error out. 190181834Sroberto */ 191181834Sroberto if (option_usage_fp == NULL) 192181834Sroberto option_usage_fp = (actual_exit_code != EXIT_SUCCESS) ? stderr : stdout; 193181834Sroberto 194181834Sroberto fprintf( option_usage_fp, pOptions->pzUsageTitle, pOptions->pzProgName ); 195181834Sroberto 196181834Sroberto { 197181834Sroberto tCC* pOptTitle = NULL; 198181834Sroberto 199181834Sroberto /* 200181834Sroberto * Determine which header and which option formatting strings to use 201181834Sroberto */ 202181834Sroberto if (checkGNUUsage(pOptions)) { 203181834Sroberto int flen = setGnuOptFmts( pOptions, &pOptTitle ); 204181834Sroberto sprintf( zOptFmtLine, zFmtFmt, flen ); 205181834Sroberto fputc( '\n', option_usage_fp ); 206181834Sroberto } 207181834Sroberto else { 208181834Sroberto int flen = setStdOptFmts( pOptions, &pOptTitle ); 209181834Sroberto sprintf( zOptFmtLine, zFmtFmt, flen ); 210181834Sroberto 211181834Sroberto /* 212181834Sroberto * When we exit with EXIT_SUCCESS and the first option is a doc 213181834Sroberto * option, we do *NOT* want to emit the column headers. 214181834Sroberto * Otherwise, we do. 215181834Sroberto */ 216181834Sroberto if ( (usage_exit_code != EXIT_SUCCESS) 217181834Sroberto || ((pOptions->pOptDesc->fOptState & OPTST_DOCUMENT) == 0) ) 218181834Sroberto 219181834Sroberto fputs( pOptTitle, option_usage_fp ); 220181834Sroberto } 221181834Sroberto 222181834Sroberto printOptionUsage( pOptions, usage_exit_code, pOptTitle ); 223181834Sroberto } 224181834Sroberto 225181834Sroberto /* 226181834Sroberto * Describe the mechanics of denoting the options 227181834Sroberto */ 228181834Sroberto switch (pOptions->fOptSet & OPTPROC_L_N_S) { 229181834Sroberto case OPTPROC_L_N_S: fputs( zFlagOkay, option_usage_fp ); break; 230181834Sroberto case OPTPROC_SHORTOPT: break; 231181834Sroberto case OPTPROC_LONGOPT: fputs( zNoFlags, option_usage_fp ); break; 232181834Sroberto case 0: fputs( zOptsOnly, option_usage_fp ); break; 233181834Sroberto } 234181834Sroberto 235181834Sroberto if ((pOptions->fOptSet & OPTPROC_NUM_OPT) != 0) { 236181834Sroberto fputs( zNumberOpt, option_usage_fp ); 237181834Sroberto } 238181834Sroberto 239181834Sroberto if ((pOptions->fOptSet & OPTPROC_REORDER) != 0) { 240181834Sroberto fputs( zReorder, option_usage_fp ); 241181834Sroberto } 242181834Sroberto 243181834Sroberto if (pOptions->pzExplain != NULL) 244181834Sroberto fputs( pOptions->pzExplain, option_usage_fp ); 245181834Sroberto 246181834Sroberto /* 247181834Sroberto * IF the user is asking for help (thus exiting with SUCCESS), 248181834Sroberto * THEN see what additional information we can provide. 249181834Sroberto */ 250181834Sroberto if (usage_exit_code == EXIT_SUCCESS) 251181834Sroberto printProgramDetails( pOptions ); 252181834Sroberto 253181834Sroberto if (pOptions->pzBugAddr != NULL) 254181834Sroberto fprintf( option_usage_fp, zPlsSendBugs, pOptions->pzBugAddr ); 255181834Sroberto fflush( option_usage_fp ); 256181834Sroberto 257181834Sroberto exit( actual_exit_code ); 258181834Sroberto} 259181834Sroberto 260181834Sroberto 261181834Sroberto/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 262181834Sroberto * 263181834Sroberto * PER OPTION TYPE USAGE INFORMATION 264181834Sroberto */ 265181834Srobertostatic void 266181834SrobertoprintExtendedUsage( 267181834Sroberto tOptions* pOptions, 268181834Sroberto tOptDesc* pOD, 269181834Sroberto arg_types_t* pAT ) 270181834Sroberto{ 271181834Sroberto /* 272181834Sroberto * IF there are option conflicts or dependencies, 273181834Sroberto * THEN print them here. 274181834Sroberto */ 275181834Sroberto if ( (pOD->pOptMust != NULL) 276181834Sroberto || (pOD->pOptCant != NULL) ) { 277181834Sroberto 278181834Sroberto fputs( zTabHyp, option_usage_fp ); 279181834Sroberto 280181834Sroberto /* 281181834Sroberto * DEPENDENCIES: 282181834Sroberto */ 283181834Sroberto if (pOD->pOptMust != NULL) { 284181834Sroberto const int* pOptNo = pOD->pOptMust; 285181834Sroberto 286181834Sroberto fputs( zReqThese, option_usage_fp ); 287181834Sroberto for (;;) { 288181834Sroberto fprintf( option_usage_fp, zTabout, pOptions->pOptDesc[ 289181834Sroberto *pOptNo ].pz_Name ); 290181834Sroberto if (*++pOptNo == NO_EQUIVALENT) 291181834Sroberto break; 292181834Sroberto } 293181834Sroberto 294181834Sroberto if (pOD->pOptCant != NULL) 295181834Sroberto fputs( zTabHypAnd, option_usage_fp ); 296181834Sroberto } 297181834Sroberto 298181834Sroberto /* 299181834Sroberto * CONFLICTS: 300181834Sroberto */ 301181834Sroberto if (pOD->pOptCant != NULL) { 302181834Sroberto const int* pOptNo = pOD->pOptCant; 303181834Sroberto 304181834Sroberto fputs( zProhib, option_usage_fp ); 305181834Sroberto for (;;) { 306181834Sroberto fprintf( option_usage_fp, zTabout, pOptions->pOptDesc[ 307181834Sroberto *pOptNo ].pz_Name ); 308181834Sroberto if (*++pOptNo == NO_EQUIVALENT) 309181834Sroberto break; 310181834Sroberto } 311181834Sroberto } 312181834Sroberto } 313181834Sroberto 314181834Sroberto /* 315181834Sroberto * IF there is a disablement string 316181834Sroberto * THEN print the disablement info 317181834Sroberto */ 318181834Sroberto if (pOD->pz_DisableName != NULL ) 319181834Sroberto fprintf( option_usage_fp, zDis, pOD->pz_DisableName ); 320181834Sroberto 321181834Sroberto /* 322181834Sroberto * IF the numeric option has a special callback, 323181834Sroberto * THEN call it, requesting the range or other special info 324181834Sroberto */ 325181834Sroberto if ( (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_NUMERIC) 326181834Sroberto && (pOD->pOptProc != NULL) 327181834Sroberto && (pOD->pOptProc != optionNumericVal) ) { 328181834Sroberto (*(pOD->pOptProc))( pOptions, NULL ); 329181834Sroberto } 330181834Sroberto 331181834Sroberto /* 332181834Sroberto * IF the option defaults to being enabled, 333181834Sroberto * THEN print that out 334181834Sroberto */ 335181834Sroberto if (pOD->fOptState & OPTST_INITENABLED) 336181834Sroberto fputs( zEnab, option_usage_fp ); 337181834Sroberto 338181834Sroberto /* 339181834Sroberto * IF the option is in an equivalence class 340181834Sroberto * AND not the designated lead 341181834Sroberto * THEN print equivalence and leave it at that. 342181834Sroberto */ 343181834Sroberto if ( (pOD->optEquivIndex != NO_EQUIVALENT) 344181834Sroberto && (pOD->optEquivIndex != pOD->optActualIndex ) ) { 345181834Sroberto fprintf( option_usage_fp, zAlt, 346181834Sroberto pOptions->pOptDesc[ pOD->optEquivIndex ].pz_Name ); 347181834Sroberto return; 348181834Sroberto } 349181834Sroberto 350181834Sroberto /* 351181834Sroberto * IF this particular option can NOT be preset 352181834Sroberto * AND some form of presetting IS allowed, 353181834Sroberto * AND it is not an auto-managed option (e.g. --help, et al.) 354181834Sroberto * THEN advise that this option may not be preset. 355181834Sroberto */ 356181834Sroberto if ( ((pOD->fOptState & OPTST_NO_INIT) != 0) 357181834Sroberto && ( (pOptions->papzHomeList != NULL) 358181834Sroberto || (pOptions->pzPROGNAME != NULL) 359181834Sroberto ) 360181834Sroberto && (pOD->optIndex < pOptions->presetOptCt) 361181834Sroberto ) 362181834Sroberto 363181834Sroberto fputs( zNoPreset, option_usage_fp ); 364181834Sroberto 365181834Sroberto /* 366181834Sroberto * Print the appearance requirements. 367181834Sroberto */ 368181834Sroberto if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP) 369181834Sroberto fputs( zMembers, option_usage_fp ); 370181834Sroberto 371181834Sroberto else switch (pOD->optMinCt) { 372181834Sroberto case 1: 373181834Sroberto case 0: 374181834Sroberto switch (pOD->optMaxCt) { 375181834Sroberto case 0: fputs( zPreset, option_usage_fp ); break; 376181834Sroberto case NOLIMIT: fputs( zNoLim, option_usage_fp ); break; 377181834Sroberto case 1: break; 378181834Sroberto /* 379181834Sroberto * IF the max is more than one but limited, print "UP TO" message 380181834Sroberto */ 381181834Sroberto default: fprintf( option_usage_fp, zUpTo, pOD->optMaxCt ); break; 382181834Sroberto } 383181834Sroberto break; 384181834Sroberto 385181834Sroberto default: 386181834Sroberto /* 387181834Sroberto * More than one is required. Print the range. 388181834Sroberto */ 389181834Sroberto fprintf( option_usage_fp, zMust, pOD->optMinCt, pOD->optMaxCt ); 390181834Sroberto } 391181834Sroberto 392181834Sroberto if ( NAMED_OPTS( pOptions ) 393181834Sroberto && (pOptions->specOptIdx.default_opt == pOD->optIndex)) 394181834Sroberto fputs( zDefaultOpt, option_usage_fp ); 395181834Sroberto} 396181834Sroberto 397181834Sroberto 398181834Sroberto/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 399181834Sroberto * 400181834Sroberto * Figure out where all the initialization files might live. 401181834Sroberto * This requires translating some environment variables and 402181834Sroberto * testing to see if a name is a directory or a file. It's 403181834Sroberto * squishy, but important to tell users how to find these files. 404181834Sroberto */ 405181834Srobertostatic void 406181834SrobertoprintInitList( 407181834Sroberto tCC* const* papz, 408181834Sroberto ag_bool* pInitIntro, 409181834Sroberto tCC* pzRc, 410181834Sroberto tCC* pzPN ) 411181834Sroberto{ 412181834Sroberto char zPath[ AG_PATH_MAX+1 ]; 413181834Sroberto 414181834Sroberto if (papz == NULL) 415181834Sroberto return; 416181834Sroberto 417181834Sroberto fputs( zPresetIntro, option_usage_fp ); 418181834Sroberto *pInitIntro = AG_FALSE; 419181834Sroberto 420181834Sroberto for (;;) { 421181834Sroberto char const* pzPath = *(papz++); 422181834Sroberto 423181834Sroberto if (pzPath == NULL) 424181834Sroberto break; 425181834Sroberto 426181834Sroberto if (optionMakePath(zPath, (int)sizeof( zPath ), pzPath, pzPN)) 427181834Sroberto pzPath = zPath; 428181834Sroberto 429181834Sroberto /* 430181834Sroberto * Print the name of the "homerc" file. If the "rcfile" name is 431181834Sroberto * not empty, we may or may not print that, too... 432181834Sroberto */ 433181834Sroberto fprintf( option_usage_fp, zPathFmt, pzPath ); 434181834Sroberto if (*pzRc != NUL) { 435181834Sroberto struct stat sb; 436181834Sroberto 437181834Sroberto /* 438181834Sroberto * IF the "homerc" file is a directory, 439181834Sroberto * then append the "rcfile" name. 440181834Sroberto */ 441181834Sroberto if ( (stat( pzPath, &sb ) == 0) 442181834Sroberto && S_ISDIR( sb.st_mode ) ) { 443181834Sroberto fputc( DIRCH, option_usage_fp ); 444181834Sroberto fputs( pzRc, option_usage_fp ); 445181834Sroberto } 446181834Sroberto } 447181834Sroberto 448181834Sroberto fputc( '\n', option_usage_fp ); 449181834Sroberto } 450181834Sroberto} 451181834Sroberto 452181834Sroberto 453181834Sroberto/* 454181834Sroberto * Print the usage information for a single option. 455181834Sroberto */ 456181834Srobertostatic void 457181834SrobertoprintOneUsage( 458181834Sroberto tOptions* pOptions, 459181834Sroberto tOptDesc* pOD, 460181834Sroberto arg_types_t* pAT ) 461181834Sroberto{ 462181834Sroberto /* 463181834Sroberto * Flag prefix: IF no flags at all, then omit it. If not printable 464181834Sroberto * (not allowed for this option), then blank, else print it. 465181834Sroberto * Follow it with a comma if we are doing GNU usage and long 466181834Sroberto * opts are to be printed too. 467181834Sroberto */ 468181834Sroberto if ((pOptions->fOptSet & OPTPROC_SHORTOPT) == 0) 469181834Sroberto fputs( pAT->pzSpc, option_usage_fp ); 470181834Sroberto else if (! isgraph( pOD->optValue)) { 471181834Sroberto if ( (pOptions->fOptSet & (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT)) 472181834Sroberto == (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT)) 473181834Sroberto fputc( ' ', option_usage_fp ); 474181834Sroberto fputs( pAT->pzNoF, option_usage_fp ); 475181834Sroberto } else { 476181834Sroberto fprintf( option_usage_fp, " -%c", pOD->optValue ); 477181834Sroberto if ( (pOptions->fOptSet & (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT)) 478181834Sroberto == (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT)) 479181834Sroberto fputs( ", ", option_usage_fp ); 480181834Sroberto } 481181834Sroberto 482181834Sroberto { 483181834Sroberto char z[ 80 ]; 484181834Sroberto tCC* pzArgType; 485181834Sroberto /* 486181834Sroberto * Determine the argument type string first on its usage, then, 487181834Sroberto * when the option argument is required, base the type string on the 488181834Sroberto * argument type. 489181834Sroberto */ 490181834Sroberto if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_NONE) { 491181834Sroberto pzArgType = pAT->pzNo; 492181834Sroberto 493181834Sroberto } else if (pOD->fOptState & OPTST_ARG_OPTIONAL) { 494181834Sroberto pzArgType = pAT->pzOpt; 495181834Sroberto 496181834Sroberto } else switch (OPTST_GET_ARGTYPE(pOD->fOptState)) { 497181834Sroberto case OPARG_TYPE_ENUMERATION: pzArgType = pAT->pzKey; break; 498181834Sroberto case OPARG_TYPE_MEMBERSHIP: pzArgType = pAT->pzKeyL; break; 499181834Sroberto case OPARG_TYPE_BOOLEAN: pzArgType = pAT->pzBool; break; 500181834Sroberto case OPARG_TYPE_NUMERIC: pzArgType = pAT->pzNum; break; 501181834Sroberto case OPARG_TYPE_HIERARCHY: pzArgType = pAT->pzNest; break; 502181834Sroberto case OPARG_TYPE_STRING: pzArgType = pAT->pzStr; break; 503181834Sroberto default: goto bogus_desc; break; 504181834Sroberto } 505181834Sroberto 506181834Sroberto snprintf( z, sizeof(z), pAT->pzOptFmt, pzArgType, pOD->pz_Name, 507181834Sroberto (pOD->optMinCt != 0) ? pAT->pzReq : pAT->pzOpt ); 508181834Sroberto 509181834Sroberto fprintf( option_usage_fp, zOptFmtLine, z, pOD->pzText ); 510181834Sroberto 511181834Sroberto switch (OPTST_GET_ARGTYPE(pOD->fOptState)) { 512181834Sroberto case OPARG_TYPE_ENUMERATION: 513181834Sroberto case OPARG_TYPE_MEMBERSHIP: 514181834Sroberto displayEnum = (pOD->pOptProc != NULL) ? AG_TRUE : displayEnum; 515181834Sroberto } 516181834Sroberto } 517181834Sroberto return; 518181834Sroberto 519181834Sroberto bogus_desc: 520181834Sroberto fprintf( stderr, zInvalOptDesc, pOD->pz_Name ); 521181834Sroberto exit( EX_SOFTWARE ); 522181834Sroberto} 523181834Sroberto 524181834Sroberto 525181834Sroberto/* 526181834Sroberto * Print out the usage information for just the options. 527181834Sroberto */ 528181834Srobertostatic void 529181834SrobertoprintOptionUsage( 530181834Sroberto tOptions* pOpts, 531181834Sroberto int ex_code, 532181834Sroberto tCC* pOptTitle ) 533181834Sroberto{ 534181834Sroberto int ct = pOpts->optCt; 535181834Sroberto int optNo = 0; 536181834Sroberto tOptDesc* pOD = pOpts->pOptDesc; 537181834Sroberto int docCt = 0; 538181834Sroberto 539181834Sroberto do { 540181834Sroberto if ((pOD->fOptState & OPTST_OMITTED) != 0) 541181834Sroberto continue; 542181834Sroberto 543181834Sroberto if ((pOD->fOptState & OPTST_DOCUMENT) != 0) { 544181834Sroberto if (ex_code == EXIT_SUCCESS) { 545181834Sroberto fprintf(option_usage_fp, argTypes.pzBrk, pOD->pzText, 546181834Sroberto pOptTitle); 547181834Sroberto docCt++; 548181834Sroberto } 549181834Sroberto 550181834Sroberto continue; 551181834Sroberto } 552181834Sroberto 553181834Sroberto /* 554181834Sroberto * IF this is the first auto-opt maintained option 555181834Sroberto * *AND* we are doing a full help 556181834Sroberto * *AND* there are documentation options 557181834Sroberto * *AND* the last one was not a doc option, 558181834Sroberto * THEN document that the remaining options are not user opts 559181834Sroberto */ 560181834Sroberto if ( (pOpts->presetOptCt == optNo) 561181834Sroberto && (ex_code == EXIT_SUCCESS) 562181834Sroberto && (docCt > 0) 563181834Sroberto && ((pOD[-1].fOptState & OPTST_DOCUMENT) == 0) ) 564181834Sroberto fprintf( option_usage_fp, argTypes.pzBrk, zAuto, pOptTitle ); 565181834Sroberto 566181834Sroberto printOneUsage( pOpts, pOD, &argTypes ); 567181834Sroberto 568181834Sroberto /* 569181834Sroberto * IF we were invoked because of the --help option, 570181834Sroberto * THEN print all the extra info 571181834Sroberto */ 572181834Sroberto if (ex_code == EXIT_SUCCESS) 573181834Sroberto printExtendedUsage( pOpts, pOD, &argTypes ); 574181834Sroberto 575181834Sroberto } while (pOD++, optNo++, (--ct > 0)); 576181834Sroberto 577181834Sroberto fputc( '\n', option_usage_fp ); 578181834Sroberto} 579181834Sroberto 580181834Sroberto 581181834Sroberto/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 582181834Sroberto * 583181834Sroberto * PROGRAM DETAILS 584181834Sroberto */ 585181834Srobertostatic void 586181834SrobertoprintProgramDetails( tOptions* pOptions ) 587181834Sroberto{ 588181834Sroberto ag_bool initIntro = AG_TRUE; 589181834Sroberto 590181834Sroberto /* 591181834Sroberto * Display all the places we look for config files 592181834Sroberto */ 593181834Sroberto printInitList( pOptions->papzHomeList, &initIntro, 594181834Sroberto pOptions->pzRcName, pOptions->pzProgPath ); 595181834Sroberto 596181834Sroberto /* 597181834Sroberto * Let the user know about environment variable settings 598181834Sroberto */ 599181834Sroberto if ((pOptions->fOptSet & OPTPROC_ENVIRON) != 0) { 600181834Sroberto if (initIntro) 601181834Sroberto fputs( zPresetIntro, option_usage_fp ); 602181834Sroberto 603181834Sroberto fprintf( option_usage_fp, zExamineFmt, pOptions->pzPROGNAME ); 604181834Sroberto } 605181834Sroberto 606181834Sroberto /* 607181834Sroberto * IF we found an enumeration, 608181834Sroberto * THEN hunt for it again. Call the handler proc with a NULL 609181834Sroberto * option struct pointer. That tells it to display the keywords. 610181834Sroberto */ 611181834Sroberto if (displayEnum) { 612181834Sroberto int ct = pOptions->optCt; 613181834Sroberto int optNo = 0; 614181834Sroberto tOptDesc* pOD = pOptions->pOptDesc; 615181834Sroberto 616181834Sroberto fputc( '\n', option_usage_fp ); 617181834Sroberto fflush( option_usage_fp ); 618181834Sroberto do { 619181834Sroberto switch (OPTST_GET_ARGTYPE(pOD->fOptState)) { 620181834Sroberto case OPARG_TYPE_ENUMERATION: 621181834Sroberto case OPARG_TYPE_MEMBERSHIP: 622181834Sroberto (*(pOD->pOptProc))( NULL, pOD ); 623181834Sroberto } 624181834Sroberto } while (pOD++, optNo++, (--ct > 0)); 625181834Sroberto } 626181834Sroberto 627181834Sroberto /* 628181834Sroberto * If there is a detail string, now is the time for that. 629181834Sroberto */ 630181834Sroberto if (pOptions->pzDetail != NULL) 631181834Sroberto fputs( pOptions->pzDetail, option_usage_fp ); 632181834Sroberto} 633181834Sroberto 634181834Sroberto 635181834Sroberto/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 636181834Sroberto * 637181834Sroberto * OPTION LINE FORMATTING SETUP 638181834Sroberto * 639181834Sroberto * The "OptFmt" formats receive three arguments: 640181834Sroberto * 1. the type of the option's argument 641181834Sroberto * 2. the long name of the option 642181834Sroberto * 3. "YES" or "no ", depending on whether or not the option must appear 643181834Sroberto * on the command line. 644181834Sroberto * These formats are used immediately after the option flag (if used) has 645181834Sroberto * been printed. 646181834Sroberto * 647181834Sroberto * Set up the formatting for GNU-style output 648181834Sroberto */ 649181834Srobertostatic int 650181834SrobertosetGnuOptFmts( tOptions* pOpts, tCC** ppT ) 651181834Sroberto{ 652181834Sroberto int flen = 22; 653181834Sroberto *ppT = zNoRq_ShrtTtl; 654181834Sroberto 655181834Sroberto argTypes.pzStr = zGnuStrArg; 656181834Sroberto argTypes.pzReq = zOneSpace; 657181834Sroberto argTypes.pzNum = zGnuNumArg; 658181834Sroberto argTypes.pzKey = zGnuKeyArg; 659181834Sroberto argTypes.pzKeyL = zGnuKeyLArg; 660181834Sroberto argTypes.pzBool = zGnuBoolArg; 661181834Sroberto argTypes.pzNest = zGnuNestArg; 662181834Sroberto argTypes.pzOpt = zGnuOptArg; 663181834Sroberto argTypes.pzNo = zOneSpace; 664181834Sroberto argTypes.pzBrk = zGnuBreak; 665181834Sroberto argTypes.pzNoF = zSixSpaces; 666181834Sroberto argTypes.pzSpc = zThreeSpaces; 667181834Sroberto 668181834Sroberto switch (pOpts->fOptSet & OPTPROC_L_N_S) { 669181834Sroberto case OPTPROC_L_N_S: argTypes.pzOptFmt = zGnuOptFmt; break; 670181834Sroberto case OPTPROC_LONGOPT: argTypes.pzOptFmt = zGnuOptFmt; break; 671181834Sroberto case 0: argTypes.pzOptFmt = zGnuOptFmt + 2; break; 672181834Sroberto case OPTPROC_SHORTOPT: 673181834Sroberto argTypes.pzOptFmt = zShrtGnuOptFmt; 674181834Sroberto zGnuStrArg[0] = zGnuNumArg[0] = zGnuKeyArg[0] = zGnuBoolArg[0] = ' '; 675181834Sroberto argTypes.pzOpt = " [arg]"; 676181834Sroberto flen = 8; 677181834Sroberto break; 678181834Sroberto } 679181834Sroberto 680181834Sroberto return flen; 681181834Sroberto} 682181834Sroberto 683181834Sroberto 684181834Sroberto/* 685181834Sroberto * Standard (AutoOpts normal) option line formatting 686181834Sroberto */ 687181834Srobertostatic int 688181834SrobertosetStdOptFmts( tOptions* pOpts, tCC** ppT ) 689181834Sroberto{ 690181834Sroberto int flen = 0; 691181834Sroberto 692181834Sroberto argTypes.pzStr = zStdStrArg; 693181834Sroberto argTypes.pzReq = zStdReqArg; 694181834Sroberto argTypes.pzNum = zStdNumArg; 695181834Sroberto argTypes.pzKey = zStdKeyArg; 696181834Sroberto argTypes.pzKeyL = zStdKeyLArg; 697181834Sroberto argTypes.pzBool = zStdBoolArg; 698181834Sroberto argTypes.pzNest = zStdNestArg; 699181834Sroberto argTypes.pzOpt = zStdOptArg; 700181834Sroberto argTypes.pzNo = zStdNoArg; 701181834Sroberto argTypes.pzBrk = zStdBreak; 702181834Sroberto argTypes.pzNoF = zFiveSpaces; 703181834Sroberto argTypes.pzSpc = zTwoSpaces; 704181834Sroberto 705181834Sroberto switch (pOpts->fOptSet & (OPTPROC_NO_REQ_OPT | OPTPROC_SHORTOPT)) { 706181834Sroberto case (OPTPROC_NO_REQ_OPT | OPTPROC_SHORTOPT): 707181834Sroberto *ppT = zNoRq_ShrtTtl; 708181834Sroberto argTypes.pzOptFmt = zNrmOptFmt; 709181834Sroberto flen = 19; 710181834Sroberto break; 711181834Sroberto 712181834Sroberto case OPTPROC_NO_REQ_OPT: 713181834Sroberto *ppT = zNoRq_NoShrtTtl; 714181834Sroberto argTypes.pzOptFmt = zNrmOptFmt; 715181834Sroberto flen = 19; 716181834Sroberto break; 717181834Sroberto 718181834Sroberto case OPTPROC_SHORTOPT: 719181834Sroberto *ppT = zReq_ShrtTtl; 720181834Sroberto argTypes.pzOptFmt = zReqOptFmt; 721181834Sroberto flen = 24; 722181834Sroberto break; 723181834Sroberto 724181834Sroberto case 0: 725181834Sroberto *ppT = zReq_NoShrtTtl; 726181834Sroberto argTypes.pzOptFmt = zReqOptFmt; 727181834Sroberto flen = 24; 728181834Sroberto } 729181834Sroberto 730181834Sroberto return flen; 731181834Sroberto} 732181834Sroberto 733181834Sroberto 734181834Sroberto/*: 735181834Sroberto * Local Variables: 736181834Sroberto * mode: C 737181834Sroberto * c-file-style: "stroustrup" 738181834Sroberto * indent-tabs-mode: nil 739181834Sroberto * End: 740181834Sroberto * end of autoopts/usage.c */ 741