// Copyright Vladimir Prus 2002-2004. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt // or copy at http://www.boost.org/LICENSE_1_0.txt) #include #include #include using namespace boost::program_options; using boost::program_options::detail::cmdline; #include #include #include #include using namespace std; #include "minitest.hpp" /* To facilitate testing, declare a number of error codes. Otherwise, we'd have to specify the type of exception that should be thrown. */ const int s_success = 0; const int s_unknown_option = 1; const int s_ambiguous_option = 2; const int s_long_not_allowed = 3; const int s_long_adjacent_not_allowed = 4; const int s_short_adjacent_not_allowed = 5; const int s_empty_adjacent_parameter = 6; const int s_missing_parameter = 7; const int s_extra_parameter = 8; const int s_unrecognized_line = 9; int translate_syntax_error_kind(invalid_command_line_syntax::kind_t k) { invalid_command_line_syntax::kind_t table[] = { invalid_command_line_syntax::long_not_allowed, invalid_command_line_syntax::long_adjacent_not_allowed, invalid_command_line_syntax::short_adjacent_not_allowed, invalid_command_line_syntax::empty_adjacent_parameter, invalid_command_line_syntax::missing_parameter, invalid_command_line_syntax::extra_parameter, invalid_command_line_syntax::unrecognized_line }; invalid_command_line_syntax::kind_t *b, *e, *i; b = table; e = table + sizeof(table)/sizeof(table[0]); i = std::find(b, e, k); assert(i != e); return std::distance(b, i) + 3; } struct test_case { const char* input; int expected_status; const char* expected_result; }; /* Parses the syntax description in 'syntax' and initialized 'cmd' accordingly' The "boost::program_options" in parameter type is needed because CW9 has std::detail and it causes an ambiguity. */ void apply_syntax(options_description& desc, const char* syntax) { string s; stringstream ss; ss << syntax; while(ss >> s) { value_semantic* v = 0; if (*(s.end()-1) == '=') { v = value(); s.resize(s.size()-1); } else if (*(s.end()-1) == '?') { v = value()->implicit_value("default"); s.resize(s.size()-1); } else if (*(s.end()-1) == '*') { v = value >()->multitoken(); s.resize(s.size()-1); } else if (*(s.end()-1) == '+') { v = value >()->multitoken(); s.resize(s.size()-1); } if (v) { desc.add_options() (s.c_str(), v, ""); } else { desc.add_options() (s.c_str(), ""); } } } void test_cmdline(const char* syntax, command_line_style::style_t style, const test_case* cases) { for (int i = 0; cases[i].input; ++i) { // Parse input vector xinput; { string s; stringstream ss; ss << cases[i].input; while (ss >> s) { xinput.push_back(s); } } options_description desc; apply_syntax(desc, syntax); cmdline cmd(xinput); cmd.style(style); cmd.set_options_description(desc); string result; int status = 0; try { vector