home *** CD-ROM | disk | FTP | other *** search
- /*************************************************************************
- ** ^FILE: ibm_args.c - parse MS-DOS and OS/2 argument vectors
- **
- ** ^DESCRIPTION:
- ** This file contains the routines used to parse MS-DOS and OS/2
- ** argument vectors and to print MS-DOS and OS/2 usage messages.
- **
- ** ^HISTORY:
- ** 27/08/91 Earl Chew <cechew@bruce.cs.monash.edu.au>
- ** - Use ProgNameLen when accessing ProgName
- ** - Use get_argdesc() to access description
- **
- ** 01/02/91 Brad Appleton <brad@ssd.csd.harris.com> Created
- ***^^**********************************************************************/
-
- #include <ctype.h>
- #include <useful.h>
- #include "strfuncs.h"
- #include "pgopen.h"
- #include "exit_codes.h"
-
- #define PARSEARGS_PRIVATE /* include private definitions */
- #include "parseargs.h"
-
- EXTERN VOID syserr ARGS((const char *, ...));
- EXTERN VOID usrerr ARGS((const char *, ...));
- EXTERN char *getenv ARGS((const char *));
- EXTERN VOID get_winsize ARGS((int, int *, int *));
-
- VERSIONID("$Header: parseargs.c,v 2.1 89/12/30 20:59:48 eric Exp $");
-
- /***************************************************************************
- ** ^GLOBAL-VARIABLE: OptPrefix, KwdPrefix
- **
- ** ^VISIBILITY:
- ** static-global (visible to all functions in this file).
- **
- ** ^DESCRIPTION:
- ** OptPrefix contains the single character prefix used to precede
- ** an option switch on the command-line.
- **
- ** KwdPrefix contains the single character prefix used to precede
- ** a keyword switch on the command-line.
- ***^^**********************************************************************/
- static char OptPrefix='/';
- static char KwdPrefix='/';
-
- #define isUNIXISH ( OptPrefix == '-' )
-
-
- /***************************************************************************
- ** ^GLOBAL-VARIABLE: Usage_Requested
- **
- ** ^VISIBILITY:
- ** static-global (visible to all functions in this file).
- **
- ** ^DESCRIPTION:
- ** Indicates whether a usage message was requested by the user
- ** (as opposed to triggerred by a syntax error). If the message
- ** is requested by the user then it is always printed in verbose
- ** mode and does not return an error-status-code.
- ***^^**********************************************************************/
- static BOOL Usage_Requested = FALSE;
-
-
- /* macros to detect an option/keyword -- watch out for side effects!! */
- #define isOPT(s) \
- ( !BTEST(cmd_flags(cmd), pa_KWDSONLY) && \
- !BTEST(cmd_state(cmd), ps_NOFLAGS) && \
- *s == OptPrefix && *(s+1) \
- )
-
- #define isKWD(s) \
- ( !BTEST(cmd_flags(cmd), pa_OPTSONLY) && \
- !BTEST(cmd_state(cmd), ps_NOFLAGS) && \
- *s == KwdPrefix && *(s+1) \
- )
-
-
- /***************************************************************************
- ** ^FUNCTION: get_prefixes - determine short and long keyword prefixes
- **
- ** ^SYNOPSIS:
- */
- #ifndef __ANSI_C__
- static VOID get_prefixes()
- #endif
- /*
- ** ^PARAMETERS:
- ** None.
- **
- ** ^DESCRIPTION:
- ** Get_prefixes will determine the prefixes to used to denote option
- ** switches and keyword switches on the command-line. The prefixes
- ** are determined by the $SWITCHAR environment varaible. The first
- ** character of the variable is the option-switch prefix and the second
- ** character is the keyword-switch prefix.
- **
- ** If The option-switch prefix is '-' then Unix-style command-line parsing
- ** is performed, otherwise MS-DOS style command-line parsing is used.
- **
- ** ^REQUIREMENTS:
- ** None.
- **
- ** ^SIDE-EFFECTS:
- ** Sets the global variables "OptPrefix" and "KwdPrefix'.
- **
- ** ^RETURN-VALUE:
- ** None.
- **
- ** ^ALGORITHM:
- ** - If $SWITCHAR is NULL or empty
- ** - use the defaults ('/' and '/').
- ** - Else
- ** - set the OptPrefix to the first character in SWITCHAR
- ** End-if
- **
- ** - If there is a second character in SWITCHAR
- ** - assign it to KwdPrefix
- ** - Else if OptPrefix is '-'
- ** - then use '+' as the default KwdPrefix
- ** - Else
- ** - use '/' as the default KwdPrefix
- ** End-if
- ***^^**********************************************************************/
- #ifdef __ANSI_C__
- static VOID get_prefixes( void )
- #endif
- {
- char *prefixes = getenv( "SWITCHAR" );
-
- if ( prefixes && *prefixes ) {
- OptPrefix = *prefixes;
- KwdPrefix = *(prefixes + 1);
- if ( !KwdPrefix ) KwdPrefix = (( OptPrefix == '-' ) ? '+' : '/');
- }
- else {
- OptPrefix = '/';
- KwdPrefix = '/';
- }
- }
-
-
- /***************************************************************************
- ** ^FUNCTION: ibm_parse - parse MS-DOS and OS/2 arg-vectors
- **
- ** ^SYNOPSIS:
- */
- #ifndef __ANSI_C__
- int ibm_parse( argv, argd )
- /*
- ** ^PARAMETERS:
- */
- char *argv[];
- /* -- the vector of string arguments from the command-line
- */
- ARGDESC argd[];
- /* -- the programmer description of the command and its args
- */
- #endif /* !__ANSI_C__ */
-
- /* ^DESCRIPTION:
- ** Ibm_parse will parse the arguments in the given vector of strings,
- ** assign the corresponding values to the command-line arguments specified
- ** in argd, and check the syntax of the command-line.
- **
- ** ^REQUIREMENTS:
- ** The final element in argv must be a NULL pointer.
- **
- ** ^SIDE-EFFECTS:
- ** argd is modified according to the command-line description and parameters
- **
- ** ^RETURN-VALUE:
- ** pe_SUCCESS (0) if no errors are encountered
- ** pe_SYSTEM (-1) if a system error is encountered
- ** pe_SYNTAX if a syntax error is encountered
- **
- ** ^ALGORITHM:
- ** - get the active option and keyword prefixes
- ** - determine whether to use Unix style or not (based on the prefixes)
- ** - for each command-line argument
- ** - attempt to match the argument as a keyword
- ** - if it is a keyword argument
- ** - record and convert its value (if any)
- ** else attempt to match the argument as an option
- ** if it is an option
- ** - record and convert its value (if any)
- ** else it is a positional parameter
- ** - record and convert its value (if any)
- ** else there are too many arguments
- ** - return pe_SYNTAX
- ** end-if
- ** end-for
- ***^^**********************************************************************/
- #ifdef __ANSI_C__
- int ibm_parse( char *argv[], ARGDESC argd[] )
- #endif
- {
- register ARGDESC *ad, *args, *cmd;
- register char **av = argv;
- register char *p;
- argName_t name;
- argMask_t flags;
- int parse_error = pe_SUCCESS;
- BOOL ad_okay, is_match = FALSE;
-
- if ( !argd ) return parse_error;
-
- /* initialize command-structure */
- if ( !CMD_isINIT(argd) ) init_args( argd );
- cmd = argd;
-
- get_prefixes();
-
- while ( av && (p = *av++) ) {
- /* is this a keyword */
- if ( isKWD(p) &&
- ( (OptPrefix != KwdPrefix) || *(p+2) && !strchr(s_ARG_SEP, *(p+2)) )
- ) {
- char *s, c = '\0';
-
- /* check for `++' to end flags */
- if ( *(p+1) == KwdPrefix && !*(p+2) ) {
- BSET( cmd_state(cmd), ps_NOFLAGS );
- cmd_list(cmd) = ARGDESCNULL;
- continue;
- }
-
- /* get past prefix and look for possible argument */
- s = strpbrk(++p, s_ARG_SEP);
- if(s) {
- c = *s;
- *s++ = '\0';
- }
-
- is_match = FALSE;
- for ( args = argd ; args && !is_match ; args = cmd_defargs(args) ) {
- for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
- if ( arg_type(ad) == argDummy ) continue;
-
- if ( !ARG_isPOSONLY(ad) && match(p, arg_sname(ad)) == 0 ) {
- is_match = TRUE;
- break;
- }/*if*/
- }
- }
-
- if ( c ) *(s-1) = c; /* restore the equal sign */
-
- if ( !is_match ) {
- if ( OptPrefix == KwdPrefix ) {
- goto MATCHOPT; /* maybe its an option (and NOT a keyword) */
- }
- usrerr("%c%s switch unknown", KwdPrefix, p);
- parse_error = pe_SYNTAX;
- cmd_list(cmd) = ARGDESCNULL;
- continue;
- }
-
- /* reset the argument flags - if this arg was already given, some
- ** of its flags may be set to indicate how it was given before.
- ** we need to know how it was given now (but save the old ones
- ** just in case the new one fails).
- */
- flags = arg_flags(ad);
- if ( ARG_isGIVEN(ad) ) {
- BCLEAR( arg_flags(ad), ARGVALSEP | ARGKEYWORD );
- if ( !ARG_isMULTIVAL(ad) ) BCLEAR( arg_flags(ad), ARGVALGIVEN );
- }
-
- BSET( arg_flags(ad), ARGKEYWORD );
-
- if( ARG_isMULTIVAL(ad) ) {
- cmd_list(cmd) = ad; /* we matched a lst or a vector */
- }
- else {
- cmd_list(cmd) = ARGDESCNULL;
- }
-
- /* if usage - just print usage and exit */
- if ( arg_type(ad) == argUsage ) {
- Usage_Requested = TRUE;
- usage(argd);
- exit(exit_USAGE);
- }
-
- /* ARGNOVALs are special, having no value */
- if ( ! ARG_isVALTAKEN(ad) ) {
- ad_okay = HANDLE(ad, s, cmd_flags(cmd));
- if ( !ad_okay ) {
- arg_flags(ad) = flags;
- parse_error = pe_SYNTAX;
- }
- else {
- BSET( arg_flags(ad), ARGGIVEN );
- ad = ARGDESCNULL;
- }
- continue;
- }/*if ARGNOVAL*/
-
- /* now get the real value */
- if (!s) {
- if ( isUNIXISH ) s = *av++;
- if ( !isUNIXISH || !s || isOPT(s) || isKWD(s) ) {
- if ( ARG_isVALOPTIONAL(ad) ) {
- BSET( arg_flags(ad), ARGGIVEN );
- }
- else {
- (VOID) get_kwdname( arg_sname(ad), name );
- usrerr("%c%s switch requires an argument", KwdPrefix, name);
- arg_flags(ad) = flags;
- parse_error = pe_SYNTAX;
- }
-
- if ( isUNIXISH ) av--;
- continue;
- }/*if arg*/
- if ( isUNIXISH ) BSET( arg_flags(ad), ARGVALSEP );
- }/*if empty*/
-
- /* try to convert the type */
- ad_okay = HANDLE(ad, s, cmd_flags(cmd));
- if ( !ad_okay ) {
- arg_flags(ad) = flags;
- parse_error = pe_SYNTAX;
- }
- else {
- BSET( arg_flags(ad), ARGGIVEN | ARGVALGIVEN );
- }
-
- continue;
- }/*if keyword*/
- else if ( isOPT(p) ) {
- p++; /* skip over option prefix */
-
- MATCHOPT:
- /* check for `--' to end flags */
- if ( *p == OptPrefix && !*(p+1) ) {
- BSET( cmd_state(cmd), ps_NOFLAGS );
- cmd_list(cmd) = ARGDESCNULL;
- continue;
- }
-
- /* We have a flag argument;
- ** remember that in the case of single character keywords,
- ** the conversion function (ad_type) tells us how many characters
- ** were used. We need that information to decide how many
- ** characters to skip before the next iteration of the while loop.
- */
- while (*p) { /* while not end of switch-chars */
-
- /* find the flag in the list */
- is_match = FALSE;
- for (args = argd; args && !is_match ; args = cmd_defargs(args)) {
- for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
- register char c1 = arg_cname(ad);
- register char c2 = *p;
-
- if ( arg_type(ad) == argDummy ) continue;
- if ( ARG_isPOSONLY(ad) ) continue;
-
- if ( BTEST(cmd_flags(cmd), pa_ANYCASE) ) {
- c1 = TOUPPER( c1 );
- c2 = TOUPPER( c2 );
- }/*if*/
-
- if ( c1 == c2 ) {
- is_match = TRUE;
- break;
- }/*if*/
- }
- }
- if ( !is_match ) {
- usrerr("%c%c switch unknown", OptPrefix, *p++);
- parse_error = pe_SYNTAX;
- cmd_list(cmd) = ARGDESCNULL;
- if ( !isUNIXISH && *p == *s_ARG_SEP ) p += strlen(p);
- if ( !isUNIXISH && *p == OptPrefix ) ++p;
- continue;
- }/* if unknown-option */
-
- /* reset the argument flags - if this arg was already given, some
- ** of its flags may be set to indicate how it was given before.
- ** we need to know how it was given now (but save the old ones
- ** just in case the new one fails).
- */
- flags = arg_flags(ad);
- if ( ARG_isGIVEN(ad) ) {
- BCLEAR( arg_flags(ad), ARGVALSEP | ARGKEYWORD );
- if ( !ARG_isMULTIVAL(ad) ) BCLEAR( arg_flags(ad), ARGVALGIVEN );
- }
-
- if ( ARG_isMULTIVAL(ad) ) {
- cmd_list(cmd) = ad; /* we matched a list (or a vector) */
- }
- else {
- cmd_list(cmd) = ARGDESCNULL;
- }
-
- /* move p up to point to the (possible) value */
- p++;
- if ( !isUNIXISH && *p && strchr(s_ARG_SEP, *p) ) ++p;
-
- /* if usage - just print usage and exit */
- if (arg_type(ad) == argUsage) {
- Usage_Requested = TRUE;
- usage(argd);
- exit(exit_USAGE);
- }
-
- /* ARGNOVALs are special, having no value */
- if (! ARG_isVALTAKEN(ad)) {
- ad_okay = HANDLE(ad, p, cmd_flags(cmd));
-
- if ( !ad_okay ) {
- arg_flags(ad) = flags;
- parse_error = pe_SYNTAX;
- }/*if*/
- else {
- BSET( arg_flags(ad), ARGGIVEN );
- ad = ARGDESCNULL;
- if ( ad_okay < 0 ) p -= ad_okay;
- }/*else*/
-
- if ( !isUNIXISH && *p == OptPrefix ) ++p;
- continue;
- }/*if*/
-
- /* now get the real value */
- if ( !(*p) ) {
- if ( isUNIXISH ) p = *av++;
- if ( !isUNIXISH || !p || isOPT(p) || isKWD(p) ) {
- if ( ARG_isVALOPTIONAL(ad) ) {
- BSET( arg_flags(ad), ARGGIVEN );
- }
- else {
- (VOID) get_argname(arg_sname(ad), name);
- usrerr( "%s required for %c%c flag",
- name, OptPrefix, arg_cname(ad) );
- arg_flags(ad) = flags;
- parse_error = pe_SYNTAX;
- }/*else*/
-
- if ( isUNIXISH ) av--;
- break;
- }/*if arg*/
- if ( isUNIXISH ) BSET( arg_flags(ad), ARGVALSEP );
- }/*if empty*/
-
- /* try to convert the type */
- ad_okay = HANDLE(ad, p, cmd_flags(cmd));
- if ( !ad_okay ) {
- arg_flags(ad) = flags;
- parse_error = pe_SYNTAX;
- p += strlen(p);
- }/*if*/
- else {
- BSET( arg_flags(ad), ARGGIVEN | ARGVALGIVEN );
- if ( isUNIXISH && ad_okay < 0 && !ARG_isVALSEPARATE(ad) ) {
- p -= ad_okay;
- }
- else {
- p += strlen(p);
- }
- }/*else*/
-
- if ( !isUNIXISH && *p == OptPrefix ) ++p;
- }/*while*/
- }/*elif option*/
- else {
- /* parsing a list of arguments */
- if ( cmd_list(cmd) ) { /* we're in the middle of a list/vector */
- ad = cmd_list(cmd);
- flags = arg_flags(ad); /* reset flags for this argv-item */
- if ( ARG_isGIVEN(ad) ) {
- BCLEAR( arg_flags(ad), ARGVALSEP | ARGKEYWORD );
- }
-
- BSET( arg_flags(ad), ARGVALSEP );
-
- ad_okay = HANDLE(ad, p, cmd_flags(cmd));
- if ( !ad_okay ) {
- arg_flags(ad) = flags;
- parse_error = pe_SYNTAX;
- }
-
- continue;
- }
- /* positional argument */
- is_match = FALSE;
- for (args = argd; args && !is_match ; args = cmd_defargs(args)) {
- for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
- if (arg_type(ad) == argDummy) continue;
-
- if ( ARG_isPOSITIONAL(ad) &&
- (!ARG_isGIVEN(ad) || ARG_isMULTIVAL(ad)) ) {
- is_match = TRUE;
- break;
- }/*if*/
- }
- }
-
- if ( !is_match ) {
- usrerr("too many arguments");
- parse_error = pe_SYNTAX;
- continue;
- }
-
- flags = arg_flags(ad);
- if ( ARG_isGIVEN(ad) ) {
- BCLEAR( arg_flags(ad), ARGVALSEP | ARGKEYWORD );
- if ( !ARG_isMULTIVAL(ad) ) BCLEAR( arg_flags(ad), ARGVALGIVEN );
- }
-
- if ( ARG_isMULTIVAL(ad) ) {
- cmd_list(cmd) = ad;
- }
-
- /* if FLAGS1ST is set then first positional marks end-of-flags */
- if ( BTEST(cmd_flags(cmd), pa_FLAGS1ST) ) {
- BSET( cmd_state(cmd), ps_NOFLAGS );
- }
-
- BSET( arg_flags(ad), ARGVALSEP );
-
- /* try to convert */
- ad_okay = HANDLE(ad, p, cmd_flags(cmd));
- if ( !ad_okay ) {
- arg_flags(ad) = flags;
- parse_error = pe_SYNTAX;
- }
- else {
- BSET( arg_flags(ad), ARGGIVEN | ARGVALGIVEN );
- }
- }/*else*/
- }/*while*/
-
- return parse_error;
- }
-
-
- /***************************************************************************
- ** ^FUNCTION: fmtarg - format command-argument syntax
- **
- ** ^SYNOPSIS:
- */
- #ifndef __ANSI_C__
- static int fmtarg( ad, buf, usgflags )
- /*
- ** ^PARAMETERS:
- */
- ARGDESC *ad;
- /* -- pointer to the argument to format
- */
- char *buf;
- /* -- character buffer to hold the formatted result
- */
- argMask_t usgflags;
- /* -- set of bitmasks corresponding to the value of the user's USAGECNTL
- ** environment variable
- */
- #endif /* !__ANSI_C__ */
-
- /* ^DESCRIPTION:
- ** Fmtarg will determine the proper command-line syntax for the
- ** given argument and write the result to the given buffer.
- **
- ** ^REQUIREMENTS:
- ** buf must be large enough to hold the formatted result (100 characters
- ** should do the trick).
- **
- ** ^SIDE-EFFECTS:
- ** buf is overwritten.
- **
- ** ^RETURN-VALUE:
- ** The number of printable characters in the argument-syntax-string
- **
- ** ^ALGORITHM:
- ** Print argument usage based on whether or not the argument is
- ** positional, hidden, multi-valued (list or vector), etc ....
- ** Optional arguments and values are enclosed in square braces.
- **
- ** Any syntax biases reflected in usgflags will be used.
- ***^^**********************************************************************/
- #ifdef __ANSI_C__
- static int fmtarg( const ARGDESC *ad, char *buf, argMask_t usgflags )
- #endif
- {
- /* buf must already be large enough */
- char *pos;
- argName_t name, keyword;
-
- (VOID) get_argname( arg_sname(ad), name );
-
- if (ARG_isPOSITIONAL(ad)) {
- sprintf( buf, "<%s>", name );
- }
- else {
- (VOID) get_kwdname( arg_sname(ad), keyword );
-
- if ( isupper(arg_cname(ad)) && toupper(*keyword) == arg_cname(ad) ) {
- *keyword = toupper(*keyword);
- }
-
- if ( !(usgflags & usg_LONGOPTS) ) {
- sprintf( buf, "%c%c", OptPrefix, arg_cname(ad) );
- }
- else if ( !(usgflags & usg_OPTS) ) {
- sprintf( buf, "%c%s", KwdPrefix, keyword );
- }
- else { /* use both */
- if ( OptPrefix == KwdPrefix && *keyword == arg_cname(ad) ) {
- if ( !*(keyword+1) )
- sprintf( buf, "%c%c", OptPrefix, arg_cname(ad) );
- else
- sprintf( buf, "%c%c[%s]", OptPrefix, arg_cname(ad), keyword+1 );
- }
- else {
- sprintf( buf, "%c%c|%c%s", OptPrefix, arg_cname(ad),
- KwdPrefix, keyword );
- }
- }
-
- pos = buf + strlen(buf);
-
- if ( ARG_isVALTAKEN(ad) && !ARG_isBOOLEAN(ad) && !ARG_isPSEUDOARG(ad) ) {
- if ( isUNIXISH ) *(pos++) = ' ';
- if ( ARG_isVALOPTIONAL(ad) ) *(pos++) = '[';
- if ( !isUNIXISH ) *(pos++) = *s_ARG_SEP;
- sprintf( pos, "<%s>", name );
- if ( ARG_isVALOPTIONAL(ad) ) strcat(pos, "]");
- }/*if*/
- }/*else*/
-
- return strlen(buf);
- }
-
-
- /***************************************************************************
- ** ^FUNCTION: ibm_usage - print a usage message
- **
- ** ^SYNOPSIS:
- */
- #ifndef __ANSI_C__
- VOID ibm_usage( argd, usage_flags )
- /*
- ** ^PARAMETERS:
- */
- ARGDESC *argd;
- /* -- the command-descriptor array
- */
- argMask_t usage_flags;
- /* -- flags set by $USAGECNTL
- */
- #endif /* !__ANSI_C__ */
-
- /* ^DESCRIPTION:
- ** Ibm_usage will print the Unix command-line usage of the given
- ** command on standard diagnostic output (stderr). The content of the
- ** usage message is controlled by the bitmasks in usage_flags which
- ** correspond to the settings in the user's USAGECNTL variable.
- **
- ** ^REQUIREMENTS:
- ** argd should be a non-null command-line argument-descriptor array
- **
- ** ^SIDE-EFFECTS:
- ** Prints on stderr.
- **
- ** ^RETURN-VALUE:
- ** None.
- **
- ** ^ALGORITHM:
- ** - if no usage is desired then exit
- ** - if paging is requested print to the pager instead of stderr
- ** - print the command-line syntax
- ** - if the description is requested print it
- ** - if verbose mode is requested, print the description of each argument
- ***^^**********************************************************************/
- #ifdef __ANSI_C__
- void ibm_usage( const ARGDESC *argd, argMask_t usage_flags )
- #endif
- {
- register CONST ARGDESC *ad, *args, *cmd;
- int max_cols = 80, max_lines = 24;
- int ll, margin, options, longest, positionals;
- BOOL first = TRUE;
- FILE *fp;
-
- if ( !argd ) return;
-
- /* initialize command-structure */
- if ( !CMD_isINIT(argd) ) init_args( (ARGDESC *)argd );
- cmd = argd;
-
- /* force verbose-mode if requested */
- if ( Usage_Requested ) BSET( usage_flags, usg_VERBOSE );
-
- if ( BTEST(usage_flags, usg_NONE) ) return;
-
- fp = ( BTEST(usage_flags, usg_PAGED) )
- ? pgopen( stderr, getenv("USAGE_PAGER") )
- : stderr;
-
- /* get screen size */
- get_winsize( fileno(fp), &max_lines, &max_cols );
-
- fprintf(fp, "Usage: %.*s", ProgNameLen, (ProgName) ? ProgName : "");
-
- ll = ProgNameLen + 7;
- margin = ll + 1;
- longest = 0;
-
- /* print Synopsis */
- for ( positionals = 0 ; positionals < 2 ; positionals++ ) {
- for ( args = argd ; args ; args = cmd_defargs(args) ) {
- for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
- argName_t buf;
- int pl;
-
- /* don't display hidden arguments */
- if ( ARG_isHIDDEN(ad) ) continue;
- if ( !positionals && ARG_isPOSITIONAL(ad) ) continue;
- if ( positionals && !ARG_isPOSITIONAL(ad) ) continue;
-
- /* figure out how wide this parameter is (for printing) */
- pl = fmtarg(ad, buf, usage_flags);
-
- if ( pl > longest) longest = pl;
-
- if ( ARG_isMULTIVAL(ad) ) {
- strcat( buf, "..." );
- pl += 3;
- }
- if ( !ARG_isREQUIRED(ad) ) {
- pl += 2;
- }
-
- /* see if this will fit */
- if ( (ll + pl + 1) > (max_cols - first) ) {
- /* no... start a new line */
- fprintf(fp, "\n%*s", margin, "");
- ll = margin;
- }
- else {
- /* yes... just throw in a space */
- fputc(' ', fp);
- ++ll;
- }
- ll += pl;
-
- /* show the argument */
- if ( !ARG_isREQUIRED(ad) ) fputc('[', fp);
- fprintf(fp, buf);
- if ( !ARG_isREQUIRED(ad) ) fputc(']', fp);
-
- first = FALSE; /* not first line anymore */
- }/*for each ad */
- }/* for each argd */
- }/* for each parm-type */
-
- fputc('\n', fp);
-
- if ( BTEST(usage_flags, usg_DESCRIPTION) ) {
- CONST char *description = cmd_description(cmd);
-
- if ( description && *description ) {
- fprintf( fp, "Description:\n" );
- indent_para(fp, max_cols, 8, "", 0, description, 0);
- fputc( '\n', fp );
- }
- }/*if*/
-
- if ( !BTEST(usage_flags, usg_VERBOSE) ) {
- if ( pgactive(fp) ) (VOID) pgclose( fp );
- return;
- }
-
- options = 0;
-
- /* print Argument descriptions */
- for ( positionals = 0 ; positionals < 2 ; positionals++ ) {
- for ( args = argd ; args ; args = cmd_defargs(args) ) {
- for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
- argName_t buf;
- char *desc;
- int desclen;
-
- /* don't display hidden arguments */
- if ( ARG_isHIDDEN(ad) ) continue;
- if ( !positionals && ARG_isPOSITIONAL(ad) ) continue;
- if ( positionals && !ARG_isPOSITIONAL(ad) ) continue;
-
- if ( !options++ ) fprintf(fp, "Options/Arguments:\n");
- fmtarg(ad, buf, usage_flags);
- desc = get_argdesc(arg_description(ad), &desclen);
- indent_para( fp, max_cols, 8, buf, longest+2, desc, desclen );
- }/*for each ad */
- }/* for each argd */
- }/* for each parm-type */
-
- if ( pgactive(fp) ) (VOID) pgclose( fp );
- }
-
-