home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
misc
/
volume29
/
parseargs
/
part06
/
ibm_args.c
next >
Wrap
C/C++ Source or Header
|
1992-05-19
|
26KB
|
804 lines
/*************************************************************************
** ^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 );
}