Compare commits

..

4 Commits

Author SHA1 Message Date
nobody
c8f95dbda3 This commit was manufactured by cvs2svn to create tag
'Version_1_33_1'.

[SVN r31916]
2005-12-05 14:04:06 +00:00
Vladimir Prus
81aff160d0 Merge fixes for unregisted options and inaccessible 'style_parser' method
from trunk to RC_1_33_0.


[SVN r31615]
2005-11-10 08:46:56 +00:00
Dave Abrahams
705e79b5ee merged from trunk
[SVN r30560]
2005-08-12 19:50:06 +00:00
nobody
3ae92db179 This commit was manufactured by cvs2svn to create branch 'RC_1_33_0'.
[SVN r30300]
2005-07-28 18:22:24 +00:00
26 changed files with 267 additions and 336 deletions

49
build/Jamfile Normal file
View File

@@ -0,0 +1,49 @@
subproject libs/program_options/build ;
SOURCES = cmdline config_file options_description parsers variables_map
value_semantic positional_options utf8_codecvt_facet convert
winmain
;
lib boost_program_options
: ../src/$(SOURCES).cpp
: # build requirements
[ common-names ] # magic for install and auto-link features
<include>$(BOOST_ROOT) <sysinclude>$(BOOST_ROOT)
std::locale-support
: debug release # build variants
;
dll boost_program_options
: ../src/$(SOURCES).cpp
: # build requirements
[ common-names ] # magic for install and auto-link features
<define>BOOST_ALL_DYN_LINK=1 # tell source we're building dll's
<runtime-link>dynamic # build only for dynamic runtimes
<include>$(BOOST_ROOT) <sysinclude>$(BOOST_ROOT)
# The following really turns on static runtime linking
# which leads to runtime crashes when using DLL, so
# seem DLL is not usable on Metrowerks 8
# std::facet-support std::locale-support
: debug release # build variants
;
install program_options lib
: <lib>boost_program_options <dll>boost_program_options
;
stage stage/lib : <lib>boost_program_options <dll>boost_program_options
:
# copy to a path rooted at BOOST_ROOT:
<locate>$(BOOST_ROOT)
# make sure the names of the libraries are correctly named:
[ common-names ]
# add this target to the "stage" and "all" psuedo-targets:
<target>stage
<target>all
:
debug release
;
# end

View File

