From 3431fcfd784ebe563b87ea7ecb790d144aea4186 Mon Sep 17 00:00:00 2001 From: zeekec Date: Mon, 21 Jul 2008 17:20:57 +0000 Subject: [PATCH] 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. --- examples/Makefile.am | 5 ++-- examples/test18.cpp | 24 +++++++++++++++++ include/tclap/CmdLine.h | 58 +++++++++++++++++++++++++++++++++-------- tests/Makefile.am | 6 +++-- tests/test69.out | 1 + tests/test69.sh | 12 +++++++++ 6 files changed, 91 insertions(+), 15 deletions(-) create mode 100644 examples/test18.cpp create mode 100644 tests/test69.out create mode 100755 tests/test69.sh diff --git a/examples/Makefile.am b/examples/Makefile.am index 0cf8811..229337d 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -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 diff --git a/examples/test18.cpp b/examples/test18.cpp new file mode 100644 index 0000000..298db54 --- /dev/null +++ b/examples/test18.cpp @@ -0,0 +1,24 @@ +#include +#include +#include +#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; + } +} + diff --git a/include/tclap/CmdLine.h b/include/tclap/CmdLine.h index a3e6ad3..d215d4c 100644 --- a/include/tclap/CmdLine.h +++ b/include/tclap/CmdLine.h @@ -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& 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 args; for (int i = 0; i < argc; i++) args.push_back(argv[i]); @@ -416,7 +437,7 @@ inline void CmdLine::parse(std::vector& args) for (int i = 0; static_cast(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& 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 /////////////////////////////////////////////////////////////////////////////// diff --git a/tests/Makefile.am b/tests/Makefile.am index 31d3ae0..4536856 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -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 diff --git a/tests/test69.out b/tests/test69.out new file mode 100644 index 0000000..a26b21e --- /dev/null +++ b/tests/test69.out @@ -0,0 +1 @@ +error: Couldn't find match for argument for arg Argument: --bob diff --git a/tests/test69.sh b/tests/test69.sh new file mode 100755 index 0000000..843b9ce --- /dev/null +++ b/tests/test69.sh @@ -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 +