Allow internal handling of parse errors to be turned off.

This allows exceptions for parse errors to be propagated to the caller.  Exiting
the program in parse is a bad idea generally, as we have no way of knowing what
cleanup needs to be done in the main program.
This commit is contained in:
zeekec 2008-07-21 17:20:57 +00:00
parent 9a32ab6294
commit 3431fcfd78
6 changed files with 91 additions and 15 deletions

View File

@ -1,7 +1,7 @@
noinst_PROGRAMS = test1 test2 test3 test4 test5 test6 test7 test8 test9 \
test10 test11 test12 test13 test14 test15 test16 \
test17
test17 test18
test1_SOURCES = test1.cpp
test2_SOURCES = test2.cpp
@ -20,7 +20,8 @@ test14_SOURCES = test14.cpp
test15_SOURCES = test15.cpp
test16_SOURCES = test16.cpp
test17_SOURCES = test17.cpp test17-a.cpp
test18_SOURCES = test18.cpp
INCLUDES = -I$(top_srcdir)/include
AM_CPPFLAGS = -I$(top_srcdir)/include
AM_CXXFLAGS = -Wall -Wextra

24
examples/test18.cpp Normal file
View File

@ -0,0 +1,24 @@
#include <string>
#include <iostream>
#include <algorithm>
#include "tclap/CmdLine.h"
using namespace TCLAP;
using namespace std;
int main(int argc, char** argv)
{
try {
CmdLine cmd("Command description message", ' ', "0.9", false);
cmd.setExceptionHandling(false);
cmd.parse(argc, argv);
} catch (ArgException &e) { // catch any exceptions
cerr << "error: " << e.error() << " for arg " << e.argId() << endl;
return 1;
}
}

View File

@ -129,6 +129,11 @@ class CmdLine : public CmdLineInterface
*/
CmdLineOutput* _output;
/**
* Should CmdLine handle parsing exceptions internally?
*/
bool _handleExceptions;
/**
* Throws an exception listing the missing args.
*/
@ -232,7 +237,7 @@ private:
/**
* Parses the command line.
* \param args - A vector of strings representing the args.
* \param args - A vector of strings representing the args.
* args[0] is still the program name.
*/
void parse(std::vector<std::string>& args);
@ -281,6 +286,21 @@ private:
*
*/
bool hasHelpAndVersion();
/**
* Disables or enables CmdLine's internal parsing exception handling.
*
* @param state Should CmdLine handle parsing exceptions internally?
*/
void setExceptionHandling(const bool state);
/**
* Returns the current state of the internal exception handling.
*
* @retval true Parsing exceptions are handled internally.
* @retval false Parsing exceptions are propagated to the caller.
*/
bool getExceptionHandling() const;
};
@ -297,6 +317,7 @@ inline CmdLine::CmdLine(const std::string& m,
_version(v),
_numRequired(0),
_delimiter(delim),
_handleExceptions(true),
_userSetOutput(false),
_helpAndVersion(help)
{
@ -307,7 +328,7 @@ inline CmdLine::~CmdLine()
{
ClearContainer(_argDeleteOnExitList);
ClearContainer(_visitorDeleteOnExitList);
if ( !_userSetOutput ) {
delete _output;
_output = 0;
@ -395,7 +416,7 @@ inline void CmdLine::add( Arg* a )
inline void CmdLine::parse(int argc, const char * const * argv)
{
// this step is necessary so that we have easy access to
// mutable strings.
// mutable strings.
std::vector<std::string> args;
for (int i = 0; i < argc; i++)
args.push_back(argv[i]);
@ -416,7 +437,7 @@ inline void CmdLine::parse(std::vector<std::string>& args)
for (int i = 0; static_cast<unsigned int>(i) < args.size(); i++) {
bool matched = false;
for (ArgListIterator it = _argList.begin();
for (ArgListIterator it = _argList.begin();
it != _argList.end(); it++) {
if ( (*it)->processArg( &i, args ) )
{
@ -443,14 +464,19 @@ inline void CmdLine::parse(std::vector<std::string>& args)
if ( requiredCount > _numRequired )
throw(CmdLineParseException("Too many arguments!"));
} catch ( ArgException& e ) {
try {
_output->failure(*this,e);
} catch ( ExitException &ee ) {
} catch ( ArgException& e ) {
// If we're not handling the exceptions, rethrow.
if ( !_handleExceptions) {
throw;
}
try {
_output->failure(*this,e);
} catch ( ExitException &ee ) {
estat = ee.getExitStatus();
shouldExit = true;
}
} catch (ExitException &ee) {
} catch (ExitException &ee) {
estat = ee.getExitStatus();
shouldExit = true;
}
@ -471,7 +497,7 @@ inline bool CmdLine::_emptyCombined(const std::string& s)
return true;
}
inline void CmdLine::missingArgsException()
inline void CmdLine::missingArgsException()
{
int count = 0;
@ -486,7 +512,7 @@ inline void CmdLine::missingArgsException()
}
}
missingArgList = missingArgList.substr(0,missingArgList.length()-2);
std::string msg;
if ( count > 1 )
msg = "Required arguments missing: ";
@ -554,6 +580,16 @@ inline bool CmdLine::hasHelpAndVersion()
return _helpAndVersion;
}
inline void CmdLine::setExceptionHandling(const bool state)
{
_handleExceptions = state;
}
inline bool CmdLine::getExceptionHandling() const
{
return _handleExceptions;
}
///////////////////////////////////////////////////////////////////////////////
//End CmdLine.cpp
///////////////////////////////////////////////////////////////////////////////

View File

@ -67,7 +67,8 @@ TESTS = test1.sh \
test65.sh \
test66.sh \
test67.sh \
test68.sh
test68.sh \
test69.sh
EXTRA_DIST = $(TESTS) \
test1.out \
@ -137,6 +138,7 @@ EXTRA_DIST = $(TESTS) \
test65.out \
test66.out \
test67.out \
test68.out
test68.out \
test69.out
CLEANFILES = tmp.out

1
tests/test69.out Normal file
View File

@ -0,0 +1 @@
error: Couldn't find match for argument for arg Argument: --bob

12
tests/test69.sh Executable file
View File

@ -0,0 +1,12 @@
#!/bin/sh
# Checks that parsing exceptions are properly
# propagated to the caller.
../examples/test18 --bob > tmp.out 2>&1
if cmp -s tmp.out $srcdir/test69.out; then
exit 0
else
exit 1
fi