Catch ExitException and exit. This allows all resources used during

parsing to be released, bug 1662188.
This commit is contained in:
macbishop 2007-02-17 14:59:30 +00:00
parent 0953ea9976
commit e0a835388b

View File

@ -1,3 +1,4 @@
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
/****************************************************************************** /******************************************************************************
* *
@ -48,6 +49,19 @@
namespace TCLAP { namespace TCLAP {
template<typename T> void DelPtr(T ptr)
{
delete ptr;
}
template<typename C> void ClearContainer(C &c)
{
typedef typename C::value_type value_type;
std::for_each(c.begin(), c.end(), DelPtr<value_type>);
c.clear();
}
/** /**
* The base class that manages the command line definition and passes * The base class that manages the command line definition and passes
* along the parsing to the appropriate Arg classes. * along the parsing to the appropriate Arg classes.
@ -137,14 +151,15 @@ class CmdLine : public CmdLineInterface
*/ */
void deleteOnExit(Visitor* ptr); void deleteOnExit(Visitor* ptr);
private: private:
/** /**
* Encapsulates the code common to the constructors (which is all * Encapsulates the code common to the constructors
* of it). * (which is all of it).
*/ */
void _constructor(); void _constructor();
/** /**
* Is set to true when a user sets the output object. We use this so * Is set to true when a user sets the output object. We use this so
* that we don't delete objects that are created outside of this lib. * that we don't delete objects that are created outside of this lib.
@ -266,9 +281,9 @@ class CmdLine : public CmdLineInterface
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
inline CmdLine::CmdLine(const std::string& m, inline CmdLine::CmdLine(const std::string& m,
char delim, char delim,
const std::string& v, const std::string& v,
bool help ) bool help )
: _progName("not_set_yet"), : _progName("not_set_yet"),
_message(m), _message(m),
_version(v), _version(v),
@ -282,21 +297,13 @@ inline CmdLine::CmdLine(const std::string& m,
inline CmdLine::~CmdLine() inline CmdLine::~CmdLine()
{ {
ArgListIterator argIter; ClearContainer(_argDeleteOnExitList);
VisitorListIterator visIter; ClearContainer(_visitorDeleteOnExitList);
for( argIter = _argDeleteOnExitList.begin(); if ( !_userSetOutput ) {
argIter != _argDeleteOnExitList.end();
++argIter)
delete *argIter;
for( visIter = _visitorDeleteOnExitList.begin();
visIter != _visitorDeleteOnExitList.end();
++visIter)
delete *visIter;
if ( !_userSetOutput )
delete _output; delete _output;
_output = 0;
}
} }
inline void CmdLine::_constructor() inline void CmdLine::_constructor()
@ -378,47 +385,63 @@ inline void CmdLine::add( Arg* a )
inline void CmdLine::parse(int argc, char** argv) inline void CmdLine::parse(int argc, char** argv)
{ {
bool shouldExit = false;
int estat = 0;
try { try {
_progName = argv[0];
_progName = argv[0]; // this step is necessary so that we have easy access to
// mutable strings.
std::vector<std::string> args;
for (int i = 1; i < argc; i++)
args.push_back(argv[i]);
// this step is necessary so that we have easy access to mutable strings. int requiredCount = 0;
std::vector<std::string> args;
for (int i = 1; i < argc; i++)
args.push_back(argv[i]);
int requiredCount = 0; for (int i = 0; static_cast<unsigned int>(i) < args.size(); i++) {
bool matched = false;
for (int i = 0; static_cast<unsigned int>(i) < args.size(); i++) for (ArgListIterator it = _argList.begin();
{ it != _argList.end(); it++) {
bool matched = false; if ( (*it)->processArg( &i, args ) )
for (ArgListIterator it = _argList.begin(); it != _argList.end(); it++) {
{ requiredCount += _xorHandler.check( *it );
if ( (*it)->processArg( &i, args ) ) matched = true;
{ break;
requiredCount += _xorHandler.check( *it ); }
matched = true;
break;
} }
}
// checks to see if the argument is an empty combined switch ... // checks to see if the argument is an empty combined
// and if so, then we've actually matched it // switch and if so, then we've actually matched it
if ( !matched && _emptyCombined( args[i] ) ) if ( !matched && _emptyCombined( args[i] ) )
matched = true; matched = true;
if ( !matched && !Arg::ignoreRest() ) if ( !matched && !Arg::ignoreRest() )
throw(CmdLineParseException("Couldn't find match for argument", throw(CmdLineParseException("Couldn't find match "
args[i])); "for argument",
} args[i]));
}
if ( requiredCount < _numRequired ) if ( requiredCount < _numRequired )
missingArgsException(); missingArgsException();
if ( requiredCount > _numRequired ) if ( requiredCount > _numRequired )
throw(CmdLineParseException("Too many arguments!")); throw(CmdLineParseException("Too many arguments!"));
} catch ( ArgException& e ) { _output->failure(*this,e); } } catch ( ArgException& e ) {
try {
_output->failure(*this,e);
} catch (ExitException &ee) {
estat = ee.getExitStatus();
shouldExit = true;
}
} catch (ExitException &ee) {
estat = ee.getExitStatus();
shouldExit = true;
}
if (shouldExit)
exit(estat);
} }
inline bool CmdLine::_emptyCombined(const std::string& s) inline bool CmdLine::_emptyCombined(const std::string& s)