[comp.sources.misc] v19i086: parseargs - functions to parse command line argument, Patch05e/5

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.