home *** CD-ROM | disk | FTP | other *** search
- From: brad@hcx1.ssd.csd.harris.com (Brad Appleton)
- Newsgroups: comp.sources.misc
- Subject: v17i056: parseargs - functions to parse command line arguments, Part11/12
- Message-ID: <1991Mar18.155757.2290@sparky.IMD.Sterling.COM>
- Date: 18 Mar 91 15:57:57 GMT
- Approved: kent@sparky.imd.sterling.com
- X-Checksum-Snefru: 44d684bb 87aa73f6 e00c92f4 f509ccbb
-
- Submitted-by: Brad Appleton <brad@hcx1.ssd.csd.harris.com>
- Posting-number: Volume 17, Issue 56
- Archive-name: parseargs/part11
-
- This is part 11 of parseargs
-
- #!/bin/sh
- # this is Part.11 (part 11 of a multipart archive)
- # do not concatenate these parts, unpack them in order with /bin/sh
- # file parseargs/useful.h continued
- #
- if test ! -r _shar_seq_.tmp; then
- echo 'Please unpack part 1 first!'
- exit 1
- fi
- (read Scheck
- if test "$Scheck" != 11; then
- echo Please unpack part "$Scheck" next!
- exit 1
- else
- exit 0
- fi
- ) < _shar_seq_.tmp || exit 1
- if test ! -f _shar_wnt_.tmp; then
- echo 'x - still skipping parseargs/useful.h'
- else
- echo 'x - continuing file parseargs/useful.h'
- sed 's/^X//' << 'SHAR_EOF' >> 'parseargs/useful.h' &&
- X EXTERN ARBPTR memcpy ARGS(( ARBPTR, const ARBPTR, int ));
- X EXTERN ARBPTR memmove ARGS(( ARBPTR, const ARBPTR, int ));
- X EXTERN ARBPTR memset ARGS(( ARBPTR, int, int ));
- # endif /* MEMORY_H */
- X
- # else
- # define memcmp(b1,b2,n) bcmp(b1,b2,n)
- # define memcpy(b1,b2,n) bcopy(b2,b1,n)
- # ifndef BSTRING_H
- # define BSTRING_H
- X EXTERN VOID bcopy ARGS(( const ARBPTR, ARBPTR, int ));
- X EXTERN int bcmp ARGS(( const ARBPTR, const ARBPTR, int ));
- X EXTERN VOID bzero ARGS(( ARBPTR, int ));
- X EXTERN int ffs ARGS(( int ));
- # endif /* BSTRING_H */
- # endif /* !BSD */
- #endif /* STRING_H */
- X
- EXTERN ARBPTR malloc ARGS(( size_t ));
- EXTERN ARBPTR ckalloc ARGS(( size_t ));
- EXTERN ARBPTR realloc ARGS(( ARBPTR, size_t ));
- EXTERN ARBPTR free ARGS(( ARBPTR ));
- EXTERN VOID exit ARGS(( int ));
- X
- #define MAXINPUTLINE 200 /* maximum string input line */
- #define MAXWORDLEN 100 /* maximum word (token) length */
- X
- #endif /* _USEFUL_H_ */
- SHAR_EOF
- echo 'File parseargs/useful.h is complete' &&
- chmod 0664 parseargs/useful.h ||
- echo 'restore of parseargs/useful.h failed'
- Wc_c="`wc -c < 'parseargs/useful.h'`"
- test 7432 -eq "$Wc_c" ||
- echo 'parseargs/useful.h: original size 7432, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- # ============= parseargs/vms_args.c ==============
- if test -f 'parseargs/vms_args.c' -a X"$1" != X"-c"; then
- echo 'x - skipping parseargs/vms_args.c (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- > _shar_wnt_.tmp
- echo 'x - extracting parseargs/vms_args.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'parseargs/vms_args.c' &&
- /*************************************************************************
- ** ^FILE: vms_args.c - parse VMS/DCL argument vectors
- **
- ** ^DESCRIPTION:
- ** This file contains the routines used to parse VMS/DCL argument
- ** vectors and to print VMS/DCL usage messages.
- **
- ** ^HISTORY:
- ** 12/03/90 Brad Appleton <brad@ssd.csd.harris.com> Created
- ***^^**********************************************************************/
- X
- #include <stdio.h>
- #include <ctype.h>
- #include <useful.h>
- X
- #ifdef vms
- # include <descrip.h>
- #endif
- X
- #include "strfuncs.h"
- #include "pgopen.h"
- X
- #define PARSEARGS_PRIVATE /* include private definitions */
- #include "parseargs.h"
- X
- EXTERN VOID syserr ARGS((const char *, ...));
- EXTERN VOID usrerr ARGS((const char *, ...));
- EXTERN VOID get_winsize ARGS((int, int *, int *));
- EXTERN BOOL argInput ARGS((ARGDESC *, char *, BOOL));
- EXTERN BOOL argOutput ARGS((ARGDESC *, char *, BOOL));
- X
- VERSIONID("$Header: vms_args.c,v 1.1 90/08/23 18:00:00 brad Exp $");
- X
- /***************************************************************************
- ** ^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;
- X
- X
- #define MAXCMDLINE 255
- #define VNULL (VOID *) 0
- X
- #define TOGGLE(flag) flag = (flag) ? FALSE : TRUE
- X
- X /* define mappings */
- #define c_SPACE '\001' /* whitespace */
- #define c_QUAL '\002' /* qualifier-delimiter */
- #define c_QSEP '\003' /* qualifier-argument separator */
- #define c_LSEP '\004' /* list-item separator character */
- X
- X
- typedef enum {
- X Parameter, /* token is a parameter */
- X Qualifier, /* token is a qualifier */
- X EndOfLine /* NUL-token (signifies end of tokens) */
- } dcl_arg_t;
- X
- X
- typedef struct {
- X dcl_arg_t type; /* token type */
- X char *token; /* token value */
- } dcl_token_t;
- X
- X
- X
- /***************************************************************************
- ** ^FUNCTION: is_cmdline - retrieve the original command-line
- **
- ** ^SYNOPSIS:
- */
- #ifndef __ANSI_C__
- X static BOOL is_cmdline( argv, result )
- /*
- ** ^PARAMETERS:
- */
- X char *argv[];
- /* -- array of strings
- */
- X char **result;
- /* -- pointer to resultant command-line
- */
- #endif /* !__ANSI_C__ */
- X
- /* ^DESCRIPTION:
- ** Is_cmdline will compare the given vector of strings to the actual
- ** string given on the command-line. If the two are approximately
- ** equivalent (modulo quotes and case) then the original command-line
- ** is copied to result, otherwise all the elements of argv are concat-
- ** enated together (in order and separated by whitespace) and assigned
- ** to *result.
- **
- ** ^REQUIREMENTS:
- ** argv must be non-null
- **
- ** ^SIDE-EFECTS:
- ** *result is assigned to either the concatenated argv string or the
- ** original command-line. The result shoub be freed using free().
- **
- ** ^RETURN-VALUE:
- ** FALSE if the argv given is different from the command-line;
- ** TRUE otherwise.
- **
- ** ^CAVEATS:
- ** The comparison is case blind and double quotes are ignored in the
- ** command-line. This is because lib$get_foreign returns double quotes
- ** intact, while VAX-C strips them off.
- **
- ** ^ACKNOWLEDGEMENTS:
- ** Thanx to Jim Barbour for writing most of this code. --BDA
- **
- ** ^ALGORITHM:
- ** - Make a single string out of argv
- ** - compare the "big" string to the command-line
- ** - IF they are "equivalent" assign command-line to result & return TRUE.
- ** ELSE assign the "big" string to result and return FALSE.
- ***^^**********************************************************************/
- #ifdef __ANSI_C__
- X static BOOL is_cmdline( const char *argv[], char **result )
- #endif
- {
- X unsigned long int stat;
- X unsigned short int len;
- X register CONST char *aptr, *sptr, *avstr;
- X static char str[ MAXCMDLINE ] = "" ;
- #ifdef vms
- X $DESCRIPTOR(str_d, str);
- #endif
- X
- X /* make a single string out of argv */
- X avstr = strjoin( argv, " " );
- X
- #ifndef vms
- X *result = (char *)avstr;
- X return FALSE;
- X
- #else
- X /* get the original command-line */
- X if ( !*str ) {
- X stat = lib$get_foreign( &str_d, VNULL, &len, VNULL );
- X str[len] = '\0';
- X if (! (stat & 1)) exit( stat );
- X }
- X
- X /* compare the two */
- X for ( aptr = avstr, sptr = str ; *aptr && *sptr ; sptr++ ) {
- X if ( toupper(*sptr) == toupper(*aptr) ) {
- X ++aptr;
- X }
- X else if ( *sptr != '"' ) {
- X *result = (char *)avstr;
- X return FALSE;
- X }
- X }
- X
- X *result = strdup( str );
- X free( avstr );
- X return TRUE;
- #endif
- }
- X
- X
- /***************************************************************************
- ** ^FUNCTION: dcl_strxlat - translate a string according to DCL syntax
- **
- ** ^SYNOPSIS:
- */
- #ifndef __ANSI_C__
- X static char *dcl_strxlat( str )
- /*
- ** ^PARAMETERS:
- */
- X char *str;
- /* -- the string to translate.
- */
- #endif /* !__ANSI_C__ */
- X
- /* ^DESCRIPTION:
- ** Dcl_strxlat will attempt to convert the given string to canonical
- ** form by escaping any unquoted special characters, and removing any
- ** unquoted whitespace around special characters (such as '=' and '/').
- ** Since the special characters are replaced with special codes, quotes
- ** are also removed.
- **
- ** ^REQUIREMENTS:
- ** <str> should be non-null and non-empty
- **
- ** ^SIDE-EFECTS:
- ** <str> is "trimmed" to canonical form and special characters are mapped
- ** to a unique code.
- **
- ** ^RETURN-VALUE:
- ** The address of the translated string.
- **
- ** ^ALGORITHM:
- ** - remove all unquoted whitespace following any unquoted "/:=+("
- ** - remove all unquoted whitespace preceding any unquoted "/:=+)"
- ** - compress all unquoted whitespace,
- ** - remove all unquoted parentheses,
- ** - re-map all other unquoted special characters and remove quotes.
- ** use the following mapping:
- ** whitespace ==> '\001'
- ** '/' ==> '\002'
- ** ':' & '=' ==> '\003'
- ** ',' & '+' ==> '\004'
- ***^^**********************************************************************/
- #ifdef __ANSI_C__
- X static char *dcl_strxlat( char *str )
- #endif
- {
- X register char c, *pread = str, *pwrite = str;
- X BOOL quoted = FALSE;
- X
- X /*
- X ** pass1 - scan forward, removing all whitespace after unquoted "/:=+,("
- X */
- X while ( c = *pwrite++ = *pread++ ) {
- X if ( c == '"' ) TOGGLE(quoted);
- X if ( !quoted && strchr("/:=+,(", c) )
- X while( isspace(*pread) ) ++pread;
- X }
- X *--pwrite = '\0'; /* NUL terminate */
- X
- X /*
- X ** pass2 - scan backward, removing all whitespace before unquoted "/:=+,)"
- X */
- X pread = --pwrite; /* set to last NON-NUL char */
- X quoted = FALSE;
- X while ( pread >= str ) {
- X c = *pwrite-- = *pread--;
- X if ( c == '"' ) TOGGLE(quoted);
- X if ( !quoted && strchr("/:=+,)", c) )
- X while( isspace(*pread) ) --pread;
- X }
- X strcpy(str, ++pwrite); /* reset BOS */
- X
- X /*
- X ** pass3 - compress all unquoted whitespace,
- X ** remove all unquoted parentheses,
- X ** re-map all other unquoted special characters and remove quotes.
- X ** use the following mapping:
- X ** whitespace -> '\001'
- X ** '/' -> '\002'
- X ** ':' & '=' -> '\003'
- X ** ',' & '+' -> '\004'
- X */
- X pread = pwrite = str;
- X quoted = FALSE;
- X while ( c = *pread++ ) {
- X if ( c == '"' )
- X TOGGLE(quoted);
- X else if ( !quoted && isspace(c) ) {
- X *pwrite++ = c_SPACE;
- X while( isspace(*pread) ) ++pread;
- X }
- X else if ( !quoted && (c == '(' || c == ')') )
- X continue;
- X else if ( !quoted && c == '/' )
- X *pwrite++ = c_QUAL;
- X else if ( !quoted && (c == ':' || c == '=') )
- X *pwrite++ = c_QSEP;
- X else if ( !quoted && (c == ',' || c == '+') )
- X *pwrite++ = c_LSEP;
- X else
- X *pwrite++ = c;
- X }/*while*/
- X
- X *pwrite = '\0'; /* NUL-terminate */
- X return str;
- }
- X
- X
- /***************************************************************************
- ** ^FUNCTION: dcl_split - split a string up into a vector of DCL tokens
- **
- ** ^SYNOPSIS:
- */
- #ifndef __ANSI_C__
- X static dcl_token_t *dcl_split( str )
- /*
- ** ^PARAMETERS:
- */
- X char *str;
- /* -- the string to split up into tokens
- */
- #endif /* !__ANSI_C__ */
- X
- /* ^DESCRIPTION:
- ** Dcl_split will split a string up into tokens (according to DCL grammar
- ** rules) and will additionally associate each token with a type (namely:
- ** a qualifier, a positional paramater, or the End-of-Tokens symbol).
- **
- ** ^REQUIREMENTS:
- ** Assume dcl_strxlat(str) has already been performed.
- **
- ** ^SIDE-EFFECTS:
- ** <str> is modified in much the same manner as it would have
- ** been modified if it were passed as the vector_string to strsplit().
- **
- ** ^RETURN-VALUE:
- ** A vector of dcl_tokens.
- **
- ** ^ALGORITHM:
- ** - first count the number of tokens and also try to interpret stuff
- ** like "parm1.1/qual1,parm1.2" by replacing the comma with a space.
- ** - allocate space for the vector of DCL tokens.
- ** - assign the approriate value and type for each token.
- **
- ** ^CAVEATS:
- ** Does not treate "/qual=(val1,val2/str,..)" as illegal
- ** ( parses it as if it were "/qual=(val1,val2)/str" )
- **
- ** Replaces "parm1.1/qual,parm1.2" with "parm1.1/qual parm1.2"
- ** which works only because parseargs requires a VMS
- ** positional list to be comma OR whitespace separated
- ** (not just comma separated).
- ***^^**********************************************************************/
- #ifdef __ANSI_C__
- X static dcl_token_t *dcl_split( char *str )
- #endif
- {
- X int tokc = 1; /* number of tokens */
- X dcl_token_t *tokv = (dcl_token_t *)NULL; /* vector of tokens */
- X register char *pread, c;
- X register int i;
- X
- X if ( !str || !(*str) ) return (dcl_token_t *)NULL;
- X
- X /* 1st pass (left-to-right) : count tokens */
- X pread = ( *str == c_QUAL ) ? (str + 1) : str;
- X while ( c = *pread++ ) {
- X if ( c == c_QUAL || c == c_SPACE ) ++tokc;
- X if ( c == c_QUAL ) {
- X /* replace "p1.1/qual,p1.2" with "p1.1/qual p1.2" */
- X char *p, delims[5];
- X
- X sprintf( delims, "%c%c%c%c", c_QSEP, c_LSEP, c_QUAL, c_SPACE );
- X if ( (p = strpbrk((str + 1), delims)) && (*p == c_LSEP) )
- X *p == c_SPACE;
- X }
- X }
- X
- X
- X /* allocate vector */
- X tokv = (dcl_token_t *)malloc( (tokc + 1) * sizeof(dcl_token_t) );
- X if ( tokv == (dcl_token_t *)NULL ) {
- X syserr( "malloc() failed in dcl_split()" );
- X }
- X tokv[ tokc ].type = EndOfLine;
- X tokv[ tokc ].token = CHARNULL;
- X
- X /* 2nd pass (right-to-left) : assign tokens to strings */
- X for ( i = 1, --pread ; pread >= str ; pread-- ) {
- X if ( *pread == c_SPACE || *pread == c_QUAL ) {
- X tokv[ tokc - i ].token = pread + 1;
- X tokv[ tokc - i ].type = ( *pread == c_QUAL ) ? Qualifier : Parameter;
- X *pread = '\0';
- X ++i;
- X }
- X }
- X
- X if ( *str ) { /* then 1st char could NOT have been '/' */
- X tokv -> token = str;
- X tokv -> type = Parameter;
- X }
- X
- X return tokv;
- }
- X
- X
- /***************************************************************************
- ** ^FUNCTION: dcl_restore - restore the `escaped' characters in a token
- **
- ** ^SYNOPSIS:
- */
- #ifndef __ANSI_C__
- X static char *dcl_restore( tokstr )
- /*
- ** ^PARAMETERS:
- */
- X char *tokstr;
- /* -- the token string to restore
- */
- #endif /* !__ANSI_C__ */
- X
- /* ^DESCRIPTION:
- ** Dcl_restore will attempt to restore any DCL special characters (such as
- ** '/' and '=') that may have been escaped by dcl_strxlat().
- **
- ** ^REQUIREMENTS:
- ** tokstr should be non-null and non-empty
- **
- ** ^SIDE-EFFECTS:
- ** Any escape characters (such as c_QUAL) are restored to their ascii
- ** representation.
- **
- ** ^RETURN-VALUE:
- ** The address of the restored string
- **
- ** ^ALGORITHM:
- ** - for each character in tokstr
- ** - if it is special then replace it with its ascii code
- ** end-if
- ** end-for
- **
- ** ^CAVEATS:
- ** The string is not restored to way it was before it was processed by
- ** dcl_strxlat(). Any characters that were removed are still missing.
- ** Furthermore, characters such as ':' and '=' which map to the same
- ** code are not always restored to what they were before but are always
- ** restored to one of the characters (e.g. c_QSEP is always restored to
- ** an '=' character even though it could have been '=' OR ':').
- ***^^**********************************************************************/
- #ifdef __ANSI_C__
- X static char *dcl_restore( char *tokstr )
- #endif
- {
- X register char *str = tokstr;
- X
- X if ( !str || !*str ) return str;
- X
- X for ( ; *str ; str++ ) {
- X switch( *str ) {
- X case c_SPACE : *str = ' '; break;
- X case c_QUAL : *str = '/'; break;
- X case c_QSEP : *str = '='; break;
- X case c_LSEP : *str = ','; break;
- X default : break;
- X }
- X }
- X
- X return tokstr;
- }
- X
- X
- X
- X
- /***************************************************************************
- ** ^FUNCTION: split_list - function to handle ARGLISTs and ARGVECs
- **
- ** ^SYNOPSIS:
- */
- #ifndef __ANSI_C__
- X static BOOL split_list( ad, vp, cmd )
- /*
- ** ^PARAMETERS:
- */
- X ARGDESC *ad;
- /* -- the argument which takes multiple values
- */
- X char *vp;
- /* -- the string of values for the argument
- */
- X ARGDESC *cmd;
- /* -- the command to which the argument belongs
- */
- #endif /* !__ANSI_C__ */
- X
- /* ^DESCRIPTION:
- ** Split_list will split the string containing the set of values into
- ** a set of tokens and will then attempt to convert each token (in the
- ** order given) using the ad_type function of the argument structure.
- **
- ** ^REQUIREMENTS:
- ** <vp> must already be preprocessed by dcl_strxlat to escape any quoted
- ** characters and to map special characters to their corresponding values.
- **
- ** ^SIDE-EFECTS:
- ** Ad has some of its flags modified as well as any modifications that
- ** are made by the ad_type function.
- **
- ** <vp> is modified by strsplit().
- **
- ** ^RETURN-VALUE:
- ** TRUE if all is hunky-dory; FALSE otherwise
- **
- ** ^ALGORITHM:
- ** - Split vp into a vector of tokens
- ** - foreach token
- ** - call ad_type(ad, token, copyf)
- ** end-if
- ** - set the ARGGIVEN and ARGVALGIVEN flags accordingly
- ***^^**********************************************************************/
- #ifdef __ANSI_C__
- X static BOOL split_list( ARGDESC *ad, char *vp, ARGDESC *cmd )
- #endif
- {
- X char **arg_vec = (char **)NULL;
- X int i, arg_num = 0;
- X BOOL err = FALSE;
- X char delims[2];
- X
- X /* set-up delimiter string */
- X *delims = c_LSEP;
- X *(delims + 1) = '\0';
- X
- X /* break string up into to tokens and handle each one */
- X arg_num = strsplit( &arg_vec, vp, delims );
- X for ( i = 0 ; i < arg_num ; i++ ) {
- X vp = arg_vec[i];
- X
- X /* try to convert the type */
- X if ( !HANDLE(ad, dcl_restore(vp), cmd_flags(cmd)) ) err = TRUE;
- X }
- X if ( !err ) BSET( arg_flags(ad), ARGGIVEN | ARGVALGIVEN );
- X
- X if ( ARG_isPOSITIONAL(ad) ) {
- X cmd_list(cmd) = ad;
- X }
- X else {
- X cmd_list(cmd) = ARGDESCNULL;
- X }
- X
- X free( arg_vec );
- X
- X return !err;
- }
- X
- X
- /***************************************************************************
- ** ^FUNCTION: vms_parse - parse VMS/DCL arg-vectors
- **
- ** ^SYNOPSIS:
- */
- #ifndef __ANSI_C__
- X int vms_parse( argv, argd )
- /*
- ** ^PARAMETERS:
- */
- X char *argv[];
- /* -- the vector of string arguments from the command-line
- */
- X ARGDESC argd[];
- /* -- the programmer description of the command and its args
- */
- #endif /* !__ANSI_C__ */
- X
- /* ^DESCRIPTION:
- ** Vms_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-EFECTS:
- ** 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:
- ** - compare argv to the command-line (use the command-line if equal)
- ** - put argv back into a single string and translate it using dcl_strxlat
- ** - reparse the string into DCL tokens using dcl_strsplit
- ** - for each DCL token
- ** - attempt to match the token as a qualifier
- ** - if it is a qualifier
- ** - 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__
- X int vms_parse( char *argv[], ARGDESC argd[] )
- #endif
- {
- X register ARGDESC *ad, *args, *cmd;
- X register char *p;
- X char *avstr;
- X BOOL is_match = FALSE;
- X int parse_error = pe_SUCCESS;
- X dcl_token_t *tok, *tokvec;
- X argName_t keyword;
- X argMask_t saveflags, flags;
- X
- X if ( !argd ) return parse_error;
- X
- X /* initialize command-structure */
- X if ( !CMD_isINIT(argd) ) init_args( argd );
- X cmd = argd;
- X saveflags = cmd_flags(cmd);
- X
- X if ( !argv || !*argv ) return parse_error;
- X
- X (VOID) is_cmdline( (CONST char **)argv, &avstr );
- X BSET( cmd_flags(cmd), pa_COPYF );
- X (VOID) dcl_strxlat( avstr );
- X if ( !avstr || !*avstr ) return parse_error;
- X tokvec = dcl_split( avstr );
- X
- X /* run through the token vector */
- X for ( tok = tokvec ; (p = tok -> token) ; tok++ ) {
- X
- X if ( tok -> type == Qualifier && !BTEST(cmd_state(cmd), ps_NOFLAGS) ) {
- X char c = '\0', *s, delims[2];
- X
- X /* set-up delimiter string */
- X *delims = c_QSEP;
- X *(delims + 1) = '\0';
- X
- X /* skip past qualifier prefix and look for possible argument */
- X s = strpbrk(p, delims);
- X if (s) {
- X c = *s;
- X *s++ = '\0';
- X }
- X
- X is_match = FALSE;
- X for ( args = argd ; args && !is_match ; args = cmd_defargs(args) ) {
- X for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
- X if (arg_type(ad) == argDummy) continue;
- X
- X if (!ARG_isPOSONLY(ad) && match(p, arg_sname(ad)) == 0) {
- X is_match = TRUE;
- X break;
- X }/*if*/
- X }
- X }
- X
- X if (c) *(s-1) = c; /* restore the equal sign */
- X
- X if ( !is_match ) {
- X usrerr("qualifier %s unknown", p);
- X parse_error = pe_SYNTAX;
- X continue;
- X }
- X
- X /* end-qualifiers */
- X if ( arg_type(ad) == argEnd ) {
- X BSET( cmd_state(cmd), ps_NOFLAGS );
- X continue;
- X }
- X /* if usage - just print usage and exit */
- X if ( arg_type(ad) == argUsage ) {
- X Usage_Requested = TRUE;
- X usage( argd );
- X free( avstr );
- X if ( tokvec ) free( tokvec );
- X cmd_flags(cmd) = saveflags;
- X exit(1);
- X }
- X /* have we seen this one before */
- X flags = arg_flags(ad);
- X if ( ARG_isGIVEN(ad) )
- X BCLEAR( arg_flags(ad), ARGVALGIVEN | ARGVALSEP );
- X
- X /* ARGNOVALs are special, having no value */
- X if ( ! ARG_isVALTAKEN(ad) ) {
- X if ( !HANDLE(ad, dcl_restore(s), cmd_flags(cmd)) ) {
- X arg_flags(ad) = flags;
- X parse_error = pe_SYNTAX;
- X }
- X else {
- X BSET( arg_flags(ad), ARGGIVEN );
- X ad = ARGDESCNULL;
- X }
- X continue;
- X }/*if ARGNOVAL*/
- X
- X /* now get the real value */
- X if ( !s || !(*s) ) {
- X if ( ARG_isVALOPTIONAL(ad) ) {
- X BSET( arg_flags(ad), ARGVALGIVEN );
- X }
- X else {
- X (VOID) get_keyword( arg_sname(ad), keyword );
- X usrerr("qualifier %s requires an argument", keyword);
- X arg_flags(ad) = flags;
- X parse_error = pe_SYNTAX;
- X }
- X continue;
- X }/*if*/
- X
- X if( ARG_isMULTIVAL(ad) ) {
- X if( !split_list(ad, s, cmd) ) {
- X arg_flags(ad) = flags;
- X parse_error = pe_SYNTAX;
- X }
- X else {
- X BSET( arg_flags(ad), ARGGIVEN | ARGVALGIVEN );
- X }
- X continue;
- X }/*if list*/
- X
- X /* try to convert the type */
- X if ( !HANDLE(ad, s, cmd_flags(cmd)) ) {
- X arg_flags(ad) = flags;
- X parse_error = pe_SYNTAX;
- X }
- X else {
- X BSET( arg_flags(ad), ARGGIVEN | ARGVALGIVEN );
- X }
- X
- X continue;
- X }/*if qual*/
- X else {
- X /* parsing a vector of arguments */
- X if ( cmd_list(cmd) ) {
- X ad = cmd_list(cmd);
- X flags = arg_flags(ad);
- X if ( ARG_isGIVEN(ad) )
- X BCLEAR( arg_flags(ad), ARGVALGIVEN | ARGVALSEP );
- X
- X BSET( arg_flags(ad), ARGVALSEP );
- X
- X if( ARG_isMULTIVAL(ad) ) {
- X if( !split_list(ad, p, cmd) ) parse_error = pe_SYNTAX;
- X }
- X else if ( !HANDLE(ad, dcl_restore(p), cmd_flags(cmd)) ) {
- X arg_flags(ad) = flags;
- X parse_error = pe_SYNTAX;
- X }
- X
- X if ( !parse_error ) BSET( arg_flags(ad), ARGGIVEN | ARGVALGIVEN );
- X
- X continue;
- X }
- X /* positional argument */
- X is_match = FALSE;
- X for ( args = argd ; args && !is_match ; args = cmd_defargs(args) ) {
- X for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
- X if (arg_type(ad) == argDummy) continue;
- X
- X if ( ARG_isPOSITIONAL(ad) &&
- X (!ARG_isGIVEN(ad) || ARG_isMULTIVAL(ad)) ) {
- X is_match = TRUE;
- X break;
- X }/*if*/
- X }
- X }
- X
- X if ( !is_match ) {
- X usrerr("too many arguments");
- X parse_error = pe_SYNTAX;
- X continue;
- X }
- X
- X if ( BTEST(cmd_flags(cmd), pa_FLAGS1ST) ) {
- X BSET( cmd_state(cmd), ps_NOFLAGS );
- X }
- X flags = arg_flags(ad);
- X if ( ARG_isGIVEN(ad) )
- X BCLEAR( arg_flags(ad), ARGVALGIVEN | ARGVALSEP );
- X
- X BSET( arg_flags(ad), ARGVALSEP );
- X
- X if( ARG_isMULTIVAL(ad) ) {
- X if( !split_list(ad, p, cmd) ) {
- X arg_flags(ad) = flags;
- X parse_error = pe_SYNTAX;
- X }
- X else {
- X BSET( arg_flags(ad), ARGGIVEN | ARGVALGIVEN );
- X }
- X continue;
- X }/*if list*/
- X
- X /* try to convert */
- X if ( !HANDLE(ad, dcl_restore(p), cmd_flags(cmd)) ) {
- X arg_flags(ad) = flags;
- X parse_error = TRUE;
- X }
- X else {
- X BSET( arg_flags(ad), ARGGIVEN | ARGVALGIVEN );
- X }
- X
- X }/*if parameter*/
- X }/*while*/
- X
- X free( avstr );
- X if ( tokvec ) free( tokvec );
- X cmd_flags(cmd) = saveflags;
- X return parse_error;
- }
- X
- X
- /***************************************************************************
- ** ^FUNCTION: fmtarg - format command-argument syntax
- **
- ** ^SYNOPSIS:
- */
- #ifndef __ANSI_C__
- X static int fmtarg( ad, buf )
- /*
- ** ^PARAMETERS:
- */
- X ARGDESC *ad;
- /* -- pointer to the argument to format
- */
- X char *buf;
- /* -- character buffer to hold the formatted result
- */
- #endif /* !__ANSI_C__ */
- X
- /* ^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-EFECTS:
- ** 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.
- ***^^**********************************************************************/
- #ifdef __ANSI_C__
- X static int fmtarg( const ARGDESC *ad, char *buf )
- #endif
- {
- X /* buf must already be large enough */
- X char * pos;
- X argName_t keyword, name;
- X
- X (VOID) get_name( arg_sname(ad), name );
- X
- X if (ARG_isPOSITIONAL(ad)) {
- X sprintf( buf, "<%s>", name );
- X }
- X else {
- X (VOID) get_keyword( arg_sname(ad), keyword );
- X sprintf( buf, "%c%s", *s_KWD_PFX, keyword );
- X pos = buf + strlen(buf);
- X
- X if ( ARG_isVALTAKEN(ad) && !ARG_isBOOLEAN(ad) && !ARG_isPSEUDOARG(ad) ) {
- X if ( ARG_isVALOPTIONAL(ad)) {
- X sprintf( pos, "[%c<%s>]", *s_ARG_SEP, name );
- X }
- X else {
- X sprintf( pos, "%c<%s>", *s_ARG_SEP, name );
- X }
- X }/*if*/
- X }/*else*/
- X
- X return (int) strlen(buf);
- }
- X
- X
- /***************************************************************************
- ** ^FUNCTION: vms_usage - print a usage message
- **
- ** ^SYNOPSIS:
- */
- #ifndef __ANSI_C__
- X VOID vms_usage( argd, usage_flags )
- /*
- ** ^PARAMETERS:
- */
- X ARGDESC *argd;
- /* -- the command-descriptor array
- */
- X argMask_t usage_flags;
- /* -- flags set by $USAGECNTL
- */
- #endif /* !__ANSI_C__ */
- X
- /* ^DESCRIPTION:
- ** Vms_usage will print the VMS/DCL 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 symbol.
- **
- ** ^REQUIREMENTS:
- ** argd should be a non-null command-line argument-descriptor array
- **
- ** ^SIDE-EFECTS:
- ** 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__
- X void vms_usage( const ARGDESC *argd, argMask_t usage_flags )
- #endif
- {
- X register CONST ARGDESC *ad, *args, *cmd;
- X int max_cols = 80, max_lines = 24;
- X int margin, ll, pl, qualifiers, longest, positionals;
- X BOOL first = TRUE;
- X FILE *fp;
- X
- X if ( !argd ) return;
- X
- X /* initialize command-structure */
- X if ( !CMD_isINIT(argd) ) init_args( (ARGDESC *)argd );
- X cmd = argd;
- X
- X /* get screen size */
- X get_winsize( fileno(stderr), &max_lines, &max_cols );
- X
- X /* force verbose-mode if requested */
- X if ( Usage_Requested ) BSET( usage_flags, usg_VERBOSE );
- X
- X if ( BTEST(usage_flags, usg_NONE) ) return;
- X
- X fp = ( BTEST(usage_flags, usg_PAGED) )
- X ? pgopen( stderr, getenv("USAGE_PAGER") )
- X : stderr;
- X
- X /* allow null argument descriptor */
- X fprintf(fp, "Format: %s", ProgName);
- X
- X ll = strlen( ProgName ) + 8;
- X margin = ll + 1;
- X longest = 0;
- X
- X for ( positionals = 0 ; positionals < 2 ; positionals++ ) {
- X for ( args = argd ; args ; args = cmd_defargs(args) ) {
- X for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
- X argName_t buf, name;
- X
- X /* don't display hidden arguments */
- X if ( ARG_isHIDDEN(ad) ) continue;
- X if ( !positionals && ARG_isPOSITIONAL(ad) ) continue;
- X if ( positionals && !ARG_isPOSITIONAL(ad) ) continue;
- X
- X /* figure out how wide this parameter is (for printing) */
- X pl = fmtarg(ad, buf);
- X
- X if ( pl > longest ) longest = pl;
- X
- X
- X if ( ARG_isMULTIVAL(ad) ) {
- X (VOID) get_name( arg_sname(ad), name );
- X strcat(buf, "[,<");
- X strcat(buf, name);
- X strcat(buf, ">...]");
- X pl += 8 + strlen(name);
- X }
- X if ( !ARG_isREQUIRED(ad) ) {
- X pl += 2; /* [] */
- X }
- X
- X /* see if this will fit */
- X if ( (ll + pl + 1) > (max_cols - first) ) {
- X /* no... start a new line */
- X fprintf(fp, "\n%*s", margin, "");
- X ll = margin;
- X }
- X else {
- X /* yes... just throw in a space */
- X fputc(' ', fp);
- X ++ll;
- X }
- X ll += pl;
- X
- X /* show the argument */
- X if ( ARG_isREQUIRED(ad) ) fputc('[', fp);
- X fprintf(fp, buf);
- X if ( ARG_isREQUIRED(ad) ) fputc(']', fp);
- X
- X first = FALSE; /* not first line anymore */
- X }/*for each ad */
- X }/* for each argd */
- X }/* for each parm-type */
- X
- X fputc('\n', fp);
- X
- X if ( BTEST(usage_flags, usg_DESCRIPTION) ) {
- X CONST char *description = cmd_description(cmd);
- X
- X if ( description && *description ) {
- X fprintf( fp, "Description:\n" );
- X indent_para(fp, max_cols, 8, "", 0, description);
- X fputc( '\n', fp );
- X }
- X }/*if*/
- X
- X if ( !BTEST(usage_flags, usg_VERBOSE) ) {
- X if ( pgactive(fp) ) (VOID) pgclose( fp );
- X return;
- X }
- X
- X qualifiers = 0;
- X for ( positionals = 0 ; positionals < 2 ; positionals++ ) {
- X for ( args = argd ; args ; args = cmd_defargs(args) ) {
- X for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
- X argName_t buf;
- X
- X /* don't display hidden arguments */
- X if ( ARG_isHIDDEN(ad) ) continue;
- X if ( !positionals && ARG_isPOSITIONAL(ad) ) continue;
- X if ( positionals && !ARG_isPOSITIONAL(ad) ) continue;
- X
- X if ( !qualifiers++ ) fprintf(fp, "Qualifiers/Parameters:\n");
- X (VOID) fmtarg(ad, buf);
- X indent_para(fp, max_cols, 8, buf, longest+2, arg_description(ad) );
- X }/*for each ad */
- X }/* for each argd */
- X }/* for each parm-type */
- X
- X if ( pgactive(fp) ) (VOID) pgclose( fp );
- }
- X
- SHAR_EOF
- chmod 0664 parseargs/vms_args.c ||
- echo 'restore of parseargs/vms_args.c failed'
- Wc_c="`wc -c < 'parseargs/vms_args.c'`"
- test 30360 -eq "$Wc_c" ||
- echo 'parseargs/vms_args.c: original size 30360, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- # ============= parseargs/vprintf.c ==============
- if test -f 'parseargs/vprintf.c' -a X"$1" != X"-c"; then
- echo 'x - skipping parseargs/vprintf.c (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- > _shar_wnt_.tmp
- echo 'x - extracting parseargs/vprintf.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'parseargs/vprintf.c' &&
- /* Portable vsprintf by Robert A. Larson <blarson@skat.usc.edu> */
- X
- /* Copyright 1989 Robert A. Larson.
- X * Distribution in any form is allowed as long as the author
- X * retains credit, changes are noted by their author and the
- X * copyright message remains intact. This program comes as-is
- X * with no warentee of fitness for any purpose.
- X *
- X * Thanks to Doug Gwyn, Chris Torek, and others who helped clarify
- X * the ansi printf specs.
- X *
- X * Please send any bug fixes and improvements to blarson@skat.usc.edu .
- X * The use of goto is NOT a bug.
- X */
- X
- /* Feb 7, 1989 blarson First usenet release */
- /* Oct 20, 1990 Brad Appleton -- enclosed in #ifdef BSD for parseargs */
- /* Oct 21, 1990 Brad Appleton -- added test in #ifdef VPRINTF_TEST */
- /* Feb 25, 1990 Brad Appleton -- #included "useful.h" and added #ifdefs
- X * to compile for ANSI-C as well as K&R
- X */
- X
- X
- /* This code implements the vsprintf function, without relying on
- X * the existance of _doprint or other system specific code.
- X *
- X * Define NOVOID if void * is not a supported type.
- X *
- X * Two compile options are available for efficency:
- X * INTSPRINTF should be defined if sprintf is int and returns
- X * the number of chacters formated.
- X * LONGINT should be defined if sizeof(long) == sizeof(int)
- X *
- X * They only make the code smaller and faster, they need not be
- X * defined.
- X *
- X * UNSIGNEDSPECIAL should be defined if unsigned is treated differently
- X * than int in argument passing. If this is definded, and LONGINT is not,
- X * the compiler must support the type unsingned long.
- X *
- X * Most quirks and bugs of the available sprintf fuction are duplicated,
- X * however * in the width and precision fields will work correctly
- X * even if sprintf does not support this, as will the n format.
- X *
- X * Bad format strings, or those with very long width and precision
- X * fields (including expanded * fields) will cause undesired results.
- X */
- X
- X /* Parseargs only needs this stuff for BSD Unix -- Brad Appleton */
- #include <useful.h>
- X
- #ifdef BSD
- #include <stdio.h>
- #include <ctype.h>
- X
- #ifdef OSK /* os9/68k can take advantage of both */
- # define LONGINT
- # define INTSPRINTF
- #endif
- X
- /* This must be a typedef not a #define! */
- #ifdef NOVOID
- X typedef char *pointer;
- #else
- X typedef void *pointer;
- #endif
- X
- #ifdef INTSPRINTF
- # define Sprintf(string,format,arg) (sprintf((string),(format),(arg)))
- #else
- # define Sprintf(string,format,arg) (\
- X sprintf((string),(format),(arg)),\
- X strlen(string)\
- )
- #endif
- X
- typedef int *intp;
- X
- #ifdef __ANSI_C__
- X int vsprintf(char *dest, register const char *format, va_list args)
- #else
- X int vsprintf(dest, format, args)
- X char *dest;
- X register char *format;
- X va_list args;
- #endif
- {
- X register char *dp = dest;
- X register char c;
- X register char *tp;
- X char tempfmt[64];
- #ifndef LONGINT
- X int longflag;
- #endif
- X
- X tempfmt[0] = '%';
- X while( (c = *format++) != 0) {
- X if(c=='%') {
- X tp = &tempfmt[1];
- #ifndef LONGINT
- X longflag = 0;
- #endif
- continue_format:
- X switch(c = *format++) {
- X case 's':
- X *tp++ = c;
- X *tp = '\0';
- X dp += Sprintf(dp, tempfmt, VA_ARG(args, char *));
- X break;
- X case 'u':
- X case 'x':
- X case 'o':
- X case 'X':
- #ifdef UNSIGNEDSPECIAL
- X *tp++ = c;
- X *tp = '\0';
- #ifndef LONGINT
- X if(longflag)
- X dp += Sprintf(dp, tempfmt, VA_ARG(args, unsigned long));
- X else
- #endif
- X dp += Sprintf(dp, tempfmt, VA_ARG(args, unsigned));
- X break;
- #endif
- X case 'd':
- X case 'c':
- X case 'i':
- X *tp++ = c;
- X *tp = '\0';
- #ifndef LONGINT
- X if(longflag)
- X dp += Sprintf(dp, tempfmt, VA_ARG(args, long));
- X else
- #endif
- X dp += Sprintf(dp, tempfmt, VA_ARG(args, int));
- X break;
- X case 'f':
- X case 'e':
- X case 'E':
- X case 'g':
- X case 'G':
- X *tp++ = c;
- X *tp = '\0';
- X dp += Sprintf(dp, tempfmt, VA_ARG(args, double));
- X break;
- X case 'p':
- X *tp++ = c;
- X *tp = '\0';
- X dp += Sprintf(dp, tempfmt, VA_ARG(args, pointer));
- X break;
- X case '-':
- X case '+':
- X case '0':
- X case '1':
- X case '2':
- X case '3':
- X case '4':
- X case '5':
- X case '6':
- X case '7':
- X case '8':
- X case '9':
- X case '.':
- X case ' ':
- X case '#':
- X case 'h':
- X *tp++ = c;
- X goto continue_format;
- X case 'l':
- #ifndef LONGINT
- X longflag = 1;
- X *tp++ = c;
- #endif
- X goto continue_format;
- X case '*':
- X tp += Sprintf(tp, "%d", VA_ARG(args, int));
- X goto continue_format;
- X case 'n':
- X *VA_ARG(args, intp) = dp - dest;
- X break;
- X case '%':
- X default:
- X *dp++ = c;
- X break;
- X }
- X } else *dp++ = c;
- X }
- X *dp = '\0';
- X return dp - dest;
- }
- X
- X
- #ifdef __ANSI_C__
- X int vfprintf(FILE *dest, register const char *format, va_list args)
- #else
- X int vfprintf(dest, format, args)
- X FILE *dest;
- X register char *format;
- X va_list args;
- #endif
- {
- X register char c;
- X register char *tp;
- X register int count = 0;
- X char tempfmt[64];
- #ifndef LONGINT
- X int longflag;
- #endif
- X
- X tempfmt[0] = '%';
- X while(c = *format++) {
- X if(c=='%') {
- X tp = &tempfmt[1];
- #ifndef LONGINT
- X longflag = 0;
- #endif
- continue_format:
- X switch(c = *format++) {
- X case 's':
- X *tp++ = c;
- X *tp = '\0';
- X count += fprintf(dest, tempfmt, VA_ARG(args, char *));
- X break;
- X case 'u':
- X case 'x':
- X case 'o':
- X case 'X':
- #ifdef UNSIGNEDSPECIAL
- X *tp++ = c;
- X *tp = '\0';
- #ifndef LONGINT
- X if(longflag)
- X count += fprintf(dest, tempfmt, VA_ARG(args, unsigned long));
- X else
- #endif
- X count += fprintf(dest, tempfmt, VA_ARG(args, unsigned));
- X break;
- #endif
- X case 'd':
- X case 'c':
- X case 'i':
- X *tp++ = c;
- X *tp = '\0';
- #ifndef LONGINT
- X if(longflag)
- X count += fprintf(dest, tempfmt, VA_ARG(args, long));
- X else
- #endif
- X count += fprintf(dest, tempfmt, VA_ARG(args, int));
- X break;
- X case 'f':
- X case 'e':
- X case 'E':
- X case 'g':
- X case 'G':
- X *tp++ = c;
- X *tp = '\0';
- X count += fprintf(dest, tempfmt, VA_ARG(args, double));
- X break;
- X case 'p':
- X *tp++ = c;
- X *tp = '\0';
- X count += fprintf(dest, tempfmt, VA_ARG(args, pointer));
- X break;
- X case '-':
- X case '+':
- X case '0':
- X case '1':
- X case '2':
- X case '3':
- X case '4':
- X case '5':
- X case '6':
- X case '7':
- X case '8':
- X case '9':
- X case '.':
- X case ' ':
- X case '#':
- X case 'h':
- X *tp++ = c;
- X goto continue_format;
- X case 'l':
- #ifndef LONGINT
- X longflag = 1;
- X *tp++ = c;
- #endif
- X goto continue_format;
- X case '*':
- X tp += Sprintf(tp, "%d", VA_ARG(args, int));
- X goto continue_format;
- X case 'n':
- X *VA_ARG(args, intp) = count;
- X break;
- X case '%':
- X default:
- X putc(c, dest);
- X count++;
- X break;
- X }
- X } else {
- X putc(c, dest);
- X count++;
- X }
- X }
- X return count;
- }
- X
- #ifdef __ANSI_C__
- X int vprintf(const char *format, va_list args)
- #else
- X int vprintf(format, args)
- X char *format;
- X va_list args;
- #endif
- {
- X return vfprintf(stdout, format, args);
- }
- #endif /* BSD Unix ONLY */
- X
- X /* use a VERY SIMPLE test case to test this out -- Brad Appleton */
- #ifdef VPRINTF_TEST
- X
- /*VARARGS1*/
- #ifdef __ANSI_C__
- X int vtest( char *fmt, ... )
- #else
- X int vtest( fmt, va_alist )
- X char *fmt;
- X va_dcl
- #endif
- {
- X va_list ap;
- X int rc;
- X
- X VA_START(ap, fmt);
- X rc = vprintf( fmt, ap );
- X VA_END(ap);
- X
- X return rc;
- }
- X
- void main()
- {
- X printf( "its a %s %% day in the %d neighborhood for %*s\n",
- X "pitiful", 4, 8, "fun" );
- X
- X vtest( "its a %s %% day in the %d neighborhood for %*s\n",
- X "pitiful", 4, 8, "fun" );
- }
- X
- #endif /* VPRINTF_TEST */
- SHAR_EOF
- chmod 0664 parseargs/vprintf.c ||
- echo 'restore of parseargs/vprintf.c failed'
- Wc_c="`wc -c < 'parseargs/vprintf.c'`"
- test 8146 -eq "$Wc_c" ||
- echo 'parseargs/vprintf.c: original size 8146, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- # ============= parseargs/winsize.c ==============
- if test -f 'parseargs/winsize.c' -a X"$1" != X"-c"; then
- echo 'x - skipping parseargs/winsize.c (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- > _shar_wnt_.tmp
- echo 'x - extracting parseargs/winsize.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'parseargs/winsize.c' &&
- /*************************************************************************
- ** ^FILE: winsize.c - implement the routine get_winsize()
- **
- ** ^DESCRIPTION:
- ** Implement the get_winsize() function for various windowing and
- ** operating systems.
- **
- ** ^HISTORY:
- ** 10/01/90 Brad Appleton <brad@ssd.csd.harris.com> Created
- ***^^**********************************************************************/
- X
- X
- /***************************************************************************
- ** ^FUNCTION: get_winsize - get the current window size
- **
- ** ^SYNOPSIS:
- ** void get_winsize( fd, nrows, ncols )
- **
- ** ^PARAMETERS:
- ** int fd;
- ** -- file-descriptor associated with the "output-window"
- **
- ** int *nrows;
- ** -- pointer to number of rows in window
- **
- ** int *ncols;
- ** -- pointer to number of columns in window
- **
- ** ^DESCRIPTION:
- ** Get_winsize will attempt to determine the maximum number of
- ** rows and colums that will fit on one screen-full of the associated
- ** output device. If it fails to do this, it will assume the "window"
- ** is a 24x80 (rows by columns) display.
- **
- ** ^REQUIREMENTS:
- ** fd must correspond to a valid output device.
- **
- ** ^SIDE-EFFECTS:
- ** The memory addressed by nrows and ncols is assigned the corresponding
- ** appropriate value(s).
- **
- ** ^RETURN-VALUE:
- ** None.
- **
- ** ^ALGORITHM:
- ** System dependent.
- ***^^**********************************************************************/
- X
- #if ( defined(__STDC__) || defined(c_plusplus) || defined(__cplusplus) )
- # define GET_WINSIZE(fd,nrows,ncols) \
- X void get_winsize( int fd, int *nrows, int *ncols )
- #else
- # define GET_WINSIZE(fd,nrows,ncols) \
- X void get_winsize( fd, nrows, ncols ) \
- X int fd, *nrows, *ncols; /* nrows and ncols are passed by reference */
- #endif
- X
- #include <stdio.h>
- #include <useful.h>
- X
- #define DEFAULT_ROWS 24
- #define DEFAULT_COLS 80
- X
- #ifdef vms
- X
- #include <stdio.h>
- #include <iodef.h>
- #include <ssdef.h>
- #include <descrip.h>
- X
- X /* structure to contain terminal characteristics */
- typedef struct {
- X short garb1, cols;
- X char garb2, garb3, garb4, rows;
- } termchar_t;
- X
- int sys$assign();
- int sys$qiow();
- int sys$dassgn();
- X
- GET_WINSIZE( fd, nrows, ncols )
- {
- X int c, charlen = 8;
- X termchar_t termchar;
- X int chan;
- X $DESCRIPTOR( devnam,"SYS$COMMAND" );
- X
- X sys$assign( &devnam, &chan, 0, 0 );
- X sys$qiow( 0, chan, IO$_SENSEMODE, 0, 0, 0, &termchar, &charlen, 0, 0, 0, 0 );
- X sys$dassgn( chan );
- X
- X *nrows = ( termchar.rows > 0 ) ? (int) termchar.rows : DEFAULT_ROWS;
- X *ncols = ( termchar.cols > 0 ) ? (int) termchar.cols : DEFAULT_COLS;
- }
- X
- #else
- #ifdef unix
- X
- X /*
- X ** we will either try to access terminfo through the termcap-interface
- X ** in the curses library (which would require linking with -lcurses)
- X ** or use termcap directly (which would require linking with -ltermcap)
- X */
- #ifndef USE_TERMCAP
- #if ( defined(USE_TERMINFO) || defined(USE_CURSES) )
- #define USE_TERMCAP
- #endif
- #endif
- X
- X
- #ifdef USE_TERMCAP
- # define TERMBUFSIZ 1024
- # define UNKNOWN_TERM "unknown"
- # define DUMB_TERMBUF "dumb:co#80:hc:"
- extern int tgetent();
- extern int tgetnum();
- #endif
- X
- X
- X /* try to get TIOCGWINSZ from termios.h, then from sys/ioctl.h */
- #include <termios.h>
- #if ( !defined(TIOCGWINSZ) && !defined(TIOCGSIZE) && !defined(WIOCGETD) )
- #include <sys/ioctl.h>
- #endif
- X
- X /* if still dont have TIOCGWINSZ (or TIOCGSIZE) try for WIOCGETD */
- #if ( !defined(TIOCGWINSZ) && !defined(TIOCGSIZE) && !defined(WIOCGETD) )
- #include <sgtty.h>
- #endif
- X
- /*
- ** get_winsize() -- determine # of rows/columns that will fit on the screen.
- **
- ** The environment variables $LINES and $COLUMNS will be used if they exist.
- ** If not, then the TIOCGWINSZ call to ioctl() is used (if it is defined).
- ** If not, then the TIOCGSIZE call to ioctl() is used (if it is defined).
- ** If not, then the WIOCGETD call to ioctl() is used (if it is defined).
- ** If not, then get the info from terminfo/termcap (if it is there)
- ** Otherwise, assume we have a 24x80 screen.
- */
- X
- extern int ioctl();
- extern int isatty();
- extern long atol();
- extern char *getenv();
- X
- GET_WINSIZE( fd, nrows, ncols )
- {
- X char *lines_env, *cols_env;
- X long lrow = 0, lcol = 0;
- X int lines = 0, cols = 0;
- #ifdef USE_TERMCAP
- X char term_buf[ TERMBUFSIZ ], *term_env;
- #endif
- #ifdef TIOCGWINSZ
- X struct winsize win;
- #else
- #ifdef TIOCGSIZE
- X struct ttysize win;
- #else
- #ifdef WIOCGETD
- X struct uwdata win;
- #endif
- #endif
- #endif
- X
- X /* make sure that fd corresponds to a terminal */
- X if ( !isatty( fd ) ) {
- X *nrows = DEFAULT_ROWS;
- X *ncols = DEFAULT_COLS;
- X return;
- X }
- X
- X /* LINES & COLUMNS environment variables override everything else */
- X lines_env = getenv( "LINES" );
- X if ( lines_env && (lrow = atol(lines_env)) > 0 ) {
- X *nrows = lines = (int) lrow;
- X }
- X
- X cols_env = getenv( "COLUMNS" );
- X if ( cols_env && (lcol = atol(cols_env)) > 0 ) {
- X *ncols = cols = (int) lcol;
- X }
- X
- #ifdef TIOCGWINSZ
- X /* see what ioctl() has to say (overrides terminfo & termcap) */
- X if ( (!lines || !cols) && ioctl(fd, TIOCGWINSZ, &win) != -1 ) {
- X if ( !lines && win.ws_row > 0 ) {
- X *nrows = lines = (int) win.ws_row;
- X }
- X
- X if ( !cols && win.ws_col > 0 ) {
- X *ncols = cols = (int) win.ws_col;
- X }
- X }/*if*/
- #else
- #ifdef TIOCGSIZE
- X /* see what ioctl() has to say (overrides terminfo & termcap) */
- X if ( (!lines || !cols) && ioctl(fd, TIOCGSIZE, &win) != -1 ) {
- X if ( !lines && win.ts_lines > 0 )
- X *nrows = lines = (int) win.ts_lines;
- X
- X if ( !cols && win.ts_cols > 0 )
- X *ncols = cols = (int) win.ts_cols;
- X }/*if*/
- #else
- #ifdef WIOCGETD
- X /* see what ioctl() has to say (overrides terminfo & termcap) */
- X if ( (!lines || !cols) && ioctl(fd, WIOCGETD, &win) != -1 ) {
- X if ( !lines && win.uw_height > 0 )
- X *nrows = lines = (int) (win.uw_height / win.uw_vs);
- X
- X if ( !cols && win.uw_width > 0 )
- X *ncols = cols = (int) (win.uw_width / win.uw_hs);
- X }/*if*/
- #endif
- #endif
- #endif
- X
- #ifdef USE_TERMCAP
- X /* see what terminfo/termcap has to say */
- X if ( !lines || !cols ) {
- X if ( !(term_env = getenv("TERM")) )
- X term_env = UNKNOWN_TERM;
- X
- X if ( (tgetent(term_buf, term_env) <= 0) )
- X strcpy( term_buf, DUMB_TERMBUF );
- X
- X if ( !lines && (lrow = tgetnum("li")) > 0 )
- X *nrows = lines = (int) lrow;
- X
- X if ( !cols && (lcol = tgetnum("co")) > 0 )
- X *ncols = cols = (int) lcol;
- X }
- #endif
- X
- X /* use 80x24 if all else fails */
- X if ( !lines ) *nrows = DEFAULT_ROWS;
- X if ( !cols ) *ncols = DEFAULT_COLS;
- X
- }/*get_winsize()*/
- X
- #else
- X
- GET_WINSIZE( fd, nrows, ncols )
- {
- X /* just use 80x24 */
- X *nrows = DEFAULT_ROWS;
- X *ncols = DEFAULT_COLS;
- }
- X
- #endif /* not a vms system */
- #endif /* not a unix-system */
- X
- #ifdef WINSIZE_TEST
- X /* test get_winsize to see if it works */
- main()
- {
- X int rows, cols;
- X
- X get_winsize( fileno(stderr), &rows, &cols );
- X printf( "Output will be %d rows by %d columns\n", rows, cols );
- X exit( 0 );
- }
- X
- #endif
- SHAR_EOF
- chmod 0664 parseargs/winsize.c ||
- echo 'restore of parseargs/winsize.c failed'
- Wc_c="`wc -c < 'parseargs/winsize.c'`"
- test 7121 -eq "$Wc_c" ||
- echo 'parseargs/winsize.c: original size 7121, current size' "$Wc_c"
- rm -f _shar_wnt_.tmp
- fi
- # ============= parseargs/xparse.c ==============
- if test -f 'parseargs/xparse.c' -a X"$1" != X"-c"; then
- echo 'x - skipping parseargs/xparse.c (File already exists)'
- rm -f _shar_wnt_.tmp
- else
- > _shar_wnt_.tmp
- echo 'x - extracting parseargs/xparse.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'parseargs/xparse.c' &&
- /*************************************************************************
- ** ^FILE: xparse.c - library functions for the parsargs(3) package
- **
- ** ^DESCRIPTION:
- ** This file implements the following functions in the parseargs library:
- **
- ** init_args() -- constructor for a command-object
- ** usage() -- pretty-print the command-usage
- ** parsecntl() -- control parsing, get/set command-attributes
- ** parseargs() -- parse argumenst from a string vector
- ** fparseargs() -- parse arguments from a file pointer
- ** lparseargs() -- parse arguments from an arglist
- ** sparseargs() -- parse arguyments in a string
- ** vparseargs() -- parse arguments from a variable argument list
- **
- ** It should be noted that sparseargs() splits the given string up into
- ** a whitespace separated series of tokens, whereas vparseargs assumes
- ** that each parameter is already a single token (hence performs no
- ** token splitting).
- **
- ** Each of these functions returns 0 upon success and non-zero otherwise
- ** (except for usage() & init_args, which have no return value).
- **
- ** ^FILES:
- ** <useful.h>
- ** <parseargs.h>
- **
- ** ^SEE_ALSO:
- ** argtype(3), parseargs(1), parseargs(3), parsecntl(3),
- **
- ** ^CAVEATS:
- ** Because of the way argument parsing is implemented under UNIX, MS-DOS
- ** and OS/2, option arguments which contain a leading dash (`-') (or
- ** whatever the option prefix character is defined to be) may not be
- ** specified as a separate argument on the command line, it must be part
- ** of the same argument. That is to say that if a program has a -f option
- ** that requires a string argument, then the following:
- ** -f-arg
- **
- ** will properly assign the string "-arg" to the option whereas the
- ** following:
- ** -f -arg
- **
- ** will be interpreted by parseargs as two option strings: the first of
- ** which ("-f") is missing a required argument and the second of which
- ** ("-arg") will most likely be flagged as an invalid option.
- **
- ** Similarly, if the user requires an ARGLIST option to take multiple
- ** arguments with leading dashes then the following method must be used:
- ** It is a "feature" of parseargs that ARGLIST arguments are always
- ** appended to the current list of arguments for the given option. Thus,
- ** if "-f" is an option taking a list of arguments, then the following
- ** are all equivalent:
- ** -farg1 arg2
- ** -f arg1 arg2
- ** -farg1 -farg2
- ** -f arg1 -f arg2
- **
- ** Hence multiple "leading dash" arguments may specified as follows:
- ** -f-dash_arg1 -f-dash_arg2 ...
- **
- ** ^BUGS:
- ** When a non-multivalued argument appears more than once on the
- ** command-line then only the last value supplied is used. A problem
- ** occurs however in the following scenario: suppose `-s' is an option
- ** that takes an optional string argument (nd suppose `-x' is some
- ** boolean flag). Then if the following command-line is issued:
- **
- ** command -s string -x -s
- **
- ** then, the argument flags will properly correspond to the second
- ** instance of the `-s' option (namely ARGGIVEN will be set but ARGVAL-
- ** GIVEN will be unset) but the value associated with the option will be
- ** "string" (because the first instance overwrote the default).
- ** Because of this, it may be safest to reassign the default value if
- ** ARGGIVEN is set but ARGVALGIVEN is unset.
- **
- ** ^HISTORY:
- ** 01/02/91 Brad Appleton <brad@ssd.csd.harris.com> Created
- ***^^**********************************************************************/
- X
- #include <stdio.h>
- #include <ctype.h>
- #include <useful.h>
- #include "strfuncs.h"
- X
- #define PARSEARGS_PRIVATE /* include private definitions */
- #define PARSEARGS_NEXTERNS /* exclude external declarations */
- #include "parseargs.h"
- X
- #ifdef amiga_style
- # define pa_DEFAULTS 0x000
- # define parse_argv_style amiga_parse
- # define print_usage_style amiga_usage
- X EXTERN int amiga_parse ARGS(( char **, ARGDESC * ));
- X EXTERN VOID amiga_usage ARGS(( const ARGDESC *, argMask_t ));
- #endif
- #ifdef ibm_style
- # define pa_DEFAULTS pa_ANYCASE
- # define parse_argv_style ibm_parse
- # define print_usage_style ibm_usage
- X EXTERN int ibm_parse ARGS(( char **, ARGDESC * ));
- X EXTERN VOID ibm_usage ARGS(( const ARGDESC *, argMask_t ));
- #endif
- #ifdef unix_style
- # define pa_DEFAULTS pa_FLAGS1ST
- # define parse_argv_style unix_parse
- # define print_usage_style unix_usage
- X EXTERN int unix_parse ARGS(( char **, ARGDESC * ));
- X EXTERN VOID unix_usage ARGS(( const ARGDESC *, argMask_t ));
- #endif
- #ifdef vms_style
- # define pa_DEFAULTS pa_PROMPT
- # define parse_argv_style vms_parse
- # define print_usage_style vms_usage
- X EXTERN int vms_parse ARGS(( char **, ARGDESC * ));
- X EXTERN VOID vms_usage ARGS(( const ARGDESC *, argMask_t ));
- #endif
- X
- X
- #if vms
- # define USER_VARIABLE "symbol"
- #else
- # define USER_VARIABLE "environment variable"
- #endif
- X
- X
- /***************************************************************************
- ** ^MACRO: SYNTAX_ERROR - check for syntax errors & missing required arguments
- **
- ** ^SYNOPSIS:
- ** SYNTAX_ERROR(status, argd)
- **
- ** ^PARAMETERS:
- ** status
- ** -- current parsing status returned by last xparsexxx() call
- **
- ** argd
- ** --argdesc-array
- **
- ** ^RETURN-VALUE:
- ** Evaluates to TRUE if need to exit, FALSE otherwise
- **
- ** ^ALGORITHM:
- ** - if (!pa_NOCHECK) and (verify_argreqs == error) then return TRUE
- ** - else return FALSE
- ***^^**********************************************************************/
- #define SYNTAX_ERROR(status, argd) ( !verify_argreqs(argd, &status) )
- X
- X
- /***************************************************************************
- ** ^GLOBAL-VARIABLE: ProgName
- **
- ** ^VISIBILITY:
- ** external global (visible to functions in all files)
- **
- ** ^DESCRIPTION:
- ** ProgName (which is initially NULL) will be used to point to the
- ** command-name (specified on the command-line) of the command that
- ** has most recently invoked a function in the parseargs library.
- ***^^**********************************************************************/
- CONST char *ProgName = (char *)NULL;
- X
- EXTERN VOID syserr ARGS((const char *, ...));
- EXTERN VOID usrerr ARGS((const char *, ...));
- EXTERN VOID eprintf ARGS((const char *, ...));
- X
- #ifdef vms_style
- X EXTERN BOOL argInput ARGS((ARGDESC *, char *, BOOL));
- X EXTERN BOOL argOutput ARGS((ARGDESC *, char *, BOOL));
- #endif
- X
- #define MAXLINE 256
- X
- X
- /* override argument descriptor, if none given by user */
- static ARGDESC Empty_ArgDesc[] = { START_ARGUMENTS, END_ARGUMENTS };
- X
- /***************************************************************************
- ** ^SECTION: DEFAULT-ARGUMENTS
- ** Each argdesc-array has an initial default argument list (which may be
- ** reset using the pc_DEFARGS function code with parsecntl). This initial
- ** default argument-list contains `?' and `H' which may be used as single
- ** character keywords to display command-usage for all command-line
- ** styles. Similarly, "?", "H", and "Help" may be used as long-keywords
- ** to display command-usage for all command-line styles. In Addition,
- ** for VMS style commands, the qualifiers /INPUT=file, /OUTPUT=file, and
- ** /ERROR=file, may be used to redirect stdin, stdout, and stderr
- ** (respectively) to a file. For AmigaDOS style commands, the keyword
- ** "ENDKWDS" may be used to disable parsing for any more keywords on
- ** the command-line.
- ***^^**********************************************************************/
- static ARGDESC Default_ArgDesc[] = {
- X START_ARGUMENTS,
- X
- /* <name> <flags> <type> <valp> <prompt> */
- X { '?', ARGHIDDEN, argUsage, __ NULL, "? (print usage and exit)" },
- X { 'H', ARGHIDDEN, argUsage, __ NULL, "Help (print usage and exit)" },
- X
- #ifdef amiga_style
- X { '-', ARGHIDDEN, argEnd, __ NULL, "ENDKeyWorDS" },
- #endif
- X
- #ifdef vms_style
- X { '<', ARGHIDDEN, argInput, __ stdin, "INPUT (redirect SYS$INPUT)" },
- X { '>', ARGHIDDEN, argOutput, __ stdout, "OUTPUT (redirect SYS$OUTPUT)" },
- X { '%', ARGHIDDEN, argOutput, __ stderr, "ERROR (redirect SYS$ERROR)" },
- #endif
- X
- X END_ARGUMENTS
- };
- X
- X
- #ifdef AmigaDOS
- # define getenv(s) CHARNULL
- # define envfree(s) s = CHARNULL
- #endif
- X
- #if ( defined(MSDOS) || defined(OS2) )
- X EXTERN char *getenv ARGS(( const char * ));
- # define envfree(s) s = CHARNULL
- #endif
- X
- #ifdef unix
- X EXTERN char *getenv ARGS(( const char * ));
- # define envfree(s) s = CHARNULL
- #endif
- X
- #ifdef vms
- # define getenv(s) getsymbol(s)
- # define envfree(s) (s) = ( !(s) ) ? CHARNULL : (free(s), CHARNULL)
- # include <descrip.h>
- # include <libdef.h>
- X
- # define MAXLEN 255
- X
- X /***************************************************************************
- X ** ^FUNCTION: get_symbol - retrieve the value of a VMS symbol
- X **
- X ** ^SYNOPSIS:
- X */
- # ifndef __ANSI_C__
- X char *get_symbol( sym_name )
- X /*
- X ** ^PARAMETERS:
- X */
- X char *sym_name;
- X /* -- name of the symbol to retrieve
- X */
- # endif /* !__ANSI_C__ */
- X
- X /* ^DESCRIPTION:
- X ** Get_symbol will lookup the named symbol and return its value
- X ** as a string.
- X **
- X ** ^REQUIREMENTS:
- X ** sym_name should correspond to the name of a pre-defined symbol.
- X **
- X ** ^SIDE-EFECTS:
- X ** None.
- X **
- X ** ^RETURN-VALUE:
- X ** NULL if the symbol is not found, otherwise it copies the symbol
- X ** value and returns the address of the copy (which may later be
- X ** deallocated using free()).
- X **
- X ** ^ACKNOWLEDGEMENTS:
- X ** Thanx to Jim Barbour for writing most of this code. --BDA
- X **
- X ** ^ALGORITHM:
- X ** Trivial - just use the LIB$GET_SYMBOL system service.
- X ***^^**********************************************************************/
- # ifdef __ANSI_C__
- X char *get_symbol( const char *sym_name )
- # endif
- X {
- X unsigned long stat, lib$get_symbol();
- X unsigned short buflen;
- X char sym_value[ MAXLEN ];
- X $DESCRIPTOR( sym_name_d, sym_name );
- X $DESCRIPTOR( sym_value_d, sym_value );
- X
- X sym_value_d.dsc$w_length = MAXLEN;
- X sym_name_d.dsc$w_length = strlen( sym_name );
- X stat = lib$get_symbol( &sym_name_d, &sym_value_d, &buflen, (void *)0 );
- X if ( stat == LIB$_NOSUCHSYM ) {
- X return CHARNULL;
- X }
- X else if ( ! (stat & 1) ) {
- X exit(stat);
- X }
- X sym_value[ buflen ] = '\0';
- X return strdup( sym_value );
- X }
- #endif /* vms */
- X
- X
- /***************************************************************************
- ** ^FUNCTION: is_interactive - determine if a stream is "interactive"
- **
- ** ^SYNOPSIS:
- */
- #ifndef __ANSI_C__
- X static BOOL is_interactive( fd )
- /*
- ** ^PARAMETERS:
- */
- X int fd;
- /* -- file descriptor associated with the input stream
- */
- #endif /* !__ANSI_C__ */
- X
- /* ^DESCRIPTION:
- ** Is_interactive determines whether or not the given i/o stream is
- ** associated with a terminal.
- **
- ** ^REQUIREMENTS:
- ** Fd must correspond to a valid, open, file-descriptor.
- SHAR_EOF
- true || echo 'restore of parseargs/xparse.c failed'
- fi
- echo 'End of part 11'
- echo 'File parseargs/xparse.c is continued in part 12'
- echo 12 > _shar_seq_.tmp
- exit 0
- exit 0 # Just in case...
- --
- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
- Sterling Software, IMD UUCP: uunet!sparky!kent
- Phone: (402) 291-8300 FAX: (402) 291-4362
- Please send comp.sources.misc-related mail to kent@uunet.uu.net.
-