# HG changeset patch
# User Alpar Juttner <alpar@cs.elte.hu>
# Date 1266171835 -3600
# Node ID c2ff0a365245e31db53ee51bce5280d6d3061688
# Parent cc9e0c15d7477a877efb6ee9f299cff19b755314
ArgParser can throw exception instead of exit(1) (#332)
diff --git a/demo/arg_parser_demo.cc b/demo/arg_parser_demo.cc
|
a
|
b
|
|
| 65 | 65 | ap.other("infile", "The input file.") |
| 66 | 66 | .other("..."); |
| 67 | 67 | |
| | 68 | // Throw an exception when problems occurs. The default behavior is to |
| | 69 | // exit(1) on these cases, but this makes Valgrind falsely warn |
| | 70 | // about memory leaks. |
| | 71 | ap.throwOnProblems(); |
| | 72 | |
| 68 | 73 | // Perform the parsing process |
| 69 | 74 | // (in case of any error it terminates the program) |
| 70 | | ap.parse(); |
| | 75 | // The try {} construct is necessary only if the ap.trowOnProblems() |
| | 76 | // setting is in use. |
| | 77 | try { |
| | 78 | ap.parse(); |
| | 79 | } catch (ArgParserException &) { return 1; } |
| 71 | 80 | |
| 72 | 81 | // Check each option if it has been given and print its value |
| 73 | 82 | std::cout << "Parameters of '" << ap.commandName() << "':\n"; |
diff --git a/lemon/arg_parser.cc b/lemon/arg_parser.cc
|
a
|
b
|
|
| 20 | 20 | |
| 21 | 21 | namespace lemon { |
| 22 | 22 | |
| | 23 | void ArgParser::_terminate(ArgParserException::Reason reason) const |
| | 24 | { |
| | 25 | if(_exit_on_problems) |
| | 26 | exit(1); |
| | 27 | else throw(ArgParserException(reason)); |
| | 28 | } |
| | 29 | |
| | 30 | |
| 23 | 31 | void ArgParser::_showHelp(void *p) |
| 24 | 32 | { |
| 25 | 33 | (static_cast<ArgParser*>(p))->showHelp(); |
| 26 | | exit(1); |
| | 34 | (static_cast<ArgParser*>(p))->_terminate(ArgParserException::HELP); |
| 27 | 35 | } |
| 28 | 36 | |
| 29 | 37 | ArgParser::ArgParser(int argc, const char * const *argv) |
| 30 | | :_argc(argc), _argv(argv), _command_name(argv[0]) { |
| | 38 | :_argc(argc), _argv(argv), _command_name(argv[0]), |
| | 39 | _exit_on_problems(true) { |
| 31 | 40 | funcOption("-help","Print a short help message",_showHelp,this); |
| 32 | 41 | synonym("help","-help"); |
| 33 | 42 | synonym("h","-help"); |
| … |
… |
|
| 342 | 351 | for(std::vector<OtherArg>::const_iterator i=_others_help.begin(); |
| 343 | 352 | i!=_others_help.end();++i) showHelp(i); |
| 344 | 353 | for(Opts::const_iterator i=_opts.begin();i!=_opts.end();++i) showHelp(i); |
| 345 | | exit(1); |
| | 354 | _terminate(ArgParserException::HELP); |
| 346 | 355 | } |
| 347 | 356 | |
| 348 | 357 | |
| … |
… |
|
| 351 | 360 | std::cerr << "\nUnknown option: " << arg << "\n"; |
| 352 | 361 | std::cerr << "\nType '" << _command_name << |
| 353 | 362 | " --help' to obtain a short summary on the usage.\n\n"; |
| 354 | | exit(1); |
| | 363 | _terminate(ArgParserException::UNKNOWN_OPT); |
| 355 | 364 | } |
| 356 | 365 | |
| 357 | 366 | void ArgParser::requiresValue(std::string arg, OptType t) const |
| … |
… |
|
| 414 | 423 | if(!ok) { |
| 415 | 424 | std::cerr << "\nType '" << _command_name << |
| 416 | 425 | " --help' to obtain a short summary on the usage.\n\n"; |
| 417 | | exit(1); |
| | 426 | _terminate(ArgParserException::INVALID_OPT); |
| 418 | 427 | } |
| 419 | 428 | } |
| 420 | 429 | |
diff --git a/lemon/arg_parser.h b/lemon/arg_parser.h
|
a
|
b
|
|
| 34 | 34 | |
| 35 | 35 | namespace lemon { |
| 36 | 36 | |
| | 37 | ///Exception used by ArgParser |
| | 38 | class ArgParserException : public Exception { |
| | 39 | public: |
| | 40 | enum Reason { |
| | 41 | HELP, /// <tt>--help</tt> option was given |
| | 42 | UNKNOWN_OPT, /// Unknown option was given |
| | 43 | INVALID_OPT /// Invalid combination of options |
| | 44 | }; |
| | 45 | |
| | 46 | private: |
| | 47 | Reason _reason; |
| | 48 | |
| | 49 | public: |
| | 50 | ///Constructor |
| | 51 | ArgParserException(Reason r) throw() : _reason(r) {} |
| | 52 | ///Virtual destructor |
| | 53 | virtual ~ArgParserException() throw() {} |
| | 54 | ///A short description of the exception |
| | 55 | virtual const char* what() const throw() { |
| | 56 | switch(_reason) |
| | 57 | { |
| | 58 | case HELP: |
| | 59 | return "lemon::ArgParseException: ask for help"; |
| | 60 | break; |
| | 61 | case UNKNOWN_OPT: |
| | 62 | return "lemon::ArgParseException: unknown option"; |
| | 63 | break; |
| | 64 | case INVALID_OPT: |
| | 65 | return "lemon::ArgParseException: invalid combination of options"; |
| | 66 | break; |
| | 67 | } |
| | 68 | return ""; |
| | 69 | } |
| | 70 | ///Return the reason for the failure |
| | 71 | Reason reason() const {return _reason; } |
| | 72 | }; |
| | 73 | |
| | 74 | |
| 37 | 75 | ///Command line arguments parser |
| 38 | 76 | |
| 39 | 77 | ///\ingroup misc |
| … |
… |
|
| 103 | 141 | std::vector<std::string> _file_args; |
| 104 | 142 | std::string _command_name; |
| 105 | 143 | |
| 106 | | |
| | 144 | |
| 107 | 145 | private: |
| 108 | 146 | //Bind a function to an option. |
| 109 | 147 | |
| … |
… |
|
| 116 | 154 | const std::string &help, |
| 117 | 155 | void (*func)(void *),void *data); |
| 118 | 156 | |
| | 157 | bool _exit_on_problems; |
| | 158 | |
| | 159 | void _terminate(ArgParserException::Reason reason) const; |
| | 160 | |
| 119 | 161 | public: |
| 120 | 162 | |
| 121 | 163 | ///Constructor |
| … |
… |
|
| 380 | 422 | ///not starting with a '-' character. |
| 381 | 423 | const std::vector<std::string> &files() const { return _file_args; } |
| 382 | 424 | |
| | 425 | ///Throw instead of exit in case of problems |
| | 426 | void throwOnProblems() |
| | 427 | { |
| | 428 | _exit_on_problems=false; |
| | 429 | } |
| 383 | 430 | }; |
| 384 | 431 | } |
| 385 | 432 | |