v17i055: parseargs - functions to parse command line arguments, Part10/12

Brad Appleton brad at hcx1.ssd.csd.harris.com
Tue Mar 19 01:57:42 AEST 1991


Submitted-by: Brad Appleton <brad at hcx1.ssd.csd.harris.com>
Posting-number: Volume 17, Issue 55
Archive-name: parseargs/part10

This is part 10 of parseargs

#!/bin/sh
# this is Part.10 (part 10 of a multipart archive)
# do not concatenate these parts, unpack them in order with /bin/sh
# file parseargs/syserr.c continued
#
if test ! -r _shar_seq_.tmp; then
	echo 'Please unpack part 1 first!'
	exit 1
fi
(read Scheck
 if test "$Scheck" != 10; then
	echo Please unpack part "$Scheck" next!
	exit 1
 else
	exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
	echo 'x - still skipping parseargs/syserr.c'
else
echo 'x - continuing file parseargs/syserr.c'
sed 's/^X//' << 'SHAR_EOF' >> 'parseargs/syserr.c' &&
/*    -- the formatted message-string to print.
*/
X   va_list ap;
/*    -- the list of variable arguments for vfprintf().
*/
#endif  /* !__ANSI_C__ */
X
/* ^DESCRIPTION:
**    _error_message will print the program name followed by the
**    formatted message. If errno is non-zero, the corresponding
**    system message will also be printed.
**
** ^REQUIREMENTS:
**    None.
**
** ^SIDE-EFECTS:
**    Writes to stderr.
**
** ^RETURN-VALUE:
**    None.
**
** ^ALGORITHM:
**    - print the program name
**    - print the message
**    - if errno is non-zero, call perror()
***^^**********************************************************************/
#ifdef __ANSI_C__
X   static void _error_message( const char *format, va_list ap )
#endif
{
X   int save_err;
X
X   save_err = errno;
X   if (ProgName  &&  *ProgName)  fprintf(stderr, "%s: ", ProgName);
X
X   (VOID) vfprintf(stderr, format, ap);
X
X   fputc('\n', stderr);
X   if ( save_err ) {
X      errno = save_err;
X      perror("System error");
X   }
X   fflush(stderr);
}
X
X
/***************************************************************************
** ^FUNCTION: syserr - print a formatted message and exit
**
** ^SYNOPSIS:
*/
#ifndef __ANSI_C__
X   VOID syserr( format, va_alist )
/*
** ^PARAMETERS:
*/
X   char *format;
/*    -- the format string to pass to vfprintf()
*/
X   va_dcl  
/*    -- the arguments to be formatted
*/
#endif  /* !__ANSI_C__ */
X
/* ^DESCRIPTION:
**    Syserr will print the current program name followed by the
**    formatted message. If errno is non-zero, it will use perror
**    to print the corresponding system error message. Lastly, Syserr
**    will terminate execution with an exit code of 1.
**
** ^REQUIREMENTS:
**    No special requirements.
**
** ^SIDE-EFECTS:
**    All output is written to stderr. Program execution is terminated.
**
** ^RETURN-VALUE:
**    None (Does not return).
**
** ^ALGORITHM:
**    - print the error message(s)
**    - take care of recursive calls to syserr()
**    - exit
***^^**********************************************************************/
#ifdef __ANSI_C__
X   void syserr( const char *format, ... )
#endif
{
X   static BOOL exiting = FALSE;
X   va_list ap;
X
X   /* print the error message */
X   VA_START(ap, format);
X   _error_message(format, ap);
X   VA_END(ap);
X
X   /* if we recursively syserr during exit, drop out now! */
X   if (exiting)  exit(1);
X
X   /* try a clean exit */
X   exiting = TRUE;
X   exit(1);
X   /*NOTREACHED*/
}
X
X
/***************************************************************************
** ^FUNCTION: eprintf - print a formatted message on stderr.
**
** ^SYNOPSIS:
*/
#ifndef __ANSI_C__
X   int eprintf( format, va_alist )
/*
** ^PARAMETERS:
*/
X   char *format;
/*    -- the printf() message to print.
*/
X   va_dcl
/*    -- the arguments to be formatted
*/
#endif  /* !__ANSI_C__ */
X
/* ^DESCRIPTION:
**    Eprintf() will behaves exactly like printf with the sole
**    exception being that it writes to stderr instead of stdout.
**
** ^REQUIREMENTS:
**    None.
**
** ^SIDE-EFECTS:
**    Writes to stderr.
**
** ^RETURN-VALUE:
**    Same as printf(3).
**
** ^ALGORITHM:
**    Trivial.
***^^**********************************************************************/
#ifdef __ANSI_C__
X   int eprintf( const char *format, ... )
#endif
{
X   int rc;
X   va_list ap;
X
X   VA_START(ap, format);
X   rc = vfprintf( stderr, format, ap );
X   VA_END(ap);
X
X   fflush(stderr);
X   return rc;
}
X
X
/***************************************************************************
** ^FUNCTION: usrerr - print a user error message
**
** ^SYNOPSIS:
*/
#ifndef __ANSI_C__
X   VOID usrerr( format, va_alist )
/*
** ^PARAMETERS:
*/
X   char *format;
/*    -- the format string to pass to vfprintf()
*/
X   va_dcl
/*    -- the arguments to be formatted
*/
#endif  /* !__ANSI_C__ */
X
/* ^DESCRIPTION:
**    Usrerr will print the current program name followed by the
**    formatted message. If errno is non-zero, it will use perror
**    to print the corresponding system error message.
**
** ^REQUIREMENTS:
**    No special requirements.
**
** ^SIDE-EFECTS:
**    All output is written to stderr.  Errno is cleared.
**
** ^RETURN-VALUE:
**    None.
**
** ^ALGORITHM:
**    - print the error message(s)
**    - set errno to zero
***^^**********************************************************************/
#ifdef __ANSI_C__
X   void usrerr( const char *format, ... )
#endif
{
X   va_list ap;
X
X   /* print the error message */
X   VA_START(ap, format);
X   _error_message(format, ap);
X   VA_END(ap);
X
X   /* give us a clean slate */
X   errno = 0;
}
SHAR_EOF
echo 'File parseargs/syserr.c is complete' &&
chmod 0664 parseargs/syserr.c ||
echo 'restore of parseargs/syserr.c failed'
Wc_c="`wc -c < 'parseargs/syserr.c'`"
test 5916 -eq "$Wc_c" ||
	echo 'parseargs/syserr.c: original size 5916, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= parseargs/test.awk ==============
if test -f 'parseargs/test.awk' -a X"$1" != X"-c"; then
	echo 'x - skipping parseargs/test.awk (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting parseargs/test.awk (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'parseargs/test.awk' &&
#!/usr/bin/awk -f
X
##########################################################################
## ^FILE: test.awk - parseargs for awk programs
##
## ^DESCRIPTION:
##    This file defines an awk function named parseargs to parse
##    command-line arguments for awk scripts. It also contains a
##    bare-bones template of what such an awk-script might contain.
##
## ^HISTORY:
##    02/21/91	Brad Appleton	<brad at ssd.csd.harris.com>	Created
###^^#####################################################################
X
X
#########
## ^FUNCTION: parseargs - parse command-line argument vectors
##
## ^SYNOPSIS:
##    parseargs( argc, argv, argd, arr )
##
## ^PARAMETERS:
##    argc -- the number of elements in argv (usually ARGC-1).
##    argv -- the vector of command-line arguments (usually ARGV).
##    argd -- the argument-description string
##    arr  -- the associative array to assign command-line values from
##
## ^DESCRIPTION:
##    Parseargs will invoke parseargs(1) to parse the command-line given
##    in <argv> for the command defined by <argd>.  The resulting values
##    will be assigned to elements of the associative array given by <arr>.
##    Values are assigned using using the syntax: arr [ "argname" ] = value;
##    The exception to this is that if the <argname> is "ARGV" then the global
##    array ARGV is reset to the given array (using tab separated fields).
##
## ^REQUIREMENTS:
##    Any desired initial values for items in <arr> should be assigned BEFORE
##    calling this function (using the syntax: arr[ "argname" ] = initial-val).
##
##    The following global variables may be assigned before calling parseargs:
##
##       PROGNAME -- name of the current awk script (default= ARGV[0])
##       PARSEOPTS -- any extra options to pass toi parseargs() (default="-ul")
##       PARSEINPUT -- input file for parseargs(1) (default=unique-name)
##       PARSEOUTPUT -- output file for parseargs(1) (default=unique-name)
##
## ^SIDE-EFFECTS:
##    The files PARSEINPUT and PARSEOUTPUT are created and then deleted.
##
##    The return value from parseargs(1) will be stored in the global-variable
##    named PARSESTATUS.
##
##    The global variable PARSEARGS will contain the command-line used to
##    invoke parseargs(1).
##
##    ARGV and ARGC may be reset, all other values are (re)set in <arr>.
##
## ^RETURN-VALUE:
##    The exit code returned by parseargs(1).
##
## ^BUGS:
##    Due to the limited ability of awk, scripts using parseargs(1) cannot
##    use short-options (with a  dash '-') because awk will attempt to interpret
##    any such arguments as options to awk and remove them from ARGV (regardless
##    of whether or not they are valid awk-options). Keyword options (with a
##    plus sign '+') may still be used without this difficulty. Dash-options
##    may be successfully processed if they did not first appear on the command
##    to the awk-script, so the full syntax of unix-style options could be 
##    provided in an array other than ARGV.
##
## ^ALGORITHM:
##    - set defaults for PROGNAME, PARSEOPTS, PARSEINPUT, and PARSEOUTPUT.
##    - build the parseargs command (dont forget to quote arguments).
##    - redirect input and output of the parseargs command.
##    - run parseargs(1)
##    - assign the exit-code from parseargs(1) to PARSESTATUS
##    - remove PARSEINPUT
##    - if PARSESTATUS != 0
##      - save RS and FS and reset RS = "" and FS = "\n"
##      - for each record in PARSEOUTPUT
##        - $1 is the argname and $2 is the value
##        - if $1 is "ARGV" reset ARGV and ARGC ($2 is a tab separated array)
##        - else assign arr[ $1 ] = $2
##      end-for
##      - restore RS and FS to previous values
##      - remove PARSEOUTPUT
##      - return PARSESTATUS
###^^####
X
function parseargs(argc, argv, argd, arr) {
X      ## set defaults -- use $$ to get a unique suffix string
X   if ( ! PROGNAME )     PROGNAME = ARGV[0];
X   if ( ! PARSEOPTS )    PARSEOPTS = "-u -l";
X
X   "echo  ${TMP:-/tmp}/parseargs.${$}_"  |  getline TMPFILE;
X   if ( ! PARSEINPUT )   PARSEINPUT = TMPFILE "in";
X   if ( ! PARSEOUTPUT )  PARSEOUTPUT = TMPFILE "out";
X
X      ## build the options and required arguments for parseargs(1)
X   PARSEARGS = sprintf( "parseargs -s awk %s -- '%s'", PARSEOPTS, PROGNAME );
X
X      ## quote each elemnt in argv and append it to the parseargs-command
X   for ( i = 1 ; i <= argc ; i++ ) {
X      arg = argv[i];
X      gsub( /'/, "'\\''", arg );
X      PARSEARGS = PARSEARGS " '" arg "'";
X   }
X
X      ## set up i/o redirection
X   PARSEARGS = PARSEARGS  " <" PARSEINPUT  " >" PARSEOUTPUT;
X   print  argd > PARSEINPUT;
X
X      ## invoke parseargs(1) and save the status
X   PARSESTATUS = system( PARSEARGS );
X   system( "/bin/rm -f " PARSEINPUT );  ## dont need input anymore
X
X      ## if successful status, read the result
X   if ( PARSESTATUS == 0 ) {
X      save_RS = RS; save_FS = FS;
X      RS = ""; FS = "\n";
X      while ( getline  < PARSEOUTPUT  > 0 ) {
X         gsub( /\034/, "\n" );
X         if ( $1 == "ARGV" ) {
X            ARGC = 1 + split( $2, ARGV, "\t" );
X            ARGV[0] = PROGNAME;
X         }
X         else  arr[ $1 ] = $2;
X      }
X      RS = save_RS; FS = save_FS;
X   }
X   system( "/bin/rm -f " PARSEOUTPUT );
X
X   return  PARSESTATUS;
}
X
X
BEGIN {
X  PROGNAME = "test.awk";
X  ARGD = sprintf( "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s",
X    "'?', ARGHIDDEN, argUsage, NULL,    'Help : print usage and exit'" ,
X    "'S', ARGVALOPT, argStr,   string,  'STRing : optional string arg'" ,
X    "'g', ARGLIST,   argStr,   groups,  'newsGROUPS : groups to test'" ,
X    "'r', ARGOPT,    argInt,   count,   'REPcount : group repeat count'" ,
X    "'d', ARGOPT,    argStr,   dirname, 'DIRectory : working directory'" ,
X    "'x', ARGOPT,    argBool,  xflag,   'Xflag : turn on X-mode'" ,
X    "'y', ARGOPT,    argUBool, yflag,   'Yflag : turn off Y-mode'" ,
X    "'s', ARGOPT,    argChar,  sepch,   'SEPchar : field separator'" ,
X    "'f', ARGLIST,   argStr,   files,   'files : files to process'" ,
X    "'n', ARGREQ|ARGPOS, argStr, name,  'name : name to use'" ,
X    "' ', ARGLIST,   argStr,   argv,    'argv : any remaining arguments'" ,
X    "ENDOFARGS" );
X
X  Args[ "count" ] = 1;
X  Args[ "dirname" ] = ".";
X  Args[ "sepch" ] = ",";
X  Args[ "yflag" ] = "TRUE";
X
X  rc = parseargs( ARGC-1, ARGV, ARGD, Args );
X  if ( rc != 0 )  exit( rc );
X
X  ## print  the parsed arguments (use defaults if not defined)
X  print "ARGUMENTS:";
X  print "==========";
X
X  for ( i in Args )
X    printf( "Args[\"%s\"] = \"%s\"\n", i, Args[i] );
X
X  argc = split( Args[ "argv" ], argv, "\t" );
X  for ( i = 1 ; i <= argc ; i++ )
X    printf( "argv[%d] = \"%s\"\n", i, argv[i] );
X    
}
SHAR_EOF
chmod 0775 parseargs/test.awk ||
echo 'restore of parseargs/test.awk failed'
Wc_c="`wc -c < 'parseargs/test.awk'`"
test 6643 -eq "$Wc_c" ||
	echo 'parseargs/test.awk: original size 6643, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= parseargs/test.csh ==============
if test -f 'parseargs/test.csh' -a X"$1" != X"-c"; then
	echo 'x - skipping parseargs/test.csh (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting parseargs/test.csh (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'parseargs/test.csh' &&
#!/bin/csh -f
#
#	test.csh - C-shell script to test out the parseargs command!
#
set NAME="`basename $0`"
X
setenv ARGUMENTS "\
X  '?', ARGHIDDEN, argUsage, NULL,    'Help {print usage and exit}', \
X  'S', ARGVALOPT, argStr,   string,  'STRing {optional string arg}', \
X  'g', ARGLIST,   argStr,   groups,  'newsGROUPS {groups to test}', \
X  'r', ARGOPT,    argInt,   count,   'REPcount {# to repeat each group}', \
X  'd', ARGOPT,    argStr,   dirname, 'DIRectory {working directory}', \
X  'x', ARGOPT,    argBool,  xflag,   'Xflag {turn on X-mode}', \
X  'y', ARGOPT,    argUBool, yflag,   'Yflag {turn off Y-mode}', \
X  's', ARGOPT,    argChar,  sepch,   'SEPchar {field separator}', \
X  'f', ARGLIST,   argStr,   files,   'files {files to process}', \
X  'n', ARGREQ|ARGPOS, argStr, name,  'name {name to use}', \
X  ' ', ARGLIST,   argStr,   argv,    'argv {any remaining arguments}', \
X  ENDOFARGS \
"
## set defaults ##
set groups='mygroup'   ## default group used by everyone
set count='1'          ## only do once unless otherwise specified
set dirname='.'        ## default to current directory
set xflag=''           ## default xflag is false
set yflag='TRUE'       ## default yflag is true
set sepch=','          ## default separator is a comma
set files=()
X
## parse command-line ##
parseargs -s csh -e ARGUMENTS -u -- "$NAME" $argv:q >/tmp/tmp$$
if ( $status != 0 ) then  ## improper syntax (or just wanted usage)
X	rm -f /tmp/tmp$$
X	exit 2
endif
X
## evaluate output from parseargs & remove temporary file
source /tmp/tmp$$
rm -f /tmp/tmp$$
X
## echo arguments ##
echo "ARGUMENTS:"
echo "=========="
echo Groups=$groups:q
echo Count=$count:q
echo Directory=$dirname:q
echo XFlag=$xflag:q
echo YFlag=$yflag:q
echo SepChar=$sepch:q
echo Name=$name:q
echo Files=$files:q
if ( $?string_flag ) then
X  if ( ! $?string ) set string="\!string arg ommited on cmd-line\!"
else
X  set string="default string"
endif
echo String=$string:q
echo New Positional Parameters=$argv:q
X
## print usage ##
parseargs -e ARGUMENTS -U "$NAME"
SHAR_EOF
chmod 0775 parseargs/test.csh ||
echo 'restore of parseargs/test.csh failed'
Wc_c="`wc -c < 'parseargs/test.csh'`"
test 2023 -eq "$Wc_c" ||
	echo 'parseargs/test.csh: original size 2023, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= parseargs/test.ksh ==============
if test -f 'parseargs/test.ksh' -a X"$1" != X"-c"; then
	echo 'x - skipping parseargs/test.ksh (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting parseargs/test.ksh (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'parseargs/test.ksh' &&
#!/bin/ksh
#
#	test.ksh - Korn shell script to test out the parseargs command!
#
X
NAME="$(basename $0)"
X
ARGUMENTS="
X  '?', ARGHIDDEN, argUsage, NULL,    'Help -- print usage and exit',
X  'S', ARGVALOPT, argStr,   string,  'STRing -- optional string arg',
X  'g', ARGLIST,   argStr,   groups,  'newsGROUPS -- groups to test',
X  'r', ARGOPT,    argInt,   count,   'REPcount -- number to repeat each group',
X  'd', ARGOPT,    argStr,   dirname, 'DIRectory -- working directory',
X  'x', ARGOPT,    argBool,  xflag,   'Xflag -- turn on X-mode',
X  'y', ARGOPT,    argUBool, yflag,   'Yflag -- turn off Y-mode',
X  's', ARGOPT,    argChar,  sepch,   'SEPchar -- field separator',
X  'f', ARGLIST,   argStr,   files,   'files -- files to process',
X  'n', ARGREQ|ARGPOS, argStr, name,  'name -- name to use',
X  ' ', ARGLIST,   argStr,    -- ,    'argv -- any remaining arguments',
X  ENDOFARGS
"
export ARGUMENTS
X
## set defaults ##
typeset groups[]           ## default group used by everyone
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 files[]
X
## parse command-line ##
parseargs -s ksh -e ARGUMENTS -uip -- "$NAME" "$@" >/tmp/tmp$$
if [ $? -ne 0 ] ; then
X  rm -f /tmp/tmp$$
X  exit 2  ## improper syntax (or just wanted usage)
fi
X
## evaluate results from parseargs and remove temporary file ##
INTERPRET="."
$INTERPRET /tmp/tmp$$
rm -f /tmp/tmp$$
X
## 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
X  string=${string:-"!string arg ommitted on cmd-line!"}
else
X  string="default string"
fi
print "String='$string'"
print "New Positional Parameters='$*'"
X
## print usage ##
parseargs -a "$ARGUMENTS" -U "$NAME"
SHAR_EOF
chmod 0775 parseargs/test.ksh ||
echo 'restore of parseargs/test.ksh failed'
Wc_c="`wc -c < 'parseargs/test.ksh'`"
test 2097 -eq "$Wc_c" ||
	echo 'parseargs/test.ksh: original size 2097, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= parseargs/test.pl ==============
if test -f 'parseargs/test.pl' -a X"$1" != X"-c"; then
	echo 'x - skipping parseargs/test.pl (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting parseargs/test.pl (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'parseargs/test.pl' &&
#!/usr/bin/perl
X
require  'parseargs.pl';
X
$ARGD = '
X  { "?", ARGHIDDEN, argUsage, NULL,    "Help : print usage and exit" },
X  { "S", ARGVALOPT, argStr,   string,  "STRing : optional string arg" },
X  { "g", ARGLIST,   argStr,   groups,  "newsGROUPS : groups to test" },
X  { "r", ARGOPT,    argInt,   count,   "REPcount : group repeat count" },
X  { "d", ARGOPT,    argStr,   dirname, "DIRectory : working directory" },
X  { "x", ARGOPT,    argBool,  xflag,   "Xflag : turn on X-mode" },
X  { "y", ARGOPT,    argUBool, yflag,   "Yflag : turn off Y-mode" },
X  { "s", ARGOPT,    argChar,  sepch,   "SEPchar : field separator" },
X  { "f", ARGLIST,   argStr,   files,   "files : files to process" },
X  { "n", ARGREQ|ARGPOS, argStr, name,  "name : name to use" },
X  { " ", ARGLIST,   argStr,   ARGV,    "ARGV : any remaining arguments" },
X  "ENDOFARGS" ';
X
$count = 1;
$dirname = '.';
$sepch = ',';
$yflag = 'TRUE';
X
&parseargs( @ARGV, $ARGD );
X
## print  the parsed arguments (use defaults if not defined)
print "ARGUMENTS:\n";
print "==========\n";
for ( $i = $[ ; $i <= $#groups ; $i++ ) {
X  printf( "Groups[%d] = '%s'\n", $i, $groups[$i] );
}
printf( "Count = %d\n", $count );
printf( "Directory = '%s'\n", $dirname );
printf( "XFlag = '%s'\n", $xflag );
printf( "YFlag = '%s'\n", $yflag );
printf( "SepChar = '%s'\n", $sepch );
printf( "Name = '%s'\n", $name );
for ( $i = $[ ; $i <= $#files ; $i++ ) {
X  printf( "Files[%d] = '%s'\n", $i, $files[$i] );
}
if ( $string_flag ) {
X  if ( ! $string ) {
X    $string = '!string arg ommitted on cmd-line!';
X  }
}
else {
X  $string = 'default string';
}
printf( "String = '%s'\n", $string );
for ( $i = $[ ; $i <= $#ARGV ; $i++ ) {
X  printf( "ARGV[%d] = '%s'\n", $i, $ARGV[$i] );
}
SHAR_EOF
chmod 0775 parseargs/test.pl ||
echo 'restore of parseargs/test.pl failed'
Wc_c="`wc -c < 'parseargs/test.pl'`"
test 1718 -eq "$Wc_c" ||
	echo 'parseargs/test.pl: original size 1718, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= parseargs/test.rc ==============
if test -f 'parseargs/test.rc' -a X"$1" != X"-c"; then
	echo 'x - skipping parseargs/test.rc (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting parseargs/test.rc (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'parseargs/test.rc' &&
#!/bin/rc
#	test.rc - rc shell script to test out the parseargs command!
#
NAME=`{basename $0}
X
ARGUMENTS='
X  "?", ARGHIDDEN, argUsage, NULL,    "Help : print usage and exit",
X  "S", ARGVALOPT, argStr,   string,  "STRing : optional string arg",
X  "g", ARGLIST,   argStr,   groups,  "newsGROUPS : groups to test",
X  "r", ARGOPT,    argInt,   count,   "REPcount <# to repeat each group>",
X  "d", ARGOPT,    argStr,   dirname, "DIRectory : working directory",
X  "x", ARGOPT,    argBool,  xflag,   "Xflag : turn on X-mode",
X  "y", ARGOPT,    argUBool, yflag,   "Yflag : turn off Y-mode",
X  "s", ARGOPT,    argChar,  sepch,   "SEPchar : field separator",
X  "f", ARGLIST,   argStr,   files,   "files : files to process",
X  "n", ARGREQ|ARGPOS, argStr, name,  "name : name to use",
X  " ", ARGLIST,   argStr,   * ,      "argv : any remaining arguments",
X  ENDOFARGS
'
X
yflag='TRUE'     ## set defaults (dir="."; count=1; sepch=',') ##
X
## parse command-line and save assignments in a temporary file ##
parseargs -s rc -e ARGUMENTS -u -- $^NAME "$@" >/tmp/tmp$$
if ( $status != 0 ) {
X  rm -f /tmp/tmp$$;
X  exit 2  ## non-zero status (usage given)
}
X
## evaluate results from parseargs and remove temporary file
. /tmp/tmp$$;  rm -f /tmp/tmp$$
X
## echo  the parsed arguments (use defaults if not defined)
echo 'ARGUMENTS:'
echo '=========='
echo Name="$name", Count=${count:-1}
echo XFlag="$xflag", YFlag="$yflag"
echo Directory="${dirname:-'.'}", SepChar="${sepch:-','}"
echo Groups="$groups"
echo Files="$files"
if ( $^string_flag )
X  string=${string:-'!string arg ommitted on cmd-line!'}
else
X  string='default string'
echo String="$string"
echo New Positional Parameters="$^*"
X
parseargs -a $^ARGUMENTS -U $^NAME     ## print usage ##
SHAR_EOF
chmod 0775 parseargs/test.rc ||
echo 'restore of parseargs/test.rc failed'
Wc_c="`wc -c < 'parseargs/test.rc'`"
test 1728 -eq "$Wc_c" ||
	echo 'parseargs/test.rc: original size 1728, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= parseargs/test.sh ==============
if test -f 'parseargs/test.sh' -a X"$1" != X"-c"; then
	echo 'x - skipping parseargs/test.sh (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting parseargs/test.sh (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'parseargs/test.sh' &&
#!/bin/sh
#	test.sh - Bourne shell script to test out the parseargs command!
#
NAME="`basename $0`";  DOT=".";
X
ARGUMENTS="
X  '?', ARGHIDDEN, argUsage, NULL,    'Help : print usage and exit',
X  'S', ARGVALOPT, argStr,   string,  'STRing : optional string arg',
X  'g', ARGLIST,   argStr,   groups,  'newsGROUPS : groups to test',
X  'r', ARGOPT,    argInt,   count,   'REPcount <# to repeat each group>',
X  'd', ARGOPT,    argStr,   dirname, 'DIRectory : working directory',
X  'x', ARGOPT,    argBool,  xflag,   'Xflag : turn on X-mode',
X  'y', ARGOPT,    argUBool, yflag,   'Yflag : turn off Y-mode',
X  's', ARGOPT,    argChar,  sepch,   'SEPchar : field separator',
X  'f', ARGLIST,   argStr,   files,   'files : files to process',
X  'n', ARGREQ|ARGPOS, argStr, name,  'name : name to use',
X  ' ', ARGLIST,   argStr,   -- ,     'argv : any remaining arguments',
X  ENDOFARGS
"
export ARGUMENTS
X
yflag='TRUE'     ## set defaults (dir="."; count=1; sepch=',') ##
X
## parse command-line and save assignments in a temporary file ##
parseargs -s sh -e ARGUMENTS -u -- "$NAME" "$@" >/tmp/tmp$$
if [ $? -ne 0 ]
X  then rm -f /tmp/tmp$$; exit 2  ## non-zero status (usage given)
fi
X
## evaluate results from parseargs and remove temporary file
$DOT /tmp/tmp$$;  rm -f /tmp/tmp$$
X
## echo  the parsed arguments (use defaults if not defined)
echo "ARGUMENTS:"
echo "=========="
echo "Name='$name', Count='${count:-1}'"
echo "XFlag='$xflag', YFlag='$yflag'"
echo "Directory='${dirname:-"."}', SepChar='${sepch:-","}'"
echo "Groups='$groups'"
echo "Files='$files'"
if [ "$string_flag" ]
X  then string=${string:-"!string arg ommitted on cmd-line!"}
X  else string="default string"
fi
echo "String='$string'"
echo "New Positional Parameters='$*'"
X
parseargs -a "$ARGUMENTS" -U "$NAME"     ## print usage ##
SHAR_EOF
chmod 0775 parseargs/test.sh ||
echo 'restore of parseargs/test.sh failed'
Wc_c="`wc -c < 'parseargs/test.sh'`"
test 1789 -eq "$Wc_c" ||
	echo 'parseargs/test.sh: original size 1789, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= parseargs/unix_args.c ==============
if test -f 'parseargs/unix_args.c' -a X"$1" != X"-c"; then
	echo 'x - skipping parseargs/unix_args.c (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting parseargs/unix_args.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'parseargs/unix_args.c' &&
/*************************************************************************
** ^FILE: unix_args.c - parse Unix argument vectors
**
** ^DESCRIPTION:
**    This file contains the routines used to parse Unix argument
**    vectors and to print Unix usage messages.
**
** ^HISTORY:
**    01/02/91 	Brad Appleton 	<brad at ssd.csd.harris.com>
**    - Added structured block comments
**    - Added optional arguments to keywords and options
**
**    --/--/--	Peter da Silva	<peter at ferranti.com>	
**
**    --/--/--	Eric P. Allman	<eric at Berkeley.EDU> 	Created
***^^**********************************************************************/
X
#include <ctype.h>
#include <useful.h>
#include "strfuncs.h"
#include "pgopen.h"
X
#define PARSEARGS_PRIVATE   /* include private definitions */
#include "parseargs.h"
X
EXTERN  VOID  syserr       ARGS((const char *, ...));
EXTERN  VOID  usrerr       ARGS((const char *, ...));
EXTERN  char *getenv       ARGS((const char *));
EXTERN  VOID  get_winsize  ARGS((int, int *, int *));
X
VERSIONID("$Header: parseargs.c,v 2.1 89/12/30 20:59:48 eric Exp $");
X
X
/***************************************************************************
** ^GLOBAL-VARIABLE: Usage_Requested
**
** ^VISIBILITY:
**    static-global (visible to all functions in this file).
**
** ^DESCRIPTION:
**    Indicates whether a usage message was requested by the user
**    (as opposed to triggered by a syntax error).  If the message
**    is requested by the user then it is always printed in verbose
**    mode and does not return an error-status-code.
***^^**********************************************************************/
static  BOOL  Usage_Requested = (BOOL) FALSE;
X
X
X   /* macros to detect an option/keyword -- watch out for side effects!! */
#define isOPT(s)  \
X   ( !BTEST(cmd_flags(cmd), pa_KWDSONLY)  && \
X     !BTEST(cmd_state(cmd), ps_NOFLAGS)  && \
X     *s == c_OPT_PFX  &&  *(s+1) \
X   )
X
#define isKWD(s)  \
X   ( !BTEST(cmd_flags(cmd), pa_OPTSONLY)  && \
X     !BTEST(cmd_state(cmd), ps_NOFLAGS)  && \
X     *s == c_KWD_PFX  &&  *(s+1) \
X   )
X
X
/***************************************************************************
** ^FUNCTION: unix_parse - parse Unix arg-vectors
**
** ^SYNOPSIS:
*/
#ifndef __ANSI_C__
X   int unix_parse( argv, argd )
/*  
** ^PARAMETERS:
*/
X   char *argv[];
/*    -- the vector of string arguments from the command-line
*/
X   ARGDESC argd[];
/*    -- the programmer description of the command and its args
*/
#endif  /* !__ANSI_C__ */
X
/* ^DESCRIPTION:
**    Unix_parse will parse the arguments in the given vector of strings,
**    assign the corresponding values to the command-line arguments specified
**    in argd, and check the syntax of the command-line.
**
** ^REQUIREMENTS:
**    The final element in argv must be a NULL pointer.
**
** ^SIDE-EFECTS:
**    argd is modified according to the command-line description and parameters
**
** ^RETURN-VALUE:
**    pe_SUCCESS (0) if no errors are encountered
**    pe_SYSTEM (-1) if a system error is encountered
**    pe_SYNTAX if a syntax error is encountered
**
** ^ALGORITHM:
**    - for each command-line argument
**       - attempt to match the argument as a keyword
**       - if it is a keyword argument
**          - record and convert its value (if any)
**         else attempt to match the argument as an option
**         if it is an option
**          - record and convert its value (if any)
**         else it is a positional parameter
**          - record and convert its value (if any)
**         else there are too many arguments
**          - return pe_SYNTAX
**         end-if
**       end-for
***^^**********************************************************************/
#ifdef __ANSI_C__
X   int unix_parse( char *argv[], ARGDESC argd[] )
#endif
{
X   register ARGDESC *ad, *args, *cmd;
X   register char **av = argv;
X   register char *p;
X   argName_t  name;
X   argMask_t  flags;
X   int  parse_error = pe_SUCCESS;
X   BOOL  ad_okay, is_match = FALSE;
X
X   if ( !argd )  return  parse_error;
X
X      /* initialize command-structure */
X   if ( !CMD_isINIT(argd) )  init_args( argd );
X   cmd = argd;
X
X   while ( av  &&  (p = *av++) ) {
X      if ( isKWD(p) ) {
X         char *s, c = '\0';
X
X         /* check for `++' to end flags */
X         if ( *(p+1) == c_KWD_PFX  &&  !*(p+2) ) {
X            BSET( cmd_state(cmd), ps_NOFLAGS );
X            cmd_list(cmd) = ARGDESCNULL;
X            continue;
X         }
X
X            /* get past prefix and look for possible argument */
X         s = strpbrk(++p, s_ARG_SEP);
X         if(s) {
X            c = *s;
X            *s++ = '\0';
X         }
X
X         is_match = FALSE;
X         for ( args = argd ; args  &&  !is_match ; args = cmd_defargs(args) ) {
X            for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
X               if ( arg_type(ad) == argDummy )  continue;
X
X               if ( !ARG_isPOSONLY(ad)  &&  match(p, arg_sname(ad)) == 0 ) {
X                  is_match = TRUE;
X                  break;
X               }/*if*/
X            }
X         }
X
X         if ( c )  *(s-1) = c;  /* restore the equal sign */
X
X         if ( !is_match ) {
X            usrerr("option %c%s unknown", c_KWD_PFX, p);
X            parse_error = pe_SYNTAX;
X            cmd_list(cmd) = ARGDESCNULL;
X            continue;
X         }
X
X         flags = arg_flags(ad);
X         if ( ARG_isGIVEN(ad) )
X            BCLEAR( arg_flags(ad), ARGVALSEP | ARGVALGIVEN | ARGKEYWORD );
X
X         BSET( arg_flags(ad), ARGKEYWORD );
X
X         if( ARG_isMULTIVAL(ad) ) {
X            cmd_list(cmd) = ad;
X         }
X         else {
X            cmd_list(cmd) = ARGDESCNULL;
X         }
X
X            /* if usage - just print usage and exit */
X         if ( arg_type(ad) == argUsage ) {
X            Usage_Requested = TRUE;
X            usage(argd);
X            exit(1);
X         }
X
X            /* ARGNOVALs are special, having no value */
X         if ( ! ARG_isVALTAKEN(ad) ) {
X            ad_okay = HANDLE(ad, s, cmd_flags(cmd));
X            if ( !ad_okay ) {
X               arg_flags(ad) = flags;
X               parse_error = pe_SYNTAX;
X            }
X            else {
X               BSET( arg_flags(ad), ARGGIVEN );
X               ad = ARGDESCNULL;
X            }
X            continue;
X         }/*if ARGNOVAL*/
X
X            /* now get the real value */
X         if (!s) {
X            s = *av++;
X            if ( !s  ||  isOPT(s)  ||  isKWD(s) ) {
X               if ( ARG_isVALOPTIONAL(ad) ) {
X                  BSET( arg_flags(ad), ARGGIVEN );
X               }
X               else {
X                  (VOID) get_keyword( arg_sname(ad), name );
X                  usrerr("option %c%s requires an argument", c_KWD_PFX, name);
X                  arg_flags(ad) = flags;
X                  parse_error = pe_SYNTAX;
X               }
X
X               av--;
X               continue;
X            }/*if arg*/
X            BSET( arg_flags(ad), ARGVALSEP );
X         }/*if empty*/
X
X            /* try to convert the type */
X         ad_okay = HANDLE(ad, s, cmd_flags(cmd));
X         if ( !ad_okay ) {
X            arg_flags(ad) = flags;
X            parse_error = pe_SYNTAX;
X         }
X         else {
X            BSET( arg_flags(ad), ARGGIVEN | ARGVALGIVEN );
X         }
X
X         continue;
X      }/*if keyword*/
X
X      else if ( isOPT(p) ) {
X         p++;  /* skip over option prefix */
X
X            /* check for `--' to end flags */
X         if ( *p == c_OPT_PFX  &&  !*(p+1) ) {
X            BSET( cmd_state(cmd), ps_NOFLAGS );
X            cmd_list(cmd) = ARGDESCNULL;
X            continue;
X         }
X
X            /* flag argument */
X         while (*p) {
X
X               /* find the flag in the list */
X            is_match = FALSE;
X            for (args = argd; args  &&  !is_match ; args = cmd_defargs(args)) {
X               for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
X                  register char c1 = arg_cname(ad);
X                  register char c2 = *p;
X
X                  if ( arg_type(ad) == argDummy )   continue;
X                  if ( ARG_isPOSONLY(ad) )   continue;
X
X                  if ( BTEST(cmd_flags(cmd), pa_ANYCASE) ) {
X                     c1 = TOUPPER( c1 );
X                     c2 = TOUPPER( c2 );
X                  }/*if*/
X
X                  if ( c1 == c2 ) {
X                     is_match = TRUE;
X                     break;
X                  }/*if*/
X               }
X            }
X            if ( !is_match ) {
X                  usrerr("option %c%c unknown", c_OPT_PFX, *p++);
X                  parse_error = pe_SYNTAX;
X                  cmd_list(cmd) = ARGDESCNULL;
X                  continue;
X            }/* if unknown-option */
X
X            flags = arg_flags(ad);
X            if ( ARG_isGIVEN(ad) )
X               BCLEAR( arg_flags(ad), ARGVALSEP | ARGVALGIVEN | ARGKEYWORD );
X
X            if( ARG_isMULTIVAL(ad) ) {
X               cmd_list(cmd) = ad;
X            }
X            else {
X               cmd_list(cmd) = ARGDESCNULL;
X            }
X
X               /* move p up to point to the (possible) value */
X            p++;
X
X            /* if usage - just print usage and exit */
X            if (arg_type(ad) == argUsage) {
X               Usage_Requested = TRUE;
X               usage(argd);
X               exit(1);
X            }
X
X               /* ARGNOVALs are special, having no value */
X            if (! ARG_isVALTAKEN(ad)) {
X               ad_okay = HANDLE(ad, p, cmd_flags(cmd));
X
X               if ( !ad_okay ) {
X                  arg_flags(ad) = flags;
X                  parse_error = pe_SYNTAX;
X               }/*if*/
X               else {
X                  BSET( arg_flags(ad), ARGGIVEN );
X                  ad = ARGDESCNULL;
X                  if ( ad_okay < 0 )  p -= ad_okay;
X               }/*else*/
X
X               continue;
X            }/*if*/
X
X               /* now get the real value */
X            if ( !(*p) ) {
X               p = *av++;
X               if ( !p  ||  isOPT(p)  ||  isKWD(p) ) {
X                  if ( ARG_isVALOPTIONAL(ad) ) {
X                     BSET( arg_flags(ad), ARGGIVEN );
X                  }
X                  else {
X                     (VOID) get_name(arg_sname(ad), name);
X                     usrerr( "%s required for %c%c flag",
X                             name, c_OPT_PFX, arg_cname(ad) );
X                     arg_flags(ad) = flags;
X                     parse_error = pe_SYNTAX;
X                  }/*else*/
X
X                  av--;
X                  break;
X               }/*if arg*/
X               BSET( arg_flags(ad), ARGVALSEP );
X            }/*if empty*/
X
X               /* try to convert the type */
X            ad_okay = HANDLE(ad, p, cmd_flags(cmd));
X            if ( !ad_okay ) {
X               arg_flags(ad) = flags;
X               parse_error = pe_SYNTAX;
X               p += strlen(p);
X            }/*if*/
X            else {
X               BSET( arg_flags(ad), ARGGIVEN | ARGVALGIVEN );
X               if ( ad_okay < 0  &&  !ARG_isVALSEPARATE(ad) ) {
X                  p -= ad_okay;
X               }
X               else {
X                  p += strlen(p);
X               }
X            }/*else*/
X
X         }/*while*/
X      }/*elif option*/
X      else {
X            /* parsing a list of arguments */
X         if( cmd_list(cmd) ) {
X            ad = cmd_list(cmd);
X            flags = arg_flags(ad);
X            if ( ARG_isGIVEN(ad) )
X               BCLEAR( arg_flags(ad), ARGVALGIVEN | ARGVALSEP | ARGKEYWORD );
X
X            BSET( arg_flags(ad), ARGVALSEP );
X
X            ad_okay = HANDLE(ad, p, cmd_flags(cmd));
X            if ( !ad_okay ) {
X               arg_flags(ad) = flags;
X               parse_error = pe_SYNTAX;
X            }
X
X            continue;
X         }
X            /* positional argument */
X         is_match = FALSE;
X         for (args = argd; args  &&  !is_match ; args = cmd_defargs(args)) {
X            for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
X               if (arg_type(ad) == argDummy)  continue;
X
X               if ( ARG_isPOSITIONAL(ad)  &&
X                    (!ARG_isGIVEN(ad) ||  ARG_isMULTIVAL(ad)) ) {
X                  is_match = TRUE;
X                  break;
X               }/*if*/
X            }
X         }
X
X         if ( !is_match ) {
X            usrerr("too any arguments");
X            parse_error = pe_SYNTAX;
X            continue;
X         }
X
X         flags = arg_flags(ad);
X         if ( ARG_isGIVEN(ad) )
X            BCLEAR( arg_flags(ad), ARGVALGIVEN | ARGKEYWORD | ARGVALSEP );
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         }
X
X         BSET( arg_flags(ad), ARGVALSEP );
X
X            /* try to convert */
X         ad_okay = HANDLE(ad, p, cmd_flags(cmd));
X         if ( !ad_okay ) {
X            arg_flags(ad) = flags;
X            parse_error = pe_SYNTAX;
X         }
X         else {
X            BSET( arg_flags(ad), ARGGIVEN | ARGVALGIVEN );
X         }
X      }/*else*/
X   }/*while*/
X
X   return  parse_error;
}
X
X
/***************************************************************************
** ^FUNCTION: fmtarg - format command-argument syntax
**
** ^SYNOPSIS:
*/
#ifndef __ANSI_C__
X   static int fmtarg( ad, buf, usgflags )
/*
** ^PARAMETERS:
*/
X   ARGDESC *ad;
/*    -- pointer to the argument to format
*/
X   char *buf;
/*    -- character buffer to hold the formatted result
*/
X   argMask_t usgflags;
/*    -- set of bitmasks corresponding to the value of the user's USAGECNTL
**       environment variable
*/
#endif  /* !__ANSI_C__ */
X
/* ^DESCRIPTION:
**    Fmtarg will determine the proper command-line syntax for the
**    given argument and write the result to the given buffer.
**
** ^REQUIREMENTS:
**    buf must be large enough to hold the formatted result (100 characters
**    should do the trick).
**
** ^SIDE-EFECTS:
**    buf is overwritten.
**
** ^RETURN-VALUE:
**    The number of printable characters in the argument-syntax-string
**
** ^ALGORITHM:
**    Print argument usage based on whether or not the argument is
**    positional, hidden, multi-valued (list or vector), etc ....
**    Optional arguments and values are enclosed in square braces.
**
**    Any syntax biases reflected in usgflags will be used.
***^^**********************************************************************/
#ifdef __ANSI_C__
X   static int fmtarg ( const ARGDESC *ad, char *buf, argMask_t usgflags )
#endif
{
X   /* buf must already be large enough */
X   char *pos;
X   argName_t   name, keyword;
X
X   (VOID) get_name( arg_sname(ad), name );
X
X   if (ARG_isPOSITIONAL(ad)) {
X      sprintf( buf, "<%s>", name );
X   }
X   else {
X      (VOID) get_keyword( arg_sname(ad), keyword );
X
X      if ( isupper(arg_cname(ad))  &&  toupper(*keyword) == arg_cname(ad) ) {
X         *keyword = toupper(*keyword);
X      }
X
X      if ( !(usgflags & usg_LONGOPTS) ) {
X         sprintf( buf, "%c%c", c_OPT_PFX, arg_cname(ad) );
X      }
X      else if ( !(usgflags & usg_OPTS) ) {
X         sprintf( buf, "%c%s", c_KWD_PFX, keyword );
X      }
X      else  {  /* use both */
X         sprintf( buf, "%c%c|%c%s", c_OPT_PFX, arg_cname(ad),
X                                    c_KWD_PFX, keyword );
X      }
X
X      pos = buf + strlen(buf);
X
X      if ( ARG_isVALTAKEN(ad)  &&  !ARG_isBOOLEAN(ad) &&  !ARG_isPSEUDOARG(ad) )
X      {
X         *(pos++) = ' ';
X
X         if  (ARG_isVALOPTIONAL(ad)) {
X            sprintf( pos, "[<%s>]", name);
X         }
X         else {
X            sprintf( pos, "<%s>", name );
X         }
X      }/*if*/
X   }/*else*/
X
X   return  strlen(buf);
}
X
X
/***************************************************************************
** ^FUNCTION: unix_usage - print a usage message
**
** ^SYNOPSIS:
*/
#ifndef __ANSI_C__
X   VOID unix_usage( argd, usage_flags )
/*
** ^PARAMETERS:
*/
X   ARGDESC *argd;
/*    -- the command-descriptor array
*/
X   argMask_t usage_flags;
/*    -- flags set by $USAGECNTL
*/
#endif  /* !__ANSI_C__ */
X
/* ^DESCRIPTION:
**    Unix_usage will print the Unix command-line usage of the given
**    command on standard diagnostic output (stderr). The content of the
**    usage message is controlled by the bitmasks in usage_flags which
**    correspond to the settings in the user's USAGECNTL variable.
**
** ^REQUIREMENTS:
**    argd should be a non-null command-line argument-descriptor array
**
** ^SIDE-EFECTS:
**    Prints on stderr.
**
** ^RETURN-VALUE:
**    None.
**
** ^ALGORITHM:
**    - if no usage is desired then exit
**    - if paging is requested print to the pager instead of stderr
**    - print the command-line syntax
**    - if the description is requested print it
**    - if verbose mode is requested, print the description of each argument
***^^**********************************************************************/
#ifdef __ANSI_C__
X   void unix_usage ( const ARGDESC *argd, argMask_t usage_flags )
#endif
{
X   register CONST ARGDESC *ad, *args, *cmd;
X   int  max_cols = 80, max_lines  = 24;
X   int  ll, margin, options, longest, positionals;
X   BOOL first = TRUE;
X   FILE *fp;
X
X   if ( !argd )  return;
X
X      /* initialize command-structure */
X   if ( !CMD_isINIT(argd) )  init_args( (ARGDESC *)argd );
X   cmd = argd;
X
X      /* force verbose-mode if requested */
X   if ( Usage_Requested )   BSET( usage_flags, usg_VERBOSE );
X
X   if ( BTEST(usage_flags, usg_NONE) )  return;
X
X   fp = ( BTEST(usage_flags, usg_PAGED) )
X      ? pgopen( stderr, getenv("USAGE_PAGER") )
X      : stderr;
X
X      /* get screen size */
X   get_winsize( fileno(fp), &max_lines, &max_cols );
X
X   fprintf(fp, "Usage: %s", ProgName);
X
X   ll = strlen( ProgName ) + 7;
X   margin = ll + 1;
X   longest = 0;
X
X      /* print Synopsis */
X   for ( positionals = 0 ; positionals < 2 ; positionals++ ) {
X      for ( args = argd ; args ; args = cmd_defargs(args) ) {
X         for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
X            argName_t  buf;
X            int pl;
X
X               /* don't display hidden arguments */
X            if ( ARG_isHIDDEN(ad) )  continue;
X            if ( !positionals  &&  ARG_isPOSITIONAL(ad) )  continue;
X            if ( positionals  &&  !ARG_isPOSITIONAL(ad) )  continue;
X
X               /* figure out how wide this parameter is (for printing) */
X            pl = fmtarg(ad, buf, usage_flags);
X
X            if ( pl > longest)  longest = pl;
X
X            if  ( ARG_isMULTIVAL(ad) ) {
X               strcat( buf, "..." );
X               pl += 3;
X            }
X            if ( !ARG_isREQUIRED(ad) ) {
X               pl += 2;
X            }
X
X            /* see if this will fit */
X            if ( (ll + pl + 1) > (max_cols - first) ) {
X                  /* no... start a new line */
X               fprintf(fp, "\n%*s", margin, "");
X               ll = margin;
X            }
X            else {
X                  /* yes... just throw in a space */
X               fputc(' ', fp);
X               ++ll;
X            }
X            ll += pl;
X
X               /* show the argument */
X            if ( !ARG_isREQUIRED(ad) )  fputc('[', fp);
X            fprintf(fp, buf);
X            if ( !ARG_isREQUIRED(ad) )  fputc(']', fp);
X
X            first = FALSE;  /* not first line anymore */
X         }/*for each ad */
X      }/* for each argd */
X   }/* for each parm-type */
X
X   fputc('\n', fp);
X
X   if ( BTEST(usage_flags, usg_DESCRIPTION) ) {
X      CONST char *description = cmd_description(cmd);
X
X      if ( description  &&  *description ) {
X         fprintf( fp, "Description:\n" );
X         indent_para(fp, max_cols, 8, "", 0, description);
X         fputc( '\n', fp );
X      }
X   }/*if*/
X
X   if ( !BTEST(usage_flags, usg_VERBOSE) )  {
X      if ( pgactive(fp) )  (VOID) pgclose( fp );
X      return;
X   }
X
X   options = 0;
X
X      /* print Argument descriptions */
X   for ( positionals = 0 ; positionals < 2 ; positionals++ ) {
X      for ( args = argd ; args ; args = cmd_defargs(args) ) {
X         for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
X            argName_t  buf;
X
X               /* don't display hidden arguments */
X            if ( ARG_isHIDDEN(ad) )  continue;
X            if ( !positionals  &&  ARG_isPOSITIONAL(ad) )  continue;
X            if ( positionals  &&  !ARG_isPOSITIONAL(ad) )  continue;
X
X            if ( !options++ )   fprintf(fp, "Options/Arguments:\n");
X            fmtarg(ad, buf, usage_flags);
X            indent_para( fp, max_cols, 8, buf, longest+2, arg_description(ad) );
X         }/*for each ad */
X      }/* for each argd */
X   }/* for each parm-type */
X
X   if ( pgactive(fp) )  (VOID) pgclose( fp );
}
X
SHAR_EOF
chmod 0664 parseargs/unix_args.c ||
echo 'restore of parseargs/unix_args.c failed'
Wc_c="`wc -c < 'parseargs/unix_args.c'`"
test 20417 -eq "$Wc_c" ||
	echo 'parseargs/unix_args.c: original size 20417, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= parseargs/unix_man.c ==============
