brad@hcx1.ssd.csd.harris.com (Brad Appleton) (03/18/91)
Submitted-by: Brad Appleton <brad@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@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@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.