# 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 | |