1
2/*
3 *  usage.c  $Id: usage.c,v 4.15 2007/04/28 22:19:23 bkorb Exp $
4 * Time-stamp:      "2007-04-15 11:02:46 bkorb"
5 *
6 *  This module implements the default usage procedure for
7 *  Automated Options.  It may be overridden, of course.
8 *
9 *  Sort options:
10    --start=END-[S]TATIC-FORWARD --patt='^/\*($|[^:])' \
11    --out=xx.c key='^[a-zA-Z0-9_]+\(' --trail='^/\*:' \
12    --spac=2 --input=usage.c
13 */
14
15/*
16 *  Automated Options copyright 1992-2007 Bruce Korb
17 *
18 *  Automated Options is free software.
19 *  You may redistribute it and/or modify it under the terms of the
20 *  GNU General Public License, as published by the Free Software
21 *  Foundation; either version 2, or (at your option) any later version.
22 *
23 *  Automated Options is distributed in the hope that it will be useful,
24 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
25 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26 *  GNU General Public License for more details.
27 *
28 *  You should have received a copy of the GNU General Public License
29 *  along with Automated Options.  See the file "COPYING".  If not,
30 *  write to:  The Free Software Foundation, Inc.,
31 *             51 Franklin Street, Fifth Floor,
32 *             Boston, MA  02110-1301, USA.
33 *
34 * As a special exception, Bruce Korb gives permission for additional
35 * uses of the text contained in his release of AutoOpts.
36 *
37 * The exception is that, if you link the AutoOpts library with other
38 * files to produce an executable, this does not by itself cause the
39 * resulting executable to be covered by the GNU General Public License.
40 * Your use of that executable is in no way restricted on account of
41 * linking the AutoOpts library code into it.
42 *
43 * This exception does not however invalidate any other reasons why
44 * the executable file might be covered by the GNU General Public License.
45 *
46 * This exception applies only to the code released by Bruce Korb under
47 * the name AutoOpts.  If you copy code from other sources under the
48 * General Public License into a copy of AutoOpts, as the General Public
49 * License permits, the exception does not apply to the code that you add
50 * in this way.  To avoid misleading anyone as to the status of such
51 * modified files, you must delete this exception notice from them.
52 *
53 * If you write modifications of your own for AutoOpts, it is your choice
54 * whether to permit this exception to apply to your modifications.
55 * If you do not wish that, delete this exception notice.
56 */
57
58#define OPTPROC_L_N_S  (OPTPROC_LONGOPT | OPTPROC_SHORTOPT)
59
60static arg_types_t argTypes;
61
62FILE* option_usage_fp = NULL;
63static char    zOptFmtLine[ 16 ];
64static ag_bool displayEnum;
65
66/* = = = START-STATIC-FORWARD = = = */
67/* static forward declarations maintained by :mkfwd */
68static ag_bool
69checkGNUUsage( tOptions* pOpts );
70
71static void
72printExtendedUsage(
73    tOptions*     pOptions,
74    tOptDesc*     pOD,
75    arg_types_t*  pAT );
76
77static void
78printInitList(
79    tCC* const* papz,
80    ag_bool*    pInitIntro,
81    tCC*        pzRc,
82    tCC*        pzPN );
83
84static void
85printOneUsage(
86    tOptions*     pOptions,
87    tOptDesc*     pOD,
88    arg_types_t*  pAT );
89
90static void
91printOptionUsage(
92    tOptions* pOpts,
93    int       ex_code,
94    tCC*      pOptTitle );
95
96static void
97printProgramDetails( tOptions* pOptions );
98
99static int
100setGnuOptFmts( tOptions* pOpts, tCC** ppT );
101
102static int
103setStdOptFmts( tOptions* pOpts, tCC** ppT );
104/* = = = END-STATIC-FORWARD = = = */
105
106
107/*
108 *  Figure out if we should try to format usage text sort-of like
109 *  the way many GNU programs do.
110 */
111static ag_bool
112checkGNUUsage( tOptions* pOpts )
113{
114    char* pz = getenv( "AUTOOPTS_USAGE" );
115    if (pz == NULL)
116        ;
117
118    else if (streqvcmp( pz, "gnu" ) == 0)
119        pOpts->fOptSet |= OPTPROC_GNUUSAGE;
120
121    else if (streqvcmp( pz, "autoopts" ) == 0)
122        pOpts->fOptSet &= ~OPTPROC_GNUUSAGE;
123
124    return (pOpts->fOptSet & OPTPROC_GNUUSAGE) ? AG_TRUE : AG_FALSE;
125}
126
127
128/*=export_func  optionOnlyUsage
129 *
130 * what:  Print usage text for just the options
131 * arg:   + tOptions*   + pOpts    + program options descriptor +
132 * arg:   + int         + ex_code  + exit code for calling exit(3) +
133 *
134 * doc:
135 *  This routine will print only the usage for each option.
136 *  This function may be used when the emitted usage must incorporate
137 *  information not available to AutoOpts.
138=*/
139void
140optionOnlyUsage(
141    tOptions* pOpts,
142    int       ex_code )
143{
144    tCC* pOptTitle = NULL;
145
146    /*
147     *  Determine which header and which option formatting strings to use
148     */
149    if (checkGNUUsage(pOpts)) {
150        (void)setGnuOptFmts( pOpts, &pOptTitle );
151    }
152    else {
153        (void)setStdOptFmts( pOpts, &pOptTitle );
154    }
155
156    printOptionUsage( pOpts, ex_code, pOptTitle );
157}
158
159
160/*=export_func  optionUsage
161 * private:
162 *
163 * what:  Print usage text
164 * arg:   + tOptions* + pOptions + program options descriptor +
165 * arg:   + int       + exitCode + exit code for calling exit(3) +
166 *
167 * doc:
168 *  This routine will print usage in both GNU-standard and AutoOpts-expanded
169 *  formats.  The descriptor specifies the default, but AUTOOPTS_USAGE will
170 *  over-ride this, providing the value of it is set to either "gnu" or
171 *  "autoopts".  This routine will @strong{not} return.
172 *
173 *  If "exitCode" is "EX_USAGE" (normally 64), then output will to to stdout
174 *  and the actual exit code will be "EXIT_SUCCESS".
175=*/
176void
177optionUsage(
178    tOptions* pOptions,
179    int       usage_exit_code )
180{
181    int actual_exit_code =
182        (usage_exit_code == EX_USAGE) ? EXIT_SUCCESS : usage_exit_code;
183
184    displayEnum = AG_FALSE;
185
186    /*
187     *  Paged usage will preset option_usage_fp to an output file.
188     *  If it hasn't already been set, then set it to standard output
189     *  on successful exit (help was requested), otherwise error out.
190     */
191    if (option_usage_fp == NULL)
192        option_usage_fp = (actual_exit_code != EXIT_SUCCESS) ? stderr : stdout;
193
194    fprintf( option_usage_fp, pOptions->pzUsageTitle, pOptions->pzProgName );
195
196    {
197        tCC* pOptTitle = NULL;
198
199        /*
200         *  Determine which header and which option formatting strings to use
201         */
202        if (checkGNUUsage(pOptions)) {
203            int flen = setGnuOptFmts( pOptions, &pOptTitle );
204            sprintf( zOptFmtLine, zFmtFmt, flen );
205            fputc( '\n', option_usage_fp );
206        }
207        else {
208            int flen = setStdOptFmts( pOptions, &pOptTitle );
209            sprintf( zOptFmtLine, zFmtFmt, flen );
210
211            /*
212             *  When we exit with EXIT_SUCCESS and the first option is a doc
213             *  option, we do *NOT* want to emit the column headers.
214             *  Otherwise, we do.
215             */
216            if (  (usage_exit_code != EXIT_SUCCESS)
217               || ((pOptions->pOptDesc->fOptState & OPTST_DOCUMENT) == 0) )
218
219                fputs( pOptTitle, option_usage_fp );
220        }
221
222        printOptionUsage( pOptions, usage_exit_code, pOptTitle );
223    }
224
225    /*
226     *  Describe the mechanics of denoting the options
227     */
228    switch (pOptions->fOptSet & OPTPROC_L_N_S) {
229    case OPTPROC_L_N_S:     fputs( zFlagOkay, option_usage_fp ); break;
230    case OPTPROC_SHORTOPT:  break;
231    case OPTPROC_LONGOPT:   fputs( zNoFlags,  option_usage_fp ); break;
232    case 0:                 fputs( zOptsOnly, option_usage_fp ); break;
233    }
234
235    if ((pOptions->fOptSet & OPTPROC_NUM_OPT) != 0) {
236        fputs( zNumberOpt, option_usage_fp );
237    }
238
239    if ((pOptions->fOptSet & OPTPROC_REORDER) != 0) {
240        fputs( zReorder, option_usage_fp );
241    }
242
243    if (pOptions->pzExplain != NULL)
244        fputs( pOptions->pzExplain, option_usage_fp );
245
246    /*
247     *  IF the user is asking for help (thus exiting with SUCCESS),
248     *  THEN see what additional information we can provide.
249     */
250    if (usage_exit_code == EXIT_SUCCESS)
251        printProgramDetails( pOptions );
252
253    if (pOptions->pzBugAddr != NULL)
254        fprintf( option_usage_fp, zPlsSendBugs, pOptions->pzBugAddr );
255    fflush( option_usage_fp );
256
257    exit( actual_exit_code );
258}
259
260
261/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
262 *
263 *   PER OPTION TYPE USAGE INFORMATION
264 */
265static void
266printExtendedUsage(
267    tOptions*     pOptions,
268    tOptDesc*     pOD,
269    arg_types_t*  pAT )
270{
271    /*
272     *  IF there are option conflicts or dependencies,
273     *  THEN print them here.
274     */
275    if (  (pOD->pOptMust != NULL)
276       || (pOD->pOptCant != NULL) ) {
277
278        fputs( zTabHyp, option_usage_fp );
279
280        /*
281         *  DEPENDENCIES:
282         */
283        if (pOD->pOptMust != NULL) {
284            const int* pOptNo = pOD->pOptMust;
285
286            fputs( zReqThese, option_usage_fp );
287            for (;;) {
288                fprintf( option_usage_fp, zTabout, pOptions->pOptDesc[
289                             *pOptNo ].pz_Name );
290                if (*++pOptNo == NO_EQUIVALENT)
291                    break;
292            }
293
294            if (pOD->pOptCant != NULL)
295                fputs( zTabHypAnd, option_usage_fp );
296        }
297
298        /*
299         *  CONFLICTS:
300         */
301        if (pOD->pOptCant != NULL) {
302            const int* pOptNo = pOD->pOptCant;
303
304            fputs( zProhib, option_usage_fp );
305            for (;;) {
306                fprintf( option_usage_fp, zTabout, pOptions->pOptDesc[
307                             *pOptNo ].pz_Name );
308                if (*++pOptNo == NO_EQUIVALENT)
309                    break;
310            }
311        }
312    }
313
314    /*
315     *  IF there is a disablement string
316     *  THEN print the disablement info
317     */
318    if (pOD->pz_DisableName != NULL )
319        fprintf( option_usage_fp, zDis, pOD->pz_DisableName );
320
321    /*
322     *  IF the numeric option has a special callback,
323     *  THEN call it, requesting the range or other special info
324     */
325    if (  (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_NUMERIC)
326       && (pOD->pOptProc != NULL)
327       && (pOD->pOptProc != optionNumericVal) ) {
328        (*(pOD->pOptProc))( pOptions, NULL );
329    }
330
331    /*
332     *  IF the option defaults to being enabled,
333     *  THEN print that out
334     */
335    if (pOD->fOptState & OPTST_INITENABLED)
336        fputs( zEnab, option_usage_fp );
337
338    /*
339     *  IF  the option is in an equivalence class
340     *        AND not the designated lead
341     *  THEN print equivalence and leave it at that.
342     */
343    if (  (pOD->optEquivIndex != NO_EQUIVALENT)
344       && (pOD->optEquivIndex != pOD->optActualIndex )  )  {
345        fprintf( option_usage_fp, zAlt,
346                 pOptions->pOptDesc[ pOD->optEquivIndex ].pz_Name );
347        return;
348    }
349
350    /*
351     *  IF this particular option can NOT be preset
352     *    AND some form of presetting IS allowed,
353     *    AND it is not an auto-managed option (e.g. --help, et al.)
354     *  THEN advise that this option may not be preset.
355     */
356    if (  ((pOD->fOptState & OPTST_NO_INIT) != 0)
357       && (  (pOptions->papzHomeList != NULL)
358          || (pOptions->pzPROGNAME != NULL)
359          )
360       && (pOD->optIndex < pOptions->presetOptCt)
361       )
362
363        fputs( zNoPreset, option_usage_fp );
364
365    /*
366     *  Print the appearance requirements.
367     */
368    if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP)
369        fputs( zMembers, option_usage_fp );
370
371    else switch (pOD->optMinCt) {
372    case 1:
373    case 0:
374        switch (pOD->optMaxCt) {
375        case 0:       fputs( zPreset, option_usage_fp ); break;
376        case NOLIMIT: fputs( zNoLim, option_usage_fp );  break;
377        case 1:       break;
378            /*
379             * IF the max is more than one but limited, print "UP TO" message
380             */
381        default:      fprintf( option_usage_fp, zUpTo, pOD->optMaxCt );  break;
382        }
383        break;
384
385    default:
386        /*
387         *  More than one is required.  Print the range.
388         */
389        fprintf( option_usage_fp, zMust, pOD->optMinCt, pOD->optMaxCt );
390    }
391
392    if (  NAMED_OPTS( pOptions )
393       && (pOptions->specOptIdx.default_opt == pOD->optIndex))
394        fputs( zDefaultOpt, option_usage_fp );
395}
396
397
398/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
399 *
400 *   Figure out where all the initialization files might live.
401 *   This requires translating some environment variables and
402 *   testing to see if a name is a directory or a file.  It's
403 *   squishy, but important to tell users how to find these files.
404 */
405static void
406printInitList(
407    tCC* const* papz,
408    ag_bool*    pInitIntro,
409    tCC*        pzRc,
410    tCC*        pzPN )
411{
412    char zPath[ AG_PATH_MAX+1 ];
413
414    if (papz == NULL)
415        return;
416
417    fputs( zPresetIntro, option_usage_fp );
418    *pInitIntro = AG_FALSE;
419
420    for (;;) {
421        char const* pzPath = *(papz++);
422
423        if (pzPath == NULL)
424            break;
425
426        if (optionMakePath(zPath, (int)sizeof( zPath ), pzPath, pzPN))
427            pzPath = zPath;
428
429        /*
430         *  Print the name of the "homerc" file.  If the "rcfile" name is
431         *  not empty, we may or may not print that, too...
432         */
433        fprintf( option_usage_fp, zPathFmt, pzPath );
434        if (*pzRc != NUL) {
435            struct stat sb;
436
437            /*
438             *  IF the "homerc" file is a directory,
439             *  then append the "rcfile" name.
440             */
441            if (  (stat( pzPath, &sb ) == 0)
442              &&  S_ISDIR( sb.st_mode ) ) {
443                fputc( DIRCH, option_usage_fp );
444                fputs( pzRc, option_usage_fp );
445            }
446        }
447
448        fputc( '\n', option_usage_fp );
449    }
450}
451
452
453/*
454 *  Print the usage information for a single option.
455 */
456static void
457printOneUsage(
458    tOptions*     pOptions,
459    tOptDesc*     pOD,
460    arg_types_t*  pAT )
461{
462    /*
463     *  Flag prefix: IF no flags at all, then omit it.  If not printable
464     *  (not allowed for this option), then blank, else print it.
465     *  Follow it with a comma if we are doing GNU usage and long
466     *  opts are to be printed too.
467     */
468    if ((pOptions->fOptSet & OPTPROC_SHORTOPT) == 0)
469        fputs( pAT->pzSpc, option_usage_fp );
470    else if (! isgraph( pOD->optValue)) {
471        if (  (pOptions->fOptSet & (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
472           == (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
473            fputc( ' ', option_usage_fp );
474        fputs( pAT->pzNoF, option_usage_fp );
475    } else {
476        fprintf( option_usage_fp, "   -%c", pOD->optValue );
477        if (  (pOptions->fOptSet & (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
478           == (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
479            fputs( ", ", option_usage_fp );
480    }
481
482    {
483        char  z[ 80 ];
484        tCC*  pzArgType;
485        /*
486         *  Determine the argument type string first on its usage, then,
487         *  when the option argument is required, base the type string on the
488         *  argument type.
489         */
490        if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_NONE) {
491            pzArgType = pAT->pzNo;
492
493        } else if (pOD->fOptState & OPTST_ARG_OPTIONAL) {
494            pzArgType = pAT->pzOpt;
495
496        } else switch (OPTST_GET_ARGTYPE(pOD->fOptState)) {
497        case OPARG_TYPE_ENUMERATION: pzArgType = pAT->pzKey;  break;
498        case OPARG_TYPE_MEMBERSHIP:  pzArgType = pAT->pzKeyL; break;
499        case OPARG_TYPE_BOOLEAN:     pzArgType = pAT->pzBool; break;
500        case OPARG_TYPE_NUMERIC:     pzArgType = pAT->pzNum;  break;
501        case OPARG_TYPE_HIERARCHY:   pzArgType = pAT->pzNest; break;
502        case OPARG_TYPE_STRING:      pzArgType = pAT->pzStr;  break;
503        default:                     goto bogus_desc;         break;
504        }
505
506        snprintf( z, sizeof(z), pAT->pzOptFmt, pzArgType, pOD->pz_Name,
507                  (pOD->optMinCt != 0) ? pAT->pzReq : pAT->pzOpt );
508
509        fprintf( option_usage_fp, zOptFmtLine, z, pOD->pzText );
510
511        switch (OPTST_GET_ARGTYPE(pOD->fOptState)) {
512        case OPARG_TYPE_ENUMERATION:
513        case OPARG_TYPE_MEMBERSHIP:
514            displayEnum = (pOD->pOptProc != NULL) ? AG_TRUE : displayEnum;
515        }
516    }
517    return;
518
519 bogus_desc:
520    fprintf( stderr, zInvalOptDesc, pOD->pz_Name );
521    exit( EX_SOFTWARE );
522}
523
524
525/*
526 *  Print out the usage information for just the options.
527 */
528static void
529printOptionUsage(
530    tOptions* pOpts,
531    int       ex_code,
532    tCC*      pOptTitle )
533{
534    int        ct     = pOpts->optCt;
535    int        optNo  = 0;
536    tOptDesc*  pOD    = pOpts->pOptDesc;
537    int        docCt  = 0;
538
539    do  {
540        if ((pOD->fOptState & OPTST_OMITTED) != 0)
541            continue;
542
543        if ((pOD->fOptState & OPTST_DOCUMENT) != 0) {
544            if (ex_code == EXIT_SUCCESS) {
545                fprintf(option_usage_fp, argTypes.pzBrk, pOD->pzText,
546                        pOptTitle);
547                docCt++;
548            }
549
550            continue;
551        }
552
553        /*
554         *  IF       this is the first auto-opt maintained option
555         *    *AND*  we are doing a full help
556         *    *AND*  there are documentation options
557         *    *AND*  the last one was not a doc option,
558         *  THEN document that the remaining options are not user opts
559         */
560        if (  (pOpts->presetOptCt == optNo)
561              && (ex_code == EXIT_SUCCESS)
562              && (docCt > 0)
563              && ((pOD[-1].fOptState & OPTST_DOCUMENT) == 0) )
564            fprintf( option_usage_fp, argTypes.pzBrk, zAuto, pOptTitle );
565
566        printOneUsage( pOpts, pOD, &argTypes );
567
568        /*
569         *  IF we were invoked because of the --help option,
570         *  THEN print all the extra info
571         */
572        if (ex_code == EXIT_SUCCESS)
573            printExtendedUsage( pOpts, pOD, &argTypes );
574
575    }  while (pOD++, optNo++, (--ct > 0));
576
577    fputc( '\n', option_usage_fp );
578}
579
580
581/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
582 *
583 *   PROGRAM DETAILS
584 */
585static void
586printProgramDetails( tOptions* pOptions )
587{
588    ag_bool  initIntro = AG_TRUE;
589
590    /*
591     *  Display all the places we look for config files
592     */
593    printInitList( pOptions->papzHomeList, &initIntro,
594                   pOptions->pzRcName, pOptions->pzProgPath );
595
596    /*
597     *  Let the user know about environment variable settings
598     */
599    if ((pOptions->fOptSet & OPTPROC_ENVIRON) != 0) {
600        if (initIntro)
601            fputs( zPresetIntro, option_usage_fp );
602
603        fprintf( option_usage_fp, zExamineFmt, pOptions->pzPROGNAME );
604    }
605
606    /*
607     *  IF we found an enumeration,
608     *  THEN hunt for it again.  Call the handler proc with a NULL
609     *       option struct pointer.  That tells it to display the keywords.
610     */
611    if (displayEnum) {
612        int        ct     = pOptions->optCt;
613        int        optNo  = 0;
614        tOptDesc*  pOD    = pOptions->pOptDesc;
615
616        fputc( '\n', option_usage_fp );
617        fflush( option_usage_fp );
618        do  {
619            switch (OPTST_GET_ARGTYPE(pOD->fOptState)) {
620            case OPARG_TYPE_ENUMERATION:
621            case OPARG_TYPE_MEMBERSHIP:
622                (*(pOD->pOptProc))( NULL, pOD );
623            }
624        }  while (pOD++, optNo++, (--ct > 0));
625    }
626
627    /*
628     *  If there is a detail string, now is the time for that.
629     */
630    if (pOptions->pzDetail != NULL)
631        fputs( pOptions->pzDetail, option_usage_fp );
632}
633
634
635/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
636 *
637 *   OPTION LINE FORMATTING SETUP
638 *
639 *  The "OptFmt" formats receive three arguments:
640 *  1.  the type of the option's argument
641 *  2.  the long name of the option
642 *  3.  "YES" or "no ", depending on whether or not the option must appear
643 *      on the command line.
644 *  These formats are used immediately after the option flag (if used) has
645 *  been printed.
646 *
647 *  Set up the formatting for GNU-style output
648 */
649static int
650setGnuOptFmts( tOptions* pOpts, tCC** ppT )
651{
652    int  flen = 22;
653    *ppT = zNoRq_ShrtTtl;
654
655    argTypes.pzStr  = zGnuStrArg;
656    argTypes.pzReq  = zOneSpace;
657    argTypes.pzNum  = zGnuNumArg;
658    argTypes.pzKey  = zGnuKeyArg;
659    argTypes.pzKeyL = zGnuKeyLArg;
660    argTypes.pzBool = zGnuBoolArg;
661    argTypes.pzNest = zGnuNestArg;
662    argTypes.pzOpt  = zGnuOptArg;
663    argTypes.pzNo   = zOneSpace;
664    argTypes.pzBrk  = zGnuBreak;
665    argTypes.pzNoF  = zSixSpaces;
666    argTypes.pzSpc  = zThreeSpaces;
667
668    switch (pOpts->fOptSet & OPTPROC_L_N_S) {
669    case OPTPROC_L_N_S:    argTypes.pzOptFmt = zGnuOptFmt;     break;
670    case OPTPROC_LONGOPT:  argTypes.pzOptFmt = zGnuOptFmt;     break;
671    case 0:                argTypes.pzOptFmt = zGnuOptFmt + 2; break;
672    case OPTPROC_SHORTOPT:
673        argTypes.pzOptFmt = zShrtGnuOptFmt;
674        zGnuStrArg[0] = zGnuNumArg[0] = zGnuKeyArg[0] = zGnuBoolArg[0] = ' ';
675        argTypes.pzOpt = " [arg]";
676        flen = 8;
677        break;
678    }
679
680    return flen;
681}
682
683
684/*
685 *  Standard (AutoOpts normal) option line formatting
686 */
687static int
688setStdOptFmts( tOptions* pOpts, tCC** ppT )
689{
690    int  flen = 0;
691
692    argTypes.pzStr  = zStdStrArg;
693    argTypes.pzReq  = zStdReqArg;
694    argTypes.pzNum  = zStdNumArg;
695    argTypes.pzKey  = zStdKeyArg;
696    argTypes.pzKeyL = zStdKeyLArg;
697    argTypes.pzBool = zStdBoolArg;
698    argTypes.pzNest = zStdNestArg;
699    argTypes.pzOpt  = zStdOptArg;
700    argTypes.pzNo   = zStdNoArg;
701    argTypes.pzBrk  = zStdBreak;
702    argTypes.pzNoF  = zFiveSpaces;
703    argTypes.pzSpc  = zTwoSpaces;
704
705    switch (pOpts->fOptSet & (OPTPROC_NO_REQ_OPT | OPTPROC_SHORTOPT)) {
706    case (OPTPROC_NO_REQ_OPT | OPTPROC_SHORTOPT):
707        *ppT = zNoRq_ShrtTtl;
708        argTypes.pzOptFmt = zNrmOptFmt;
709        flen = 19;
710        break;
711
712    case OPTPROC_NO_REQ_OPT:
713        *ppT = zNoRq_NoShrtTtl;
714        argTypes.pzOptFmt = zNrmOptFmt;
715        flen = 19;
716        break;
717
718    case OPTPROC_SHORTOPT:
719        *ppT = zReq_ShrtTtl;
720        argTypes.pzOptFmt = zReqOptFmt;
721        flen = 24;
722        break;
723
724    case 0:
725        *ppT = zReq_NoShrtTtl;
726        argTypes.pzOptFmt = zReqOptFmt;
727        flen = 24;
728    }
729
730    return flen;
731}
732
733
734/*:
735 * Local Variables:
736 * mode: C
737 * c-file-style: "stroustrup"
738 * indent-tabs-mode: nil
739 * End:
740 * end of autoopts/usage.c */
741