Compare commits

...

12 Commits

Author SHA1 Message Date
Beman Dawes
730b5f2169 Release 1.41.0
[SVN r57747]
2009-11-18 14:58:26 +00:00
Troy D. Straszheim
5820ee9f7f rm cmake from the release branch before it goes out broken. Policy dictates that you never commit to release, you commit to trunk and merge to release.
[SVN r56941]
2009-10-17 01:10:45 +00:00
Troy D. Straszheim
67ba23b8d9 Add basic copyright/license to keep cmake out of the inspection report
[SVN r55095]
2009-07-22 21:51:01 +00:00
Vladimir Prus
c3cb7cf05d Merge from trunk
[SVN r54884]
2009-07-11 12:00:18 +00:00
Jeremiah Willcock
bdbd3dfc42 Fixed almost all tab and min/max issues found by inspect tool
[SVN r53142]
2009-05-20 19:41:20 +00:00
Douglas Gregor
15c990b7af Fix CMake build of Program Options DLL tests
[SVN r52847]
2009-05-08 06:13:08 +00:00
Douglas Gregor
1a884cef74 Fix CMake test builds for ProgramOptions and Units libraries.
[SVN r52843]
2009-05-07 23:53:56 +00:00
Vladimir Prus
3c6401b19a Prevent multitoken options from eating tokens after '--' separator.
Thanks to Gevorg Voskanyan for the bug report and the testcase.


[SVN r52440]
2009-04-17 09:45:00 +00:00
Vladimir Prus
ed4847e0a7 Fix warnings
[SVN r52439]
2009-04-17 09:35:10 +00:00
Vladimir Prus
6eef67f5ba Merge from trunk
[SVN r52211]
2009-04-06 09:43:03 +00:00
Vladimir Prus
91d9cabb51 When processing value multitoken options, don't eat futher options.
Fixes #469.


[SVN r52154]
2009-04-03 13:42:29 +00:00
John Maddock
22e8d11888 Merge PDF build changes from Trunk.
[SVN r51417]
2009-02-23 18:39:32 +00:00
16 changed files with 171 additions and 90 deletions

View File

@@ -1,22 +0,0 @@
#----------------------------------------------------------------------------
# This file was automatically generated from the original CMakeLists.txt file
# Add a variable to hold the headers for the library
set (lib_headers
program_options.hpp
program_options
)
# Add a library target to the build system
boost_library_project(
program_options
SRCDIRS src
TESTDIRS test
HEADERS ${lib_headers}
# DOCDIRS
DESCRIPTION "Access to configuration data given on command line, in config files and other sources."
MODULARIZED
AUTHORS "Vladimir Prus <ghost -at- cs.msu.su>"
# MAINTAINERS
)

View File

@@ -5,6 +5,7 @@ toolset.using doxygen ;
boostbook program_option
: program_options.xml
: <implicit-dependency>autodoc
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html
;
doxygen autodoc

View File

@@ -77,7 +77,7 @@ int main(int ac, char* av[])
cout << "Listen port is " << portnum << "\n";
}
catch(exception& e)
catch(std::exception& e)
{
cout << e.what() << "\n";
return 1;

View File

@@ -94,7 +94,7 @@ int main(int ac, char* av[])
<< vm["magic"].as<magic_number>().n << "\"\n";
}
}
catch(exception& e)
catch(std::exception& e)
{
cout << e.what() << "\n";
}

View File

