Brad Appleton <brad@hcx1.ssd.csd.harris.com> (05/18/91)
Submitted-by: Brad Appleton <brad@hcx1.ssd.csd.harris.com> Posting-number: Volume 19, Issue 86 Archive-name: parseargs/patch05e Patch-To: parseargs: Volume 17, Issue 45-57 #!/bin/sh # do not concatenate these parts, unpack them in order with /bin/sh # file PATCH05 continued # if test ! -r _shar_seq_.tmp; then echo 'Please unpack part 1 first!' exit 1 fi (read Scheck if test "$Scheck" != 5; 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 PATCH05' else echo 'x - continuing file PATCH05' sed 's/^X//' << 'SHAR_EOF' >> 'PATCH05' && - ment should be the object itself. - - If mode is pc_READ, then the desired attributes are copied - into the object pointed to by the last parameter. If the - mode is pc_WRITE, then the attributes from the last parame- - ter are copied to the command- object. If mode is pc_RDWR, - then the attributes pointed to by the last parameter are - copied to the command-object, and then the previous value of - these attributes (before they were overwritten) is copied - into the object pointed to by the last parameter. - - If cntl is pc_ARGFLAGS, then the only valid mode is pc_READ. - All other attributes may be written or read by parsecntl. - - FUNCTION CODES - Each of the following function codes specifies an attribute - that is to be manipulated by parsecntl. The function code - is the second parameter to parsecntl. With the exception of - pc_ARGFLAGS, each of the function codes corresponds to a - call to parsecntl 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). - - pc_PARSEFLAGS - 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 - - - - Page 1 - - - - - - - PARSECNTL(3) PARSECNTL(3) - - - - bitmasks if the parse-flags are only being written, - otherwise it should be a pointer to an argMask_t vari- - able. - - pc_ARGFLAGS - 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) argu- - ment should be a pointer to the argMask_t variable - which will receive the resulting argument-flags. - - pc_DEFARGS - 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. In - such a manner, a programmer could specify a different - 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 com- - mand. 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[] = { - - - - Page 2 - - - - - - - PARSECNTL(3) PARSECNTL(3) - - - - STARTOFARGS, - { 'L', ARGOPT, argBool, __ &lflag, "list (list the items)" }, - { 'I', ARGOPT, argStr, __ &item, "item (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( int argc, char *argv[] ) - { - ARGDESC *cmd = cmd1_args; - int rc; - - if ( strcmp(*argv, "cmd2") == 0 ) - cmd = cmd2_args; - - rc = parsecntl( cmd, pc_DEFARGS, pc_WRITE, common_args ); - if ( rc != pe_SUCCESS ) - syserr( "unable to set default args" ); - - rc = 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). - - pc_NAME - - pc_PURPOSE - - pc_DESCRIPTION - Each of these last three function codes are used to - modify or query the name, purpose, or description asso- - ciated with a command. The fourth parameter to - - - - Page 3 - - - - - - - PARSECNTL(3) PARSECNTL(3) - - - - parsecntl should be the new string to use (or the - address of the string, a char** variable, to recieve - the current value). - - PARSE MODES - Parsecntl may be used to read current command attributes, - write (assign) new command attributes, or both. The mode - argument to parsecntl determines which of these three alter- - natives 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 (assum- - ing 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 immediately before parsecntl was invoked. - - 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(3) func- - tion. - - pa_PROMPT - 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 argu- - ments 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. - - pa_IGNORE - Ignore any unrecognized or improperly specified - command-line arguments and continue execution of the - program. Normally, if a required argument is unmatched - (or an argument is improperly specified), a usage mes- - sage is printed program execution is terminated. - - pa_OPTSONLY - 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). - - - - Page 4 - - - - - - - PARSECNTL(3) PARSECNTL(3) - - - - pa_KWDSONLY - Under UNIX, setting this flag disables the parsing of - single-character options. This will cause all argu- - ments starting with `-' to always be treated as a posi- - tional parameter (instead of an option). - - pa_FLAGS1ST - 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 posi- - tional arguments (the -x option will be unmatched). - - If this flag is UNSET, then both of the previous exam- - ples are considered to consist of one option and one - positional argument. - - pa_ANYCASE - Setting this flag will cause character-case to be - ignored when attempting to match single-character argu- - ment names (i.e. causes "-i" and "-I" to be considered - equivalent). - - pa_ARGV0 - 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. - - pa_NOCHECK - 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 one of the functions in - the parseargs library). - - pa_CONTINUE - 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 - - - - Page 5 - - - - - - - PARSECNTL(3) PARSECNTL(3) - - - - to "NOT GIVEN" and other (normal) initializations are - not be performed. This is useful in conjunction with - the pa_NOCHECK flag when more than one call to par- - seargs 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. - - pa_NOCMDENV - Setting this flag prevents parseargs from checking the - CMD-NAME_ARGS environment variable (or symbol) for any - user-defined default command arguments. - - pa_COPYF - 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. Set- - ting this flag will cause a value of TRUE to be pro- - vided as the copyf argument to all the arg-type - (argXxxxx) functions when an argument is matched. - - ARGUMENT FLAGS - These are the possible bitmasks that may be turned ON or OFF - in the ad_flags field of an ARGDESC structure. - - ARGOPT - This flag is actually a dummy flag (i.e. it is the - default). This flag specifies that the command-line - argument is optional (need not appear on the command- - line). It is only needed if no other flags are used to - define the given argument. If other flags are given - and ARGREQ is NOT one of them, then ARGOPT is always - assumed. - - ARGREQ - The associated command argument is required on the - command-line. - - ARGPOS - The associated command argument is positonal. The - difference between using this flag to indicate a posi- - tional argument and between using a blank in the - ad_name field to indicate a positional arguments is the - following: If this flag is set but the ad_name of the - argument is non-blank, then this argument may be - matched either positionally or by keyword. If the - ad_name field is blank, then this argument may only be - matched positionally. - - ARGNOVAL - The associated command argument takes no value (as in - - - - Page 6 - - - - - - - PARSECNTL(3) PARSECNTL(3) - - - - "-x value"); Its mere presence (or lack thereof) on the - command-line is sufficient to determine the necessary - action(s) to take (as in "-x"). Boolean argument types - and Pseudo-argument types automatically default to ARG- - NOVAL. - - ARGVALOPT - This flag is used to indicate that the command-line - argument takes a value (as in "-s string" or - "/str=string") but that the value to this command-line - argument is NOT required (hence simply "-s" or "/str" - is also permissable). - - ARGVALREQ - Another "dummy" flag. Unless ARGNOVAL or ARGVALOPT is - specified, ARGVALREQ is always assumed. This flag indi- - cates that the value to a command-line argument is - required (hence "-s string" is okay but just "-s" is - not). - - ARGHIDDEN - Don't display this argument in usage messages but still - attempt to match it against strings given on the - command-line. - - ARGLIST - A variable number of values are used for this argument - (and hence may use more than one or two argv elements - from the command-line as in "-l val1 val2 ..."). The - list of values must be stored in an ArgList structure - (NOT a vector structure), an the corresponding - argument-type function should be one of the listXxxx - functions. - - ARGVEC - A variable number of values are used for this argument - (and hence may use more than one or two argv elements - from the command-line as in in "-v val1 val2 ..."). The - list of values must be stored in a vector structure - (NOT an ArgList structure). - - The following bitmasks may also be present, but, unlike the - above masks which must be specified by the programmer at - initialization time, the following masks must only be read - (never set) by the programmer. They may be queried by using - the pc_ARGFLAGS function code and the mode pc_READ with par- - secntl(3). - - ARGGIVEN - The argument WAS given on the command-line. - - ARGVALGIVEN - - - - Page 7 - - - - - - - PARSECNTL(3) PARSECNTL(3) - - - - The value for this argument was given on the command- - line. - - ARGVALSEP - The value to this argument was supplied in a separate - argv element from the argument itself (as in "-x value" - as opposed to "-xvalue"). - - ARGKEYWORD - This argument was matched as a keyword (long-form) on - the command-line and not as a single character. - - ARGDESCRIBED - This argument was given a description by the programmer - at initialization. - - ARGCOPYF - This flag is only used for lists and vectors (mul- - tivalued arguments) and is used on a per-item basis. If - it is set, it means that the corresponding value in the - vector/list required space to be allocated (such as the - duplication of a temporary string). - - RETURN VALUE - The functions in the parseargs library will return a value - of zero upon succesful completion. They may however, return - any of the following status codes (which are defined in - <parseargs.h>): - - pe_SYSTEM - A system error occurred. The global variable errno may - indicate the problem (then again, it may not). - - pe_SUCCESS - Success, no errors encountered (zero is returned). - - pe_SYNTAX - A command-line syntax error was encountered - - pe_DEFARGS - An attempt (using parsecntl) was made to change the - default arg-search list of a command to point to an - argdesc-array which already has the given command on - its default arg-search list (which would cause an - infinite loop when attempting to match an unknown - command-line argument). - - pe_NOMATCH - Unable to match the named argument. This occurs when - the argument keyword name passed to parsecntl (using - the pc_ARGFLAGS functions code) was found in the given - argdesc-array or in its default-list. - - - - Page 8 - - - - - - - PARSECNTL(3) PARSECNTL(3) - - - - pe_BADMODE - Bad mode for given command in parsecntl. This occurs - when pc_WRITE or pc_RDWR mode is passed to parsecntl in - conjunction with the pc_ARGFLAGS functions code. Par- - secntl will not modify existing arguments. - - pe_BADCNTL - Bad command for parsecntl. This occurs if an unknown - function-code was passed to parsecntl. - - SIDE EFFECTS - Each of the functions in the parseargs library will set the - external character string ProgName to be the name of the - last command that was operated upon by any of the library - routines. - - When an argument-descriptor array is first encountered by - any of the parseargs library routines, it is initially com- - piled into an intermediate form that is more convenient to - manipulate. As a direct result, it is not advisable to - attempt to index directly into the array to manipulate one - of the argument descriptors (because the argdesc that you - thought was there may actually be somewhere else). After the - array has been given its initial value(s), only parsecntl(3) - should be used to manipulate or query the attributes of an - argument descriptor. - - SEE ALSO - argtype(3), parseargs(3), parseargs(1) - - AUTHOR - Brad Appleton (brad@ssd.csd.harris.com) - Harris Computer Systems, Fort Lauderdale, FL USA - - - - - - - - - - - - - - - - - - - - - - - Page 9 - - - --- 0 ---- diff -cNr ../patchlevel4/patchlevel.h ./patchlevel.h *** ../patchlevel4/patchlevel.h Thu May 2 11:05:47 1991 --- ./patchlevel.h Thu May 2 14:36:20 1991 *************** *** 2,22 **** X ** ^FILE: patchlevel.h - current patchlevel for parseargs X ** X ** ^HISTORY: X ** 04/10/91 Brad Appleton <brad@ssd.csd.harris.com> X ** Patch04 X ** - fixed problem with prompting in xparse.c:prompt_user() ! ** - under vms, getenv was defined to be 'getsymbol', it should be ! ** 'get_symbol' (note the underscore). ! ** - now uses <errno.h> ! ** - parseargs no longer included <fcntl.h> X ** - fix bug in vms_args.c printing '[]' for required args and vis-a-vis ! ** - fixed bug in argInput and argOutput in argtype.c X ** - fixed bug in <os>_args.c where ARGVALGIVEN was improperly being X ** cleared if the argument was a list or a vector. This was causing X ** parseargs(1) to screw up on optional lists. ! ** - fixed bug in strfuncs.c:strnicmp() X ** - changed strfuncs.[ch] so that my version of strdup is always used ! ** (my version dies if malloc failed, others return NULL). X ** - Added some changes for SUN and VAX X ** - Added -1 option to parseargs(1) X ** - Unhid the -# option to parseargs(1) --- 2,36 ---- X ** ^FILE: patchlevel.h - current patchlevel for parseargs X ** X ** ^HISTORY: + ** 04/25/91 Brad Appleton <brad@ssd.csd.harris.com> + ** Patch05 + ** - documented support for zsh in parseargs(1) + ** - added missing call to pclose() in pgopen.c:pgclose() + ** - added zsh to the list of shells supported by parseargs(1) + ** (I have yet to document this in the man-pages) + ** - changed the shell_info structure used by parseargs(1) to + ** represent different shells. It should now be much simpler + ** to add new shells to parseargs.c + ** - fixed a bug in strfuncs.c:basename() for VMS systems + ** - added more comments to explain whats going on in each <os>_args.c + ** - updated the README file to correspond with the patchlevel(s) + ** - updated dependencies in doc/Makefile + ** X ** 04/10/91 Brad Appleton <brad@ssd.csd.harris.com> X ** Patch04 X ** - fixed problem with prompting in xparse.c:prompt_user() ! ** - under VMS, getenv was defined to be 'getsymbol', it should ! ** be 'get_symbol' (note the underscore). ! ** - now includes <errno.h> to declare errno ! ** - parseargs no longer includes <fcntl.h> X ** - fix bug in vms_args.c printing '[]' for required args and vis-a-vis ! ** - fixed bug in argInput and argOutput in argtype.c for VMS X ** - fixed bug in <os>_args.c where ARGVALGIVEN was improperly being X ** cleared if the argument was a list or a vector. This was causing X ** parseargs(1) to screw up on optional lists. ! ** - fixed bug in strfuncs.c:strnicmp() (it was ignoring the length) X ** - changed strfuncs.[ch] so that my version of strdup is always used ! ** (my version exits if malloc failed, others return NULL). X ** - Added some changes for SUN and VAX X ** - Added -1 option to parseargs(1) X ** - Unhid the -# option to parseargs(1) *************** *** 25,31 **** X ** 04/04/91 Brad Appleton <brad@ssd.csd.harris.com> X ** Patch04 (continued) X ** - fixed bug in xparse.c with PARSECNTL='Prompt' being ignored. - ** - added test.pl to test.all and added options to test.all X ** - fixed newline printing error in perl-scripts for parseargs(1) X ** - added -C option to parseargs(1) and to the docs X ** - added "patchlevel.h" to distribution --- 39,44 ---- *************** *** 53,59 **** X X #define VERSION 2 X #define REVISION 0 ! #define PATCHLEVEL 4 X X #ifdef __STDC__ X static const char --- 66,72 ---- X X #define VERSION 2 X #define REVISION 0 ! #define PATCHLEVEL 5 X X #ifdef __STDC__ X static const char *************** *** 60,63 **** X #else X static char X #endif ! _Ident[] = "@(#)parseargs 2.0 patchlevel 4"; --- 73,76 ---- X #else X static char X #endif ! _Ident[] = "@(#)parseargs 2.0 patchlevel 5"; diff -cNr ../patchlevel4/pgopen.c ./pgopen.c *** ../patchlevel4/pgopen.c Thu May 2 11:06:13 1991 --- ./pgopen.c Thu May 2 14:36:23 1991 *************** *** 71,77 **** X extern int strcmp(); X extern int access(); X extern int isatty(); - extern int wait(); X extern unsigned sleep(); X X static void pg_error(); /* broken-pipe exception handler */ --- 71,76 ---- *************** *** 157,163 **** X ** - if we used popen() to open this pager then X ** - call pclose to close the pager-program X ** - unset the SIGPIPE signal-handler - ** - wait for the pager-process to die X ** end-if X ** - reset the pager-file-pointer to NULL X ** - set the pager-state to closed --- 156,161 ---- *************** *** 172,179 **** X fflush( Pager_FP ); X X if ( Pager_Type == PG_ENV || Pager_Type == PG_DFLT ) { ! signal( SIGPIPE, (void (*)())SIG_IGN ); ! wait( (int *) 0 ); X } X X Pager_FP = (FILE *)NULL; --- 170,177 ---- X fflush( Pager_FP ); X X if ( Pager_Type == PG_ENV || Pager_Type == PG_DFLT ) { ! (VOID) pclose( Pager_FP ); ! (VOID) signal( SIGPIPE, (void (*)())SIG_IGN ); X } X X Pager_FP = (FILE *)NULL; diff -cNr ../patchlevel4/strfuncs.c ./strfuncs.c *** ../patchlevel4/strfuncs.c Thu May 2 11:06:14 1991 --- ./strfuncs.c Thu May 2 14:36:35 1991 *************** *** 12,17 **** --- 12,19 ---- X ** strlcpy() -- copy a string and map to lowercase X ** strupr() -- convert a string to uppercase X ** strlwr() -- convert a string to lowercase + ** stricmp() -- case insensitive comparison of strings + ** strnicmp() -- case insensitive length-limited comparison of strings X ** strdup() -- return a (newly allocated) copy of a string X ** strpbrk() -- return first occurrence of character in a set X ** strspn() -- return length of initial prefix of a character set *************** *** 20,31 **** X ** strrtrim() -- trim rightmost (trailing) characters in a string X ** strtrim() -- trim leading and trailing characters in a string X ** strsplit() -- split a string up into a vector of tokens ! ** strjoin() -- join a vector of token into a single string X ** get_name() -- return the aname (argument-name) of an argument X ** get_keyword() -- return the sname (keyword-name) of an argument X ** match() -- match two keywords (case insensitive) upto a unique prefix - ** stricmp() -- case insensitive comparison of strings - ** strnicmp() -- case insensitive length-limited comparison of strings X ** basename() -- remove the leading directories (and disks) from a path X ** indent_para() -- print an indented hanging paragraph X ** --- 22,31 ---- X ** strrtrim() -- trim rightmost (trailing) characters in a string X ** strtrim() -- trim leading and trailing characters in a string X ** strsplit() -- split a string up into a vector of tokens ! ** strjoin() -- join a vector of tokens into a single string X ** get_name() -- return the aname (argument-name) of an argument X ** get_keyword() -- return the sname (keyword-name) of an argument X ** match() -- match two keywords (case insensitive) upto a unique prefix X ** basename() -- remove the leading directories (and disks) from a path X ** indent_para() -- print an indented hanging paragraph X ** *************** *** 601,607 **** X ** - for i in 0 .. (numtokens - 1) do X ** - vector[i] = token_str X ** - advance token_str to point at the next character past the ! ** righmost NUL-byte (which should be the start of the next token). X ** end-for X ** - return the number of tokens parsed. X ***^^**********************************************************************/ --- 601,607 ---- X ** - for i in 0 .. (numtokens - 1) do X ** - vector[i] = token_str X ** - advance token_str to point at the next character past the ! ** rightmost NUL-byte (which should be the start of the next token). X ** end-for X ** - return the number of tokens parsed. X ***^^**********************************************************************/ *************** *** 680,687 **** X X /* ^DESCRIPTION: X ** Strjoin will make a single string out of the given vector by copying ! ** all the tokens from the given vector (in order) toa newly allocated ! ** string. Each token will be separated by an occurence of <separator>. X ** X ** If <separator> is NULL then a single space is used as the separator. X ** If <separator> is empty, then no separator is used and the tokens are --- 680,687 ---- X X /* ^DESCRIPTION: X ** Strjoin will make a single string out of the given vector by copying ! ** all the tokens from the given vector (in order) to a newly allocated ! ** string. Tokens will be separated by a single occurence of <separator>. X ** X ** If <separator> is NULL then a single space is used as the separator. X ** If <separator> is empty, then no separator is used and the tokens are *************** *** 688,701 **** X ** simply concatenated together. X ** X ** ^REQUIREMENTS: ! ** argv must be non-NULL (it must be a valid address), and must be terminated ! ** by a pointer to NULL (argv[last+1] == NULL). X ** X ** ^SIDE-EFECTS: X ** Storage is allocated. X ** X ** ^RETURN-VALUE: ! ** The addres of the newly-joined results (which should be deallocated X ** using free()). Returns NULL if nothing was joined. X ** X ** ^ALGORITHM: --- 688,701 ---- X ** simply concatenated together. X ** X ** ^REQUIREMENTS: ! ** argv must be non-NULL (it must be a valid address), and must be ! ** terminated by a pointer to NULL (argv[last+1] == NULL). X ** X ** ^SIDE-EFECTS: X ** Storage is allocated. X ** X ** ^RETURN-VALUE: ! ** The address of the newly-joined result (which should be deallocated X ** using free()). Returns NULL if nothing was joined. X ** X ** ^ALGORITHM: *************** *** 1078,1084 **** X X if ( vers ) *vers ='\0'; X if ( ext && (!stricmp(ext, ".COM") || !stricmp(ext, ".EXE")) ) { ! ext = '\0'; X } X X return base; --- 1078,1084 ---- X X if ( vers ) *vers ='\0'; X if ( ext && (!stricmp(ext, ".COM") || !stricmp(ext, ".EXE")) ) { ! *ext = '\0'; X } X X return base; *************** *** 1200,1206 **** X char ch; X X /* print the title */ ! fprintf( fp, "%*s%-*s", margin, "", indent, title ); X X idx = maxcols - margin - indent; X --- 1200,1206 ---- X char ch; X X /* print the title */ ! fprintf( fp, "%*s%-*s", margin, "", indent, title ); X X idx = maxcols - margin - indent; X diff -cNr ../patchlevel4/strfuncs.h ./strfuncs.h *** ../patchlevel4/strfuncs.h Thu May 2 11:06:15 1991 --- ./strfuncs.h Thu May 2 14:36:38 1991 *************** *** 32,37 **** --- 32,38 ---- X EXTERN char *strtrim ARGS(( char *, const char * )); X EXTERN int strsplit ARGS(( char ***, char *, const char * )); X EXTERN char *strjoin ARGS(( const char **, const char * )); + X EXTERN char *get_name ARGS(( const char *, char * )); X EXTERN char *get_keyword ARGS(( const char *, char * )); X EXTERN int match ARGS(( const char *, const char * )); diff -cNr ../patchlevel4/test.ksh ./test.ksh *** ../patchlevel4/test.ksh Thu May 2 10:57:08 1991 --- ./test.ksh Thu May 2 14:36:50 1991 *************** *** 22,33 **** X export ARGUMENTS X X ## set defaults ## - typeset groups[] ## default group used by everyone X typeset count='1' ## only do once unless otherwise specified X typeset dirname='.' ## default to current directory X typeset xflag='' ## default xflag is false X typeset yflag='TRUE' ## default yflag is true X typeset sepch=',' ## default separator is a comma X typeset files[] X X ## parse command-line ## --- 22,33 ---- X export ARGUMENTS X X ## set defaults ## X typeset count='1' ## only do once unless otherwise specified X typeset dirname='.' ## default to current directory X typeset xflag='' ## default xflag is false X typeset yflag='TRUE' ## default yflag is true X typeset sepch=',' ## default separator is a comma + typeset groups[] X typeset files[] X X ## parse command-line ## diff -cNr ../patchlevel4/test.zsh ./test.zsh *** ../patchlevel4/test.zsh Wed Dec 31 18:00:00 1969 --- ./test.zsh Thu May 2 14:36:59 1991 *************** *** 0 **** --- 1,65 ---- + #!/bin/zsh + # + # test.zsh - Z shell script to test out the parseargs command! + # + + NAME="`basename $0`" + + ARGUMENTS=" + '?', ARGHIDDEN, argUsage, NULL, 'Help -- print usage and exit', + 'S', ARGVALOPT, argStr, string, 'STRing -- optional string arg', + 'g', ARGLIST, argStr, groups, 'newsGROUPS -- groups to test', + 'r', ARGOPT, argInt, count, 'REPcount -- number to repeat each group', + 'd', ARGOPT, argStr, dirname, 'DIRectory -- working directory', + 'x', ARGOPT, argBool, xflag, 'Xflag -- turn on X-mode', + 'y', ARGOPT, argUBool, yflag, 'Yflag -- turn off Y-mode', + 's', ARGOPT, argChar, sepch, 'SEPchar -- field separator', + 'f', ARGLIST, argStr, files, 'files -- files to process', + 'n', ARGREQ|ARGPOS, argStr, name, 'name -- name to use', + ' ', ARGLIST, argStr, argv, 'argv -- any remaining arguments', + ENDOFARGS + " + export ARGUMENTS + + ## set defaults ## + typeset count='1' ## only do once unless otherwise specified + typeset dirname='.' ## default to current directory + typeset xflag='' ## default xflag is false + typeset yflag='TRUE' ## default yflag is true + typeset sepch=',' ## default separator is a comma + typeset groups + typeset files + + ## parse command-line ## + parseargs -s zsh -e ARGUMENTS -u -- "$NAME" "$@" >/tmp/tmp$$ + if [ $? -ne 0 ] ; then + rm -f /tmp/tmp$$ + exit 2 ## improper syntax (or just wanted usage) + fi + + ## evaluate results from parseargs and remove temporary file ## + INTERPRET="." + $INTERPRET /tmp/tmp$$ + rm -f /tmp/tmp$$ + + ## print arguments ## + print "ARGUMENTS:" + print "==========" + print "Groups='${groups[@]}'" + print "Count='$count'" + print "Directory='$dirname'" + print "XFlag='$xflag'" + print "YFlag='$yflag'" + print "SepChar='$sepch'" + print "Name='$name'" + print "Files='${files[@]}'" + if [ "$string_flag" ] ; then + string=${string:-"!string arg ommitted on cmd-line!"} + else + string="default string" + fi + print "String='$string'" + print "New Positional Parameters='$*'" + + ## print usage ## + parseargs -a "$ARGUMENTS" -U "$NAME" diff -cNr ../patchlevel4/unix_args.c ./unix_args.c *** ../patchlevel4/unix_args.c Thu May 2 11:06:16 1991 --- ./unix_args.c Thu May 2 14:37:02 1991 *************** *** 128,134 **** X cmd = argd; X X while ( av && (p = *av++) ) { ! if ( isKWD(p) ) { X char *s, c = '\0'; X X /* check for `++' to end flags */ --- 128,134 ---- X cmd = argd; X X while ( av && (p = *av++) ) { ! if ( isKWD(p) ) { /* we have a keyword here */ X char *s, c = '\0'; X X /* check for `++' to end flags */ *************** *** 166,171 **** --- 166,176 ---- X continue; X } X + /* reset the argument flags - if this arg was already given, some + ** of its flags may be set to indicate how it was given before. + ** we need to know how it was given now (but save the old ones + ** just in case the new one fails). + */ X flags = arg_flags(ad); X if ( ARG_isGIVEN(ad) ) { X BCLEAR( arg_flags(ad), ARGVALSEP | ARGKEYWORD ); *************** *** 174,180 **** X X BSET( arg_flags(ad), ARGKEYWORD ); X ! if( ARG_isMULTIVAL(ad) ) { X cmd_list(cmd) = ad; X } X else { --- 179,185 ---- X X BSET( arg_flags(ad), ARGKEYWORD ); X ! if( ARG_isMULTIVAL(ad) ) { /* we matched a list (or a vector) */ X cmd_list(cmd) = ad; X } X else { *************** *** 245,251 **** X continue; X } X ! /* flag argument */ X while (*p) { X X /* find the flag in the list */ --- 250,261 ---- X continue; X } X ! /* We have a flag argument; ! ** remember that in the case of single character keywords, ! ** the conversion function (ad_type) tells us how many characters ! ** were used. We need that information to decide how many ! ** characters to skip before the next iteration of the while loop. ! */ X while (*p) { X X /* find the flag in the list */ *************** *** 276,281 **** --- 286,296 ---- X continue; X }/* if unknown-option */ X + /* reset the argument flags - if this arg was already given, some + ** of its flags may be set to indicate how it was given before. + ** we need to know how it was given now (but save the old ones + ** just in case the new one fails). + */ X flags = arg_flags(ad); X if ( ARG_isGIVEN(ad) ) { X BCLEAR( arg_flags(ad), ARGVALSEP | ARGKEYWORD ); *************** *** 283,289 **** X } X X if( ARG_isMULTIVAL(ad) ) { ! cmd_list(cmd) = ad; X } X else { X cmd_list(cmd) = ARGDESCNULL; --- 298,304 ---- X } X X if( ARG_isMULTIVAL(ad) ) { ! cmd_list(cmd) = ad; /* we matched a list (or a vector) */ X } X else { X cmd_list(cmd) = ARGDESCNULL; *************** *** 358,365 **** X }/*elif option*/ X else { X /* parsing a list of arguments */ ! if ( cmd_list(cmd) ) { X ad = cmd_list(cmd); X flags = arg_flags(ad); X if ( ARG_isGIVEN(ad) ) { X BCLEAR( arg_flags(ad), ARGVALSEP | ARGKEYWORD ); --- 373,386 ---- X }/*elif option*/ X else { X /* parsing a list of arguments */ ! if ( cmd_list(cmd) ) { /* we're in the middle of a list */ X ad = cmd_list(cmd); + + /* reset the argument flags - if this arg was already given, some + ** of its flags may be set to indicate how it was given before. + ** we need to know how it was given now (but save the old ones + ** just in case the new one fails). + */ X flags = arg_flags(ad); X if ( ARG_isGIVEN(ad) ) { X BCLEAR( arg_flags(ad), ARGVALSEP | ARGKEYWORD ); *************** *** 395,400 **** --- 416,426 ---- X continue; X } X + /* reset the argument flags - if this arg was already given, some + ** of its flags may be set to indicate how it was given before. + ** we need to know how it was given now (but save the old ones + ** just in case the new one fails). + */ X flags = arg_flags(ad); X if ( ARG_isGIVEN(ad) ) { X BCLEAR( arg_flags(ad), ARGVALSEP | ARGKEYWORD ); *************** *** 401,410 **** X if ( !ARG_isMULTIVAL(ad) ) BCLEAR( arg_flags(ad), ARGVALGIVEN ); X } X ! if ( ARG_isMULTIVAL(ad) ) { X cmd_list(cmd) = ad; X } X X if ( BTEST(cmd_flags(cmd), pa_FLAGS1ST) ) { X BSET( cmd_state(cmd), ps_NOFLAGS ); X } --- 427,437 ---- X if ( !ARG_isMULTIVAL(ad) ) BCLEAR( arg_flags(ad), ARGVALGIVEN ); X } X ! if ( ARG_isMULTIVAL(ad) ) { /* we positionally matched a list */ X cmd_list(cmd) = ad; X } X + /* if FLAGS1ST is set then first positional marks end-of-flags */ X if ( BTEST(cmd_flags(cmd), pa_FLAGS1ST) ) { X BSET( cmd_state(cmd), ps_NOFLAGS ); X } diff -cNr ../patchlevel4/useful.h ./useful.h *** ../patchlevel4/useful.h Thu May 2 11:06:17 1991 --- ./useful.h Thu May 2 14:37:07 1991 *************** *** 25,31 **** X #ifndef _USEFUL_H_ X #define _USEFUL_H_ X ! #if ( defined(_unix) || defined(UNIX) || defined(__UNIX) ) X # ifndef unix X # define unix X # endif --- 25,31 ---- X #ifndef _USEFUL_H_ X #define _USEFUL_H_ X ! #if (defined(_unix) || defined(__unix) || defined(_unix_) || defined(__unix__)) X # ifndef unix X # define unix X # endif *************** *** 44,50 **** X # ifdef sun X # define BSD X # endif ! # ifdef apollo X # define BSD X # endif X # if ( defined(_CX_UX) && defined(ucb_universe) ) --- 44,50 ---- X # ifdef sun X # define BSD X # endif ! # if ( defined(apollo) || defined(aegis) ) X # define BSD X # endif X # if ( defined(_CX_UX) && defined(ucb_universe) ) *************** *** 203,209 **** X # define FILENULL ((FILE *) NULL) X #endif X ! #ifdef __ANSI_C__ X typedef void *ARBPTR; X #else X typedef char *ARBPTR; --- 203,209 ---- X # define FILENULL ((FILE *) NULL) X #endif X ! #if ( defined(__ANSI_C__) || defined(vms) ) X typedef void *ARBPTR; X #else X typedef char *ARBPTR; diff -cNr ../patchlevel4/vms_args.c ./vms_args.c *** ../patchlevel4/vms_args.c Thu May 2 11:06:18 1991 --- ./vms_args.c Thu May 2 14:37:09 1991 *************** *** 653,659 **** X cmd_flags(cmd) = saveflags; X exit(1); X } ! /* have we seen this one before */ X flags = arg_flags(ad); X if ( ARG_isGIVEN(ad) ) { X BCLEAR( arg_flags(ad), ARGVALSEP ); --- 653,663 ---- X cmd_flags(cmd) = saveflags; X exit(1); X } ! /* reset the argument flags - if this arg was already given, some ! ** of its flags may be set to indicate how it was given before. ! ** we need to know how it was given now (but save the old ones ! ** just in case the new one fails). ! */ X flags = arg_flags(ad); X if ( ARG_isGIVEN(ad) ) { X BCLEAR( arg_flags(ad), ARGVALSEP ); *************** *** 752,760 **** --- 756,771 ---- X continue; X } X + /* if FLAGS1ST is set then first positional marks end-of-flags */ X if ( BTEST(cmd_flags(cmd), pa_FLAGS1ST) ) { X BSET( cmd_state(cmd), ps_NOFLAGS ); X } + + /* reset the argument flags - if this arg was already given, some + ** of its flags may be set to indicate how it was given before. + ** we need to know how it was given now (but save the old ones + ** just in case the new one fails). + */ X flags = arg_flags(ad); X if ( ARG_isGIVEN(ad) ) { X BCLEAR( arg_flags(ad), ARGVALSEP ); diff -cNr ../patchlevel4/winsize.c ./winsize.c *** ../patchlevel4/winsize.c Thu May 2 10:57:14 1991 --- ./winsize.c Thu May 2 14:37:13 1991 *************** *** 46,52 **** X ** System dependent. X ***^^**********************************************************************/ X ! #if ( defined(__STDC__) || defined(c_plusplus) || defined(__cplusplus) ) X # define GET_WINSIZE(fd,nrows,ncols) \ X void get_winsize( int fd, int *nrows, int *ncols ) X #else --- 46,54 ---- X ** System dependent. X ***^^**********************************************************************/ X ! #include <stdio.h> ! ! #ifdef __ANSI_C__ X # define GET_WINSIZE(fd,nrows,ncols) \ X void get_winsize( int fd, int *nrows, int *ncols ) X #else *************** *** 55,63 **** X int fd, *nrows, *ncols; /* nrows and ncols are passed by reference */ X #endif X - #include <stdio.h> - #include <useful.h> - X #define DEFAULT_ROWS 24 X #define DEFAULT_COLS 80 X --- 57,62 ---- *************** *** 67,72 **** --- 66,72 ---- X #include <iodef.h> X #include <ssdef.h> X #include <descrip.h> + #include <useful.h> X X /* structure to contain terminal characteristics */ X typedef struct { *************** *** 127,132 **** --- 127,134 ---- X #if ( !defined(TIOCGWINSZ) && !defined(TIOCGSIZE) && !defined(WIOCGETD) ) X #include <sgtty.h> X #endif + + #include <useful.h> X X /* X ** get_winsize() -- determine # of rows/columns that will fit on the screen. diff -cNr ../patchlevel4/xparse.c ./xparse.c *** ../patchlevel4/xparse.c Thu May 2 11:06:20 1991 --- ./xparse.c Thu May 2 14:37:17 1991 *************** *** 139,145 **** X #endif X X ! #if vms X # define USER_VARIABLE "symbol" X #else X # define USER_VARIABLE "environment variable" --- 139,145 ---- X #endif X X ! #ifdef vms X # define USER_VARIABLE "symbol" X #else X # define USER_VARIABLE "environment variable" *************** *** 180,186 **** X ** command-name (specified on the command-line) of the command that X ** has most recently invoked a function in the parseargs library. X ***^^**********************************************************************/ ! CONST char *ProgName = (char *)NULL; X X EXTERN VOID syserr ARGS((const char *, ...)); X EXTERN VOID usrerr ARGS((const char *, ...)); --- 180,186 ---- X ** command-name (specified on the command-line) of the command that X ** has most recently invoked a function in the parseargs library. X ***^^**********************************************************************/ ! CONST char *ProgName = CHARNULL; X X EXTERN VOID syserr ARGS((const char *, ...)); X EXTERN VOID usrerr ARGS((const char *, ...)); *************** *** 521,527 **** X register ARGDESC *ad, *anchor; X int ad_count = 0; X BOOL old_style = FALSE; ! char *description = (char *)NULL, *purpose = (char *)NULL; X X if ( !argd ) return; X --- 521,527 ---- X register ARGDESC *ad, *anchor; X int ad_count = 0; X BOOL old_style = FALSE; ! char *description = CHARNULL, *purpose = CHARNULL; X X if ( !argd ) return; X *************** *** 1382,1388 **** X BSET( cmd_state(cmd), ps_NOCMDENV ); X X /* split line up into whitespace separated tokens */ ! if ( !strsplit( &argv, env_val, (char *)NULL ) ) { X free( argv ); X return; X } --- 1382,1388 ---- X BSET( cmd_state(cmd), ps_NOCMDENV ); X X /* split line up into whitespace separated tokens */ ! if ( !strsplit( &argv, env_val, CHARNULL ) ) { X free( argv ); X return; X } *************** *** 1874,1880 **** X BSET(cmd_flags(argd), pa_ARGV0); X X /* split line up into whitespace separated tokens */ ! if ( !strsplit( &argv, str, (char *)NULL ) ) { X free( argv ); X return rc; X } --- 1874,1880 ---- X BSET(cmd_flags(argd), pa_ARGV0); X X /* split line up into whitespace separated tokens */ ! if ( !strsplit( &argv, str, CHARNULL ) ) { X free( argv ); X return rc; X } *************** *** 1972,1977 **** --- 1972,1997 ---- X X if ( !CMD_isINIT(argd) ) init_args(argd); X + /* We want the following scenario for the various calls to sparseargs(): + ** assume there are N lines in the input file. Then there will be N + ** calls to sparseargs(). For all calls, we want pa_ARGV0 and pa_COPYF + ** to be ON. Then for the ALL but the very last call, we want pa_NOCHECK + ** to be off. For all but the very first call - we want pa_CONTINUE to + ** be turned ON. So we have the following table: + ** + ** Parse || invocation of sparseargs + ** Flag || 0 | 1 | 2 .. N-1 | N + ** ============++========+===========+=================+=============== + ** ARGV0 || on | on | on | on + ** ------------++--------+-----------+-----------------+--------------- + ** COPYF || on | on | on | on + ** ------------++--------+-----------+-----------------+--------------- + ** NOCHECK || on | on | on | OFF + ** ------------++--------+-----------+-----------------+--------------- + ** CONTINUE || OFF | on | on | on + ** ============++========+===========+=================+=============== + */ + X /* save old flags & initialize parse flags for first call */ X saveflags = cmd_flags(argd); X BSET(cmd_flags(argd), pa_ARGV0 | pa_NOCHECK | pa_COPYF); *************** *** 1985,1997 **** X }/*if*/ X X /* trim leading and trailing whitespace and check for comments */ ! (VOID) strtrim( text, (char *)NULL ); X if ( !text || !(*text) || *text == c_COMMENT ) continue; X X rc = sparseargs( text, argd ); X X /* set up parseflags for next call */ ! BSET(cmd_flags(argd), pa_CONTINUE); X }/*while !EOF*/ X X if ( !BTEST(saveflags, pa_NOCHECK) ) BCLEAR(cmd_flags(argd), pa_NOCHECK); --- 2005,2019 ---- X }/*if*/ X X /* trim leading and trailing whitespace and check for comments */ ! (VOID) strtrim( text, CHARNULL ); X if ( !text || !(*text) || *text == c_COMMENT ) continue; X X rc = sparseargs( text, argd ); X X /* set up parseflags for next call */ ! if ( !BTEST(cmd_flags(argd), pa_CONTINUE) ) { ! BSET(cmd_flags(argd), pa_CONTINUE); ! } X }/*while !EOF*/ X X if ( !BTEST(saveflags, pa_NOCHECK) ) BCLEAR(cmd_flags(argd), pa_NOCHECK); *************** *** 2079,2085 **** X /* allocate a NULL terminated arg-vector */ X argv = (char **)malloc( (argc + 1) * sizeof(char *) ); X if ( !argv ) return pe_SYSTEM; ! argv[ argc ] = (char *)NULL; X X /* make 2nd pass to assign the elements of the vector */ X for ( ls = argls, i = 0 ; ls ; ls = L_NEXT(ls), i++ ) { --- 2101,2107 ---- X /* allocate a NULL terminated arg-vector */ X argv = (char **)malloc( (argc + 1) * sizeof(char *) ); X if ( !argv ) return pe_SYSTEM; ! argv[ argc ] = CHARNULL; X X /* make 2nd pass to assign the elements of the vector */ X for ( ls = argls, i = 0 ; ls ; ls = L_NEXT(ls), i++ ) { *************** *** 2183,2189 **** X /* allocate a NULL terminated arg-vector */ X argv = (char **) malloc( (argc + 1) * sizeof(char *) ); X if ( !argv ) return pe_SYSTEM; ! argv[ argc ] = (char *)NULL; X X VA_START(ap, argc); X for ( i = 0; i < argc && (arg = VA_ARG(ap, char *)) ; i++ ) { --- 2205,2211 ---- X /* allocate a NULL terminated arg-vector */ X argv = (char **) malloc( (argc + 1) * sizeof(char *) ); X if ( !argv ) return pe_SYSTEM; ! argv[ argc ] = CHARNULL; X X VA_START(ap, argc); X for ( i = 0; i < argc && (arg = VA_ARG(ap, char *)) ; i++ ) { SHAR_EOF echo 'File PATCH05 is complete' && chmod 0664 PATCH05 || echo 'restore of PATCH05 failed' Wc_c="`wc -c < 'PATCH05'`" test 268263 -eq "$Wc_c" || echo 'PATCH05: original size 268263, current size' "$Wc_c" rm -f _shar_wnt_.tmp fi rm -f _shar_seq_.tmp echo You have unpacked the last part 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.