v17i052: parseargs - functions to parse command line arguments, Part07/12
Brad Appleton
brad at hcx1.ssd.csd.harris.com
Tue Mar 19 01:56:20 AEST 1991
Submitted-by: Brad Appleton <brad at hcx1.ssd.csd.harris.com>
Posting-number: Volume 17, Issue 52
Archive-name: parseargs/part07
This is part 7 of parseargs
#!/bin/sh
# this is Part.07 (part 7 of a multipart archive)
# do not concatenate these parts, unpack them in order with /bin/sh
# file parseargs/parseargs.h continued
#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 7; 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/parseargs.h'
else
echo 'x - continuing file parseargs/parseargs.h'
sed 's/^X//' << 'SHAR_EOF' >> 'parseargs/parseargs.h' &&
** port vectors). An arg-vector is a structure which contains a count, an
** array of elements (i.e. an argc/argv pair), and an array of flags, one
** for each element of argv. There are two macros in defined in
** <parseargs.h> which are used for arg-vectors. ARGVEC_T may be used to
** declare a vector structure or a vector type; ARGVEC_EMPTY may be used
** to initialize the structure. It is strongly recommended that ARGVEC_T
** be used to declare vector types in a typedef statement (particularly
** if one is using function prototypes) but for those who insist, it may
** be used to directly declare a structure. String-vectors will always
** have an extra NULL-pointer at the end such that:
**
** ( StrVec.array[ StrVec.count ] == (char *)NULL )
**
** is always true, and character-vectors will always have an extra NUL-
** character at the end such that:
**
** ( CharVec.array[ CharVec.count ] == '\0' )
**
** is always true. Integer and floating point vectors contain no extra
** "null" elements.
**
** Once created, arg-vectors may be deallocated by calling the macro vec-
** Free or the macro vecDeepFree and passing it the arg-vector structure.
** The differemce between these two macros is that the latter will also
** free each item in the vector that required space to be allocated (at
** the expense of traversing the vector). At this writing, the only
** predefined argument-type(s) that would benefit from vecDeepFree is
** argStr vectors.
**
** An example use of arg-lists, and of arg-vectors follows:
**
** #include <parseargs.h>
**
** typedef ARGVEC_T(char *) strvec_t;
**
** static ArgList *StringList = ARGLISTNULL;
** static strvec_t StringVec = ARGVEC_EMPTY(char *);
** static ARGVEC_T(int) NumberVec = ARGVEC_EMPTY(int);
**
** static
** CMD_OBJECT Args
** CMD_NAME "foo -- do whatever foo does"
** CMD_DESCRIPTION "put a brief paragraph here"
** CMD_ARGUMENTS
** 'l', ARGLIST, listStr, __ &StrList, "LiSt {list of strings}",
** 's', ARGVEC, argStr, __ &StrVec, "STRing {vector of strings}",
** 'i', ARGVEC, argInt, __ &NumVec, "NUMber {vector of numbers}",
** END_ARGUMENTS
** CMD_END
**
** main( int argc, char *argv[] )
** {
** int i, *ls;
**
** if ( parseargs(argv, Args) ) syserr( "parseargs failed" );
**
** for ( ls = StrList, i=1 ; ls ; ls = L_NEXT(ls), i++ )
** printf( "List item %d=%s, flags=%x0\n",
** i, L_STRING(ls), L_FLAGS(ls) );
**
** for ( i = 0 ; i < StrVec.count ; i++ )
** printf( "String[%d]=%s, flags=%x0\n",
** i, StrVec.array[i], StrVec.flags[i] );
**
** for ( i = 0 ; i < NumVec.count ; i++ )
** printf( "Number[%d]=%s, flags=%x0\n",
** i, NumVec.array[i], NumVec.flags[i] );
**
** listFree( StrList );
** StrList = ARGLISTNULL;
**
** vecDeepFree( StrVec, char * );
** vecFree( NumVec, int );
**
** exit( 0 );
** }
**
**^^***********************************************************************/
X
X /* definition of an arg-list */
typedef struct arglist {
X struct arglist *nl_next; /* pointer to next item */
X ARBPTR nl_val; /* value of current item */
X argMask_t nl_flags; /* flags for current item */
} ArgList;
#define ARGLISTNULL (ArgList *)NULL
X
X /* definition of an arg-list-head (the first two fields MUST exactly
X ** overlay with their corresponding elements in an ArgList struct)
X */
typedef struct arglisthead {
X ArgList *nl_next; /* pointer to next item */
X ARBPTR nl_val; /* value of current item */
X argMask_t nl_flags; /* flags for current item */
X ArgList *nl_tail; /* pointer to last item */
} ArgListHead;
#define ARGLISTHEADNULL (ArgListHead *)NULL
X
X /*
X ** macros to manipulate arg-lists
X */
#define L_STRING(ls) ((char *)((ls)->nl_val)) /* Item as a string */
#define L_NEXT(ls) ((ls)->nl_next) /* Next item of list */
#define L_ADVANCE(ls) (ls) = (ArgList *)L_NEXT(ls) /* Advance list ptr */
#define L_FLAGS(ls) ((ls)->nl_flags) /* flags of current item */
X
X /*
X ** macros to declare and initialize arg-vectors
X ** (NOTE: this wont work for vectors of function pointers)
X */
#define ARGVEC_T(type) \
X struct { type *array; unsigned short count; argMask_t *flags; }
#define ARGVEC_EMPTY(type) \
X { (type *) NULL, (unsigned short) 0, (argMask_t *) NULL }
X
X
/**********************************************************************
** ^SECTION: PARSE-FLAGS
** The following bitmasks may be combined in order to modify the
** behavior of the parseargs library. The parse flags for a given
** may be set through the use of the parsecntl() function.
*/
#define pa_PROMPT 0x0001
/* -- Prompt the user for any missing arguments that are required on the
** command-line. No special escaping or quoting is performed on the
** user input. Required arguments that expect a list of values will
** be repeatedly prompted for (one item per line) until a blank line
** (followed by a carriage return) is entered.
*/
#define pa_IGNORE 0x0002
/* -- Ignore any unrecognized or improperly specified command-line arguments
** and continue execution of the program. Normally, if an argument is
** unmatched (or is improperly specified), a usage message is printed
** program execution is terminated.
*/
#define pa_OPTSONLY 0x0004
/* -- Under UNIX, setting this flag will disable the parsing of long-option
** syntax. This will cause all arguments starting with '+' to always be
** treated as a positional parameter (instead of a long-option).
*/
#define pa_KWDSONLY 0x0008
/* -- Under UNIX, setting this flag disables the parsing of single-character
** options. This will cause all arguments starting with '-' to always
** be treated as a positional parameter (instead of an option).
*/
#define pa_FLAGS1ST 0x0010
/* -- Setting this flag causes the parseargs library to force any and all
** non-positional arguments to be specified before any positional ones.
** As an example, under UNIX, if this flag is SET then parseargs will
** consider the command line "cmd -x arg" to consist of one option and
** one positional argument; however the command line "cmd arg -x" would
** be considered to consist of two positional arguments (the -x option
** will be unmatched).
**
** If this flag is UNSET, then both of the previous examples are
** considered to consist of one option and one positional argument.
*/
#define pa_ANYCASE 0x0020
/* -- Setting this flag cause character-case to be ignored when attempting
** to match single-character argument names (i.e. causes "-i" and "-I"
** will be considered equivalent).
*/
#define pa_ARGV0 0x0040
/* -- Normally, the parseargs library will assume that the first argument
** on the command-line is the name of the command. Setting this flag
** tells parseargs that this is NOT the case and that the very first
** argument on the command-line is a bona-fide argument to the command.
*/
#define pa_NOCHECK 0x0080
/* -- Setting this flag will prevent parseargs from checking for any
** required arguments that were not given on the command-line. This
** is useful when more than one call to the parseargs library is needed
** to parse all the command-line arguments (which could occur if the
** command-line argument came from a file or from two argv-vectors).
**
** Keeping this flag on until the final set of arguments is parsed will
** cause parseargs to not check for missing arguments until the last set
** of arguments has been parsed (by the final call to *parseargs).
*/
#define pa_CONTINUE 0x0100
/* -- Setting this flag will cause subsequent calls to the parseargs library
** to NOT reset the current command-state. Hence, all arguments will not
** be initially set to "NOT GIVEN" and other (normal) initializations are
** not be performed. This is useful in conjunction with the pa_NOCHECK
** when more than one call to parseargs is required to parse all the
** command arguments. In this scenario, pa_CONTINUE should be unset (the
** default setting) for the very first call to parseargs, but should then
** be set before any subsequent calls to parseargs are made.
*/
#define pa_NOCMDENV 0x0200
/* -- Setting this flag prevents parseargs from checking the <CMD-NAME>_ARGS
** environment variable for any user-defined default command arguments.
*/
#define pa_COPYF 0x0400
/* -- When this flag is OFF (the default), a value of FALSE is provided as
** the <copyf> argument to all the arg-type (argXxxxx) functions when an
** argument is matched. Setting this flag will cause a value of TRUE to
** be provided as the <copyf> argument to all the arg-type (argXxxxx)
** functions when an argument is matched.
*/
/**^^**********************************************************************/
X
X
/**********************************************************************
** ^SECTION: PARSE-CNTLS - specify which attributes to get/set
** Each of the following function codes specifies an attribute that
** is to be manipulated by parsecntl(3). The function code is the
** second parameter to parsecntl(3). With the exception of pc_ARGFLAGS,
** each of the function codes corresponds to a call to parsecntl(3)
** using four parameters (pc_ARGFLAGS uses 5 parameters). In each case,
** the last parameter is either the address of a buffer to write the
** attribute to, or the actual buffer to read the attribute from
** (depending upon the mode -- the third parameter to parsecntl).
*/
typedef enum {
X pc_PARSEFLAGS,
/* -- get/set parse flags
**
** This function code is used to read and/or modify the existing parsing
** parsing behavior. The fourth parameter to parsecntl should be a
** combination of pc_XXXX bitmasks if the parse-flags are only being
** written, otherwise it should be a pointer to an argMask_t variable.
*/
X pc_ARGFLAGS,
/* -- get/set argument flags
**
** This function code may only be used to read the argument-flags of
** a named argument. It is an error to specify a mode that attempts
** to write the argument-flags with this function code. The fourth
** parameter to parsecntl should be the keyword name of the argument
** whose flags are to be read. The fifth (and final) argument should
** be a pointer to the argMask_t variable which will receive the resulting
** argument-flags.
*/
X pc_DEFARGS,
/* -- get/set the default arguments
**
** This function code is used to query or modify the current default
** argument-descriptor list for the given command. The fourth parameter
** to parsecntl should be the argument-descriptor array to assign as the
** new default-list (or the address of an argdesc-array if the default
** list is being retrieved).
**
** If a given option/qualifier does not appear to match any items in the
** argdesc-array, a default argdesc-array is then searched to match the
** option. If it is STILL unmatched then it is flagged as such. The
** default-argdesc array is automatically used by all programmer-defined
** argdesc-array but may be unset or reset using the pc_DEFARGS function
** of parsecntl(3). In such a manner, a programmer could specify a dif-
** ferent set of default-arguments to search for. Furthermore, default
** argdesc-arrays may also be assigned default argdesc-arrays, thus
** allowing the programmer to define a whole search-list of default
** argdesc-arrays for a given command.
**
** This could prove useful in a situation where a set of commands have a
** few common-options and differ in their remaining ones. If the same
** main() were used for each command, then main could define one common
** argdesc-array and then a set of argdesc-arrays for each command. Main
** could then figure out which argdesc-array to used based on the name in
** argv[0], and set its default argdesc-array to be the common argdesc-
** array, as in the following:
**
** #include <parseargs.h>
** .
** . variable declarations
** .
**
** static ARGDESC common_args[] = {
** STARTOFARGS,
** 'L', ARGOPT, argBool, __ &lflag, "list (list available items)"
** 'I', ARGOPT, argStr, __ &item, "item (specify item to use)",
** ENDOFARGS
** };
**
** static ARGDESC cmd1_args[] = {
** STARTOFARGS,
** 's', ARGOPT, argBool, __ &sflag, "S (set S)",
** 't', ARGOPT, argBool, __ &tflag, "T (set T)",
** ENDOFARGS
** };
**
** static ARGDESC cmd2_args[] = {
** STARTOFARGS,
** 'x', ARGOPT, argBool, __ &xflag, "X (set X)",
** 'y', ARGOPT, argBool, __ &yflag, "Y (set Y)",
** ENDOFARGS
** };
**
** main( argc, argv ) int argc; char *argv[];
** {
** ARGDESC *cmd = cmd1_args;
** int status;
**
** if ( strcmp(*argv, "cmd2") == 0 ) cmd = cmd2_args;
**
** if ( parsecntl( cmd, pc_DEFARGS, pc_WRITE, common_args ) != 0 )
** syserr( "unable to set default args" );
**
** status = parseargs( argv, cmd );
** .
** .
** .
** }
**
** Note that in the above call to parsecntl(3), that zero will be
** returned upon success and non-zero upon failure. If pe_DEFARGS is
** returned, then cmd is already on common_args's list of defaults (and
** would result in an infinite loop while parsing).
*/
X pc_NAME,
/* -- get/set the command-name
*/
X pc_PURPOSE,
/* -- get/set the command-purpose
*/
X pc_DESCRIPTION
/* -- get/set the command-description
*/
/* Each of these last three function codes are used to modify or query the
** name, purpose, or description associated with a command. The fourth
** parameter to parsecntl should be the new string to use (or the address
** of the string, a char** variable, to recieve the current value).
*/
} parsecntl_t;
X
/**^^**********************************************************************/
X
X
/**********************************************************************
** ^SECTION: PARSE-MODES - modes to get/set command attributes.
** Parsecntl may be used to read current command attributes, write/assign
** new command attributes, or both. The mode argument to parsecntl
** determines the which of these three alternatives are desired. If the
** programmer merely wishes to assign new attributes, then invoking
** parsecntl in pc_WRITE mode and passing the new attributes will do the
** job. If the programmer wishes simply to query attributes, then
** invoking parsecntl in pc_READ mode and passing a pointer to the
** desired object in which to write the attribute settings will suffice.
**
** If the programmer wishes to assign new attributes and at the same time
** find out what the attributes were before making the assignment, then
** programmer must invoke parsecntl for pc_RDWR mode and pass a pointer
** to the object containing the new attribute settings; When parsecntl
** returns, then (assuming it returns 0) the desired attributes will have
** been assigned and the object that contained the new attribute settings
** will now contain the attribute settings that were in effect before
** parsecntl was invoked.
*/
typedef enum {
X pc_READ,
/* -- read-mode: attributes are retrieved
*/
X pc_WRITE,
/* -- write-mode: attributes are assigned new values
*/
X pc_RDWR
/* -- read/write-mode: attributes are retrieved and then assigned
*/
X
} parsemode_t;
/**^^**********************************************************************/
X
X
X /*
X ** private (implementation specific) definitions
X */
#ifdef PARSEARGS_PRIVATE
X
X /* macros to define command-line style specific character sequences */
# ifdef amiga_style
# define s_ARG_SEP "=:" /* AmigaDOS argument separator characters */
# endif
# ifdef ibm_style
# define s_ARG_SEP "=" /* MS-DOS and OS/2 argument separator characters */
# endif
# ifdef unix_style
# define c_OPT_PFX '-' /* Unix option prefix character */
# define c_KWD_PFX '+' /* Unix keyword prefix character */
# define s_ARG_SEP "=:" /* Unix keyword-value separator characters */
# endif
# ifdef vms_style
# define s_KWD_PFX "/" /* VMS qualifier prefix character */
# define s_LSI_SEP ",+" /* VMS LiSt Item separator characters */
# define s_ARG_SEP "=:" /* VMS qualifier-value separator characters */
# endif
X
X
X /* call the function to parse the given argument-value string */
# define HANDLE(ad,vp,pflags) ((*arg_type(ad))(ad, vp, BTEST(pflags, pa_COPYF)))
X
X
X /* parse-state flags */
# define ps_OLDSTYLE 0x01 /* force backward compatibility? */
# define ps_NOFLAGS 0x02 /* opt/kwd parsing in effect? */
# define ps_NOCMDENV 0x04 /* <CMD>_ARGS environment-variable parsed? */
# define ps_NOPARSECNTL 0x08 /* PARSECNTL environment-variable parsed? */
X
typedef unsigned char ps_flags_t;
X
X
X /*
X ** structure to hold arg-desc pointers maintained in the command-context
X */
typedef struct {
X ARGDESC *default_argd; /* pointer to default args */
X ARGDESC *current_list; /* pointer to ad with arglist (or argvector)
X ** that is currently being appended.
X */
# ifdef amiga_style
X ARGDESC *previous_ad; /* pointer to previously matched ad */
# endif
} ARGDPTRS;
X
X /*
X ** structures to replace the first and last argument descriptor
X ** in a command (each field must exactly overlay its counterpart
X ** in an ARGDESC struct).
X */
typedef struct {
X char id; /* id is ALWAYS '\0' for first and last ad */
X ps_flags_t state_flags; /* current parse-state */
X CONST char *argv0; /* argv[0] from the command-line */
X ARGDPTRS *argdp; /* structure with ARGDESC pointers */
X CONST char *purpose; /* one-line purpose provided with CMD_NAME */
} CTXDESC; /* the command-context */
X
typedef struct {
X char id; /* id is ALWAYS '\0' for first and last ad */
X argMask_t parse_flags; /* current parse-flag bitmasks */
X CONST char *name; /* command-name provided with CMD_NAME */
X CTXDESC *context; /* pointer to command-context */
X CONST char *description; /* description provided with CMD_DESCRIPTION */
} CMDDESC; /* the command-descriptor */
X
X /*
X ** macros to extract command-line attributes in the command-object
X */
# define cmd_desc(cmd) (CMDDESC *)cmd
# define cmd_id(cmd) (cmd_desc(cmd)) -> id
# define cmd_flags(cmd) (cmd_desc(cmd)) -> parse_flags
# define cmd_name(cmd) (cmd_desc(cmd)) -> name
# define cmd_description(cmd) (cmd_desc(cmd)) -> description
# define cmd_context(cmd) (cmd_desc(cmd)) -> context
# define cmd_ctxid(cmd) (cmd_context(cmd)) -> id
# define cmd_state(cmd) (cmd_context(cmd)) -> state_flags
# define cmd_argv0(cmd) (cmd_context(cmd)) -> argv0
# define cmd_purpose(cmd) (cmd_context(cmd)) -> purpose
# define cmd_ptrs(cmd) (cmd_context(cmd)) -> argdp
# define cmd_defargs(cmd) (cmd_ptrs(cmd)) -> default_argd
# define cmd_list(cmd) (cmd_ptrs(cmd)) -> current_list
# ifdef amiga_style
# define cmd_prev(cmd) (cmd_ptrs(cmd)) -> previous_ad
# endif
X
X /* macro to determine if a command-object has been initialized */
# define CMD_isINIT(cmd) \
X ( !cmd_id(cmd) && cmd_context(cmd) )
X
X /*
X ** macros to help ascertain argument type
X */
# define ARG_isBOOLEAN(ad) \
X ( arg_type(ad) == argBool || arg_type(ad) == argSBool || \
X arg_type(ad) == argUBool || arg_type(ad) == argTBool \
X )
# define ARG_isPSEUDOARG(ad) \
X ( arg_type(ad) == argEnd || \
X arg_type(ad) == argUsage || \
X arg_type(ad) == argDummy \
X )
X
X /*
X ** macros to assist in traversing a command-object
X */
# define ARG_FIRST(cmd) ((cmd) + 1)
# define ARG_LAST(cmd) ( ((ARGDESC *)cmd_context(cmd)) - 1 )
# define ARG_isEND(ad) ( arg_cname(ad) == '\0' )
# define ARG_ADVANCE(ad) (ad)++
# define ARG_RETREAT(ad) (ad)--
X
X
/**********************************************************************
** ^SECTION: USAGECNTL
** Each of the different values in $USAGECNTL corresponds to a
** bitmask as follows:
*/
# define usg_NONE 0x0001
/* -- "Quiet", "Silent", and "None" : dont print usage
*/
# define usg_VERBOSE 0x0002
/* -- "Verbose", "!Terse" : print argument descriptions
*/
# define usg_OPTS 0x0004
/* -- "Options" -- print option syntax
*/
# define usg_LONGOPTS 0x0008
/* -- "LongOpts", "KeyWords" : print long-option/keyword syntax
*/
# define usg_DESCRIPTION 0x0010
/* -- "Description" : print the command description
*/
# define usg_PAGED 0x0020
/* -- "Paged" : pipe the usage message through a paging program
*/
/**^^**********************************************************************/
X
#endif /* PARSEARGS_PRIVATE */
X
X /*
X ** pre-defined types available for ad_type
X */
#ifndef PARSEARGS_NARGTYPES
# define ARGTYPE(name) EXTERN BOOL name ARGS(( ARGDESC *, char *, BOOL ))
X ARGTYPE( argUsage );
X ARGTYPE( argEnd );
X ARGTYPE( argDummy );
X ARGTYPE( argBool );
X ARGTYPE( argSBool );
X ARGTYPE( argUBool );
X ARGTYPE( argTBool );
X ARGTYPE( argChar );
X ARGTYPE( argStr );
X ARGTYPE( argInt );
X ARGTYPE( argShort );
X ARGTYPE( argLong );
X ARGTYPE( argFloat );
X ARGTYPE( argDouble );
X ARGTYPE( listStr );
X EXTERN VOID listFree ARGS((ArgList *argls));
# define vecFree(vec,type) \
X do { \
X if ( vec.count > 0 ) { \
X if ( vec.array ) free( vec.array ); \
X if ( vec.flags ) free( vec.flags ); \
X } \
X vec.array = (type *)NULL; \
X vec.flags = (argMask_t *)NULL; \
X vec.count = 0; \
X } while ( 0 )
# define vecDeepFree(vec,type) \
X do { \
X register int i; \
X \
X for ( i = 0 ; i < vec.count ; i++ ) \
X if ( BTEST(vec.flags[i], ARGCOPYF) ) \
X free( (ARBPTR) vec.array[i] ); \
X \
X if ( vec.count > 0 ) { \
X if ( vec.array ) free( vec.array ); \
X if ( vec.flags ) free( vec.flags ); \
X } \
X vec.array = (type *)NULL; \
X vec.flags = (argMask_t *)NULL; \
X vec.count = 0; \
X } while ( 0 )
X
# undef ARGTYPE
#endif /* PARSEARGS_NARGTYPES */
X
X /*
X ** parseargs library function-prototypes
X */
#ifndef PARSEARGS_NEXTERNS
X EXTERN int fparseargs ARGS(( FILE *, ARGDESC * ));
X EXTERN int lparseargs ARGS(( ArgList *, ARGDESC * ));
X EXTERN int sparseargs ARGS(( char *, ARGDESC * ));
X EXTERN int vparseargs ARGS(( ARGDESC *, int, ...));
X EXTERN int parseargs ARGS(( char **, ARGDESC * ));
X EXTERN int parsecntl ARGS(( ARGDESC *, parsecntl_t, parsemode_t, ...));
X EXTERN VOID usage ARGS(( const ARGDESC * ));
X EXTERN VOID init_args ARGS(( ARGDESC * ));
X extern CONST char *ProgName;
#endif /* PARSEARGS_NEXTERNS */
X
#endif /* PARSEARGS_H */
SHAR_EOF
echo 'File parseargs/parseargs.h is complete' &&
chmod 0664 parseargs/parseargs.h ||
echo 'restore of parseargs/parseargs.h failed'
Wc_c="`wc -c < 'parseargs/parseargs.h'`"
test 42981 -eq "$Wc_c" ||
echo 'parseargs/parseargs.h: original size 42981, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= parseargs/parseargs.pl ==============
if test -f 'parseargs/parseargs.pl' -a X"$1" != X"-c"; then
echo 'x - skipping parseargs/parseargs.pl (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting parseargs/parseargs.pl (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'parseargs/parseargs.pl' &&
;#########################################################################
;# ^FILE: parseargs.pl - parseargs for perl programs
;#
;# ^DESCRIPTION:
;# This file defines a perl function named parseargs to parse
;# command-line arguments for perl scripts.
;#
;# ^HISTORY:
;# 02/25/91 Brad Appleton <brad at ssd.csd.harris.com> Created
;##^^#####################################################################
X
X
;########
;# ^FUNCTION: parseargs - parse command-line argument vectors
;#
;# ^SYNOPSIS:
;# rc = &parseargs( @argv, $argd )
;#
;# ^PARAMETERS:
;# argv -- the vector of command-line arguments (usually ARGV).
;# argd -- the argument-description string
;#
;# ^DESCRIPTION:
;# Parseargs will invoke parseargs(1) to parse the command-line given
;# in <argv> for the command defined by <argd>. The resulting values
;# will be assigned to the variables indicated by the argument-description
;# string.
;#
;# ^REQUIREMENTS:
;# Any desired initial values for variables from the argument-description
;# string should be assigned BEFORE calling this function.
;#
;# The following global variables may be assigned before calling parseargs:
;#
;# PARSEOPTS -- any extra options to pass to parseargs() (default="-u")
;#
;# ^SIDE-EFFECTS:
;# The global variable PARSEARGS will contain the command-line used to
;# invoke parseargs(1).
;#
;# ARGV and ARGC may be reset, all other values are (re)set in <arr>.
;#
;# ^RETURN-VALUE:
;# The exit code returned by parseargs(1).
;#
;# ^ALGORITHM:
;# - set defaults for PARSEOPTS
;# - build the parseargs command (dont forget to quote arguments).
;# - run parseargs(1) and evaluate the output unless $?
;##^^####
X
sub parseargs {
X local(@argv) = @_;
X local($argd);
X local($parse_output);
X local($_);
X local($[) = 0;
X local($i);
X
X $argd = pop( @argv ); ## get last arg and remove it
X
X if ( $PARSEOPTS == "" ) {
X $PARSEOPTS = '-u';
X }
X $PARSEARGS = 'parseargs -s perl ' . $PARSEOPTS . " -- '" . $0 . "'";
X for ( $i = $[ ; $i <= $#argv ; $i++ ) {
X $argv[$i] =~ s/'/'\\''/g;
X $PARSEARGS .= " '" . $argv[$i] . "'";
X }
X $parse_output = `echo \'$argd\' | $PARSEARGS`;
X eval $parse_output unless $?;
X if ( $? ) {
X $! = 0;
X die "\n";
X }
}
X
1;
SHAR_EOF
chmod 0775 parseargs/parseargs.pl ||
echo 'restore of parseargs/parseargs.pl failed'
Wc_c="`wc -c < 'parseargs/parseargs.pl'`"
test 2311 -eq "$Wc_c" ||
echo 'parseargs/parseargs.pl: original size 2311, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= parseargs/parseargs1.txt ==============
if test -f 'parseargs/parseargs1.txt' -a X"$1" != X"-c"; then
echo 'x - skipping parseargs/parseargs1.txt (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting parseargs/parseargs1.txt (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'parseargs/parseargs1.txt' &&
X
X
X
PARSEARGS(1) PARSEARGS(1)
X
X
X
NAME
X parseargs - parse command line arguments in shell scripts
X
SYNOPSIS
X parseargs [-U] [-M] [-T string] [-F string] [-A] [-a arg-
X spec] [-e name] [-f file] [-l] [-o] [-s shell]
X [-u] [-i] [-p] -- name [arguments ...]
X
OPTIONS
X -U just print program usage, do not parse the
X command line
X
X -M just print (n|t)roff -man manual page
X template, do not parse the command line
X
X -T string string to use for true boolean arguments
X (default=``TRUE'')
X
X -F string string to use for false boolean arguments
X (default=``'')
X
X -A modify array behavior for the specified shell.
X
X -a arg-spec argument specification string
X
X -e name read the arg-spec string from the environment
X variable named name
X
X -f file read the arg-spec from file (default=stdin)
X
X -l Long-options only. Disable the parsing of
X (single-character) options.
X
X -o Options only. Disable the parsing of long-
X options (keywords).
X
X -s shell use shell command syntax (default=``sh'')
X
X -u unset positional parameters before assigning
X variables
X
X -p prompt the user for missing required arguments
X
X -i ignore bad command-line syntax and continue
X processing (instead of aborting)
X
ARGUMENTS
X -- Indicates that any remaining options are
X intended for the calling program.
X
X name name of calling program
X
X
X
X
Page 1
X
X
X
X
X
X
PARSEARGS(1) PARSEARGS(1)
X
X
X
X arguments arguments to calling program
X
DESCRIPTION
X Given a command name, a vector of string-valued arguments
X such as that passed to a shell script, and a specification
X string describing the possible arguments, parseargs matches
X actual arguments to possible arguments, converts values to
X the desired type, and diagnoses problems such as missing
X arguments, extra arguments, and argument values that are
X syntactically incorrect. Other behavior such as prompting
X the user for missing arguments and ignoring as command-line
X syntax may be specified on the command-line through the use
X of various options, or through the use of the ``PARSECNTL''
X environment variable.
X
X Given the command name and the argument specification
X string, parseargs -U prints a reasonably friendly version of
X the usage of the calling program on standard diagnostic
X output. The ``verbosity'' of the usage message may be
X controlled through the use of the ``USAGECNTL'' environment
X variable.
X
X Given the command name and the argument specification
X string, parseargs -M prints a template of the command-syntax
X on standard output that is suitable for input to nroff or
X troff using the -man macro package.
X
X The argument specification string contains one entry for
X each possible flag. Entries in the arguments specification
X string are separated by commas. Each entry has five comma-
X separated fields: a name, some flags, a type, a variable-
X name, and a prompt. Each of these fields are described
X below:
X
X name The single character name of the associated flag.
X For example, to indicate that the program is
X expecting a ``-x'' flag, this field would contain
X 'x'. Positional arguments (those without a ``-x''
X prefix) are indicated by passing a ``space''
X character.
X
X flags Flags modifying the semantics of this entry.
X These should have one of ARGREQ to indicate a
X required argument or ARGOPT to indicate an
X optional argument (ARGOPT is the default unless
X ARGREQ is specified). ARGPOS can be ``ored'' in
X to indicate a positional argument that may also be
X keyword matched. ARGNOVAL can be ``ored'' in to
X indicate that an argument is an option or a
X keyword that does not use an accompanying argument
X (such as a boolean flag). This flag is only
X required for corresponding argument types that are
X
X
X
Page 2
X
X
X
X
X
X
PARSEARGS(1) PARSEARGS(1)
X
X
X
X implemented by the programmer; parseargs already
X knows which pre-defined argument types take an
X argument. ARGVALOPT can be ``ored'' in to
X indicate that an argument to the option may be
X optionally supplied on the command-line, but is
X not required. ARGVALREQ can be ``ored'' in to
X indicate that an argument to the option is
X required (this is the default behavior for options
X that take arguments). ARGLIST can be ``ored'' in
X (using the `|' character) to indicate that an
X argument is actually a list of one or more
X arguments from the command line. ARGHIDDEN can be
X ``ored'' in to indicate a flag that should not be
X printed in usage messages - for example, flags
X intended for internal debugging purposes.
X
X type The type of the argument. Existing types include
X argUsage (print usage message and exit), argBool
X and argSBool (set Boolean flags), argUBool (unset
X Boolean flags), argStr (string-valued arguments),
X argChar (char-valued arguments), argInt (native
X integer arguments), argShort (short integer
X arguments), argLong (long integer arguments),
X argFloat (short floating point arguments),
X argDouble (long floating point arguments), and
X argDummy (only used as part of usage message, not
X matched on command-line).
X
X variable The name of the shell variable that should receive
X the converted value.
X
X prompt The string used when prompting interactively for
X argument values, and printed in usage messages.
X This string may be followed by a textual
X description that is enclosed in parentheses,
X square brackets, curly braces, or angle brackets.
X
X The argument specification string must be terminated by the
X single string: ``ENDOFARGS''.
X
X Note that the comma character (',') is used to separate all
X fields within an entry, and to separate the entries
X themselves. For this reason, no field in any entry may
X contain a comma unless it appears inside of double or single
X quotes.
X
X Parseargs will parse all command-line arguments for the
X calling script and match them against the argument
X specification string provided. The argument specification
X string is read from standard input by default but may not
X come from a terminal. The argument specification string may
X be supplied as a single string argument by using the -a
X
X
X
Page 3
X
X
X
X
X
X
PARSEARGS(1) PARSEARGS(1)
X
X
X
X ``string'' flag. Long argument specification strings
X however, may limit the number of arguments to the script if
X there is a limit to the number of arguments and/or
X characters that may appear on the command line. For this
X reason, the argument specification string may be stored: in
X an environment variable using the -e name option; in a file
X and read using the -f file option; or read from standard
X input. When using the -e option, the user must remember to
X use the name of an environment variable (not a mere shell
X variable)! The default behavior is to read the argument
X specification from standard input.
X
SHELLS
X After the command line has been parsed, parseargs will print
X on standard output, a script to set the shell variables
X which correspond to arguments that were present on the
X command-line. This script may be evaluated by redirecting
X it to a file and then executing the file, or by directly
X evaluating the output from parseargs (under most UNIX
X shells, this could be done using eval). If any arguments on
X the command line contained any special characters that
X needed to be escaped from the shell, these characters will
X remain intact (not be evaluated by the shell) in the
X corresponding shell variable.
X
X The -s shell option may be used to tell parseargs which
X shell syntax to use. At present, parseargs only recognizes
X ``sh'', ``csh'', ``ksh'', ``tcsh'', ``bash'', ``rc'',
X ``awk'', and ``perl'' as valid command interpreters. Awk
X output is slightly different from that of the other shells
X in that the actual variable setting are not printed but each
X line of an associative array is printed (the first field is
X the array index, the second is the value for that index).
X If no shell is specified, then the Bourne shell (``sh'')
X will be assumed.
X
X If the user wishes to use a value other than ``TRUE'' for a
X boolean flag that is true, this may be done using the -T
X string option. The same may also be done for a boolean flag
X that is false using the -F string option.
X
X Parseargs will only set the values of variables that
X correspond to arguments that were given on the command line.
X If a particular argument was not supplied on the command
X line, then no assignment is made for the corresponding shell
X variable and it will have the same value that it had before
X parseargs was invoked. The only exception to this is that if
X the -u option is specified, then the positional parameters
X are unset before any shell variable assignments (which may
X reset the positional parameters) are made.
X
X
X
X
X
Page 4
X
X
X
X
X
X
PARSEARGS(1) PARSEARGS(1)
X
X
X
X The double-dash (``--'') which precedes the name and
X arguments of the calling program is needed in order for
X parseargs to be able to distinguish options to itself from
X options for the calling program.
X
X The default behavior of parseargs is allow both single-
X character options and long-options (keywords) on the
X command-line. The user may specify that only options (long-
X options) are to be permitted by specifying the -o (-l)
X option on the command-line.
X
OPTIONS WITH OPTIONAL ARGUMENTS
X Options that may take an optional argument need special
X consideration. The shell programmer needs to know whether
X or not the option was given, and (if given) if it was
X accompanied by an argument. In order to accommodate this
X need, parseargs will set an additional shell variable for
X each argument that is given the ARGVALOPT flag if it is
X supplied on the command line regardless of whether or not it
X was accompanied by its optional argument. If the user has
X defined an option which may optionally take an argument and
X the option appears on the command line with or without its
X associated argument, then the shell variable <name>_flag
X will be assigned the value ``TRUE'' (or the value supplied
X with the -T option to parseargs) where <name> is the name of
X the shell variable associated with the option in the
X argument description string.
X
ARGUMENT LISTS
X Parseargs treats ARGLIST arguments in a special way. The
X method used for setting up an argument list depends largely
X upon the syntax of shell that was specified on the command
X line via the -s option (although ARGLIST arguments are
X treated exactly the same as ARGVEC arguments).
X Resetting the Positional Parameters to an Argument List
X
X For the Bourne, Bourne-Again, and Korn shells, if the
X variable name corresponding to the ARGLIST argument is
X ``--'', then the positional parameters of the calling
X program will be re-assigned to the contents of the argument
X list ($1 will be the first item, $2 the second item, and so
X on). In this particular case, the calling program may wish
X to use the -u option to reset the positional parameters to
X NULL before making any shell-variable assignments (this way,
X the positional parameters will be unset if the associated
X list of command line arguments is not encountered).
X
X Similarly for the C and TC shells, if the variable name
X corresponding to the ARGLIST argument is ``argv'', then the
X positional parameters of the calling program will be re-
X assigned to the contents of the argument list.
X
X
X
X
Page 5
X
X
X
X
X
X
PARSEARGS(1) PARSEARGS(1)
X
X
X
X For the Plan 9 shell (rc), if the variable name
X corresponding to the ARGLIST argument is ``*'', then the
X positional parameters of the calling program will be re-
X assigned to the contents of the argument list.
X
X For the awk and perl, if the variable name corresponding to
X the ARGLIST argument is ``ARGV'', then the positional
X parameters of the calling program will be re-assigned to the
X contents of the argument list.
X Bourne Shell Argument Lists
X
X For the Bourne shell, if the associated variable name is NOT
X ``--'' and the -A option was NOT specified, then that
X variable is treated as a regular shell variable and is
X assigned using the following syntax:
X name='arg1 arg2 ...'
X After invoking parseargs, if you wish to go through all the
X words in the variable name and one of the words in name
X contains an IFS character (such as a space or a tab), then
X that particular word will be treated by the Bourne shell as
X two distinct words.
X
X Also for the Bourne shell, If the associated variable name
X is NOT ``--'' and the -A option WAS specified, then that
X variable is treated as the root name of an array that is set
X using the following syntax:
X name1='arg1'
X name2='arg2'
X ...
X and the variable ``name_count'' will be set to contain the
X number of items in the array. The user may then step
X through all the items in the array using the following
X syntax:
X i=1
X while [ $i -le $name_count ] ; do
X eval echo "item #$i is: " \$name$i
X i=`expr $i + 1`
X done
X Korn Shell Argument Lists
X
X For the Korn shell, if the associated variable name is NOT
X ``--'', then that variable is treated as an array and is
X assigned using the -A option of the set command. The first
X item will be in ${name[0]}, the second item will be in
X ${name[1]}, etc ..., and all items may be given by
X ${name[*]} or ${name[@]}. If the associated variable name
X is NOT ``--'' and the -A option WAS specified, then that
X variable is assigned using the +A option of the set command
X (which preserves any array elements that were not
X overwritten by the set command).
X It should be noted that there is a bug in versions of the
X Korn shell earlier than 11/16/88a, in which the following:
X
X
X
Page 6
X
X
X
X
X
X
PARSEARGS(1) PARSEARGS(1)
X
X
X
X set -A name 'arg1' 'arg2' ...
X causes the positional parameters to be overwritten as an
X unintentional side-effect. If your version of the Korn shell
X is earlier than this and you wish to keep the contents of
X your positional parameters after invoking parseargs than you
X must save them yourself before you call parseargs. This may
X be accomplished by the following:
X set -A save_parms "$@"
X C and TC Shell Argument Lists
X
X For the C and TC shells, ARGLIST variables are treated as
X word-lists and are assigned using the following syntax:
X set name = ( 'arg1' 'arg2' ... )
X The first item will be in $name[1], the second item will be
X in $name[2], etc ..., and all items may be given by $name.
X Notice that Korn shell arrays start at index zero whereas C
X and TC shell word-lists start at index one.
X
X Bourne-Again Shell Argument Lists
X
X At present, the Free Software Foundation's Bourne-Again
X shell is treated exactly the same as the Bourne Shell. This
X will change when bash supports arrays.
X Plan 9 Shell Argument Lists
X
X For the Plan 9 shell, if the associated variable name is not
X ``*'' then it is considered to be word-list and set using
X the following syntax:
X name=( 'arg1' 'arg2' ... )
X
X Awk Argument Lists
X For awk, if the -A option is not given, then the output for
X thes variable-list will be a line with the variable name,
X followed by a line with each of the values (each value will
X be separated with the field separator specified using the -S
X option - which defaults to a space).
X name
X arg1 arg2 ...
X If the -A option is given, then the associated variable is
X considered the root name of an array. The ouput for the
X array will consist of two lines for each item in the list
X (as in the following expample):
X name1
X arg1
X
X name2
X arg2
X
X and the variable ``name_count'' will have an output line
X showing the number of items in the array.
X
X
X
X
X
Page 7
X
X
X
X
X
X
PARSEARGS(1) PARSEARGS(1)
X
X
X
X Perl Argument Lists
X
X For perl, each argument list is considered an array and is
X set using the following syntax:
X @name=( arg1 , arg2 , ... )
X
X
X The word-lists used by the C shell, the arrays used by the
X Korn shell, the Plan 9 shell, awk, perl, and the positional
X parameters used by all shells (if overwritten by parseargs)
X will preserve any IFS characters in their contents. That is
X to say that if an item in one of the aforementioned multi-
X word lists contains any IFS characters, it will not be split
X up into multiple items but will remain a single item which
X contains IFS characters.
X
SUPPLYING DEFAULT ARGUMENTS
X Programs that use parseargs may be given default arguments
X under UNIX and PCs through the use of environment variables
X (symbols are used for VMS systems). If a C-program or
X shell-script uses parseargs to implement a command named
X ``cmd'' then the environment variable ``CMD_ARGS'' will be
X parsed for any "default" arguments before the command-line
X is parsed. The command-line will over-ride any options that
X are specified in this environment variable (except that
X ARGLISTs and ARGVECs set in ``CMD_ARGS'' will be appended
X from the command-line
X
X It is important to note that the contents of the
X ``CMD_ARGS'' environment variable are NOT expanded by the
X shell and hence any special characters (such as quotes or
X back-slashes) will NOT be escaped or removed by parseargs.
X Furthermore, it will not be possible to try and use a tab,
X space, or newline character in the environment variable as
X anything other than an argument separator.
X
X Lastly, parts of an option specification in ``CMD_ARGS'' may
X NOT be continued on the command-line. As an example, if -f
X requires an argument and CMD_ARGS="-f", then the command-
X line "cmd bah" will NOT assign "bah" as the argument to -f
X but will instead complain about a missing argument for -f.
X Similarly, if -l takes a list of arguments and CMD_ARGS="-l
X item1 item2", then the command-line "cmd bah", will NOT
X assign "bah" to the end of the list containing "item1" and
X "item2" but will instead treat "bah" as the first positional
X parameter on the command-line.
X
PARSING BEHAVIOR
X The programmer may control parsing behavior through the use
X of parsecntl(3). The user may set his (or her) own desired
X parsing behavior through the use of the ``PARSECNTL''
X environment variable. By indicating any number of flags
X
X
X
Page 8
X
X
X
X
X
X
PARSEARGS(1) PARSEARGS(1)
X
X
X
X (possibly negated) the user will directly modify the
X behavior of the parseargs library. Flags may be combined by
X placing a `+' or `|' character in between flags. A switch is
X negated by immediately preceding it with a `!' or `-'
X character. The possible ``flags'' are given by the
X following table. Flags are case-insensitive.
X
X Prompt
X Prompt the user for any missing arguments that are
X required on the command-line. No special escaping or
X quoting is performed on the user input. Required
X arguments that expect a list of values will be
X repeatedly prompted for (one item per line) until a
X blank line (followed by a carriage return) is entered.
X
X Ignore
X Ignore any unrecognized or improperly specified
X command-line arguments and continue execution of the
X program. Normally, if an argument is unmatched (or is
X improperly specified), a usage message is printed
X program execution is terminated.
X
X OptsOnly
X Under UNIX, setting this flag will disable the parsing
X of long-option syntax. This will cause all arguments
X starting with '+' to always be treated as a positional
X parameter (instead of a long-option).
X
X KwdsOnly
X Under UNIX, setting this flag disables the parsing of
X single-character options. This will cause all
X arguments starting with '-' to always be treated as a
X positional parameter (instead of an option).
X
X LoptsOnly
X Same as KwdsOnly.
X
X Flags1st
X Setting this flag causes the parseargs library to force
X any and all non-positional arguments to be specified
X before any positional ones. As an example, under UNIX,
X if this flag is SET then parseargs will consider the
X command line "cmd -x arg" to consist of one option and
X one positional argument; however the command line "cmd
X arg -x" would be considered to consist of two
X positional arguments (the -x option will be unmatched).
X
X If this flag is UNSET, then both of the previous
X examples are considered to consist of one option and
X one positional argument.
X
X CaseIgnore
X
X
X
Page 9
X
X
X
X
X
X
PARSEARGS(1) PARSEARGS(1)
X
X
X
X Setting this flag cause character-case to be ignored
X when attempting to match single-character argument
X names (i.e. causes "-i" and "-I" will be considered
X equivalent).
X
X If the environment variable ``PARSECNTL'' is empty or
X undefined, then parsing behavior set by the programmer is
X used. If the programmer has not explicitly used
X parsecntl(3) to modify the parsing behavior will be
X ``!Prompt + !Ignore'' for Unix MS-DOS, OS/2, and AmigaDOS
X systems, and ``Prompt'' for VMS systems.
X
USAGE MESSAGES
X Through the use of an environment variable (or a VMS
X symbol), the user may control the syntax and the verbosity
X of the command-usage messages that are printed by parseargs.
X The desired level of verbosity may be set by defining the
X environment variable ``USAGECNTL" to be a combination of
X strings (case insensitive). The value of each string
X controls one of three different ``modes'' of behavior in the
X displaying of usage messages: The first ``mode'' is
X ``verbose'' mode, which controls whether or not a detailed
X description of each argument should accompany the usual
X command-line sysnopsis. If verbose mode is ``off'', then
X only a command-line synopsis is printed (this is also
X refferred to as ``terse'' mode). The other two ``modes''
X control the displaying of option syntax and long-option
X syntax. A mode may be explicitly disabled by preceding its
X corresponding string with the `!' character. The ``modes''
X which correspond to the possible values of the ``USAGECNTL''
X environment variable are given by the following table.
X
X
X Quiet
X No usage message of any kind is displayed.
X
X Silent
X Same as Quiet.
X
X Paged
X The usage message is piped to a pager. The pager used
X is named by the ``USAGE_PAGER'' environment variable.
X If this variable is unset or empty (or is not the name
X of an executable program) then the pager named by the
X ``PAGER'' environment variable us used. If this
X variable is unset or empty (or is not the name of an
X executable program) then /usr/ucb/more is used.
X
X Description
X The command description is printed.
X
X Terse
X
X
X
Page 10
X
X
X
X
X
X
PARSEARGS(1) PARSEARGS(1)
X
X
X
X Terse mode, just print command-line synopsis.
X
X Verbose
X Verbose mode, print descriptions for each argument
X
X Options
X Option syntax is displayed.
X
X LongOpts
X Long-option syntax is displayed.
X
X KeyWords
X Same as LongOpts.
X
X If the environment variable ``USAGECNTL'' is empty or
X undefined, then the default usage level (which is presently
X ``Verbose + Options'') will be used.
X
EXAMPLES
X As a first example, consider the following argument
X specification for a Bourne shell script:
X
X #!/bin/sh
X
X RepCount=2;
X Verbose="";
X ARGSPEC="
X 'c', ARGOPT, argInt, RepCount, 'count {# times to repeat}',
X 'v', ARGOPT, argBool, Verbose, 'verbose {turn on verbose mode}',
X ' ', ARGREQ, argStr, InFile, 'input {file to read from}',
X ' ', ARGOPT, argStr, OutFile, 'output {file to write to}',
X 'X', ARGHIDDEN, argBool, XRated, 'xrated {naughty! naughty!}',
X ' ', ARGOPT|ARGLIST, listStr, Files, 'files {files to process}',
X ENDOFARGS
X "
X
X eval `echo "$ARGUMENTS" | parseargs -s sh -- $0 "$@"`
X
X This describes a Bourne shell script accepting up to three
X flag arguments and one or two positional arguments, plus a
X list of additional file arguments. Only the first
X positional argument is required. The possible flags (in
X UNIX) are:
X
X -c count An integer repetition count. This defaults
X to two.
X
X -v A Boolean ``verbose'' flag. It defaults to
X FALSE (an empty string).
X
X -X A Boolean ``X Rated'' flag. This is not
X printed in the usage message.
X
X
X
Page 11
X
X
X
X
X
X
PARSEARGS(1) PARSEARGS(1)
X
X
X
X The two positional arguments are both strings, as is the
X final list. If we were to invoke the above script with the
X following command line:
X cmdname -v input_file output_file file1 file2
X
X Then, after invoking parseargs, the following shell
X variables would contain the following values:
X $RepCount would evaluate to ``2''
X
X $Verbose would evaluate to ``TRUE''
X $InFile would evaluate to ``input_file''
X
X $OutFile would evaluate to ``output_file''
X $Files would evaluate to ``file1 file2''
X
X $XRated would be unset and would evaluate to an empty
X string (``'').
X
X
X Now let's present a more complete example. The following
X page shows a Bourne shell script which uses parseargs to
X parse its command line, echoes the settings of all its
X associated command line variables, and then prints its
X command usage.
X
X #!/bin/sh
X # test.sh - Bourne shell script to test out the parseargs command!
X #
X NAME="`basename $0`"; DOT=".";
X
X ARGUMENTS="
X '?', ARGHIDDEN, argUsage, NULL, 'Help : print usage and exit',
X 'S', ARGVALOPT, argStr, string, 'STRing : optional string arg',
X 'g', ARGLIST, argStr, groups, 'newsGROUPS : groups to test',
X 'r', ARGOPT, argInt, count, 'REPcount <# to repeat each group>',
X 'd', ARGOPT, argStr, dirname, 'DIRectory : working directory',
X 'x', ARGOPT, argBool, xflag, 'Xflag : turn on X-mode',
X 'y', ARGOPT, argUBool, yflag, 'Yflag : turn off Y-mode',
X 's', ARGOPT, argChar, sepch, 'SEPchar : field separator',
X 'f', ARGLIST, argStr, files, 'files : files to process',
X 'n', ARGREQ|ARGPOS, argStr, name, 'name : name to use',
X ' ', ARGLIST, argStr, -- , 'argv : any remaining arguments',
X ENDOFARGS
X "
X export ARGUMENTS
X
X yflag='TRUE' ## set defaults (dir="."; count=1; sepch=',') ##
X
X ## parse command-line and save assignments in a temporary file ##
X parseargs -s sh -e ARGUMENTS -u -- "$NAME" "$@" >/tmp/tmp$$
X if [ $? -ne 0 ]
X then rm -f /tmp/tmp$$; exit 2 ## non-zero status (usage given)
X
X
X
Page 12
X
X
X
X
X
X
PARSEARGS(1) PARSEARGS(1)
X
X
X
X fi
X
X ## evaluate results from parseargs and remove temporary file
X $DOT /tmp/tmp$$; rm -f /tmp/tmp$$
X
X ## echo the parsed arguments (use defaults if not defined)
X echo "ARGUMENTS:"
X echo "=========="
X echo "Name='$name', Count='${count:-1}'"
X echo "XFlag='$xflag', YFlag='$yflag'"
X echo "Directory='${dirname:-"."}', SepChar='${sepch:-","}'"
X echo "Groups='$groups'"
X echo "Files='$files'"
X if [ "$string_flag" ]
X then string=${string:-"!string arg ommitted on cmd-line!"}
X else string="default string"
X fi
X echo "String='$string'"
X echo "New Positional Parameters='$*'"
X
X parseargs -a "$ARGUMENTS" -U "$NAME" ## print usage ##
X
DIAGNOSTICS
X Parseargs may exit with one of the following status codes:
X
X
X -1 Some type of system error occurred during execution,
X causing the program to exit prematurely.
X
X 0 Normal exit status (no problems were encountered).
X
X 1 The calling program specified the -U or the -M option
X to parseargs, or specified an argUsage flag on the
X command line. Only the appropriate message is
X displayed.
X
X 2 A command line syntax error was encountered by
X parseargs. The offending command line argument may have
X been intended for either parseargs or for the calling
X program.
X
X 3 The environment variable that was specified with the -e
X option is either NULL (has an empty value) or does not
X exist. Perhaps the user specified a shell variable
X and/or forgot to export it.
X
X 4 A syntax error was encountered in the argument
X specification string that was specified to parseargs.
X
FILES
X /usr/local/parseargs.pl
X This file defines a perl function named parseargs to
X
X
X
Page 13
X
X
X
X
X
X
PARSEARGS(1) PARSEARGS(1)
X
X
X
X parse arguments more conveniently for perl-scripts. The
X function is both documented and implemented in this
X file. The user should ``require'' this file in his/her
X perl-script before invoking the function.
X
X /usr/local/parseargs.awk
X This file defines an awk function named parseargs to
X parse arguments more conveniently for awk-scripts. The
X function is both documented and implemented in this
X file. The user should include this file in his/her
X awk-script before invoking the function.
X
SEE ALSO
X argtype(3), parseargs(3), parsecntl(3)
X
CAVEATS
X Because of the way argument parsing is implemented under
X UNIX, MS-DOS, and OS/2, option arguments which contain a
X leading dash (`-') (or whatever the option prefix character
X is defined to be) may not be specified as a separate
X argument on the command line, it must be part of the same
X argument. That is to say that if a program has a -f option
X that requires a string argument, then the following:
X -f-arg
X
X will properly assign the string ``-arg'' to the option
X whereas the following:
X -f -arg
X
X will be interpreted by parseargs as two option strings: the
X first of which (``-f'') is missing a required argument and
X the second of which (``-arg'') will most likely be flagged
X as an invalid option.
X
X Similarly, if the user requires an ARGLIST option to take
X multiple arguments with leading dashes then the following
X method must be used: It is a ``feature'' of parseargs that
X ARGLIST arguments are always appended to the current list of
X arguments for the given option. Thus, if ``-f'' is an option
X taking a list of arguments, then the following are all
X equivalent:
X -farg1 arg2
X
X -f arg1 arg2
X -farg1 -farg2
X
X -f arg1 -f arg2
X Hence multiple ``leading dash'' arguments may specified as
X follows:
X
X -f-dash_arg1 -f-dash_arg2 ...
X
X
X
X
Page 14
X
X
X
X
X
X
PARSEARGS(1) PARSEARGS(1)
X
X
X
BUGS
X It does not make sense to use any arguments of type argTBool
X since parseargs currently has no way of knowing what the
X initial value of the variable is. For this reason, argTBool
X is not recognized as a valid argument type (even though it
X is used by parseargs(3)). By the same token, since the user
X cannot create their own arguments types on the fly from a
X shell-script, ARGNOVAL is not recognized as a valid argument
X flag.
X
X Commas will not be interpreted properly if any field in the
X argument specification string contains double quotes that
X are nested inside of double quotes, or single quotes that
X are nested inside of single quotes.
X
X Inside the argument specification string, any repeated
X string of commas that does not appear inside of double or
X single quotes will be treated as a single comma.
X
X Text descriptions for argument entries are automatically
X formatted in usage messages. Any attempt by the user to
X include tabs and/or newlines in the description will cause
X it to be formatted improperly.
X
X Parseargs cannot properly preserve any newlines in shell
X variables if the eval command is used to read its output
X (this is a shortcoming of the eval command, not of
X parseargs). If the user is concerned about this particular
X case, then the user should redirect the output from
X parseargs to a temporary file and use the source command in
X csh or the dot command (`.') in sh and ksh, to interpret the
X results; otherwise, newlines will be translated into spaces,
SHAR_EOF
true || echo 'restore of parseargs/parseargs1.txt failed'
fi
echo 'End of part 7'
echo 'File parseargs/parseargs1.txt is continued in part 8'
echo 8 > _shar_seq_.tmp
exit 0
exit 0 # Just in case...
--
Kent Landfield INTERNET: kent at 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 at uunet.uu.net.
More information about the Comp.sources.misc
mailing list