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 \ noinst_PROGRAMS = test1 test2 test3 test4 test5 test6 test7 test8 test9 \
test10 test11 test12 test13 test14 test15 test16 \ test10 test11 test12 test13 test14 test15 test16 \
test17 test17 test18
test1_SOURCES = test1.cpp test1_SOURCES = test1.cpp
test2_SOURCES = test2.cpp test2_SOURCES = test2.cpp
@ -20,7 +20,8 @@ test14_SOURCES = test14.cpp
test15_SOURCES = test15.cpp test15_SOURCES = test15.cpp
test16_SOURCES = test16.cpp test16_SOURCES = test16.cpp
test17_SOURCES = test17.cpp test17-a.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 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; CmdLineOutput* _output;
/**
* Should CmdLine handle parsing exceptions internally?
*/
bool _handleExceptions;
/** /**
* Throws an exception listing the missing args. * Throws an exception listing the missing args.
*/ */
@ -232,7 +237,7 @@ private:
/** /**
* Parses the command line. * 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. * args[0] is still the program name.
*/ */
void parse(std::vector<std::string>& args); void parse(std::vector<std::string>& args);
@ -281,6 +286,21 @@ private:
* *
*/ */
bool hasHelpAndVersion(); 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), _version(v),
_numRequired(0), _numRequired(0),
_delimiter(delim), _delimiter(delim),
_handleExceptions(true),
_userSetOutput(false), _userSetOutput(false),
_helpAndVersion(help) _helpAndVersion(help)
{ {
@ -307,7 +328,7 @@ inline CmdLine::~CmdLine()
{ {
ClearContainer(_argDeleteOnExitList); ClearContainer(_argDeleteOnExitList);
ClearContainer(_visitorDeleteOnExitList); ClearContainer(_visitorDeleteOnExitList);
if ( !_userSetOutput ) { if ( !_userSetOutput ) {
delete _output; delete _output;
_output = 0; _output = 0;
@ -395,7 +416,7 @@ inline void CmdLine::add( Arg* a )
inline void CmdLine::parse(int argc, const char * const * argv) inline void CmdLine::parse(int argc, const char * const * argv)
{ {
// this step is necessary so that we have easy access to // this step is necessary so that we have easy access to
// mutable strings. // mutable strings.
std::vector<std::string> args; std::vector<std::string> args;
for (int i = 0; i < argc; i++) for (int i = 0; i < argc; i++)
args.push_back(argv[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++) { for (int i = 0; static_cast<unsigned int>(i) < args.size(); i++) {
bool matched = false; bool matched = false;
for (ArgListIterator it = _argList.begin(); for (ArgListIterator it = _argList.begin();
it != _argList.end(); it++) { it != _argList.end(); it++) {
if ( (*it)->processArg( &i, args ) ) if ( (*it)->processArg( &i, args ) )
{ {
@ -443,14 +464,19 @@ inline void CmdLine::parse(std::vector<std::string>& args)
if ( requiredCount > _numRequired ) if ( requiredCount > _numRequired )
throw(CmdLineParseException("Too many arguments!")); throw(CmdLineParseException("Too many arguments!"));
} catch ( ArgException& e ) { } catch ( ArgException& e ) {
try { // If we're not handling the exceptions, rethrow.
_output->failure(*this,e); if ( !_handleExceptions) {
} catch ( ExitException &ee ) { throw;
}
try {
_output->failure(*this,e);
} catch ( ExitException &ee ) {
estat = ee.getExitStatus(); estat = ee.getExitStatus();
shouldExit = true; shouldExit = true;
} }
} catch (ExitException &ee) { } catch (ExitException &ee) {
estat = ee.getExitStatus(); estat = ee.getExitStatus();
shouldExit = true; shouldExit = true;
} }
@ -471,7 +497,7 @@ inline bool CmdLine::_emptyCombined(const std::string& s)
return true; return true;
} }
inline void CmdLine::missingArgsException() inline void CmdLine::missingArgsException()
{ {
int count = 0; int count = 0;
@ -486,7 +512,7 @@ inline void CmdLine::missingArgsException()
} }
} }
missingArgList = missingArgList.substr(0,missingArgList.length()-2); missingArgList = missingArgList.substr(0,missingArgList.length()-2);
std::string msg; std::string msg;
if ( count > 1 ) if ( count > 1 )
msg = "Required arguments missing: "; msg = "Required arguments missing: ";
@ -554,6 +580,16 @@ inline bool CmdLine::hasHelpAndVersion()
return _helpAndVersion; return _helpAndVersion;
} }
inline void CmdLine::setExceptionHandling(const bool state)
{
_handleExceptions = state;
}
inline bool CmdLine::getExceptionHandling() const
{
return _handleExceptions;
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
//End CmdLine.cpp //End CmdLine.cpp
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View File

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