if test -f 'parseargs/unix_man.c' -a X"$1" != X"-c"; then
	echo 'x - skipping parseargs/unix_man.c (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting parseargs/unix_man.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'parseargs/unix_man.c' &&
/*************************************************************************
** ^FILE: unix_man.c - print manual templates for user command
**
** ^DESCRIPTION:
**    This file is the portion of parseargs(1) that prints a Unix
**    manual template of a given command on the standard output.
**    The template is formatted for {n|t}roff using the -man macros.
**
** ^HISTORY:
**    01/02/91 	Brad Appleton 	<brad at ssd.csd.harris.com> 	Created
***^^**********************************************************************/
X
#include <stdio.h>
#include <ctype.h>
#include <useful.h>
#include "strfuncs.h"
X
#define PARSEARGS_PRIVATE   /* include private definitions */
#include "parseargs.h"
X
EXTERN  VOID  syserr  ARGS((const char *, ...));
EXTERN  VOID  usrerr  ARGS((const char *, ...));
X
#define MAXCOLS  65
#define VAL(str)           ((str) ? str : "")
#define COMMENT            printf(".\\\"-----------------------------------\n")
#define TH(title,section)  printf(".TH %s %d\n", title, section )
#define SH(title)          printf(".SH %s\n", title )
#define TP(cols,title)     printf(".TP %d\n%s\n", cols, title )
#define PP                 printf(".PP\n" )
X
X
/***************************************************************************
** ^FUNCTION: fmtarg - format command-argument syntax
**
** ^SYNOPSIS:
*/
#ifndef __ANSI_C__
X   static int fmtarg( ad, buf )
/*
** ^PARAMETERS:
*/
X   ARGDESC *ad;
/*    -- pointer to the argument to format
*/
X   char *buf;
/*    -- character buffer to hold the formatted result
*/
#endif  /* !__ANSI_C__ */
X
/* ^DESCRIPTION:
**    Fmtarg will determine the proper command-line syntax for the
**    given argument and write the result to the given buffer.
**
** ^REQUIREMENTS:
**    buf must be large enough to hold the formatted result (100 characters
**    should do the trick).
**
** ^SIDE-EFECTS:
**    buf is overwritten.
**
** ^RETURN-VALUE:
**    The number of printable characters in the argument-syntax-string
**
** ^ALGORITHM:
**    Print argument usage based on whether or not the argument is
**    positional, hidden, multi-valued (list or vector), etc ....
**    Optional arguments and values are enclosed in square braces.
***^^**********************************************************************/
#ifdef __ANSI_C__
X   static int fmtarg( const ARGDESC *ad , char *buf )
#endif
{
X      /* buf must already be large enough */
X   char *pos;
X   argName_t   name;
X
X   (VOID) get_name( arg_sname(ad), name );
X
X   if (ARG_isPOSITIONAL(ad)) {
X       if ( ARG_isMULTIVAL(ad) ) {
X          sprintf( buf, "\\fI%s\\fP\\ ...", name );
X          return   (strlen(name) + 4);
X       }/*if list*/
X
X       sprintf( buf, "\\fI%s\\fP", name );
X       return  strlen(name);
X   }/*if parm*/
X
X   sprintf(buf, "\\fB\-%c\\fP", arg_cname(ad));
X   pos = buf + strlen(buf);
X
X   if ( ARG_isVALTAKEN(ad)  &&  !ARG_isBOOLEAN(ad)  &&  !ARG_isPSEUDOARG(ad) ) {
X       if ( ARG_isMULTIVAL(ad) ) {
X          if ( ARG_isVALOPTIONAL(ad) ) {
X             sprintf(pos, "\\ \\s-1[\\s+1\\fI%s\\fP\\ ...\\s-1]\\s+1", name);
X             return  (strlen(name) + 9);
X          }/*if optarg*/
X
X          sprintf( pos, "\\ \\fI%s\\ ...\\fP", name );
X          return  (strlen(name) + 7);
X       }/*if list*/
X
X       if ( ARG_isVALOPTIONAL(ad) ) {
X          sprintf( pos, "\\ \\s-1[\\s+1\\fI%s\\fP\\s-1]\\s+1", name );
X          return  (strlen(name) + 5);
X       }/*if optarg*/
X
X       sprintf( pos, "\\ \\fI%s\\fP", name );
X       return  (strlen(name) + 3);
X   }/*if*/
X
X   return  2;
}
X
X
/***************************************************************************
** ^FUNCTION: manpage - print the manual template
**
** ^SYNOPSIS:
*/
#ifndef __ANSI_C__
X   VOID manpage ( argd )
/*
** ^PARAMETERS:
*/
X   ARGDESC *argd;
/*    -- the command-argdesc-array
*/
#endif  /* !__ANSI_C__ */
X
/* ^DESCRIPTION:
**    Manpage print on standard output, a Unix manual template for the
**    given command. The NAME, SYNOPSIS, and OPTIONS sections are filled
**    in and the DESCRIPTION section is partially filled in with any
**    known command-description. The FILES, SEE ALSO, DIAGNOSTICS, CAVEATS,
**    BUGS, AUTHOR, and HISTORY section titles are provided but the body
**    of each section must be composed by the documentor.
**
** ^REQUIREMENTS:
**    Argd should be a valid command-line descriptor array.
**
** ^SIDE-EFECTS:
**    Prints on standard-output.
**
** ^RETURN-VALUE:
**    None.
**
** ^ALGORITHM:
**    - print .TH setting followed by NAME section.
**    - cycle through each argument and print is syntax for the SYNOPSIS.
**    - print the description (if it exists).
**    - cycle through each argument again and print its syntax and description
**      for the OPTIONS section.
**    - print just the headings for the remaining sections.
***^^**********************************************************************/
#ifdef __ANSI_C__
X   void manpage( const ARGDESC *argd )
#endif
{
X   register CONST ARGDESC *ad, *args, *cmd;
X   argName_t  name;
X   CONST char *program, *purpose, *description;
X   int   len, maxlen, positionals;
X
X      /* allow null argument descriptor */
X   if ( !argd )  return;
X
X   if ( !CMD_isINIT(argd) )   init_args( (ARGDESC *)argd );
X   cmd = argd;
X
X   (VOID) strcpy( name, cmd_name(cmd) );
X   if ( cmd_name(cmd) ) {
X      program = cmd_name(cmd);
X   }
X   else if ( cmd_argv0(cmd) ) {
X      program = cmd_argv0(cmd);
X   }
X
X   purpose = cmd_purpose(cmd);
X   description = cmd_description(cmd);
X
X   printf(".\\\"---------- TO PRINT, USE: {n,t}roff -man file ----------\n");
X   printf(".if n .po 1\n");
X   printf(".if n .ll 78\n");
X
X   COMMENT;
X   TH( strupr(name), 1 );
X
X   COMMENT;
X   SH( "NAME" );
X   printf( "%s \\- %s\n", VAL(program), VAL(purpose) );
X
X   COMMENT;
X   SH( "SYNOPSIS" );
X
X   len = strlen( program ) + 1;
X   sprintf( name, "\\fB%s\\fP", program );
X   TP( len, name );
X
X   maxlen = 0;
X   for ( positionals = 0 ; positionals < 2 ; positionals++ ) {
X     for ( args = argd ; args ; args = cmd_defargs(args) ) {
X        for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
X           argName_t  buf;
X
X              /* don't display hidden arguments */
X           if ( ARG_isHIDDEN(ad) )  continue;
X           if ( !positionals  &&  ARG_isPOSITIONAL(ad) )  continue;
X           if ( positionals  &&  !ARG_isPOSITIONAL(ad) )  continue;
X
X           len = fmtarg( ad, buf );
X           if ( len > maxlen )   maxlen = len;
X
X           if ( ARG_isREQUIRED(ad) ) {
X               printf( "%s\n", buf );
X           }
X           else {
X               printf( "[%s]\n", buf );
X           }
X        }/*for each ad */
X     }/* for each argd */
X   }/* for each parm-type */
X
X   COMMENT;
X   SH( "DESCRIPTION" );
X   PP;
X   indent_para(stdout, MAXCOLS, 0, "", 0, VAL(description) );
X
X   COMMENT;
X   SH( "OPTIONS" );
X
X   for ( positionals = 0 ; positionals < 2 ; positionals++ ) {
X      for ( args = argd ; args ; args = cmd_defargs(args) ) {
X         for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
X            argName_t  buf;
X
X               /* don't display hidden arguments */
X            if ( ARG_isHIDDEN(ad) )  continue;
X            if ( !positionals  &&  ARG_isPOSITIONAL(ad) )  continue;
X            if ( positionals  &&  !ARG_isPOSITIONAL(ad) )  continue;
X
X            (VOID) fmtarg( ad, buf );
X            TP( maxlen + 2, buf );
X            indent_para(stdout, MAXCOLS, 0, "", 0, arg_description(ad) );
X         }/*for each ad */
X      }/* for each argd */
X   }/* for each parm-type */
X
X   COMMENT;
X   SH( "FILES" );
X   PP;
X
X   COMMENT;
X   SH( "SEE ALSO" );
X   PP;
X
X   COMMENT;
X   SH( "DIAGNOSTICS" );
X   PP;
X
X   COMMENT;
X   SH( "CAVEATS" );
X   PP;
X
X   COMMENT;
X   SH( "BUGS" );
X   PP;
X
X   COMMENT;
X   SH( "AUTHOR" );
X   PP;
X
X   COMMENT;
X   SH( "HISTORY" );
X   PP;
}
SHAR_EOF
chmod 0664 parseargs/unix_man.c ||
echo 'restore of parseargs/unix_man.c failed'
Wc_c="`wc -c < 'parseargs/unix_man.c'`"
test 7749 -eq "$Wc_c" ||
	echo 'parseargs/unix_man.c: original size 7749, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= parseargs/useful.h ==============