@@ -52,7 +52,8 @@
<listitem>
<para>ascii input passed to a Unicode value, and Unicode input
passed to an ascii value will be converted using a codecvt
facet (which may be specified by the user).
facet (which may be specified by the user(which can be
specified by the user)
</para>
</listitem>
</itemizedlist>
@@ -82,7 +83,7 @@
</para>
<para>The Unicode support outlined above is not complete. For example, we
don't support Unicode option names. Unicode support is hard and
don't plan allow Unicode in option names. Unicode support is hard and
requires a Boost-wide solution. Even comparing two arbitrary Unicode
strings is non-trivial. Finally, using Unicode in option names is
related to internationalization, which has it's own

View File

@@ -184,7 +184,7 @@ store(command_line_parser(args).options(desc).run(), vm);
options_description general("General options");
general.add_options()
("help", "produce a help message")
("help-module", value<string>(),
("help-module", value<string>()->implicit(),
"produce a help for a given module")
("version", "output the version number")
;
@@ -284,7 +284,7 @@ void validate(boost::any& v,
using namespace boost::program_options;
// Make sure no previous assignment to 'a' was made.
validators::check_first_occurrence(v);
validators::check_first_occurence(v);
// Extract the first string from 'values'. If there is more than
// one string, it's an error, and exception will be thrown.
const string& s = validators::get_single_string(values);

View File

@@ -4,11 +4,6 @@
</head>
<body>
Automatic redirection failed, please go to
<a href="../../../doc/html/program_options.html">../../../doc/html/program_options.html</a>
&nbsp;<hr>
<p>© Copyright Beman Dawes, 2001</p>
<p>Distributed under the Boost Software License, Version 1.0. (See accompanying
file <a href="../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy
at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
<a href="../../../doc/html/program_options.html">../../../doc/html/program_options.html</a>
</body>
</html>

View File

@@ -181,7 +181,7 @@ options_description desc;
desc.add_options()
("help", "produce help message")
("compression", value&lt;string&gt;(), "compression level")
("verbose", value&lt;string&gt;()->zero_token(), "verbosity level")
("verbose", value&lt;string&gt;()->implicit(), "verbosity level")
("email", value&lt;string&gt;()->multitoken(), "email to send to")
;
</programlisting>
@@ -348,18 +348,11 @@ positional_options_description pd; pd.add("input-file", 1);
given the same name.
<programlisting>
positional_options_description pd;
pd.add("output-file", 2).add("input-file", -1);
pd.add("output-file", 2).add_optional("input-file", -1);
</programlisting>
In the above example, the first two positional options will be associated
with name "output-file", and any others with the name "input-file".
</para>
<warning>
<para>The &positional_options_desc; class only specifies translation from
position to name, and the option name should still be registered with
an instance of the &options_description; class.</para>
</warning>
</section>
@@ -488,7 +481,7 @@ notify(vm);
<filename>autoexec.bat</filename> file or (on recent versions) the
<filename>Control Panel/System/Advanced/Environment Variables</filename>
dialog, and on Unix &#x2014;, the <filename>/etc/profile</filename>,
<filename>~/.profile</filename> and <filename>~/.bash_profile</filename>
<filename>~/profile</filename> and <filename>~/bash_profile</filename>
files. Because environment variables can be set for the entire system,
they are particularly suitable for options which apply to all programs.
</para>
@@ -567,15 +560,8 @@ notify(vm);
<row>
<entry>&parse_command_line;</entry>
<entry>parses command line (simpified interface)</entry>
<entry>parses command line</entry>
</row>
<row>
<entry>&basic_command_line_parser;</entry>
<entry>parses command line (extended interface)</entry>
</row>
<row>
<entry>&parse_config_file;</entry>
<entry>parses config file</entry>

View File

@@ -96,7 +96,7 @@ Compression level was set to 10.
<para>An option value, surely, can have other types than <code>int</code>, and
can have other interesting properties, which we'll discuss right now. The
complete version of the code snipped below can be found in
<filename>example/options_description.cpp</filename>.</para>
"example/options_description.cpp".</para>
<para>Imagine we're writing a compiler. It should take the optimization
level, a number of include paths, and a number of input files, and perform some
@@ -115,29 +115,21 @@ desc.add_options()
</programlisting>
</para>
<para>The <literal>"help"</literal> option should be familiar from
the previous example. It's a good idea to have this option in all cases.
</para>
<para>The "--help" option should be familiar from the previous example.
It's a good idea to have this option in all cases.</para>
<para>The <literal>"optimization"</literal> option shows two new features. First, we specify
<para>The "optimization" option shows two new features. First, we specify
the address of the variable(<code>&amp;opt</code>). After storing values, that
variable will have the value of the option. Second, we specify a default
value of 10, which will be used if no value is specified by the user.
</para>
<para>The <literal>"include-path"</literal> option is an example of the
only case where the interface of the <code>options_description</code>
class serves only one
<para>The "include-path" option is an example of the only case where
the interface of the <code>options_description</code> class serves only one
source -- the command line. Users typically like to use short option names
for common options, and the "include-path,I" name specifies that short
option name is "I". So, both "--include-path" and "-I" can be used.
</para>
<para>Note also that the type of the <literal>"include-path"</literal>
option is <type>std::vector</type>. The library provides special
support for vectors -- it will be possible to specify the option several
times, and all specified values will be collected in one vector.
</para>
<para>The "input-file" option specifies the list of files to
process. That's okay for a start, but, of course, writing something like:
@@ -345,7 +337,7 @@ Optimization level is 4
<!--
Local Variables:
mode: nxml
mode: xml
sgml-indent-data: t
sgml-parent-document: ("program_options.xml" "section")
sgml-set-face: t

23
example/Jamfile Normal file
View File

@@ -0,0 +1,23 @@
subproject libs/program_options/example ;
rule program-options-example ( name extra-sources * )
{
exe $(name) : $(name).cpp <lib>../build/boost_program_options $(extra-sources)
: <include>$(BOOST_ROOT) ;
}
program-options-example first ;
program-options-example options_description ;
program-options-example multiple_sources ;
program-options-example custom_syntax ;
program-options-example response_file ;
program-options-example option_groups ;
program-options-example real ;
program-options-example regex <lib>../../regex/build/boost_regex ;
#program-options-example prefix ;

View File

@@ -12,13 +12,13 @@ namespace boost { namespace program_options { namespace command_line_style {
There are "long" options, which start with "--" and "short",
which start with either "-" or "/". Both kinds can be allowed or
disallowed, see allow_long and allow_short. The allowed character
for short options is also configurable.
for short option is also configurable.
Option's value can be specified in the same token as name
Option's value can be specified in the same token as value
("--foo=bar"), or in the next token.
It's possible to introduce long options by the same character as
short options, see allow_long_disguise.
It's possible to introduce long option by the same character as
long option, see allow_long_disguise.
Finally, guessing (specifying only prefix of option) and case
insensitive processing are supported.
@@ -39,7 +39,7 @@ namespace boost { namespace program_options { namespace command_line_style {
@endverbatim
*/
long_allow_adjacent = allow_slash_for_short << 1,
/** Allow option parameter in the next token for
/** Allow option parameter in the same token for
long options. */
long_allow_next = long_allow_adjacent << 1,
/** Allow option parameter in the same token for
@@ -59,7 +59,7 @@ namespace boost { namespace program_options { namespace command_line_style {
/** Allow abbreviated spellings for long options,
if they unambiguously identify long option.
No long option name should be prefix of other
long option name if guessing is in effect.
long option name is guessing is in effect.
*/
allow_guessing = allow_sticky << 1,
/** Ignore the difference in case for options.

View File

@@ -82,12 +82,11 @@ namespace boost { namespace program_options {
validation_error(const std::string& what) : error(what) {}
~validation_error() throw() {}
void set_option_name(const std::string& option);
const char* what() const throw();
private:
mutable std::string m_message; // For on-demand formatting in 'what'
std::string m_option_name; // The name of the option which
// caused the exception.
const char* what() const throw();
};
class BOOST_PROGRAM_OPTIONS_DECL invalid_option_value

View File

@@ -78,12 +78,10 @@ namespace program_options {
virtual ~option_description();
enum match_result { no_match, full_match, approximate_match };
/** Given 'option', specified in the input source,
return 'true' is 'option' specifies *this.
*/
match_result match(const std::string& option, bool approx) const;
bool match(const std::string& option, bool approx) const;
/** Return the key that should identify the option, in
particular in the variables_map class.

View File

@@ -37,11 +37,10 @@ namespace boost { namespace program_options {
No calls to 'add' can be made after call with 'max_value' equal to
'-1'.
*/
positional_options_description&
add(const char* name, int max_count);
void 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

@@ -14,9 +14,9 @@
#include <boost/lexical_cast.hpp>
#include <string>
#include <vector>
#include <typeinfo>
namespace boost { namespace program_options {
@@ -74,13 +74,6 @@ namespace boost { namespace program_options {
// Nothing here. Specializations to follow.
};
/** Helper conversion class for values that accept ascii
strings as input.
Overrides the 'parse' method and defines new 'xparse'
method taking std::string. Depending on whether input
to parse is ascii or UTF8, will pass it to xparse unmodified,
or with UTF8->ascii conversion.
*/
template<>
class BOOST_PROGRAM_OPTIONS_DECL
value_semantic_codecvt_helper<char> : public value_semantic {
@@ -94,13 +87,6 @@ namespace boost { namespace program_options {
const = 0;
};
/** Helper conversion class for values that accept ascii
strings as input.
Overrides the 'parse' method and defines new 'xparse'
method taking std::wstring. Depending on whether input
to parse is ascii or UTF8, will recode input to Unicode, or
pass it unmodified.
*/
template<>
class BOOST_PROGRAM_OPTIONS_DECL
value_semantic_codecvt_helper<wchar_t> : public value_semantic {
@@ -115,7 +101,6 @@ namespace boost { namespace program_options {
const = 0;
#endif
};
/** Class which specifies a simple handling of a value: the value will
have string type and only one token is allowed. */
class BOOST_PROGRAM_OPTIONS_DECL
@@ -149,29 +134,9 @@ namespace boost { namespace program_options {
bool m_zero_tokens;
};
/** Base class for all option that have a fixed type, and are
willing to announce this type to the outside world.
Any 'value_semantics' for which you want to find out the
type can be dynamic_cast-ed to typed_value_base. If conversion
succeeds, the 'type' method can be called.
*/
class typed_value_base
{
public:
// Returns the type of the value described by this
// object.
virtual const std::type_info& value_type() const = 0;
// Not really needed, since deletion from this
// class is silly, but just in case.
virtual ~typed_value_base() {}
};
/** Class which handles value of a specific type. */
template<class T, class charT = char>
class typed_value : public value_semantic_codecvt_helper<charT>,
public typed_value_base
{
class typed_value : public value_semantic_codecvt_helper<charT> {
public:
/** Ctor. The 'store_to' parameter tells where to store
the value when it's known. The parameter can be NULL. */
@@ -262,7 +227,7 @@ namespace boost { namespace program_options {
/** Creates an instance of the 'validator' class and calls
its operator() to perform the actual conversion. */
its operator() to perform athe ctual conversion. */
void xparse(boost::any& value_store,
const std::vector< std::basic_string<charT> >& new_tokens)
const;
@@ -285,13 +250,6 @@ namespace boost { namespace program_options {
when creating *this, stores the value there. Otherwise,
does nothing. */
void notify(const boost::any& value_store) const;
public: // typed_value_base overrides
const std::type_info& value_type() const
{
return typeid(T);
}
private:

View File

@@ -24,27 +24,6 @@ namespace boost { namespace program_options {
class value_semantic;
class variables_map;
// forward declaration
/** Stores in 'm' all options that are defined in 'options'.
If 'm' already has a non-defaulted value of an option, that value
is not changed, even if 'options' specify some value.
*/
BOOST_PROGRAM_OPTIONS_DECL void store(const basic_parsed_options<char>& options, variables_map& m,
bool utf8 = false);
/** Stores in 'm' all options that are defined in 'options'.
If 'm' already has a non-defaulted value of an option, that value
is not changed, even if 'options' specify some value.
This is wide character variant.
*/
BOOST_PROGRAM_OPTIONS_DECL void store(const basic_parsed_options<wchar_t>& options,
variables_map& m);
/** Runs all 'notify' function for options in 'm'. */
BOOST_PROGRAM_OPTIONS_DECL void notify(variables_map& m);
/** Class holding value of option. Contains details about how the
value is set and allows to conveniently obtain the value.
*/
@@ -57,15 +36,10 @@ namespace boost { namespace program_options {
/** If stored value if of type T, returns that value. Otherwise,
throws boost::bad_any_cast exception. */
template<class T>
const T& as() const {
return boost::any_cast<const T&>(v);
}
/** @overload */
template<class T>
T& as() {
return boost::any_cast<T&>(v);
}
template<class T> const T& as() const;
/** @overload */
template<class T> T& as();
/// Returns true if no value is stored.
bool empty() const;
@@ -87,9 +61,10 @@ namespace boost { namespace program_options {
// be easily accessible, so we need to store semantic here.
shared_ptr<const value_semantic> m_value_semantic;
friend void store(const basic_parsed_options<char>& options,
friend void BOOST_PROGRAM_OPTIONS_DECL
store(const basic_parsed_options<char>& options,
variables_map& m, bool);
friend void notify(variables_map& m);
friend void BOOST_PROGRAM_OPTIONS_DECL notify(variables_map& m);
};
/** Implements string->string mapping with convenient value casting
@@ -129,11 +104,7 @@ namespace boost { namespace program_options {
const abstract_variables_map* m_next;
};
/** Concrete variables map which store variables in real map.
This class is derived from std::map<std::string, variable_value>,
so you can use all map operators to examine its content.
*/
/** Concrete variables map which store variables in real map. */
class BOOST_PROGRAM_OPTIONS_DECL variables_map : public abstract_variables_map,
public std::map<std::string, variable_value>
{
@@ -159,6 +130,25 @@ namespace boost { namespace program_options {
bool utf8);
};
/** Stores in 'm' all options that are defined in 'options'.
If 'm' already has a non-defaulted value of an option, that value
is not changed, even if 'options' specify some value.
*/
BOOST_PROGRAM_OPTIONS_DECL void store(const basic_parsed_options<char>& options, variables_map& m,
bool utf8 = false);
/** Stores in 'm' all options that are defined in 'options'.
If 'm' already has a non-defaulted value of an option, that value
is not changed, even if 'options' specify some value.
This is wide character variant.
*/
BOOST_PROGRAM_OPTIONS_DECL void store(const basic_parsed_options<wchar_t>& options,
variables_map& m);
/** Runs all 'notify' function for options in 'm'. */
BOOST_PROGRAM_OPTIONS_DECL void notify(variables_map& m);
/*
* Templates/inlines
@@ -190,6 +180,18 @@ namespace boost { namespace program_options {
return v;
}
template<class T>
const T&
variable_value::as() const {
return boost::any_cast<const T&>(v);
}
template<class T>
T&
variable_value::as() {
return boost::any_cast<T&>(v);
}
}}
#endif

View File

@@ -4,11 +4,6 @@
</head>
<body>
Automatic redirection failed, please go to
<a href="../../doc/html/program_options.html">../../doc/html/program_options.html</a>
&nbsp;<hr>
<p>© Copyright Beman Dawes, 2001</p>
<p>Distributed under the Boost Software License, Version 1.0. (See accompanying
file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy
at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
<a href="../../doc/html/program_options.html">../../doc/html/program_options.html</a>
</body>
</html>
</html>

View File

@@ -498,8 +498,7 @@ namespace boost { namespace program_options { namespace detail {
if (!r.first.empty()) {
option next;
next.string_key = r.first;
if (!r.second.empty())
next.value.push_back(r.second);
next.value.push_back(r.second);
result.push_back(next);
args.erase(args.begin());
}

View File

@@ -23,7 +23,6 @@
#include <cstring>
#include <cstdarg>
#include <sstream>
#include <iterator>
using namespace std;
namespace boost { namespace program_options {
@@ -54,10 +53,10 @@ namespace boost { namespace program_options {
{
}
option_description::match_result
bool
option_description::match(const std::string& option, bool approx) const
{
match_result result = no_match;
bool result = false;
if (!m_long_name.empty()) {
if (*m_long_name.rbegin() == '*')
@@ -66,26 +65,23 @@ namespace boost { namespace program_options {
// prefix is OK.
if (option.find(m_long_name.substr(0, m_long_name.length()-1))
== 0)
result = approximate_match;
result = true;
}
if (approx)
{
if (m_long_name.find(option) == 0)
if (m_long_name == option)
result = full_match;
else
result = approximate_match;
result = true;
}
else
{
if (m_long_name == option)
result = full_match;
result = true;
}
}
if (m_short_name == option)
result = full_match;
result = true;
return result;
}
@@ -262,38 +258,21 @@ namespace boost { namespace program_options {
// case sensitivity and trailing '*' and so we can't use simple map.
for(unsigned i = 0; i < m_options.size(); ++i)
{
option_description::match_result r =
m_options[i]->match(name, approx);
if (r == option_description::no_match)
continue;
// If we have a full patch, and an approximate match,
// ignore approximate match instead of reporting error.
// Say, if we have options "all" and "all-chroots", then
// "--all" on the command line should select the first one,
// without ambiguity.
//
// For now, we don't check the situation when there are
// two full matches.
if (r == option_description::full_match)
if (m_options[i]->match(name, approx))
{
return m_options[i].get();
}
if (found != -1)
{
vector<string> alts;
// FIXME: the use of 'key' here might not
// be the best approach.
alts.push_back(m_options[found]->key(name));
alts.push_back(m_options[i]->key(name));
boost::throw_exception(ambiguous_option(name, alts));
}
else
{
found = i;
if (found != -1)
{
vector<string> alts;
// FIXME: the use of 'key' here might not
// be the best approach.
alts.push_back(m_options[found]->key(name));
alts.push_back(m_options[i]->key(name));
boost::throw_exception(ambiguous_option(name, alts));
}
else
{
found = i;
}
}
}
if (found != -1) {
@@ -312,26 +291,11 @@ namespace boost { namespace program_options {
namespace {
/* Given a string 'par', that contains no newline characters
outputs it to 'os' with wordwrapping, that is, as several
line.
Each output line starts with 'indent' space characters,
following by characters from 'par'. The total length of
line is no longer than 'line_length'.
*/
void format_paragraph(std::ostream& os,
std::string par,
unsigned indent,
unsigned first_column_width,
unsigned line_length)
{
// Through reminder of this function, 'line_length' will
// be the length available for characters, not including
// indent.
assert(indent < line_length);
line_length -= indent;
// index of tab (if present) is used as additional indent relative
// to first_column_width if paragrapth is spanned over multiple
// lines if tab is not on first line it is ignored
@@ -355,16 +319,16 @@ namespace boost { namespace program_options {
// this assert may fail due to user error or
// environment conditions!
assert(par_indent < line_length);
assert(par_indent < (line_length - first_column_width));
// ignore tab if not on first line
if (par_indent >= line_length)
if (par_indent >= (line_length - first_column_width))
{
par_indent = 0;
}
}
if (par.size() < line_length)
if (par.size() < (line_length - first_column_width))
{
os << par;
}
@@ -373,16 +337,17 @@ namespace boost { namespace program_options {
string::const_iterator line_begin = par.begin();
const string::const_iterator par_end = par.end();
bool first_line = true; // of current paragraph!
bool first_line = true; // of current paragraph!
unsigned indent = first_column_width;
while (line_begin < par_end) // paragraph lines
{
if (!first_line)
{
// If line starts with space, but second character
// is not space, remove the leading space.
// We don't remove double spaces because those
// might be intentianal.
// trimm leading single spaces
// if (firstchar == ' ') &&
// ((exists(firstchar + 1) && (firstchar + 1 != ' '))
if ((*line_begin == ' ') &&
((line_begin + 1 < par_end) &&
(*(line_begin + 1) != ' ')))
@@ -391,30 +356,35 @@ namespace boost { namespace program_options {
}
}
// Take care to never increment the iterator past
// the end, since MSVC 8.0 (brokenly), assumes that
// doing that, even if no access happens, is a bug.
unsigned remaining = distance(line_begin, par_end);
string::const_iterator line_end = line_begin +
((remaining < line_length) ? remaining : line_length);
string::const_iterator line_end;
if (line_begin + (line_length - indent) > par_end)
{
line_end = par_end;
}
else
{
line_end = line_begin + (line_length - indent);
}
// prevent chopped words
// Is line_end between two non-space characters?
// if (lastchar != ' ') &&
// ((exists(lastchar + 1) && (lastchar + 1 != ' '))
if ((*(line_end - 1) != ' ') &&
((line_end < par_end) && (*line_end != ' ')))
{
// find last ' ' in the second half of the current paragraph line
string::const_iterator last_space =
find(reverse_iterator<string::const_iterator>(line_end),
reverse_iterator<string::const_iterator>(line_begin),
find(reverse_iterator<string::const_iterator>(line_end - 1),
reverse_iterator<string::const_iterator>(line_begin - 1),
' ')
.base();
if (last_space != line_begin)
if (last_space != line_begin - 1)
{
// is last_space within the second half of the
// is last_space within the second half ot the
// current line
if ((unsigned)std::distance(last_space, line_end) <
if (unsigned(distance(last_space, line_end)) <
(line_length - indent) / 2)
{
line_end = last_space;
@@ -427,7 +397,7 @@ namespace boost { namespace program_options {
if (first_line)
{
indent += par_indent;
indent = first_column_width + par_indent;
first_line = false;
}
@@ -466,7 +436,7 @@ namespace boost { namespace program_options {
assert(line_length > first_column_width);
// Note: can't use 'tokenizer' as name of typedef -- borland
// will consider uses of 'tokenizer' below as uses of
// will consider subsequence uses of 'tokenizer' as uses of
// boost::tokenizer, not typedef.
typedef boost::tokenizer<boost::char_separator<char> > tok;

View File

@@ -17,7 +17,7 @@ namespace boost { namespace program_options {
positional_options_description::positional_options_description()
{}
positional_options_description&
void
positional_options_description::add(const char* name, int max_count)
{
assert(max_count != -1 || m_trailing.empty());
@@ -27,7 +27,7 @@ namespace boost { namespace program_options {
else {
m_names.resize(m_names.size() + max_count, name);
}
return *this;
}
unsigned

View File

@@ -170,12 +170,9 @@ namespace boost { namespace program_options {
{
check_first_occurrence(v);
string s(get_single_string(xs));
if (!s.empty() && (
(*s.begin() == '\'' && *s.rbegin() == '\'' ||
*s.begin() == '"' && *s.rbegin() == '"')))
{
if (*s.begin() == '\'' && *s.rbegin() == '\'' ||
*s.begin() == '"' && *s.rbegin() == '"')
v = any(s.substr(1, s.size()-2));
}
else
v = any(s);
}

View File

@@ -35,25 +35,14 @@ namespace boost { namespace program_options {
std::set<std::string> new_final;
// Declared once, to please Intel in VC++ mode;
unsigned i;
// First, convert/store all given options
for (i = 0; i < options.options.size(); ++i) {
for (size_t i = 0; i < options.options.size(); ++i) {
const string& name = options.options[i].string_key;
// Skip positional options without name
if (name.empty())
continue;
// Ignore unregistered option. The 'unregistered'
// field can be true only if user has explicitly asked
// to allow unregistered options. We can't store them
// to variables map (lacking any information about paring),
// so just ignore them.
if (options.options[i].unregistered)
continue;
// If option has final value, skip this assignment
if (xm.m_final.count(name))
continue;
@@ -95,7 +84,7 @@ namespace boost { namespace program_options {
// Second, apply default values.
const vector<shared_ptr<option_description> >& all = desc.options();
for(i = 0; i < all.size(); ++i)
for(unsigned i = 0; i < all.size(); ++i)
{
const option_description& d = *all[i];
string key = d.key("");

View File

@@ -12,12 +12,10 @@ namespace boost { namespace program_options {
using namespace std;
// Take a command line string and splits in into tokens, according
// to the rules windows command line processor uses.
//
// The rules are pretty funny, see
// The rules for windows command line are pretty funny, see
// http://article.gmane.org/gmane.comp.lib.boost.user/3005
// http://msdn.microsoft.com/library/en-us/vccelng/htm/progs_12.asp
BOOST_PROGRAM_OPTIONS_DECL
std::vector<std::string> split_winmain(const std::string& input)
{
@@ -25,7 +23,7 @@ namespace boost { namespace program_options {
string::const_iterator i = input.begin(), e = input.end();
for(;i != e; ++i)
if (!isspace((unsigned char)*i))
if (!isspace(*i))
break;
if (i != e) {
@@ -57,11 +55,11 @@ namespace boost { namespace program_options {
current.append(backslash_count, '\\');
backslash_count = 0;
}
if (isspace((unsigned char)*i) && !inside_quoted) {
if (isspace(*i) && !inside_quoted) {
// Space outside quoted section terminate the current argument
result.push_back(current);
current.resize(0);
for(;i != e && isspace((unsigned char)*i); ++i)
for(;i != e && isspace(*i); ++i)
;
--i;
} else {
@@ -88,7 +86,7 @@ namespace boost { namespace program_options {
{
vector<wstring> result;
vector<string> aux = split_winmain(to_internal(cmdline));
for (unsigned i = 0, e = aux.size(); i < e; ++i)
for (unsigned i = 0, e = result.size(); i < e; ++i)
result.push_back(from_utf8(aux[i]));
return result;
}

47
test/Jamfile Normal file
View File

@@ -0,0 +1,47 @@
subproject libs/program_options/test ;
import testing ;
rule program-options-test ( name )
{
return [
run $(name).cpp <lib>../build/boost_program_options
<lib>../../test/build/boost_test_exec_monitor : :
: <include>$(BOOST_ROOT)
std::locale-support ]
;
}
rule program-options-dll-test ( name )
{
return [
run $(name).cpp <dll>../build/boost_program_options
<lib>../../test/build/boost_test_exec_monitor : :
: <include>$(BOOST_ROOT)
<define>BOOST_ALL_DYN_LINK=1
<runtime-link>dynamic
: $(name)_dll ]
;
}
test-suite program_options :
[ program-options-test options_description_test ]
[ program-options-test parsers_test ]
[ program-options-test variable_map_test ]
[ program-options-test cmdline_test ]
[ program-options-test positional_options_test ]
[ program-options-test unicode_test ]
[ program-options-test winmain ]
[ program-options-dll-test options_description_test ]
[ program-options-dll-test parsers_test ]
[ program-options-dll-test variable_map_test ]
[ program-options-dll-test cmdline_test ]
[ program-options-dll-test positional_options_test ]
[ program-options-dll-test unicode_test ]
[ program-options-dll-test winmain ]
;

View File

@@ -2,7 +2,7 @@
project
: requirements
<library>../build//boost_program_options
<library>/boost/test//boost_test_exec_monitor/<link>static
<library>/boost/test//boost_test_exec_monitor
<link>static
# <define>_GLIBCXX_CONCEPT_CHECKS
@@ -13,8 +13,7 @@ rule po-test ( source )
{
return
[ run $(source) ]
[ run $(source) : : : <link>shared <define>BOOST_PROGRAM_OPTIONS_DYN_LINK=1
: $(source:B)_dll ]
[ run $(source) : : : <link>shared : $(source:B)_dll ]
;
}

View File

@@ -14,47 +14,17 @@ using namespace boost;
#include <boost/test/test_tools.hpp>
#include <utility>
#include <string>
#include <sstream>
using namespace std;
void test_type()
{
options_description desc;
desc.add_options()
("foo", value<int>(), "")
("bar", value<std::string>(), "")
;
const typed_value_base* b = dynamic_cast<const typed_value_base*>
(desc.find("foo", false).semantic().get());
BOOST_CHECK(b);
BOOST_CHECK(b->value_type() == typeid(int));
const typed_value_base* b2 = dynamic_cast<const typed_value_base*>
(desc.find("bar", false).semantic().get());
BOOST_CHECK(b2);
BOOST_CHECK(b2->value_type() == typeid(std::string));
}
void test_approximation()
{
options_description desc;
desc.add_options()
("foo", new untyped_value())
("fee", new untyped_value())
("baz", new untyped_value())
("all", new untyped_value())
("all-chroots", new untyped_value())
("all-sessions", new untyped_value())
;
("foo", new untyped_value())
("fee", new untyped_value())
("baz", new untyped_value());
BOOST_CHECK_EQUAL(desc.find("fo", true).long_name(), "foo");
BOOST_CHECK_EQUAL(desc.find("all", true).long_name(), "all");
BOOST_CHECK_EQUAL(desc.find("all-ch", true).long_name(), "all-chroots");
// BOOST_CHECK(desc.count_approx("foo") == 1);
// set<string> a = desc.approximations("f");
// BOOST_CHECK(a.size() == 2);
@@ -62,25 +32,8 @@ void test_approximation()
// BOOST_CHECK(*(++a.begin()) == "foo");
}
void test_formatting()
{
// Long option descriptions used to crash on MSVC-8.0.
options_description desc;
desc.add_options()(
"test", new untyped_value(),
"foo foo foo foo foo foo foo foo foo foo foo foo foo foo"
"foo foo foo foo foo foo foo foo foo foo foo foo foo foo"
"foo foo foo foo foo foo foo foo foo foo foo foo foo foo"
"foo foo foo foo foo foo foo foo foo foo foo foo foo foo");
stringstream ss;
ss << desc;
}
int test_main(int, char* [])
{
test_type();
test_approximation();
test_formatting();
return 0;
}

View File

@@ -6,7 +6,6 @@
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/variables_map.hpp>
using namespace boost::program_options;
// We'll use po::value everywhere to workaround vc6 bug.
namespace po = boost::program_options;
@@ -133,16 +132,6 @@ void test_command_line()
check_value(a4[0], "foo", "4");
check_value(a4[1], "bar", "11");
// Check that we don't crash on empty values of type 'string'
char* cmdline4[] = {"", "--open", ""};
options_description desc2;
desc2.add_options()
("open", po::value<string>())
;
variables_map vm;
po::store(po::parse_command_line(3, cmdline4, desc2), vm);
}
@@ -230,14 +219,9 @@ void test_unregistered()
BOOST_CHECK(a2[1] == "--bar");
BOOST_CHECK(a2[2] == "1");
// Test that storing unregisted options has no effect
variables_map vm;
store(command_line_parser(cmdline1).options(desc).
allow_unregistered().run(),
vm);
BOOST_CHECK_EQUAL(vm.size(), 0u);
}
int test_main(int, char* [])

View File

@@ -49,31 +49,28 @@ void test_parsing()
("first", po::value<int>())
("second", po::value<int>())
("input-file", po::value< vector<string> >())
("some-other", po::value<string>())
;
positional_options_description p;
p.add("input-file", 2).add("some-other", 1);
p.add("input-file", 2);
vector<string> args;
args.push_back("--first=10");
args.push_back("file1");
args.push_back("--second=10");
args.push_back("file2");
args.push_back("file3");
// Check that positional options are handled.
parsed_options parsed =
command_line_parser(args).options(desc).positional(p).run();
BOOST_REQUIRE(parsed.options.size() == 5);
BOOST_REQUIRE(parsed.options.size() == 4);
BOOST_CHECK_EQUAL(parsed.options[1].string_key, "input-file");
BOOST_CHECK_EQUAL(parsed.options[1].value[0], "file1");
BOOST_CHECK_EQUAL(parsed.options[3].string_key, "input-file");
BOOST_CHECK_EQUAL(parsed.options[3].value[0], "file2");
BOOST_CHECK_EQUAL(parsed.options[4].value[0], "file3");
args.push_back("file4");
args.push_back("file3");
// Check that excessive number of positional options is detected.
BOOST_CHECK_THROW(command_line_parser(args).options(desc).positional(p)

View File

@@ -7,6 +7,7 @@
#include <fstream>
#include <sstream>
#include <iostream>
#include <cassert>
#include <boost/progress.hpp>
#include <boost/bind.hpp>
#include <boost/ref.hpp>
@@ -93,7 +94,7 @@ void test_convert(const std::string& input,
facet);
}
BOOST_CHECK(output.size()*2 == expected_output.size());
assert(output.size()*2 == expected_output.size());
for(unsigned i = 0; i < output.size(); ++i) {
@@ -102,20 +103,20 @@ void test_convert(const std::string& input,
low &= 0xFF;
unsigned low2 = expected_output[2*i];
low2 &= 0xFF;
BOOST_CHECK(low == low2);
assert(low == low2);
}
{
unsigned high = output[i];
high >>= 8;
high &= 0xFF;
unsigned high2 = expected_output[2*i+1];
BOOST_CHECK(high == high2);
assert(high == high2);
}
}
string ref = boost::to_8_bit(output, facet);
BOOST_CHECK(ref == input);
assert(ref == input);
}
int test_main(int ac, char* av[])