@@ -8,6 +8,8 @@
#include <boost/program_options/detail/convert.hpp>
#include <iterator>
namespace boost { namespace program_options {
namespace detail {

View File

@@ -55,13 +55,12 @@ namespace boost { namespace program_options {
{
static std::basic_string<charT> empty;
if (v.size() > 1)
throw validation_error("multiple values not allowed");
if (v.size() == 1)
boost::throw_exception(validation_error("multiple values not allowed"));
else if (v.size() == 1)
return v.front();
else if (allow_empty)
return empty;
else
throw validation_error("at least one value required");
else if (!allow_empty)
boost::throw_exception(validation_error("at least one value required"));
return empty;
}
/* Throws multiple_occurrences if 'value' is not empty. */

View File

@@ -41,7 +41,7 @@ namespace boost { namespace program_options {
add(const char* name, int max_count);
/** Returns the maximum number of positional options that can
be present. Can return numeric_limits<unsigned>::max() to
be present. Can return (numeric_limits<unsigned>::max)() to
indicate unlimited number. */
unsigned max_total_count() const;

View File

@@ -1,3 +0,0 @@
boost_module(program_options DEPENDS any bind smart_ptr tokenizer)
# bind is needed because of a dependency on boost/mem_fn.hpp

View File

@@ -1,5 +0,0 @@
boost_add_library(boost_program_options
cmdline.cpp config_file.cpp options_description.cpp parsers.cpp
variables_map.cpp value_semantic.cpp positional_options.cpp
utf8_codecvt_facet.cpp convert.cpp winmain.cpp
SHARED_COMPILE_FLAGS "-DBOOST_PROGRAM_OPTIONS_DYN_LINK=1")

View File

@@ -23,6 +23,7 @@
#include <cassert>
#include <cstring>
#include <cctype>
#include <climits>
#include <cstdio>
@@ -151,7 +152,7 @@ namespace boost { namespace program_options { namespace detail {
error = "style disallows all characters for short options";
if (error)
throw invalid_command_line_style(error);
boost::throw_exception(invalid_command_line_style(error));
// Need to check that if guessing and long disguise are enabled
// -f will mean the same as -foo
@@ -195,24 +196,24 @@ namespace boost { namespace program_options { namespace detail {
if (m_additional_parser)
style_parsers.push_back(
bind(&cmdline::handle_additional_parser, this, _1));
boost::bind(&cmdline::handle_additional_parser, this, _1));
if (m_style & allow_long)
style_parsers.push_back(
bind(&cmdline::parse_long_option, this, _1));
boost::bind(&cmdline::parse_long_option, this, _1));
if ((m_style & allow_long_disguise))
style_parsers.push_back(
bind(&cmdline::parse_disguised_long_option, this, _1));
boost::bind(&cmdline::parse_disguised_long_option, this, _1));
if ((m_style & allow_short) && (m_style & allow_dash_for_short))
style_parsers.push_back(
bind(&cmdline::parse_short_option, this, _1));
boost::bind(&cmdline::parse_short_option, this, _1));
if ((m_style & allow_short) && (m_style & allow_slash_for_short))
style_parsers.push_back(bind(&cmdline::parse_dos_option, this, _1));
style_parsers.push_back(boost::bind(&cmdline::parse_dos_option, this, _1));
style_parsers.push_back(bind(&cmdline::parse_terminator, this, _1));
style_parsers.push_back(boost::bind(&cmdline::parse_terminator, this, _1));
vector<option> result;
while(!args.empty())
@@ -254,6 +255,62 @@ namespace boost { namespace program_options { namespace detail {
}
}
/* If an key option is followed by a positional option,
can can consume more tokens (e.g. it's multitoke option),
give those tokens to it. */
vector<option> result2;
for (unsigned i = 0; i < result.size(); ++i)
{
result2.push_back(result[i]);
option& opt = result2.back();
if (opt.string_key.empty())
continue;
const option_description* xd =
m_desc->find_nothrow(opt.string_key,
(m_style & allow_guessing));
if (!xd)
continue;
unsigned min_tokens = xd->semantic()->min_tokens();
unsigned max_tokens = xd->semantic()->max_tokens();
if (min_tokens < max_tokens && opt.value.size() < max_tokens)
{
// This option may grab some more tokens.
// We only allow to grab tokens that are not already
// recognized as key options.
int can_take_more = max_tokens - opt.value.size();
unsigned j = i+1;
for (; can_take_more && j < result.size(); --can_take_more, ++j)
{
option& opt2 = result[j];
if (!opt2.string_key.empty())
break;
if (opt2.position_key == INT_MAX)
{
// We use INT_MAX to mark positional options that
// were found after the '--' terminator and therefore
// should stay positional forever.
break;
}
assert(opt2.value.size() == 1);
opt.value.push_back(opt2.value[0]);
assert(opt2.original_tokens.size() == 1);
opt.original_tokens.push_back(opt2.original_tokens[0]);
}
i = j-1;
}
}
result.swap(result2);
// Assign position keys to positional options.
int position_key = 0;
for(unsigned i = 0; i < result.size(); ++i) {
@@ -269,8 +326,8 @@ namespace boost { namespace program_options { namespace detail {
if (opt.position_key != -1) {
if (position >= m_positional->max_total_count())
{
throw too_many_positional_options_error(
"too many positional options");
boost::throw_exception(too_many_positional_options_error(
"too many positional options"));
}
opt.string_key = m_positional->name_for_position(position);
++position;
@@ -323,22 +380,25 @@ namespace boost { namespace program_options { namespace detail {
if (present_tokens >= min_tokens)
{
if (!opt.value.empty() && max_tokens == 0) {
throw invalid_command_line_syntax(opt.string_key,
invalid_command_line_syntax::extra_parameter);
boost::throw_exception(invalid_command_line_syntax(opt.string_key,
invalid_command_line_syntax::extra_parameter));
}
max_tokens -= opt.value.size();
// If an option wants, at minimum, N tokens, we grab them
// there and don't care if they look syntactically like an
// option.
// A value is optional if min_tokens == 0, but max_tokens > 0.
// If a value is optional, it must appear in opt.value (because
// it was 'adjacent'. Otherwise, remove the expectation of a
// non-adjacent value. (For now, we just check max_tokens == 1,
// as there is no current support for max_tokens>1)
if (min_tokens == 0 && max_tokens == 1 && opt.value.empty())
--max_tokens;
if (opt.value.size() <= min_tokens)
{
min_tokens -= opt.value.size();
}
else
{
min_tokens = 0;
}
// Everything's OK, move the values to the result.
for(;!other_tokens.empty() && max_tokens--; ) {
for(;!other_tokens.empty() && min_tokens--; ) {
opt.value.push_back(other_tokens[0]);
opt.original_tokens.push_back(other_tokens[0]);
other_tokens.erase(other_tokens.begin());
@@ -346,8 +406,8 @@ namespace boost { namespace program_options { namespace detail {
}
else
{
throw invalid_command_line_syntax(opt.string_key,
invalid_command_line_syntax::missing_parameter);
boost::throw_exception(invalid_command_line_syntax(opt.string_key,
invalid_command_line_syntax::missing_parameter));
}
}
@@ -367,8 +427,8 @@ namespace boost { namespace program_options { namespace detail {
name = tok.substr(2, p-2);
adjacent = tok.substr(p+1);
if (adjacent.empty())
throw invalid_command_line_syntax(name,
invalid_command_line_syntax::empty_adjacent_parameter);
boost::throw_exception( invalid_command_line_syntax(name,
invalid_command_line_syntax::empty_adjacent_parameter));
}
else
{
@@ -492,6 +552,8 @@ namespace boost { namespace program_options { namespace detail {
{
option opt;
opt.value.push_back(args[i]);
opt.original_tokens.push_back(args[i]);
opt.position_key = INT_MAX;
result.push_back(opt);
}
args.clear();

View File

@@ -67,10 +67,16 @@ namespace boost { namespace program_options {
woption result;
result.string_key = opt.string_key;
result.position_key = opt.position_key;
result.unregistered = opt.unregistered;
std::transform(opt.value.begin(), opt.value.end(),
back_inserter(result.value),
bind(from_utf8, _1));
boost::bind(from_utf8, _1));
std::transform(opt.original_tokens.begin(),
opt.original_tokens.end(),
back_inserter(result.original_tokens),
boost::bind(from_utf8, _1));
return result;
}
}

View File

@@ -74,11 +74,13 @@ namespace boost { namespace program_options {
try {
d.semantic()->parse(v.value(), options.options[i].value, utf8);
}
#ifndef BOOST_NO_EXCEPTIONS
catch(validation_error& e)
{
e.set_option_name(name);
throw;
}
#endif
v.m_value_semantic = d.semantic();
// The option is not composing, and the value is explicitly
@@ -133,7 +135,16 @@ namespace boost { namespace program_options {
k != vm.end();
++k)
{
k->second.m_value_semantic->notify(k->second.value());
/* Users might wish to use variables_map to store their own values
that are not parsed, and therefore will not have value_semantics
defined. Do no crash on such values. In multi-module programs,
one module might add custom values, and the 'notify' function
will be called after that, so we check that value_sematics is
not NULL. See:
https://svn.boost.org/trac/boost/ticket/2782
*/
if (k->second.m_value_semantic)
k->second.m_value_semantic->notify(k->second.value());
}
}

View File

@@ -1,21 +0,0 @@
boost_additional_test_dependencies(program_options BOOST_DEPENDS test)
set(PROGRAM_OPTIONS_LIBRARIES
boost_program_options
boost_test_exec_monitor)
macro(program_options_test_run TESTNAME)
boost_test_run(${TESTNAME}
DEPENDS boost_program_options boost_test_exec_monitor STATIC)
boost_test_run("${TESTNAME}_dll"
"${TESTNAME}.cpp"
DEPENDS boost_program_options boost_test_exec_monitor-static SHARED)
endmacro(program_options_test_run)
program_options_test_run(options_description_test)
program_options_test_run(parsers_test)
program_options_test_run(variable_map_test)
program_options_test_run(cmdline_test)
program_options_test_run(positional_options_test)
program_options_test_run(unicode_test)
program_options_test_run(winmain)

View File

@@ -146,8 +146,52 @@ void test_command_line()
variables_map vm;
po::store(po::parse_command_line(3, cmdline4, desc2), vm);
char* cmdline5[] = {"", "-p7", "-o", "1", "2", "3", "-x8"};
options_description desc3;
desc3.add_options()
(",p", po::value<string>())
(",o", po::value<string>()->multitoken())
(",x", po::value<string>())
;
vector<option> a5 =
parse_command_line(7, cmdline5, desc3, 0, additional_parser).options;
BOOST_CHECK_EQUAL(a5.size(), 3u);
check_value(a5[0], "-p", "7");
BOOST_REQUIRE(a5[1].value.size() == 3);
BOOST_CHECK_EQUAL(a5[1].string_key, "-o");
BOOST_CHECK_EQUAL(a5[1].value[0], "1");
BOOST_CHECK_EQUAL(a5[1].value[1], "2");
BOOST_CHECK_EQUAL(a5[1].value[2], "3");
check_value(a5[2], "-x", "8");
po::options_description desc4( "" );
desc4.add_options()
( "multitoken,m",
po::value< std::vector< std::string > >()->multitoken(),
"values"
)
( "file",
po::value< std::string >(),
"the file to process"
)
;
po::positional_options_description p;
p.add( "file", 1 );
char* cmdline6[] = {"", "-m", "token1", "token2", "--", "some_file"};
vector<option> a6 =
command_line_parser(6, cmdline6).options(desc4).positional(p)
.run().options;
BOOST_CHECK_EQUAL(a6.size(), 2u);
BOOST_REQUIRE(a6[0].value.size() == 2);
BOOST_CHECK_EQUAL(a6[0].string_key, "multitoken");
BOOST_CHECK_EQUAL(a6[0].value[0], "token1");
BOOST_CHECK_EQUAL(a6[0].value[1], "token2");
BOOST_CHECK_EQUAL(a6[1].string_key, "file");
BOOST_REQUIRE(a6[1].value.size() == 1);
BOOST_CHECK_EQUAL(a6[1].value[0], "some_file");
}
void test_config_file()

View File

@@ -34,9 +34,13 @@ void test_unicode_to_unicode()
args.push_back(L"--foo=\x044F");
variables_map vm;
store(wcommand_line_parser(args).options(desc).run(), vm);
basic_parsed_options<wchar_t> parsed =
wcommand_line_parser(args).options(desc).run();
store(parsed, vm);
BOOST_CHECK(vm["foo"].as<wstring>() == L"\x044F");
BOOST_CHECK(vm["foo"].as<wstring>() == L"\x044F");
BOOST_CHECK(parsed.options[0].original_tokens.size() == 1);
BOOST_CHECK(parsed.options[0].original_tokens[0] == L"--foo=\x044F");
}
// Test that unicode input is property converted into

View File

@@ -96,8 +96,11 @@ void test_variable_map()
("imp", po::value<int>()->implicit_value(100))
("iim", po::value<int>()->implicit_value(200)->default_value(201))
("mmp,m", po::value<int>()->implicit_value(123)->default_value(124))
("foo", po::value<int>())
;
char* cmdline6_[] = { "--imp=1", "-m" };
/* The -m option is implicit. It does not have value in inside the token,
and we should not grab the next token. */
char* cmdline6_[] = { "--imp=1", "-m", "--foo=1" };
vector<string> cmdline6 = sv(cmdline6_,
sizeof(cmdline6_)/sizeof(cmdline6_[0]));
parsed_options a6 = command_line_parser(cmdline6).options(desc3).run();
@@ -105,7 +108,7 @@ void test_variable_map()
variables_map vm4;
store(a6, vm4);
notify(vm4);
BOOST_REQUIRE(vm4.size() == 3);
BOOST_REQUIRE(vm4.size() == 4);
BOOST_CHECK(vm4["imp"].as<int>() == 1);
BOOST_CHECK(vm4["iim"].as<int>() == 201);
BOOST_CHECK(vm4["mmp"].as<int>() == 123);