if test -f 'parseargs/useful.h' -a X"$1" != X"-c"; then
	echo 'x - skipping parseargs/useful.h (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting parseargs/useful.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'parseargs/useful.h' &&
/*************************************************************************
** ^FILE: useful.h - various definitions of general interest
**
** ^DESCRIPTION:
**    This file #defines several macros that are either of very general
**    use, or that assist in writing portable programs between various
**    systems and/or compilers.
**
** ^HISTORY:
**    --/--/--	Brad Appleton	<brad at ssd.csd.harris.com>	
**    - Added structured block comments
**    - Added varargs/stdarg macros
**    - Added BSET, BCLEAR, BTEST macros for handling bitmasks
**    - #defined EXTERN to be extern "C" for C++
**    - Added #defines for STDIN, STDOUT, and STDERR file descriptors
**
**    --/--/--	Peter da Silva	<peter at ferranti.com>	
**
**    --/--/--	Eric P. Allman	<eric at Berkeley.EDU> 	Created
***^^**********************************************************************/
X
/* $Header: useful.h,v 2.0 89/12/24 00:56:33 eric Exp $ */
X
#ifndef _USEFUL_H_
#define _USEFUL_H_
X
#ifndef unix
# if (defined(_unix) || defined(_unix_) || defined(__unix) || defined(__unix__) || defined(UNIX) || defined(_UNIX) || defined(_UNIX_) || defined(__UNIX) || defined(__UNIX__) || defined(Unix) || defined(_Unix) || defined(_Unix_) || defined(__Unix) || defined(__Unix__) || defined(sun))
#   define unix
# endif /* _UNIX */
#endif /* unix */
X
#ifndef BSD
# if (defined(ucb_universe) || defined(UCB) || defined(_BSD) || defined(_BSD_) || defined(__BSD) || defined(__BSD__) || defined(BSD_UNIX) || defined(_BSD_UNIX) || defined(_BSD_UNIX_) || defined(__BSD_UNIX) || defined(__BSD_UNIX__) || defined(sun))
#   define BSD
# endif /* _BSD */
#endif /* BSD */
X
#ifndef AmigaDOS
# if (defined(MANX) || defined(AZTEC))
#   define AmigaDOS
# endif
#endif /* AmigaDOS */
X
#ifndef vms
# if (defined(_vms) || defined(_vms_) || defined(__vms) || defined(__vms__) || defined(VMS) || defined(_VMS) || defined(_VMS_) || defined(__VMS) || defined(__VMS__))
#   define vms
# endif /* _VMS */
#endif /* vms */
X
#ifndef MSDOS
# if (defined(_MSDOS) || defined(_MSDOS_) || defined(__MSDOS) || defined(__MSDOS__) || defined(MS_DOS) || defined(_MS_DOS) || defined(_MS_DOS_) || defined(__MS_DOS) || defined(__MS_DOS__))
#   define MSDOS
# endif /* _MSDOS */
#endif /* MSDOS */
X
#ifndef OS2
# if (defined(_OS2) || defined(_OS2_) || defined(__OS2) || defined(__OS2__))
#   define OS2
# endif /* _OS2 */
#endif /* OS2 */
X
X
#ifndef FILE
# include <stdio.h>
#endif
X
#ifndef STDIN
# define STDIN   0
# define STDOUT  1
# define STDERR  2
#endif
X
X   /* macros to portably convert character case */
#define TOUPPER(c)  ( islower(c) ) ? toupper(c) : (c)
#define TOLOWER(c)  ( isupper(c) ) ? tolower(c) : (c)
X
X   /* give a stab at the multiple-language dilemma */
#ifdef __STDC__
#  define ARGS(x)		x
#  define NOARGS		( void )
#  define __ANSI_C__
#else
#  if defined(c_plusplus) || defined(__cplusplus)
#    define ARGS(x)		x
#    define NOARGS		()
#    define __ANSI_C__
#  else
#    define ARGS(x)	    ()
#    define NOARGS		()
#  endif
#endif
X
X   /* give a stab at the variable arguments dilemma  --BDA */
#ifdef __STDC__
#  ifndef va_arg
#    include <stdarg.h>
#  endif
#  define  VA_START(ap,last)  va_start(ap, last)
#  define  VA_ARG(ap,type)    va_arg(ap, type)
#  define  VA_END(ap)         va_end(ap)
#else
#  ifndef va_arg
#    include  <varargs.h>
#  endif
#  define  VA_START(ap,last)  va_start(ap)
#  define  VA_ARG(ap,type)    va_arg(ap, type)
#  define  VA_END(ap)         va_end(ap)
#endif
X
#if ( !defined(__ANSI_C__)  &&  !defined(_SIZE_T_DEFINED) )
X  typedef unsigned int size_t;
# define _SIZE_T_DEFINED 1
#endif
X
#ifndef VOID
#  if ( defined(__ANSI_C__)  ||  !defined(NOVOID) )
#    define VOID		void
#  else
#    define VOID		int
#  endif
#endif
X
#ifndef TRUE
#  define TRUE		1
#  define FALSE		0
#endif
X
#ifndef STATIC
#  ifndef NODEBUG
#    define STATIC
#  else
#    define STATIC		static
#  endif
#endif
X
#ifndef EXTERN
#  if defined(c_plusplus) || defined(__cplusplus)
#    define EXTERN		extern "C"
#  else
#    define EXTERN		extern
#  endif
#endif
X
#ifndef CONST
#  ifdef __ANSI_C__
#    define CONST		const
#  else
#    define CONST
#  endif
#endif
X
#ifndef NULL
#  define NULL		0
#endif
X
#ifndef CHARNULL
#  define CHARNULL	((char *) NULL)
#endif
X
#ifndef FILENULL
#  define FILENULL	((FILE *) NULL)
#endif
X
#ifdef __ANSI_C__
X   typedef   void *ARBPTR;
#else
X   typedef   char *ARBPTR;
#endif
X
#define __		(ARBPTR)
#define ARBNULL		(__ NULL)
X
#ifndef BOOL
X   typedef   char   BOOL;
#endif
X
#ifdef lint
#  define VERSIONID(v)
#else
#  define VERSIONID(v)	static char _Version[] = v
#endif
X
X   /* keep BITSET for compatibilty
X   ** but use BSET, BCLEAR, etc... instead   --BDA
X   */
#define BITSET(bstr,mask)	( ((bstr) & (mask)) != 0 )
X
#define BTEST(bstr,mask)	( ((bstr) & (mask)) != 0 )
#define BSET(bstr,mask)     (bstr) |= (mask)
#define BCLEAR(bstr,mask)   (bstr) &= ~(mask)
X
#ifndef STRING_H
# define STRING_H
X   EXTERN  char  *strcat    ARGS(( char *, const char * ));
X   EXTERN  char  *strncat   ARGS(( char *, const char *, int ));
X   EXTERN  int    strcmp    ARGS(( const char *, const char * ));
X   EXTERN  int    strncmp   ARGS(( const char *, const char *, int ));
X   EXTERN  char  *strcpy    ARGS(( char *, const char * ));
X   EXTERN  char  *strncpy   ARGS(( char *, const char *, int ));
X   EXTERN  int    strlen    ARGS(( const char * ));
X   
# ifndef BSD
#  define index(s,c)   strchr(s,c)
#  define rindex(s,c)  strrchr(s,c)
X   EXTERN  char  *strchr    ARGS(( const char *, int ));
X   EXTERN  char  *strrchr   ARGS(( const char *, int ));
X   EXTERN  char  *strpbrk   ARGS(( const char *, const char * ));
X   EXTERN  int    strspn    ARGS(( const char *, const char * ));
X   EXTERN  int    strcspn   ARGS(( const char *, const char * ));
X   EXTERN  char  *strtok    ARGS(( char *, char * ));
X   EXTERN  char  *strdup    ARGS(( const char * ));
X   
# else
#  define strchr(s,c)   index(s,c)
#  define strrchr(s,c)  rindex(s,c)
X   EXTERN  char  *index     ARGS(( const char *, int ));
X   EXTERN  char  *rindex    ARGS(( const char *, int ));
# endif /* !BSD */
X   
# ifdef BSD
#  define bcmp(b1,b2,n)   memcmp(b1,b2,n)
#  define bcopy(b1,b2,n)  memcpy(b2,b1,n)
#  define bzero(b,n)      memset(b,'\0',n)
#  ifndef MEMORY_H
#    define MEMORY_H
X   EXTERN  ARBPTR  memccpy   ARGS(( ARBPTR, const ARBPTR, int, int ));
X   EXTERN  ARBPTR  memchr    ARGS(( ARBPTR, int, int ));
X   EXTERN  int     memcmp    ARGS(( const ARBPTR, const ARBPTR, int ));
SHAR_EOF
true || echo 'restore of parseargs/useful.h failed'
fi
echo 'End of  part 10'
echo 'File parseargs/useful.h is continued in part 11'
echo 11 > _shar_seq_.tmp
exit 0
exit 0 # Just in case...
-- 
Kent Landfield                   INTERNET: kent at sparky.IMD.Sterling.COM
Sterling Software, IMD           UUCP:     uunet!sparky!kent
Phone:    (402) 291-8300         FAX:      (402) 291-4362
Please send comp.sources.misc-related mail to kent at uunet.uu.net.



More information about the Comp.sources.misc mailing list