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 46 Archive-name: parseargs/part01 This is part 1 of parseargs #!/bin/sh # This is a shell archive (produced by shar 3.49) # To extract the files from this archive, save it to a file, remove # everything above the "!/bin/sh" line above, and type "sh file_name". # # made 03/16/1991 21:25 UTC by kent@sparky.IMD.Sterling.COM # Source directory /u1/csm/queue/parseargs # # existing files will NOT be overwritten unless -c is specified # # This is part 1 of a multipart archive # do not concatenate these parts, unpack them in order with /bin/sh # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 5018 -rw-rw-r-- parseargs/Intro # 4033 -rw-rw-r-- parseargs/MANIFEST # 4516 -rw-rw-r-- parseargs/Makefile # 7778 -rw-rw-r-- parseargs/Makefile.cpp # 41278 -rw-rw-r-- parseargs/README # 16890 -rw-rw-r-- parseargs/amiga_args.c # 5961 -rw-rw-r-- parseargs/arglist.c # 22590 -rw-rw-r-- parseargs/argtype.c # 7427 -rw-rw-r-- parseargs/argtype3.txt # 2300 -rw-rw-r-- parseargs/doc/Makefile # 3591 -rw-rw-r-- parseargs/doc/arg_macros.inc # 3543 -rw-rw-r-- parseargs/doc/argdesc.inc # 5228 -rw-rw-r-- parseargs/doc/argflags.inc # 7204 -rw-rw-r-- parseargs/doc/argtype.man3 # 1216 -rw-rw-r-- parseargs/doc/argvalopt.inc # 2103 -rw-rw-r-- parseargs/doc/bugs.inc # 1768 -rw-rw-r-- parseargs/doc/caveats.inc # 1627 -rw-rw-r-- parseargs/doc/cmd_macros.inc # 1093 -rw-rw-r-- parseargs/doc/defargs.inc # 1979 -rw-rw-r-- parseargs/doc/env_args.inc # 3224 -rw-rw-r-- parseargs/doc/env_parse.inc # 2820 -rw-rw-r-- parseargs/doc/env_usage.inc # 937 -rw-rw-r-- parseargs/doc/fparseargs3.inc # 1101 -rw-rw-r-- parseargs/doc/lib_bugs.inc # 428 -rw-rw-r-- parseargs/doc/lparseargs3.inc # 4932 -rw-rw-r-- parseargs/doc/multivals.inc # 12151 -rw-rw-r-- parseargs/doc/parseargs.man1 # 9554 -rw-rw-r-- parseargs/doc/parseargs.man3 # 1461 -rw-rw-r-- parseargs/doc/parseargs1.inc # 642 -rw-rw-r-- parseargs/doc/parseargs3.inc # 974 -rw-rw-r-- parseargs/doc/parsecntl.man3 # 1721 -rw-rw-r-- parseargs/doc/parsecntl3.inc # 4875 -rw-rw-r-- parseargs/doc/parsecntls.inc # 5108 -rw-rw-r-- parseargs/doc/parseflags.inc # 1427 -rw-rw-r-- parseargs/doc/parsemodes.inc # 2118 -rw-rw-r-- parseargs/doc/returns.inc # 6926 -rw-rw-r-- parseargs/doc/sh_arrays.inc # 2275 -rw-rw-r-- parseargs/doc/shells.inc # 836 -rw-rw-r-- parseargs/doc/sparseargs3.inc # 449 -rw-rw-r-- parseargs/doc/usage3.inc # 737 -rw-rw-r-- parseargs/doc/vparseargs3.inc # 23858 -rw-rw-r-- parseargs/ibm_args.c # 6648 -rw-rw-r-- parseargs/parseargs.awk # 70264 -rw-rw-r-- parseargs/parseargs.c # 42981 -rw-rw-r-- parseargs/parseargs.h # 2311 -rwxrwxr-x parseargs/parseargs.pl # 33378 -rw-rw-r-- parseargs/parseargs1.txt # 37108 -rw-rw-r-- parseargs/parseargs3.txt # 17278 -rw-rw-r-- parseargs/parsecntl3.txt # 12588 -rw-rw-r-- parseargs/pgopen.c # 977 -rw-rw-r-- parseargs/pgopen.h # 9196 -rw-rw-r-- parseargs/stest.c # 34399 -rw-rw-r-- parseargs/strfuncs.c # 1729 -rw-rw-r-- parseargs/strfuncs.h # 5916 -rw-rw-r-- parseargs/syserr.c # 6643 -rwxrwxr-x parseargs/test.awk # 2023 -rwxrwxr-x parseargs/test.csh # 2097 -rwxrwxr-x parseargs/test.ksh # 1718 -rwxrwxr-x parseargs/test.pl # 1728 -rwxrwxr-x parseargs/test.rc # 1789 -rwxrwxr-x parseargs/test.sh # 20417 -rw-rw-r-- parseargs/unix_args.c # 7749 -rw-rw-r-- parseargs/unix_man.c # 7432 -rw-rw-r-- parseargs/useful.h # 30360 -rw-rw-r-- parseargs/vms_args.c # 8146 -rw-rw-r-- parseargs/vprintf.c # 7121 -rw-rw-r-- parseargs/winsize.c # 70930 -rw-rw-r-- parseargs/xparse.c # if test -r _shar_seq_.tmp; then echo 'Must unpack archives in sequence!' echo Please unpack part `cat _shar_seq_.tmp` next exit 1 fi # ============= parseargs/Intro ============== if test ! -d 'parseargs'; then echo 'x - creating directory parseargs' mkdir 'parseargs' fi if test -f 'parseargs/Intro' -a X"$1" != X"-c"; then echo 'x - skipping parseargs/Intro (File already exists)' rm -f _shar_wnt_.tmp else > _shar_wnt_.tmp echo 'x - extracting parseargs/Intro (Text)' sed 's/^X//' << 'SHAR_EOF' > 'parseargs/Intro' && X X PARSEARGS X X extracted from Eric Allman's X X NIFTY UTILITY LIBRARY X X Created by Eric P. Allman X <eric@Berkeley.EDU> X X Modified by Peter da Silva X <peter@Ferranti.COM> X X Modified and Rewritten by Brad Appleton X <brad@SSD.CSD.Harris.COM> X X X Welcome to parseargs! Dont let the initial size of this package scare you. X over 75% of it is English text, and more than 50% of the source is comments. X X Parseargs is a set of functions to parse command-line arguments. Unlike X getopt and its variants, parseargs does more than just split up the X command-line into some canonical form. Parseargs will actually parse the X command-line, assigning the appropriate command-line values to the X corresponding variables, and will verify the command-line syntax (and print X a usage message if necessary). Furthermore, many features of it's parsing X behavior are configurable at run-time. Some of these features include the X following: X X o Prompting the user for missing arguments X o Allowing keywords (+count=4) and/or options (-c4) X o Checking for default arguments in an environment variable X o Ignoring bad syntax instead of terminating X o Ignoring upper/lower case on the command-line X o Controlling the location of non-positional parameters X o Controlling the contents (syntax and verbosity) of usage messages X o Having long usage messages piped through a paging program X X Parseargs also allows for options that take an optional argument, and X options that take a (possibly optional) list of one or more arguments. X In addition, parseargs may be configured at compile-time to parse X command-lines in accordance with the native command-syntax of any of the X following operating systems: X X o Unix X o VAX/VMS X o OS/2 X o MS-DOS X o AmigaDOS X X Parseargs consists of a set of C-functions to parse arguments from the X command-line, from files, from strings, from linked-lists, and from X string-vectors. Also included is a command-line interface which will parse X arguments for shell scripts (sh, csh/tcsh, ksh, bash, and rc), awk-scripts, X and perl-scripts. X X The basic structure used by parseargs is the argument-descriptor (sometimes X called "argdesc" for brevity). An array/string of argdescs is declared by X the user to describe the command in question. The resulting argdesc-array X is passed to all the parseargs functions and is used to hold all information X about the command. a sample argdesc-array is shown below. X X STARTOFARGS, X { 'a', ARGVALOPT, argStr, &area, "AREAcode : optional area-code" }, X { 'g', ARGLIST, argStr, &groups, "newsGROUPS : groups to test" }, X { 'r', ARGOPT, argInt, &count, "REPcount : repetition factor" }, X { 's', ARGOPT, argChar, &sepch, "SEPchar : field separator" }, X { 'x', ARGOPT, argBool, &xflag, "Xflag : turn on X-mode" }, X { ' ', ARGREQ, argStr, &name, "name : name to use" }, X { ' ', ARGLIST, argStr, &args, "args : any remaining arguments" }, X ENDOFARGS X X Once the above array/string is declared it is a simple matter to invoke X parseargs from C as in the following example: X X status = parseargs( argdesc_array, argv ); X X or from a shell script as in the following example: X X echo "$ARGDESC_STR" | parseargs -s sh -- "$0" "$@" >tmp$$ X if [ $? = 0 ] ; then X . tmp$$ X fi X /bin/rm -f tmp$$ X X And before you know it, your command-line had been parsed, all variables X have been assigned their corresponding values from the command-line, syntax X has been verified, and a usage message (if required) has been printed. X X Under UNIX, the command-line syntax (using single character options) for the X above command would be: X X cmdname [-a [<areacode>]] [-g <newsgroups>...] [-r <repcount>] X [-s <sepchar>] [-x] <name> [<args>...] X X The UNIX command-line syntax using keywords (or long options) would be: X X cmdname [+area [<areacode>]] [+groups <newsgroups>...] [+rep <repcount>] X [+sep <sepchar>] [+x] <name> [<args>...] X X The VMS command-line syntax would be the following: X X cmdname [/AREA[=<areacode>]] [/GROUPS=<newsgroups>[,<newsgroups>...] X [/REP=<repcount>] [/SEP=<sepchar>] [/X] <name> X [<args>[,<args>...]] X X The MS-DOS and OS/2 command-line syntax would be the following (unless the X environment variable $SWITCHAR is '-' in which case UNIX syntax is used): X X cmdname [/a[=<areacode>]] [/g=<newsgroups>...] [/r=<repcount>] X [/s=<sepchar>] [/x] <name> [<args>...] X X The AmigaDOS command-line syntax would be the following: X X cmdname [AREA [<areacode>]] [GROUPS <newsgroups>...] [REP <repcount>] X [SEP <sepchar>] [X] <name> [<args>...] X X X Please look at the README files and manpages for more detailed information! SHAR_EOF chmod 0664 parseargs/Intro || echo 'restore of parseargs/Intro failed' Wc_c="`wc -c < 'parseargs/Intro'`" test 5018 -eq "$Wc_c" || echo 'parseargs/Intro: original size 5018, current size' "$Wc_c" rm -f _shar_wnt_.tmp fi # ============= parseargs/MANIFEST ============== if test -f 'parseargs/MANIFEST' -a X"$1" != X"-c"; then echo 'x - skipping parseargs/MANIFEST (File already exists)' rm -f _shar_wnt_.tmp else > _shar_wnt_.tmp echo 'x - extracting parseargs/MANIFEST (Text)' sed 's/^X//' << 'SHAR_EOF' > 'parseargs/MANIFEST' && X File Name Archive # Description ----------------------------------------------------------- X Intro 2 Introduction to parseargs X MANIFEST 1 This file X Makefile 2 makefile for parseargs library X Makefile.cpp 3 makefile template read by the C preprocessor X README 1 release information X amiga_args.c 4 parse AmigaDOS command-lines X arglist.c 2 implement the listXxxx functions for arglists X argtype.c 5 implement the argXxxx argument type functions X doc/ 1 directory containing documentation X doc/Makefile 2 makefile for the documentation X doc/arg_macros.inc 2 describe arg-xxx and ARG_XXX macros X doc/argdesc.inc 2 describe an ARGDESC structure X doc/argflags.inc 2 describe argument flags X doc/argtype.man3 3 {n,t}roff source for argtype(3) X doc/argvalopt.inc 1 describe options with optional arguments X doc/bugs.inc 2 BUGS section for parseargs(1) X doc/caveats.inc 1 CAVEATS section for parseargs(1) and (3) X doc/cmd_macros.inc 1 describe CMD_XXX macros X doc/defargs.inc 1 describe the default argdesc-array X doc/env_args.inc 1 describe use of $CMD_ARGS X doc/env_parse.inc 2 describe use of $PARSECNTL X doc/env_usage.inc 2 describe use of $USAGECNTL X doc/fparseargs3.inc 1 describe fparseargs(3) X doc/lib_bugs.inc 1 BUGS section for parseargs(3) X doc/lparseargs3.inc 1 describe lparseargs(3) X doc/multivals.inc 2 describe multivals(3) X doc/parseargs.man1 4 {n,t}roff source for parseargs(1) X doc/parseargs.man3 4 {n,t}roff source for parseargs(3) X doc/parseargs1.inc 1 describe parseargs(1) X doc/parseargs3.inc 1 describe parseargs(3) X doc/parsecntl.man3 1 {n,t}roff source for parsecntl(3) X doc/parsecntl3.inc 1 describe parsecntl(3) X doc/parsecntls.inc 2 describe function-codes for parsecntl(3) X doc/parseflags.inc 2 describe parse flags X doc/parsemodes.inc 1 describe modes for parsecntl(3) X doc/returns.inc 2 describe function return values X doc/sh_arrays.inc 3 describe handling of shell arrays X doc/shells.inc 2 describe handling of different shells X doc/sparseargs3.inc 1 describe sparseargs(3) X doc/usage3.inc 1 describe usage(3) X doc/vparseargs3.inc 1 describe vparseargs(3) X ibm_args.c 5 parse MS-DOS and OS/2 command-lines X parseargs.awk 3 parseargs for awk X parseargs.c 7 C source for parseargs(1) X parseargs.h 6 include file for parseargs library X parseargs.pl 2 parseargs for perl X pgopen.c 4 pipe output to a pager X pgopen.h 1 include file for pgopen.c X stest.c 3 test progarm for parseargs(3) X strfuncs.c 6 string library X strfuncs.h 1 include file for strfuncs.c X syserr.c 2 diagnostic message printing routines X test.awk 3 awk test program for parseargs(1) X test.csh 2 C-shell test program for parseargs(1) X test.ksh 2 Korn shell test program for parseargs(1) X test.pl 1 perl test program for parseargs(1) X test.rc 1 Plan 9 shell test program for parseargs(1) X test.sh 1 Bourne shell test program for parseargs(1) X unix_args.c 4 parse Unix command-lines X unix_man.c 3 print Unix manual-page templates X useful.h 3 common include file for the library X vms_args.c 5 parse VAX/VMS DCL command-lines X vprintf.c 3 portable vfprintf, vprintf, and vsprintf X winsize.c 3 determine # rows and # columns of window X xparse.c 8 implement the parseargs library SHAR_EOF chmod 0664 parseargs/MANIFEST || echo 'restore of parseargs/MANIFEST failed' Wc_c="`wc -c < 'parseargs/MANIFEST'`" test 4033 -eq "$Wc_c" || echo 'parseargs/MANIFEST: original size 4033, current size' "$Wc_c" rm -f _shar_wnt_.tmp fi # ============= parseargs/Makefile ============== if test -f 'parseargs/Makefile' -a X"$1" != X"-c"; then echo 'x - skipping parseargs/Makefile (File already exists)' rm -f _shar_wnt_.tmp else > _shar_wnt_.tmp echo 'x - extracting parseargs/Makefile (Text)' sed 's/^X//' << 'SHAR_EOF' > 'parseargs/Makefile' && # $Header: Makefile,v 2.1 89/12/30 20:59:01 eric Exp $ X ### # operating-system dependent stuff ### .UNIVERSE = att #.UNIVERSE = ucb OS_TYPE = unix # OS_DEFS = -D${OS_TYPE} -D${.UNIVERSE}_universe X ### # targets ### NAME = parseargs PROGRAM = ${NAME} LIBRARY = ${NAME} STYLE = unix X ### # target directories ### LOCAL = /usr/local LIBDIR = ${LOCAL}/lib INCDIR = ${LOCAL}/include X ### # compilation options ### INCLUDES = -I. # MODEL = -Ms # MODELNAME = S OPT = -O # OPT = -g TEST_DEFS = USR_DEFS = -DUSE_PAGER DEFINES = ${OS_DEFS} ${USR_DEFS} ${TEST_DEFS} -D${STYLE}_style OPTIONS = CFLAGS = ${OPT} ${MODEL} ${INCLUDES} ${DEFINES} ${OPTIONS} LINTFLAGS = ${INCLUDES} ${DEFINES} ${OPTIONS} X ### # libraries ### LIBARGS = ${MODELNAME}lib${STYLE}_args.a LIBFILE = ${MODELNAME}libparse.a LOCLIBS = ${LIBARGS} # SYSLIBS = -lm -lcurses -ltermcap LIBS = ${LOCLIBS} ${SYSLIBS} X ### # commands ### AR = ar rvu DEL = rm -f COPY = cp CHDIR = cd LINT = lint MKTAGS = ctags PRINT = pr RANLIB = ranlib SHAR = shar SQZ = compress -v X ### # files used ### DOCS= doc/Makefile \ X doc/argtype.man3 \ X doc/parseargs.man1 \ X doc/parseargs.man3 \ X doc/parsecntl.man3 \ X doc/arg_macros.inc \ X doc/argdesc.inc \ X doc/argflags.inc \ X doc/argvalopt.inc \ X doc/bugs.inc \ X doc/caveats.inc \ X doc/cmd_macros.inc \ X doc/defargs.inc \ X doc/env_args.inc \ X doc/env_parse.inc \ X doc/env_usage.inc \ X doc/fparseargs3.inc \ X doc/lib_bugs.inc \ X doc/lparseargs3.inc \ X doc/multivals.inc \ X doc/parseargs1.inc \ X doc/parseargs3.inc \ X doc/parsecntl3.inc \ X doc/parsecntls.inc \ X doc/parseflags.inc \ X doc/parsemodes.inc \ X doc/returns.inc \ X doc/sh_arrays.inc \ X doc/shells.inc \ X doc/sparseargs3.inc \ X doc/usage3.inc \ X doc/vparseargs3.inc SCRIPTS = test.sh test.csh test.ksh test.rc test.awk test.pl TEMPLATES = ${NAME}.pl ${NAME}.awk XXXFILES = Intro README MANIFEST Makefile Makefile.cpp X HDRS = ${NAME}.h \ X pgopen.h \ X strfuncs.h \ X useful.h X SRCS = ${NAME}.c \ X argtype.c \ X arglist.c \ X amiga_args.c \ X ibm_args.c \ X pgopen.c \ X stest.c \ X strfuncs.c \ X syserr.c \ X unix_args.c \ X unix_man.c \ X vms_args.c \ X vprintf.c \ X winsize.c \ X xparse.c X OBJS = ${STYLE}_args.o \ X arglist.o \ X argtype.o \ X pgopen.o \ X strfuncs.o \ X syserr.o \ X vprintf.o \ X winsize.o \ X xparse.o X PROG_OBJS = ${NAME}.o unix_man.o TEST_OBJS = stest.o X FILES = ${XXFILES} ${DOCS} ${HDRS} ${SRCS} ${TEMPLATES} ${SCRIPTS} X ### # target dependencies ### all: ${LIBARGS} test ${PROGRAM} X test: ${STYLE}_test X ${STYLE}_test : stest.o ${LOCLIBS} X ${CC} ${CFLAGS} -o ${STYLE}_test stest.o ${LOCLIBS} ${SYSLIBS} X ${LIBARGS}: ${OBJS} X ${AR} $@ ${OBJS} X ${RANLIB} $@ X ${PROGRAM}: ${PROG_OBJS} ${LOCLIBS} X ${CC} ${CFLAGS} -o $@ ${PROG_OBJS} ${LOCLIBS} ${SYSLIBS} X ### # object dependencies ### ${NAME}.o: ${NAME}.c ${NAME}.h strfuncs.h useful.h amiga_args.o: amiga_args.c ${NAME}.h pgopen.h strfuncs.h useful.h arglist.o: arglist.c ${NAME}.h strfuncs.h useful.h argtype.o: argtype.c ${NAME}.h strfuncs.h useful.h ibm_args.o: ibm_args.c ${NAME}.h pgopen.h strfuncs.h useful.h pgopen.o: pgopen.c useful.h stest.o: stest.c ${NAME}.h useful.h strfuncs.o: strfuncs.c useful.h syserr.o: syserr.c useful.h unix_args.o: unix_args.c ${NAME}.h pgopen.h strfuncs.h useful.h unix_man.o: unix_man.c ${NAME}.h strfuncs.h useful.h vms_args.o: vms_args.c ${NAME}.h pgopen.h strfuncs.h useful.h vprintf.o: vprintf.c useful.h winsize.o: winsize.c useful.h xparse.o: xparse.c ${NAME}.h strfuncs.h useful.h X ### # installation dependencies ### install: ${INCDIR}/${NAME}.h \ X ${LIBDIR}/${LIBFILE} \ X ${LOCAL}/${PROGRAM} X X ${INCDIR}/${NAME}.h: ${NAME}.h useful.h X ( ${CHDIR} ${INCDIR}; ${DEL} ${NAME}.h useful.h ) X ${COPY} ${NAME}.h useful.h ${INCDIR} X X ${LIBDIR}/${LIBFILE}: ${LIBARGS} X ${DEL} ${LIBDIR}/${LIBFILE} X ${COPY} ${LIBARGS} ${LIBDIR}/${LIBFILE} X ${RANLIB} ${LIBDIR}/${LIBFILE} X X ${LOCAL}/${PROGRAM}: ${PROGRAM} ${TEMPLATES} X ( ${CHDIR} ${LOCAL} ; ${DEL} ${PROGRAM} ${TEMPLATES} ) X ${COPY} ${PROGRAM} ${TEMPLATES} ${LOCAL} X ### # maintenance dependencies ### lint: ${SRCS} X ${LINT} ${LINTFLAGS} ${SRCS} X shar: ${NAME}.shar X ${NAME}.shar: ${FILES} X ${DEL} ${NAME}.shar X ${SHAR} ${FILES} >${NAME}.shar X clean: X ${DEL} ${OBJS} ${PROG_OBJS} ${TEST_OBJS} X ${DEL} tags core .exrc X clobber: clean X ${DEL} ${LIBARGS} ${PROGRAM} ${STYLE}_test X tags: ${SRCS} ${HDRS} X ${MKTAGS} ${SRCS} ${HDRS} X collapse: clobber shar X ${SQZ} ${NAME}.shar X ${DEL} ${FILES} X print: ${SRCS} ${HDRS} X @${PRINT} ${SRCS} ${HDRS} X SHAR_EOF chmod 0664 parseargs/Makefile || echo 'restore of parseargs/Makefile failed' Wc_c="`wc -c < 'parseargs/Makefile'`" test 4516 -eq "$Wc_c" || echo 'parseargs/Makefile: original size 4516, current size' "$Wc_c" rm -f _shar_wnt_.tmp fi # ============= parseargs/Makefile.cpp ============== if test -f 'parseargs/Makefile.cpp' -a X"$1" != X"-c"; then echo 'x - skipping parseargs/Makefile.cpp (File already exists)' rm -f _shar_wnt_.tmp else > _shar_wnt_.tmp echo 'x - extracting parseargs/Makefile.cpp (Text)' sed 's/^X//' << 'SHAR_EOF' > 'parseargs/Makefile.cpp' && #define REM # #define REMLINE ### X #define ECHO(x) x X #ifdef unix # define SYSTEM_NAME \unix # define SYSTEM_TYPE att # define _Output(file) >file # define _Executable(file) file # define _Library(file) file # define _Object(file) file.o # define _SubDir(d1,d2) d1/d2 # define _Dir(dir) dir # define _Pathname(dir,file) dir/file # define ROOT_DIR / # define AR_CMD ar rvu # define DEL_CMD rm -f # define COPY_CMD cp # define CHDIR_CMD cd # define LINT_CMD lint # define MKTAGS_CMD ctags # define PRINT_CMD pr # define RANLIB_CMD ranlib # define SHAR_CMD shar # define SQZ_CMD compress -v #endif X #ifdef vms # define SYSTEM_NAME \vms # define SYSTEM_TYPE dec # define _Output(file) /OUTPUT=file # define _Executable(file) file.exe # define _Library(file) file # define _Object(file) file.obj # define _SubDir(d1,d2) d1.d2 # define _Dir(dir) [dir] # define _Pathname(dir,file) ECHO(dir)file # define ROOT_DIR # define AR_CMD ar rvu # define DEL_CMD delete/file # define COPY_CMD copy/file # define CHDIR_CMD set/dir # define LINT_CMD lint # define MKTAGS_CMD ctags # define PRINT_CMD type # define RANLIB_CMD ranlib # define SHAR_CMD shar # define SQZ_CMD compress/file #endif X #if ( defined(AZTEC) || defined(MANX) ) # define SYSTEM_NAME amiga # define SYSTEM_TYPE commodore # define _Output(file) >file # define _Executable(file) file.exe # define _Library(file) file # define _Object(file) file.obj # define _SubDir(d1,d2) d1/d2 # define _Dir(dir) dir # define _Pathname(dir,file) dir/file # define ROOT_DIR / # define AR_CMD ar rvu # define DEL_CMD rm -f # define COPY_CMD cp # define CHDIR_CMD cd # define LINT_CMD lint # define MKTAGS_CMD ctags # define PRINT_CMD type # define RANLIB_CMD ranlib # define SHAR_CMD shar # define SQZ_CMD compress -v #endif X #ifdef MS_DOS # define SYSTEM_NAME dos # define SYSTEM_TYPE ibm # define _Output(file) >file # define _Executable(file) file.exe # define _Library(file) file # define _Object(file) file.obj # define _SubDir(d1,d2) d1\\d2 # define _Dir(dir) dir # define _Pathname(dir,file) dir\\file # define ROOT_DIR \\ # define AR_CMD ar rvu # define DEL_CMD del # define COPY_CMD copy # define CHDIR_CMD cd # define LINT_CMD lint # define MKTAGS_CMD ctags # define PRINT_CMD type # define RANLIB_CMD ranlib # define SHAR_CMD shar # define SQZ_CMD arc -c #endif X #ifdef OS2 # define SYSTEM_NAME os2 # define SYSTEM_TYPE ibm # define _Output(file) >file # define _Executable(file) file.exe # define _Library(file) file # define _Object(file) file.obj # define _SubDir(d1,d2) d1\\d2 # define _Dir(dir) dir # define _Pathname(dir,file) dir\\file # define ROOT_DIR \\ # define AR_CMD ar rvu # define DEL_CMD del # define COPY_CMD copy # define CHDIR_CMD cd # define LINT_CMD lint # define MKTAGS_CMD ctags # define PRINT_CMD type # define RANLIB_CMD ranlib # define SHAR_CMD shar # define SQZ_CMD arc -c #endif X REM $Header: Makefile,v 2.1 89/12/30 20:59:01 eric Exp $ X REMLINE REM operating-system dependent stuff REMLINE .UNIVERSE = SYSTEM_TYPE OS_TYPE = SYSTEM_NAME REM OS_DEFS = -D${OS_TYPE} -D${.UNIVERSE}_universe X REMLINE REM targets REMLINE NAME = parseargs PROGRAM = _Executable(${NAME}) LIBRARY = _Library(${NAME}) STYLE = SYSTEM_NAME X REMLINE REM target directories REMLINE LOCAL = _Dir(_SubDir(usr,local)) LIBDIR = _Dir(_SubDir(${LOCAL},lib)) INCDIR = _Dir(_SubDir(${LOCAL},include)) X REMLINE REM compilation options REMLINE INCLUDES = -I. REM MODEL = -Ms REM MODELNAME = S OPT = -O REM OPT = -g TEST_DEFS = USR_DEFS = -DUSE_PAGER DEFINES = ${OS_DEFS} ${USR_DEFS} ${TEST_DEFS} -D${STYLE}_style OPTIONS = CFLAGS = ${OPT} ${MODEL} ${INCLUDES} ${DEFINES} ${OPTIONS} LINTFLAGS = ${INCLUDES} ${DEFINES} ${OPTIONS} X REMLINE REM libraries REMLINE LIBARGS = ${MODELNAME}lib${STYLE}_args.a LIBFILE = ${MODELNAME}libparse.a LOCLIBS = ${LIBARGS} REM SYSLIBS = -lm -lcurses -ltermcap LIBS = ${LOCLIBS} ${SYSLIBS} X REMLINE REM commands REMLINE AR = AR_CMD DEL = DEL_CMD COPY = COPY_CMD CHDIR = CHDIR_CMD LINT = LINT_CMD MKTAGS = MKTAGS_CMD PRINT = PRINT_CMD RANLIB = RANLIB_CMD SHAR = SHAR_CMD SQZ = SQZ_CMD X REMLINE REM files used REMLINE DOCS= doc/Makefile \ X doc/argtype.man3 \ X doc/parseargs.man1 \ X doc/parseargs.man3 \ X doc/parsecntl.man3 \ X doc/arg_macros.inc \ X doc/argdesc.inc \ X doc/argflags.inc \ X doc/argvalopt.inc \ X doc/bugs.inc \ X doc/caveats.inc \ X doc/cmd_macros.inc \ X doc/defargs.inc \ X doc/env_args.inc \ X doc/env_parse.inc \ X doc/env_usage.inc \ X doc/fparseargs3.inc \ X doc/lib_bugs.inc \ X doc/lparseargs3.inc \ X doc/multivals.inc \ X doc/parseargs1.inc \ X doc/parseargs3.inc \ X doc/parsecntl3.inc \ X doc/parsecntls.inc \ X doc/parseflags.inc \ X doc/parsemodes.inc \ X doc/returns.inc \ X doc/sh_arrays.inc \ X doc/shells.inc \ X doc/sparseargs3.inc \ X doc/usage3.inc \ X doc/vparseargs3.inc SCRIPTS = test.sh test.csh test.ksh test.rc test.awk test.pl TEMPLATES = ${NAME}.pl ${NAME}.awk XXXFILES = Intro README MANIFEST Makefile Makefile.cpp X HDRS = ${NAME}.h \ X pgopen.h \ X strfuncs.h \ X useful.h X SRCS = ${NAME}.c \ X argtype.c \ X arglist.c \ X amiga_args.c \ X ibm_args.c \ X pgopen.c \ X stest.c \ X strfuncs.c \ X syserr.c \ X unix_args.c \ X unix_man.c \ X vms_args.c \ X vprintf.c \ X winsize.c \ X xparse.c X OBJS = _Object(${STYLE}_args) \ X _Object(arglist) \ X _Object(argtype) \ X _Object(pgopen) \ X _Object(strfuncs) \ X _Object(syserr) \ X _Object(vprintf) \ X _Object(winsize) \ X _Object(xparse) X PROG_OBJS = _Object(${NAME}) _Object(unix_man) TEST_OBJS = _Object(stest) X FILES = ${XXFILES} ${DOCS} ${HDRS} ${SRCS} ${TEMPLATES} ${SCRIPTS} X REMLINE REM target dependencies REMLINE all: ${LIBARGS} test ${PROGRAM} X test: ${STYLE}_test X ${STYLE}_test : _Object(stest) ${LOCLIBS} X ${CC} ${CFLAGS} -o ${STYLE}_test _Object(stest) ${LOCLIBS} ${SYSLIBS} X ${LIBARGS}: ${OBJS} X ${AR} $@ ${OBJS} X ${RANLIB} $@ X ${PROGRAM}: ${PROG_OBJS} ${LOCLIBS} X ${CC} ${CFLAGS} -o $@ ${PROG_OBJS} ${LOCLIBS} ${SYSLIBS} X REMLINE REM object dependencies REMLINE ${NAME}.o: ${NAME}.c ${NAME}.h strfuncs.h useful.h amiga_args.o: amiga_args.c ${NAME}.h pgopen.h strfuncs.h useful.h arglist.o: arglist.c ${NAME}.h strfuncs.h useful.h argtype.o: argtype.c ${NAME}.h strfuncs.h useful.h ibm_args.o: ibm_args.c ${NAME}.h pgopen.h strfuncs.h useful.h pgopen.o: pgopen.c useful.h stest.o: stest.c ${NAME}.h useful.h strfuncs.o: strfuncs.c useful.h syserr.o: syserr.c useful.h unix_args.o: unix_args.c ${NAME}.h pgopen.h strfuncs.h useful.h unix_man.o: unix_man.c ${NAME}.h strfuncs.h useful.h vms_args.o: vms_args.c ${NAME}.h pgopen.h strfuncs.h useful.h vprintf.o: vprintf.c useful.h winsize.o: winsize.c useful.h xparse.o: xparse.c ${NAME}.h strfuncs.h useful.h X REMLINE REM installation dependencies REMLINE install: _Pathname(${INCDIR},${NAME}.h) \ X _Pathname(${LIBDIR},${LIBFILE}) \ X _Pathname(${LOCAL},${PROGRAM}) X _Pathname(${INCDIR},${NAME}.h): ${NAME}.h useful.h X ( ${CHDIR} ${INCDIR}; ${DEL} ${NAME}.h useful.h ) X ${COPY} ${NAME}.h useful.h ${INCDIR} X _Pathname(${LIBDIR},${LIBFILE}): ${LIBARGS} X ${DEL} _Pathname(${LIBDIR},${LIBFILE}) X ${COPY} ${LIBARGS} _Pathname(${LIBDIR},${LIBFILE}) X ${RANLIB} _Pathname(${LIBDIR},${LIBFILE}) X _Pathname(${LOCAL},${PROGRAM}): ${PROGRAM} ${TEMPLATES} X ( ${CHDIR} ${LOCAL} ; ${DEL} ${PROGRAM} ${TEMPLATES} ) X ${COPY} ${PROGRAM} ${TEMPLATES} ${LOCAL} X REMLINE REM maintenance dependencies REMLINE lint: ${SRCS} X ${LINT} ${LINTFLAGS} ${SRCS} X shar: ${NAME}.shar X ${NAME}.shar: ${FILES} X ${DEL} ${NAME}.shar X ${SHAR} ${FILES} _Output(${NAME}.shar) X clean: X ${DEL} ${OBJS} ${PROG_OBJS} ${TEST_OBJS} X ${DEL} tags core .exrc X clobber: clean X ${DEL} ${LIBARGS} ${PROGRAM} ${STYLE}_test X tags: ${SRCS} ${HDRS} X ${MKTAGS} ${SRCS} ${HDRS} X collapse: clobber shar X ${SQZ} ${NAME}.shar X ${DEL} ${FILES} X print: ${SRCS} ${HDRS} X @${PRINT} ${SRCS} ${HDRS} X SHAR_EOF chmod 0664 parseargs/Makefile.cpp || echo 'restore of parseargs/Makefile.cpp failed' Wc_c="`wc -c < 'parseargs/Makefile.cpp'`" test 7778 -eq "$Wc_c" || echo 'parseargs/Makefile.cpp: original size 7778, current size' "$Wc_c" rm -f _shar_wnt_.tmp fi # ============= parseargs/README ============== if test -f 'parseargs/README' -a X"$1" != X"-c"; then echo 'x - skipping parseargs/README (File already exists)' rm -f _shar_wnt_.tmp else > _shar_wnt_.tmp echo 'x - extracting parseargs/README (Text)' sed 's/^X//' << 'SHAR_EOF' > 'parseargs/README' && X X X X PARSEARGS X X extracted from Eric Allman's X X NIFTY UTILITY LIBRARY X X Eric P. Allman X University of California X Berkeley, California X eric@Berkeley.EDU X X modifications by X X Peter da Silva X Ferranti International Controls Corporation X Sugar Land, Texas X peter@ferranti.com X X modified and rewritten by X X Brad Appleton X Harris Corporation, Computer Systems Division X Fort Lauderdale, Florida USA X brad@ssd.csd.harris.com X X X X SUMMARY X ======= X This directory contains a subset of a utility library that I have used X (in various forms) for several years now. This particular version is X rather sparse, being a relatively recent reimplementation. X X [ The rest of the utility library has been left out, to reduce the X size of Parseargs. The complete set of utilities was pubbed in the X first comp.sources.misc distribution. -- PDS ] X X I am making this available as a result of the rather surprising X response to my C Advisor column in UNIX Review Vol. 7 No. 11 on X argument parsing, in which I described an alternative to getopt. X Several dozen people have asked for the source code -- an amazing X number, considering that in the four years prior to this column, I X have gotten perhaps six letters in total. X X X COPY/REUSE POLICY X ================= X Permission is hereby granted to freely copy and redistribute this X software, provided that the author is clearly credited in all copies X and derivations. Neither the name of the author nor that of the X University may be used to endorse or promote products derived from X this software without specific written permission. This software is X provided ``As Is'' and without any express or implied warranties. X X X CONTENTS X ======== X README : this file. X [ Intro : introduction to parseargs -- BDA ] X [ doc/Makefile : makefile for parseargs documentation -- BDA ] X [ doc/* : documentation for parseargs -- BDA ] X Makefile : a makefile for the library. X [ Makefile.cpp : a makefile template -- BDA ] X useful.h : a general header file, used by most everything. X parseargs.h : headers for the argument parser. X [ parseargs.c is now broken down into the following files : PDS ] X unix_args.c : a command line argument parser. Popular X response to my C Advisor column about this routine X in UNIX Review Vol. 7 No. 11 prompted me to make X this distribution available. X amiga_args.c : Amiga version of unix_args.c -- PDS X ibm_args.c : IBM-PC version of unix_args.c -- BDA X vms_args.c : VAX/VMS version of unix_args.c -- BDA X arglist.c : routines for ARGLIST options. -- PDS X argtype.c : routines for other options. The argument value parsers X for floating point values may be excluded by #defining the X macro NOFLOAT (only if you do NOT need floating-point values). X I had to break this out because RISC/os 4.01 from Mips doesn't X seem to support strtod in the BSD environment. You may find you X need to include -lm for this to work. X strfuncs.[ch] : string-manipulation functions & X dictionary-style searching routines. X [ end of parseargs.c : PDS ] X [ parseargs.c has been resurrected as a command line interface X to the parseargs library routines -- BDA ] X syserr.c : error message printing routines. X stest.c : a small test program for the argument parser. X [ xparse.c : source for [flsv]parseargs() and parsecntl() -- BDA ] X [ unix_man.c : routine to print unix man1 templates -- BDA ] X [ winsize.c : routine to "portably" get the screen size -- BDA ] X [ pgopen.[ch] : Unix source to pipe output to a pager -- BDA ] X [ vprintf.c : portable implementations of vprintf() & vfprintf() ] X [ parseargs.awk : awk interface to parseargs(1) -- BDA ] X [ parseargs.pl : perl interface to parseargs(1) -- BDA ] X [ test.sh : Bourne shell-script to test parseargs(1) -- BDA ] X [ test.csh : C shell-script to test parseargs(1) -- BDA ] X [ test.ksh : Korn shell-script to test parseargs(1) -- BDA ] X [ test.awk : awk script to test parseargs(1) -- BDA ] X [ test.pl : perl script to test parseargs(1) -- BDA ] X X The parseargs routines really ought to have a way of matching a list X (e.g., return the rest of argv). This isn't especially hard to do, but X I haven't gotten around to it yet. [ Added, with ARGLIST flag -- PDS ] X X [ Added argUsage and argDummy pseudo-argument types -- BDA ] X [ Added arg{S,T,U}Bool boolean argument types -- BDA ] X [ Added ARGNOVAL argument flag to implement trigger types -- BDA ] X [ Added ARGVALOPT, ARGVALREQ, and ARGVALGIVEN argument flags to X implement options with optional arguments -- BDA ] X [ Added ARGPOS argument flag to implement arguments that may be X matched both positonally and by keyword -- BDA ] X [ Added ARGVEC for argc/argv structures and implemented them for X string, character, floating point, and integer types -- BDA ] X [ Added fparseargs(3), sparseargs(3), vparseargs(3), lparseargs(3), X and parsecntl(3) functions for flexibility and robustness -- BDA ] X X X DISCLAIMERS X =========== X I hacked this code up to (hopefully) work on ANSI C compilers, since X several readers seem to be interested in this sort of thing. I can't X claim to have really tested this. X [ Now compiles under both BSD & AT&T Unix Systems using both ANSI and X non-ANSI C compilers -- BDA ] X X The original version was tested under SunOS 4.0 on SPARC X architectures. The version you see has been loosely tested on a Mips X M/2000 running RISC/os 4.01; I have only tried it in the BSD X environment, and that only loosely. X X ACKNOWLEDGEMENTS X ================ X I wrote the first version of this code while working at the X International Computer Science Institute in Berkeley, CA. X X ______________________________________________________________________________ X X Update to parseargs by Peter da Silva (peter@ferranti.com): X X (2nd update: more improvements to arg parsing, argChar type) X (3rd update: return to original calling sequence, argList type) X (4th update: removed routines not relevant to parseargs, X removed tracing/interactive stuff.) X X X Parseargs is a really nifty set of routines, but it doesn't fit too X well with standard UNIX semantics. In particular, you can get into a X lot of trouble using it in a script if it drops into interactive mode X on you. Also, it's not as useful as it could be for non-UNIX systems. X To make it work better, I've made a couple of changes. X X It compiled straight out of the box on System III once I'd provided X bcopy, bcmp, and strtol. The strtol I've provided is almost totally X untested, but hopefully you won't need to use it. It's only for folks X with old UNIX systems. X X First change was to disable the interactive prompting for arguments. I X think that's inconsistent with usual UNIX semantics. X X The second change was to allow for a trailing list of arguments. I X originally implemented this by changing the calling sequence to X parseargs. On reflection this would just produce incompatibilities, so X I added a new flag, ARGLIST, and a new type, listStr. Later, other X kinds of lists can presumably be added. A list handles a pointer to a X list of objects: X X struct arglist *fred; X X Operations are defined on arglists, L_NEXT(fred) produces the next X element in fred. L_STRING(fred) produces the value of fred cast to X "char *". X X During evaluation the list is kept in LIFO order, and it's reversed X just before returning to parseargs. This simplifies the coding of the X list routines, but still lets you step through the list in a X reasonable order. [ lists are now maintained in FIFO order --BDA ] X X The final change is the addition of a 'argChar' type. This parses X character arguments (such as the '-T' option to 'awk'), accepting X single characters, X X Parseargs itself no longer uses ckalloc, traceset, funclist, and so X on. these routines are pretty cool, but when you're grafting parseargs X onto an existing program they just get in the way. Also, it's possible X to make parseargs fail in a cleaner fashion by handling out-of-memory X cases myself. Certainly there's not going to be any loose memory lying X around to be collected when parseargs starts up! X X Also, the error messages have been made a bit more descriptive. X Instead of saying "stest: value required for -c flag", it prints X "stest: RepCount required for -c flag". The ad_prompt element should X really be a descriptive word that can be used in a sentence... or for X non_UNIX systems a multi-character or keyword based flag. I have an X Amiga version included, for example, that uses keyword syntax. In that X version, the usage message reads: X X Usage: amiga_test <name> [GROUP <newsgroup>]... [REP <repcount>] + X [DIR <dirname>] [X] [Y] [Z] [TAB <tabchar>] [<file>]... X X Instead of: X X Usage: unix_test <Name> [-n <newsGROUP>]... [-c <REPcount>] [-d <DIRname>] [-x] [-y] [-z] [-t <TABchar>] [<File>]... X X X This would solve the old problem of UNIX programs sticking out like a X sore thumb in other operating systems. X X The Amiga version still needs to prompt for options if called with a X single types and finally integrate CLI and Workbench environments. X X Latest update: the prompt string may include a more extensive comment X (in parentheses, after the one-word initial comment), that will be X used in error messages and listed in the usage message. X X [ comment may appear in square brackets, curly braces, angle brackets, X or parentheses (so one can use the other 3 in the comment) -- BDA ] X X The environment variable USAGE controls the printing of the usage X message: X X USAGE == -1 No usage message. X USAGE == 0 Short message (default). X USAGE == 1 Names of flags given in parentheses. X USAGE == 2 Long description of options given. X USAGE == 3 Both flag names and long description given. X X Examples: X X $ USAGE=3; export USAGE X $ unix_test -c X unix_test: REPcount (number of times to repeat each group) required for -c flag X unix_test: Name required X Usage: unix_test <Name> [-n <newsGROUP>]... [-c <REPcount>] [-d <DIRname>] [-x] (Xflag) [-y] (Yflag) [-z] (Zflag) [-t <TABchar>] [<File>]... X Options: X -n newsGROUP newsgroups to test X -c REPcount number of times to repeat each group X -x (Xflag) expand in X direction X -y (Yflag) expand in Y direction X -z (Zflag) expand in Z direction X $ USAGE=0; export USAGE X $ unix_test X unix_test: Name required X Usage: unix_test <Name> [-n <newsGROUP>]... [-c <REPcount>] [-d <DIRname>] [-x] [-y] [-z] [-t <TABchar>] [<File>]... X $ USAGE=-1; export USAGE X $ unix_test X unix_test: Name required X X X [ changed to use the environment variable USAGECNTL instead of USAGE. X "USAGE" is a variable name commonly used in shell scripts. --BDA ] X X [ when keywords are desired (via USAGECNTL) their actual command-line X syntax is now displayed (instead of just appearing in parentheses) X -- BDA ] X X ______________________________________________________________________________ X X X Update to parseargs (and major re-write) by Brad Appleton X (brad@travis.ssd.csd.harris.com) X Last Update: 03/01/91 X X DISCLAIMER X ========== X Neither Brad Appleton, nor Harris Corporation (including any of its X subsidiaries and subdivisions and Harris Computer Systems Division in X particular) are responsible for maintaining and supporting this X software or for any consequences resulting from the use of this X software, no matter how awful, even if they arise from flaws in the X software. X X X NEW FILES: parseargs.c, xparse.c, pgopen.[ch], vprintf.c X ======================================================== X I thought parseargs was so cool that I wanted to be able to use it for X shell-scripts too! To do that I would need a command-line interface. X I decided to make the command-line interface look as close as possible X to the C-interface so I basically implemented a very small X interpreter; Hence, parseargs.c was resurrected but this time as an X interface to the parseargs library instead of being the guts of it. X X Xparse.c implements routines to parse arguments from a file X (fparseargs), from an arglist (lparseargs), from a string X (sparseargs), from a variable argument-list (vparseargs), and from a X string-vector (parseargs). It also contains the routine parsecntl() X which controls the parsing behavior of a commands, and the routine X usage() which prints a usage message. Each of the <os>_args.c files X used to implement its own parseargs() and usage() functions, this has X been changed so that parseargs() and usage() are implemented in X xparse.c and the guts of the os-specific parsing and formatting is X implemented in the routines <os>_parse() and <os>_usage() in the file X <os>_args.c! X X On Unix systems, if the user desires, usage messages are paged using X popen(3S). The pager used is ${USAGE_PAGER:-${PAGER:-/usr/ucb/more}}. X If for some reason this fails then no paging is performed. The pager X library is implemented in the file pgopen.c and only used if the macro X USE_PAGER is #defined. Pgopen.h is an include file which will include X the external declarations for pgopen.c if USE_PAGER is #defined and X defines some functionally equivalent (but non-paging) macros instead. X X The file vprintf.c is a portable implementation of vprintf(), X vfprintf(), and vsprintf() for systems (such as BSD Unix) that don't X already have them. X X X NEW ARGUMENT TYPES: argUsage, arg[UTS]Bool, & argDummy X ====================================================== X I added the following argument types to parseargs: X X argUsage -- print a usage message X argDummy -- dummy argument, not parsed but used for messages X argSBool -- set a boolean flag X argTBool -- toggle a boolean flag X argUBool -- unset a boolean flag X X Consult the manual page for argtype(3) for more information. X I also added the capability to handle ARGVEC arguments into the X remaining argument type functions. X X NEW ARGUMENT FLAGS: X =================== X I added the following argument flags to parseargs: X X ARGPOS -- arg is positionally matched and keyword matched X ARGNOVAL -- arg takes no value X ARGVALOPT -- arg takes an optional value X ARGVALREQ -- arg requires a value X ARGGIVEN -- arg was supplied on command-line X ARGVALGIVEN -- arg-value was supplied on command-line X ARGDESCRIBED -- argument was given a description X ARGKEYWORD -- argument was matched as a keyword X ARGVALSEP -- arg-value was in a separate token from the argument X X Consult the manual page for parseargs(1) & parseargs(3) for more information. X X NEW INTERFACE X ============= X I added a set of Macros to allow a more "self documenting" approach to X declaring argument-descriptor arrays. The "old-style" is still X accepted (but if used it is recommended that the STARTOFARGS macro is X used in conjunction with ENDOFARGS). The new style is documented in the X parseargs(3) manual under the heading "CMD MACROS" X X X MODIFICATIONS TO USAGE MESSAGES X =============================== X After Peter modified usage() to look at the USAGE environment X variable, I decided that, even if the user had turned USAGE off, that X (s)he really did want the usage if an argUsage option was specified so X I added a static global Usage_Requested to xparse.c to over-ride X the USAGE variable (if necessary) so that a verbose message is always X given when an argUsage option is specified (regardless of the value in X the environment variable). X X I also changed the name of the environment variable that gets "looked" X up to be USAGECNTL instead of USAGE since USAGE is a common variable X name for shell scripts. Furthermore, I changed the contents of USAGECNTL X from a number to a sequence of mnemonic strings (for better readability). X I also made USAGECNTL control whether or not a command-description is X printed and whther or not the message is piped to a pager on Unix. X X Under VMS, the global symbol USAGECNTL is used in lieu of an environment X variable. See the parseargs(3) and parseargs(1) manual pages for more X information regarding USAGECNTL. X X SPECIFYING ALTERNATE PARSING BEHAVIOR X ===================================== X Parseargs provides 3 methods for controlling "how" the command-line is X parsed. There is a parsecntl() function which may be used to specify X flags other than the default parse-behavior. The user may define the X environment variable (or global symbol) PARSECNTL to contain the option- X string that corresponds to the desired combination of pa_XXXX flags X #defined in parseargs.h. The parseargs command, also allows for options X to specify certain parsing behavior. The parsecntl() function provides X finer control than either of the other two methods. The user's PARSECNTL X variable will always over-ride any conflicting flags that were set by X parsecntl() or by the parseargs command via command-line options. X See the manual pages for parseargs(1), parseargs(3), and parsecntl(3) X for more information. X X GIVING DEFAULT ARGUMENTS X ======================== X Programs that use parseargs may be given default arguments under UNIX X and PCs through the use of environment variables (symbols are used for X VMS systems). If a C-program or a shell-script uses parseargs to imple- X ment a command named "foo" then the environment variable (or global X synbol) FOO_ARGS will be parsed for any "default" arguments before argv X is parsed. Argv will over-ride any options that are specified in X FOO_ARGS (except that ARGLISTs and ARGVECs set in FOO_ARGS will be X appended from argv[]). X X X SPECIFYING DEFAULT ARGDESCs TO SEARCH X ===================================== X If a given option/qualifier does not appear to match any items in the X argdesc-array, a default argdesc-array is then searched to match the X option. If it is STILL unmatched then it is flagged as such. The X default-argdesc array is automatically used by all programmer-defined X argdesc-array but may be unset or reset using the pc_DEFARGS function X of parsecntl(3). X X X ADDING NEW SHELLS TO parseargs(1) X ================================= X I did my best to implement parseargs.c in a manner that would make it X relatively easy to add new shell-types. At this point in time, parseargs X will generate output for the following command-interpreters: X X sh (Bourne Shell) X csh/tcsh (C-Shell) X bash (Bourne-Again Shell) X ksh (Korn Shell) X rc (Plan 9 Shell) X perl X awk X X Parseargs.c thinks the Free Software Foundation's Bourne-Again Shell X (bash) is equivalent to the Bourne shell (sh). Bash is a superset of X sh (so I am told) but I do not know enough about it to treat it X differently. I hope someone who is familiar with bash syntax will X correct this deficiency (particularly with shell arrays). X X If someone wants to try to add more shell-types to parseargs.c, here X are the main things that need to be done: X X 1. add #defines for both the name (a string) and type (an integer) of X shell (e.g #define BOURNE_SHELL "sh" and #define SH 4) X X 2. add a shell_info entry into the array Shell[]. The index of the X entry in the array should be the number used in the #define for the X type of shell. X X 3. make sure that get_shell_type() will return the proper value for X the new shell. X X 4. print_args doesnt really do any shell specific stuff outside of X indexing into the table. The print_arglist() and X unset_positional_parameters() functions do some shell specific stuff X and will need a case added to the switch statement(s) for the newly X added shell. X X 5. If the information in the shell-info structure is not sufficient X for the new shell then you should either: X a) redefine the structure for all shells including your shell. X b) add some special code into print_args() for your shell! X X For a more thorough discussion of parseargs(1), consult the manual pages! X X X MODIFICATIONS TO KEYWORD MATCHING X ================================= X I changed keyword matching in strfuncs.c just a tad by allowing only a X partial match on the keyword (instead of a full match), this way the X user only needs to give enough of the keyword on the command line so X that it will uniquely match a suffix of a keyword in the arg- X descriptor table. A drawback to this is that if the user does NOT X specify enough of the keyword to uniquely match ONE arg-desc entry, X then the first such entry encountered will be considered to match the X partial keyword on the command-line. X X This "shortest-prefix" matching is performed 1st on only the uppercase X characters in the ad_prompt, and then (if no match) on the whole X prompt. This is "nice" in that the user only needs to specify the X shortest prefix but it also means that a typo can very easily be X interpreted as an option when it shouldnt be (both "+new" and "+gr" X would match "newsGROUPS") or the wrong option may be matched if too X small a portion of the keyword is provided. X X To help prevent this type of thing... Unless the keyword to be matched X has length < 2, I force the user to specify at least 2 characters for X the keyword (for VAX/VMS this minimum length becomes 4 iff the keyword X starts with "NO"). X X amiga_args.c still uses the old keyword matching function. Since X AmigaDOS keywords have no '/' or '-' prefix -- I thought it would be X too dangerous to allow such "partial matching" because it would be too X easy for bona-fide arguments to partially match a keyword! X X X MODIFICATIONS TO CHARACTER ARGTYPES X =================================== X Under UNIX, an argChar option argument may now be provided on the X command-line immediately following the option-letter and the X characters following the character argument are still processed as X options. Hence, if '-c' is an argChar option and '-x', '-y', and '-z' X are boolean options, then we may specify the character '_' as an X argument to '-c' as well as specifying the '-x', '-y' and '-z' flags X in the following manner: X X -c_xyz X X Of course, the following will have the same effect: X X -c_ -xyz X X as will this: X X -c _ -xyz X X but the following is incorrect: X X -c _xyz X X In other words, only the character that immediately follows an argChar X option is considered to be an argument to the option and other option X characters may immediately precede the single-character argument. X X X MODIFICATIONS TO BOOLEAN ARGTYPES X ================================= X Boolean types may now take an argument if so desired. under VAX/VMS: X X "/FLAG" (1) X X will turn ON an an argBool or argSBool flag, will turn OFF an argUBool X flag, and will toggle an argTBool flag. However, the following: X X "/FLAG=ON" (2) X X will turn ON the flag regardless of whether it is argBool, argSBool, X argUBool, or argTBool (so long as it is one of them). Similarly, X X "/FLAG=OFF" (3) X X will always turn a boolean flag OFF! X X Similar syntax is used for AmigaDOS, the corresponding Amiga X specification for examples (1)-(3) above would be: X X FLAG (1) X FLAG=ON (2) X FLAG=OFF (3) X X For the Amiga, the boolean argument MUST be part of the same argv[] X element as the keyword itself ("FLAG ON" or "FLAG OFF" is not X acceptable). X X For Unix (and IBM-PCs), long option examples of (1)-(3) would be the X following: X X +flag (1) X +flag=on (2) X +flag=off (3) X X As with the Amiga, the boolean argument ("on" or "off") MUST be part X of the same argv[] element as the long-option itself. X X For single character options under Unix, the corresponding examples X for (1)-(3) are as follows: X X -f (1) X -f+ (2) X -f- (3) X X As with Unix, the boolean argument ("on" or "off") MUST be part of the X same argv[] element as the long-option itself. X X For single character options under MS-DOS and OS/2, the corresponding X examples for (1)-(3) are as follows: X X /f (1) X /f+ (2) X /f- (3) X X With single character options, any boolean argument must be a single X character and must be in the character immediately following the the X option character. If the character following the option character is X NOT one of '-', '+', '0', ment) then the default action will be taken X (set, clear or toggle depending upon the type of boolean flag) and the X character immediately following the boolean option is assumed to be X another option-specification (e.g. -fc4 and -f+c4 are both allowed X where 'f' is a boolean flag and 'c' is an integer (argInt) flag). X X With all supported operating systems, the following arguments may be X used as Boolean arguments (differences between uppercase/lowercase are X ignored): X X Arg Effect X ===== ==================== X ^ Toggles flag (single character options only) X ~ Toggles flag (single character options only) X 1 Sets flag X 0 Unsets flag X + Sets flag X - Unsets flag X T Sets flag X F Unsets flag X YES Sets flag X NO Unsets flag X ON Sets flag X OFF Unsets flag X TRUE Sets flag X FALSE Unsets flag X X With single character options under Unix and IBM-PCs, only '+', '-', X '0', '1', '^' and '~' may be used. X X X CHANGES TO ARGTYPE RETURN VALUES X ================================ X In order to allow only a single character to be consumed for arguments X to boolean and character options, I had to change the way return X values from an argtype function were handled. Previously, the argtype X function merely returned TRUE (1) upon success and FALSE (0) upon X failure. I changed this slightly. Now, an argument type function X returns: X X FALSE (0) if the argument was NOT successfully interpreted X X TRUE (1) if the argument was successfully interpreted and ALL X characters of the argument were used. X X -N (<0) if the argument was successfully interpreted AND only X the first N characters of the argument were used. X X At this time, only the Boolean and argChar argument type functions X return any value other than TRUE or FALSE. X X X NEW ARGUMENT LISTS X ================== X Arglists have been enhanced with a new type called arg-vectors (and X use the ARGVEC flag instead of the ARGLIST flag). Arg-vectors are a X structure containing an argv/argc pair. There are two macros in X parseargs.h which are used for arg-vectors. ARGVEC_T may be used to X declare a vector structure or a vector type; ARGVEC_EMPTY may be used X to initialize the structure. It is strongly recommended that ARGVEC_T X be used to declare vector types in a typedef statement (particularly X if one is using function prototypes) but for those who insist, it may X be used to directly declare a structure. An example of both uses (as X well as an example use of ArgLists) may be found in the documentation. X X X MISCELLANEOUS FIXES/ENHANCEMENTS X ================================ X unix_args.c did not consider '-' or '+' to be valid arguments unless X '--' had already been specified. This has been fixed. X X The compile-time interactive option seemed to have been removed from X parseargs so I put it back in and made it a run-time option (that is X selected using the pa_PROMPT function-code to parsecntl()). I also X made it prompt repeatedly for arglists (a blank line ends the list). X No characters are escaped or trimmed (such as whitespace, quotes, or X special characters) when a prompted argument is read from the user! X X amiga_args.c will now check to see if an argument matches a keyword X before assigning it as a keyword argument. If 'STRING' is an argStr X and 'REP' is an argInt then: "cmd STRING REP=4" will leave string X without a value and assign REP to be 4. Previously, this would have X resulted in assigning the value of optional keyword arguments. X X Arglists are no longer stored in LIFO order and then reversed at the X last minute, they are now always stored in FIFO order (the order given X on the command-line). X X I also provided extensive updating to the manual pages so that they X now reflect the current capabilities of parseargs! X X X MODIFICATIONS TO parseargs.h X ============================ X I hacked parseargs.h up a bit so that certain items may be excluded or X included by #defining certain names before including the file. X X If PARSEARGS_PRIVATE is #defined, then various type and macro X definitions which are specific to the implementation of parseargs (but X not to its use) are included. This is my hack at C++ friend functions; X A file declares itself to be a "friend" by #defining PARSEARGS_PRIVATE X before #including the file parseargs.h X X If PARSEARGS_NEXTERNS is #defined, then the external function declarations X for the various parseargs functions (parseargs, parsecntl, fparseargs, X etc ...) are NOT included. This is really only useful to the files that X actually implement the various parseargs functions. X X If PARSEARGS_NARGTYPES is #defined, then the external function X declarations for the various argtype functions (argInt, argStr, X listStr, etc ..) are NOT included. This is really only useful to the X files that actually implement the various argtype functions. X X Also, ARGDESC is now a typedef instead of a #define. On the same note, X arglists may be declared by using the "ArgList" typedef or by using X the "struct arglist" structure declaration. X X X MODIFICATIONS TO THE ARGDESC ARRAY X ================================== X Before I got my hands on it - parseargs had no parsecntl() or means of X parsing arguments from a file or a string. Any and all arguments to be X parsed would be handled in a single invocation of parseargs. In order X to allow arguments to be parsed using multiple passes (which would be X required if we were to parse arguments in a file for example) I added X the notion of parse-flags to modify parsing behavior. Because of this, X I also required certain local variables to now be static. In order to X allow parsing for multiple commands - I put the parse-flags and the X static variables into the argument descriptor array itself. This way - X each arg-descriptor has its own set of flags and state variables to X record its own context. X X To implement this without changing the existing syntax, I put all this X stuff into the FIRST & LAST argument descriptors in the array. If an X argdesc-array is declared using the CMD_XXXXX macros, then this is X already taken care of. If an argdesc array is used using the old-style X syntax, ENDOFARGS will now define two arg-descs at the end of the X array. Parseargs needs to recognize the old syntax and shift each X element in the array down by one position (creating room for a new one X at the top). I would have preferred to just swap the first and last X entries in this case but I have to preserve the original order of any X positionally-matched parameters! This means that extra pre-processing X (to shift the array) needs to be performed for argdesc-arrays that are X declared using the old syntax! To avoid this overhead - users of the X old syntax could use the pre#defined macro STARTOFARGS and make it the X first entry in the argdesc-array. X X Also, each arg-descriptor is now precompiled so that the argument X prompt and the argument description are stored in two separate strings X (the first of which is pointed to by the "ad_prompt" field). This X avoids the need to constantly write code to "locate" the description X every time it is desired by the programmer. X X In order to ease the use of the various attributes of arg-descriptors, X (including the argument-prompt and the argument description) a set of X macros is available for extracting the corresponding attributes of a X command, or one of its argument entries. Public macros are documented X in the manual pages, private ones are listed here: X X cmd_name(Args) -- the given command-name X cmd_flags(Args) -- the command parse flags X cmd_context(Args) -- pointer to the command-context X (which is stored in the last argument-descriptor) X cmd_state(Args) -- the command-state flags X cmd_list(Args) -- pointer to currently active arg-list X cmd_prev(Args) -- pointer to previously matched arg (Amiga only) X cmd_defargs(Args) -- pointer to default argdesc for this command X cmd_argv0(Args) -- pointer to argv[0] from command-line X cmd_purpose(Args) -- one-line description of command X cmd_description(Args) -- multi-line description of command SHAR_EOF true || echo 'restore of parseargs/README failed' fi echo 'End of part 1' echo 'File parseargs/README is continued in part 2' echo 2 > _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.