home *** CD-ROM | disk | FTP | other *** search
- From: brad@amber.ssd.csd.harris.com (Brad Appleton)
- Newsgroups: comp.sources.misc
- Subject: v41i160: options - C++ library for parsing Unix-style command-lines, Patch03
- Date: 6 Mar 1994 22:50:03 -0600
- Organization: Harris Computer Systems
- Sender: root@sparky.sterling.com
- Approved: kent@sparky.sterling.com
- Message-ID: <2lebpr$h5g@sparky.sterling.com>
- Reply-To: brad@travis.csd.harris.com
- X-Md4-Signature: 3902fa663d240ab2147df673807b5601
-
- Submitted-by: brad@amber.ssd.csd.harris.com (Brad Appleton)
- Posting-number: Volume 41, Issue 160
- Archive-name: options/patch03
- Environment: C++
- Patch-To: options: Volume 31, Issue 45-46
-
- This is patch-level 3 of "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.
-
- To apply this patch:
- --------------------
- 0) save this article to a file in your "Options" source directory
-
- 1) "cd" to your Options source directory
-
- 2) Remove all lines in the sharfile (the file you saved in #0)
- that precede the line that starts with "#! /bin/sh".
-
- 3) Run the command "sh sharfile" (or whatever you named your sharfile).
- This will create a file named "PATCH03" in your current directory
-
- 4) Run "patch -p0 < PATCH03"
-
-
- Changes in this release:
- ------------------------
- - Added OptionSpec class to options.C
- - Permitted use of stdio instead of iostreams via #ifdef USE_STDIO
-
- For those of you who are unfamiliar with "Options", the following
- is an excerpt from the README file. You can send e-mail to me at
- brad@ssd.csd.harris.com if you want the complete C++ source.
-
- ------------------------------------------------------------------------------
-
- 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"
- }
-
- ------------------------------------------------------------------------------
- #! /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: PATCH03
- # Wrapped by brad@amber on Fri Feb 11 17:30:41 1994
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'PATCH03' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'PATCH03'\"
- else
- echo shar: Extracting \"'PATCH03'\" \(49743 characters\)
- sed "s/^X//" >'PATCH03' <<'END_OF_FILE'
- X*** README.OLD Fri Feb 11 17:30:08 1994
- X--- README Wed Feb 09 09:21:44 1994
- X***************
- X*** 158,160 ****
- X--- 158,165 ----
- X 10/08/93 Brad Appleton <brad@ssd.csd.harris.com>
- X -----------------------------------------------------------------------------
- X - Added "hidden" options
- X+
- X+ 02/08/94 Brad Appleton <brad@ssd.csd.harris.com>
- X+ -----------------------------------------------------------------------------
- X+ - Added OptionSpec class to options.C
- X+ - Permitted use of stdio instead of iostreams via #ifdef USE_STDIO
- X*** options.3.OLD Fri Feb 11 17:30:10 1994
- X--- options.3 Fri Feb 11 16:59:40 1994
- X***************
- X*** 145,156 ****
- 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--- 145,150 ----
- X*** options.C.OLD Fri Feb 11 17:30:13 1994
- X--- options.C Fri Feb 11 17:27:33 1994
- X***************
- X*** 9,18 ****
- X //
- X // 10/08/93 Brad Appleton <brad@ssd.csd.harris.com>
- X // - Added "hidden" options
- X // ^^**************************************************************************
- X
- X #include <stdlib.h>
- X- #include <iostream.h>
- X #include <ctype.h>
- X #include <string.h>
- X
- X--- 9,27 ----
- X //
- X // 10/08/93 Brad Appleton <brad@ssd.csd.harris.com>
- X // - Added "hidden" options
- X+ //
- X+ // 02/08/94 Brad Appleton <brad@ssd.csd.harris.com>
- X+ // - Added "OptionSpec" class
- X+ // - Permitted use of stdio instead of iostreams via #ifdef USE_STDIO
- X // ^^**************************************************************************
- X
- X+ #ifdef USE_STDIO
- X+ # include <stdio.h>
- X+ #else
- X+ # include <iostream.h>
- X+ #endif
- X+
- X #include <stdlib.h>
- X #include <ctype.h>
- X #include <string.h>
- X
- X***************
- X*** 22,28 ****
- X void exit(int);
- X }
- X
- X! static const char ident[] = "@(#)Options 1.02" ;
- X
- X // I need a portable version of "tolower" that does NOT modify
- X // non-uppercase characters.
- X--- 31,37 ----
- X void exit(int);
- X }
- X
- X! static const char ident[] = "@(#)Options 1.03" ;
- X
- X // I need a portable version of "tolower" that does NOT modify
- X // non-uppercase characters.
- X***************
- X*** 29,34 ****
- X--- 38,86 ----
- X //
- X #define TOLOWER(c) (isupper(c) ? tolower(c) : c)
- X
- X+ // ******************************************************** insertion operators
- X+
- X+ // If you are using <stdio.h> then you need this stuff!
- X+ // If you are using <iostream.h> then #ifdef this stuff out
- X+ //
- X+
- X+
- X+ #ifdef USE_STDIO
- X+
- X+ static const char endl = '\n' ;
- X+
- X+ class OutFILE {
- X+ public:
- X+ OutFILE(FILE * fileptr) : fp(fileptr) {}
- X+
- X+ OutFILE &
- X+ operator<<(char ch);
- X+
- X+ OutFILE &
- X+ operator<<(const char * str);
- X+
- X+ private:
- X+ FILE * fp;
- X+ } ;
- X+
- X+ OutFILE &
- X+ OutFILE::operator<<(char ch) {
- X+ fputc(ch, fp);
- X+ return *this;
- X+ }
- X+
- X+ OutFILE &
- X+ OutFILE::operator<<(const char * str) {
- X+ fputs(str, fp);
- X+ return *this;
- X+ }
- X+
- X+
- X+ static OutFILE cerr(stderr);
- X+ static OutFILE cout(stdout);
- X+
- X+ #endif /* USE_STDIO */
- X+
- X // ************************************************************** OptIter
- X
- X OptIter::~OptIter(void) {}
- X***************
- X*** 107,112 ****
- X--- 159,170 ----
- X
- X // ************************************************************* OptIstreamIter
- X
- X+ #ifdef vms
- X+ enum { c_COMMENT = '!' } ;
- X+ #else
- X+ enum { c_COMMENT = '#' } ;
- X+ #endif
- X+
- X const unsigned OptIstreamIter::MAX_LINE_LEN = 1024 ;
- X
- X // Constructor
- X***************
- X*** 115,122 ****
- X }
- X
- X // Destructor
- X! OptIstreamIter::~OptIstreamIter(void)
- X! {
- X delete tok_iter;
- X }
- X
- X--- 173,179 ----
- X }
- X
- X // Destructor
- X! OptIstreamIter::~OptIstreamIter(void) {
- X delete tok_iter;
- X }
- X
- X***************
- X*** 139,146 ****
- 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--- 196,202 ----
- X }
- X
- X const char *
- X! OptIstreamIter::operator()(void) {
- X const char * result = NULL;
- X if (tok_iter) result = tok_iter->operator()();
- X if (result) return result;
- X***************
- X*** 162,168 ****
- 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--- 218,224 ----
- X is.getline(buf, sizeof(buf));
- X char * ptr = buf;
- X while (isspace(*ptr)) ++ptr;
- X! if (*ptr && (*ptr != c_COMMENT)) {
- X delete tok_iter;
- X tok_iter = new OptStrTokIter(ptr);
- X return;
- X***************
- X*** 170,372 ****
- X } while (is);
- X }
- X
- X! // ******************************************************************* Options
- X
- X! // See if an opt-spec is a Hidden option
- X inline static int
- X! isHiddenOpt(const char * optspec) { return (*optspec == '-'); }
- 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! const char * cp = *optv;
- X! while (cp = *(optv++)) {
- X! if (isHiddenOpt(cp)) ++cp;
- X! if (! *cp) {
- X! cerr << name << ": invalid option spec \"" << cp << "\"." << endl ;
- X! cerr << "\tmust be at least 1 character long." << endl ;
- X! ++errors;
- X! } else if (cp[1] && (strchr("|?:*+", cp[1]) == NULL)) {
- X! cerr << name << ": invalid option spec \"" << cp << "\"." << endl ;
- X! cerr << "\t2nd character must be in the set \"|?:*+\"." << endl ;
- X! ++errors;
- X! }
- X! }/*while*/
- 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! const char * basename = ::strrchr(cmdname, '/');
- X! if (basename) cmdname = basename + 1;
- X! verify(name, optv);
- X }
- X
- X! Options::~Options(void) {}
- X
- X! // return values for a keyword matching function
- X! enum kwdmatch_t { NO_MATCH, PARTIAL_MATCH, EXACT_MATCH } ;
- X
- X! // Get the option-char of an option-spec.
- X! inline static char
- X! OptChar(const char * optspec) { return *optspec; }
- X
- X! // Get the long-option of an option-spec.
- X! inline static const char *
- X! LongOpt(const char * optspec) {
- X! return ((optspec)[1] && (optspec)[2] &&
- X! (! isspace((optspec)[2]))) ? ((optspec) + 2) : NULL ;
- X! }
- X
- X! // Is the option-char null?
- X! inline static int
- X! isNullOpt(char optchar) {
- X! return ((! optchar) || isspace(optchar) || (! isprint(optchar))) ;
- X! }
- X
- X! // Does this option require an argument?
- X! inline static int
- X! isRequired(const char * optspec) {
- X! return (((optspec)[1] == ':') || ((optspec)[1] == '+')) ;
- X! }
- X
- X! // Does this option take an optional argument?
- X! inline static int
- X! isOptional(const char * optspec) {
- X! return (((optspec)[1] == '?') || ((optspec)[1] == '*')) ;
- X! }
- X
- X! // Does this option take no arguments?
- X! inline static int
- X! isNoArg(const char * optspec) {
- X! return (((optspec)[1] == '|') || (! (optspec)[1])) ;
- X! }
- X
- X! // Can this option take more than one argument?
- X! inline static int
- X! isList(const char * optspec) {
- X! return (((optspec)[1] == '+') || ((optspec)[1] == '*')) ;
- X! }
- X
- X! // Does this option take any arguments?
- X! inline static int
- X! isValTaken(const char * optspec) {
- X! return (isRequired(optspec) || isOptional(optspec)) ;
- X! }
- X
- X! // Check for explicit "end-of-options"
- X! inline static int
- X! isEndOpts(const char * token)
- X! {
- X! return ((token == NULL) || (! strcmp(token, "--"))) ;
- X! }
- X
- X! // See if an argument is an option
- X! inline static int
- X! isOption(unsigned flags, const char * arg)
- X! {
- X! return (((*arg != '\0') || (arg[1] != '\0')) &&
- X! ((*arg == '-') || ((flags & Options::PLUS) && (*arg == '+')))) ;
- X }
- X
- X // ---------------------------------------------------------------------------
- X! // ^FUNCTION: kwdmatch - match a keyword
- X //
- X // ^SYNOPSIS:
- X! // static kwdmatch_t kwdmatch(src, attempt, len)
- X //
- X // ^PARAMETERS:
- X! // char * src -- the actual keyword to match
- X! // char * attempt -- the possible keyword to compare against "src"
- X! // int len -- number of character of "attempt" to consider
- X! // (if 0 then we should use all of "attempt")
- X //
- X // ^DESCRIPTION:
- X! // See if "attempt" matches some prefix of "src" (case insensitive).
- X //
- X // ^REQUIREMENTS:
- X! // - attempt should be non-NULL and non-empty
- X //
- X // ^SIDE-EFFECTS:
- X! // None.
- X //
- X // ^RETURN-VALUE:
- X! // An enumeration value of type kwdmatch_t corresponding to whether
- X! // We had an exact match, a partial match, or no match.
- X //
- X // ^ALGORITHM:
- X! // Trivial
- X // ^^-------------------------------------------------------------------------
- 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! if ((! *src) && (! *attempt)) return EXACT_MATCH ;
- X! if ((! *src) || (! *attempt)) return NO_MATCH ;
- X
- X! for (i = 0 ; ((i < len) || (len == 0)) &&
- X! (attempt[i]) && (attempt[i] != ' ') ; i++) {
- X! if (TOLOWER(src[i]) != TOLOWER(attempt[i])) return NO_MATCH ;
- X }
- X
- X! return (src[i]) ? PARTIAL_MATCH : EXACT_MATCH ;
- X }
- X
- X // ---------------------------------------------------------------------------
- X! // ^FUNCTION: match_opt - match an option
- X //
- X // ^SYNOPSIS:
- X! // static const char * match_opt(optv, opt)
- X //
- X // ^PARAMETERS:
- X- // char * optv[] -- vector of option-specifications
- X // char opt -- the option-character to match
- X // int ignore_case -- should we ignore character-case?
- X //
- X // ^DESCRIPTION:
- X! // See if "opt" is found in "optv"
- X //
- X // ^REQUIREMENTS:
- X! // - optv should be non-NULL and terminated by a NULL pointer.
- X //
- X // ^SIDE-EFFECTS:
- X // None.
- X--- 226,571 ----
- X } while (is);
- X }
- X
- X! // **************************************************** Options class utilities
- X
- X! // Is this option-char null?
- X inline static int
- X! isNullOpt(char optchar) {
- X! return ((! optchar) || isspace(optchar) || (! isprint(optchar)));
- X! }
- X!
- X! // Check for explicit "end-of-options"
- X! inline static int
- X! isEndOpts(const char * token) {
- X! return ((token == NULL) || (! ::strcmp(token, "--"))) ;
- X! }
- X
- X+ // See if an argument is an option
- X+ inline static int
- X+ isOption(unsigned flags, const char * arg) {
- X+ return (((*arg != '\0') || (arg[1] != '\0')) &&
- X+ ((*arg == '-') || ((flags & Options::PLUS) && (*arg == '+')))) ;
- X+ }
- X+
- X+ // return values for a keyword matching function
- X+ enum kwdmatch_t { NO_MATCH, PARTIAL_MATCH, EXACT_MATCH } ;
- X+
- X // ---------------------------------------------------------------------------
- X! // ^FUNCTION: kwdmatch - match a keyword
- X //
- X // ^SYNOPSIS:
- X! // static kwdmatch_t kwdmatch(src, attempt, len)
- X //
- X // ^PARAMETERS:
- X! // char * src -- the actual keyword to match
- X! // char * attempt -- the possible keyword to compare against "src"
- X! // int len -- number of character of "attempt" to consider
- X! // (if 0 then we should use all of "attempt")
- X //
- X // ^DESCRIPTION:
- X! // See if "attempt" matches some prefix of "src" (case insensitive).
- X //
- X // ^REQUIREMENTS:
- X! // - attempt should be non-NULL and non-empty
- X //
- X // ^SIDE-EFFECTS:
- X! // None.
- X //
- X // ^RETURN-VALUE:
- X! // An enumeration value of type kwdmatch_t corresponding to whether
- X! // We had an exact match, a partial match, or no match.
- X //
- X // ^ALGORITHM:
- X! // Trivial
- X // ^^-------------------------------------------------------------------------
- X! static kwdmatch_t
- X! kwdmatch(const char * src, const char * attempt, int len =0) {
- X! int i;
- X
- X! if (src == attempt) return EXACT_MATCH ;
- X! if ((src == NULL) || (attempt == NULL)) return NO_MATCH ;
- X! if ((! *src) && (! *attempt)) return EXACT_MATCH ;
- X! if ((! *src) || (! *attempt)) return NO_MATCH ;
- X
- X! for (i = 0 ; ((i < len) || (len == 0)) &&
- X! (attempt[i]) && (attempt[i] != ' ') ; i++) {
- X! if (TOLOWER(src[i]) != TOLOWER(attempt[i])) return NO_MATCH ;
- X! }
- X
- X! return (src[i]) ? PARTIAL_MATCH : EXACT_MATCH ;
- X }
- X
- X! // **************************************************************** OptionSpec
- X
- X! // Class that represents an option-specification
- X! // *NOTE*:: Assumes that the char-ptr given to the constructor points
- X! // to storage that will NOT be modified and whose lifetime will
- X! // be as least as long as the OptionSpec object we construct.
- X! //
- X! class OptionSpec {
- X! public:
- X! OptionSpec(const char * decl =NULL)
- X! : hidden(0), spec(decl) { CheckHidden(); }
- X
- X! OptionSpec(const OptionSpec & cp) : hidden(cp.hidden), spec(cp.spec) {}
- X
- X! // NOTE: use default destructor!
- X
- X! // Assign to another OptionSpec
- X! OptionSpec &
- X! operator=(const OptionSpec & cp) {
- X! if (this != &cp) {
- X! spec = cp.spec;
- X! hidden = cp.hidden;
- X! }
- X! return *this;
- X! }
- X
- X! // Assign to a string
- X! OptionSpec &
- X! operator=(const char * decl) {
- X! if (spec != decl) {
- X! spec = decl;
- X! hidden = 0;
- X! CheckHidden();
- X! }
- X! return *this;
- X! }
- X
- X! // Convert to char-ptr by returning the original declaration-string
- X! operator const char*() { return isHiddenOpt() ? (spec - 1) : spec; }
- X
- X! // Is this option NULL?
- X! int
- X! isNULL(void) const { return (spec == NULL); }
- X
- X! // Is this options incorrectly specified?
- X! int
- X! isSyntaxError(const char * name) const;
- X
- X! // See if this is a Hidden option
- X! int
- X! isHiddenOpt(void) const { return hidden; }
- X
- X! // Get the corresponding option-character
- X! char
- X! OptChar(void) const { return *spec; }
- X
- X! // Get the corresponding long-option string
- X! const char *
- X! LongOpt(void) const {
- X! return (spec[1] && spec[2] && (! isspace(spec[2]))) ? (spec + 2) : NULL;
- X! }
- X!
- X! // Does this option require an argument?
- X! int
- X! isValRequired(void) const {
- X! return ((spec[1] == ':') || (spec[1] == '+'));
- X! }
- X!
- X! // Does this option take an optional argument?
- X! int
- X! isValOptional(void) const {
- X! return ((spec[1] == '?') || (spec[1] == '*'));
- X! }
- X!
- X! // Does this option take no arguments?
- X! int
- X! isNoArg(void) const {
- X! return ((spec[1] == '|') || (! spec[1]));
- X! }
- X!
- X! // Can this option take more than one argument?
- X! int
- X! isList(void) const {
- X! return ((spec[1] == '+') || (spec[1] == '*'));
- X! }
- X!
- X! // Does this option take any arguments?
- X! int
- X! isValTaken(void) const {
- X! return (isValRequired() || isValOptional()) ;
- X! }
- X!
- X! // Format this option in the given buffer
- X! unsigned
- X! Format(char * buf, unsigned optctrls) const;
- X!
- X! private:
- X! void
- X! CheckHidden(void) {
- X! if ((! hidden) && (*spec == '-')) {
- X! ++hidden;
- X! ++spec;
- X! }
- X! }
- X!
- X! unsigned hidden : 1; // hidden-flag
- X! const char * spec; // string specification
- X! } ;
- X!
- X! int
- X! OptionSpec::isSyntaxError(const char * name) const {
- X! int error = 0;
- X! if ((! spec) || (! *spec)) {
- X! cerr << name << ": empty option specifier." << endl;
- X! cerr << "\tmust be at least 1 character long." << endl;
- X! ++error;
- X! } else if (spec[1] && (strchr("|?:*+", spec[1]) == NULL)) {
- X! cerr << name << ": bad option specifier \"" << spec << "\"." << endl;
- X! cerr << "\t2nd character must be in the set \"|?:*+\"." << endl;
- X! ++error;
- X! }
- X! return error;
- X }
- X
- X // ---------------------------------------------------------------------------
- X! // ^FUNCTION: OptionSpec::Format - format an option-spec for a usage message
- X //
- X // ^SYNOPSIS:
- X! // unsigned OptionSpec::Format(buf, optctrls) const
- X //
- X // ^PARAMETERS:
- X! // char * buf -- where to print the formatted option
- X! // unsigned optctrls -- option-parsing configuration flags
- X //
- X // ^DESCRIPTION:
- X! // Self-explanatory.
- X //
- X // ^REQUIREMENTS:
- X! // - buf must be large enough to hold the result
- X //
- X // ^SIDE-EFFECTS:
- X! // - writes to buf.
- X //
- X // ^RETURN-VALUE:
- X! // Number of characters written to buf.
- X //
- X // ^ALGORITHM:
- X! // Follow along in the source - it's not hard but it is tedious!
- X // ^^-------------------------------------------------------------------------
- X! unsigned
- X! OptionSpec::Format(char * buf, unsigned optctrls) const {
- X! static char default_value[] = "<value>";
- X! if (isHiddenOpt()) return (unsigned)(*buf = '\0');
- X! char optchar = OptChar();
- X! const char * longopt = LongOpt();
- X! char * p = buf ;
- X
- X! const char * value = NULL;
- X! int longopt_len = 0;
- X! int value_len = 0;
- X
- X! if (longopt) {
- X! value = ::strchr(longopt, ' ');
- X! longopt_len = (value) ? (value - longopt) : ::strlen(longopt);
- X! } else {
- X! value = ::strchr(spec + 1, ' ');
- X }
- X+ while (value && (*value == ' ')) ++value;
- X+ if (value && *value) {
- X+ value_len = ::strlen(value);
- X+ } else {
- X+ value = default_value;
- X+ value_len = sizeof(default_value) - 1;
- X+ }
- X
- X! if ((optctrls & Options::SHORT_ONLY) &&
- X! ((! isNullOpt(optchar)) || (optctrls & Options::NOGUESSING))) {
- X! longopt = NULL;
- X! }
- X! if ((optctrls & Options::LONG_ONLY) &&
- X! (longopt || (optctrls & Options::NOGUESSING))) {
- X! optchar = '\0';
- X! }
- X! if (isNullOpt(optchar) && (longopt == NULL)) {
- X! *buf = '\0';
- X! return 0;
- X! }
- X!
- X! *(p++) = '[';
- X!
- X! // print the single character option
- X! if (! isNullOpt(optchar)) {
- X! *(p++) = '-';
- X! *(p++) = optchar;
- X! }
- X!
- X! if ((! isNullOpt(optchar)) && (longopt)) *(p++) = '|';
- X!
- X! // print the long option
- X! if (longopt) {
- X! *(p++) = '-';
- X! if (! (optctrls & (Options::LONG_ONLY | Options::SHORT_ONLY))) {
- X! *(p++) = '-';
- X! }
- X! strncpy(p, longopt, longopt_len);
- X! p += longopt_len;
- X! }
- X!
- X! // print any argument the option takes
- X! if (isValTaken()) {
- X! *(p++) = ' ' ;
- X! if (isValOptional()) *(p++) = '[' ;
- X! strcpy(p, value);
- X! p += value_len;
- X! if (isList()) {
- X! strcpy(p, " ...");
- X! p += 4;
- X! }
- X! if (isValOptional()) *(p++) = ']' ;
- X! }
- X!
- X! *(p++) = ']';
- X! *p = '\0';
- X!
- X! return (unsigned) strlen(buf);
- X }
- X
- X+ // ******************************************************************* Options
- 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+ const char * basename = ::strrchr(cmdname, '/');
- X+ if (basename) cmdname = basename + 1;
- X+ check_syntax();
- X+ }
- X+
- X+ Options::~Options(void) {}
- X+
- X+ // Make sure each option-specifier has correct syntax.
- X+ //
- X+ // If there is even one invalid specifier, then exit ungracefully!
- X+ //
- X+ void
- X+ Options::check_syntax(void) const {
- X+ int errors = 0;
- X+ if ((optvec == NULL) || (! *optvec)) return;
- X+
- X+ for (const char * const * optv = optvec ; *optv ; optv++) {
- X+ OptionSpec optspec = *optv;
- X+ errors += optspec.isSyntaxError(cmdname);
- X+ }
- X+ if (errors) exit(127);
- X+ }
- X+
- X // ---------------------------------------------------------------------------
- X! // ^FUNCTION: Options::match_opt - match an option
- X //
- X // ^SYNOPSIS:
- X! // const char * match_opt(opt, int ignore_case) const
- X //
- X // ^PARAMETERS:
- X // char opt -- the option-character to match
- X // int ignore_case -- should we ignore character-case?
- X //
- X // ^DESCRIPTION:
- X! // See if "opt" is found in "optvec"
- X //
- X // ^REQUIREMENTS:
- X! // - optvec should be non-NULL and terminated by a NULL pointer.
- X //
- X // ^SIDE-EFFECTS:
- X // None.
- X***************
- X*** 380,398 ****
- X // - see if "opt" is a match, if so return option-spec
- X // end-for
- X // ^^-------------------------------------------------------------------------
- X! static const char *
- X! match_opt(const char * const optv[], char opt, int ignore_case =0)
- X! {
- X! if ((optv == NULL) || (! *optv)) return NULL;
- X
- X! for (const char * optspec = *optv; optspec ; optspec = *(++optv)) {
- X! if (isHiddenOpt(optspec)) ++optspec;
- X! char optchar = OptChar(optspec);
- X if (isNullOpt(optchar)) continue;
- X if (opt == optchar) {
- X! return optspec;
- X } else if (ignore_case && (TOLOWER(opt) == TOLOWER(optchar))) {
- X! return optspec;
- X }
- X }
- X
- X--- 579,596 ----
- X // - see if "opt" is a match, if so return option-spec
- X // end-for
- X // ^^-------------------------------------------------------------------------
- X! const char *
- X! Options::match_opt(char opt, int ignore_case) const {
- X! if ((optvec == NULL) || (! *optvec)) return NULL;
- X
- X! for (const char * const * optv = optvec ; *optv ; optv++) {
- X! OptionSpec optspec = *optv;
- X! char optchar = optspec.OptChar();
- X if (isNullOpt(optchar)) continue;
- X if (opt == optchar) {
- X! return optspec;
- X } else if (ignore_case && (TOLOWER(opt) == TOLOWER(optchar))) {
- X! return optspec;
- X }
- X }
- X
- X***************
- X*** 400,412 ****
- X }
- X
- X // ---------------------------------------------------------------------------
- X! // ^FUNCTION: match_longopt - match a long-option
- X //
- X // ^SYNOPSIS:
- X! // static const char * match_longopt(optv, opt, len, ambiguous)
- X //
- X // ^PARAMETERS:
- X- // char * optv[] -- the vector of option-specs
- X // char * opt -- the long-option to match
- X // int len -- the number of character of "opt" to match
- X // int & ambiguous -- set by this routine before returning.
- X--- 598,609 ----
- X }
- X
- X // ---------------------------------------------------------------------------
- X! // ^FUNCTION: Options::match_longopt - match a long-option
- X //
- X // ^SYNOPSIS:
- X! // const char * Options::match_longopt(opt, len, ambiguous)
- X //
- X // ^PARAMETERS:
- X // char * opt -- the long-option to match
- X // int len -- the number of character of "opt" to match
- X // int & ambiguous -- set by this routine before returning.
- X***************
- X*** 431,438 ****
- X // foreach option-spec
- X // if we have an EXACT-MATCH, return the option-spec
- X // if we have a partial-match then
- X! // if we already had a previous partial match then
- X! // set ambiguous = TRUE and retrun NULL
- X // else
- X // remember this options spec and continue matching
- X // end-if
- X--- 628,635 ----
- X // foreach option-spec
- X // if we have an EXACT-MATCH, return the option-spec
- X // if we have a partial-match then
- X! // if we already had a previous partial match then
- X! // set ambiguous = TRUE and return NULL
- X // else
- X // remember this options spec and continue matching
- X // end-if
- X***************
- X*** 440,460 ****
- X // end-for
- X // if we had exactly 1 partial match return it, else return NULL
- X // ^^-------------------------------------------------------------------------
- X! static const char *
- X! match_longopt(const char * const optv[],
- X! const char * opt,
- X! int len,
- X! int & ambiguous)
- X! {
- X kwdmatch_t result;
- X const char * matched = NULL ;
- X
- X ambiguous = 0;
- X! if ((optv == NULL) || (! *optv)) return NULL;
- X
- X! for (const char * optspec = *optv; optspec ; optspec = *(++optv)) {
- X! if (isHiddenOpt(optspec)) ++optspec;
- X! const char * longopt = LongOpt(optspec);
- X if (longopt == NULL) continue;
- X result = kwdmatch(longopt, opt, len);
- X if (result == EXACT_MATCH) {
- X--- 637,653 ----
- X // end-for
- X // if we had exactly 1 partial match return it, else return NULL
- X // ^^-------------------------------------------------------------------------
- X! const char *
- X! Options::match_longopt(const char * opt, int len, int & ambiguous) const {
- X kwdmatch_t result;
- X const char * matched = NULL ;
- X
- X ambiguous = 0;
- X! if ((optvec == NULL) || (! *optvec)) return NULL;
- X
- X! for (const char * const * optv = optvec ; *optv ; optv++) {
- X! OptionSpec optspec = *optv;
- X! const char * longopt = optspec.LongOpt();
- X if (longopt == NULL) continue;
- X result = kwdmatch(longopt, opt, len);
- X if (result == EXACT_MATCH) {
- X***************
- X*** 467,473 ****
- X matched = optspec;
- X }
- X }
- X! }/*for*/
- X
- X return matched;
- X }
- X--- 660,666 ----
- X matched = optspec;
- X }
- X }
- X! }//for
- X
- X return matched;
- X }
- X***************
- X*** 503,525 ****
- X // It gets complicated -- follow the comments in the source.
- X // ^^-------------------------------------------------------------------------
- X int
- X! Options::parse_opt(OptIter & iter, const char * & optarg)
- 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 // Check for an unknown option
- X! if (optspec == NULL) {
- X // See if this was a long-option in disguise
- X! if (! (optctrls & NOGUESSING)) {
- X unsigned save_ctrls = optctrls;
- X const char * save_nextchar = nextchar;
- X nextchar -= 1;
- X! optctrls |= (QUIET | NOGUESSING);
- X int optchar = parse_longopt(iter, optarg);
- X optctrls = save_ctrls;
- X if (optchar > 0) {
- X--- 696,717 ----
- X // It gets complicated -- follow the comments in the source.
- X // ^^-------------------------------------------------------------------------
- X int
- X! Options::parse_opt(OptIter & iter, const char * & optarg) {
- 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! OptionSpec optspec = match_opt(*(nextchar++), (optctrls & Options::ANYCASE));
- X
- X // Check for an unknown option
- X! if (optspec.isNULL()) {
- X // See if this was a long-option in disguise
- X! if (! (optctrls & Options::NOGUESSING)) {
- X unsigned save_ctrls = optctrls;
- X const char * save_nextchar = nextchar;
- X nextchar -= 1;
- X! optctrls |= (Options::QUIET | Options::NOGUESSING);
- X int optchar = parse_longopt(iter, optarg);
- X optctrls = save_ctrls;
- X if (optchar > 0) {
- X***************
- X*** 528,545 ****
- X nextchar = save_nextchar;
- X }
- X }
- X! if (! (optctrls & QUIET)) {
- X cerr << cmdname << ": unknown option -"
- X << *(nextchar - 1) << "." << endl ;
- X }
- X optarg = (nextchar - 1); // record the bad option in optarg
- X! return BADCHAR;
- X }
- X
- X // If no argument is taken, then leave now
- X! if (isNoArg(optspec)) {
- X optarg = NULL;
- X! return OptChar(optspec);
- X }
- X
- X // Check for argument in this arg
- X--- 720,737 ----
- X nextchar = save_nextchar;
- X }
- X }
- X! if (! (optctrls & Options::QUIET)) {
- X cerr << cmdname << ": unknown option -"
- X << *(nextchar - 1) << "." << endl ;
- X }
- X optarg = (nextchar - 1); // record the bad option in optarg
- X! return Options::BADCHAR;
- X }
- X
- X // If no argument is taken, then leave now
- X! if (optspec.isNoArg()) {
- X optarg = NULL;
- X! return optspec.OptChar();
- X }
- X
- X // Check for argument in this arg
- X***************
- X*** 546,572 ****
- X if (*nextchar) {
- X optarg = nextchar; // the argument is right here
- X nextchar = NULL; // we've exhausted this arg
- X! if (isList(optspec)) listopt = optspec ; // save the list-spec
- X! return OptChar(optspec);
- X }
- X
- X // Check for argument in next arg
- X const char * nextarg = iter.curr();
- X if ((nextarg != NULL) &&
- X! (isRequired(optspec) || (! isOption(optctrls, nextarg)))) {
- X optarg = nextarg; // the argument is here
- X iter.next(); // end of arg - advance
- X! if (isList(optspec)) listopt = optspec ; // save the list-spec
- X! return OptChar(optspec);
- X }
- X
- X // No argument given - if its required, thats an error
- X optarg = NULL;
- X! if (isRequired(optspec) && !(optctrls & QUIET)) {
- X! cerr << cmdname << ": argument required for -" << OptChar(optspec)
- X << " option." << endl ;
- X }
- X! return OptChar(optspec);
- X }
- X
- X // ---------------------------------------------------------------------------
- X--- 738,764 ----
- X if (*nextchar) {
- X optarg = nextchar; // the argument is right here
- X nextchar = NULL; // we've exhausted this arg
- X! if (optspec.isList()) listopt = optspec ; // save the list-spec
- X! return optspec.OptChar();
- X }
- X
- X // Check for argument in next arg
- X const char * nextarg = iter.curr();
- X if ((nextarg != NULL) &&
- X! (optspec.isValRequired() || (! isOption(optctrls, nextarg)))) {
- X optarg = nextarg; // the argument is here
- X iter.next(); // end of arg - advance
- X! if (optspec.isList()) listopt = optspec ; // save the list-spec
- X! return optspec.OptChar();
- X }
- X
- X // No argument given - if its required, thats an error
- X optarg = NULL;
- X! if (optspec.isValRequired() && !(optctrls & Options::QUIET)) {
- X! cerr << cmdname << ": argument required for -" << optspec.OptChar()
- X << " option." << endl ;
- X }
- X! return optspec.OptChar();
- X }
- X
- X // ---------------------------------------------------------------------------
- X***************
- X*** 601,608 ****
- X // It gets complicated -- follow the comments in the source.
- X // ^^-------------------------------------------------------------------------
- X int
- X! Options::parse_longopt(OptIter & iter, const char * & optarg)
- X! {
- X int len = 0, ambiguous = 0;
- X
- X listopt = NULL ; // reset the list-spec
- X--- 793,799 ----
- X // It gets complicated -- follow the comments in the source.
- X // ^^-------------------------------------------------------------------------
- X int
- X! Options::parse_longopt(OptIter & iter, const char * & optarg) {
- X int len = 0, ambiguous = 0;
- X
- X listopt = NULL ; // reset the list-spec
- X***************
- X*** 617,631 ****
- X }
- X
- X // Try to match a known long-option
- X! const char * optspec = match_longopt(optvec, nextchar, len, ambiguous);
- X
- X // Check for an unknown long-option
- X! if (optspec == NULL) {
- X // See if this was a short-option in disguise
- X! if ((! ambiguous) && (! (optctrls & NOGUESSING))) {
- X unsigned save_ctrls = optctrls;
- X const char * save_nextchar = nextchar;
- X! optctrls |= (QUIET | NOGUESSING);
- X int optchar = parse_opt(iter, optarg);
- X optctrls = save_ctrls;
- X if (optchar > 0) {
- X--- 808,822 ----
- X }
- X
- X // Try to match a known long-option
- X! OptionSpec optspec = match_longopt(nextchar, len, ambiguous);
- X
- X // Check for an unknown long-option
- X! if (optspec.isNULL()) {
- X // See if this was a short-option in disguise
- X! if ((! ambiguous) && (! (optctrls & Options::NOGUESSING))) {
- X unsigned save_ctrls = optctrls;
- X const char * save_nextchar = nextchar;
- X! optctrls |= (Options::QUIET | Options::NOGUESSING);
- X int optchar = parse_opt(iter, optarg);
- X optctrls = save_ctrls;
- X if (optchar > 0) {
- X***************
- X*** 634,660 ****
- X nextchar = save_nextchar;
- X }
- X }
- X! if (! (optctrls & QUIET)) {
- X cerr << cmdname << ": " << ((ambiguous) ? "ambiguous" : "unknown")
- X << " option "
- X! << ((optctrls & LONG_ONLY) ? "-" : "--")
- X << nextchar << "." << endl ;
- X }
- X optarg = nextchar; // record the bad option in optarg
- X nextchar = NULL; // we've exhausted this argument
- X! return (ambiguous) ? AMBIGUOUS : BADKWD;
- X }
- X
- X // If no argument is taken, then leave now
- X! if (isNoArg(optspec)) {
- X! if ((val) && ! (optctrls & QUIET)) {
- X cerr << cmdname << ": option "
- X! << ((optctrls & LONG_ONLY) ? "-" : "--")
- X! << LongOpt(optspec) << " does NOT take an argument." << endl ;
- X }
- X optarg = val; // record the unexpected argument
- X nextchar = NULL; // we've exhausted this argument
- X! return OptChar(optspec);
- X }
- X
- X // Check for argument in this arg
- X--- 825,851 ----
- X nextchar = save_nextchar;
- X }
- X }
- X! if (! (optctrls & Options::QUIET)) {
- X cerr << cmdname << ": " << ((ambiguous) ? "ambiguous" : "unknown")
- X << " option "
- X! << ((optctrls & Options::LONG_ONLY) ? "-" : "--")
- X << nextchar << "." << endl ;
- X }
- X optarg = nextchar; // record the bad option in optarg
- X nextchar = NULL; // we've exhausted this argument
- X! return (ambiguous) ? Options::AMBIGUOUS : Options::BADKWD;
- X }
- X
- X // If no argument is taken, then leave now
- X! if (optspec.isNoArg()) {
- X! if ((val) && ! (optctrls & Options::QUIET)) {
- X cerr << cmdname << ": option "
- X! << ((optctrls & Options::LONG_ONLY) ? "-" : "--")
- X! << optspec.LongOpt() << " does NOT take an argument." << endl ;
- X }
- X optarg = val; // record the unexpected argument
- X nextchar = NULL; // we've exhausted this argument
- X! return optspec.OptChar();
- X }
- X
- X // Check for argument in this arg
- X***************
- X*** 661,685 ****
- X if (val) {
- X optarg = val; // the argument is right here
- X nextchar = NULL; // we exhausted the rest of this arg
- X! if (isList(optspec)) listopt = optspec ; // save the list-spec
- X! return OptChar(optspec);
- X }
- X
- X // Check for argument in next arg
- X const char * nextarg = iter.curr(); // find the next argument to parse
- X if ((nextarg != NULL) &&
- X! (isRequired(optspec) || (! isOption(optctrls, nextarg)))) {
- X optarg = nextarg; // the argument is right here
- X iter.next(); // end of arg - advance
- X nextchar = NULL; // we exhausted the rest of this arg
- X! if (isList(optspec)) listopt = optspec ; // save the list-spec
- X! return OptChar(optspec);
- X }
- X
- X // No argument given - if its required, thats an error
- X optarg = NULL;
- X! if (isRequired(optspec) && !(optctrls & QUIET)) {
- X! const char * longopt = LongOpt(optspec);
- X const char * spc = ::strchr(longopt, ' ');
- X int longopt_len;
- X if (spc) {
- X--- 852,876 ----
- X if (val) {
- X optarg = val; // the argument is right here
- X nextchar = NULL; // we exhausted the rest of this arg
- X! if (optspec.isList()) listopt = optspec ; // save the list-spec
- X! return optspec.OptChar();
- X }
- X
- X // Check for argument in next arg
- X const char * nextarg = iter.curr(); // find the next argument to parse
- X if ((nextarg != NULL) &&
- X! (optspec.isValRequired() || (! isOption(optctrls, nextarg)))) {
- X optarg = nextarg; // the argument is right here
- X iter.next(); // end of arg - advance
- X nextchar = NULL; // we exhausted the rest of this arg
- X! if (optspec.isList()) listopt = optspec ; // save the list-spec
- X! return optspec.OptChar();
- X }
- X
- X // No argument given - if its required, thats an error
- X optarg = NULL;
- X! if (optspec.isValRequired() && !(optctrls & Options::QUIET)) {
- X! const char * longopt = optspec.LongOpt();
- X const char * spc = ::strchr(longopt, ' ');
- X int longopt_len;
- X if (spc) {
- X***************
- X*** 688,805 ****
- X longopt_len = ::strlen(longopt);
- X }
- X cerr << cmdname << ": argument required for "
- X! << ((optctrls & LONG_ONLY) ? "-" : "--");
- X cerr.write(longopt, longopt_len) << " option." << endl ;
- X }
- X nextchar = NULL; // we exhausted the rest of this arg
- X! return OptChar(optspec);
- X }
- X
- X // ---------------------------------------------------------------------------
- X- // ^FUNCTION: Options::fmt_opt - format an option-spec for a usage message
- X- //
- X- // ^SYNOPSIS:
- X- // unsigned Options::fmt_opt(optspec, buf)
- X- //
- X- // ^PARAMETERS:
- X- // char * optspec -- the option-specification
- X- // char * buf -- where to print the formatted option
- X- //
- X- // ^DESCRIPTION:
- X- // Self-explanatory.
- X- //
- X- // ^REQUIREMENTS:
- X- // - optspec must be a valid option-spec.
- X- // - buf must be large enough to hold the result
- X- //
- X- // ^SIDE-EFFECTS:
- X- // - writes to buf.
- X- //
- X- // ^RETURN-VALUE:
- X- // Number of characters written to buf.
- X- //
- X- // ^ALGORITHM:
- X- // Trivial.
- X- // ^^-------------------------------------------------------------------------
- X- unsigned
- X- Options::fmt_opt(const char * optspec, char * buf) const
- X- {
- X- static char default_value[] = "<value>";
- X- if (isHiddenOpt(optspec)) return (unsigned)(*buf = '\0');
- X- char optchar = OptChar(optspec);
- X- const char * longopt = LongOpt(optspec);
- X- char * p = buf ;
- X-
- X- const char * value = NULL;
- X- int longopt_len = 0;
- X- int value_len = 0;
- X-
- X- if (longopt) {
- X- value = ::strchr(longopt, ' ');
- X- longopt_len = (value) ? (value - longopt) : ::strlen(longopt);
- X- } else {
- X- value = ::strchr(optspec + 1, ' ');
- X- }
- X- while (value && (*value == ' ')) ++value;
- X- if (value && *value) {
- X- value_len = ::strlen(value);
- X- } else {
- X- value = default_value;
- X- value_len = sizeof(default_value) - 1;
- X- }
- X-
- X- if ((optctrls & SHORT_ONLY) &&
- X- ((! isNullOpt(optchar)) || (optctrls & NOGUESSING))) {
- X- longopt = NULL;
- X- }
- X- if ((optctrls & LONG_ONLY) && (longopt || (optctrls & NOGUESSING))) {
- X- optchar = '\0';
- X- }
- X- if (isNullOpt(optchar) && (longopt == NULL)) {
- X- *buf = '\0';
- X- return 0;
- X- }
- X-
- X- *(p++) = '[';
- X-
- X- // print the single character option
- X- if (! isNullOpt(optchar)) {
- X- *(p++) = '-';
- X- *(p++) = optchar;
- X- }
- X-
- X- if ((! isNullOpt(optchar)) && (longopt)) *(p++) = '|';
- X-
- X- // print the long option
- X- if (longopt) {
- X- *(p++) = '-';
- X- if (! (optctrls & (LONG_ONLY | SHORT_ONLY))) {
- X- *(p++) = '-';
- X- }
- X- strncpy(p, longopt, longopt_len);
- X- p += longopt_len;
- X- }
- X-
- X- // print any argument the option takes
- X- if (isValTaken(optspec)) {
- X- *(p++) = ' ' ;
- X- if (isOptional(optspec)) *(p++) = '[' ;
- X- strcpy(p, value);
- X- p += value_len;
- X- if (isList(optspec)) {
- X- strcpy(p, " ...");
- X- p += 4;
- X- }
- X- if (isOptional(optspec)) *(p++) = ']' ;
- X- }
- X-
- X- *(p++) = ']';
- X- *p = '\0';
- X-
- X- return (unsigned) strlen(buf);
- X- }
- X-
- X- // ---------------------------------------------------------------------------
- X // ^FUNCTION: Options::usage - print usage
- X //
- X // ^SYNOPSIS:
- X--- 879,892 ----
- X longopt_len = ::strlen(longopt);
- X }
- X cerr << cmdname << ": argument required for "
- X! << ((optctrls & Options::LONG_ONLY) ? "-" : "--");
- X cerr.write(longopt, longopt_len) << " option." << endl ;
- X }
- X nextchar = NULL; // we exhausted the rest of this arg
- X! return optspec.OptChar();
- X }
- X
- X // ---------------------------------------------------------------------------
- X // ^FUNCTION: Options::usage - print usage
- X //
- X // ^SYNOPSIS:
- X***************
- X*** 825,832 ****
- X // Print usage on os, wrapping long lines where necessary.
- X // ^^-------------------------------------------------------------------------
- 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--- 912,918 ----
- X // Print usage on os, wrapping long lines where necessary.
- X // ^^-------------------------------------------------------------------------
- X void
- X! Options::usage(ostream & os, const char * positionals) const {
- X const char * const * optv = optvec;
- X unsigned cols = 79;
- X int first, nloop;
- X***************
- X*** 846,851 ****
- X--- 932,938 ----
- X // print the options and the positional arguments
- X for (nloop = 0, first = 1 ; !nloop ; optv++, first = 0) {
- X unsigned len;
- X+ OptionSpec optspec = *optv;
- X
- X // figure out how wide this parameter is (for printing)
- X if (! *optv) {
- X***************
- X*** 852,859 ****
- X len = strlen(positionals);
- X ++nloop; // terminate this loop
- X } else {
- X! if (isHiddenOpt(*optv)) continue;
- X! len = fmt_opt(*optv, buf);
- X }
- X
- X // Will this fit?
- X--- 939,946 ----
- X len = strlen(positionals);
- X ++nloop; // terminate this loop
- X } else {
- X! if (optspec.isHiddenOpt()) continue;
- X! len = optspec.Format(buf, optctrls);
- X }
- X
- X // Will this fit?
- X***************
- X*** 908,915 ****
- X // It gets complicated -- follow the comments in the source.
- X // ^^-------------------------------------------------------------------------
- X int
- X! Options::operator()(OptIter & iter, const char * & optarg)
- X! {
- X explicit_end = 0;
- X
- X // See if we have an option left over from before ...
- X--- 995,1001 ----
- X // It gets complicated -- follow the comments in the source.
- X // ^^-------------------------------------------------------------------------
- X int
- X! Options::operator()(OptIter & iter, const char * & optarg) {
- X explicit_end = 0;
- X
- X // See if we have an option left over from before ...
- X***************
- X*** 921,941 ****
- X const char * arg = iter.curr();
- X if (arg == NULL) {
- X listopt = NULL;
- X! return ENDOPTS;
- X } else if (isEndOpts(arg)) {
- X iter.next(); // advance past end-of-options arg
- X listopt = NULL;
- X explicit_end = 1;
- X! return ENDOPTS;
- X }
- X
- X // Do we have a positional arg?
- X if (! listopt) {
- X if ((! *arg) || (! arg[1])) {
- X! return ENDOPTS;
- X } else if ((*arg != '-') &&
- X! ((! (optctrls & PLUS)) || (*arg != '+'))) {
- X! return ENDOPTS;
- X }
- X }
- X
- X--- 1007,1027 ----
- X const char * arg = iter.curr();
- X if (arg == NULL) {
- X listopt = NULL;
- X! return Options::ENDOPTS;
- X } else if (isEndOpts(arg)) {
- X iter.next(); // advance past end-of-options arg
- X listopt = NULL;
- X explicit_end = 1;
- X! return Options::ENDOPTS;
- X }
- X
- X // Do we have a positional arg?
- X if (! listopt) {
- X if ((! *arg) || (! arg[1])) {
- X! return Options::ENDOPTS;
- X } else if ((*arg != '-') &&
- X! ((! (optctrls & Options::PLUS)) || (*arg != '+'))) {
- X! return Options::ENDOPTS;
- X }
- X }
- X
- X***************
- X*** 942,952 ****
- X iter.next(); // pass the argument that arg already points to
- X
- X // See if we have a long option ...
- X! if (! (optctrls & SHORT_ONLY)) {
- X if ((*arg == '-') && (arg[1] == '-')) {
- X nextchar = arg + 2;
- X return parse_longopt(iter, optarg);
- X! } else if ((optctrls & PLUS) && (*arg == '+')) {
- X nextchar = arg + 1;
- X return parse_longopt(iter, optarg);
- X }
- X--- 1028,1038 ----
- X iter.next(); // pass the argument that arg already points to
- X
- X // See if we have a long option ...
- X! if (! (optctrls & Options::SHORT_ONLY)) {
- X if ((*arg == '-') && (arg[1] == '-')) {
- X nextchar = arg + 2;
- X return parse_longopt(iter, optarg);
- X! } else if ((optctrls & Options::PLUS) && (*arg == '+')) {
- X nextchar = arg + 1;
- X return parse_longopt(iter, optarg);
- X }
- X***************
- X*** 953,959 ****
- X }
- X if (*arg == '-') {
- X nextchar = arg + 1;
- X! if (optctrls & LONG_ONLY) {
- X return parse_longopt(iter, optarg);
- X } else {
- X return parse_opt(iter, optarg);
- X--- 1039,1045 ----
- X }
- X if (*arg == '-') {
- X nextchar = arg + 1;
- X! if (optctrls & Options::LONG_ONLY) {
- X return parse_longopt(iter, optarg);
- X } else {
- X return parse_opt(iter, optarg);
- X***************
- X*** 961,967 ****
- X }
- X
- X // If we get here - it is because we have a list value
- X optarg = arg ; // record the list value
- X! return OptChar(listopt) ;
- X }
- X
- X--- 1047,1054 ----
- X }
- X
- X // If we get here - it is because we have a list value
- X+ OptionSpec optspec = listopt;
- X optarg = arg ; // record the list value
- X! return optspec.OptChar() ;
- X }
- X
- X*** options.h.OLD Fri Feb 11 17:30:16 1994
- X--- options.h Fri Feb 11 17:27:01 1994
- X***************
- X*** 169,180 ****
- 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--- 169,174 ----
- X***************
- X*** 371,384 ****
- X const char * listopt; // last list-option we matched
- X const char * cmdname; // name of the command
- X
- X int
- X parse_opt(OptIter & iter, const char * & optarg);
- X
- X int
- X parse_longopt(OptIter & iter, const char * & optarg);
- X-
- X- unsigned
- X- fmt_opt(const char * optspec, char * buf) const;
- X
- X public:
- X enum OptCtrl {
- X--- 365,384 ----
- X const char * listopt; // last list-option we matched
- X const char * cmdname; // name of the command
- X
- X+ void
- X+ check_syntax(void) const;
- X+
- X+ const char *
- X+ match_opt(char opt, int ignore_case =0) const;
- X+
- X+ const char *
- X+ match_longopt(const char * opt, int len, int & ambiguous) const;
- X+
- X int
- X parse_opt(OptIter & iter, const char * & optarg);
- X
- X int
- X parse_longopt(OptIter & iter, const char * & optarg);
- X
- X public:
- X enum OptCtrl {
- X*** testopts.C.OLD Fri Feb 11 17:30:19 1994
- X--- testopts.C Tue Feb 08 19:07:24 1994
- X***************
- X*** 32,48 ****
- X setflags(const char * flags_str, Options & opts) {
- X if (flags_str && *flags_str) {
- X unsigned flags = opts.ctrls();
- X! if (::strchr(flags_str, '+')) flags |= Options::PLUS;
- X! if (::strchr(flags_str, 'A')) flags |= Options::ANYCASE;
- X! if (::strchr(flags_str, 'a')) flags |= Options::ANYCASE;
- X! if (::strchr(flags_str, 'L')) flags |= Options::LONG_ONLY;
- X! if (::strchr(flags_str, 'l')) flags |= Options::LONG_ONLY;
- X! if (::strchr(flags_str, 'S')) flags |= Options::SHORT_ONLY;
- X! if (::strchr(flags_str, 's')) flags |= Options::SHORT_ONLY;
- X! if (::strchr(flags_str, 'Q')) flags |= Options::QUIET;
- X! if (::strchr(flags_str, 'q')) flags |= Options::QUIET;
- X! if (::strchr(flags_str, 'n')) flags |= Options::NOGUESSING;
- X! if (::strchr(flags_str, 'N')) flags |= Options::NOGUESSING;
- X opts.ctrls(flags);
- X }
- X }
- X--- 32,61 ----
- X setflags(const char * flags_str, Options & opts) {
- X if (flags_str && *flags_str) {
- X unsigned flags = opts.ctrls();
- X! for (const char * p = flags_str; *p; p++) {
- X! switch (*p) {
- X! case '+' :
- X! flags |= Options::PLUS;
- X! break;
- X! case 'A' : case 'a' :
- X! flags |= Options::ANYCASE;
- X! break;
- X! case 'L' : case 'l' :
- X! flags |= Options::LONG_ONLY;
- X! break;
- X! case 'S' : case 's' :
- X! flags |= Options::SHORT_ONLY;
- X! break;
- X! case 'Q' : case 'q' :
- X! flags |= Options::QUIET;
- X! break;
- X! case 'N' : case 'n' :
- X! flags |= Options::NOGUESSING;
- X! break;
- X! default :
- X! break;
- X! }
- X! }
- X opts.ctrls(flags);
- X }
- X }
- END_OF_FILE
- if test 49743 -ne `wc -c <'PATCH03'`; then
- echo shar: \"'PATCH03'\" unpacked with wrong size!
- fi
- # end of 'PATCH03'
- fi
- echo shar: End of shell archive.
- exit 0
-
- exit 0 # Just in case...
-