mirror of
https://github.com/cuberite/TCLAP.git
synced 2025-09-08 20:00:04 -04:00
Catch ExitException and exit. This allows all resources used during
parsing to be released, bug 1662188.
This commit is contained in:
parent
0953ea9976
commit
e0a835388b
@ -1,3 +1,4 @@
|
||||
// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
@ -48,6 +49,19 @@
|
||||
|
||||
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
|
||||
* along the parsing to the appropriate Arg classes.
|
||||
@ -137,14 +151,15 @@ class CmdLine : public CmdLineInterface
|
||||
*/
|
||||
void deleteOnExit(Visitor* ptr);
|
||||
|
||||
private:
|
||||
private:
|
||||
|
||||
/**
|
||||
* Encapsulates the code common to the constructors (which is all
|
||||
* of it).
|
||||
* Encapsulates the code common to the constructors
|
||||
* (which is all of it).
|
||||
*/
|
||||
void _constructor();
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@ -266,9 +281,9 @@ class CmdLine : public CmdLineInterface
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline CmdLine::CmdLine(const std::string& m,
|
||||
char delim,
|
||||
const std::string& v,
|
||||
bool help )
|
||||
char delim,
|
||||
const std::string& v,
|
||||
bool help )
|
||||
: _progName("not_set_yet"),
|
||||
_message(m),
|
||||
_version(v),
|
||||
@ -282,21 +297,13 @@ inline CmdLine::CmdLine(const std::string& m,
|
||||
|
||||
inline CmdLine::~CmdLine()
|
||||
{
|
||||
ArgListIterator argIter;
|
||||
VisitorListIterator visIter;
|
||||
|
||||
for( argIter = _argDeleteOnExitList.begin();
|
||||
argIter != _argDeleteOnExitList.end();
|
||||
++argIter)
|
||||
delete *argIter;
|
||||
|
||||
for( visIter = _visitorDeleteOnExitList.begin();
|
||||
visIter != _visitorDeleteOnExitList.end();
|
||||
++visIter)
|
||||
delete *visIter;
|
||||
|
||||
if ( !_userSetOutput )
|
||||
ClearContainer(_argDeleteOnExitList);
|
||||
ClearContainer(_visitorDeleteOnExitList);
|
||||
|
||||
if ( !_userSetOutput ) {
|
||||
delete _output;
|
||||
_output = 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline void CmdLine::_constructor()
|
||||
@ -378,47 +385,63 @@ inline void CmdLine::add( Arg* a )
|
||||
|
||||
inline void CmdLine::parse(int argc, char** argv)
|
||||
{
|
||||
bool shouldExit = false;
|
||||
int estat = 0;
|
||||
|
||||
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.
|
||||
std::vector<std::string> args;
|
||||
for (int i = 1; i < argc; i++)
|
||||
args.push_back(argv[i]);
|
||||
int requiredCount = 0;
|
||||
|
||||
int requiredCount = 0;
|
||||
|
||||
for (int i = 0; static_cast<unsigned int>(i) < args.size(); i++)
|
||||
{
|
||||
bool matched = false;
|
||||
for (ArgListIterator it = _argList.begin(); it != _argList.end(); it++)
|
||||
{
|
||||
if ( (*it)->processArg( &i, args ) )
|
||||
{
|
||||
requiredCount += _xorHandler.check( *it );
|
||||
matched = true;
|
||||
break;
|
||||
for (int i = 0; static_cast<unsigned int>(i) < args.size(); i++) {
|
||||
bool matched = false;
|
||||
for (ArgListIterator it = _argList.begin();
|
||||
it != _argList.end(); it++) {
|
||||
if ( (*it)->processArg( &i, args ) )
|
||||
{
|
||||
requiredCount += _xorHandler.check( *it );
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// checks to see if the argument is an empty combined switch ...
|
||||
// and if so, then we've actually matched it
|
||||
if ( !matched && _emptyCombined( args[i] ) )
|
||||
matched = true;
|
||||
// checks to see if the argument is an empty combined
|
||||
// switch and if so, then we've actually matched it
|
||||
if ( !matched && _emptyCombined( args[i] ) )
|
||||
matched = true;
|
||||
|
||||
if ( !matched && !Arg::ignoreRest() )
|
||||
throw(CmdLineParseException("Couldn't find match for argument",
|
||||
args[i]));
|
||||
}
|
||||
if ( !matched && !Arg::ignoreRest() )
|
||||
throw(CmdLineParseException("Couldn't find match "
|
||||
"for argument",
|
||||
args[i]));
|
||||
}
|
||||
|
||||
if ( requiredCount < _numRequired )
|
||||
missingArgsException();
|
||||
if ( requiredCount < _numRequired )
|
||||
missingArgsException();
|
||||
|
||||
if ( requiredCount > _numRequired )
|
||||
throw(CmdLineParseException("Too many arguments!"));
|
||||
if ( requiredCount > _numRequired )
|
||||
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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user