From 52b15b6e6e3318c6e5008168d2c600d6e7688d4a Mon Sep 17 00:00:00 2001 From: mes5k Date: Thu, 3 Apr 2003 17:57:37 +0000 Subject: [PATCH] new update --- src/Arg.cpp | 97 ++++++++++++++++++++++++++++------------------- src/CmdLine.cpp | 70 +++++++++++----------------------- src/SwitchArg.cpp | 43 +++++++++++++++++++-- 3 files changed, 121 insertions(+), 89 deletions(-) diff --git a/src/Arg.cpp b/src/Arg.cpp index d2be65a..191b0fe 100644 --- a/src/Arg.cpp +++ b/src/Arg.cpp @@ -24,6 +24,8 @@ namespace TCLAP { +bool Arg::_ignoreRest = false; + Arg::Arg( const string& flag, const string& name, const string& desc, @@ -36,12 +38,12 @@ Arg::Arg( const string& flag, _required(req), _valueRequired(valreq), _alreadySet(false), + _ignoreable(true), _visitor( v ) { - if ( _flag == "" ) - _labeled = false; - else - _labeled = true; + if ( _flag.length() > 1 ) + throw(ArgException("Argument flag can only be one character long", + toString() ) ); }; Arg::Arg() @@ -50,8 +52,7 @@ Arg::Arg() _flag(""), _required(false), _valueRequired(false), - _alreadySet(false), - _labeled(false) + _alreadySet(false) { }; Arg::Arg(const Arg& a) @@ -60,8 +61,7 @@ Arg::Arg(const Arg& a) _flag(a._flag), _required(a._required), _valueRequired(a._valueRequired), - _alreadySet(a._alreadySet), - _labeled(a._labeled) + _alreadySet(a._alreadySet) { }; Arg::~Arg() { }; @@ -76,62 +76,81 @@ Arg& Arg::operator=(const Arg& a) _required = a._required; _valueRequired = a._valueRequired; _alreadySet = a._alreadySet; - _labeled = a._labeled; } return *this; }; -/* -bool Arg::operator<(const Arg& a) const +string Arg::shortID( const string& valueId ) const { - if ( _required && !a._required ) - return false; + string id = ""; - if ( !_required && a._required ) - return true; + id = "-" + _flag; + + if ( _valueRequired ) + id += " <" + valueId + ">"; - if ( _labeled && !a._labeled ) - return false; + if ( !_required ) + id = "[" + id + "]"; + + return id; +} + +string Arg::longID( const string& valueId ) const +{ + string id = ""; + + id = "-" + _flag; + + if ( _valueRequired ) + id += " <" + valueId + ">"; + + + id += ", --" + _name; + + if ( _valueRequired ) + id += " <" + valueId + ">"; + + return id; - if ( !_labeled && a._labeled ) - return true; - - return false; } -*/ bool Arg::operator==(const Arg& a) { - if ( _labeled ) - { - if ( _flag == a._flag || _name == a._name ) - return true; - else - return false; - } + if ( _flag == a._flag || + _name == a._name || + _description == a._description ) + return true; else - { - if ( _name == a._name || _description == a._description ) - return true; - else - return false; - } + return false; } // should be overridden -bool Arg::processArg(int* i, int argc, char** argv) +bool Arg::processArg(int* i, vector& args ) { - cerr << "WARNING: Ignoring unknown argument: " << argv[*i] << endl; + cerr << "WARNING: Ignoring unknown argument: " << args[*i] << endl; return false; } const string& Arg::getName() const { return _name; } ; -const string& Arg::getDescription() const { return _description; }; + +string Arg::getDescription() const +{ + string desc = ""; + if ( _required ) + desc = "(required) "; + + if ( _valueRequired ) + desc += "(value required) "; + + desc += _description; + return desc; +}; + const string& Arg::getFlag() const { return _flag; }; bool Arg::isRequired() const { return _required; } bool Arg::isValueRequired() const { return _valueRequired; } bool Arg::isAlreadySet() const { return _alreadySet; } -bool Arg::isLabeled() const { return _labeled; } +bool Arg::isIgnoreable() const { return _ignoreable; } bool Arg::argMatches( const string& argFlag ) const { diff --git a/src/CmdLine.cpp b/src/CmdLine.cpp index 0602ce9..27b2e29 100644 --- a/src/CmdLine.cpp +++ b/src/CmdLine.cpp @@ -28,18 +28,22 @@ CmdLine::CmdLine(char *progName, const string& m, const string& v ) : _progName(progName), _message(m), _version(v), - _numRequired(0), - _maxLength(0) + _numRequired(0) { SwitchArg* help = new SwitchArg("h","help", - "displays usage information and exits", + "Displays usage information and exits.", false, new HelpVisitor( this ) ); add( *help ); SwitchArg* vers = new SwitchArg("v","version", - "displays version information and exits", + "Displays version information and exits.", false, new VersionVisitor( this ) ); add( *vers ); + + SwitchArg* ignore = new SwitchArg("-","ignore_rest", + "Ignores the rest of the labeled arguments following this flag.", + false, new IgnoreRestVisitor() ); + add( *ignore ); } void CmdLine::add( Arg& a ) @@ -51,12 +55,11 @@ void CmdLine::add( Arg& a ) return; } - if ( a.isLabeled() ) - _argList.push_front( &a ); - else + if ( a.getFlag() == "" ) _argList.push_back( &a ); + else + _argList.push_front( &a ); - _maxLength = max( _maxLength, (int)((a.getName()).length()) ); if ( a.isRequired() ) _numRequired++; } @@ -73,45 +76,13 @@ void CmdLine::usage( int exitVal ) cout << endl << "USAGE: " << endl << endl << " " << _progName ; for (ArgIterator it = _argList.begin(); it != _argList.end(); it++) - { - - cout << " "; - if ( !(*it)->isRequired() ) cout << "["; - if ( (*it)->isLabeled() ) - cout << "-" << ((*it))->getFlag(); - if ( (*it)->isValueRequired() ) - { - if ( (*it)->isLabeled() ) cout << " "; - cout << (*it)->getName(); - } - if ( !(*it)->isRequired() ) cout << "]"; - } + cout << " " << (*it)->shortID(); cout << endl << endl << "Where: " << endl << endl; for (ArgIterator it = _argList.begin(); it != _argList.end(); it++) - { - cout.setf(ios::left); - - string s; - - if ( !(*it)->isRequired() ) s += "["; - else s += " "; - - if ( (*it)->isLabeled() ) - s = s + "-" + (*it)->getFlag(); - - if ( (*it)->isValueRequired() ) - { - if ( (*it)->isLabeled() ) s += " "; - s += (*it)->getName(); - } - - if ( !(*it)->isRequired() ) s += "]"; - - cout << " " << setw(_maxLength + 5) << s.c_str() << " = " - << (*it)->getDescription() << endl; - } + cout << " " << (*it)->longID() << endl << " " + << (*it)->getDescription() << endl << endl; cout << endl << endl << _message << endl << endl; exit( exitVal ); @@ -121,14 +92,19 @@ void CmdLine::parse(int argc, char** argv) { try { + // this step is necessary so that we have easy access to mutable strings. + vector args; + for (int i = 1; i < argc; i++) + args.push_back(argv[i]); + int requiredCount = 0; - for (int i = 1; i < argc; i++) + for (int i = 0; i < args.size(); i++) { bool matched = false; for (ArgIterator it = _argList.begin(); it != _argList.end(); it++) { - if ( (*it)->processArg( &i, argc, argv ) ) + if ( (*it)->processArg( &i, args ) ) { if ( (*it)->isRequired() ) requiredCount++; matched = true; @@ -136,8 +112,8 @@ void CmdLine::parse(int argc, char** argv) } } - if ( !matched ) - throw( ArgException("Couldn't find match for argument",argv[i])); + if ( !matched && !Arg::ignoreRest() ) + throw( ArgException("Couldn't find match for argument",args[i])); } if ( requiredCount < _numRequired ) diff --git a/src/SwitchArg.cpp b/src/SwitchArg.cpp index ba20297..ace9c40 100644 --- a/src/SwitchArg.cpp +++ b/src/SwitchArg.cpp @@ -40,10 +40,47 @@ SwitchArg::~SwitchArg() { }; bool SwitchArg::getValue() { return _value; }; -bool SwitchArg::processArg(int *i, int argc, char** argv) +bool SwitchArg::combinedSwitchesMatch(string& combinedSwitches ) { - if ( argMatches( argv[*i] ) ) + // make sure this is actually a combined switch + if ( combinedSwitches[0] != '-' ) + return false; + + // make sure it isn't a long name + if ( combinedSwitches[1] == '-' ) + return false; + + // ok, we're not specifying a ValueArg, so we know that we have + // a combined switch list. + for ( int i = 1; i < combinedSwitches.length(); i++ ) + if ( combinedSwitches[i] == _flag[0] ) + { + // update the combined switches so this one is no longer present + // this is necessary so that no unlabeled args are matched + // later in the processing. + combinedSwitches.erase(i,1); + return true; + } + + // none of the switches passed in the list match. + return false; +} + + +bool SwitchArg::processArg(int *i, vector& args) +{ + if ( _ignoreable && Arg::ignoreRest() ) + return false; + + if ( argMatches( args[*i] ) || combinedSwitchesMatch( args[*i] ) ) { + // If we match on a combined switch, then we want to return false + // so that other switches in the combination will also have a + // chance to match. + bool ret = false; + if ( argMatches( args[*i] ) ) + ret = true; + if ( _alreadySet ) throw(ArgException("Argument already set!", toString())); @@ -56,7 +93,7 @@ bool SwitchArg::processArg(int *i, int argc, char** argv) _checkWithVisitor(); - return true; + return ret; } else return false;