brad@hcx1.ssd.csd.harris.com (Brad Appleton) (03/18/91)
Submitted-by: Brad Appleton <brad@hcx1.ssd.csd.harris.com> Posting-number: Volume 17, Issue 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@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@ssd.csd.harris.com> ** - Added structured block comments ** - Added optional arguments to keywords and options ** ** --/--/-- Peter da Silva <peter@ferranti.com> ** ** --/--/-- Eric P. Allman <eric@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@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@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@ferranti.com> ** ** --/--/-- Eric P. Allman <eric@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@sparky.IMD.Sterling.COM Sterling Software, IMD UUCP: uunet!sparky!kent Phone: (402) 291-8300 FAX: (402) 291-4362 Please send comp.sources.misc-related mail to kent@uunet.uu.net.