xref: /netbsd-src/external/bsd/ntp/dist/sntp/libopts/usage.c (revision b757af438b42b93f8c6571f026d8b8ef3eaf5fc9)
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