home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.sources.misc
- From: brad@hcx1.ssd.csd.harris.com (Brad Appleton)
- Subject: v36i092: options - C++ library for parsing Unix-style command-lines, Patch01
- Message-ID: <1993Apr4.172850.29092@sparky.imd.sterling.com>
- X-Md4-Signature: 4a13499239e54d0506cea4c47d1004b0
- Date: Sun, 4 Apr 1993 17:28:50 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: brad@hcx1.ssd.csd.harris.com (Brad Appleton)
- Posting-number: Volume 36, Issue 92
- Archive-name: options/patch01
- Environment: C++
- Patch-To: options: Volume 31, Issue 45-46
-
- This is patch01 for the Options C++ class library.
-
- To apply this patch:
-
- 1) cd to your "Options" source directory
- 2) Unshar this file by typing "sh name-of-this-file"
- (this will create the files MANIFEST and PATCH01)
- 3) type "patch -p0 <PATCH01"
-
- Changes made in this patch are as follows:
- - made changes to compile with g++
- - added an OptIstreamIter class to iterate over options from an input stream
-
- For those of you that are unfamiliar with the Options C++ class library,
- an excerpt from the README file follows:
-
-
- WHAT IS THIS?
- =============
- This is "Options", a C++ library for parsing Unix-style command-line options.
- Options understands options and gnu-long-options and the parsing behavior is
- somewhat configurable. See the documentation (or the file <options.h>) for a
- complete description.
-
- You "declare" your options by declaring an array of strings like so:
-
- const char * optv[] = {
- "c:count <number>",
- "s?str <string>",
- "x|xmode",
- NULL
- } ;
-
- Note the character (one of ':', '?', '|', '*', or '+') between the short
- and long name of the option. It specifies the option type:
-
- '|' -- indicates that the option takes NO argument;
- '?' -- indicates that the option takes an OPTIONAL argument;
- ':' -- indicates that the option takes a REQUIRED argument;
- '*' -- indicates that the option takes 0 or more arguments;
- '+' -- indicates that the option takes 1 or more arguments;
-
- Using the above example, optv[] now corresponds to the following:
-
- progname [-c <number>] [-s [<string>]] [-x]
-
- Using long-options, optv corresponds to the following ("-" or "+" may
- be used instead of "--" as the prefix):
-
- progname [--count <number>] [--str [<string>]] [--xmode]
-
- Now you can iterate over your options like so:
-
- #include <stdlib.h>
- #include <options.h>
-
- main(int argc, char *argv[]) {
- Options opts(*argv, optv);
- OptArgvIter iter(--argc, ++argv);
- const char *optarg, *str = NULL;
- int errors = 0, xflag = 0, count = 1;
-
- while( char optchar = opts(iter, optarg) ) {
- switch (optchar) {
- case 's' :
- str = optarg; break;
- case 'x' :
- ++xflag; break;
- case 'c' :
- if (optarg == NULL) ++errors;
- else count = (int) atol(optarg);
- break;
- default : ++errors; break;
- } //switch
- }
- ... // process the rest of the arguments in "iter"
- }
-
-
- ______________________ "And miles to go before I sleep." ______________________
- Brad Appleton Harris Corp., Computer Systems Division
- Senior Software Engineer 2101 West Cypress Creek Road, M/S 161
- brad@ssd.csd.harris.com Fort Lauderdale, FL 33309-1892 USA
- ...!uunet!travis!brad Phone: (305) 973-5190
- ~~~~~~~~~~~~~~~~~~~ Disclaimer: I said it, not my employer! ~~~~~~~~~~~~~~~~~~~
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of shell archive."
- # Contents: PATCH01 MANIFEST
- # Wrapped by brad@amber on Fri Mar 26 11:06:37 1993
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'PATCH01' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'PATCH01'\"
- else
- echo shar: Extracting \"'PATCH01'\" \(14884 characters\)
- sed "s/^X//" >'PATCH01' <<'END_OF_FILE'
- X*** Makefile.OLD Fri Mar 26 11:01:52 1993
- X--- Makefile Thu Mar 25 17:20:22 1993
- X***************
- X*** 66,72 ****
- X library: ${LIBRARY}
- X
- X ${LIBRARY}: ${OBJS}
- X! ar -r $@ ${OBJS}
- X ranlib $@
- X
- X test: testopts
- X--- 66,72 ----
- X library: ${LIBRARY}
- X
- X ${LIBRARY}: ${OBJS}
- X! ar r $@ ${OBJS}
- X ranlib $@
- X
- X test: testopts
- X***************
- X*** 84,90 ****
- X rm -f tags testopts ${LIBRARY}
- X
- X shar:
- X! shar README ${SRCS} ${DOCS} Makefile >SHAR
- X
- X ###
- X # object dependencies
- X--- 84,90 ----
- X rm -f tags testopts ${LIBRARY}
- X
- X shar:
- X! shar README MANIFEST ${SRCS} ${DOCS} Makefile >SHAR
- X
- X ###
- X # object dependencies
- X*** README.OLD Fri Mar 26 11:01:57 1993
- X--- README Thu Mar 25 17:31:12 1993
- X***************
- X*** 90,102 ****
- X
- X CONTENTS
- X ========
- X! This release should contain the following files:
- X! Makefile -- the makefile
- X! README -- this file
- X! options.3 -- Unix manual page(s) for the Options class
- X! options.h -- include file and documentation for the Options class
- X! options.C -- the C++ source for the Options class
- X! testopts.C -- a test program for the Options class
- X
- X
- X REQUIREMENTS
- X--- 90,97 ----
- X
- X CONTENTS
- X ========
- X! See the file "MANIFEST" in the distribution for a complete list and
- X! description of all the files included in this release.
- X
- X
- X REQUIREMENTS
- X***************
- X*** 140,151 ****
- X that I wrote for the FSF that was posted on one of the "gnu" newsgroups
- X (I think it was the group gnu.utils.bug) in February of 1992. Many thanks
- X to David J. MacKenzie for his input. Options provides may more features
- X! than "getopts" did.
- X
- X
- X PATCHLEVEL
- X ==========
- X! The is release 1 of Options at patchlevel 0.
- X
- X
- X HISTORY
- X--- 135,147 ----
- X that I wrote for the FSF that was posted on one of the "gnu" newsgroups
- X (I think it was the group gnu.utils.bug) in February of 1992. Many thanks
- X to David J. MacKenzie for his input. Options provides may more features
- X! than "getopts" did. If you want the original "getopts" package (which
- X! has since been vastly enhanced) then send me e-mail.
- X
- X
- X PATCHLEVEL
- X ==========
- X! The is release 1 of Options at patchlevel 1.
- X
- X
- X HISTORY
- X***************
- X*** 155,157 ****
- X--- 151,157 ----
- X -----------------------------------------------------------------------------
- X First release.
- X
- X+ 03/23/93 Brad Appleton <brad@ssd.csd.harris.com>
- X+ -----------------------------------------------------------------------------
- X+ - Made some changes for compiling with g++
- X+ - Added OptIstreamIter class
- X*** options.3.OLD Fri Mar 26 11:02:02 1993
- X--- options.3 Fri Mar 26 10:39:14 1993
- X***************
- X*** 118,123 ****
- X--- 118,173 ----
- X
- X
- X .vs -2
- X+ // OptIstreamIter is a class for iterating over arguments that come
- X+ // from an input stream. Each line of the input stream is considered
- X+ // to be a set of white-space separated tokens. If the the first
- X+ // non-white character on a line is '#' ('!' for VMS systems) then
- X+ // the line is considered a comment and is ignored.
- X+ //
- X+ // *Note:: If a line is more than 1022 characters in length then we
- X+ // treat it as if it were several lines of length 1022 or less.
- X+ //
- X+ // *Note:: The string tokens returned by this iterator are pointers
- X+ // to temporary buffers which may not necessarily stick around
- X+ // for too long after the call to curr() or operator(), hence
- X+ // if you need the string value to persist - you will need to
- X+ // make a copy.
- X+ //
- X+ .vs +2
- X+ class OptIstreamIter : public OptIter {
- X+ private:
- X+ istream & is ;
- X+ OptStrTokIter * tok_iter ;
- X+
- X+ void
- X+ fill(void);
- X+
- X+ public:
- X+ static const unsigned MAX_LINE_LEN ;
- X+
- X+ #ifdef vms
- X+ enum { c_COMMENT = '!' } ;
- X+ #else
- X+ enum { c_COMMENT = '#' } ;
- X+ #endif
- X+
- X+ OptIstreamIter(istream & input);
- X+
- X+ virtual
- X+ ~OptIstreamIter(void);
- X+
- X+ virtual const char *
- X+ curr(void);
- X+
- X+ virtual void
- X+ next(void);
- X+
- X+ virtual const char *
- X+ operator()(void);
- X+ } ;
- X+
- X+
- X+ .vs -2
- X // Class to hold option-specifications and parsing-specifications
- X //
- X .vs +2
- X*** options.C.OLD Fri Mar 26 11:02:07 1993
- X--- options.C Tue Mar 23 16:55:12 1993
- X***************
- X*** 3,8 ****
- X--- 3,11 ----
- X //
- X // ^HISTORY:
- X // 01/16/92 Brad Appleton <brad@ssd.csd.harris.com> Created
- X+ //
- X+ // 03/23/93 Brad Appleton <brad@ssd.csd.harris.com>
- X+ // - Added OptIstreamIter class
- X // ^^**************************************************************************
- X
- X #include <stdlib.h>
- X***************
- X*** 99,106 ****
- X--- 102,228 ----
- X cur = ::strtok(tokstr, seps);
- X }
- X
- X+ // ************************************************************* OptIstreamIter
- X+
- X+ const unsigned OptIstreamIter::MAX_LINE_LEN = 1024 ;
- X+
- X+ // Constructor
- X+ OptIstreamIter::OptIstreamIter(istream & input) : is(input), tok_iter(NULL)
- X+ {
- X+ }
- X+
- X+ // Destructor
- X+ OptIstreamIter::~OptIstreamIter(void)
- X+ {
- X+ delete tok_iter;
- X+ }
- X+
- X+ const char *
- X+ OptIstreamIter::curr(void) {
- X+ const char * result = NULL;
- X+ if (tok_iter) result = tok_iter->curr();
- X+ if (result) return result;
- X+ fill();
- X+ return (! is) ? NULL : tok_iter->curr();
- X+ }
- X+
- X+ void
- X+ OptIstreamIter::next(void) {
- X+ const char * result = NULL;
- X+ if (tok_iter) result = tok_iter->operator()();
- X+ if (result) return;
- X+ fill();
- X+ if (! is) tok_iter->next();
- X+ }
- X+
- X+ const char *
- X+ OptIstreamIter::operator()(void)
- X+ {
- X+ const char * result = NULL;
- X+ if (tok_iter) result = tok_iter->operator()();
- X+ if (result) return result;
- X+ fill();
- X+ return (! is) ? NULL : tok_iter->operator()();
- X+ }
- X+
- X+ // What we do is this: for each line of text in the istream, we use
- X+ // a OptStrTokIter to iterate over each token on the line.
- X+ //
- X+ // If the first non-white character on a line is c_COMMENT, then we
- X+ // consider the line to be a comment and we ignore it.
- X+ //
- X+ void
- X+ OptIstreamIter::fill(void) {
- X+ char buf[OptIstreamIter::MAX_LINE_LEN];
- X+ do {
- X+ *buf = '\0';
- X+ is.getline(buf, sizeof(buf));
- X+ char * ptr = buf;
- X+ while (isspace(*ptr)) ++ptr;
- X+ if (*ptr && (*ptr != OptIstreamIter::c_COMMENT)) {
- X+ delete tok_iter;
- X+ tok_iter = new OptStrTokIter(ptr);
- X+ return;
- X+ }
- X+ } while (is);
- X+ }
- X+
- X // ******************************************************************* Options
- X
- X+ // ---------------------------------------------------------------------------
- X+ // ^FUNCTION: verify - verify the syntax of each option-spec
- X+ //
- X+ // ^SYNOPSIS:
- X+ // static void verify(name, optv[])
- X+ //
- X+ // ^PARAMETERS:
- X+ // const char * name - name of this command
- X+ // const char * const optv[] - the vector of option-specs to inspect.
- X+ //
- X+ // ^DESCRIPTION:
- X+ // All we have to do is iterate through the option vector and make sure
- X+ // That each option-spec is of the proper format.
- X+ //
- X+ // ^REQUIREMENTS:
- X+ // - optv[] should be non-NULL and terminated by a NULL pointer.
- X+ //
- X+ // ^SIDE-EFFECTS:
- X+ // If an invalid option-spec is found, prints a message on cerr and
- X+ // exits with a status of 127.
- X+ //
- X+ // ^RETURN-VALUE:
- X+ // None.
- X+ //
- X+ // ^ALGORITHM:
- X+ // For each option-spec
- X+ // - ensure (length > 0)
- X+ // - verify the the second character is one of "|?:*+"
- X+ // end-for
- X+ // ^^-------------------------------------------------------------------------
- X+ static void
- X+ verify(const char * name, const char * const optv[])
- X+ {
- X+ int errors = 0;
- X+ if ((optv == NULL) || (! *optv)) return;
- X+
- X+ for (; *optv ; optv++) {
- X+ char *p;
- X+ if (! **optv) {
- X+ cerr << name << ": invalid option spec \"" << *optv << "\"." << endl ;
- X+ cerr << "\tmust be at least 1 character long." << endl ;
- X+ ++errors;
- X+ }
- X+ if ((**optv) && ((*optv)[1]) &&
- X+ ((p = strchr("|?:*+", (*optv)[1])) == NULL)) {
- X+ cerr << name << ": invalid option spec \"" << *optv << "\"." << endl ;
- X+ cerr << "\t2nd character must be in the set \"|?:*+\"." << endl ;
- X+ ++errors;
- X+ }
- X+ }/*for*/
- X+
- X+ if (errors) exit(127);
- X+ }
- X+
- X Options::Options(const char * name, const char * const optv[])
- X : cmdname(name), optvec(optv), explicit_end(0), optctrls(DEFAULT),
- X nextchar(NULL), listopt(NULL)
- X***************
- X*** 107,112 ****
- X--- 229,235 ----
- X {
- X const char * basename = ::strrchr(cmdname, '/');
- X if (basename) cmdname = basename + 1;
- X+ verify(name, optv);
- X }
- X
- X Options::~Options(void) {}
- X***************
- X*** 177,235 ****
- X }
- X
- X // ---------------------------------------------------------------------------
- X- // ^FUNCTION: verify - verify the syntax of each option-spec
- X- //
- X- // ^SYNOPSIS:
- X- // static void verify(optv[])
- X- //
- X- // ^PARAMETERS:
- X- // const char * const optv[] - the vector of option-specs to inspect.
- X- //
- X- // ^DESCRIPTION:
- X- // All we have to do is iterate through the option vector and make sure
- X- // That each option-spec is of the proper format.
- X- //
- X- // ^REQUIREMENTS:
- X- // - optv[] should be non-NULL and terminated by a NULL pointer.
- X- //
- X- // ^SIDE-EFFECTS:
- X- // If an invalid option-spec is found, prints a message on cerr and
- X- // exits with a status of 127.
- X- //
- X- // ^RETURN-VALUE:
- X- // None.
- X- //
- X- // ^ALGORITHM:
- X- // For each option-spec
- X- // - ensure (length > 0)
- X- // - verify the the second character is one of "|?:*+"
- X- // end-for
- X- // ^^-------------------------------------------------------------------------
- X- static void
- X- verify(const char * const optv[])
- X- {
- X- int errors = 0;
- X- if ((optv == NULL) || (! *optv)) return;
- X-
- X- for (; *optv ; optv++) {
- X- char *p;
- X- if (! **optv) {
- X- cerr << "invalid option spec \"" << *optv << "\"." << endl ;
- X- cerr << "\tmust be at least 1 character long." << endl ;
- X- ++errors;
- X- }
- X- if ((**optv) && ((*optv)[1]) &&
- X- ((p = strchr("|?:*+", (*optv)[1])) == NULL)) {
- X- cerr << "invalid option spec \"" << *optv << "\"." << endl ;
- X- cerr << "\t2nd character must be in the set \"|?:*+\"." << endl ;
- X- ++errors;
- X- }
- X- }/*for*/
- X-
- X- if (errors) exit(127);
- X- }
- X-
- X- // ---------------------------------------------------------------------------
- X // ^FUNCTION: kwdmatch - match a keyword
- X //
- X // ^SYNOPSIS:
- X--- 300,305 ----
- X***************
- X*** 260,266 ****
- X static kwdmatch_t
- X kwdmatch(const char * src, const char * attempt, int len =0)
- X {
- X! unsigned i;
- X
- X if (src == attempt) return EXACT_MATCH ;
- X if ((src == NULL) || (attempt == NULL)) return NO_MATCH ;
- X--- 330,336 ----
- X static kwdmatch_t
- X kwdmatch(const char * src, const char * attempt, int len =0)
- X {
- X! int i;
- X
- X if (src == attempt) return EXACT_MATCH ;
- X if ((src == NULL) || (attempt == NULL)) return NO_MATCH ;
- X***************
- X*** 429,435 ****
- X {
- X listopt = NULL; // reset the list pointer
- X
- X! if ((optvec == NULL) || (! *optvec)) return NULL;
- X
- X // Try to match a known option
- X const char * optspec = match_opt(optvec, *(nextchar++));
- X--- 499,505 ----
- X {
- X listopt = NULL; // reset the list pointer
- X
- X! if ((optvec == NULL) || (! *optvec)) return Options::ENDOPTS;
- X
- X // Try to match a known option
- X const char * optspec = match_opt(optvec, *(nextchar++));
- X***************
- X*** 529,535 ****
- X
- X listopt = NULL ; // reset the list-spec
- X
- X! if ((optvec == NULL) || (! *optvec)) return NULL;
- X
- X // if a value is supplied in this argv element, get it now
- X const char * val = strpbrk(nextchar, ":=") ;
- X--- 599,605 ----
- X
- X listopt = NULL ; // reset the list-spec
- X
- X! if ((optvec == NULL) || (! *optvec)) return Options::ENDOPTS;
- X
- X // if a value is supplied in this argv element, get it now
- X const char * val = strpbrk(nextchar, ":=") ;
- X***************
- X*** 748,754 ****
- X void
- X Options::usage(ostream & os, const char * positionals) const
- X {
- X! const char ** optv = optvec;
- X unsigned cols = 79;
- X int first, nloop;
- X char buf[256] ;
- X--- 818,824 ----
- X void
- X Options::usage(ostream & os, const char * positionals) const
- X {
- X! const char * const * optv = optvec;
- X unsigned cols = 79;
- X int first, nloop;
- X char buf[256] ;
- X*** options.h.OLD Fri Mar 26 11:02:13 1993
- X--- options.h Tue Mar 23 16:58:19 1993
- X***************
- X*** 8,13 ****
- X--- 8,16 ----
- X //
- X // ^HISTORY:
- X // 03/06/92 Brad Appleton <brad@ssd.csd.harris.com> Created
- X+ //
- X+ // 03/23/93 Brad Appleton <brad@ssd.csd.harris.com>
- X+ // - Added OptIstreamIter class
- X // ^^**************************************************************************
- X
- X #ifndef _options_h
- X***************
- X*** 14,19 ****
- X--- 17,23 ----
- X #define _options_h
- X
- X class ostream;
- X+ class istream;
- X
- X // Abstract class to iterate through options/arguments
- X //
- X***************
- X*** 136,141 ****
- X--- 140,193 ----
- X delimiters(const char * delims) {
- X seps = (delims) ? delims : default_delims ;
- X }
- X+ } ;
- X+
- X+
- X+ // OptIstreamIter is a class for iterating over arguments that come
- X+ // from an input stream. Each line of the input stream is considered
- X+ // to be a set of white-space separated tokens. If the the first
- X+ // non-white character on a line is '#' ('!' for VMS systems) then
- X+ // the line is considered a comment and is ignored.
- X+ //
- X+ // *Note:: If a line is more than 1022 characters in length then we
- X+ // treat it as if it were several lines of length 1022 or less.
- X+ //
- X+ // *Note:: The string tokens returned by this iterator are pointers
- X+ // to temporary buffers which may not necessarily stick around
- X+ // for too long after the call to curr() or operator(), hence
- X+ // if you need the string value to persist - you will need to
- X+ // make a copy.
- X+ //
- X+ class OptIstreamIter : public OptIter {
- X+ private:
- X+ istream & is ;
- X+ OptStrTokIter * tok_iter ;
- X+
- X+ void
- X+ fill(void);
- X+
- X+ public:
- X+ static const unsigned MAX_LINE_LEN ;
- X+
- X+ #ifdef vms
- X+ enum { c_COMMENT = '!' } ;
- X+ #else
- X+ enum { c_COMMENT = '#' } ;
- X+ #endif
- X+
- X+ OptIstreamIter(istream & input);
- X+
- X+ virtual
- X+ ~OptIstreamIter(void);
- X+
- X+ virtual const char *
- X+ curr(void);
- X+
- X+ virtual void
- X+ next(void);
- X+
- X+ virtual const char *
- X+ operator()(void);
- X } ;
- X
- X
- X*** testopts.C.OLD Fri Mar 26 11:02:17 1993
- X--- testopts.C Fri Nov 13 07:27:28 1992
- X***************
- X*** 10,16 ****
- X long atol(const char *);
- X }
- X
- X! static const char *optv[] = {
- X "?|?",
- X "H|help",
- X "f?flags",
- X--- 10,16 ----
- X long atol(const char *);
- X }
- X
- X! static const char * const optv[] = {
- X "?|?",
- X "H|help",
- X "f?flags",
- END_OF_FILE
- if test 14884 -ne `wc -c <'PATCH01'`; then
- echo shar: \"'PATCH01'\" unpacked with wrong size!
- fi
- # end of 'PATCH01'
- fi
- if test -f 'MANIFEST' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'MANIFEST'\"
- else
- echo shar: Extracting \"'MANIFEST'\" \(524 characters\)
- sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
- X File Name Archive # Description
- X-----------------------------------------------------------
- X MANIFEST 1 this shipping list
- X Makefile 1 make file for the product
- X README 1 read this file first
- X options.3 1 man page for the Options(3C++) library
- X options.C 2 implementation of the Options(3C++) library
- X options.h 1 definition of the Options(3C++) library
- X testopts.C 1 test program for the library
- END_OF_FILE
- if test 524 -ne `wc -c <'MANIFEST'`; then
- echo shar: \"'MANIFEST'\" unpacked with wrong size!
- fi
- # end of 'MANIFEST'
- fi
- echo shar: End of shell archive.
- exit 0
-
- exit 0 # Just in case...
-