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