mirror of
https://github.com/cuberite/TCLAP.git
synced 2025-09-10 12:49:08 -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 {
|
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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user