summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/program_options
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 18:45:59 +0000
commit19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch)
tree42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/boost/libs/program_options
parentInitial commit. (diff)
downloadceph-19fcec84d8d7d21e796c7624e521b60d28ee21ed.tar.xz
ceph-19fcec84d8d7d21e796c7624e521b60d28ee21ed.zip
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/program_options')
-rw-r--r--src/boost/libs/program_options/Jamfile11
-rw-r--r--src/boost/libs/program_options/README.md37
-rw-r--r--src/boost/libs/program_options/build/Jamfile.v216
-rwxr-xr-xsrc/boost/libs/program_options/ci/build.sh19
-rwxr-xr-xsrc/boost/libs/program_options/ci/codecov.sh43
-rwxr-xr-xsrc/boost/libs/program_options/ci/coverity.sh42
-rwxr-xr-xsrc/boost/libs/program_options/ci/cppcheck.sh38
-rwxr-xr-xsrc/boost/libs/program_options/ci/mingw.bat50
-rw-r--r--src/boost/libs/program_options/example/Jamfile.v221
-rw-r--r--src/boost/libs/program_options/example/config_file_types.cpp242
-rw-r--r--src/boost/libs/program_options/example/custom_syntax.cpp63
-rw-r--r--src/boost/libs/program_options/example/env_options.cpp47
-rw-r--r--src/boost/libs/program_options/example/first.cpp51
-rw-r--r--src/boost/libs/program_options/example/multiple_sources.cfg5
-rw-r--r--src/boost/libs/program_options/example/multiple_sources.cpp121
-rw-r--r--src/boost/libs/program_options/example/option_groups.cpp97
-rw-r--r--src/boost/libs/program_options/example/options_description.cpp86
-rw-r--r--src/boost/libs/program_options/example/options_heirarchy.cpp690
-rw-r--r--src/boost/libs/program_options/example/real.cpp96
-rw-r--r--src/boost/libs/program_options/example/regex.cpp101
-rw-r--r--src/boost/libs/program_options/example/response_file.cpp94
-rw-r--r--src/boost/libs/program_options/example/response_file.rsp3
-rw-r--r--src/boost/libs/program_options/index.html14
-rw-r--r--src/boost/libs/program_options/meta/libraries.json15
-rw-r--r--src/boost/libs/program_options/src/cmdline.cpp713
-rw-r--r--src/boost/libs/program_options/src/config_file.cpp198
-rw-r--r--src/boost/libs/program_options/src/convert.cpp161
-rw-r--r--src/boost/libs/program_options/src/options_description.cpp699
-rw-r--r--src/boost/libs/program_options/src/parsers.cpp258
-rw-r--r--src/boost/libs/program_options/src/positional_options.cpp53
-rw-r--r--src/boost/libs/program_options/src/split.cpp62
-rw-r--r--src/boost/libs/program_options/src/utf8_codecvt_facet.cpp21
-rw-r--r--src/boost/libs/program_options/src/value_semantic.cpp428
-rw-r--r--src/boost/libs/program_options/src/variables_map.cpp248
-rw-r--r--src/boost/libs/program_options/src/winmain.cpp102
-rw-r--r--src/boost/libs/program_options/test/Jamfile.v244
-rw-r--r--src/boost/libs/program_options/test/cmdline_test.cpp656
-rw-r--r--src/boost/libs/program_options/test/config_test.cfg9
-rw-r--r--src/boost/libs/program_options/test/exception_test.cpp264
-rw-r--r--src/boost/libs/program_options/test/exception_txt_test.cpp693
-rw-r--r--src/boost/libs/program_options/test/minitest.hpp25
-rw-r--r--src/boost/libs/program_options/test/optional_test.cpp53
-rw-r--r--src/boost/libs/program_options/test/options_description_test.cpp347
-rw-r--r--src/boost/libs/program_options/test/parsers_test.cpp388
-rw-r--r--src/boost/libs/program_options/test/positional_options_test.cpp91
-rw-r--r--src/boost/libs/program_options/test/program_options_size_test.py53
-rw-r--r--src/boost/libs/program_options/test/quick.cpp49
-rw-r--r--src/boost/libs/program_options/test/required_test.cfg1
-rw-r--r--src/boost/libs/program_options/test/required_test.cpp125
-rw-r--r--src/boost/libs/program_options/test/split_test.cpp189
-rw-r--r--src/boost/libs/program_options/test/test_convert.cpp146
-rw-r--r--src/boost/libs/program_options/test/ucs2.txtbin0 -> 2750 bytes
-rw-r--r--src/boost/libs/program_options/test/unicode_test.cpp164
-rw-r--r--src/boost/libs/program_options/test/unrecognized_test.cpp88
-rw-r--r--src/boost/libs/program_options/test/utf8.txtbin0 -> 2622 bytes
-rw-r--r--src/boost/libs/program_options/test/variable_map_test.cpp290
-rw-r--r--src/boost/libs/program_options/test/winmain.cpp74
-rw-r--r--src/boost/libs/program_options/test/winmain.py39
58 files changed, 8733 insertions, 0 deletions
diff --git a/src/boost/libs/program_options/Jamfile b/src/boost/libs/program_options/Jamfile
new file mode 100644
index 000000000..f0de2e0bc
--- /dev/null
+++ b/src/boost/libs/program_options/Jamfile
@@ -0,0 +1,11 @@
+# Boost.ProgramOptions Library Jamfile
+#
+# Copyright (c) 2018 James E. King III
+#
+# Use, modification, and distribution are subject to 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)
+
+# please order by name to ease maintenance
+build-project example ;
+build-project test ;
diff --git a/src/boost/libs/program_options/README.md b/src/boost/libs/program_options/README.md
new file mode 100644
index 000000000..b2bd595ed
--- /dev/null
+++ b/src/boost/libs/program_options/README.md
@@ -0,0 +1,37 @@
+Program Options, part of the collection of [Boost C++ Libraries](http://github.com/boostorg), allows for definition and acquisition of (name, value) pairs from the user via conventional methods such as command line and config file. It is roughly analogous to getopt_long, but for use with C++.
+
+### License
+
+Distributed under the [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt).
+
+### Properties
+
+* C++03
+* Requires Linking
+
+### Build Status
+(in progress...)
+
+|Branch | Travis | Appveyor | codecov.io | Deps | Docs | Tests |
+|:-------------: | ------ | -------- | ---------- | ---- | ---- | ----- |
+|[`master`](https://github.com/boostorg/program_options/tree/master) | [![Build Status](https://travis-ci.org/boostorg/program_options.svg?branch=master)](https://travis-ci.org/boostorg/program_options) | [![Build status](https://ci.appveyor.com/api/projects/status/e0quisadwh1v7ok5/branch/master?svg=true)](https://ci.appveyor.com/project/vprus/program-options/branch/master) | [![codecov](https://codecov.io/gh/boostorg/program_options/branch/master/graph/badge.svg)](https://codecov.io/gh/boostorg/program_options/branch/master) | [![Deps](https://img.shields.io/badge/deps-master-brightgreen.svg)](https://pdimov.github.io/boostdep-report/master/program_options.html) | [![Documentation](https://img.shields.io/badge/docs-master-brightgreen.svg)](http://www.boost.org/doc/libs/master/doc/html/program_options.html) | [![Enter the Matrix](https://img.shields.io/badge/matrix-master-brightgreen.svg)](http://www.boost.org/development/tests/master/developer/program_options.html)
+|[`develop`](https://github.com/boostorg/program_options/tree/develop) | [![Build Status](https://travis-ci.org/boostorg/program_options.svg?branch=develop)](https://travis-ci.org/boostorg/program_options) | [![Build status](https://ci.appveyor.com/api/projects/status/e0quisadwh1v7ok5/branch/develop?svg=true)](https://ci.appveyor.com/project/vprus/program-options/branch/develop) | [![codecov](https://codecov.io/gh/boostorg/program_options/branch/develop/graph/badge.svg)](https://codecov.io/gh/boostorg/program_options/branch/develop) | [![Deps](https://img.shields.io/badge/deps-develop-brightgreen.svg)](https://pdimov.github.io/boostdep-report/develop/program_options.html) | [![Documentation](https://img.shields.io/badge/docs-develop-brightgreen.svg)](http://www.boost.org/doc/libs/develop/doc/html/program_options.html) | [![Enter the Matrix](https://img.shields.io/badge/matrix-develop-brightgreen.svg)](http://www.boost.org/development/tests/develop/developer/program_options.html)
+
+### Directories
+
+| Name | Purpose |
+| --------- | ------------------------------ |
+| `build` | build script for link library |
+| `ci` | continuous integration scripts |
+| `doc` | documentation |
+| `example` | use case examples |
+| `include` | headers |
+| `src` | source code for link library |
+| `test` | unit tests |
+
+### More information
+
+* [Ask questions](http://stackoverflow.com/questions/ask?tags=c%2B%2B,boost,boost-program_options): Be sure to read the documentation first to see if it answers your question.
+* [Report bugs](https://github.com/boostorg/program_options/issues): Be sure to mention Boost version, platform and compiler you're using. A small compilable code sample to reproduce the problem is always good as well.
+* [Submit Pull Requests](https://github.com/boostorg/program_options/pulls) against the **develop** branch. Note that by submitting patches you agree to license your modifications under the [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt). Be sure to include tests proving your changes work properly.
+* Discussions about the library are held on the [Boost developers mailing list](http://www.boost.org/community/groups.html#main). Be sure to read the [discussion policy](http://www.boost.org/community/policy.html) before posting and add the `[program_options]` tag at the beginning of the subject line.
diff --git a/src/boost/libs/program_options/build/Jamfile.v2 b/src/boost/libs/program_options/build/Jamfile.v2
new file mode 100644
index 000000000..852054d01
--- /dev/null
+++ b/src/boost/libs/program_options/build/Jamfile.v2
@@ -0,0 +1,16 @@
+
+project boost/program_options
+ : source-location ../src
+ ;
+
+SOURCES =
+ cmdline config_file options_description parsers variables_map
+ value_semantic positional_options utf8_codecvt_facet
+ convert winmain split
+ ;
+
+boost-lib program_options
+ : $(SOURCES).cpp
+ : # See https://svn.boost.org/trac/boost/ticket/5049
+ <target-os>hpux,<toolset>gcc:<define>_INCLUDE_STDC__SOURCE_199901
+ ; \ No newline at end of file
diff --git a/src/boost/libs/program_options/ci/build.sh b/src/boost/libs/program_options/ci/build.sh
new file mode 100755
index 000000000..49dd24aec
--- /dev/null
+++ b/src/boost/libs/program_options/ci/build.sh
@@ -0,0 +1,19 @@
+#! /bin/bash
+#
+# Copyright 2017 James E. King III
+# 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)
+#
+# Bash script to run in travis to perform a bjam build
+# cwd should be $BOOST_ROOT/libs/$SELF before running
+#
+
+set -ex
+
+# default language level: c++03
+if [[ -z "$CXXSTD" ]]; then
+ CXXSTD=03
+fi
+
+$BOOST_ROOT/b2 . toolset=$TOOLSET cxxstd=$CXXSTD $CXXFLAGS $DEFINES $LINKFLAGS $TESTFLAGS $B2_ADDRESS_MODEL $B2_LINK $B2_THREADING $B2_VARIANT -j3 $*
diff --git a/src/boost/libs/program_options/ci/codecov.sh b/src/boost/libs/program_options/ci/codecov.sh
new file mode 100755
index 000000000..2f7ea10f6
--- /dev/null
+++ b/src/boost/libs/program_options/ci/codecov.sh
@@ -0,0 +1,43 @@
+#! /bin/bash
+#
+# Copyright 2017, 2018 James E. King III
+# 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)
+#
+# Bash script to run in travis to perform codecov.io integration
+#
+
+###
+### NOTE: Make sure you grab .codecov.yml
+###
+
+# assumes cwd is the top level directory of the boost project
+# assumes an environment variable $SELF is the boost project name
+
+set -ex
+
+B2_VARIANT=debug
+ci/build.sh cxxflags=-fprofile-arcs cxxflags=-ftest-coverage linkflags=-fprofile-arcs linkflags=-ftest-coverage
+
+# switch back to the original source code directory
+cd $TRAVIS_BUILD_DIR
+
+# get the version of lcov
+lcov --version
+
+# coverage files are in ../../b2 from this location
+lcov --gcov-tool=gcov-7 --rc lcov_branch_coverage=1 --base-directory "$BOOST_ROOT/libs/$SELF" --directory "$BOOST_ROOT" --capture --output-file all.info
+
+# all.info contains all the coverage info for all projects - limit to ours
+lcov --gcov-tool=gcov-7 --rc lcov_branch_coverage=1 --extract all.info "*/boost/$SELF/*" "*/libs/$SELF/src/*" --output-file coverage.info
+
+# dump a summary on the console - helps us identify problems in pathing
+lcov --gcov-tool=gcov-7 --rc lcov_branch_coverage=1 --list coverage.info
+
+#
+# upload to codecov.io
+#
+curl -s https://codecov.io/bash > .codecov
+chmod +x .codecov
+./.codecov -f coverage.info -X gcov -x "gcov-7"
diff --git a/src/boost/libs/program_options/ci/coverity.sh b/src/boost/libs/program_options/ci/coverity.sh
new file mode 100755
index 000000000..0de08a4ce
--- /dev/null
+++ b/src/boost/libs/program_options/ci/coverity.sh
@@ -0,0 +1,42 @@
+#! /bin/bash
+#
+# Copyright 2017 James E. King III
+# 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)
+#
+# Bash script to run in travis to perform a Coverity Scan build
+# To skip the coverity integration download (which is huge) if
+# you already have it from a previous run, add --skipdownload
+#
+
+#
+# Environment Variables
+#
+# COVERITY_SCAN_NOTIFICATION_EMAIL - email address to notify
+# COVERITY_SCAN_TOKEN - the Coverity Scan token (should be secure)
+# SELF - the boost libs directory name
+
+set -ex
+
+pushd /tmp
+if [[ "$1" != "--skipdownload" ]]; then
+ rm -rf coverity_tool.tgz cov-analysis*
+ wget https://scan.coverity.com/download/linux64 --post-data "token=$COVERITY_SCAN_TOKEN&project=boostorg/$SELF" -O coverity_tool.tgz
+ tar xzf coverity_tool.tgz
+fi
+COVBIN=$(echo $(pwd)/cov-analysis*/bin)
+export PATH=$COVBIN:$PATH
+popd
+
+ci/build.sh clean
+rm -rf cov-int/
+cov-build --dir cov-int ci/build.sh
+tar cJf cov-int.tar.xz cov-int/
+curl --form token="$COVERITY_SCAN_TOKEN" \
+ --form email="$COVERITY_SCAN_NOTIFICATION_EMAIL" \
+ --form file=@cov-int.tar.xz \
+ --form version="$(git describe --tags)" \
+ --form description="boostorg/$SELF" \
+ https://scan.coverity.com/builds?project="boostorg/$SELF"
+
diff --git a/src/boost/libs/program_options/ci/cppcheck.sh b/src/boost/libs/program_options/ci/cppcheck.sh
new file mode 100755
index 000000000..7734ffcc1
--- /dev/null
+++ b/src/boost/libs/program_options/ci/cppcheck.sh
@@ -0,0 +1,38 @@
+#! /bin/bash
+#
+# Copyright 2018 James E. King III
+# 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)
+#
+# Bash script to run in travis to perform a cppcheck
+# cwd should be $BOOST_ROOT before running
+#
+
+set -ex
+
+# default language level: c++03
+if [[ -z "$CXXSTD" ]]; then
+ CXXSTD=03
+fi
+
+# Travis' ubuntu-trusty comes with cppcheck 1.62 which is pretty old
+# default cppcheck version: 1.82
+if [[ -z "$CPPCHKVER" ]]; then
+ CPPCHKVER=1.82
+fi
+
+pushd ~
+wget https://github.com/danmar/cppcheck/archive/$CPPCHKVER.tar.gz
+tar xzf $CPPCHKVER.tar.gz
+mkdir cppcheck-build
+cd cppcheck-build
+cmake ../cppcheck-$CPPCHKVER -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX=~/cppcheck
+make -j3 install
+popd
+
+~/cppcheck/bin/cppcheck -I. --std=c++$CXXSTD --enable=all --error-exitcode=1 \
+ --force --check-config --suppress=*:boost/preprocessor/tuple/size.hpp \
+ -UBOOST_USER_CONFIG -UBOOST_COMPILER_CONFIG -UBOOST_STDLIB_CONFIG -UBOOST_PLATFORM_CONFIG \
+ libs/$SELF 2>&1 | grep -v 'Cppcheck does not need standard library headers'
+
diff --git a/src/boost/libs/program_options/ci/mingw.bat b/src/boost/libs/program_options/ci/mingw.bat
new file mode 100755
index 000000000..bc189fdb7
--- /dev/null
+++ b/src/boost/libs/program_options/ci/mingw.bat
@@ -0,0 +1,50 @@
+::
+:: MinGW Build Script for Appveyor, leveraging the MSYS2 installation
+:: Copyright (C) 2018 James E. King III
+:: Distributed under the Boost Software License, Version 1.0.
+:: (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
+::
+
+@ECHO ON
+SETLOCAL EnableDelayedExpansion
+
+:: Set up the toolset
+echo using gcc : %FLAVOR% : %ARCH%-w64-mingw32-g++.exe ; > %USERPROFILE%\user-config.jam
+SET UPPERFLAVOR=%FLAVOR%
+CALL :TOUPPER UPPERFLAVOR
+
+:: Install packages needed to build boost
+:: Optional: comment out ones this library does not need,
+:: so people can copy this script to another library.
+
+FOR %%a IN ("gcc" "icu" "libiconv" "openssl" "xz" "zlib") DO (
+ c:\msys64\usr\bin\env MSYSTEM=%UPPERFLAVOR% c:\msys64\usr\bin\bash -l -c ^
+ "pacman --sync --needed --noconfirm %FLAVOR%/mingw-w64-%ARCH%-%%a" || EXIT /B
+)
+c:\msys64\usr\bin\env MSYSTEM=%UPPERFLAVOR% c:\msys64\usr\bin\bash -l -c ^
+ "pacman --sync --needed --noconfirm python3" || EXIT /B
+
+::
+:: Now build things...
+::
+
+c:\msys64\usr\bin\env MSYSTEM=%UPPERFLAVOR% c:\msys64\usr\bin\bash -l -c ^
+ "cd %CD:\=/% && ./bootstrap.sh --with-toolset=gcc" || EXIT /B
+
+c:\msys64\usr\bin\env MSYSTEM=%UPPERFLAVOR% c:\msys64\usr\bin\bash -l -c ^
+ "cd %CD:\=/% && ./b2 libs/%SELF% toolset=gcc-%FLAVOR% cxxstd=%CXXSTD% %CXXFLAGS% %DEFINES% %B2_ADDRESS_MODEL% %B2_LINK% %B2_THREADING% %B2_VARIANT% -j3" || EXIT /B
+
+EXIT /B 0
+
+::
+:: Function to uppercase a variable
+:: from: https://stackoverflow.com/questions/34713621/batch-converting-variable-to-uppercase
+::
+
+:TOUPPER <variable>
+@ECHO OFF
+FOR %%a IN ("a=A" "b=B" "c=C" "d=D" "e=E" "f=F" "g=G" "h=H" "i=I"
+ "j=J" "k=K" "l=L" "m=M" "n=N" "o=O" "p=P" "q=Q" "r=R"
+ "s=S" "t=T" "u=U" "v=V" "w=W" "x=X" "y=Y" "z=Z" ) DO ( CALL SET %~1=%%%~1:%%~a%% )
+@ECHO ON
+GOTO :EOF \ No newline at end of file
diff --git a/src/boost/libs/program_options/example/Jamfile.v2 b/src/boost/libs/program_options/example/Jamfile.v2
new file mode 100644
index 000000000..9f0b1d8fa
--- /dev/null
+++ b/src/boost/libs/program_options/example/Jamfile.v2
@@ -0,0 +1,21 @@
+
+project
+ : requirements <library>../build//boost_program_options
+ <hardcode-dll-paths>true
+ <link>static
+ ;
+
+exe first : first.cpp ;
+exe options_description : options_description.cpp ;
+exe multiple_sources : multiple_sources.cpp ;
+exe custom_syntax : custom_syntax.cpp ;
+
+exe real : real.cpp ;
+exe regex : regex.cpp /boost/regex//boost_regex ;
+
+# The following examples use C++ features beyond C++03.
+# It would be possible to make compilation of each conditional on specific config check,
+# for now just disable the compilation.
+#exe config_file_types : config_file_types.cpp ;
+#exe env_options : env_options.cpp ;
+#exe options_heirarchy : options_heirarchy.cpp ;
diff --git a/src/boost/libs/program_options/example/config_file_types.cpp b/src/boost/libs/program_options/example/config_file_types.cpp
new file mode 100644
index 000000000..e466e94a1
--- /dev/null
+++ b/src/boost/libs/program_options/example/config_file_types.cpp
@@ -0,0 +1,242 @@
+// Copyright Thomas Kent 2016
+// 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)
+
+// This example shows a config file (in ini format) being parsed by the
+// program_options library. It includes a numebr of different value types.
+
+#include <boost/program_options.hpp>
+namespace po = boost::program_options;
+
+#include <assert.h>
+#include <iostream>
+#include <sstream>
+using namespace std;
+
+const double FLOAT_SEPERATION = 0.00000000001;
+bool check_float(double test, double expected)
+{
+ double seperation = expected * (1 + FLOAT_SEPERATION) / expected;
+ if ((test < expected + seperation) && (test > expected - seperation))
+ {
+ return true;
+ }
+ return false;
+}
+
+stringstream make_file()
+{
+ stringstream ss;
+ ss << "# This file checks parsing of various types of config values\n";
+ //FAILS: ss << "; a windows style comment\n";
+
+ ss << "global_string = global value\n";
+ ss << "unregistered_entry = unregistered value\n";
+
+ ss << "\n[strings]\n";
+ ss << "word = word\n";
+ ss << "phrase = this is a phrase\n";
+ ss << "quoted = \"quotes are in result\"\n";
+
+ ss << "\n[ints]\n";
+ ss << "positive = 41\n";
+ ss << "negative = -42\n";
+ //FAILS: Lexical cast doesn't support hex, oct, or bin
+ //ss << "hex = 0x43\n";
+ //ss << "oct = 044\n";
+ //ss << "bin = 0b101010\n";
+
+ ss << "\n[floats]\n";
+ ss << "positive = 51.1\n";
+ ss << "negative = -52.1\n";
+ ss << "double = 53.1234567890\n";
+ ss << "int = 54\n";
+ ss << "int_dot = 55.\n";
+ ss << "dot = .56\n";
+ ss << "exp_lower = 57.1e5\n";
+ ss << "exp_upper = 58.1E5\n";
+ ss << "exp_decimal = .591e5\n";
+ ss << "exp_negative = 60.1e-5\n";
+ ss << "exp_negative_val = -61.1e5\n";
+ ss << "exp_negative_negative_val = -62.1e-5\n";
+
+ ss << "\n[booleans]\n";
+ ss << "number_true = 1\n";
+ ss << "number_false = 0\n";
+ ss << "yn_true = yes\n";
+ ss << "yn_false = no\n";
+ ss << "tf_true = true\n";
+ ss << "tf_false = false\n";
+ ss << "onoff_true = on\n";
+ ss << "onoff_false = off\n";
+ ss << "present_equal_true = \n";
+ //FAILS: Must be an =
+ //ss << "present_no_equal_true\n";
+
+ ss.seekp(ios_base::beg);
+ return ss;
+}
+
+po::options_description set_options()
+{
+ po::options_description opts;
+ opts.add_options()
+ ("global_string", po::value<string>())
+
+ ("strings.word", po::value<string>())
+ ("strings.phrase", po::value<string>())
+ ("strings.quoted", po::value<string>())
+
+ ("ints.positive", po::value<int>())
+ ("ints.negative", po::value<int>())
+ ("ints.hex", po::value<int>())
+ ("ints.oct", po::value<int>())
+ ("ints.bin", po::value<int>())
+
+ ("floats.positive", po::value<float>())
+ ("floats.negative", po::value<float>())
+ ("floats.double", po::value<double>())
+ ("floats.int", po::value<float>())
+ ("floats.int_dot", po::value<float>())
+ ("floats.dot", po::value<float>())
+ ("floats.exp_lower", po::value<float>())
+ ("floats.exp_upper", po::value<float>())
+ ("floats.exp_decimal", po::value<float>())
+ ("floats.exp_negative", po::value<float>())
+ ("floats.exp_negative_val", po::value<float>())
+ ("floats.exp_negative_negative_val", po::value<float>())
+
+ // Load booleans as value<bool>, so they will require a --option=value on the command line
+ //("booleans.number_true", po::value<bool>())
+ //("booleans.number_false", po::value<bool>())
+ //("booleans.yn_true", po::value<bool>())
+ //("booleans.yn_false", po::value<bool>())
+ //("booleans.tf_true", po::value<bool>())
+ //("booleans.tf_false", po::value<bool>())
+ //("booleans.onoff_true", po::value<bool>())
+ //("booleans.onoff_false", po::value<bool>())
+ //("booleans.present_equal_true", po::value<bool>())
+ //("booleans.present_no_equal_true", po::value<bool>())
+
+ // Load booleans as bool_switch, so that a --option will set it true on the command line
+ // The difference between these two types does not show up when parsing a file
+ ("booleans.number_true", po::bool_switch())
+ ("booleans.number_false", po::bool_switch())
+ ("booleans.yn_true", po::bool_switch())
+ ("booleans.yn_false", po::bool_switch())
+ ("booleans.tf_true", po::bool_switch())
+ ("booleans.tf_false", po::bool_switch())
+ ("booleans.onoff_true", po::bool_switch())
+ ("booleans.onoff_false", po::bool_switch())
+ ("booleans.present_equal_true", po::bool_switch())
+ ("booleans.present_no_equal_true", po::bool_switch())
+ ;
+ return opts;
+}
+
+vector<string> parse_file(stringstream &file, po::options_description &opts, po::variables_map &vm)
+{
+ const bool ALLOW_UNREGISTERED = true;
+ cout << file.str() << endl;
+
+ po::parsed_options parsed = parse_config_file(file, opts, ALLOW_UNREGISTERED);
+ store(parsed, vm);
+ vector<string> unregistered = po::collect_unrecognized(parsed.options, po::exclude_positional);
+ notify(vm);
+
+ return unregistered;
+}
+
+void check_results(po::variables_map &vm, vector<string> unregistered)
+{
+ // Check that we got the correct values back
+ string expected_global_string = "global value";
+
+ string expected_unreg_option = "unregistered_entry";
+ string expected_unreg_value = "unregistered value";
+
+ string expected_strings_word = "word";
+ string expected_strings_phrase = "this is a phrase";
+ string expected_strings_quoted = "\"quotes are in result\"";
+
+ int expected_int_postitive = 41;
+ int expected_int_negative = -42;
+ int expected_int_hex = 0x43;
+ int expected_int_oct = 044;
+ int expected_int_bin = 0b101010;
+
+ float expected_float_positive = 51.1f;
+ float expected_float_negative = -52.1f;
+ double expected_float_double = 53.1234567890;
+ float expected_float_int = 54.0f;
+ float expected_float_int_dot = 55.0f;
+ float expected_float_dot = .56f;
+ float expected_float_exp_lower = 57.1e5f;
+ float expected_float_exp_upper = 58.1E5f;
+ float expected_float_exp_decimal = .591e5f;
+ float expected_float_exp_negative = 60.1e-5f;
+ float expected_float_exp_negative_val = -61.1e5f;
+ float expected_float_exp_negative_negative_val = -62.1e-5f;
+
+ bool expected_number_true = true;
+ bool expected_number_false = false;
+ bool expected_yn_true = true;
+ bool expected_yn_false = false;
+ bool expected_tf_true = true;
+ bool expected_tf_false = false;
+ bool expected_onoff_true = true;
+ bool expected_onoff_false = false;
+ bool expected_present_equal_true = true;
+ bool expected_present_no_equal_true = true;
+
+ assert(vm["global_string"].as<string>() == expected_global_string);
+
+ assert(unregistered[0] == expected_unreg_option);
+ assert(unregistered[1] == expected_unreg_value);
+
+ assert(vm["strings.word"].as<string>() == expected_strings_word);
+ assert(vm["strings.phrase"].as<string>() == expected_strings_phrase);
+ assert(vm["strings.quoted"].as<string>() == expected_strings_quoted);
+
+ assert(vm["ints.positive"].as<int>() == expected_int_postitive);
+ assert(vm["ints.negative"].as<int>() == expected_int_negative);
+ //assert(vm["ints.hex"].as<int>() == expected_int_hex);
+ //assert(vm["ints.oct"].as<int>() == expected_int_oct);
+ //assert(vm["ints.bin"].as<int>() == expected_int_bin);
+
+ assert(check_float(vm["floats.positive"].as<float>(), expected_float_positive));
+ assert(check_float(vm["floats.negative"].as<float>(), expected_float_negative));
+ assert(check_float(vm["floats.double"].as<double>(), expected_float_double));
+ assert(check_float(vm["floats.int"].as<float>(), expected_float_int));
+ assert(check_float(vm["floats.int_dot"].as<float>(), expected_float_int_dot));
+ assert(check_float(vm["floats.dot"].as<float>(), expected_float_dot));
+ assert(check_float(vm["floats.exp_lower"].as<float>(), expected_float_exp_lower));
+ assert(check_float(vm["floats.exp_upper"].as<float>(), expected_float_exp_upper));
+ assert(check_float(vm["floats.exp_decimal"].as<float>(), expected_float_exp_decimal));
+ assert(check_float(vm["floats.exp_negative"].as<float>(), expected_float_exp_negative));
+ assert(check_float(vm["floats.exp_negative_val"].as<float>(), expected_float_exp_negative_val));
+ assert(check_float(vm["floats.exp_negative_negative_val"].as<float>(), expected_float_exp_negative_negative_val));
+
+ assert(vm["booleans.number_true"].as<bool>() == expected_number_true);
+ assert(vm["booleans.number_false"].as<bool>() == expected_number_false);
+ assert(vm["booleans.yn_true"].as<bool>() == expected_yn_true);
+ assert(vm["booleans.yn_false"].as<bool>() == expected_yn_false);
+ assert(vm["booleans.tf_true"].as<bool>() == expected_tf_true);
+ assert(vm["booleans.tf_false"].as<bool>() == expected_tf_false);
+ assert(vm["booleans.onoff_true"].as<bool>() == expected_onoff_true);
+ assert(vm["booleans.onoff_false"].as<bool>() == expected_onoff_false);
+ assert(vm["booleans.present_equal_true"].as<bool>() == expected_present_equal_true);
+ //assert(vm["booleans.present_no_equal_true"].as<bool>() == expected_present_no_equal_true);
+}
+
+int main(int ac, char* av[])
+{
+ auto file = make_file();
+ auto opts = set_options();
+ po::variables_map vars;
+ auto unregistered = parse_file(file, opts, vars);
+ check_results(vars, unregistered);
+
+ return 0;
+}
diff --git a/src/boost/libs/program_options/example/custom_syntax.cpp b/src/boost/libs/program_options/example/custom_syntax.cpp
new file mode 100644
index 000000000..829087d9d
--- /dev/null
+++ b/src/boost/libs/program_options/example/custom_syntax.cpp
@@ -0,0 +1,63 @@
+// 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)
+
+/** This example shows how to support custom options syntax.
+
+ It's possible to install 'custom_parser'. It will be invoked on all command
+ line tokens and can return name/value pair, or nothing. If it returns
+ nothing, usual processing will be done.
+*/
+
+
+#include <boost/program_options/options_description.hpp>
+#include <boost/program_options/parsers.hpp>
+#include <boost/program_options/variables_map.hpp>
+
+using namespace boost::program_options;
+
+#include <iostream>
+using namespace std;
+
+/* This custom option parse function recognize gcc-style
+ option "-fbar" / "-fno-bar".
+*/
+pair<string, string> reg_foo(const string& s)
+{
+ if (s.find("-f") == 0) {
+ if (s.substr(2, 3) == "no-")
+ return make_pair(s.substr(5), string("false"));
+ else
+ return make_pair(s.substr(2), string("true"));
+ } else {
+ return make_pair(string(), string());
+ }
+}
+
+int main(int ac, char* av[])
+{
+ try {
+ options_description desc("Allowed options");
+ desc.add_options()
+ ("help", "produce a help message")
+ ("foo", value<string>(), "just an option")
+ ;
+
+ variables_map vm;
+ store(command_line_parser(ac, av).options(desc).extra_parser(reg_foo)
+ .run(), vm);
+
+ if (vm.count("help")) {
+ cout << desc;
+ cout << "\nIn addition -ffoo and -fno-foo syntax are recognized.\n";
+ }
+ if (vm.count("foo")) {
+ cout << "foo value with the value of "
+ << vm["foo"].as<string>() << "\n";
+ }
+ }
+ catch(exception& e) {
+ cout << e.what() << "\n";
+ }
+}
diff --git a/src/boost/libs/program_options/example/env_options.cpp b/src/boost/libs/program_options/example/env_options.cpp
new file mode 100644
index 000000000..bab37e252
--- /dev/null
+++ b/src/boost/libs/program_options/example/env_options.cpp
@@ -0,0 +1,47 @@
+// Copyright Thomas Kent 2016
+// 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 <boost/program_options.hpp>
+namespace po = boost::program_options;
+#include <string>
+#include <iostream>
+
+std::string mapper(std::string env_var)
+{
+ // ensure the env_var is all caps
+ std::transform(env_var.begin(), env_var.end(), env_var.begin(), ::toupper);
+
+ if (env_var == "PATH") return "path";
+ if (env_var == "EXAMPLE_VERBOSE") return "verbosity";
+ return "";
+}
+
+void get_env_options()
+{
+ po::options_description config("Configuration");
+ config.add_options()
+ ("path", "the execution path")
+ ("verbosity", po::value<std::string>()->default_value("INFO"), "set verbosity: DEBUG, INFO, WARN, ERROR, FATAL")
+ ;
+
+ po::variables_map vm;
+ store(po::parse_environment(config, boost::function1<std::string, std::string>(mapper)), vm);
+ notify(vm);
+
+ if (vm.count("path"))
+ {
+ std::cout << "First 75 chars of the system path: \n";
+ std::cout << vm["path"].as<std::string>().substr(0, 75) << std::endl;
+ }
+
+ std::cout << "Verbosity: " << vm["verbosity"].as<std::string>() << std::endl;
+}
+
+int main(int ac, char* av[])
+{
+ get_env_options();
+
+ return 0;
+}
diff --git a/src/boost/libs/program_options/example/first.cpp b/src/boost/libs/program_options/example/first.cpp
new file mode 100644
index 000000000..8763fec9c
--- /dev/null
+++ b/src/boost/libs/program_options/example/first.cpp
@@ -0,0 +1,51 @@
+// 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)
+
+/* The simplest usage of the library.
+ */
+
+#include <boost/program_options.hpp>
+namespace po = boost::program_options;
+
+#include <iostream>
+#include <iterator>
+using namespace std;
+
+int main(int ac, char* av[])
+{
+ try {
+
+ po::options_description desc("Allowed options");
+ desc.add_options()
+ ("help", "produce help message")
+ ("compression", po::value<double>(), "set compression level")
+ ;
+
+ po::variables_map vm;
+ po::store(po::parse_command_line(ac, av, desc), vm);
+ po::notify(vm);
+
+ if (vm.count("help")) {
+ cout << desc << "\n";
+ return 0;
+ }
+
+ if (vm.count("compression")) {
+ cout << "Compression level was set to "
+ << vm["compression"].as<double>() << ".\n";
+ } else {
+ cout << "Compression level was not set.\n";
+ }
+ }
+ catch(exception& e) {
+ cerr << "error: " << e.what() << "\n";
+ return 1;
+ }
+ catch(...) {
+ cerr << "Exception of unknown type!\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/program_options/example/multiple_sources.cfg b/src/boost/libs/program_options/example/multiple_sources.cfg
new file mode 100644
index 000000000..6966d0048
--- /dev/null
+++ b/src/boost/libs/program_options/example/multiple_sources.cfg
@@ -0,0 +1,5 @@
+#
+# Comment out this line to use hard-coded default value of 10
+#
+optimization = 1
+include-path = /opt \ No newline at end of file
diff --git a/src/boost/libs/program_options/example/multiple_sources.cpp b/src/boost/libs/program_options/example/multiple_sources.cpp
new file mode 100644
index 000000000..22c8235bc
--- /dev/null
+++ b/src/boost/libs/program_options/example/multiple_sources.cpp
@@ -0,0 +1,121 @@
+// 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)
+
+/* Shows how to use both command line and config file. */
+
+#include <boost/program_options.hpp>
+namespace po = boost::program_options;
+
+
+#include <iostream>
+#include <fstream>
+#include <iterator>
+using namespace std;
+
+// A helper function to simplify the main part.
+template<class T>
+ostream& operator<<(ostream& os, const vector<T>& v)
+{
+ copy(v.begin(), v.end(), ostream_iterator<T>(os, " "));
+ return os;
+}
+
+
+int main(int ac, char* av[])
+{
+ try {
+ int opt;
+ string config_file;
+
+ // Declare a group of options that will be
+ // allowed only on command line
+ po::options_description generic("Generic options");
+ generic.add_options()
+ ("version,v", "print version string")
+ ("help", "produce help message")
+ ("config,c", po::value<string>(&config_file)->default_value("multiple_sources.cfg"),
+ "name of a file of a configuration.")
+ ;
+
+ // Declare a group of options that will be
+ // allowed both on command line and in
+ // config file
+ po::options_description config("Configuration");
+ config.add_options()
+ ("optimization", po::value<int>(&opt)->default_value(10),
+ "optimization level")
+ ("include-path,I",
+ po::value< vector<string> >()->composing(),
+ "include path")
+ ;
+
+ // Hidden options, will be allowed both on command line and
+ // in config file, but will not be shown to the user.
+ po::options_description hidden("Hidden options");
+ hidden.add_options()
+ ("input-file", po::value< vector<string> >(), "input file")
+ ;
+
+
+ po::options_description cmdline_options;
+ cmdline_options.add(generic).add(config).add(hidden);
+
+ po::options_description config_file_options;
+ config_file_options.add(config).add(hidden);
+
+ po::options_description visible("Allowed options");
+ visible.add(generic).add(config);
+
+ po::positional_options_description p;
+ p.add("input-file", -1);
+
+ po::variables_map vm;
+ store(po::command_line_parser(ac, av).
+ options(cmdline_options).positional(p).run(), vm);
+ notify(vm);
+
+ ifstream ifs(config_file.c_str());
+ if (!ifs)
+ {
+ cout << "can not open config file: " << config_file << "\n";
+ return 0;
+ }
+ else
+ {
+ store(parse_config_file(ifs, config_file_options), vm);
+ notify(vm);
+ }
+
+ if (vm.count("help")) {
+ cout << visible << "\n";
+ return 0;
+ }
+
+ if (vm.count("version")) {
+ cout << "Multiple sources example, version 1.0\n";
+ return 0;
+ }
+
+ if (vm.count("include-path"))
+ {
+ cout << "Include paths are: "
+ << vm["include-path"].as< vector<string> >() << "\n";
+ }
+
+ if (vm.count("input-file"))
+ {
+ cout << "Input files are: "
+ << vm["input-file"].as< vector<string> >() << "\n";
+ }
+
+ cout << "Optimization level is " << opt << "\n";
+ }
+ catch(exception& e)
+ {
+ cout << e.what() << "\n";
+ return 1;
+ }
+ return 0;
+}
diff --git a/src/boost/libs/program_options/example/option_groups.cpp b/src/boost/libs/program_options/example/option_groups.cpp
new file mode 100644
index 000000000..63e1fca48
--- /dev/null
+++ b/src/boost/libs/program_options/example/option_groups.cpp
@@ -0,0 +1,97 @@
+// 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)
+
+/** This example shows how to handle options groups.
+
+ For a test, run:
+
+ option_groups --help
+ option_groups --num-threads 10
+ option_groups --help-module backend
+
+ The first invocation would show to option groups, and will not show the
+ '--num-threads' options. The second invocation will still get the value of
+ the hidden '--num-threads' option. Finally, the third invocation will show
+ the options for the 'backend' module, including the '--num-threads' option.
+
+*/
+
+
+#include <boost/program_options/options_description.hpp>
+#include <boost/program_options/parsers.hpp>
+#include <boost/program_options/variables_map.hpp>
+#include <boost/tokenizer.hpp>
+#include <boost/token_functions.hpp>
+using namespace boost;
+using namespace boost::program_options;
+
+#include <iostream>
+#include <fstream>
+#include <exception>
+using namespace std;
+
+int main(int ac, char* av[])
+{
+ try {
+ // Declare three groups of options.
+ options_description general("General options");
+ general.add_options()
+ ("help", "produce a help message")
+ ("help-module", value<string>(),
+ "produce a help for a given module")
+ ("version", "output the version number")
+ ;
+
+ options_description gui("GUI options");
+ gui.add_options()
+ ("display", value<string>(), "display to use")
+ ;
+
+ options_description backend("Backend options");
+ backend.add_options()
+ ("num-threads", value<int>(), "the initial number of threads")
+ ;
+
+ // Declare an options description instance which will include
+ // all the options
+ options_description all("Allowed options");
+ all.add(general).add(gui).add(backend);
+
+ // Declare an options description instance which will be shown
+ // to the user
+ options_description visible("Allowed options");
+ visible.add(general).add(gui);
+
+
+ variables_map vm;
+ store(parse_command_line(ac, av, all), vm);
+
+ if (vm.count("help"))
+ {
+ cout << visible;
+ return 0;
+ }
+ if (vm.count("help-module")) {
+ const string& s = vm["help-module"].as<string>();
+ if (s == "gui") {
+ cout << gui;
+ } else if (s == "backend") {
+ cout << backend;
+ } else {
+ cout << "Unknown module '"
+ << s << "' in the --help-module option\n";
+ return 1;
+ }
+ return 0;
+ }
+ if (vm.count("num-threads")) {
+ cout << "The 'num-threads' options was set to "
+ << vm["num-threads"].as<int>() << "\n";
+ }
+ }
+ catch(std::exception& e) {
+ cout << e.what() << "\n";
+ }
+}
diff --git a/src/boost/libs/program_options/example/options_description.cpp b/src/boost/libs/program_options/example/options_description.cpp
new file mode 100644
index 000000000..e9ad2a67d
--- /dev/null
+++ b/src/boost/libs/program_options/example/options_description.cpp
@@ -0,0 +1,86 @@
+// 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 <boost/program_options.hpp>
+
+using namespace boost;
+namespace po = boost::program_options;
+
+#include <iostream>
+#include <algorithm>
+#include <iterator>
+using namespace std;
+
+
+// A helper function to simplify the main part.
+template<class T>
+ostream& operator<<(ostream& os, const vector<T>& v)
+{
+ copy(v.begin(), v.end(), ostream_iterator<T>(os, " "));
+ return os;
+}
+
+int main(int ac, char* av[])
+{
+ try {
+ int opt;
+ int portnum;
+ po::options_description desc("Allowed options");
+ desc.add_options()
+ ("help", "produce help message")
+ ("optimization", po::value<int>(&opt)->default_value(10),
+ "optimization level")
+ ("verbose,v", po::value<int>()->implicit_value(1),
+ "enable verbosity (optionally specify level)")
+ ("listen,l", po::value<int>(&portnum)->implicit_value(1001)
+ ->default_value(0,"no"),
+ "listen on a port.")
+ ("include-path,I", po::value< vector<string> >(),
+ "include path")
+ ("input-file", po::value< vector<string> >(), "input file")
+ ;
+
+ po::positional_options_description p;
+ p.add("input-file", -1);
+
+ po::variables_map vm;
+ po::store(po::command_line_parser(ac, av).
+ options(desc).positional(p).run(), vm);
+ po::notify(vm);
+
+ if (vm.count("help")) {
+ cout << "Usage: options_description [options]\n";
+ cout << desc;
+ return 0;
+ }
+
+ if (vm.count("include-path"))
+ {
+ cout << "Include paths are: "
+ << vm["include-path"].as< vector<string> >() << "\n";
+ }
+
+ if (vm.count("input-file"))
+ {
+ cout << "Input files are: "
+ << vm["input-file"].as< vector<string> >() << "\n";
+ }
+
+ if (vm.count("verbose")) {
+ cout << "Verbosity enabled. Level is " << vm["verbose"].as<int>()
+ << "\n";
+ }
+
+ cout << "Optimization level is " << opt << "\n";
+
+ cout << "Listen port is " << portnum << "\n";
+ }
+ catch(std::exception& e)
+ {
+ cout << e.what() << "\n";
+ return 1;
+ }
+ return 0;
+}
diff --git a/src/boost/libs/program_options/example/options_heirarchy.cpp b/src/boost/libs/program_options/example/options_heirarchy.cpp
new file mode 100644
index 000000000..c913b149e
--- /dev/null
+++ b/src/boost/libs/program_options/example/options_heirarchy.cpp
@@ -0,0 +1,690 @@
+// Copyright Thomas Kent 2016
+// 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)
+
+//
+// This is an example of a program that uses multiple facets of the boost
+// program_options library. It will go through different types of config
+// options in a heirarchal manner:
+// 1. Default options are set.
+// 2. Command line options are set (they override defaults).
+// 3. Environment options are set (they override defaults but not command
+// line options).
+// 4. Config files specified on the command line are read, if present, in
+// the order specified. (these override defaults but not options from the
+// other steps).
+// 5. Default config file (default.cfg) is read, if present (it overrides
+// defaults but not options from the other steps).
+//
+// See the bottom of this file for full usage examples
+//
+
+#include <boost/program_options.hpp>
+namespace po = boost::program_options;
+#include <string>
+#include <iostream>
+#include <map>
+#include <stdexcept>
+#include <fstream>
+
+const std::string version("1.0");
+
+// Used to exit the program if the help/version option is set
+class OptionsExitsProgram : public std::exception
+{};
+
+struct GuiOpts
+{
+ unsigned int width;
+ unsigned int height;
+};
+
+struct NetworkOpts
+{
+ std::string address;
+ unsigned short port;
+};
+
+class OptionsHeirarchy
+{
+public:
+ // The constructor sets up all the various options that will be parsed
+ OptionsHeirarchy()
+ {
+ SetOptions();
+ }
+
+ // Parse options runs through the heirarchy doing all the parsing
+ void ParseOptions(int argc, char* argv[])
+ {
+ ParseCommandLine(argc, argv);
+ CheckForHelp();
+ CheckForVersion();
+ ParseEnvironment();
+ ParseConfigFiles();
+ ParseDefaultConfigFile();
+ }
+
+ // Below is the interface to access the data, once ParseOptions has been run
+ std::string Path()
+ {
+ return results["path"].as<std::string>();
+ }
+ std::string Verbosity()
+ {
+ return results["verbosity"].as<std::string>();
+ }
+ std::vector<std::string> IncludePath()
+ {
+ if (results.count("include-path"))
+ {
+ return results["include-path"].as<std::vector<std::string>>();
+ }
+ return std::vector<std::string>();
+ }
+ std::string MasterFile()
+ {
+ if (results.count("master-file"))
+ {
+ return results["master-file"].as<std::string>();
+ }
+ return "";
+ }
+ std::vector<std::string> Files()
+ {
+ if (results.count("file"))
+ {
+ return results["file"].as<std::vector<std::string>>();
+ }
+ return std::vector<std::string>();
+ }
+ bool GUI()
+ {
+ if (results["run-gui"].as<bool>())
+ {
+ return true;
+ }
+ return false;
+ }
+ GuiOpts GuiValues()
+ {
+ GuiOpts opts;
+ opts.width = results["gui.width"].as<unsigned int>();
+ opts.height = results["gui.height"].as<unsigned int>();
+ return opts;
+ }
+ NetworkOpts NetworkValues()
+ {
+ NetworkOpts opts;
+ opts.address = results["network.ip"].as<std::string>();
+ opts.port = results["network.port"].as<unsigned short>();
+ return opts;
+ }
+
+private:
+ void SetOptions()
+ {
+ SetCommandLineOptions();
+ SetCommonOptions();
+ SetConfigOnlyOptions();
+ SetEnvMapping();
+ }
+ void SetCommandLineOptions()
+ {
+ command_line_options.add_options()
+ ("help,h", "display this help message")
+ ("version,v", "show program version")
+ ("config,c", po::value<std::vector<std::string>>(),
+ "config files to parse (always parses default.cfg)")
+ ;
+ hidden_command_line_options.add_options()
+ ("master-file", po::value<std::string>())
+ ("file", po::value<std::vector<std::string>>())
+ ;
+ positional_options.add("master-file", 1);
+ positional_options.add("file", -1);
+ }
+ void SetCommonOptions()
+ {
+ common_options.add_options()
+ ("path", po::value<std::string>()->default_value(""),
+ "the execution path to use (imports from environment if not specified)")
+ ("verbosity", po::value<std::string>()->default_value("INFO"),
+ "set verbosity: DEBUG, INFO, WARN, ERROR, FATAL")
+ ("include-path,I", po::value<std::vector<std::string>>()->composing(),
+ "paths to search for include files")
+ ("run-gui", po::bool_switch(), "start the GUI")
+ ;
+ }
+ void SetConfigOnlyOptions()
+ {
+ config_only_options.add_options()
+ ("log-dir", po::value<std::string>()->default_value("log"))
+ ("gui.height", po::value<unsigned int>()->default_value(100))
+ ("gui.width", po::value<unsigned int>()->default_value(100))
+ ("network.ip", po::value<std::string>()->default_value("127.0.0.1"))
+ ("network.port", po::value<unsigned short>()->default_value(12345))
+ ;
+ // Run a parser here (with no command line options) to add these defaults into
+ // results, this way they will be enabled even if no config files are parsed.
+ store(po::command_line_parser(0, 0).options(config_only_options).run(), results);
+ notify(results);
+ }
+ void SetEnvMapping()
+ {
+ env_to_option["PATH"] = "path";
+ env_to_option["EXAMPLE_VERBOSE"] = "verbosity";
+ }
+
+
+ void ParseCommandLine(int argc, char* argv[])
+ {
+ po::options_description cmd_opts;
+ cmd_opts.add(command_line_options).add(hidden_command_line_options).add(common_options);
+ store(po::command_line_parser(argc, argv).
+ options(cmd_opts).positional(positional_options).run(), results);
+ notify(results);
+ }
+ void CheckForHelp()
+ {
+ if (results.count("help"))
+ {
+ PrintHelp();
+ }
+ }
+ void PrintHelp()
+ {
+ std::cout << "Program Options Example" << std::endl;
+ std::cout << "Usage: example [OPTION]... MASTER-FILE [FILE]...\n";
+ std::cout << " or example [OPTION] --run-gui\n";
+ po::options_description help_opts;
+ help_opts.add(command_line_options).add(common_options);
+ std::cout << help_opts << std::endl;
+ throw OptionsExitsProgram();
+ }
+ void CheckForVersion()
+ {
+ if (results.count("version"))
+ {
+ PrintVersion();
+ }
+ }
+ void PrintVersion()
+ {
+ std::cout << "Program Options Example " << version << std::endl;
+ throw OptionsExitsProgram();
+ }
+ void ParseEnvironment()
+ {
+ store(po::parse_environment(common_options,
+ // The next two lines are the crazy syntax to use EnvironmentMapper as
+ // the lookup function for env->config name conversions
+ boost::function1<std::string, std::string>(
+ std::bind1st(std::mem_fun(&OptionsHeirarchy::EnvironmentMapper), this))),
+ results);
+ notify(results);
+ }
+ std::string EnvironmentMapper(std::string env_var)
+ {
+ // ensure the env_var is all caps
+ std::transform(env_var.begin(), env_var.end(), env_var.begin(), ::toupper);
+
+ auto entry = env_to_option.find(env_var);
+ if (entry != env_to_option.end())
+ {
+ return entry->second;
+ }
+ return "";
+ }
+ void ParseConfigFiles()
+ {
+ if (results.count("config"))
+ {
+ auto files = results["config"].as<std::vector<std::string>>();
+ for (auto file = files.begin(); file != files.end(); file++)
+ {
+ LoadAConfigFile(*file);
+ }
+ }
+ }
+ void LoadAConfigFile(std::string filename)
+ {
+ bool ALLOW_UNREGISTERED = true;
+
+ po::options_description config_opts;
+ config_opts.add(config_only_options).add(common_options);
+
+ std::ifstream cfg_file(filename.c_str());
+ if (cfg_file)
+ {
+ store(parse_config_file(cfg_file, config_opts, ALLOW_UNREGISTERED), results);
+ notify(results);
+ }
+ }
+ void ParseDefaultConfigFile()
+ {
+ LoadAConfigFile("default.cfg");
+ }
+
+ std::map<std::string, std::string> env_to_option;
+ po::options_description config_only_options;
+ po::options_description common_options;
+ po::options_description command_line_options;
+ po::options_description hidden_command_line_options;
+ po::positional_options_description positional_options;
+ po::variables_map results;
+};
+
+
+void get_env_options()
+{
+}
+
+void PrintOptions(OptionsHeirarchy options)
+{
+ auto path = options.Path();
+ if (path.length())
+ {
+ std::cout << "First 75 chars of the system path: \n";
+ std::cout << options.Path().substr(0, 75) << std::endl;
+ }
+
+ std::cout << "Verbosity: " << options.Verbosity() << std::endl;
+ std::cout << "Include Path:\n";
+ auto includePaths = options.IncludePath();
+ for (auto path = includePaths.begin(); path != includePaths.end(); path++)
+ {
+ std::cout << " " << *path << std::endl;
+ }
+ std::cout << "Master-File: " << options.MasterFile() << std::endl;
+ std::cout << "Additional Files:\n";
+ auto files = options.Files();
+ for (auto file = files.begin(); file != files.end(); file++)
+ {
+ std::cout << " " << *file << std::endl;
+ }
+
+ std::cout << "GUI Enabled: " << std::boolalpha << options.GUI() << std::endl;
+ if (options.GUI())
+ {
+ auto gui_values = options.GuiValues();
+ std::cout << "GUI Height: " << gui_values.height << std::endl;
+ std::cout << "GUI Width: " << gui_values.width << std::endl;
+ }
+
+ auto network_values = options.NetworkValues();
+ std::cout << "Network Address: " << network_values.address << std::endl;
+ std::cout << "Network Port: " << network_values.port << std::endl;
+}
+
+int main(int ac, char* av[])
+{
+ OptionsHeirarchy options;
+ try
+ {
+ options.ParseOptions(ac, av);
+ PrintOptions(options);
+ }
+ catch (OptionsExitsProgram){}
+
+ return 0;
+}
+
+/*
+Full Usage Examples
+===================
+
+These were run on windows, so some results may show that environment, but
+results should be similar on POSIX platforms.
+
+Help
+----
+To see the help screen, with the available options just pass the --help (or -h)
+parameter. The program will then exit.
+
+ > example.exe --help
+ Program Options Example
+ Usage: example [OPTION]... MASTER-FILE [FILE]...
+ or example [OPTION] --run-gui
+
+ -h [ --help ] display this help message
+ -v [ --version ] show program version
+ -c [ --config ] arg config files to parse (always parses default.cfg)
+
+ --path arg the execution path to use (imports from
+ environment if not specified)
+ --verbosity arg (=INFO) set verbosity: DEBUG, INFO, WARN, ERROR, FATAL
+ -I [ --include-path ] arg paths to search for include files
+ --run-gui start the GUI
+
+Version is similar to help (--version or -v).
+
+ > example.exe -v
+ Program Options Example 1.0
+
+Basics
+------
+Running without any options will get the default values (path is set from the
+environment):
+
+ > example.exe
+ First 75 chars of the system path:
+ C:\Program Files (x86)\MSBuild\14.0\bin;C:\Perl\site\bin;C:\Perl\bin;C:\Pro
+ Verbosity: INFO
+ Include Path:
+ Master-File:
+ Additional Files:
+ GUI Enabled: false
+ Network Address: 127.0.0.1
+ Network Port: 12345
+
+We can easily override that environment path with a simple option:
+
+ > example.exe --path a/b/c;d/e/f
+ First 75 chars of the system path:
+ a/b/c;d/e/f
+ Verbosity: INFO
+ Include Path:
+ Master-File:
+ Additional Files:
+ GUI Enabled: false
+ Network Address: 127.0.0.1
+ Network Port: 12345
+
+You can use a space or equals sign after long options, also backslashes are
+treated literally on windows, on POSIX they need to be escaped.
+
+ > example.exe --path=a\b\c\;d\e\\f
+ First 75 chars of the system path:
+ a\b\c\;d\e\\f
+ Verbosity: INFO
+ Include Path:
+ Master-File:
+ Additional Files:
+ GUI Enabled: false
+ Network Address: 127.0.0.1
+ Network Port: 12345
+
+For short options you can use a space:
+
+ > example.exe -I path/to/includes
+ First 75 chars of the system path:
+ C:\Program Files (x86)\MSBuild\14.0\bin;C:\Perl\site\bin;C:\Perl\bin;C:\Pro
+ Verbosity: INFO
+ Include Path:
+ path\to\includes
+ Master-File:
+ Additional Files:
+ GUI Enabled: false
+ Network Address: 127.0.0.1
+ Network Port: 12345
+
+Or you can put the option immediately after it:
+
+ > example.exe -Ipath/to/includes
+ First 75 chars of the system path:
+ C:\Program Files (x86)\MSBuild\14.0\bin;C:\Perl\site\bin;C:\Perl\bin;C:\Pro
+ Verbosity: INFO
+ Include Path:
+ path\to\includes
+ Master-File:
+ Additional Files:
+ GUI Enabled: false
+ Network Address: 127.0.0.1
+ Network Port: 12345
+
+The include path (--include-path or -I) option allows for multiple paths to be
+specified (both on the command line and in config files) and combined into a
+vector for use by the program.
+
+ > example.exe --include-path=a/b/c --include-path d/e/f -I g/h/i -Ij/k/l
+ First 75 chars of the system path:
+ C:\Program Files (x86)\MSBuild\14.0\bin;C:\Perl\site\bin;C:\Perl\bin;C:\Pro
+ Verbosity: INFO
+ Include Path:
+ a/b/c
+ d/e/f
+ g/h/i
+ j/k/l
+ Master-File:
+ Additional Files:
+ GUI Enabled: false
+ Network Address: 127.0.0.1
+ Network Port: 12345
+
+There are also the option of flags that do not take parameters and just set a
+boolean value to true. In this case, running the gui also causes default values
+for the gui to be output to the screen.
+
+ > example.exe --run-gui
+ First 75 chars of the system path:
+ C:\Program Files (x86)\MSBuild\14.0\bin;C:\Perl\site\bin;C:\Perl\bin;C:\Pro
+ Verbosity: INFO
+ Include Path:
+ Master-File:
+ Additional Files:
+ GUI Enabled: true
+ GUI Height: 100
+ GUI Width: 100
+ Network Address: 127.0.0.1
+ Network Port: 12345
+
+There are also "positional" options at the end of the command line. The first
+one specifies the "master" file the others are additional files.
+
+ > example.exe --path=a-path -I an-include master.cpp additional1.cpp additional2.cpp
+ First 75 chars of the system path:
+ a-path
+ Verbosity: INFO
+ Include Path:
+ an-include
+ Master-File: master.cpp
+ Additional Files:
+ additional1.cpp
+ additional2.cpp
+ GUI Enabled: false
+ Network Address: 127.0.0.1
+ Network Port: 12345
+
+Environment Variables
+---------------------
+In addition to the PATH environment variable, it also knows how to read the
+EXAMPLE_VERBOSE environmental variable and use that to set the verbosity
+option/
+
+ > set EXAMPLE_VERBOSE=DEBUG
+ > example.exe
+ First 75 chars of the system path:
+ C:\Program Files (x86)\MSBuild\14.0\bin;C:\Perl\site\bin;C:\Perl\bin;C:\Pro
+ Verbosity: DEBUG
+ Include Path:
+ Master-File:
+ Additional Files:
+ GUI Enabled: false
+ Network Address: 127.0.0.1
+ Network Port: 12345
+
+However, if the --verboseity flag is also set, it will override the env
+variable. This illustrates an important example, the way program_options works,
+is that a parser will not override a value that has previously been set by
+another parser. Thus the env parser doesn't override the command line parser.
+(We will see this again in config files.) Default values are seperate from this
+heirarcy, they only apply if no parser has set the value and it is being read.
+
+ > set EXAMPLE_VERBOSE=DEBUG
+ > example.exe --verbosity=WARN
+ First 75 chars of the system path:
+ C:\Program Files (x86)\MSBuild\14.0\bin;C:\Perl\site\bin;C:\Perl\bin;C:\Pro
+ Verbosity: WARN
+ Include Path:
+ Master-File:
+ Additional Files:
+ GUI Enabled: false
+ Network Address: 127.0.0.1
+ Network Port: 12345
+
+(You can unset an environmental variable with an empty set command)
+
+ > set EXAMPLE_VERBOSE=
+ > example.exe
+ First 75 chars of the system path:
+ C:\Program Files (x86)\MSBuild\14.0\bin;C:\Perl\site\bin;C:\Perl\bin;C:\Pro
+ Verbosity: INFO
+ Include Path:
+ Master-File:
+ Additional Files:
+ GUI Enabled: false
+ Network Address: 127.0.0.1
+ Network Port: 12345
+
+
+Config Files
+------------
+Config files generally follow the [INI file format]
+(https://en.wikipedia.org/wiki/INI_file) with a few exceptions.
+
+Values can be simply added tp options with an equal sign. Here are two include
+paths added via the default config file (default.cfg), you can have optional
+spaces around the equal sign.
+
+ # You can use comments in a config file
+ include-path=first/default/path
+ include-path = second/default/path
+
+Results in
+
+ > example.exe
+ First 75 chars of the system path:
+ C:\Program Files (x86)\MSBuild\14.0\bin;C:\Perl\site\bin;C:\Perl\bin;C:\Pro
+ Verbosity: INFO
+ Include Path:
+ first/default/path
+ second/default/path
+ Master-File:
+ Additional Files:
+ GUI Enabled: false
+ Network Address: 127.0.0.1
+ Network Port: 12345
+
+Values can also be in sections of the config file. Again, editing default.cfg
+
+ include-path=first/default/path
+ include-path = second/default/path
+
+ [network]
+ ip=1.2.3.4
+ port=3000
+
+Results in
+
+ > example.exe
+ First 75 chars of the system path:
+ C:\Program Files (x86)\MSBuild\14.0\bin;C:\Perl\site\bin;C:\Perl\bin;C:\Pro
+ Verbosity: INFO
+ Include Path:
+ first/default/path
+ second/default/path
+ Master-File:
+ Additional Files:
+ GUI Enabled: false
+ Network Address: 1.2.3.4
+ Network Port: 3000
+
+This example is also setup to allow multiple config files to be specified on
+the command line, which are checked before the default.cfg file is read (but
+after the environment and command line parsing). Thus we can set the first.cfg
+file to contain the following:
+
+ verbosity=ERROR
+
+ [network]
+ ip = 5.6.7.8
+
+Results in:
+
+ > example.exe --config first.cfg
+ First 75 chars of the system path:
+ C:\Program Files (x86)\MSBuild\14.0\bin;C:\Perl\site\bin;C:\Perl\bin;C:\Pro
+ Verbosity: ERROR
+ Include Path:
+ first/default/path
+ second/default/path
+ Master-File:
+ Additional Files:
+ GUI Enabled: false
+ Network Address: 5.6.7.8
+ Network Port: 3000
+
+But since the config files are read after the command line, setting the
+verbosity there causes the value in the file to be ignored.
+
+ > example.exe --config first.cfg --verbosity=WARN
+ First 75 chars of the system path:
+ C:\Program Files (x86)\MSBuild\14.0\bin;C:\Perl\site\bin;C:\Perl\bin;C:\Pro
+ Verbosity: WARN
+ Include Path:
+ first/default/path
+ second/default/path
+ Master-File:
+ Additional Files:
+ GUI Enabled: false
+ Network Address: 5.6.7.8
+ Network Port: 3000
+
+The config files are parsed in the order they are received on the command line.
+So adding the second.cfg file:
+
+ verbosity=FATAL
+ run-gui=true
+
+ [gui]
+ height=720
+ width=1280
+
+Results in a combination of all three config files:
+
+ > example.exe --config first.cfg --config second.cfg
+ First 75 chars of the system path:
+ C:\Program Files (x86)\MSBuild\14.0\bin;C:\Perl\site\bin;C:\Perl\bin;C:\Pro
+ Verbosity: ERROR
+ Include Path:
+ first/default/path
+ second/default/path
+ Master-File:
+ Additional Files:
+ GUI Enabled: true
+ GUI Height: 720
+ GUI Width: 1280
+ Network Address: 5.6.7.8
+ Network Port: 3000
+
+Incidently the boolean run-gui option could have been set a number of ways
+that all result in the C++ boolean value of true:
+
+ run-gui=true
+ run-gui=on
+ run-gui=1
+ run-gui=yes
+ run-gui=
+
+Since run-gui is an option that was set with the bool_switch type, which
+forces its use on the command line without a parameter (i.e. --run-gui instead
+of --run-gui=true) it can't be given a "false" option, bool_switch values can
+only be turned true. If instead we had a value ("my-switch", po::value<bool>())
+that could be set at the command line --my-switch=true or --my-switch=false, or
+any of the other types of boolean keywords true: true, on, 1, yes;
+false: false, off, 0, no. In a config file this could look like:
+
+ my-switch=true
+ my-switch=on
+ my-switch=1
+ my-switch=yes
+ my-switch=
+
+ my-switch=false
+ my-switch=off
+ my-switch=0
+ my-switch=no
+
+*/
diff --git a/src/boost/libs/program_options/example/real.cpp b/src/boost/libs/program_options/example/real.cpp
new file mode 100644
index 000000000..1c5d13221
--- /dev/null
+++ b/src/boost/libs/program_options/example/real.cpp
@@ -0,0 +1,96 @@
+// 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 <boost/program_options.hpp>
+using namespace boost::program_options;
+
+#include <iostream>
+using namespace std;
+
+/* Auxiliary functions for checking input for validity. */
+
+/* Function used to check that 'opt1' and 'opt2' are not specified
+ at the same time. */
+void conflicting_options(const variables_map& vm,
+ const char* opt1, const char* opt2)
+{
+ if (vm.count(opt1) && !vm[opt1].defaulted()
+ && vm.count(opt2) && !vm[opt2].defaulted())
+ throw logic_error(string("Conflicting options '")
+ + opt1 + "' and '" + opt2 + "'.");
+}
+
+/* Function used to check that of 'for_what' is specified, then
+ 'required_option' is specified too. */
+void option_dependency(const variables_map& vm,
+ const char* for_what, const char* required_option)
+{
+ if (vm.count(for_what) && !vm[for_what].defaulted())
+ if (vm.count(required_option) == 0 || vm[required_option].defaulted())
+ throw logic_error(string("Option '") + for_what
+ + "' requires option '" + required_option + "'.");
+}
+
+int main(int argc, char* argv[])
+{
+ try {
+ string ofile;
+ string macrofile, libmakfile;
+ bool t_given = false;
+ bool b_given = false;
+ string mainpackage;
+ string depends = "deps_file";
+ string sources = "src_file";
+ string root = ".";
+
+ options_description desc("Allowed options");
+ desc.add_options()
+ // First parameter describes option name/short name
+ // The second is parameter to option
+ // The third is description
+ ("help,h", "print usage message")
+ ("output,o", value(&ofile), "pathname for output")
+ ("macrofile,m", value(&macrofile), "full pathname of macro.h")
+ ("two,t", bool_switch(&t_given), "preprocess both header and body")
+ ("body,b", bool_switch(&b_given), "preprocess body in the header context")
+ ("libmakfile,l", value(&libmakfile),
+ "write include makefile for library")
+ ("mainpackage,p", value(&mainpackage),
+ "output dependency information")
+ ("depends,d", value(&depends),
+ "write dependencies to <pathname>")
+ ("sources,s", value(&sources), "write source package list to <pathname>")
+ ("root,r", value(&root), "treat <dirname> as project root directory")
+ ;
+
+ variables_map vm;
+ store(parse_command_line(argc, argv, desc), vm);
+
+ if (vm.count("help")) {
+ cout << desc << "\n";
+ return 0;
+ }
+
+ conflicting_options(vm, "output", "two");
+ conflicting_options(vm, "output", "body");
+ conflicting_options(vm, "output", "mainpackage");
+ conflicting_options(vm, "two", "mainpackage");
+ conflicting_options(vm, "body", "mainpackage");
+
+ conflicting_options(vm, "two", "body");
+ conflicting_options(vm, "libmakfile", "mainpackage");
+ conflicting_options(vm, "libmakfile", "mainpackage");
+
+ option_dependency(vm, "depends", "mainpackage");
+ option_dependency(vm, "sources", "mainpackage");
+ option_dependency(vm, "root", "mainpackage");
+
+ cout << "two = " << vm["two"].as<bool>() << "\n";
+ }
+ catch(exception& e) {
+ cerr << e.what() << "\n";
+ }
+}
diff --git a/src/boost/libs/program_options/example/regex.cpp b/src/boost/libs/program_options/example/regex.cpp
new file mode 100644
index 000000000..df98f77a0
--- /dev/null
+++ b/src/boost/libs/program_options/example/regex.cpp
@@ -0,0 +1,101 @@
+// 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)
+
+// This example shows how a user-defined class can be parsed using
+// specific mechanism -- not the iostream operations used by default.
+//
+// A new class 'magic_number' is defined and the 'validate' method is overloaded
+// to validate the values of that class using Boost.Regex.
+// To test, run
+//
+// regex -m 123-456
+// regex -m 123-4567
+//
+// The first invocation should output:
+//
+// The magic is "456"
+//
+// and the second invocation should issue an error message.
+
+#include <boost/program_options.hpp>
+#include <boost/regex.hpp>
+
+using namespace boost;
+using namespace boost::program_options;
+
+#include <iostream>
+using namespace std;
+
+/* Define a completely non-sensical class. */
+struct magic_number {
+public:
+ magic_number(int n) : n(n) {}
+ int n;
+};
+
+/* Overload the 'validate' function for the user-defined class.
+ It makes sure that value is of form XXX-XXX
+ where X are digits and converts the second group to an integer.
+ This has no practical meaning, meant only to show how
+ regex can be used to validate values.
+*/
+void validate(boost::any& v,
+ const std::vector<std::string>& values,
+ magic_number*, int)
+{
+ static regex r("\\d\\d\\d-(\\d\\d\\d)");
+
+ using namespace boost::program_options;
+
+ // Make sure no previous assignment to 'a' was made.
+ validators::check_first_occurrence(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);
+
+ // Do regex match and convert the interesting part to
+ // int.
+ smatch match;
+ if (regex_match(s, match, r)) {
+ v = any(magic_number(lexical_cast<int>(match[1])));
+ } else {
+ throw validation_error(validation_error::invalid_option_value);
+ }
+}
+
+
+int main(int ac, char* av[])
+{
+ try {
+ options_description desc("Allowed options");
+ desc.add_options()
+ ("help", "produce a help screen")
+ ("version,v", "print the version number")
+ ("magic,m", value<magic_number>(),
+ "magic value (in NNN-NNN format)")
+ ;
+
+ variables_map vm;
+ store(parse_command_line(ac, av, desc), vm);
+
+ if (vm.count("help")) {
+ cout << "Usage: regex [options]\n";
+ cout << desc;
+ return 0;
+ }
+ if (vm.count("version")) {
+ cout << "Version 1.\n";
+ return 0;
+ }
+ if (vm.count("magic")) {
+ cout << "The magic is \""
+ << vm["magic"].as<magic_number>().n << "\"\n";
+ }
+ }
+ catch(std::exception& e)
+ {
+ cout << e.what() << "\n";
+ }
+}
diff --git a/src/boost/libs/program_options/example/response_file.cpp b/src/boost/libs/program_options/example/response_file.cpp
new file mode 100644
index 000000000..ce80f76a9
--- /dev/null
+++ b/src/boost/libs/program_options/example/response_file.cpp
@@ -0,0 +1,94 @@
+// 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)
+
+/** This example shows how to handle response file.
+
+ For a test, build and run:
+ response_file -I foo @response_file.rsp
+
+ The expected output is:
+ Include paths: foo bar biz
+
+ Thanks to Hartmut Kaiser who raised the issue of response files
+ and discussed the possible approach.
+*/
+
+
+#include <boost/program_options/options_description.hpp>
+#include <boost/program_options/parsers.hpp>
+#include <boost/program_options/variables_map.hpp>
+#include <boost/tokenizer.hpp>
+#include <boost/token_functions.hpp>
+using namespace boost;
+using namespace boost::program_options;
+
+#include <iostream>
+#include <fstream>
+using namespace std;
+
+// Additional command line parser which interprets '@something' as a
+// option "config-file" with the value "something"
+pair<string, string> at_option_parser(string const&s)
+{
+ if ('@' == s[0])
+ return std::make_pair(string("response-file"), s.substr(1));
+ else
+ return pair<string, string>();
+}
+
+int main(int ac, char* av[])
+{
+ try {
+ options_description desc("Allowed options");
+ desc.add_options()
+ ("help", "produce a help message")
+ ("include-path,I", value< vector<string> >()->composing(),
+ "include path")
+ ("magic", value<int>(), "magic value")
+ ("response-file", value<string>(),
+ "can be specified with '@name', too")
+ ;
+
+ variables_map vm;
+ store(command_line_parser(ac, av).options(desc)
+ .extra_parser(at_option_parser).run(), vm);
+
+ if (vm.count("help")) {
+ cout << desc;
+ }
+ if (vm.count("response-file")) {
+ // Load the file and tokenize it
+ ifstream ifs(vm["response-file"].as<string>().c_str());
+ if (!ifs) {
+ cout << "Could not open the response file\n";
+ return 1;
+ }
+ // Read the whole file into a string
+ stringstream ss;
+ ss << ifs.rdbuf();
+ // Split the file content
+ char_separator<char> sep(" \n\r");
+ string sstr = ss.str();
+ tokenizer<char_separator<char> > tok(sstr, sep);
+ vector<string> args;
+ copy(tok.begin(), tok.end(), back_inserter(args));
+ // Parse the file and store the options
+ store(command_line_parser(args).options(desc).run(), vm);
+ }
+
+ if (vm.count("include-path")) {
+ const vector<string>& s = vm["include-path"].as<vector< string> >();
+ cout << "Include paths: ";
+ copy(s.begin(), s.end(), ostream_iterator<string>(cout, " "));
+ cout << "\n";
+ }
+ if (vm.count("magic")) {
+ cout << "Magic value: " << vm["magic"].as<int>() << "\n";
+ }
+ }
+ catch (std::exception& e) {
+ cout << e.what() << "\n";
+ }
+}
diff --git a/src/boost/libs/program_options/example/response_file.rsp b/src/boost/libs/program_options/example/response_file.rsp
new file mode 100644
index 000000000..d7c677730
--- /dev/null
+++ b/src/boost/libs/program_options/example/response_file.rsp
@@ -0,0 +1,3 @@
+-I bar
+-I biz
+--magic 10 \ No newline at end of file
diff --git a/src/boost/libs/program_options/index.html b/src/boost/libs/program_options/index.html
new file mode 100644
index 000000000..66cb529e4
--- /dev/null
+++ b/src/boost/libs/program_options/index.html
@@ -0,0 +1,14 @@
+<html>
+<head>
+<meta http-equiv="refresh" content="0; URL=../../doc/html/program_options.html">
+</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>
+</body>
+</html> \ No newline at end of file
diff --git a/src/boost/libs/program_options/meta/libraries.json b/src/boost/libs/program_options/meta/libraries.json
new file mode 100644
index 000000000..5fbf31268
--- /dev/null
+++ b/src/boost/libs/program_options/meta/libraries.json
@@ -0,0 +1,15 @@
+{
+ "key": "program_options",
+ "name": "Program Options",
+ "authors": [
+ "Vladimir Prus"
+ ],
+ "description": "The program_options library allows program developers to obtain program options, that is (name, value) pairs from the user, via conventional methods such as command line and config file.",
+ "category": [
+ "IO",
+ "Miscellaneous"
+ ],
+ "maintainers": [
+ "Vladimir Prus <vladimir.prus -at- gmail.com>"
+ ]
+}
diff --git a/src/boost/libs/program_options/src/cmdline.cpp b/src/boost/libs/program_options/src/cmdline.cpp
new file mode 100644
index 000000000..c2cf1da11
--- /dev/null
+++ b/src/boost/libs/program_options/src/cmdline.cpp
@@ -0,0 +1,713 @@
+// 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)
+
+#define BOOST_PROGRAM_OPTIONS_SOURCE
+#include <boost/program_options/config.hpp>
+
+#include <boost/config.hpp>
+
+#include <boost/program_options/detail/cmdline.hpp>
+#include <boost/program_options/errors.hpp>
+#include <boost/program_options/value_semantic.hpp>
+#include <boost/program_options/options_description.hpp>
+#include <boost/program_options/positional_options.hpp>
+#include <boost/throw_exception.hpp>
+
+#include <boost/bind.hpp>
+
+#include <string>
+#include <utility>
+#include <vector>
+#include <cassert>
+#include <cstring>
+#include <cctype>
+#include <climits>
+
+#include <cstdio>
+
+#include <iostream>
+
+namespace boost { namespace program_options {
+
+ using namespace std;
+ using namespace boost::program_options::command_line_style;
+
+
+ string
+ invalid_syntax::get_template(kind_t kind)
+ {
+ // Initially, store the message in 'const char*' variable,
+ // to avoid conversion to string in all cases.
+ const char* msg;
+ switch(kind)
+ {
+ case empty_adjacent_parameter:
+ msg = "the argument for option '%canonical_option%' should follow immediately after the equal sign";
+ break;
+ case missing_parameter:
+ msg = "the required argument for option '%canonical_option%' is missing";
+ break;
+ case unrecognized_line:
+ msg = "the options configuration file contains an invalid line '%invalid_line%'";
+ break;
+ // none of the following are currently used:
+ case long_not_allowed:
+ msg = "the unabbreviated option '%canonical_option%' is not valid";
+ break;
+ case long_adjacent_not_allowed:
+ msg = "the unabbreviated option '%canonical_option%' does not take any arguments";
+ break;
+ case short_adjacent_not_allowed:
+ msg = "the abbreviated option '%canonical_option%' does not take any arguments";
+ break;
+ case extra_parameter:
+ msg = "option '%canonical_option%' does not take any arguments";
+ break;
+ default:
+ msg = "unknown command line syntax error for '%s'";
+ }
+ return msg;
+ }
+
+
+}}
+
+
+namespace boost { namespace program_options { namespace detail {
+
+ // vc6 needs this, but borland chokes when this is added.
+#if BOOST_WORKAROUND(_MSC_VER, < 1300)
+ using namespace std;
+ using namespace program_options;
+#endif
+
+
+ cmdline::cmdline(const vector<string>& args)
+ {
+ init(args);
+ }
+
+ cmdline::cmdline(int argc, const char*const * argv)
+ {
+#if defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)
+ vector<string> args;
+ copy(argv+1, argv+argc+!argc, inserter(args, args.end()));
+ init(args);
+#else
+ init(vector<string>(argv+1, argv+argc+!argc));
+#endif
+ }
+
+ void
+ cmdline::init(const vector<string>& args)
+ {
+ this->m_args = args;
+ m_style = command_line_style::default_style;
+ m_desc = 0;
+ m_positional = 0;
+ m_allow_unregistered = false;
+ }
+
+ void
+ cmdline::style(int style)
+ {
+ if (style == 0)
+ style = default_style;
+
+ check_style(style);
+ this->m_style = style_t(style);
+ }
+
+ void
+ cmdline::allow_unregistered()
+ {
+ this->m_allow_unregistered = true;
+ }
+
+ void
+ cmdline::check_style(int style) const
+ {
+ bool allow_some_long =
+ (style & allow_long) || (style & allow_long_disguise);
+
+ const char* error = 0;
+ if (allow_some_long &&
+ !(style & long_allow_adjacent) && !(style & long_allow_next))
+ error = "boost::program_options misconfiguration: "
+ "choose one or other of 'command_line_style::long_allow_next' "
+ "(whitespace separated arguments) or "
+ "'command_line_style::long_allow_adjacent' ('=' separated arguments) for "
+ "long options.";
+
+ if (!error && (style & allow_short) &&
+ !(style & short_allow_adjacent) && !(style & short_allow_next))
+ error = "boost::program_options misconfiguration: "
+ "choose one or other of 'command_line_style::short_allow_next' "
+ "(whitespace separated arguments) or "
+ "'command_line_style::short_allow_adjacent' ('=' separated arguments) for "
+ "short options.";
+
+ if (!error && (style & allow_short) &&
+ !(style & allow_dash_for_short) && !(style & allow_slash_for_short))
+ error = "boost::program_options misconfiguration: "
+ "choose one or other of 'command_line_style::allow_slash_for_short' "
+ "(slashes) or 'command_line_style::allow_dash_for_short' (dashes) for "
+ "short options.";
+
+ if (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
+ }
+
+ bool
+ cmdline::is_style_active(style_t style) const
+ {
+ return ((m_style & style) ? true : false);
+ }
+
+ void
+ cmdline::set_options_description(const options_description& desc)
+ {
+ m_desc = &desc;
+ }
+
+ void
+ cmdline::set_positional_options(
+ const positional_options_description& positional)
+ {
+ m_positional = &positional;
+ }
+
+ int
+ cmdline::get_canonical_option_prefix()
+ {
+ if (m_style & allow_long)
+ return allow_long;
+
+ if (m_style & allow_long_disguise)
+ return allow_long_disguise;
+
+ if ((m_style & allow_short) && (m_style & allow_dash_for_short))
+ return allow_dash_for_short;
+
+ if ((m_style & allow_short) && (m_style & allow_slash_for_short))
+ return allow_slash_for_short;
+
+ return 0;
+ }
+
+ vector<option>
+ cmdline::run()
+ {
+ // The parsing is done by having a set of 'style parsers'
+ // and trying then in order. Each parser is passed a vector
+ // of unparsed tokens and can consume some of them (by
+ // removing elements on front) and return a vector of options.
+ //
+ // We try each style parser in turn, untill some input
+ // is consumed. The returned vector of option may contain the
+ // result of just syntactic parsing of token, say --foo will
+ // be parsed as option with name 'foo', and the style parser
+ // is not required to care if that option is defined, and how
+ // many tokens the value may take.
+ // So, after vector is returned, we validate them.
+ assert(m_desc);
+
+ vector<style_parser> style_parsers;
+
+ if (m_style_parser)
+ style_parsers.push_back(m_style_parser);
+
+ if (m_additional_parser)
+ style_parsers.push_back(
+ boost::bind(&cmdline::handle_additional_parser, this, _1));
+
+ if (m_style & allow_long)
+ style_parsers.push_back(
+ boost::bind(&cmdline::parse_long_option, this, _1));
+
+ if ((m_style & allow_long_disguise))
+ style_parsers.push_back(
+ boost::bind(&cmdline::parse_disguised_long_option, this, _1));
+
+ if ((m_style & allow_short) && (m_style & allow_dash_for_short))
+ style_parsers.push_back(
+ boost::bind(&cmdline::parse_short_option, this, _1));
+
+ if ((m_style & allow_short) && (m_style & allow_slash_for_short))
+ style_parsers.push_back(boost::bind(&cmdline::parse_dos_option, this, _1));
+
+ style_parsers.push_back(boost::bind(&cmdline::parse_terminator, this, _1));
+
+ vector<option> result;
+ vector<string>& args = m_args;
+ while(!args.empty())
+ {
+ bool ok = false;
+ for(unsigned i = 0; i < style_parsers.size(); ++i)
+ {
+ unsigned current_size = static_cast<unsigned>(args.size());
+ vector<option> next = style_parsers[i](args);
+
+ // Check that option names
+ // are valid, and that all values are in place.
+ if (!next.empty())
+ {
+ vector<string> e;
+ for(unsigned k = 0; k < next.size()-1; ++k) {
+ finish_option(next[k], e, style_parsers);
+ }
+ // For the last option, pass the unparsed tokens
+ // so that they can be added to next.back()'s values
+ // if appropriate.
+ finish_option(next.back(), args, style_parsers);
+ for (unsigned j = 0; j < next.size(); ++j)
+ result.push_back(next[j]);
+ }
+
+ if (args.size() != current_size) {
+ ok = true;
+ break;
+ }
+ }
+
+ if (!ok) {
+ option opt;
+ opt.value.push_back(args[0]);
+ opt.original_tokens.push_back(args[0]);
+ result.push_back(opt);
+ args.erase(args.begin());
+ }
+ }
+
+ /* If an key option is followed by a positional option,
+ can can consume more tokens (e.g. it's multitoken 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;
+ try
+ {
+ xd = m_desc->find_nothrow(opt.string_key,
+ is_style_active(allow_guessing),
+ is_style_active(long_case_insensitive),
+ is_style_active(short_case_insensitive));
+ }
+ catch(error_with_option_name& e)
+ {
+ // add context and rethrow
+ e.add_context(opt.string_key, opt.original_tokens[0], get_canonical_option_prefix());
+ throw;
+ }
+
+ 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 - static_cast<int>(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) {
+ if (result[i].string_key.empty())
+ result[i].position_key = position_key++;
+ }
+
+ if (m_positional)
+ {
+ unsigned position = 0;
+ for (unsigned i = 0; i < result.size(); ++i) {
+ option& opt = result[i];
+ if (opt.position_key != -1) {
+ if (position >= m_positional->max_total_count())
+ {
+ boost::throw_exception(too_many_positional_options_error());
+ }
+ opt.string_key = m_positional->name_for_position(position);
+ ++position;
+ }
+ }
+ }
+
+ // set case sensitive flag
+ for (unsigned i = 0; i < result.size(); ++i) {
+ if (result[i].string_key.size() > 2 ||
+ (result[i].string_key.size() > 1 && result[i].string_key[0] != '-'))
+ {
+ // it is a long option
+ result[i].case_insensitive = is_style_active(long_case_insensitive);
+ }
+ else
+ {
+ // it is a short option
+ result[i].case_insensitive = is_style_active(short_case_insensitive);
+ }
+ }
+
+ return result;
+ }
+
+ void
+ cmdline::finish_option(option& opt,
+ vector<string>& other_tokens,
+ const vector<style_parser>& style_parsers)
+ {
+ if (opt.string_key.empty())
+ return;
+
+ //
+ // Be defensive:
+ // will have no original token if option created by handle_additional_parser()
+ std::string original_token_for_exceptions = opt.string_key;
+ if (opt.original_tokens.size())
+ original_token_for_exceptions = opt.original_tokens[0];
+
+ try
+ {
+ // First check that the option is valid, and get its description.
+ const option_description* xd = m_desc->find_nothrow(opt.string_key,
+ is_style_active(allow_guessing),
+ is_style_active(long_case_insensitive),
+ is_style_active(short_case_insensitive));
+
+ if (!xd)
+ {
+ if (m_allow_unregistered) {
+ opt.unregistered = true;
+ return;
+ } else {
+ boost::throw_exception(unknown_option());
+ }
+ }
+ const option_description& d = *xd;
+
+ // Canonize the name
+ opt.string_key = d.key(opt.string_key);
+
+ // We check that the min/max number of tokens for the option
+ // agrees with the number of tokens we have. The 'adjacent_value'
+ // (the value in --foo=1) counts as a separate token, and if present
+ // must be consumed. The following tokens on the command line may be
+ // left unconsumed.
+ unsigned min_tokens = d.semantic()->min_tokens();
+ unsigned max_tokens = d.semantic()->max_tokens();
+
+ unsigned present_tokens = static_cast<unsigned>(opt.value.size() + other_tokens.size());
+
+ if (present_tokens >= min_tokens)
+ {
+ if (!opt.value.empty() && max_tokens == 0)
+ {
+ boost::throw_exception(
+ invalid_command_line_syntax(invalid_command_line_syntax::extra_parameter));
+ }
+
+ // Grab min_tokens values from other_tokens, but only if those tokens
+ // are not recognized as options themselves.
+ if (opt.value.size() <= min_tokens)
+ {
+ min_tokens -= static_cast<unsigned>(opt.value.size());
+ }
+ else
+ {
+ min_tokens = 0;
+ }
+
+ // Everything's OK, move the values to the result.
+ for(;!other_tokens.empty() && min_tokens--; )
+ {
+ // check if extra parameter looks like a known option
+ // we use style parsers to check if it is syntactically an option,
+ // additionally we check if an option_description exists
+ vector<option> followed_option;
+ vector<string> next_token(1, other_tokens[0]);
+ for (unsigned i = 0; followed_option.empty() && i < style_parsers.size(); ++i)
+ {
+ followed_option = style_parsers[i](next_token);
+ }
+ if (!followed_option.empty())
+ {
+ original_token_for_exceptions = other_tokens[0];
+ const option_description* od = m_desc->find_nothrow(other_tokens[0],
+ is_style_active(allow_guessing),
+ is_style_active(long_case_insensitive),
+ is_style_active(short_case_insensitive));
+ if (od)
+ boost::throw_exception(
+ invalid_command_line_syntax(invalid_command_line_syntax::missing_parameter));
+ }
+ opt.value.push_back(other_tokens[0]);
+ opt.original_tokens.push_back(other_tokens[0]);
+ other_tokens.erase(other_tokens.begin());
+ }
+ }
+ else
+ {
+ boost::throw_exception(
+ invalid_command_line_syntax(invalid_command_line_syntax::missing_parameter));
+
+ }
+ }
+ // use only original token for unknown_option / ambiguous_option since by definition
+ // they are unrecognised / unparsable
+ catch(error_with_option_name& e)
+ {
+ // add context and rethrow
+ e.add_context(opt.string_key, original_token_for_exceptions, get_canonical_option_prefix());
+ throw;
+ }
+
+ }
+
+ vector<option>
+ cmdline::parse_long_option(vector<string>& args)
+ {
+ vector<option> result;
+ const string& tok = args[0];
+ if (tok.size() >= 3 && tok[0] == '-' && tok[1] == '-')
+ {
+ string name, adjacent;
+
+ string::size_type p = tok.find('=');
+ if (p != tok.npos)
+ {
+ name = tok.substr(2, p-2);
+ adjacent = tok.substr(p+1);
+ if (adjacent.empty())
+ boost::throw_exception( invalid_command_line_syntax(
+ invalid_command_line_syntax::empty_adjacent_parameter,
+ name,
+ name,
+ get_canonical_option_prefix()) );
+ }
+ else
+ {
+ name = tok.substr(2);
+ }
+ option opt;
+ opt.string_key = name;
+ if (!adjacent.empty())
+ opt.value.push_back(adjacent);
+ opt.original_tokens.push_back(tok);
+ result.push_back(opt);
+ args.erase(args.begin());
+ }
+ return result;
+ }
+
+
+ vector<option>
+ cmdline::parse_short_option(vector<string>& args)
+ {
+ const string& tok = args[0];
+ if (tok.size() >= 2 && tok[0] == '-' && tok[1] != '-')
+ {
+ vector<option> result;
+
+ string name = tok.substr(0,2);
+ string adjacent = tok.substr(2);
+
+ // Short options can be 'grouped', so that
+ // "-d -a" becomes "-da". Loop, processing one
+ // option at a time. We exit the loop when either
+ // we've processed all the token, or when the remainder
+ // of token is considered to be value, not further grouped
+ // option.
+ for(;;) {
+ const option_description* d;
+ try
+ {
+
+ d = m_desc->find_nothrow(name, false, false,
+ is_style_active(short_case_insensitive));
+ }
+ catch(error_with_option_name& e)
+ {
+ // add context and rethrow
+ e.add_context(name, name, get_canonical_option_prefix());
+ throw;
+ }
+
+
+ // FIXME: check for 'allow_sticky'.
+ if (d && (m_style & allow_sticky) &&
+ d->semantic()->max_tokens() == 0 && !adjacent.empty()) {
+ // 'adjacent' is in fact further option.
+ option opt;
+ opt.string_key = name;
+ result.push_back(opt);
+
+ if (adjacent.empty())
+ {
+ args.erase(args.begin());
+ break;
+ }
+
+ name = string("-") + adjacent[0];
+ adjacent.erase(adjacent.begin());
+ } else {
+
+ option opt;
+ opt.string_key = name;
+ opt.original_tokens.push_back(tok);
+ if (!adjacent.empty())
+ opt.value.push_back(adjacent);
+ result.push_back(opt);
+ args.erase(args.begin());
+ break;
+ }
+ }
+ return result;
+ }
+ return vector<option>();
+ }
+
+ vector<option>
+ cmdline::parse_dos_option(vector<string>& args)
+ {
+ vector<option> result;
+ const string& tok = args[0];
+ if (tok.size() >= 2 && tok[0] == '/')
+ {
+ string name = "-" + tok.substr(1,1);
+ string adjacent = tok.substr(2);
+
+ option opt;
+ opt.string_key = name;
+ if (!adjacent.empty())
+ opt.value.push_back(adjacent);
+ opt.original_tokens.push_back(tok);
+ result.push_back(opt);
+ args.erase(args.begin());
+ }
+ return result;
+ }
+
+ vector<option>
+ cmdline::parse_disguised_long_option(vector<string>& args)
+ {
+ const string& tok = args[0];
+ if (tok.size() >= 2 &&
+ ((tok[0] == '-' && tok[1] != '-') ||
+ ((m_style & allow_slash_for_short) && tok[0] == '/')))
+ {
+ try
+ {
+ if (m_desc->find_nothrow(tok.substr(1, tok.find('=')-1),
+ is_style_active(allow_guessing),
+ is_style_active(long_case_insensitive),
+ is_style_active(short_case_insensitive)))
+ {
+ args[0].insert(0, "-");
+ if (args[0][1] == '/')
+ args[0][1] = '-';
+ return parse_long_option(args);
+ }
+ }
+ catch(error_with_option_name& e)
+ {
+ // add context and rethrow
+ e.add_context(tok, tok, get_canonical_option_prefix());
+ throw;
+ }
+ }
+ return vector<option>();
+ }
+
+ vector<option>
+ cmdline::parse_terminator(vector<string>& args)
+ {
+ vector<option> result;
+ const string& tok = args[0];
+ if (tok == "--")
+ {
+ for(unsigned i = 1; i < args.size(); ++i)
+ {
+ 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();
+ }
+ return result;
+ }
+
+ vector<option>
+ cmdline::handle_additional_parser(vector<string>& args)
+ {
+ vector<option> result;
+ pair<string, string> r = m_additional_parser(args[0]);
+ if (!r.first.empty()) {
+ option next;
+ next.string_key = r.first;
+ if (!r.second.empty())
+ next.value.push_back(r.second);
+ result.push_back(next);
+ args.erase(args.begin());
+ }
+ return result;
+ }
+
+ void
+ cmdline::set_additional_parser(additional_parser p)
+ {
+ m_additional_parser = p;
+ }
+
+ void
+ cmdline::extra_style_parser(style_parser s)
+ {
+ m_style_parser = s;
+ }
+
+
+
+}}}
diff --git a/src/boost/libs/program_options/src/config_file.cpp b/src/boost/libs/program_options/src/config_file.cpp
new file mode 100644
index 000000000..f2a57b4b8
--- /dev/null
+++ b/src/boost/libs/program_options/src/config_file.cpp
@@ -0,0 +1,198 @@
+// 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)
+
+
+#define BOOST_PROGRAM_OPTIONS_SOURCE
+#include <boost/program_options/config.hpp>
+
+#include <boost/program_options/detail/config_file.hpp>
+#include <boost/program_options/errors.hpp>
+#include <boost/program_options/detail/convert.hpp>
+#include <boost/throw_exception.hpp>
+
+#include <iostream>
+#include <fstream>
+#include <cassert>
+
+namespace boost { namespace program_options { namespace detail {
+
+ using namespace std;
+
+ common_config_file_iterator::common_config_file_iterator(
+ const std::set<std::string>& allowed_options,
+ bool allow_unregistered)
+ : allowed_options(allowed_options),
+ m_allow_unregistered(allow_unregistered)
+ {
+ for(std::set<std::string>::const_iterator i = allowed_options.begin();
+ i != allowed_options.end();
+ ++i)
+ {
+ add_option(i->c_str());
+ }
+ }
+
+ void
+ common_config_file_iterator::add_option(const char* name)
+ {
+ string s(name);
+ assert(!s.empty());
+ if (*s.rbegin() == '*') {
+ s.resize(s.size()-1);
+ bool bad_prefixes(false);
+ // If 's' is a prefix of one of allowed suffix, then
+ // lower_bound will return that element.
+ // If some element is prefix of 's', then lower_bound will
+ // return the next element.
+ set<string>::iterator i = allowed_prefixes.lower_bound(s);
+ if (i != allowed_prefixes.end()) {
+ if (i->find(s) == 0)
+ bad_prefixes = true;
+ }
+ if (i != allowed_prefixes.begin()) {
+ --i;
+ if (s.find(*i) == 0)
+ bad_prefixes = true;
+ }
+ if (bad_prefixes)
+ boost::throw_exception(error("options '" + string(name) + "' and '" +
+ *i + "*' will both match the same "
+ "arguments from the configuration file"));
+ allowed_prefixes.insert(s);
+ }
+ }
+
+ namespace {
+ string trim_ws(const string& s)
+ {
+ string::size_type n, n2;
+ n = s.find_first_not_of(" \t\r\n");
+ if (n == string::npos)
+ return string();
+ else {
+ n2 = s.find_last_not_of(" \t\r\n");
+ return s.substr(n, n2-n+1);
+ }
+ }
+ }
+
+
+ void common_config_file_iterator::get()
+ {
+ string s;
+ string::size_type n;
+ bool found = false;
+
+ while(this->getline(s)) {
+
+ // strip '#' comments and whitespace
+ if ((n = s.find('#')) != string::npos)
+ s = s.substr(0, n);
+ s = trim_ws(s);
+
+ if (!s.empty()) {
+ // Handle section name
+ if (*s.begin() == '[' && *s.rbegin() == ']') {
+ m_prefix = s.substr(1, s.size()-2);
+ if (*m_prefix.rbegin() != '.')
+ m_prefix += '.';
+ }
+ else if ((n = s.find('=')) != string::npos) {
+
+ string name = m_prefix + trim_ws(s.substr(0, n));
+ string value = trim_ws(s.substr(n+1));
+
+ bool registered = allowed_option(name);
+ if (!registered && !m_allow_unregistered)
+ boost::throw_exception(unknown_option(name));
+
+ found = true;
+ this->value().string_key = name;
+ this->value().value.clear();
+ this->value().value.push_back(value);
+ this->value().unregistered = !registered;
+ this->value().original_tokens.clear();
+ this->value().original_tokens.push_back(name);
+ this->value().original_tokens.push_back(value);
+ break;
+
+ } else {
+ boost::throw_exception(invalid_config_file_syntax(s, invalid_syntax::unrecognized_line));
+ }
+ }
+ }
+ if (!found)
+ found_eof();
+ }
+
+
+ bool
+ common_config_file_iterator::allowed_option(const std::string& s) const
+ {
+ set<string>::const_iterator i = allowed_options.find(s);
+ if (i != allowed_options.end())
+ return true;
+ // If s is "pa" where "p" is allowed prefix then
+ // lower_bound should find the element after "p".
+ // This depends on 'allowed_prefixes' invariant.
+ i = allowed_prefixes.lower_bound(s);
+ if (i != allowed_prefixes.begin() && s.find(*--i) == 0)
+ return true;
+ return false;
+ }
+
+#if BOOST_WORKAROUND(__COMO_VERSION__, BOOST_TESTED_AT(4303)) || \
+ (defined(__sgi) && BOOST_WORKAROUND(_COMPILER_VERSION, BOOST_TESTED_AT(741)))
+ template<>
+ bool
+ basic_config_file_iterator<wchar_t>::getline(std::string& s)
+ {
+ std::wstring ws;
+ // On Comeau, using two-argument version causes
+ // call to some internal function with std::wstring, and '\n'
+ // (not L'\n') and compile can't resolve that call.
+
+ if (std::getline(*is, ws, L'\n')) {
+ s = to_utf8(ws);
+ return true;
+ } else {
+ return false;
+ }
+ }
+#endif
+
+}}}
+
+#if 0
+using boost::program_options::config_file;
+
+#include <sstream>
+#include <cassert>
+
+int main()
+{
+ try {
+ stringstream s(
+ "a = 1\n"
+ "b = 2\n");
+
+ config_file cf(s);
+ cf.add_option("a");
+ cf.add_option("b");
+
+ assert(++cf);
+ assert(cf.name() == "a");
+ assert(cf.value() == "1");
+ assert(++cf);
+ assert(cf.name() == "b");
+ assert(cf.value() == "2");
+ assert(!++cf);
+ }
+ catch(exception& e)
+ {
+ cout << e.what() << "\n";
+ }
+}
+#endif
diff --git a/src/boost/libs/program_options/src/convert.cpp b/src/boost/libs/program_options/src/convert.cpp
new file mode 100644
index 000000000..9be759e26
--- /dev/null
+++ b/src/boost/libs/program_options/src/convert.cpp
@@ -0,0 +1,161 @@
+// Copyright Vladimir Prus 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 <fstream>
+#include <locale.h>
+#include <locale>
+#include <iostream>
+#include <string>
+#include <locale>
+#include <stdexcept>
+
+#include <boost/config.hpp>
+
+#define BOOST_PROGRAM_OPTIONS_SOURCE
+#include <boost/program_options/config.hpp>
+#include <boost/program_options/detail/convert.hpp>
+#include <boost/program_options/detail/utf8_codecvt_facet.hpp>
+#include <boost/throw_exception.hpp>
+
+#include <boost/bind.hpp>
+
+using namespace std;
+
+namespace boost { namespace detail {
+
+ /* Internal function to actually perform conversion.
+ The logic in from_8_bit and to_8_bit function is exactly
+ the same, except that one calls 'in' method of codecvt and another
+ calls the 'out' method, and that syntax difference makes straightforward
+ template implementation impossible.
+
+ This functions takes a 'fun' argument, which should have the same
+ parameters and return type and the in/out methods. The actual converting
+ function will pass functional objects created with boost::bind.
+ Experiments show that the performance loss is less than 10%.
+ */
+ template<class ToChar, class FromChar, class Fun>
+ std::basic_string<ToChar>
+ convert(const std::basic_string<FromChar>& s, Fun fun)
+
+ {
+ std::basic_string<ToChar> result;
+
+ std::mbstate_t state = std::mbstate_t();
+
+ const FromChar* from = s.data();
+ const FromChar* from_end = s.data() + s.size();
+ // The interface of cvt is not really iterator-like, and it's
+ // not possible the tell the required output size without the conversion.
+ // All we can is convert data by pieces.
+ while(from != from_end) {
+
+ // std::basic_string does not provide non-const pointers to the data,
+ // so converting directly into string is not possible.
+ ToChar buffer[32];
+
+ ToChar* to_next = buffer;
+ // Need variable because boost::bind doesn't work with rvalues.
+ ToChar* to_end = buffer + 32;
+ std::codecvt_base::result r =
+ fun(state, from, from_end, from, buffer, to_end, to_next);
+
+ if (r == std::codecvt_base::error)
+ boost::throw_exception(
+ std::logic_error("character conversion failed"));
+ // 'partial' is not an error, it just means not all source
+ // characters were converted. However, we need to check that at
+ // least one new target character was produced. If not, it means
+ // the source data is incomplete, and since we don't have extra
+ // data to add to source, it's error.
+ if (to_next == buffer)
+ boost::throw_exception(
+ std::logic_error("character conversion failed"));
+
+ // Add converted characters
+ result.append(buffer, to_next);
+ }
+
+ return result;
+ }
+}}
+
+namespace boost {
+
+#ifndef BOOST_NO_STD_WSTRING
+ BOOST_PROGRAM_OPTIONS_DECL std::wstring
+ from_8_bit(const std::string& s,
+ const std::codecvt<wchar_t, char, std::mbstate_t>& cvt)
+ {
+ return detail::convert<wchar_t>(
+ s,
+ boost::bind(&std::codecvt<wchar_t, char, mbstate_t>::in,
+ &cvt,
+ _1, _2, _3, _4, _5, _6, _7));
+ }
+
+ BOOST_PROGRAM_OPTIONS_DECL std::string
+ to_8_bit(const std::wstring& s,
+ const std::codecvt<wchar_t, char, std::mbstate_t>& cvt)
+ {
+ return detail::convert<char>(
+ s,
+ boost::bind(&codecvt<wchar_t, char, mbstate_t>::out,
+ &cvt,
+ _1, _2, _3, _4, _5, _6, _7));
+ }
+
+
+ namespace {
+ boost::program_options::detail::utf8_codecvt_facet
+ utf8_facet;
+ }
+
+ BOOST_PROGRAM_OPTIONS_DECL std::wstring
+ from_utf8(const std::string& s)
+ {
+ return from_8_bit(s, utf8_facet);
+ }
+
+ BOOST_PROGRAM_OPTIONS_DECL std::string
+ to_utf8(const std::wstring& s)
+ {
+ return to_8_bit(s, utf8_facet);
+ }
+
+ BOOST_PROGRAM_OPTIONS_DECL std::wstring
+ from_local_8_bit(const std::string& s)
+ {
+ typedef codecvt<wchar_t, char, mbstate_t> facet_type;
+ return from_8_bit(s,
+ BOOST_USE_FACET(facet_type, locale()));
+ }
+
+ BOOST_PROGRAM_OPTIONS_DECL std::string
+ to_local_8_bit(const std::wstring& s)
+ {
+ typedef codecvt<wchar_t, char, mbstate_t> facet_type;
+ return to_8_bit(s,
+ BOOST_USE_FACET(facet_type, locale()));
+ }
+#endif
+
+ namespace program_options
+ {
+ BOOST_PROGRAM_OPTIONS_DECL std::string to_internal(const std::string& s)
+ {
+ return s;
+ }
+
+#ifndef BOOST_NO_STD_WSTRING
+ BOOST_PROGRAM_OPTIONS_DECL std::string to_internal(const std::wstring& s)
+ {
+ return to_utf8(s);
+ }
+#endif
+ }
+
+
+}
diff --git a/src/boost/libs/program_options/src/options_description.cpp b/src/boost/libs/program_options/src/options_description.cpp
new file mode 100644
index 000000000..dc0eae874
--- /dev/null
+++ b/src/boost/libs/program_options/src/options_description.cpp
@@ -0,0 +1,699 @@
+// Copyright Vladimir Prus 2002-2004.
+// Copyright Bertolt Mildner 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)
+
+
+#define BOOST_PROGRAM_OPTIONS_SOURCE
+#include <boost/program_options/config.hpp>
+#include <boost/program_options/options_description.hpp>
+// FIXME: this is only to get multiple_occurrences class
+// should move that to a separate headers.
+#include <boost/program_options/parsers.hpp>
+
+
+#include <boost/lexical_cast.hpp>
+#include <boost/tokenizer.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/throw_exception.hpp>
+
+#include <cassert>
+#include <climits>
+#include <cstring>
+#include <cstdarg>
+#include <sstream>
+#include <iterator>
+using namespace std;
+
+namespace boost { namespace program_options {
+
+ namespace {
+
+ template< class charT >
+ std::basic_string< charT > tolower_(const std::basic_string< charT >& str)
+ {
+ std::basic_string< charT > result;
+ for (typename std::basic_string< charT >::size_type i = 0; i < str.size(); ++i)
+ {
+ result.append(1, static_cast< charT >(std::tolower(str[i])));
+ }
+ return result;
+ }
+
+ } // unnamed namespace
+
+
+ option_description::option_description()
+ {
+ }
+
+ option_description::
+ option_description(const char* names,
+ const value_semantic* s)
+ : m_value_semantic(s)
+ {
+ this->set_names(names);
+ }
+
+
+ option_description::
+ option_description(const char* names,
+ const value_semantic* s,
+ const char* description)
+ : m_description(description), m_value_semantic(s)
+ {
+ this->set_names(names);
+ }
+
+ option_description::~option_description()
+ {
+ }
+
+ option_description::match_result
+ option_description::match(const std::string& option,
+ bool approx,
+ bool long_ignore_case,
+ bool short_ignore_case) const
+ {
+ match_result result = no_match;
+ std::string local_option = (long_ignore_case ? tolower_(option) : option);
+
+ for(std::vector<std::string>::const_iterator it(m_long_names.begin()); it != m_long_names.end(); it++)
+ {
+ std::string local_long_name((long_ignore_case ? tolower_(*it) : *it));
+
+ if (!local_long_name.empty()) {
+
+
+ if ((result == no_match) && (*local_long_name.rbegin() == '*'))
+ {
+ // The name ends with '*'. Any specified name with the given
+ // prefix is OK.
+ if (local_option.find(local_long_name.substr(0, local_long_name.length()-1))
+ == 0)
+ result = approximate_match;
+ }
+
+ if (local_long_name == local_option)
+ {
+ result = full_match;
+ break;
+ }
+ else if (approx)
+ {
+ if (local_long_name.find(local_option) == 0)
+ {
+ result = approximate_match;
+ }
+ }
+ }
+
+ }
+
+ if (result != full_match)
+ {
+ std::string local_short_name(short_ignore_case ? tolower_(m_short_name) : m_short_name);
+
+ if (local_short_name == local_option)
+ {
+ result = full_match;
+ }
+ }
+
+ return result;
+ }
+
+ const std::string&
+ option_description::key(const std::string& option) const
+ {
+ // We make the arbitrary choise of using the first long
+ // name as the key, regardless of anything else
+ if (!m_long_names.empty()) {
+ const std::string& first_long_name = *m_long_names.begin();
+ if (first_long_name.find('*') != string::npos)
+ // The '*' character means we're long_name
+ // matches only part of the input. So, returning
+ // long name will remove some of the information,
+ // and we have to return the option as specified
+ // in the source.
+ return option;
+ else
+ return first_long_name;
+ }
+ else
+ return m_short_name;
+ }
+
+ std::string
+ option_description::canonical_display_name(int prefix_style) const
+ {
+ // We prefer the first long name over any others
+ if (!m_long_names.empty())
+ {
+ if (prefix_style == command_line_style::allow_long)
+ return "--" + *m_long_names.begin();
+ if (prefix_style == command_line_style::allow_long_disguise)
+ return "-" + *m_long_names.begin();
+ }
+ // sanity check: m_short_name[0] should be '-' or '/'
+ if (m_short_name.length() == 2)
+ {
+ if (prefix_style == command_line_style::allow_slash_for_short)
+ return string("/") + m_short_name[1];
+ if (prefix_style == command_line_style::allow_dash_for_short)
+ return string("-") + m_short_name[1];
+ }
+ if (!m_long_names.empty())
+ return *m_long_names.begin();
+ else
+ return m_short_name;
+ }
+
+
+ const std::string&
+ option_description::long_name() const
+ {
+ static std::string empty_string("");
+ return m_long_names.empty() ? empty_string : *m_long_names.begin();
+ }
+
+ const std::pair<const std::string*, std::size_t>
+ option_description::long_names() const
+ {
+ // reinterpret_cast is to please msvc 10.
+ return (m_long_names.empty())
+ ? std::pair<const std::string*, size_t>(reinterpret_cast<const std::string*>(0), 0 )
+ : std::pair<const std::string*, size_t>( &(*m_long_names.begin()), m_long_names.size());
+ }
+
+ option_description&
+ option_description::set_names(const char* _names)
+ {
+ m_long_names.clear();
+ std::istringstream iss(_names);
+ std::string name;
+
+ while(std::getline(iss, name, ',')) {
+ m_long_names.push_back(name);
+ }
+ assert(!m_long_names.empty() && "No option names were specified");
+
+ bool try_interpreting_last_name_as_a_switch = m_long_names.size() > 1;
+ if (try_interpreting_last_name_as_a_switch) {
+ const std::string& last_name = *m_long_names.rbegin();
+ if (last_name.length() == 1) {
+ m_short_name = '-' + last_name;
+ m_long_names.pop_back();
+ // The following caters to the (valid) input of ",c" for some
+ // character c, where the caller only wants this option to have
+ // a short name.
+ if (m_long_names.size() == 1 && (*m_long_names.begin()).empty()) {
+ m_long_names.clear();
+ }
+ }
+ }
+ // We could theoretically also ensure no remaining long names
+ // are empty, or that none of them have length 1
+ return *this;
+ }
+
+ const std::string&
+ option_description::description() const
+ {
+ return m_description;
+ }
+
+ shared_ptr<const value_semantic>
+ option_description::semantic() const
+ {
+ return m_value_semantic;
+ }
+
+ std::string
+ option_description::format_name() const
+ {
+ if (!m_short_name.empty())
+ {
+ return m_long_names.empty()
+ ? m_short_name
+ : string(m_short_name).append(" [ --").
+ append(*m_long_names.begin()).append(" ]");
+ }
+ return string("--").append(*m_long_names.begin());
+ }
+
+ std::string
+ option_description::format_parameter() const
+ {
+ if (m_value_semantic->max_tokens() != 0)
+ return m_value_semantic->name();
+ else
+ return "";
+ }
+
+ options_description_easy_init::
+ options_description_easy_init(options_description* owner)
+ : owner(owner)
+ {}
+
+ options_description_easy_init&
+ options_description_easy_init::
+ operator()(const char* name,
+ const char* description)
+ {
+ // Create untypes semantic which accepts zero tokens: i.e.
+ // no value can be specified on command line.
+ // FIXME: does not look exception-safe
+ shared_ptr<option_description> d(
+ new option_description(name, new untyped_value(true), description));
+
+ owner->add(d);
+ return *this;
+ }
+
+ options_description_easy_init&
+ options_description_easy_init::
+ operator()(const char* name,
+ const value_semantic* s)
+ {
+ shared_ptr<option_description> d(new option_description(name, s));
+ owner->add(d);
+ return *this;
+ }
+
+ options_description_easy_init&
+ options_description_easy_init::
+ operator()(const char* name,
+ const value_semantic* s,
+ const char* description)
+ {
+ shared_ptr<option_description> d(new option_description(name, s, description));
+
+ owner->add(d);
+ return *this;
+ }
+
+ const unsigned options_description::m_default_line_length = 80;
+
+ options_description::options_description(unsigned line_length,
+ unsigned min_description_length)
+ : m_line_length(line_length)
+ , m_min_description_length(min_description_length)
+ {
+ // we require a space between the option and description parts, so add 1.
+ assert(m_min_description_length < m_line_length - 1);
+ }
+
+ options_description::options_description(const std::string& caption,
+ unsigned line_length,
+ unsigned min_description_length)
+ : m_caption(caption)
+ , m_line_length(line_length)
+ , m_min_description_length(min_description_length)
+ {
+ // we require a space between the option and description parts, so add 1.
+ assert(m_min_description_length < m_line_length - 1);
+ }
+
+ void
+ options_description::add(shared_ptr<option_description> desc)
+ {
+ m_options.push_back(desc);
+ belong_to_group.push_back(false);
+ }
+
+ options_description&
+ options_description::add(const options_description& desc)
+ {
+ shared_ptr<options_description> d(new options_description(desc));
+ groups.push_back(d);
+
+ for (size_t i = 0; i < desc.m_options.size(); ++i) {
+ add(desc.m_options[i]);
+ belong_to_group.back() = true;
+ }
+
+ return *this;
+ }
+
+ options_description_easy_init
+ options_description::add_options()
+ {
+ return options_description_easy_init(this);
+ }
+
+ const option_description&
+ options_description::find(const std::string& name,
+ bool approx,
+ bool long_ignore_case,
+ bool short_ignore_case) const
+ {
+ const option_description* d = find_nothrow(name, approx,
+ long_ignore_case, short_ignore_case);
+ if (!d)
+ boost::throw_exception(unknown_option());
+ return *d;
+ }
+
+ const std::vector< shared_ptr<option_description> >&
+ options_description::options() const
+ {
+ return m_options;
+ }
+
+ const option_description*
+ options_description::find_nothrow(const std::string& name,
+ bool approx,
+ bool long_ignore_case,
+ bool short_ignore_case) const
+ {
+ shared_ptr<option_description> found;
+ bool had_full_match = false;
+ vector<string> approximate_matches;
+ vector<string> full_matches;
+
+ // We use linear search because matching specified option
+ // name with the declared option name need to take care about
+ // 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, long_ignore_case, short_ignore_case);
+
+ if (r == option_description::no_match)
+ continue;
+
+ if (r == option_description::full_match)
+ {
+ full_matches.push_back(m_options[i]->key(name));
+ found = m_options[i];
+ had_full_match = true;
+ }
+ else
+ {
+ // FIXME: the use of 'key' here might not
+ // be the best approach.
+ approximate_matches.push_back(m_options[i]->key(name));
+ if (!had_full_match)
+ found = m_options[i];
+ }
+ }
+ if (full_matches.size() > 1)
+ boost::throw_exception(ambiguous_option(full_matches));
+
+ // If we have a full match, 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.
+ if (full_matches.empty() && approximate_matches.size() > 1)
+ boost::throw_exception(ambiguous_option(approximate_matches));
+
+ return found.get();
+ }
+
+ BOOST_PROGRAM_OPTIONS_DECL
+ std::ostream& operator<<(std::ostream& os, const options_description& desc)
+ {
+ desc.print(os);
+ return os;
+ }
+
+ 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 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
+ string::size_type par_indent = par.find('\t');
+
+ if (par_indent == string::npos)
+ {
+ par_indent = 0;
+ }
+ else
+ {
+ // only one tab per paragraph allowed
+ if (count(par.begin(), par.end(), '\t') > 1)
+ {
+ boost::throw_exception(program_options::error(
+ "Only one tab per paragraph is allowed in the options description"));
+ }
+
+ // erase tab from string
+ par.erase(par_indent, 1);
+
+ // this assert may fail due to user error or
+ // environment conditions!
+ assert(par_indent < line_length);
+
+ // ignore tab if not on first line
+ if (par_indent >= line_length)
+ {
+ par_indent = 0;
+ }
+ }
+
+ if (par.size() < line_length)
+ {
+ os << par;
+ }
+ else
+ {
+ string::const_iterator line_begin = par.begin();
+ const string::const_iterator par_end = par.end();
+
+ bool first_line = true; // of current paragraph!
+
+ 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.
+ if ((*line_begin == ' ') &&
+ ((line_begin + 1 < par_end) &&
+ (*(line_begin + 1) != ' ')))
+ {
+ line_begin += 1; // line_begin != line_end
+ }
+ }
+
+ // 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 = static_cast<unsigned>(std::distance(line_begin, par_end));
+ string::const_iterator line_end = line_begin +
+ ((remaining < line_length) ? remaining : line_length);
+
+ // prevent chopped words
+ // Is line_end between two non-space characters?
+ 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),
+ ' ')
+ .base();
+
+ if (last_space != line_begin)
+ {
+ // is last_space within the second half ot the
+ // current line
+ if (static_cast<unsigned>(std::distance(last_space, line_end)) <
+ (line_length / 2))
+ {
+ line_end = last_space;
+ }
+ }
+ } // prevent chopped words
+
+ // write line to stream
+ copy(line_begin, line_end, ostream_iterator<char>(os));
+
+ if (first_line)
+ {
+ indent += static_cast<unsigned>(par_indent);
+ line_length -= static_cast<unsigned>(par_indent); // there's less to work with now
+ first_line = false;
+ }
+
+ // more lines to follow?
+ if (line_end != par_end)
+ {
+ os << '\n';
+
+ for(unsigned pad = indent; pad > 0; --pad)
+ {
+ os.put(' ');
+ }
+ }
+
+ // next line starts after of this line
+ line_begin = line_end;
+ } // paragraph lines
+ }
+ }
+
+ void format_description(std::ostream& os,
+ const std::string& desc,
+ unsigned first_column_width,
+ unsigned line_length)
+ {
+ // we need to use one char less per line to work correctly if actual
+ // console has longer lines
+ assert(line_length > 1);
+ if (line_length > 1)
+ {
+ --line_length;
+ }
+
+ // line_length must be larger than first_column_width
+ // this assert may fail due to user error or environment conditions!
+ 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
+ // boost::tokenizer, not typedef.
+ typedef boost::tokenizer<boost::char_separator<char> > tok;
+
+ tok paragraphs(
+ desc,
+ char_separator<char>("\n", "", boost::keep_empty_tokens));
+
+ tok::const_iterator par_iter = paragraphs.begin();
+ const tok::const_iterator par_end = paragraphs.end();
+
+ while (par_iter != par_end) // paragraphs
+ {
+ format_paragraph(os, *par_iter, first_column_width,
+ line_length);
+
+ ++par_iter;
+
+ // prepair next line if any
+ if (par_iter != par_end)
+ {
+ os << '\n';
+
+ for(unsigned pad = first_column_width; pad > 0; --pad)
+ {
+ os.put(' ');
+ }
+ }
+ } // paragraphs
+ }
+
+ void format_one(std::ostream& os, const option_description& opt,
+ unsigned first_column_width, unsigned line_length)
+ {
+ stringstream ss;
+ ss << " " << opt.format_name() << ' ' << opt.format_parameter();
+
+ // Don't use ss.rdbuf() since g++ 2.96 is buggy on it.
+ os << ss.str();
+
+ if (!opt.description().empty())
+ {
+ if (ss.str().size() >= first_column_width)
+ {
+ os.put('\n'); // first column is too long, lets put description in new line
+ for (unsigned pad = first_column_width; pad > 0; --pad)
+ {
+ os.put(' ');
+ }
+ } else {
+ for(unsigned pad = first_column_width - static_cast<unsigned>(ss.str().size()); pad > 0; --pad)
+ {
+ os.put(' ');
+ }
+ }
+
+ format_description(os, opt.description(),
+ first_column_width, line_length);
+ }
+ }
+ }
+
+ unsigned
+ options_description::get_option_column_width() const
+ {
+ /* Find the maximum width of the option column */
+ unsigned width(23);
+ unsigned i; // vc6 has broken for loop scoping
+ for (i = 0; i < m_options.size(); ++i)
+ {
+ const option_description& opt = *m_options[i];
+ stringstream ss;
+ ss << " " << opt.format_name() << ' ' << opt.format_parameter();
+ width = (max)(width, static_cast<unsigned>(ss.str().size()));
+ }
+
+ /* Get width of groups as well*/
+ for (unsigned j = 0; j < groups.size(); ++j)
+ width = max(width, groups[j]->get_option_column_width());
+
+ /* this is the column were description should start, if first
+ column is longer, we go to a new line */
+ const unsigned start_of_description_column = m_line_length - m_min_description_length;
+
+ width = (min)(width, start_of_description_column-1);
+
+ /* add an additional space to improve readability */
+ ++width;
+ return width;
+ }
+
+ void
+ options_description::print(std::ostream& os, unsigned width) const
+ {
+ if (!m_caption.empty())
+ os << m_caption << ":\n";
+
+ if (!width)
+ width = get_option_column_width();
+
+ /* The options formatting style is stolen from Subversion. */
+ for (unsigned i = 0; i < m_options.size(); ++i)
+ {
+ if (belong_to_group[i])
+ continue;
+
+ const option_description& opt = *m_options[i];
+
+ format_one(os, opt, width, m_line_length);
+
+ os << "\n";
+ }
+
+ for (unsigned j = 0; j < groups.size(); ++j) {
+ os << "\n";
+ groups[j]->print(os, width);
+ }
+ }
+
+}}
diff --git a/src/boost/libs/program_options/src/parsers.cpp b/src/boost/libs/program_options/src/parsers.cpp
new file mode 100644
index 000000000..3e435eea3
--- /dev/null
+++ b/src/boost/libs/program_options/src/parsers.cpp
@@ -0,0 +1,258 @@
+// 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 <boost/config.hpp>
+
+#define BOOST_PROGRAM_OPTIONS_SOURCE
+#include <boost/program_options/config.hpp>
+#include <boost/program_options/parsers.hpp>
+#include <boost/program_options/options_description.hpp>
+#include <boost/program_options/positional_options.hpp>
+#include <boost/program_options/detail/cmdline.hpp>
+#include <boost/program_options/detail/config_file.hpp>
+#include <boost/program_options/environment_iterator.hpp>
+#include <boost/program_options/detail/convert.hpp>
+
+#include <boost/bind.hpp>
+#include <boost/throw_exception.hpp>
+
+#include <cctype>
+#include <fstream>
+
+#if !defined(__GNUC__) || __GNUC__ < 3
+#include <iostream>
+#else
+#include <istream>
+#endif
+
+#ifdef _WIN32
+#include <stdlib.h>
+#else
+#include <unistd.h>
+#endif
+
+// The 'environ' should be declared in some cases. E.g. Linux man page says:
+// (This variable must be declared in the user program, but is declared in
+// the header file unistd.h in case the header files came from libc4 or libc5,
+// and in case they came from glibc and _GNU_SOURCE was defined.)
+// To be safe, declare it here.
+
+// It appears that on Mac OS X the 'environ' variable is not
+// available to dynamically linked libraries.
+// See: http://article.gmane.org/gmane.comp.lib.boost.devel/103843
+// See: http://lists.gnu.org/archive/html/bug-guile/2004-01/msg00013.html
+#if defined(__APPLE__) && defined(__DYNAMIC__)
+// The proper include for this is crt_externs.h, however it's not
+// available on iOS. The right replacement is not known. See
+// https://svn.boost.org/trac/boost/ticket/5053
+extern "C" { extern char ***_NSGetEnviron(void); }
+#define environ (*_NSGetEnviron())
+#else
+#if defined(__MWERKS__)
+#include <crtl.h>
+#else
+#if !defined(_WIN32) || defined(__COMO_VERSION__)
+extern char** environ;
+#endif
+#endif
+#endif
+
+using namespace std;
+
+namespace boost { namespace program_options {
+
+#ifndef BOOST_NO_STD_WSTRING
+ namespace {
+ woption woption_from_option(const option& opt)
+ {
+ 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),
+ 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;
+ }
+ }
+
+ basic_parsed_options<wchar_t>
+ ::basic_parsed_options(const parsed_options& po)
+ : description(po.description),
+ utf8_encoded_options(po),
+ m_options_prefix(po.m_options_prefix)
+ {
+ for (unsigned i = 0; i < po.options.size(); ++i)
+ options.push_back(woption_from_option(po.options[i]));
+ }
+#endif
+
+ template<class charT>
+ basic_parsed_options<charT>
+ parse_config_file(std::basic_istream<charT>& is,
+ const options_description& desc,
+ bool allow_unregistered)
+ {
+ set<string> allowed_options;
+
+ const vector<shared_ptr<option_description> >& options = desc.options();
+ for (unsigned i = 0; i < options.size(); ++i)
+ {
+ const option_description& d = *options[i];
+
+ if (d.long_name().empty())
+ boost::throw_exception(
+ error("abbreviated option names are not permitted in options configuration files"));
+
+ allowed_options.insert(d.long_name());
+ }
+
+ // Parser return char strings
+ parsed_options result(&desc);
+ copy(detail::basic_config_file_iterator<charT>(
+ is, allowed_options, allow_unregistered),
+ detail::basic_config_file_iterator<charT>(),
+ back_inserter(result.options));
+ // Convert char strings into desired type.
+ return basic_parsed_options<charT>(result);
+ }
+
+ template
+ BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options<char>
+ parse_config_file(std::basic_istream<char>& is,
+ const options_description& desc,
+ bool allow_unregistered);
+
+#ifndef BOOST_NO_STD_WSTRING
+ template
+ BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options<wchar_t>
+ parse_config_file(std::basic_istream<wchar_t>& is,
+ const options_description& desc,
+ bool allow_unregistered);
+#endif
+
+ template<class charT>
+ basic_parsed_options<charT>
+ parse_config_file(const char* filename,
+ const options_description& desc,
+ bool allow_unregistered)
+ {
+ // Parser return char strings
+ std::basic_ifstream< charT > strm(filename);
+ if (!strm)
+ {
+ boost::throw_exception(reading_file(filename));
+ }
+
+ basic_parsed_options<charT> result
+ = parse_config_file(strm, desc, allow_unregistered);
+
+ if (strm.bad())
+ {
+ boost::throw_exception(reading_file(filename));
+ }
+
+ return result;
+ }
+
+ template
+ BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options<char>
+ parse_config_file(const char* filename,
+ const options_description& desc,
+ bool allow_unregistered);
+
+#ifndef BOOST_NO_STD_WSTRING
+ template
+ BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options<wchar_t>
+ parse_config_file(const char* filename,
+ const options_description& desc,
+ bool allow_unregistered);
+#endif
+
+
+// This versio, which accepts any options without validation, is disabled,
+// in the hope that nobody will need it and we cant drop it altogether.
+// Besides, probably the right way to handle all options is the '*' name.
+#if 0
+ BOOST_PROGRAM_OPTIONS_DECL parsed_options
+ parse_config_file(std::istream& is)
+ {
+ detail::config_file_iterator cf(is, false);
+ parsed_options result(0);
+ copy(cf, detail::config_file_iterator(),
+ back_inserter(result.options));
+ return result;
+ }
+#endif
+
+ BOOST_PROGRAM_OPTIONS_DECL parsed_options
+ parse_environment(const options_description& desc,
+ const function1<std::string, std::string>& name_mapper)
+ {
+ parsed_options result(&desc);
+
+ for(environment_iterator i(environ), e; i != e; ++i) {
+ string option_name = name_mapper(i->first);
+
+ if (!option_name.empty()) {
+ option n;
+ n.string_key = option_name;
+ n.value.push_back(i->second);
+ result.options.push_back(n);
+ }
+ }
+
+ return result;
+ }
+
+ namespace detail {
+ class prefix_name_mapper {
+ public:
+ prefix_name_mapper(const std::string& prefix)
+ : prefix(prefix)
+ {}
+
+ std::string operator()(const std::string& s)
+ {
+ string result;
+ if (s.find(prefix) == 0) {
+ for(string::size_type n = prefix.size(); n < s.size(); ++n)
+ {
+ // Intel-Win-7.1 does not understand
+ // push_back on string.
+ result += static_cast<char>(tolower(s[n]));
+ }
+ }
+ return result;
+ }
+ private:
+ std::string prefix;
+ };
+ }
+
+ BOOST_PROGRAM_OPTIONS_DECL parsed_options
+ parse_environment(const options_description& desc,
+ const std::string& prefix)
+ {
+ return parse_environment(desc, detail::prefix_name_mapper(prefix));
+ }
+
+ BOOST_PROGRAM_OPTIONS_DECL parsed_options
+ parse_environment(const options_description& desc, const char* prefix)
+ {
+ return parse_environment(desc, string(prefix));
+ }
+
+
+
+
+}}
diff --git a/src/boost/libs/program_options/src/positional_options.cpp b/src/boost/libs/program_options/src/positional_options.cpp
new file mode 100644
index 000000000..72dc0d6b0
--- /dev/null
+++ b/src/boost/libs/program_options/src/positional_options.cpp
@@ -0,0 +1,53 @@
+// Copyright Vladimir Prus 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)
+
+#define BOOST_PROGRAM_OPTIONS_SOURCE
+#include <boost/program_options/config.hpp>
+
+#include <boost/program_options/positional_options.hpp>
+
+#include <boost/limits.hpp>
+
+#include <cassert>
+
+namespace boost { namespace program_options {
+
+ positional_options_description::positional_options_description()
+ {}
+
+ positional_options_description&
+ positional_options_description::add(const char* name, int max_count)
+ {
+ assert(max_count != -1 || m_trailing.empty());
+
+ if (max_count == -1)
+ m_trailing = name;
+ else {
+ m_names.resize(m_names.size() + max_count, name);
+ }
+ return *this;
+ }
+
+ unsigned
+ positional_options_description::max_total_count() const
+ {
+ return m_trailing.empty() ?
+ static_cast<unsigned>(m_names.size()) : (std::numeric_limits<unsigned>::max)();
+ }
+
+ const std::string&
+ positional_options_description::name_for_position(unsigned position) const
+ {
+ assert(position < max_total_count());
+
+ if (position < m_names.size())
+ return m_names[position];
+ else
+ return m_trailing;
+ }
+
+
+}}
+
diff --git a/src/boost/libs/program_options/src/split.cpp b/src/boost/libs/program_options/src/split.cpp
new file mode 100644
index 000000000..96da068b8
--- /dev/null
+++ b/src/boost/libs/program_options/src/split.cpp
@@ -0,0 +1,62 @@
+// Copyright Sascha Ochsenknecht 2009.
+// 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)
+
+#define BOOST_PROGRAM_OPTIONS_SOURCE
+
+#include <boost/program_options/parsers.hpp>
+#include <boost/tokenizer.hpp>
+
+#include <string>
+#include <vector>
+
+namespace boost { namespace program_options { namespace detail {
+
+ template< class charT >
+ std::vector<std::basic_string<charT> >
+ split_unix(
+ const std::basic_string<charT>& cmdline,
+ const std::basic_string<charT>& seperator,
+ const std::basic_string<charT>& quote,
+ const std::basic_string<charT>& escape)
+ {
+ typedef boost::tokenizer< boost::escaped_list_separator<charT>,
+ typename std::basic_string<charT>::const_iterator,
+ std::basic_string<charT> > tokenizerT;
+
+ tokenizerT tok(cmdline.begin(), cmdline.end(),
+ boost::escaped_list_separator< charT >(escape, seperator, quote));
+
+ std::vector< std::basic_string<charT> > result;
+ for (typename tokenizerT::iterator cur_token(tok.begin()), end_token(tok.end()); cur_token != end_token; ++cur_token) {
+ if (!cur_token->empty())
+ result.push_back(*cur_token);
+ }
+ return result;
+ }
+
+}}} // namespace
+
+namespace boost { namespace program_options {
+
+ // Take a command line string and splits in into tokens, according
+ // to the given collection of seperators chars.
+ BOOST_PROGRAM_OPTIONS_DECL std::vector<std::string>
+ split_unix(const std::string& cmdline, const std::string& seperator,
+ const std::string& quote, const std::string& escape)
+ {
+ return detail::split_unix< char >(cmdline, seperator, quote, escape);
+ }
+
+#ifndef BOOST_NO_STD_WSTRING
+ BOOST_PROGRAM_OPTIONS_DECL std::vector<std::wstring>
+ split_unix(const std::wstring& cmdline, const std::wstring& seperator,
+ const std::wstring& quote, const std::wstring& escape)
+ {
+ return detail::split_unix< wchar_t >(cmdline, seperator, quote, escape);
+ }
+#endif
+
+}} // namespace
+
diff --git a/src/boost/libs/program_options/src/utf8_codecvt_facet.cpp b/src/boost/libs/program_options/src/utf8_codecvt_facet.cpp
new file mode 100644
index 000000000..2e4c532c3
--- /dev/null
+++ b/src/boost/libs/program_options/src/utf8_codecvt_facet.cpp
@@ -0,0 +1,21 @@
+// Copyright Vladimir Prus 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)
+
+#define BOOST_PROGRAM_OPTIONS_SOURCE
+#include <boost/program_options/config.hpp>
+
+#define BOOST_UTF8_BEGIN_NAMESPACE \
+ namespace boost { namespace program_options { namespace detail {
+
+#define BOOST_UTF8_END_NAMESPACE }}}
+#define BOOST_UTF8_DECL BOOST_PROGRAM_OPTIONS_DECL
+
+#include <boost/detail/utf8_codecvt_facet.ipp>
+
+
+#undef BOOST_UTF8_BEGIN_NAMESPACE
+#undef BOOST_UTF8_END_NAMESPACE
+#undef BOOST_UTF8_DECL
+
diff --git a/src/boost/libs/program_options/src/value_semantic.cpp b/src/boost/libs/program_options/src/value_semantic.cpp
new file mode 100644
index 000000000..a7366d438
--- /dev/null
+++ b/src/boost/libs/program_options/src/value_semantic.cpp
@@ -0,0 +1,428 @@
+// Copyright Vladimir Prus 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)
+
+#define BOOST_PROGRAM_OPTIONS_SOURCE
+#include <boost/program_options/config.hpp>
+#include <boost/program_options/value_semantic.hpp>
+#include <boost/program_options/detail/convert.hpp>
+#include <boost/program_options/detail/cmdline.hpp>
+#include <set>
+
+#include <cctype>
+
+namespace boost { namespace program_options {
+
+ using namespace std;
+
+
+#ifndef BOOST_NO_STD_WSTRING
+ namespace
+ {
+ std::string convert_value(const std::wstring& s)
+ {
+ try {
+ return to_local_8_bit(s);
+ }
+ catch(const std::exception&) {
+ return "<unrepresentable unicode string>";
+ }
+ }
+ }
+#endif
+
+ void
+ value_semantic_codecvt_helper<char>::
+ parse(boost::any& value_store,
+ const std::vector<std::string>& new_tokens,
+ bool utf8) const
+ {
+ if (utf8) {
+#ifndef BOOST_NO_STD_WSTRING
+ // Need to convert to local encoding.
+ std::vector<string> local_tokens;
+ for (unsigned i = 0; i < new_tokens.size(); ++i) {
+ std::wstring w = from_utf8(new_tokens[i]);
+ local_tokens.push_back(to_local_8_bit(w));
+ }
+ xparse(value_store, local_tokens);
+#else
+ boost::throw_exception(
+ std::runtime_error("UTF-8 conversion not supported."));
+#endif
+ } else {
+ // Already in local encoding, pass unmodified
+ xparse(value_store, new_tokens);
+ }
+ }
+
+#ifndef BOOST_NO_STD_WSTRING
+ void
+ value_semantic_codecvt_helper<wchar_t>::
+ parse(boost::any& value_store,
+ const std::vector<std::string>& new_tokens,
+ bool utf8) const
+ {
+ std::vector<wstring> tokens;
+ if (utf8) {
+ // Convert from utf8
+ for (unsigned i = 0; i < new_tokens.size(); ++i) {
+ tokens.push_back(from_utf8(new_tokens[i]));
+ }
+
+ } else {
+ // Convert from local encoding
+ for (unsigned i = 0; i < new_tokens.size(); ++i) {
+ tokens.push_back(from_local_8_bit(new_tokens[i]));
+ }
+ }
+
+ xparse(value_store, tokens);
+ }
+#endif
+
+ BOOST_PROGRAM_OPTIONS_DECL std::string arg("arg");
+
+ std::string
+ untyped_value::name() const
+ {
+ return arg;
+ }
+
+ unsigned
+ untyped_value::min_tokens() const
+ {
+ if (m_zero_tokens)
+ return 0;
+ else
+ return 1;
+ }
+
+ unsigned
+ untyped_value::max_tokens() const
+ {
+ if (m_zero_tokens)
+ return 0;
+ else
+ return 1;
+ }
+
+
+ void
+ untyped_value::xparse(boost::any& value_store,
+ const std::vector<std::string>& new_tokens) const
+ {
+ if (!value_store.empty())
+ boost::throw_exception(
+ multiple_occurrences());
+ if (new_tokens.size() > 1)
+ boost::throw_exception(multiple_values());
+ value_store = new_tokens.empty() ? std::string("") : new_tokens.front();
+ }
+
+ BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>*
+ bool_switch()
+ {
+ return bool_switch(0);
+ }
+
+ BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>*
+ bool_switch(bool* v)
+ {
+ typed_value<bool>* r = new typed_value<bool>(v);
+ r->default_value(0);
+ r->zero_tokens();
+
+ return r;
+ }
+
+ /* Validates bool value.
+ Any of "1", "true", "yes", "on" will be converted to "1".<br>
+ Any of "0", "false", "no", "off" will be converted to "0".<br>
+ Case is ignored. The 'xs' vector can either be empty, in which
+ case the value is 'true', or can contain explicit value.
+ */
+ BOOST_PROGRAM_OPTIONS_DECL void validate(any& v, const vector<string>& xs,
+ bool*, int)
+ {
+ check_first_occurrence(v);
+ string s(get_single_string(xs, true));
+
+ for (size_t i = 0; i < s.size(); ++i)
+ s[i] = char(tolower(s[i]));
+
+ if (s.empty() || s == "on" || s == "yes" || s == "1" || s == "true")
+ v = any(true);
+ else if (s == "off" || s == "no" || s == "0" || s == "false")
+ v = any(false);
+ else
+ boost::throw_exception(invalid_bool_value(s));
+ }
+
+ // This is blatant copy-paste. However, templating this will cause a problem,
+ // since wstring can't be constructed/compared with char*. We'd need to
+ // create auxiliary 'widen' routine to convert from char* into
+ // needed string type, and that's more work.
+#if !defined(BOOST_NO_STD_WSTRING)
+ BOOST_PROGRAM_OPTIONS_DECL
+ void validate(any& v, const vector<wstring>& xs, bool*, int)
+ {
+ check_first_occurrence(v);
+ wstring s(get_single_string(xs, true));
+
+ for (size_t i = 0; i < s.size(); ++i)
+ s[i] = wchar_t(tolower(s[i]));
+
+ if (s.empty() || s == L"on" || s == L"yes" || s == L"1" || s == L"true")
+ v = any(true);
+ else if (s == L"off" || s == L"no" || s == L"0" || s == L"false")
+ v = any(false);
+ else
+ boost::throw_exception(invalid_bool_value(convert_value(s)));
+ }
+#endif
+ BOOST_PROGRAM_OPTIONS_DECL
+ void validate(any& v, const vector<string>& xs, std::string*, int)
+ {
+ check_first_occurrence(v);
+ v = any(get_single_string(xs));
+ }
+
+#if !defined(BOOST_NO_STD_WSTRING)
+ BOOST_PROGRAM_OPTIONS_DECL
+ void validate(any& v, const vector<wstring>& xs, std::string*, int)
+ {
+ check_first_occurrence(v);
+ v = any(get_single_string(xs));
+ }
+#endif
+
+ namespace validators {
+
+ BOOST_PROGRAM_OPTIONS_DECL
+ void check_first_occurrence(const boost::any& value)
+ {
+ if (!value.empty())
+ boost::throw_exception(
+ multiple_occurrences());
+ }
+ }
+
+
+ invalid_option_value::
+ invalid_option_value(const std::string& bad_value)
+ : validation_error(validation_error::invalid_option_value)
+ {
+ set_substitute("value", bad_value);
+ }
+
+#ifndef BOOST_NO_STD_WSTRING
+ invalid_option_value::
+ invalid_option_value(const std::wstring& bad_value)
+ : validation_error(validation_error::invalid_option_value)
+ {
+ set_substitute("value", convert_value(bad_value));
+ }
+#endif
+
+
+
+ invalid_bool_value::
+ invalid_bool_value(const std::string& bad_value)
+ : validation_error(validation_error::invalid_bool_value)
+ {
+ set_substitute("value", bad_value);
+ }
+
+
+
+
+
+
+ error_with_option_name::error_with_option_name( const std::string& template_,
+ const std::string& option_name,
+ const std::string& original_token,
+ int option_style) :
+ error(template_),
+ m_option_style(option_style),
+ m_error_template(template_)
+ {
+ // parameter | placeholder | value
+ // --------- | ----------- | -----
+ set_substitute_default("canonical_option", "option '%canonical_option%'", "option");
+ set_substitute_default("value", "argument ('%value%')", "argument");
+ set_substitute_default("prefix", "%prefix%", "");
+ m_substitutions["option"] = option_name;
+ m_substitutions["original_token"] = original_token;
+ }
+
+
+ const char* error_with_option_name::what() const throw()
+ {
+ // will substitute tokens each time what is run()
+ substitute_placeholders(m_error_template);
+
+ return m_message.c_str();
+ }
+
+ void error_with_option_name::replace_token(const string& from, const string& to) const
+ {
+ for (;;)
+ {
+ std::size_t pos = m_message.find(from.c_str(), 0, from.length());
+ // not found: all replaced
+ if (pos == std::string::npos)
+ return;
+ m_message.replace(pos, from.length(), to);
+ }
+ }
+
+ string error_with_option_name::get_canonical_option_prefix() const
+ {
+ switch (m_option_style)
+ {
+ case command_line_style::allow_dash_for_short:
+ return "-";
+ case command_line_style::allow_slash_for_short:
+ return "/";
+ case command_line_style::allow_long_disguise:
+ return "-";
+ case command_line_style::allow_long:
+ return "--";
+ case 0:
+ return "";
+ }
+ throw std::logic_error("error_with_option_name::m_option_style can only be "
+ "one of [0, allow_dash_for_short, allow_slash_for_short, "
+ "allow_long_disguise or allow_long]");
+ }
+
+
+ string error_with_option_name::get_canonical_option_name() const
+ {
+ if (!m_substitutions.find("option")->second.length())
+ return m_substitutions.find("original_token")->second;
+
+ string original_token = strip_prefixes(m_substitutions.find("original_token")->second);
+ string option_name = strip_prefixes(m_substitutions.find("option")->second);
+
+ // For long options, use option name
+ if (m_option_style == command_line_style::allow_long ||
+ m_option_style == command_line_style::allow_long_disguise)
+ return get_canonical_option_prefix() + option_name;
+
+ // For short options use first letter of original_token
+ if (m_option_style && original_token.length())
+ return get_canonical_option_prefix() + original_token[0];
+
+ // no prefix
+ return option_name;
+ }
+
+
+ void error_with_option_name::substitute_placeholders(const string& error_template) const
+ {
+ m_message = error_template;
+ std::map<std::string, std::string> substitutions(m_substitutions);
+ substitutions["canonical_option"] = get_canonical_option_name();
+ substitutions["prefix"] = get_canonical_option_prefix();
+
+
+ //
+ // replace placeholder with defaults if values are missing
+ //
+ for (map<string, string_pair>::const_iterator iter = m_substitution_defaults.begin();
+ iter != m_substitution_defaults.end(); ++iter)
+ {
+ // missing parameter: use default
+ if (substitutions.count(iter->first) == 0 ||
+ substitutions[iter->first].length() == 0)
+ replace_token(iter->second.first, iter->second.second);
+ }
+
+
+ //
+ // replace placeholder with values
+ // placeholder are denoted by surrounding '%'
+ //
+ for (map<string, string>::iterator iter = substitutions.begin();
+ iter != substitutions.end(); ++iter)
+ replace_token('%' + iter->first + '%', iter->second);
+ }
+
+
+ void ambiguous_option::substitute_placeholders(const string& original_error_template) const
+ {
+ // For short forms, all alternatives must be identical, by
+ // definition, to the specified option, so we don't need to
+ // display alternatives
+ if (m_option_style == command_line_style::allow_dash_for_short ||
+ m_option_style == command_line_style::allow_slash_for_short)
+ {
+ error_with_option_name::substitute_placeholders(original_error_template);
+ return;
+ }
+
+
+ string error_template = original_error_template;
+ // remove duplicates using std::set
+ std::set<std::string> alternatives_set (m_alternatives.begin(), m_alternatives.end());
+ std::vector<std::string> alternatives_vec (alternatives_set.begin(), alternatives_set.end());
+
+ error_template += " and matches ";
+ // Being very cautious: should be > 1 alternative!
+ if (alternatives_vec.size() > 1)
+ {
+ for (unsigned i = 0; i < alternatives_vec.size() - 1; ++i)
+ error_template += "'%prefix%" + alternatives_vec[i] + "', ";
+ error_template += "and ";
+ }
+
+ // there is a programming error if multiple options have the same name...
+ if (m_alternatives.size() > 1 && alternatives_vec.size() == 1)
+ error_template += "different versions of ";
+
+ error_template += "'%prefix%" + alternatives_vec.back() + "'";
+
+
+ // use inherited logic
+ error_with_option_name::substitute_placeholders(error_template);
+ }
+
+
+
+
+
+
+ string
+ validation_error::get_template(kind_t kind)
+ {
+ // Initially, store the message in 'const char*' variable,
+ // to avoid conversion to std::string in all cases.
+ const char* msg;
+ switch(kind)
+ {
+ case invalid_bool_value:
+ msg = "the argument ('%value%') for option '%canonical_option%' is invalid. Valid choices are 'on|off', 'yes|no', '1|0' and 'true|false'";
+ break;
+ case invalid_option_value:
+ msg = "the argument ('%value%') for option '%canonical_option%' is invalid";
+ break;
+ case multiple_values_not_allowed:
+ msg = "option '%canonical_option%' only takes a single argument";
+ break;
+ case at_least_one_value_required:
+ msg = "option '%canonical_option%' requires at least one argument";
+ break;
+ // currently unused
+ case invalid_option:
+ msg = "option '%canonical_option%' is not valid";
+ break;
+ default:
+ msg = "unknown error";
+ }
+ return msg;
+ }
+
+}}
diff --git a/src/boost/libs/program_options/src/variables_map.cpp b/src/boost/libs/program_options/src/variables_map.cpp
new file mode 100644
index 000000000..bc85f7e34
--- /dev/null
+++ b/src/boost/libs/program_options/src/variables_map.cpp
@@ -0,0 +1,248 @@
+// 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)
+
+
+#define BOOST_PROGRAM_OPTIONS_SOURCE
+#include <boost/program_options/config.hpp>
+#include <boost/program_options/parsers.hpp>
+#include <boost/program_options/options_description.hpp>
+#include <boost/program_options/value_semantic.hpp>
+#include <boost/program_options/variables_map.hpp>
+
+#include <cassert>
+
+namespace boost { namespace program_options {
+
+ using namespace std;
+
+ // First, performs semantic actions for 'oa'.
+ // Then, stores in 'm' all options that are defined in 'desc'.
+ BOOST_PROGRAM_OPTIONS_DECL
+ void store(const parsed_options& options, variables_map& xm,
+ bool utf8)
+ {
+ // TODO: what if we have different definition
+ // for the same option name during different calls
+ // 'store'.
+ assert(options.description);
+ const options_description& desc = *options.description;
+
+ // We need to access map's operator[], not the overriden version
+ // variables_map. Ehmm.. messy.
+ std::map<std::string, variable_value>& m = xm;
+
+ std::set<std::string> new_final;
+
+ // Declared once, to please Intel in VC++ mode;
+ unsigned i;
+
+ // Declared here so can be used to provide context for exceptions
+ string option_name;
+ string original_token;
+
+#ifndef BOOST_NO_EXCEPTIONS
+ try
+#endif
+ {
+
+ // First, convert/store all given options
+ for (i = 0; i < options.options.size(); ++i) {
+
+ option_name = options.options[i].string_key;
+ // Skip positional options without name
+ if (option_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(option_name))
+ continue;
+
+ original_token = options.options[i].original_tokens.size() ?
+ options.options[i].original_tokens[0] : "";
+ const option_description& d = desc.find(option_name, false,
+ false, false);
+
+ variable_value& v = m[option_name];
+ if (v.defaulted()) {
+ // Explicit assignment here erases defaulted value
+ v = variable_value();
+ }
+
+ d.semantic()->parse(v.value(), options.options[i].value, utf8);
+
+ v.m_value_semantic = d.semantic();
+
+ // The option is not composing, and the value is explicitly
+ // provided. Ignore values of this option for subsequent
+ // calls to 'store'. We store this to a temporary set,
+ // so that several assignment inside *this* 'store' call
+ // are allowed.
+ if (!d.semantic()->is_composing())
+ new_final.insert(option_name);
+ }
+ }
+#ifndef BOOST_NO_EXCEPTIONS
+ catch(error_with_option_name& e)
+ {
+ // add context and rethrow
+ e.add_context(option_name, original_token, options.m_options_prefix);
+ throw;
+ }
+#endif
+ xm.m_final.insert(new_final.begin(), new_final.end());
+
+
+
+ // Second, apply default values and store required options.
+ const vector<shared_ptr<option_description> >& all = desc.options();
+ for(i = 0; i < all.size(); ++i)
+ {
+ const option_description& d = *all[i];
+ string key = d.key("");
+ // FIXME: this logic relies on knowledge of option_description
+ // internals.
+ // The 'key' is empty if options description contains '*'.
+ // In that
+ // case, default value makes no sense at all.
+ if (key.empty())
+ {
+ continue;
+ }
+ if (m.count(key) == 0) {
+
+ boost::any def;
+ if (d.semantic()->apply_default(def)) {
+ m[key] = variable_value(def, true);
+ m[key].m_value_semantic = d.semantic();
+ }
+ }
+
+ // add empty value if this is an required option
+ if (d.semantic()->is_required()) {
+
+ // For option names specified in multiple ways, e.g. on the command line,
+ // config file etc, the following precedence rules apply:
+ // "--" > ("-" or "/") > ""
+ // Precedence is set conveniently by a single call to length()
+ string canonical_name = d.canonical_display_name(options.m_options_prefix);
+ if (canonical_name.length() > xm.m_required[key].length())
+ xm.m_required[key] = canonical_name;
+ }
+ }
+ }
+
+ BOOST_PROGRAM_OPTIONS_DECL
+ void store(const wparsed_options& options, variables_map& m)
+ {
+ store(options.utf8_encoded_options, m, true);
+ }
+
+ BOOST_PROGRAM_OPTIONS_DECL
+ void notify(variables_map& vm)
+ {
+ vm.notify();
+ }
+
+ abstract_variables_map::abstract_variables_map()
+ : m_next(0)
+ {}
+
+ abstract_variables_map::
+ abstract_variables_map(const abstract_variables_map* next)
+ : m_next(next)
+ {}
+
+ const variable_value&
+ abstract_variables_map::operator[](const std::string& name) const
+ {
+ const variable_value& v = get(name);
+ if (v.empty() && m_next)
+ return (*m_next)[name];
+ else if (v.defaulted() && m_next) {
+ const variable_value& v2 = (*m_next)[name];
+ if (!v2.empty() && !v2.defaulted())
+ return v2;
+ else return v;
+ } else {
+ return v;
+ }
+ }
+
+ void
+ abstract_variables_map::next(abstract_variables_map* next)
+ {
+ m_next = next;
+ }
+
+ variables_map::variables_map()
+ {}
+
+ variables_map::variables_map(const abstract_variables_map* next)
+ : abstract_variables_map(next)
+ {}
+
+ void variables_map::clear()
+ {
+ std::map<std::string, variable_value>::clear();
+ m_final.clear();
+ m_required.clear();
+ }
+
+ const variable_value&
+ variables_map::get(const std::string& name) const
+ {
+ static variable_value empty;
+ const_iterator i = this->find(name);
+ if (i == this->end())
+ return empty;
+ else
+ return i->second;
+ }
+
+ void
+ variables_map::notify()
+ {
+ // This checks if all required options occur
+ for (map<string, string>::const_iterator r = m_required.begin();
+ r != m_required.end();
+ ++r)
+ {
+ const string& opt = r->first;
+ const string& display_opt = r->second;
+ map<string, variable_value>::const_iterator iter = find(opt);
+ if (iter == end() || iter->second.empty())
+ {
+ boost::throw_exception(required_option(display_opt));
+
+ }
+ }
+
+ // Lastly, run notify actions.
+ for (map<string, variable_value>::iterator k = begin();
+ k != end();
+ ++k)
+ {
+ /* 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 not 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());
+ }
+ }
+
+}}
diff --git a/src/boost/libs/program_options/src/winmain.cpp b/src/boost/libs/program_options/src/winmain.cpp
new file mode 100644
index 000000000..6220043f6
--- /dev/null
+++ b/src/boost/libs/program_options/src/winmain.cpp
@@ -0,0 +1,102 @@
+// 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)
+
+#define BOOST_PROGRAM_OPTIONS_SOURCE
+#include <boost/program_options/parsers.hpp>
+#include <cctype>
+
+using std::size_t;
+
+#ifdef _WIN32
+namespace boost { namespace program_options {
+
+ // 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
+ // 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)
+ {
+ std::vector<std::string> result;
+
+ std::string::const_iterator i = input.begin(), e = input.end();
+ for(;i != e; ++i)
+ if (!isspace((unsigned char)*i))
+ break;
+
+ if (i != e) {
+
+ std::string current;
+ bool inside_quoted = false;
+ bool empty_quote = false;
+ int backslash_count = 0;
+
+ for(; i != e; ++i) {
+ if (*i == '"') {
+ // '"' preceded by even number (n) of backslashes generates
+ // n/2 backslashes and is a quoted block delimiter
+ if (backslash_count % 2 == 0) {
+ current.append(backslash_count / 2, '\\');
+ empty_quote = inside_quoted && current.empty();
+ inside_quoted = !inside_quoted;
+ // '"' preceded by odd number (n) of backslashes generates
+ // (n-1)/2 backslashes and is literal quote.
+ } else {
+ current.append(backslash_count / 2, '\\');
+ current += '"';
+ }
+ backslash_count = 0;
+ } else if (*i == '\\') {
+ ++backslash_count;
+ } else {
+ // Not quote or backslash. All accumulated backslashes should be
+ // added
+ if (backslash_count) {
+ current.append(backslash_count, '\\');
+ backslash_count = 0;
+ }
+ if (isspace((unsigned char)*i) && !inside_quoted) {
+ // Space outside quoted section terminate the current argument
+ result.push_back(current);
+ current.resize(0);
+ empty_quote = false;
+ for(;i != e && isspace((unsigned char)*i); ++i)
+ ;
+ --i;
+ } else {
+ current += *i;
+ }
+ }
+ }
+
+ // If we have trailing backslashes, add them
+ if (backslash_count)
+ current.append(backslash_count, '\\');
+
+ // If we have non-empty 'current' or we're still in quoted
+ // section (even if 'current' is empty), add the last token.
+ if (!current.empty() || inside_quoted || empty_quote)
+ result.push_back(current);
+ }
+ return result;
+ }
+
+#ifndef BOOST_NO_STD_WSTRING
+ BOOST_PROGRAM_OPTIONS_DECL std::vector<std::wstring>
+ split_winmain(const std::wstring& cmdline)
+ {
+ std::vector<std::wstring> result;
+ std::vector<std::string> aux = split_winmain(to_internal(cmdline));
+ for (size_t i = 0, e = aux.size(); i < e; ++i)
+ result.push_back(from_utf8(aux[i]));
+ return result;
+ }
+#endif
+
+}}
+#endif
+
diff --git a/src/boost/libs/program_options/test/Jamfile.v2 b/src/boost/libs/program_options/test/Jamfile.v2
new file mode 100644
index 000000000..a45ed8e67
--- /dev/null
+++ b/src/boost/libs/program_options/test/Jamfile.v2
@@ -0,0 +1,44 @@
+import testing ;
+
+project
+ : requirements
+ <library>../build//boost_program_options
+ <link>static
+ <variant>debug
+
+# <define>_GLIBCXX_CONCEPT_CHECKS
+# <define>_GLIBCXX_DEBUG
+ ;
+
+rule po-test ( source : input-file ? )
+{
+ return
+ [ run $(source) : : $(input-file) ]
+ [ run $(source) : : $(input-file)
+ : <link>shared <define>BOOST_PROGRAM_OPTIONS_DYN_LINK=1
+ : $(source:B)_dll ]
+ ;
+}
+
+test-suite program_options :
+
+ [ po-test options_description_test.cpp ]
+ [ po-test parsers_test.cpp : config_test.cfg ]
+ [ po-test variable_map_test.cpp ]
+ [ po-test cmdline_test.cpp ]
+ [ po-test positional_options_test.cpp ]
+ [ po-test unicode_test.cpp ]
+ [ po-test winmain.cpp ]
+ [ po-test exception_test.cpp ]
+ [ po-test split_test.cpp ]
+ [ po-test unrecognized_test.cpp ]
+ [ po-test required_test.cpp : required_test.cfg ]
+ [ po-test exception_txt_test.cpp ]
+ [ po-test optional_test.cpp ]
+ [ run options_description_test.cpp : : : <rtti>off <define>BOOST_NO_RTTI <define>BOOST_NO_TYPEID : options_description_no_rtti_test ]
+ ;
+
+exe test_convert : test_convert.cpp ;
+
+# `quick` target (for CI)
+run quick.cpp : --path=initial ;
diff --git a/src/boost/libs/program_options/test/cmdline_test.cpp b/src/boost/libs/program_options/test/cmdline_test.cpp
new file mode 100644
index 000000000..1fc0af83c
--- /dev/null
+++ b/src/boost/libs/program_options/test/cmdline_test.cpp
@@ -0,0 +1,656 @@
+// 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 <boost/program_options/cmdline.hpp>
+#include <boost/program_options/options_description.hpp>
+#include <boost/program_options/detail/cmdline.hpp>
+using namespace boost::program_options;
+using boost::program_options::detail::cmdline;
+
+#include <iostream>
+#include <sstream>
+#include <vector>
+#include <cassert>
+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<string>();
+ s.resize(s.size()-1);
+ } else if (*(s.end()-1) == '?') {
+ v = value<string>()->implicit_value("default");
+ s.resize(s.size()-1);
+ } else if (*(s.end()-1) == '*') {
+ v = value<vector<string> >()->multitoken();
+ s.resize(s.size()-1);
+ } else if (*(s.end()-1) == '+') {
+ v = value<vector<string> >()->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<string> 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<option> options = cmd.run();
+
+ for(unsigned j = 0; j < options.size(); ++j)
+ {
+ option opt = options[j];
+
+ if (opt.position_key != -1) {
+ if (!result.empty())
+ result += " ";
+ result += opt.value[0];
+ } else {
+ if (!result.empty())
+ result += " ";
+ result += opt.string_key + ":";
+ for (size_t k = 0; k < opt.value.size(); ++k) {
+ if (k != 0)
+ result += "-";
+ result += opt.value[k];
+ }
+ }
+ }
+ }
+ catch(unknown_option&) {
+ status = s_unknown_option;
+ }
+ catch(ambiguous_option&) {
+ status = s_ambiguous_option;
+ }
+ catch(invalid_command_line_syntax& e) {
+ status = translate_syntax_error_kind(e.kind());
+ }
+ BOOST_CHECK_EQUAL(status, cases[i].expected_status);
+ BOOST_CHECK_EQUAL(result, cases[i].expected_result);
+ }
+}
+
+void test_long_options()
+{
+ using namespace command_line_style;
+ cmdline::style_t style = cmdline::style_t(
+ allow_long | long_allow_adjacent);
+
+ test_case test_cases1[] = {
+ // Test that long options are recognized and everything else
+ // is treated like arguments
+ {"--foo foo -123 /asd", s_success, "foo: foo -123 /asd"},
+
+ // Unknown option
+ {"--unk", s_unknown_option, ""},
+
+ // Test that abbreviated names do not work
+ {"--fo", s_unknown_option, ""},
+
+ // Test for disallowed parameter
+ {"--foo=13", s_extra_parameter, ""},
+
+ // Test option with required parameter
+ {"--bar=", s_empty_adjacent_parameter, ""},
+ {"--bar", s_missing_parameter, ""},
+
+ {"--bar=123", s_success, "bar:123"},
+ {0, 0, 0}
+ };
+ test_cmdline("foo bar=", style, test_cases1);
+
+
+ style = cmdline::style_t(
+ allow_long | long_allow_next);
+
+ test_case test_cases2[] = {
+ {"--bar 10", s_success, "bar:10"},
+ {"--bar", s_missing_parameter, ""},
+ // Since --bar accepts a parameter, --foo is
+ // considered a value, even though it looks like
+ // an option.
+ {"--bar --foo", s_success, "bar:--foo"},
+ {0, 0, 0}
+ };
+ test_cmdline("foo bar=", style, test_cases2);
+ style = cmdline::style_t(
+ allow_long | long_allow_adjacent
+ | long_allow_next);
+
+ test_case test_cases3[] = {
+ {"--bar=10", s_success, "bar:10"},
+ {"--bar 11", s_success, "bar:11"},
+ {0, 0, 0}
+ };
+ test_cmdline("foo bar=", style, test_cases3);
+
+ style = cmdline::style_t(
+ allow_long | long_allow_adjacent
+ | long_allow_next | case_insensitive);
+
+ // Test case insensitive style.
+ // Note that option names are normalized to lower case.
+ test_case test_cases4[] = {
+ {"--foo", s_success, "foo:"},
+ {"--Foo", s_success, "foo:"},
+ {"--bar=Ab", s_success, "bar:Ab"},
+ {"--Bar=ab", s_success, "bar:ab"},
+ {"--giz", s_success, "Giz:"},
+ {0, 0, 0}
+ };
+ test_cmdline("foo bar= baz? Giz", style, test_cases4);
+}
+
+void test_short_options()
+{
+ using namespace command_line_style;
+ cmdline::style_t style;
+
+ style = cmdline::style_t(
+ allow_short | allow_dash_for_short
+ | short_allow_adjacent);
+
+ test_case test_cases1[] = {
+ {"-d d /bar", s_success, "-d: d /bar"},
+ // This is treated as error when long options are disabled
+ {"--foo", s_success, "--foo"},
+ {"-d13", s_extra_parameter, ""},
+ {"-f14", s_success, "-f:14"},
+ {"-g -f1", s_success, "-g: -f:1"},
+ {"-f", s_missing_parameter, ""},
+ {0, 0, 0}
+ };
+ test_cmdline(",d ,f= ,g", style, test_cases1);
+
+ style = cmdline::style_t(
+ allow_short | allow_dash_for_short
+ | short_allow_next);
+
+ test_case test_cases2[] = {
+ {"-f 13", s_success, "-f:13"},
+ {"-f -13", s_success, "-f:-13"},
+ {"-f", s_missing_parameter, ""},
+ {"-f /foo", s_success, "-f:/foo"},
+ {"-f -d", s_missing_parameter, ""},
+ {0, 0, 0}
+ };
+ test_cmdline(",d ,f=", style, test_cases2);
+
+ style = cmdline::style_t(
+ allow_short | short_allow_next
+ | allow_dash_for_short | short_allow_adjacent);
+
+ test_case test_cases3[] = {
+ {"-f10", s_success, "-f:10"},
+ {"-f 10", s_success, "-f:10"},
+ {"-f -d", s_missing_parameter, ""},
+ {0, 0, 0}
+ };
+ test_cmdline(",d ,f=", style, test_cases3);
+
+ style = cmdline::style_t(
+ allow_short | short_allow_next
+ | allow_dash_for_short
+ | short_allow_adjacent | allow_sticky);
+
+ test_case test_cases4[] = {
+ {"-de", s_success, "-d: -e:"},
+ {"-df10", s_success, "-d: -f:10"},
+ // FIXME: review
+ //{"-d12", s_extra_parameter, ""},
+ {"-f12", s_success, "-f:12"},
+ {"-fe", s_success, "-f:e"},
+ {0, 0, 0}
+ };
+ test_cmdline(",d ,f= ,e", style, test_cases4);
+
+}
+
+
+void test_dos_options()
+{
+ using namespace command_line_style;
+ cmdline::style_t style;
+
+ style = cmdline::style_t(
+ allow_short
+ | allow_slash_for_short | short_allow_adjacent);
+
+ test_case test_cases1[] = {
+ {"/d d -bar", s_success, "-d: d -bar"},
+ {"--foo", s_success, "--foo"},
+ {"/d13", s_extra_parameter, ""},
+ {"/f14", s_success, "-f:14"},
+ {"/f", s_missing_parameter, ""},
+ {0, 0, 0}
+ };
+ test_cmdline(",d ,f=", style, test_cases1);
+
+ style = cmdline::style_t(
+ allow_short
+ | allow_slash_for_short | short_allow_next
+ | short_allow_adjacent | allow_sticky);
+
+ test_case test_cases2[] = {
+ {"/de", s_extra_parameter, ""},
+ {"/fe", s_success, "-f:e"},
+ {0, 0, 0}
+ };
+ test_cmdline(",d ,f= ,e", style, test_cases2);
+
+}
+
+
+void test_disguised_long()
+{
+ using namespace command_line_style;
+ cmdline::style_t style;
+
+ style = cmdline::style_t(
+ allow_short | short_allow_adjacent
+ | allow_dash_for_short
+ | short_allow_next | allow_long_disguise
+ | long_allow_adjacent);
+
+ test_case test_cases1[] = {
+ {"-foo -f", s_success, "foo: foo:"},
+ {"-goo=x -gy", s_success, "goo:x goo:y"},
+ {"-bee=x -by", s_success, "bee:x bee:y"},
+ {0, 0, 0}
+ };
+ test_cmdline("foo,f goo,g= bee,b?", style, test_cases1);
+
+ style = cmdline::style_t(style | allow_slash_for_short);
+ test_case test_cases2[] = {
+ {"/foo -f", s_success, "foo: foo:"},
+ {"/goo=x", s_success, "goo:x"},
+ {0, 0, 0}
+ };
+ test_cmdline("foo,f goo,g= bee,b?", style, test_cases2);
+}
+
+void test_guessing()
+{
+ using namespace command_line_style;
+ cmdline::style_t style;
+
+ style = cmdline::style_t(
+ allow_short | short_allow_adjacent
+ | allow_dash_for_short
+ | allow_long | long_allow_adjacent
+ | allow_guessing | allow_long_disguise);
+
+ test_case test_cases1[] = {
+ {"--opt1", s_success, "opt123:"},
+ {"--opt", s_ambiguous_option, ""},
+ {"--f=1", s_success, "foo:1"},
+ {"-far", s_success, "foo:ar"},
+ {0, 0, 0}
+ };
+ test_cmdline("opt123 opt56 foo,f=", style, test_cases1);
+
+ test_case test_cases2[] = {
+ {"--fname file --fname2 file2", s_success, "fname: file fname2: file2"},
+ {"--fnam file --fnam file2", s_ambiguous_option, ""},
+ {"--fnam file --fname2 file2", s_ambiguous_option, ""},
+ {"--fname2 file2 --fnam file", s_ambiguous_option, ""},
+ {0, 0, 0}
+ };
+ test_cmdline("fname fname2", style, test_cases2);
+}
+
+void test_arguments()
+{
+ using namespace command_line_style;
+ cmdline::style_t style;
+
+ style = cmdline::style_t(
+ allow_short | allow_long
+ | allow_dash_for_short
+ | short_allow_adjacent | long_allow_adjacent);
+
+ test_case test_cases1[] = {
+ {"-f file -gx file2", s_success, "-f: file -g:x file2"},
+ {"-f - -gx - -- -e", s_success, "-f: - -g:x - -e"},
+ {0, 0, 0}
+ };
+ test_cmdline(",f ,g= ,e", style, test_cases1);
+
+ // "--" should stop options regardless of whether long options are
+ // allowed or not.
+
+ style = cmdline::style_t(
+ allow_short | short_allow_adjacent
+ | allow_dash_for_short);
+
+ test_case test_cases2[] = {
+ {"-f - -gx - -- -e", s_success, "-f: - -g:x - -e"},
+ {0, 0, 0}
+ };
+ test_cmdline(",f ,g= ,e", style, test_cases2);
+}
+
+void test_prefix()
+{
+ using namespace command_line_style;
+ cmdline::style_t style;
+
+ style = cmdline::style_t(
+ allow_short | allow_long
+ | allow_dash_for_short
+ | short_allow_adjacent | long_allow_adjacent
+ );
+
+ test_case test_cases1[] = {
+ {"--foo.bar=12", s_success, "foo.bar:12"},
+ {0, 0, 0}
+ };
+
+ test_cmdline("foo*=", style, test_cases1);
+}
+
+
+pair<string, string> at_option_parser(string const&s)
+{
+ if ('@' == s[0])
+ return std::make_pair(string("response-file"), s.substr(1));
+ else
+ return pair<string, string>();
+}
+
+pair<string, string> at_option_parser_broken(string const&s)
+{
+ if ('@' == s[0])
+ return std::make_pair(string("some garbage"), s.substr(1));
+ else
+ return pair<string, string>();
+}
+
+
+
+void test_additional_parser()
+{
+ options_description desc;
+ desc.add_options()
+ ("response-file", value<string>(), "response file")
+ ("foo", value<int>(), "foo")
+ ("bar,baz", value<int>(), "bar")
+ ;
+
+ vector<string> input;
+ input.push_back("@config");
+ input.push_back("--foo=1");
+ input.push_back("--baz=11");
+
+ cmdline cmd(input);
+ cmd.set_options_description(desc);
+ cmd.set_additional_parser(at_option_parser);
+
+ vector<option> result = cmd.run();
+
+ BOOST_REQUIRE(result.size() == 3);
+ BOOST_CHECK_EQUAL(result[0].string_key, "response-file");
+ BOOST_CHECK_EQUAL(result[0].value[0], "config");
+ BOOST_CHECK_EQUAL(result[1].string_key, "foo");
+ BOOST_CHECK_EQUAL(result[1].value[0], "1");
+ BOOST_CHECK_EQUAL(result[2].string_key, "bar");
+ BOOST_CHECK_EQUAL(result[2].value[0], "11");
+
+ // Test that invalid options returned by additional style
+ // parser are detected.
+ cmdline cmd2(input);
+ cmd2.set_options_description(desc);
+ cmd2.set_additional_parser(at_option_parser_broken);
+
+ BOOST_CHECK_THROW(cmd2.run(), unknown_option);
+
+}
+
+vector<option> at_option_parser2(vector<string>& args)
+{
+ vector<option> result;
+ if ('@' == args[0][0]) {
+ // Simulate reading the response file.
+ result.push_back(option("foo", vector<string>(1, "1")));
+ result.push_back(option("bar", vector<string>(1, "1")));
+ args.erase(args.begin());
+ }
+ return result;
+}
+
+
+void test_style_parser()
+{
+ options_description desc;
+ desc.add_options()
+ ("foo", value<int>(), "foo")
+ ("bar", value<int>(), "bar")
+ ;
+
+ vector<string> input;
+ input.push_back("@config");
+
+ cmdline cmd(input);
+ cmd.set_options_description(desc);
+ cmd.extra_style_parser(at_option_parser2);
+
+ vector<option> result = cmd.run();
+
+ BOOST_REQUIRE(result.size() == 2);
+ BOOST_CHECK_EQUAL(result[0].string_key, "foo");
+ BOOST_CHECK_EQUAL(result[0].value[0], "1");
+ BOOST_CHECK_EQUAL(result[1].string_key, "bar");
+ BOOST_CHECK_EQUAL(result[1].value[0], "1");
+}
+
+void test_unregistered()
+{
+ // Check unregisted option when no options are registed at all.
+ options_description desc;
+
+ vector<string> input;
+ input.push_back("--foo=1");
+ input.push_back("--bar");
+ input.push_back("1");
+ input.push_back("-b");
+ input.push_back("-biz");
+
+ cmdline cmd(input);
+ cmd.set_options_description(desc);
+ cmd.allow_unregistered();
+
+ vector<option> result = cmd.run();
+ BOOST_REQUIRE(result.size() == 5);
+ // --foo=1
+ BOOST_CHECK_EQUAL(result[0].string_key, "foo");
+ BOOST_CHECK_EQUAL(result[0].unregistered, true);
+ BOOST_CHECK_EQUAL(result[0].value[0], "1");
+ // --bar
+ BOOST_CHECK_EQUAL(result[1].string_key, "bar");
+ BOOST_CHECK_EQUAL(result[1].unregistered, true);
+ BOOST_CHECK(result[1].value.empty());
+ // '1' is considered a positional option, not a value to
+ // --bar
+ BOOST_CHECK(result[2].string_key.empty());
+ BOOST_CHECK(result[2].position_key == 0);
+ BOOST_CHECK_EQUAL(result[2].unregistered, false);
+ BOOST_CHECK_EQUAL(result[2].value[0], "1");
+ // -b
+ BOOST_CHECK_EQUAL(result[3].string_key, "-b");
+ BOOST_CHECK_EQUAL(result[3].unregistered, true);
+ BOOST_CHECK(result[3].value.empty());
+ // -biz
+ BOOST_CHECK_EQUAL(result[4].string_key, "-b");
+ BOOST_CHECK_EQUAL(result[4].unregistered, true);
+ BOOST_CHECK_EQUAL(result[4].value[0], "iz");
+
+ // Check sticky short options together with unregisted options.
+
+ desc.add_options()
+ ("help,h", "")
+ ("magic,m", value<string>(), "")
+ ;
+
+ input.clear();
+ input.push_back("-hc");
+ input.push_back("-mc");
+
+
+ cmdline cmd2(input);
+ cmd2.set_options_description(desc);
+ cmd2.allow_unregistered();
+
+ result = cmd2.run();
+
+ BOOST_REQUIRE(result.size() == 3);
+ BOOST_CHECK_EQUAL(result[0].string_key, "help");
+ BOOST_CHECK_EQUAL(result[0].unregistered, false);
+ BOOST_CHECK(result[0].value.empty());
+ BOOST_CHECK_EQUAL(result[1].string_key, "-c");
+ BOOST_CHECK_EQUAL(result[1].unregistered, true);
+ BOOST_CHECK(result[1].value.empty());
+ BOOST_CHECK_EQUAL(result[2].string_key, "magic");
+ BOOST_CHECK_EQUAL(result[2].unregistered, false);
+ BOOST_CHECK_EQUAL(result[2].value[0], "c");
+
+ // CONSIDER:
+ // There's a corner case:
+ // -foo
+ // when 'allow_long_disguise' is set. Should this be considered
+ // disguised long option 'foo' or short option '-f' with value 'oo'?
+ // It's not clear yet, so I'm leaving the decision till later.
+}
+
+void test_implicit_value()
+{
+ using namespace command_line_style;
+ cmdline::style_t style;
+
+ style = cmdline::style_t(
+ allow_long | long_allow_adjacent
+ );
+
+ test_case test_cases1[] = {
+ // 'bar' does not even look like option, so is consumed
+ {"--foo bar", s_success, "foo:bar"},
+ // '--bar' looks like option, and such option exists, so we don't consume this token
+ {"--foo --bar", s_success, "foo: bar:"},
+ // '--biz' looks like option, but does not match any existing one.
+ // Presently this results in parse error, since
+ // (1) in cmdline.cpp:finish_option, we only consume following tokens if they are
+ // requires
+ // (2) in cmdline.cpp:run, we let options consume following positional options
+ // For --biz, an exception is thrown between 1 and 2.
+ // We might want to fix that in future.
+ {"--foo --biz", s_unknown_option, ""},
+ {0, 0, 0}
+ };
+
+ test_cmdline("foo? bar?", style, test_cases1);
+}
+
+int main(int /*ac*/, char** /*av*/)
+{
+ test_long_options();
+ test_short_options();
+ test_dos_options();
+ test_disguised_long();
+ test_guessing();
+ test_arguments();
+ test_prefix();
+ test_additional_parser();
+ test_style_parser();
+ test_unregistered();
+ test_implicit_value();
+
+ return 0;
+}
diff --git a/src/boost/libs/program_options/test/config_test.cfg b/src/boost/libs/program_options/test/config_test.cfg
new file mode 100644
index 000000000..1530f7c8a
--- /dev/null
+++ b/src/boost/libs/program_options/test/config_test.cfg
@@ -0,0 +1,9 @@
+gv1 = 0#asd
+empty_value =
+plug3 = 7
+b = true
+
+[m1]
+v1 = 1
+v2 = 2
+v3 = 3
diff --git a/src/boost/libs/program_options/test/exception_test.cpp b/src/boost/libs/program_options/test/exception_test.cpp
new file mode 100644
index 000000000..438f68db6
--- /dev/null
+++ b/src/boost/libs/program_options/test/exception_test.cpp
@@ -0,0 +1,264 @@
+// Copyright Sascha Ochsenknecht 2009.
+// 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 <boost/program_options/parsers.hpp>
+#include <boost/program_options/options_description.hpp>
+#include <boost/program_options/variables_map.hpp>
+#include <boost/program_options/cmdline.hpp>
+using namespace boost::program_options;
+
+#include <iostream>
+#include <sstream>
+#include <vector>
+#include <cassert>
+using namespace std;
+
+#include "minitest.hpp"
+
+
+void test_ambiguous()
+{
+ options_description desc;
+ desc.add_options()
+ ("cfgfile,c", value<string>()->multitoken(), "the config file")
+ ("output,c", value<string>(), "the output file")
+ ("output,o", value<string>(), "the output file")
+ ;
+
+ const char* cmdline[] = {"program", "-c", "file", "-o", "anotherfile"};
+
+ variables_map vm;
+ try {
+ store(parse_command_line(sizeof(cmdline)/sizeof(const char*),
+ const_cast<char**>(cmdline), desc), vm);
+ }
+ catch (ambiguous_option& e)
+ {
+ BOOST_CHECK_EQUAL(e.alternatives().size(), 2);
+ BOOST_CHECK_EQUAL(e.get_option_name(), "-c");
+ BOOST_CHECK_EQUAL(e.alternatives()[0], "cfgfile");
+ BOOST_CHECK_EQUAL(e.alternatives()[1], "output");
+ }
+}
+
+
+void test_ambiguous_long()
+{
+ options_description desc;
+ desc.add_options()
+ ("cfgfile,c", value<string>()->multitoken(), "the config file")
+ ("output,c", value<string>(), "the output file")
+ ("output,o", value<string>(), "the output file")
+ ;
+
+ const char* cmdline[] = {"program", "--cfgfile", "file", "--output", "anotherfile"};
+
+ variables_map vm;
+ try {
+ store(parse_command_line(sizeof(cmdline)/sizeof(const char*),
+ const_cast<char**>(cmdline), desc), vm);
+ }
+ catch (ambiguous_option& e)
+ {
+ BOOST_CHECK_EQUAL(e.alternatives().size(), 2);
+ BOOST_CHECK_EQUAL(e.get_option_name(), "--output");
+ BOOST_CHECK_EQUAL(e.alternatives()[0], "output");
+ BOOST_CHECK_EQUAL(e.alternatives()[1], "output");
+ }
+}
+
+void test_ambiguous_multiple_long_names()
+{
+ options_description desc;
+ desc.add_options()
+ ("cfgfile,foo,c", value<string>()->multitoken(), "the config file")
+ ("output,foo,o", value<string>(), "the output file")
+ ;
+
+ const char* cmdline[] = {"program", "--foo", "file"};
+
+ variables_map vm;
+ try {
+ store(parse_command_line(sizeof(cmdline)/sizeof(const char*),
+ const_cast<char**>(cmdline), desc), vm);
+ }
+ catch (ambiguous_option& e)
+ {
+ BOOST_CHECK_EQUAL(e.alternatives().size(), 2);
+ BOOST_CHECK_EQUAL(e.get_option_name(), "--foo");
+ BOOST_CHECK_EQUAL(e.alternatives()[0], "cfgfile");
+ BOOST_CHECK_EQUAL(e.alternatives()[1], "output");
+ }
+}
+
+
+
+void test_unknown_option()
+{
+ options_description desc;
+ desc.add_options()
+ ("cfgfile,c", value<string>(), "the configfile")
+ ;
+
+ const char* cmdline[] = {"program", "-c", "file", "-f", "anotherfile"};
+
+ variables_map vm;
+ try {
+ store(parse_command_line(sizeof(cmdline)/sizeof(const char*),
+ const_cast<char**>(cmdline), desc), vm);
+ }
+ catch (unknown_option& e)
+ {
+ BOOST_CHECK_EQUAL(e.get_option_name(), "-f");
+ BOOST_CHECK_EQUAL(string(e.what()), "unrecognised option '-f'");
+ }
+}
+
+
+
+void test_multiple_values()
+{
+ options_description desc;
+ desc.add_options()
+ ("cfgfile,c", value<string>()->multitoken(), "the config file")
+ ("output,o", value<string>(), "the output file")
+ ;
+
+ const char* cmdline[] = { "program", "-o", "fritz", "hugo", "--cfgfile", "file", "c", "-o", "text.out" };
+
+ variables_map vm;
+ try {
+ store(parse_command_line(sizeof(cmdline)/sizeof(const char*),
+ const_cast<char**>(cmdline), desc), vm);
+ notify(vm);
+ }
+ catch (validation_error& e)
+ {
+ // TODO: this is currently validation_error, shouldn't it be multiple_values ???
+ //
+ // multiple_values is thrown only at one place untyped_value::xparse(),
+ // but I think this can never be reached
+ // because: untyped_value always has one value and this is filtered before reach specific
+ // validation and parsing
+ //
+ BOOST_CHECK_EQUAL(e.get_option_name(), "--cfgfile");
+ BOOST_CHECK_EQUAL(string(e.what()), "option '--cfgfile' only takes a single argument");
+ }
+}
+
+
+void test_multiple_occurrences()
+{
+ options_description desc;
+ desc.add_options()
+ ("cfgfile,c", value<string>(), "the configfile")
+ ;
+
+ const char* cmdline[] = {"program", "--cfgfile", "file", "-c", "anotherfile"};
+
+ variables_map vm;
+ try {
+ store(parse_command_line(sizeof(cmdline)/sizeof(const char*),
+ const_cast<char**>(cmdline), desc), vm);
+ notify(vm);
+ }
+ catch (multiple_occurrences& e)
+ {
+ BOOST_CHECK_EQUAL(e.get_option_name(), "--cfgfile");
+ BOOST_CHECK_EQUAL(string(e.what()), "option '--cfgfile' cannot be specified more than once");
+ }
+}
+
+void test_multiple_occurrences_with_different_names()
+{
+ options_description desc;
+ desc.add_options()
+ ("cfgfile,config-file,c", value<string>(), "the configfile")
+ ;
+
+ const char* cmdline[] = {"program", "--config-file", "file", "--cfgfile", "anotherfile"};
+
+ variables_map vm;
+ try {
+ store(parse_command_line(sizeof(cmdline)/sizeof(const char*),
+ const_cast<char**>(cmdline), desc), vm);
+ notify(vm);
+ }
+ catch (multiple_occurrences& e)
+ {
+ BOOST_CHECK( (e.get_option_name() == "--cfgfile") || (e.get_option_name() == "--config-file"));
+ BOOST_CHECK(
+ (string(e.what()) == "option '--cfgfile' cannot be specified more than once") ||
+ (string(e.what()) == "option '--config-file' cannot be specified more than once")
+ );
+ }
+}
+
+
+void test_multiple_occurrences_with_non_key_names()
+{
+ options_description desc;
+ desc.add_options()
+ ("cfgfile,config-file,c", value<string>(), "the configfile")
+ ;
+
+ const char* cmdline[] = {"program", "--config-file", "file", "-c", "anotherfile"};
+
+ variables_map vm;
+ try {
+ store(parse_command_line(sizeof(cmdline)/sizeof(const char*),
+ const_cast<char**>(cmdline), desc), vm);
+ notify(vm);
+ }
+ catch (multiple_occurrences& e)
+ {
+ BOOST_CHECK_EQUAL(e.get_option_name(), "--cfgfile");
+ BOOST_CHECK_EQUAL(string(e.what()), "option '--cfgfile' cannot be specified more than once");
+ }
+}
+
+
+void test_missing_value()
+{
+ options_description desc;
+ desc.add_options()
+ ("cfgfile,c", value<string>()->multitoken(), "the config file")
+ ("output,o", value<string>(), "the output file")
+ ;
+ // missing value for option '-c'
+ const char* cmdline[] = { "program", "-c", "-c", "output.txt"};
+
+ variables_map vm;
+
+ try {
+ store(parse_command_line(sizeof(cmdline)/sizeof(const char*),
+ const_cast<char**>(cmdline), desc), vm);
+ notify(vm);
+ }
+ catch (invalid_command_line_syntax& e)
+ {
+ BOOST_CHECK_EQUAL(e.kind(), invalid_syntax::missing_parameter);
+ BOOST_CHECK_EQUAL(e.tokens(), "--cfgfile");
+ }
+}
+
+
+
+int main(int /*ac*/, char** /*av*/)
+{
+ test_ambiguous();
+ test_ambiguous_long();
+ test_ambiguous_multiple_long_names();
+ test_unknown_option();
+ test_multiple_values();
+ test_multiple_occurrences();
+ test_multiple_occurrences_with_different_names();
+ test_multiple_occurrences_with_non_key_names();
+ test_missing_value();
+
+ return 0;
+}
+
diff --git a/src/boost/libs/program_options/test/exception_txt_test.cpp b/src/boost/libs/program_options/test/exception_txt_test.cpp
new file mode 100644
index 000000000..43e0014bc
--- /dev/null
+++ b/src/boost/libs/program_options/test/exception_txt_test.cpp
@@ -0,0 +1,693 @@
+// Copyright Leo Goodstadt 2012
+// 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 <boost/program_options/parsers.hpp>
+#include <boost/program_options/options_description.hpp>
+#include <boost/program_options/variables_map.hpp>
+#include <boost/program_options/cmdline.hpp>
+using namespace boost::program_options;
+
+#include <iostream>
+#include <sstream>
+#include <vector>
+#include <cassert>
+using namespace std;
+
+#include "minitest.hpp"
+
+
+
+//
+// like BOOST_CHECK_EQUAL but with more descriptive error message
+//
+#define CHECK_EQUAL(description, a, b) if (a != b) {std::cerr << "\n\nError:\n<<" << \
+ description << ">>\n Expected text=\"" << b << "\"\n Actual text =\"" << a << "\"\n\n"; assert(a == b);}
+
+
+// Uncomment for Debugging, removes asserts so we can see more failures!
+//#define BOOST_ERROR(description) std::cerr << description; std::cerr << "\n";
+
+
+//8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
+//
+// Uncomment to print out the complete set of diagnostic messages for the different test cases
+/*
+#define CHECK_EQUAL(description, a, b) if (a != b) {std::cerr << "\n\nError: " << \
+ description << "\n Expecting\n" << b << "\n Found\n" << a << "\n\n"; } \
+ else {std::cout << description<< "\t" << b << "\n";}
+*/
+
+//8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888
+
+
+//
+// test exception for each specified command line style, e.g. short dash or config file
+//
+template<typename EXCEPTION>
+void test_each_exception_message(const string& test_description, const vector<const char*>& argv, options_description& desc, int style, string exception_msg, istream& is = cin)
+{
+ if (exception_msg.length() == 0)
+ return;
+ variables_map vm;
+ unsigned argc = argv.size();
+
+
+ try {
+ if (style == -1)
+ store(parse_config_file(is, desc), vm);
+ else
+ store(parse_command_line(argv.size(), &argv[0], desc, style), vm);
+ notify(vm);
+ }
+ catch (EXCEPTION& e)
+ {
+ //cerr << "Correct:\n\t" << e.what() << "\n";
+ CHECK_EQUAL(test_description, e.what(), exception_msg);
+ return;
+ }
+ catch (std::exception& e)
+ {
+ // concatenate argv without boost::algorithm::join
+ string argv_txt;
+ for (unsigned ii = 0; ii < argc - 1; ++ii)
+ argv_txt += argv[ii] + string(" ");
+ if (argc)
+ argv_txt += argv[argc - 1];
+
+ BOOST_ERROR("\n<<" + test_description +
+ string(">>\n Unexpected exception type!\n Actual text =\"") + e.what() +
+ "\"\n argv =\"" + argv_txt +
+ "\"\n Expected text=\"" + exception_msg + "\"\n");
+ return;
+ }
+ BOOST_ERROR(test_description + ": No exception thrown. ");
+}
+
+
+
+
+//
+// test exception messages for all command line styles (unix/long/short/slash/config file)
+//
+// try each command line style in turn
+const int unix_style = command_line_style::unix_style;
+const int short_dash = command_line_style::allow_dash_for_short | command_line_style::allow_short | command_line_style::short_allow_adjacent | command_line_style::allow_sticky;
+const int short_slash = command_line_style::allow_slash_for_short | command_line_style::allow_short | command_line_style::short_allow_adjacent;
+const int long_dash = command_line_style::allow_long | command_line_style::long_allow_adjacent | command_line_style::allow_guessing;
+
+
+
+template<typename EXCEPTION>
+void test_exception_message(const vector<vector<const char*> >& argv,
+ options_description& desc,
+ const string& error_description,
+ const char* expected_message_template[5])
+{
+ string expected_message;
+
+ // unix
+ expected_message = expected_message_template[0];
+ test_each_exception_message<EXCEPTION>(error_description + " -- unix",
+ argv[0], desc, unix_style, expected_message);
+
+ // long dash only
+ expected_message = expected_message_template[1];
+ test_each_exception_message<EXCEPTION>(error_description + " -- long_dash",
+ argv[1], desc, long_dash, expected_message);
+
+
+ // short dash only
+ expected_message = expected_message_template[2];
+ test_each_exception_message<EXCEPTION>(error_description + " -- short_dash",
+ argv[2], desc, short_dash, expected_message);
+
+ // short slash only
+ expected_message = expected_message_template[3];
+ test_each_exception_message<EXCEPTION>(error_description + " -- short_slash",
+ argv[3], desc, short_slash, expected_message);
+
+ // config file only
+ expected_message = expected_message_template[4];
+ if (expected_message.length())
+ {
+ istringstream istrm(argv[4][0]);
+ test_each_exception_message<EXCEPTION>(error_description + " -- config_file",
+ argv[4], desc, -1, expected_message, istrm);
+ }
+
+}
+
+#define VEC_STR_PUSH_BACK(vec, c_array) \
+ vec.push_back(vector<const char*>(c_array, c_array + sizeof(c_array) / sizeof(char*)));
+
+//________________________________________________________________________________________
+//
+// invalid_option_value
+//
+//________________________________________________________________________________________
+void test_invalid_option_value_exception_msg()
+{
+ options_description desc;
+ desc.add_options()
+ ("int-option,d", value< int >(), "An option taking an integer")
+ ;
+
+ vector<vector<const char*> > argv;
+ const char* argv0[] = { "program", "-d", "A_STRING"} ; VEC_STR_PUSH_BACK(argv, argv0);
+ const char* argv1[] = { "program", "--int", "A_STRING"}; VEC_STR_PUSH_BACK(argv, argv1);
+ const char* argv2[] = { "program", "-d", "A_STRING"} ; VEC_STR_PUSH_BACK(argv, argv2);
+ const char* argv3[] = { "program", "/d", "A_STRING"} ; VEC_STR_PUSH_BACK(argv, argv3);
+ const char* argv4[] = { "int-option=A_STRING"} ; VEC_STR_PUSH_BACK(argv, argv4);
+
+ const char* expected_msg[5] = {
+ "the argument ('A_STRING') for option '--int-option' is invalid",
+ "the argument ('A_STRING') for option '--int-option' is invalid",
+ "the argument ('A_STRING') for option '-d' is invalid",
+ "the argument ('A_STRING') for option '/d' is invalid",
+ "the argument ('A_STRING') for option 'int-option' is invalid",
+ };
+
+
+ test_exception_message<invalid_option_value>(argv, desc, "invalid_option_value",
+ expected_msg);
+
+
+}
+
+//________________________________________________________________________________________
+//
+// missing_value
+//
+//________________________________________________________________________________________
+void test_missing_value_exception_msg()
+{
+ options_description desc;
+ desc.add_options()
+ ("cfgfile,e", value<string>(), "the config file")
+ ("output,o", value<string>(), "the output file")
+ ;
+ vector<vector<const char*> > argv;
+ const char* argv0[] = { "program", "-e", "-e", "output.txt"} ; VEC_STR_PUSH_BACK(argv, argv0);
+ const char* argv1[] = { "program", "--cfgfile"} ; VEC_STR_PUSH_BACK(argv, argv1);
+ const char* argv2[] = { "program", "-e", "-e", "output.txt"} ; VEC_STR_PUSH_BACK(argv, argv2);
+ const char* argv3[] = { "program", "/e", "/e", "output.txt"} ; VEC_STR_PUSH_BACK(argv, argv3);
+ const char* argv4[] = { ""} ; VEC_STR_PUSH_BACK(argv, argv4);
+
+ const char* expected_msg[5] = {
+ "the required argument for option '--cfgfile' is missing",
+ "the required argument for option '--cfgfile' is missing",
+ "the required argument for option '-e' is missing",
+ "", // Ignore probable bug in cmdline::finish_option
+ //"the required argument for option '/e' is missing",
+ "",
+ };
+ test_exception_message<invalid_command_line_syntax>(argv, desc,
+ "invalid_syntax::missing_parameter",
+ expected_msg);
+}
+
+//________________________________________________________________________________________
+//
+// ambiguous_option
+//
+//________________________________________________________________________________________
+void test_ambiguous_option_exception_msg()
+{
+ options_description desc;
+ desc.add_options()
+ ("cfgfile1,c", value<string>(), "the config file")
+ ("cfgfile2,o", value<string>(), "the config file")
+ ("good,g", "good option")
+ ("output,c", value<string>(), "the output file")
+ ("output", value<string>(), "the output file")
+ ;
+
+ vector<vector<const char*> > argv;
+ const char* argv0[] = {"program", "-ggc", "file", "-o", "anotherfile"} ; VEC_STR_PUSH_BACK(argv, argv0);
+ const char* argv1[] = {"program", "--cfgfile", "file", "--cfgfile", "anotherfile"} ; VEC_STR_PUSH_BACK(argv, argv1);
+ const char* argv2[] = {"program", "-ggc", "file", "-o", "anotherfile"} ; VEC_STR_PUSH_BACK(argv, argv2);
+ const char* argv3[] = {"program", "/c", "file", "/o", "anotherfile"} ; VEC_STR_PUSH_BACK(argv, argv3);
+ const char* argv4[] = { "output=output.txt\n"} ; VEC_STR_PUSH_BACK(argv, argv4);
+ const char* expected_msg[5] = {
+ "option '-c' is ambiguous and matches '--cfgfile1', and '--output'",
+ "option '--cfgfile' is ambiguous and matches '--cfgfile1', and '--cfgfile2'",
+ "option '-c' is ambiguous",
+ "option '/c' is ambiguous",
+ "option 'output' is ambiguous and matches different versions of 'output'",
+ };
+ test_exception_message<ambiguous_option>(argv, desc, "ambiguous_option",
+ expected_msg);
+}
+
+//________________________________________________________________________________________
+//
+// multiple_occurrences
+//
+//________________________________________________________________________________________
+void test_multiple_occurrences_exception_msg()
+{
+ options_description desc;
+ desc.add_options()
+ ("cfgfile,c", value<string>(), "the configfile")
+ ;
+
+ vector<vector<const char*> > argv;
+ const char* argv0[] = {"program", "-c", "file", "-c", "anotherfile"} ; VEC_STR_PUSH_BACK(argv, argv0);
+ const char* argv1[] = {"program", "--cfgfi", "file", "--cfgfi", "anotherfile"} ; VEC_STR_PUSH_BACK(argv, argv1);
+ const char* argv2[] = {"program", "-c", "file", "-c", "anotherfile"} ; VEC_STR_PUSH_BACK(argv, argv2);
+ const char* argv3[] = {"program", "/c", "file", "/c", "anotherfile"} ; VEC_STR_PUSH_BACK(argv, argv3);
+ const char* argv4[] = { "cfgfile=output.txt\ncfgfile=output.txt\n"} ; VEC_STR_PUSH_BACK(argv, argv4);
+ const char* expected_msg[5] = {
+ "option '--cfgfile' cannot be specified more than once",
+ "option '--cfgfile' cannot be specified more than once",
+ "option '-c' cannot be specified more than once",
+ "option '/c' cannot be specified more than once",
+ "option 'cfgfile' cannot be specified more than once",
+ };
+ test_exception_message<multiple_occurrences>(argv, desc, "multiple_occurrences",
+ expected_msg);
+}
+
+//________________________________________________________________________________________
+//
+// unknown_option
+//
+//________________________________________________________________________________________
+void test_unknown_option_exception_msg()
+{
+ options_description desc;
+ desc.add_options()
+ ("good,g", "good option")
+ ;
+
+ vector<vector<const char*> > argv;
+ const char* argv0[] = {"program", "-ggc", "file"} ; VEC_STR_PUSH_BACK(argv, argv0);
+ const char* argv1[] = {"program", "--cfgfile", "file"} ; VEC_STR_PUSH_BACK(argv, argv1);
+ const char* argv2[] = {"program", "-ggc", "file"} ; VEC_STR_PUSH_BACK(argv, argv2);
+ const char* argv3[] = {"program", "/c", "file"} ; VEC_STR_PUSH_BACK(argv, argv3);
+ const char* argv4[] = { "cfgfile=output.txt\n"} ; VEC_STR_PUSH_BACK(argv, argv4);
+ const char* expected_msg[5] = {
+ "unrecognised option '-ggc'",
+ "unrecognised option '--cfgfile'",
+ "unrecognised option '-ggc'",
+ "unrecognised option '/c'",
+ "unrecognised option 'cfgfile'",
+ };
+ test_exception_message<unknown_option>(argv, desc, "unknown_option", expected_msg);
+}
+
+//________________________________________________________________________________________
+//
+// validation_error::invalid_bool_value
+//
+//________________________________________________________________________________________
+void test_invalid_bool_value_exception_msg()
+{
+ options_description desc;
+ desc.add_options()
+ ("bool_option,b", value< bool>(), "bool_option")
+ ;
+
+
+ vector<vector<const char*> > argv;
+ const char* argv0[] = {"program", "-b", "file"} ; VEC_STR_PUSH_BACK(argv, argv0);
+ const char* argv1[] = {"program", "--bool_optio", "file"} ; VEC_STR_PUSH_BACK(argv, argv1);
+ const char* argv2[] = {"program", "-b", "file"} ; VEC_STR_PUSH_BACK(argv, argv2);
+ const char* argv3[] = {"program", "/b", "file"} ; VEC_STR_PUSH_BACK(argv, argv3);
+ const char* argv4[] = { "bool_option=output.txt\n"} ; VEC_STR_PUSH_BACK(argv, argv4);
+ const char* expected_msg[5] = {
+ "the argument ('file') for option '--bool_option' is invalid. Valid choices are 'on|off', 'yes|no', '1|0' and 'true|false'",
+ "the argument ('file') for option '--bool_option' is invalid. Valid choices are 'on|off', 'yes|no', '1|0' and 'true|false'",
+ "the argument ('file') for option '-b' is invalid. Valid choices are 'on|off', 'yes|no', '1|0' and 'true|false'",
+ "the argument ('file') for option '/b' is invalid. Valid choices are 'on|off', 'yes|no', '1|0' and 'true|false'",
+ "the argument ('output.txt') for option 'bool_option' is invalid. Valid choices are 'on|off', 'yes|no', '1|0' and 'true|false'",
+ };
+ test_exception_message<validation_error>(argv,
+ desc,
+ "validation_error::invalid_bool_value",
+ expected_msg);
+}
+
+
+
+
+//________________________________________________________________________________________
+//
+// validation_error::multiple_values_not_allowed
+//
+//________________________________________________________________________________________
+//
+// Strange exception: sole purpose seems to be catching multitoken() associated with a scalar
+// validation_error::multiple_values_not_allowed seems thus to be a programmer error
+//
+//
+void test_multiple_values_not_allowed_exception_msg()
+{
+ options_description desc;
+ desc.add_options()
+ ("cfgfile,c", value<string>()->multitoken(), "the config file")
+ ("good,g", "good option")
+ ("output,o", value<string>(), "the output file")
+ ;
+
+ vector<vector<const char*> > argv;
+ const char* argv0[] = { "program", "-c", "file", "c", "-o", "fritz", "hugo" } ; VEC_STR_PUSH_BACK(argv, argv0);
+ const char* argv1[] = { "program", "--cfgfil", "file", "c", "--outpu", "fritz", "hugo" } ; VEC_STR_PUSH_BACK(argv, argv1);
+ const char* argv2[] = { "program", "-c", "file", "c", "-o", "fritz", "hugo"} ; VEC_STR_PUSH_BACK(argv, argv2);
+ const char* argv3[] = { "program", "/c", "file", "c", "/o", "fritz", "hugo"} ; VEC_STR_PUSH_BACK(argv, argv3);
+ const char* argv4[] = { "" } ; VEC_STR_PUSH_BACK(argv, argv4);
+ const char* expected_msg[5] = {
+ "option '--cfgfile' only takes a single argument",
+ "option '--cfgfile' only takes a single argument",
+ "option '-c' only takes a single argument",
+ "option '/c' only takes a single argument",
+ "",
+ };
+ test_exception_message<validation_error>(argv,
+ desc,
+ "validation_error::multiple_values_not_allowed",
+ expected_msg);
+}
+
+//________________________________________________________________________________________
+//
+// validation_error::at_least_one_value_required
+//
+//________________________________________________________________________________________
+//
+// Strange exception: sole purpose seems to be catching zero_tokens() associated with a scalar
+// validation_error::multiple_values_not_allowed seems thus to be a programmer error
+//
+//
+void test_at_least_one_value_required_exception_msg()
+{
+
+
+ options_description desc;
+ desc.add_options()
+ ("cfgfile,c", value<int>()->zero_tokens(), "the config file")
+ ("other,o", value<string>(), "other")
+ ;
+
+ vector<vector<const char*> > argv;
+ const char* argv0[] = { "program", "-c" } ; VEC_STR_PUSH_BACK(argv, argv0);
+ const char* argv1[] = { "program", "--cfg", "--o", "name" } ; VEC_STR_PUSH_BACK(argv, argv1);
+ const char* argv2[] = { "program", "-c" , "-o" , "name" } ; VEC_STR_PUSH_BACK(argv, argv2);
+ const char* argv3[] = { "program", "/c" } ; VEC_STR_PUSH_BACK(argv, argv3);
+ const char* argv4[] = { "" } ; VEC_STR_PUSH_BACK(argv, argv4);
+ const char* expected_msg[5] = {
+ "option '--cfgfile' requires at least one argument",
+ "option '--cfgfile' requires at least one argument",
+ "option '-c' requires at least one argument",
+ "option '/c' requires at least one argument",
+ "",
+ };
+ test_exception_message<validation_error>(argv,
+ desc,
+ "validation_error::at_least_one_value_required",
+ expected_msg);
+}
+
+
+//________________________________________________________________________________________
+//
+// required_option
+//
+//________________________________________________________________________________________
+void test_required_option_exception_msg()
+{
+ options_description desc;
+ desc.add_options()
+ ("cfgfile,c", value<string>()->required(), "the config file")
+ ("good,g", "good option")
+ ("output,o", value<string>()->required(), "the output file")
+ ;
+
+ vector<vector<const char*> > argv;
+ const char* argv0[] = { "program", "-g" } ; VEC_STR_PUSH_BACK(argv, argv0);
+ const char* argv1[] = { "program", "--g" } ; VEC_STR_PUSH_BACK(argv, argv1);
+ const char* argv2[] = { "program", "-g"} ; VEC_STR_PUSH_BACK(argv, argv2);
+ const char* argv3[] = { "program", "/g"} ; VEC_STR_PUSH_BACK(argv, argv3);
+ const char* argv4[] = { "" } ; VEC_STR_PUSH_BACK(argv, argv4);
+ const char* expected_msg[5] = {
+ "the option '--cfgfile' is required but missing",
+ "the option '--cfgfile' is required but missing",
+ "the option '-c' is required but missing",
+ "the option '/c' is required but missing",
+ "the option 'cfgfile' is required but missing",
+ };
+ test_exception_message<required_option>(argv,
+ desc,
+ "required_option",
+ expected_msg);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/**
+ * Check if this is the expected exception with the right message is being thrown inside
+ * func
+*/
+template <typename EXCEPTION, typename FUNC>
+void test_exception(const string& test_name, const string& exception_txt, FUNC func)
+{
+
+ try {
+ options_description desc;
+ variables_map vm;
+ func(desc, vm);
+ }
+ catch (EXCEPTION& e)
+ {
+ CHECK_EQUAL(test_name, e.what(), exception_txt);
+ return;
+ }
+ catch (std::exception& e)
+ {
+ BOOST_ERROR(string(test_name + ":\nUnexpected exception. ") + e.what() +
+ "\nExpected text:\n" + exception_txt + "\n\n");
+ return;
+ }
+ BOOST_ERROR(test_name + ": No exception thrown. ");
+}
+
+
+
+//________________________________________________________________________________________
+//
+// check_reading_file
+//
+//________________________________________________________________________________________
+void check_reading_file(options_description& desc, variables_map& vm)
+{
+ desc.add_options()
+ ("output,o", value<string>(), "the output file");
+
+ const char* file_name = "no_such_file";
+ store(parse_config_file<char>(file_name, desc, true), vm);
+
+}
+
+
+//________________________________________________________________________________________
+//
+// config_file_wildcard
+//
+//________________________________________________________________________________________
+void config_file_wildcard(options_description& desc, variables_map& vm)
+{
+ desc.add_options()
+ ("outpu*", value<string>(), "the output file1")
+ ("outp*", value<string>(), "the output file2")
+ ;
+ istringstream is("output1=whichone\noutput2=whichone\n");
+ store(parse_config_file(is, desc), vm);
+}
+
+//________________________________________________________________________________________
+//
+// invalid_syntax::unrecognized_line
+//
+//________________________________________________________________________________________
+void unrecognized_line(options_description& desc, variables_map& vm)
+{
+ istringstream is("funny wierd line\n");
+ store(parse_config_file(is, desc), vm);
+}
+
+//________________________________________________________________________________________
+//
+// abbreviated_options_in_config_file
+//
+//________________________________________________________________________________________
+void abbreviated_options_in_config_file(options_description& desc, variables_map& vm)
+{
+ desc.add_options()(",o", value<string>(), "the output file");
+ istringstream is("o=output.txt\n");
+ store(parse_config_file(is, desc), vm);
+}
+
+
+//________________________________________________________________________________________
+//
+// too_many_positional_options
+//
+//________________________________________________________________________________________
+void too_many_positional_options(options_description& desc, variables_map& vm)
+{
+ const char* argv[] = {"program", "1", "2", "3"};
+ positional_options_description positional_args;
+ positional_args.add("two_positional_arguments", 2);
+ store(command_line_parser(4, argv).options(desc).positional(positional_args).run(), vm);
+}
+
+
+//________________________________________________________________________________________
+//
+// invalid_command_line_style
+//
+//________________________________________________________________________________________
+
+void test_invalid_command_line_style_exception_msg()
+{
+ string test_name = "invalid_command_line_style";
+ using namespace command_line_style;
+ options_description desc;
+ desc.add_options()("output,o", value<string>(), "the output file");
+
+ vector<int> invalid_styles;
+ invalid_styles.push_back(allow_short | short_allow_adjacent);
+ invalid_styles.push_back(allow_short | allow_dash_for_short);
+ invalid_styles.push_back(allow_long);
+ vector<string> invalid_diagnostics;
+ invalid_diagnostics.push_back("boost::program_options misconfiguration: choose one "
+ "or other of 'command_line_style::allow_slash_for_short' "
+ "(slashes) or 'command_line_style::allow_dash_for_short' "
+ "(dashes) for short options.");
+ invalid_diagnostics.push_back("boost::program_options misconfiguration: choose one "
+ "or other of 'command_line_style::short_allow_next' "
+ "(whitespace separated arguments) or "
+ "'command_line_style::short_allow_adjacent' ('=' "
+ "separated arguments) for short options.");
+ invalid_diagnostics.push_back("boost::program_options misconfiguration: choose one "
+ "or other of 'command_line_style::long_allow_next' "
+ "(whitespace separated arguments) or "
+ "'command_line_style::long_allow_adjacent' ('=' "
+ "separated arguments) for long options.");
+
+
+ const char* argv[] = {"program"};
+ variables_map vm;
+ for (unsigned ii = 0; ii < 3; ++ii)
+ {
+ bool exception_thrown = false;
+ try
+ {
+ store(parse_command_line(1, argv, desc, invalid_styles[ii]), vm);
+ }
+ catch (invalid_command_line_style& e)
+ {
+ string error_msg("arguments are not allowed for unabbreviated option names");
+ CHECK_EQUAL(test_name, e.what(), invalid_diagnostics[ii]);
+ exception_thrown = true;
+ }
+ catch (std::exception& e)
+ {
+ BOOST_ERROR(string(test_name + ":\nUnexpected exception. ") + e.what() +
+ "\nExpected text:\n" + invalid_diagnostics[ii] + "\n");
+ exception_thrown = true;
+ }
+ if (!exception_thrown)
+ {
+ BOOST_ERROR(test_name << ": No exception thrown. ");
+ }
+ }
+}
+
+void test_empty_value_inner(options_description &opts, variables_map& vm) {
+ positional_options_description popts;
+ opts.add_options()("foo", value<uint32_t>()->value_name("<time>")->required());
+ popts.add("foo", 1);
+ vector<string> tokens(1, "");
+ parsed_options parsed = command_line_parser(tokens)
+ .style(command_line_style::default_style & ~command_line_style::allow_guessing)
+ .options(opts)
+ .positional(popts)
+ .run();
+ store(parsed, vm);
+}
+
+void test_empty_value() {
+ // Test that passing empty token for an option that requires integer does not result
+ // in out-of-range error in error reporting code.
+ test_exception<invalid_option_value>(
+ "test_empty_value",
+ "the argument for option '--foo' is invalid",
+ test_empty_value_inner);
+}
+
+int main(int /*ac*/, char** /*av*/)
+{
+ test_ambiguous_option_exception_msg();
+ test_unknown_option_exception_msg();
+ test_multiple_occurrences_exception_msg();
+ test_missing_value_exception_msg();
+ test_invalid_option_value_exception_msg();
+ test_invalid_bool_value_exception_msg();
+ test_multiple_values_not_allowed_exception_msg();
+ test_required_option_exception_msg();
+ test_at_least_one_value_required_exception_msg();
+ test_empty_value();
+
+ string test_name;
+ string expected_message;
+
+
+ // check_reading_file
+ test_name = "check_reading_file";
+ expected_message = "can not read options configuration file 'no_such_file'";
+ test_exception<reading_file>(test_name, expected_message, check_reading_file);
+
+ // config_file_wildcard
+ test_name = "config_file_wildcard";
+ expected_message = "options 'outpu*' and 'outp*' will both match the same arguments from the configuration file";
+ test_exception<error>(test_name, expected_message, config_file_wildcard);
+
+ // unrecognized_line
+ test_name = "unrecognized_line";
+ expected_message = "the options configuration file contains an invalid line 'funny wierd line'";
+ test_exception<invalid_syntax>(test_name, expected_message, unrecognized_line);
+
+
+ // abbreviated_options_in_config_file
+ test_name = "abbreviated_options_in_config_file";
+ expected_message = "abbreviated option names are not permitted in options configuration files";
+ test_exception<error>(test_name, expected_message, abbreviated_options_in_config_file);
+
+ test_name = "too_many_positional_options";
+ expected_message = "too many positional options have been specified on the command line";
+ test_exception<too_many_positional_options_error>(
+ test_name, expected_message, too_many_positional_options);
+
+ test_invalid_command_line_style_exception_msg();
+
+
+ return 0;
+}
+
diff --git a/src/boost/libs/program_options/test/minitest.hpp b/src/boost/libs/program_options/test/minitest.hpp
new file mode 100644
index 000000000..7d38efd2b
--- /dev/null
+++ b/src/boost/libs/program_options/test/minitest.hpp
@@ -0,0 +1,25 @@
+#ifndef BOOST_PROGRAM_OPTIONS_MINITEST
+#define BOOST_PROGRAM_OPTIONS_MINITEST
+
+#include <assert.h>
+#include <iostream>
+#include <stdlib.h>
+
+#define BOOST_REQUIRE(b) assert(b)
+#define BOOST_CHECK(b) assert(b)
+#define BOOST_CHECK_EQUAL(a, b) assert(a == b)
+#define BOOST_ERROR(description) std::cerr << description; std::cerr << "\n"; abort();
+#define BOOST_CHECK_THROW(expression, exception) \
+ try \
+ { \
+ expression; \
+ BOOST_ERROR("expected exception not thrown");\
+ throw 10; \
+ } \
+ catch(exception &) \
+ { \
+ }
+
+
+
+#endif
diff --git a/src/boost/libs/program_options/test/optional_test.cpp b/src/boost/libs/program_options/test/optional_test.cpp
new file mode 100644
index 000000000..b38308e58
--- /dev/null
+++ b/src/boost/libs/program_options/test/optional_test.cpp
@@ -0,0 +1,53 @@
+// 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 <boost/program_options.hpp>
+namespace po = boost::program_options;
+
+#include <boost/optional.hpp>
+
+#include <string>
+
+#include "minitest.hpp"
+
+std::vector<std::string> sv(const char* array[], unsigned size)
+{
+ std::vector<std::string> r;
+ for (unsigned i = 0; i < size; ++i)
+ r.push_back(array[i]);
+ return r;
+}
+
+void test_optional()
+{
+ boost::optional<int> foo, bar, baz;
+
+ po::options_description desc;
+ desc.add_options()
+ ("foo,f", po::value(&foo), "")
+ ("bar,b", po::value(&bar), "")
+ ("baz,z", po::value(&baz), "")
+ ;
+
+ const char* cmdline1_[] = { "--foo=12", "--bar", "1"};
+ std::vector<std::string> cmdline1 = sv(cmdline1_,
+ sizeof(cmdline1_)/sizeof(const char*));
+ po::variables_map vm;
+ po::store(po::command_line_parser(cmdline1).options(desc).run(), vm);
+ po::notify(vm);
+
+ BOOST_REQUIRE(!!foo);
+ BOOST_CHECK(*foo == 12);
+
+ BOOST_REQUIRE(!!bar);
+ BOOST_CHECK(*bar == 1);
+
+ BOOST_CHECK(!baz);
+}
+
+int main(int, char*[])
+{
+ test_optional();
+ return 0;
+}
diff --git a/src/boost/libs/program_options/test/options_description_test.cpp b/src/boost/libs/program_options/test/options_description_test.cpp
new file mode 100644
index 000000000..d0df7ef39
--- /dev/null
+++ b/src/boost/libs/program_options/test/options_description_test.cpp
@@ -0,0 +1,347 @@
+// 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 <boost/program_options/options_description.hpp>
+using namespace boost::program_options;
+
+#include <boost/function.hpp>
+using namespace boost;
+
+#include <utility>
+#include <string>
+#include <sstream>
+using namespace std;
+
+#include "minitest.hpp"
+
+void test_type()
+{
+ options_description desc;
+ desc.add_options()
+ ("foo", value<int>(), "")
+ ("bar", value<string>(), "")
+ ;
+
+#ifndef BOOST_NO_RTTI
+ 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(string));
+#endif
+}
+
+void test_approximation()
+{
+ options_description desc;
+ desc.add_options()
+ ("foo", new untyped_value())
+ ("fee", new untyped_value())
+ ("baz", new untyped_value())
+ ("all-chroots", new untyped_value())
+ ("all-sessions", new untyped_value())
+ ("all", 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");
+
+ options_description desc2;
+ desc2.add_options()
+ ("help", "display this message")
+ ("config", value<string>(), "config file name")
+ ("config-value", value<string>(), "single config value")
+ ;
+
+ BOOST_CHECK_EQUAL(desc2.find("config", true).long_name(), "config");
+ BOOST_CHECK_EQUAL(desc2.find("config-value", true).long_name(),
+ "config-value");
+
+
+// BOOST_CHECK(desc.count_approx("foo") == 1);
+// set<string> a = desc.approximations("f");
+// BOOST_CHECK(a.size() == 2);
+// BOOST_CHECK(*a.begin() == "fee");
+// BOOST_CHECK(*(++a.begin()) == "foo");
+}
+
+void test_approximation_with_multiname_options()
+{
+ options_description desc;
+ desc.add_options()
+ ("foo", new untyped_value())
+ ("fee", new untyped_value())
+ ("fe,baz", new untyped_value())
+ ("chroots,all-chroots", new untyped_value())
+ ("sessions,all-sessions", new untyped_value())
+ ("everything,all", new untyped_value())
+ ("qux,fo", new untyped_value())
+ ;
+
+ BOOST_CHECK_EQUAL(desc.find("fo", true).long_name(), "qux");
+
+ BOOST_CHECK_EQUAL(desc.find("all", true).long_name(), "everything");
+ BOOST_CHECK_EQUAL(desc.find("all-ch", true).long_name(), "chroots");
+
+ BOOST_CHECK_EQUAL(desc.find("foo", false, false, false).long_names().second, 1u);
+ BOOST_CHECK_EQUAL(desc.find("foo", false, false, false).long_names().first[0], "foo");
+
+ BOOST_CHECK_EQUAL(desc.find("fe", false, false, false).long_names().second, 2u);
+ BOOST_CHECK_EQUAL(desc.find("fe", false, false, false).long_names().first[0], "fe");
+ BOOST_CHECK_EQUAL(desc.find("baz", false, false, false).long_names().first[1], "baz");
+
+ BOOST_CHECK_EQUAL(desc.find("baz", false, false, false).long_names().second, 2u);
+ BOOST_CHECK_EQUAL(desc.find("baz", false, false, false).long_names().first[0], "fizbaz");
+ BOOST_CHECK_EQUAL(desc.find("baz", false, false, false).long_names().first[1], "baz");
+}
+
+void test_long_names_for_option_description()
+{
+ options_description desc;
+ desc.add_options()
+ ("foo", new untyped_value())
+ ("fe,baz", new untyped_value())
+ ("chroots,all-chroots", new untyped_value())
+ ("sessions,all-sessions", new untyped_value())
+ ("everything,all", new untyped_value())
+ ("qux,fo,q", new untyped_value())
+ ;
+
+ BOOST_CHECK_EQUAL(desc.find("foo", false, false, false).long_names().second, 1u);
+ BOOST_CHECK_EQUAL(desc.find("foo", false, false, false).long_names().first[0], "foo");
+
+ BOOST_CHECK_EQUAL(desc.find("fe", false, false, false).long_names().second, 2u);
+ BOOST_CHECK_EQUAL(desc.find("fe", false, false, false).long_names().first[0], "fe");
+ BOOST_CHECK_EQUAL(desc.find("baz", false, false, false).long_names().first[1], "baz");
+
+ BOOST_CHECK_EQUAL(desc.find("qux", false, false, false).long_names().second, 2u);
+ BOOST_CHECK_EQUAL(desc.find("qux", false, false, false).long_names().first[0], "qux");
+ BOOST_CHECK_EQUAL(desc.find("qux", false, false, false).long_names().first[1], "fo");
+}
+
+
+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")
+ ("list", new untyped_value(),
+ "a list:\n \t"
+ "item1, item2, item3, item4, item5, item6, item7, item8, item9, "
+ "item10, item11, item12, item13, item14, item15, item16, item17, item18")
+ ("well_formated", new untyped_value(),
+ "As you can see this is a very well formatted option description.\n"
+ "You can do this for example:\n\n"
+ "Values:\n"
+ " Value1: \tdoes this and that, bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla\n"
+ " Value2: \tdoes something else, bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla\n\n"
+ " This paragraph has a first line indent only, bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla")
+ ;
+
+ stringstream ss;
+ ss << desc;
+ BOOST_CHECK_EQUAL(ss.str(),
+" --test arg foo foo foo foo foo foo foo foo foo foo foo foo foo \n"
+" foofoo foo foo foo foo foo foo foo foo foo foo foo foo \n"
+" foofoo foo foo foo foo foo foo foo foo foo foo foo foo \n"
+" foofoo foo foo foo foo foo foo foo foo foo foo foo foo \n"
+" foo\n"
+" --list arg a list:\n"
+" item1, item2, item3, item4, item5, item6, item7, \n"
+" item8, item9, item10, item11, item12, item13, \n"
+" item14, item15, item16, item17, item18\n"
+" --well_formated arg As you can see this is a very well formatted option \n"
+" description.\n"
+" You can do this for example:\n"
+" \n"
+" Values:\n"
+" Value1: does this and that, bla bla bla bla bla bla \n"
+" bla bla bla bla bla bla bla bla bla\n"
+" Value2: does something else, bla bla bla bla bla bla \n"
+" bla bla bla bla bla bla bla bla bla\n"
+" \n"
+" This paragraph has a first line indent only, bla \n"
+" bla bla bla bla bla bla bla bla bla bla bla bla bla bla\n"
+ );
+}
+
+void test_multiname_option_formatting()
+{
+ options_description desc;
+ desc.add_options()
+ ("foo,bar", new untyped_value(), "a multiple-name option")
+ ;
+
+ stringstream ss;
+ ss << desc;
+ BOOST_CHECK_EQUAL(ss.str(),
+" --foo arg a multiple-name option\n"
+ );
+}
+
+
+void test_formatting_description_length()
+{
+ {
+ options_description desc("",
+ options_description::m_default_line_length,
+ options_description::m_default_line_length / 2U);
+ desc.add_options()
+ ("an-option-that-sets-the-max", new untyped_value(), // > 40 available for desc
+ "this description sits on the same line, but wrapping should still work correctly")
+ ("a-long-option-that-would-leave-very-little-space-for-description", new untyped_value(),
+ "the description of the long opt, but placed on the next line\n"
+ " \talso ensure that the tabulation works correctly when a"
+ " description size has been set");
+
+ stringstream ss;
+ ss << desc;
+ BOOST_CHECK_EQUAL(ss.str(),
+ " --an-option-that-sets-the-max arg this description sits on the same line,\n"
+ " but wrapping should still work \n"
+ " correctly\n"
+ " --a-long-option-that-would-leave-very-little-space-for-description arg\n"
+ " the description of the long opt, but \n"
+ " placed on the next line\n"
+ " also ensure that the tabulation \n"
+ " works correctly when a description \n"
+ " size has been set\n");
+ }
+ {
+ // the default behaviour reserves 23 (+1 space) characters for the
+ // option column; this shows that the min_description_length does not
+ // breach that.
+ options_description desc("",
+ options_description::m_default_line_length,
+ options_description::m_default_line_length - 10U); // leaves < 23 (default option space)
+ desc.add_options()
+ ("an-option-that-encroaches-description", new untyped_value(),
+ "this description should always be placed on the next line, and wrapping should continue as normal");
+
+ stringstream ss;
+ ss << desc;
+ BOOST_CHECK_EQUAL(ss.str(),
+ " --an-option-that-encroaches-description arg\n"
+ //123456789_123456789_
+ " this description should always be placed on the next line, and \n"
+ " wrapping should continue as normal\n");
+ }
+}
+
+void test_long_default_value()
+{
+ options_description desc;
+ desc.add_options()
+ ("cfgfile,c",
+ value<string>()->default_value("/usr/local/etc/myprogramXXXXXXXXX/configuration.conf"),
+ "the configfile")
+ ;
+
+ stringstream ss;
+ ss << desc;
+ BOOST_CHECK_EQUAL(ss.str(),
+" -c [ --cfgfile ] arg (=/usr/local/etc/myprogramXXXXXXXXX/configuration.conf)\n"
+" the configfile\n"
+ );
+}
+
+void test_word_wrapping()
+{
+ options_description desc("Supported options");
+ desc.add_options()
+ ("help", "this is a sufficiently long text to require word-wrapping")
+ ("prefix", value<string>()->default_value("/h/proj/tmp/dispatch"), "root path of the dispatch installation")
+ ("opt1", "this_is_a_sufficiently_long_text_to_require_word-wrapping_but_cannot_be_wrapped")
+ ("opt2", "this_is_a_sufficiently long_text_to_require_word-wrapping")
+ ("opt3", "this_is_a sufficiently_long_text_to_require_word-wrapping_but_will_not_be_wrapped")
+ ;
+ stringstream ss;
+ ss << desc;
+ BOOST_CHECK_EQUAL(ss.str(),
+"Supported options:\n"
+" --help this is a sufficiently long text to \n"
+" require word-wrapping\n"
+" --prefix arg (=/h/proj/tmp/dispatch) root path of the dispatch installation\n"
+" --opt1 this_is_a_sufficiently_long_text_to_requ\n"
+" ire_word-wrapping_but_cannot_be_wrapped\n"
+" --opt2 this_is_a_sufficiently \n"
+" long_text_to_require_word-wrapping\n"
+" --opt3 this_is_a sufficiently_long_text_to_requ\n"
+" ire_word-wrapping_but_will_not_be_wrappe\n"
+" d\n"
+ );
+}
+
+void test_default_values()
+{
+ options_description desc("Supported options");
+ desc.add_options()
+ ("maxlength", value<double>()->default_value(.1, "0.1"), "Maximum edge length to keep.")
+ ;
+ stringstream ss;
+ ss << desc;
+ BOOST_CHECK_EQUAL(ss.str(),
+"Supported options:\n"
+" --maxlength arg (=0.1) Maximum edge length to keep.\n"
+ );
+}
+
+void test_value_name()
+{
+ options_description desc("Supported options");
+ desc.add_options()
+ ("include", value<string>()->value_name("directory"), "Search for headers in 'directory'.")
+ ;
+
+ stringstream ss;
+ ss << desc;
+ BOOST_CHECK_EQUAL(ss.str(),
+"Supported options:\n"
+" --include directory Search for headers in 'directory'.\n"
+ );
+}
+
+void test_multiname_key_and_switch_selection()
+{
+ // cases:
+ // foo,f -> f
+ // foo, c -> c
+ // foo,f,g -> g
+ // f,g,h -> h
+ // f,foo throws
+ // foo,bar -> no switch
+ // foo,f,bar -> no switch
+
+ // what about empty strings - consecutive ,'s ?
+}
+
+int main(int, char* [])
+{
+ test_type();
+ test_approximation();
+ test_long_names_for_option_description();
+ test_formatting();
+ test_multiname_key_and_switch_selection();
+ test_multiname_option_formatting();
+ test_formatting_description_length();
+ test_long_default_value();
+ test_word_wrapping();
+ test_default_values();
+ test_value_name();
+ return 0;
+}
+
diff --git a/src/boost/libs/program_options/test/parsers_test.cpp b/src/boost/libs/program_options/test/parsers_test.cpp
new file mode 100644
index 000000000..4cf832ee7
--- /dev/null
+++ b/src/boost/libs/program_options/test/parsers_test.cpp
@@ -0,0 +1,388 @@
+// 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 <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;
+
+#include <boost/function.hpp>
+using namespace boost;
+
+#include <sstream>
+#include <iostream>
+#include <iomanip>
+using namespace std;
+
+#if defined(__sun)
+#include <stdlib.h> // for putenv on solaris
+#else
+#include <cstdlib> // for putenv
+#endif
+
+#include "minitest.hpp"
+
+#define TEST_CHECK_THROW(expression, exception, description) \
+ try \
+ { \
+ expression; \
+ BOOST_ERROR(description);\
+ throw 10; \
+ } \
+ catch(exception &) \
+ { \
+ }
+
+pair<string, vector< vector<string> > > msp(const string& s1)
+{
+ return std::make_pair(s1, vector< vector<string> >());
+}
+
+
+pair<string, vector< vector<string> > > msp(const string& s1, const string& s2)
+{
+ vector< vector<string> > v(1);
+ v[0].push_back(s2);
+ return std::make_pair(s1, v);
+}
+
+void check_value(const option& option, const char* name, const char* value)
+{
+ BOOST_CHECK(option.string_key == name);
+ BOOST_REQUIRE(option.value.size() == 1);
+ BOOST_CHECK(option.value.front() == value);
+}
+
+vector<string> sv(const char* array[], unsigned size)
+{
+ vector<string> r;
+ for (unsigned i = 0; i < size; ++i)
+ r.push_back(array[i]);
+ return r;
+}
+
+pair<string, string> additional_parser(const std::string&)
+{
+ return pair<string, string>();
+}
+
+namespace command_line {
+
+#if 0
+// The following commented out blocks used to test parsing
+// command line without syntax specification behaviour.
+// It is disabled now and probably will never be enabled again:
+// it is not possible to figure out what command line means without
+// user's help.
+void test_parsing_without_specifying_options() {
+ char* cmdline1[] = { "--a", "--b=12", "-f", "-g4", "-", "file" };
+ options_and_arguments a1 = parse_command_line(cmdline1,
+ cmdline1 + sizeof(cmdline1) / sizeof(cmdline1[0]));
+ BOOST_REQUIRE(a1.options().size() == 4);
+ BOOST_CHECK(a1.options()[0] == msp("a", ""));
+ BOOST_CHECK(a1.options()[1] == msp("b", "12"));
+ BOOST_CHECK(a1.options()[2] == msp("-f", ""));
+ BOOST_CHECK(a1.options()[3] == msp("-g", "4"));
+ BOOST_REQUIRE(a1.arguments().size() == 2);
+ BOOST_CHECK(a1.arguments()[0] == "-");
+ BOOST_CHECK(a1.arguments()[1] == "file");
+ char* cmdline2[] = { "--a", "--", "file" };
+ options_and_arguments a2 = parse_command_line(cmdline2,
+ cmdline2 + sizeof(cmdline2) / sizeof(cmdline2[0]));
+ BOOST_REQUIRE(a2.options().size() == 1);
+ BOOST_CHECK(a2.options()[0] == msp("a", ""));
+ BOOST_CHECK(a2.arguments().size() == 1);
+ BOOST_CHECK(a2.arguments()[0] == "file");
+}
+#endif
+
+void test_many_different_options() {
+ options_description desc;
+ desc.add_options()
+ ("foo,f", new untyped_value(), "")
+ ( // Explicit qualification is a workaround for vc6
+ "bar,b", po::value<std::string>(), "")
+ ("car,voiture", new untyped_value())
+ ("dog,dawg", new untyped_value())
+ ("baz", new untyped_value())
+ ("plug*", new untyped_value());
+ const char* cmdline3_[] = { "--foo=12", "-f4", "--bar=11", "-b4",
+ "--voiture=15", "--dawg=16", "--dog=17", "--plug3=10" };
+ vector<string> cmdline3 = sv(cmdline3_,
+ sizeof(cmdline3_) / sizeof(const char*));
+ vector<option> a3 =
+ command_line_parser(cmdline3).options(desc).run().options;
+ BOOST_CHECK_EQUAL(a3.size(), 8u);
+ check_value(a3[0], "foo", "12");
+ check_value(a3[1], "foo", "4");
+ check_value(a3[2], "bar", "11");
+ check_value(a3[3], "bar", "4");
+ check_value(a3[4], "car", "15");
+ check_value(a3[5], "dog", "16");
+ check_value(a3[6], "dog", "17");
+ check_value(a3[7], "plug3", "10");
+
+ // Regression test: check that '0' as style is interpreted as
+ // 'default_style'
+ vector<option> a4 = parse_command_line(
+ sizeof(cmdline3_) / sizeof(const char*), cmdline3_, desc, 0,
+ additional_parser).options;
+ // The default style is unix-style, where the first argument on the command-line
+ // is the name of a binary, not an option value, so that should be ignored
+ BOOST_CHECK_EQUAL(a4.size(), 7u);
+ check_value(a4[0], "foo", "4");
+ check_value(a4[1], "bar", "11");
+ check_value(a4[2], "bar", "4");
+ check_value(a4[3], "car", "15");
+ check_value(a4[4], "dog", "16");
+ check_value(a4[5], "dog", "17");
+ check_value(a4[6], "plug3", "10");
+}
+
+void test_not_crashing_with_empty_string_values() {
+ // Check that we don't crash on empty values of type 'string'
+ const char* cmdline4[] = { "", "--open", "" };
+ options_description desc2;
+ desc2.add_options()("open", po::value<string>());
+ variables_map vm;
+ po::store(
+ po::parse_command_line(sizeof(cmdline4) / sizeof(const char*),
+ const_cast<char**>(cmdline4), desc2), vm);
+}
+
+void test_multitoken() {
+ const 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(
+ sizeof(cmdline5) / sizeof(const char*),
+ const_cast<char**>(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");
+}
+
+void test_multitoken_and_multiname() {
+ const char* cmdline[] = { "program", "-fone", "-b", "two", "--foo", "three", "four", "-zfive", "--fee", "six" };
+ options_description desc;
+ desc.add_options()
+ ("bar,b", po::value<string>())
+ ("foo,fee,f", po::value<string>()->multitoken())
+ ("fizbaz,baz,z", po::value<string>());
+
+ vector<option> parsed_options = parse_command_line(
+ sizeof(cmdline) / sizeof(const char*),
+ const_cast<char**>(cmdline), desc, 0, additional_parser).options;
+
+ BOOST_CHECK_EQUAL(parsed_options.size(), 5u);
+ check_value(parsed_options[0], "foo", "one");
+ check_value(parsed_options[1], "bar", "two");
+ BOOST_CHECK_EQUAL(parsed_options[2].string_key, "foo");
+ BOOST_REQUIRE(parsed_options[2].value.size() == 2);
+ BOOST_CHECK_EQUAL(parsed_options[2].value[0], "three");
+ BOOST_CHECK_EQUAL(parsed_options[2].value[1], "four");
+ check_value(parsed_options[3], "fizbaz", "five");
+ check_value(parsed_options[4], "foo", "six");
+
+ const char* cmdline_2[] = { "program", "-fone", "-b", "two", "--fee", "three", "four", "-zfive", "--foo", "six" };
+
+ parsed_options = parse_command_line(
+ sizeof(cmdline_2) / sizeof(const char*),
+ const_cast<char**>(cmdline_2), desc, 0, additional_parser).options;
+
+ BOOST_CHECK_EQUAL(parsed_options.size(), 5u);
+ check_value(parsed_options[0], "foo", "one");
+ check_value(parsed_options[1], "bar", "two");
+ BOOST_CHECK_EQUAL(parsed_options[2].string_key, "foo");
+ BOOST_REQUIRE(parsed_options[2].value.size() == 2);
+ BOOST_CHECK_EQUAL(parsed_options[2].value[0], "three");
+ BOOST_CHECK_EQUAL(parsed_options[2].value[1], "four");
+ check_value(parsed_options[3], "fizbaz", "five");
+ check_value(parsed_options[4], "foo", "six");
+}
+
+
+void test_multitoken_vector_option() {
+ po::options_description desc4("");
+ desc4.add_options()
+ ("multitoken,multi-token,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);
+ const char* cmdline6[] = { "", "-m", "token1", "token2", "--", "some_file" };
+ vector<option> a6 =
+ command_line_parser(sizeof(cmdline6) / sizeof(const char*),
+ const_cast<char**>(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");
+}
+
+} // namespace command_line
+
+void test_command_line()
+{
+ #if 0
+ command_line::test_parsing_without_specifying_options();
+ #endif
+ command_line::test_many_different_options();
+ // Check that we don't crash on empty values of type 'string'
+ command_line::test_not_crashing_with_empty_string_values();
+ command_line::test_multitoken();
+ command_line::test_multitoken_vector_option();
+ command_line::test_multitoken_and_multiname();
+}
+
+void test_config_file(const char* config_file)
+{
+ options_description desc;
+ desc.add_options()
+ ("gv1", new untyped_value)
+ ("gv2", new untyped_value)
+ ("empty_value", new untyped_value)
+ ("plug*", new untyped_value)
+ ("m1.v1", new untyped_value)
+ ("m1.v2", new untyped_value)
+ ("m1.v3,alias3", new untyped_value)
+ ("b", bool_switch())
+ ;
+
+ const char content1[] =
+ " gv1 = 0#asd\n"
+ "empty_value = \n"
+ "plug3 = 7\n"
+ "b = true\n"
+ "[m1]\n"
+ "v1 = 1\n"
+ "\n"
+ "v2 = 2\n"
+ "v3 = 3\n"
+ ;
+
+ stringstream ss(content1);
+ vector<option> a1 = parse_config_file(ss, desc).options;
+ BOOST_REQUIRE(a1.size() == 7);
+ check_value(a1[0], "gv1", "0");
+ check_value(a1[1], "empty_value", "");
+ check_value(a1[2], "plug3", "7");
+ check_value(a1[3], "b", "true");
+ check_value(a1[4], "m1.v1", "1");
+ check_value(a1[5], "m1.v2", "2");
+ check_value(a1[6], "m1.v3", "3");
+
+ // same test, but now options come from file
+ vector<option> a2 = parse_config_file<char>(config_file, desc).options;
+ BOOST_REQUIRE(a2.size() == 7);
+ check_value(a2[0], "gv1", "0");
+ check_value(a2[1], "empty_value", "");
+ check_value(a2[2], "plug3", "7");
+ check_value(a2[3], "b", "true");
+ check_value(a2[4], "m1.v1", "1");
+ check_value(a2[5], "m1.v2", "2");
+ check_value(a2[6], "m1.v3", "3");
+}
+
+void test_environment()
+{
+ options_description desc;
+ desc.add_options()
+ ("foo", new untyped_value, "")
+ ("bar", new untyped_value, "")
+ ;
+
+#if (defined(_WIN32) && ! defined(__BORLANDC__)) || (defined(__CYGWIN__))
+ _putenv("PO_TEST_FOO=1");
+#else
+ putenv(const_cast<char*>("PO_TEST_FOO=1"));
+#endif
+ parsed_options p = parse_environment(desc, "PO_TEST_");
+
+ BOOST_REQUIRE(p.options.size() == 1);
+ BOOST_CHECK (p.options[0].string_key == "foo");
+ BOOST_REQUIRE(p.options[0].value.size() == 1);
+ BOOST_CHECK (p.options[0].value[0] == "1");
+
+ //TODO: since 'bar' does not allow a value, it cannot appear in environemt,
+ // which already has a value.
+}
+
+void test_unregistered()
+{
+ options_description desc;
+
+ const char* cmdline1_[] = { "--foo=12", "--bar", "1"};
+ vector<string> cmdline1 = sv(cmdline1_,
+ sizeof(cmdline1_)/sizeof(const char*));
+ vector<option> a1 =
+ command_line_parser(cmdline1).options(desc).allow_unregistered().run()
+ .options;
+
+ BOOST_REQUIRE(a1.size() == 3);
+ BOOST_CHECK(a1[0].string_key == "foo");
+ BOOST_CHECK(a1[0].unregistered == true);
+ BOOST_REQUIRE(a1[0].value.size() == 1);
+ BOOST_CHECK(a1[0].value[0] == "12");
+ BOOST_CHECK(a1[1].string_key == "bar");
+ BOOST_CHECK(a1[1].unregistered == true);
+ BOOST_CHECK(a1[2].string_key == "");
+ BOOST_CHECK(a1[2].unregistered == false);
+
+
+ vector<string> a2 = collect_unrecognized(a1, include_positional);
+ BOOST_CHECK(a2[0] == "--foo=12");
+ 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);
+
+
+ const char content1[] =
+ "gv1 = 0\n"
+ "[m1]\n"
+ "v1 = 1\n"
+ ;
+
+ stringstream ss(content1);
+ vector<option> a3 = parse_config_file(ss, desc, true).options;
+ BOOST_REQUIRE(a3.size() == 2);
+ cout << "XXX" << a3[0].value.front() << "\n";
+ check_value(a3[0], "gv1", "0");
+ check_value(a3[1], "m1.v1", "1");
+}
+
+
+
+int main(int, char* av[])
+{
+ test_command_line();
+ test_config_file(av[1]);
+ test_environment();
+ test_unregistered();
+ return 0;
+}
+
diff --git a/src/boost/libs/program_options/test/positional_options_test.cpp b/src/boost/libs/program_options/test/positional_options_test.cpp
new file mode 100644
index 000000000..2c1dfd66c
--- /dev/null
+++ b/src/boost/libs/program_options/test/positional_options_test.cpp
@@ -0,0 +1,91 @@
+// Copyright Vladimir Prus 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 <boost/program_options/positional_options.hpp>
+#include <boost/program_options/options_description.hpp>
+#include <boost/program_options/parsers.hpp>
+using namespace boost::program_options;
+// We'll use po::value everywhere to workaround vc6 bug.
+namespace po = boost::program_options;
+
+
+#include <boost/limits.hpp>
+
+#include "minitest.hpp"
+
+#include <vector>
+using namespace std;
+
+void test_positional_options()
+{
+ positional_options_description p;
+ p.add("first", 1);
+
+ BOOST_CHECK_EQUAL(p.max_total_count(), 1u);
+ BOOST_CHECK_EQUAL(p.name_for_position(0), "first");
+
+ p.add("second", 2);
+
+ BOOST_CHECK_EQUAL(p.max_total_count(), 3u);
+ BOOST_CHECK_EQUAL(p.name_for_position(0), "first");
+ BOOST_CHECK_EQUAL(p.name_for_position(1), "second");
+ BOOST_CHECK_EQUAL(p.name_for_position(2), "second");
+
+ p.add("third", -1);
+
+ BOOST_CHECK_EQUAL(p.max_total_count(), (std::numeric_limits<unsigned>::max)());
+ BOOST_CHECK_EQUAL(p.name_for_position(0), "first");
+ BOOST_CHECK_EQUAL(p.name_for_position(1), "second");
+ BOOST_CHECK_EQUAL(p.name_for_position(2), "second");
+ BOOST_CHECK_EQUAL(p.name_for_position(3), "third");
+ BOOST_CHECK_EQUAL(p.name_for_position(10000), "third");
+}
+
+void test_parsing()
+{
+ options_description desc;
+ desc.add_options()
+ ("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);
+
+ 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_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");
+
+ // Check that excessive number of positional options is detected.
+ BOOST_CHECK_THROW(command_line_parser(args).options(desc).positional(p)
+ .run(),
+ too_many_positional_options_error);
+}
+
+int main(int, char* [])
+{
+ test_positional_options();
+ test_parsing();
+ return 0;
+}
+
diff --git a/src/boost/libs/program_options/test/program_options_size_test.py b/src/boost/libs/program_options/test/program_options_size_test.py
new file mode 100644
index 000000000..25ca2f740
--- /dev/null
+++ b/src/boost/libs/program_options/test/program_options_size_test.py
@@ -0,0 +1,53 @@
+#!/usr/bin/python
+
+import os
+import string
+
+
+call = " hook(10);\n";
+call = " hook(10); hook2(10);hook3(0);hook4(0);\n";
+
+def run_test(num_calls, compiler_command):
+ f = open("program_options_test.cpp", "w")
+ f.write("""#include <boost/program_options.hpp>
+using namespace boost::program_options;
+
+void do_it()
+{
+ boost::program_options::options_description desc;
+ desc.add_options()
+""")
+ for i in range(0, num_calls):
+ f.write("(\"opt%d\", value<int>())\n")
+ f.write(";\n}\n")
+ f.close()
+ os.system(compiler_command + " -c -save-temps -I /home/ghost/Work/Boost/boost-svn program_options_test.cpp")
+
+ nm = os.popen("nm -S program_options_test.o")
+ for l in nm:
+ if string.find(l, "Z5do_itv") != -1:
+ break
+ size = int(string.split(l)[1], 16)
+ return size
+
+def run_tests(range, compiler_command):
+
+ last_size = None
+ first_size = None
+ for num in range:
+ size = run_test(num, compiler_command)
+ if last_size:
+ print "%2d calls: %5d bytes (+ %d)" % (num, size, size-last_size)
+ else:
+ print "%2d calls: %5d bytes" % (num, size)
+ first_size = size
+ last_size = size
+ print "Avarage: ", (last_size-first_size)/(range[-1]-range[0])
+
+if __name__ == '__main__':
+ for compiler in [ "g++ -Os", "g++ -O3"]:
+ print "****", compiler, "****"
+ run_tests(range(1, 20), compiler)
+
+
+
diff --git a/src/boost/libs/program_options/test/quick.cpp b/src/boost/libs/program_options/test/quick.cpp
new file mode 100644
index 000000000..edf45c4a2
--- /dev/null
+++ b/src/boost/libs/program_options/test/quick.cpp
@@ -0,0 +1,49 @@
+
+// Copyright 2017 Peter Dimov.
+//
+// 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
+
+// See library home page at http://www.boost.org/libs/program_options
+
+#include <boost/program_options.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+namespace po = boost::program_options;
+
+int main( int argc, char const* argv[] )
+{
+ po::options_description desc( "Allowed options" );
+
+ desc.add_options()
+ ( "path,p", po::value<std::string>(), "set initial path" )
+ ;
+
+ po::variables_map vm;
+
+ try
+ {
+ po::store( po::parse_command_line( argc, argv, desc ), vm );
+ po::notify( vm );
+ }
+ catch( std::exception const & x )
+ {
+ std::cerr << "Error: " << x.what() << std::endl;
+ return 1;
+ }
+
+ std::string p;
+
+ if( vm.count( "path" ) )
+ {
+ p = vm[ "path" ].as<std::string>();
+ }
+
+ std::string expected( "initial" );
+
+ BOOST_TEST_EQ( p, expected );
+
+ return boost::report_errors();
+}
diff --git a/src/boost/libs/program_options/test/required_test.cfg b/src/boost/libs/program_options/test/required_test.cfg
new file mode 100644
index 000000000..4b25dd68e
--- /dev/null
+++ b/src/boost/libs/program_options/test/required_test.cfg
@@ -0,0 +1 @@
+cfgfile = file.cfg
diff --git a/src/boost/libs/program_options/test/required_test.cpp b/src/boost/libs/program_options/test/required_test.cpp
new file mode 100644
index 000000000..1c623cd5c
--- /dev/null
+++ b/src/boost/libs/program_options/test/required_test.cpp
@@ -0,0 +1,125 @@
+// Copyright Sascha Ochsenknecht 2009.
+// 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 <boost/program_options.hpp>
+using namespace boost::program_options;
+
+#include <string>
+#include <iostream>
+#include <fstream>
+using namespace std;
+
+#include "minitest.hpp"
+
+
+void required_throw_test()
+{
+ options_description opts;
+ opts.add_options()
+ ("cfgfile,c", value<string>()->required(), "the configfile")
+ ("fritz,f", value<string>()->required(), "the output file")
+ ;
+
+ variables_map vm;
+ bool thrown = false;
+ {
+ // This test must throw exception
+ string cmdline = "prg -f file.txt";
+ vector< string > tokens = split_unix(cmdline);
+ thrown = false;
+ try {
+ store(command_line_parser(tokens).options(opts).run(), vm);
+ notify(vm);
+ }
+ catch (required_option& e) {
+ BOOST_CHECK_EQUAL(e.what(), string("the option '--cfgfile' is required but missing"));
+ thrown = true;
+ }
+ BOOST_CHECK(thrown);
+ }
+
+ {
+ // This test mustn't throw exception
+ string cmdline = "prg -c config.txt";
+ vector< string > tokens = split_unix(cmdline);
+ thrown = false;
+ try {
+ store(command_line_parser(tokens).options(opts).run(), vm);
+ notify(vm);
+ }
+ catch (required_option& e) {
+ thrown = true;
+ }
+ BOOST_CHECK(!thrown);
+ }
+}
+
+
+
+void simple_required_test(const char* config_file)
+{
+ options_description opts;
+ opts.add_options()
+ ("cfgfile,c", value<string>()->required(), "the configfile")
+ ("fritz,f", value<string>()->required(), "the output file")
+ ;
+
+ variables_map vm;
+ bool thrown = false;
+ {
+ // This test must throw exception
+ string cmdline = "prg -f file.txt";
+ vector< string > tokens = split_unix(cmdline);
+ thrown = false;
+ try {
+ // options coming from different sources
+ store(command_line_parser(tokens).options(opts).run(), vm);
+ store(parse_config_file<char>(config_file, opts), vm);
+ notify(vm);
+ }
+ catch (required_option& e) {
+ thrown = true;
+ }
+ BOOST_CHECK(!thrown);
+ }
+}
+
+void multiname_required_test()
+{
+ options_description opts;
+ opts.add_options()
+ ("foo,bar", value<string>()->required(), "the foo")
+ ;
+
+ variables_map vm;
+ bool thrown = false;
+ {
+ // This test must throw exception
+ string cmdline = "prg --bar file.txt";
+ vector< string > tokens = split_unix(cmdline);
+ thrown = false;
+ try {
+ // options coming from different sources
+ store(command_line_parser(tokens).options(opts).run(), vm);
+ notify(vm);
+ }
+ catch (required_option& e) {
+ thrown = true;
+ }
+ BOOST_CHECK(!thrown);
+ }
+}
+
+
+
+int main(int /*argc*/, char* av[])
+{
+ required_throw_test();
+ simple_required_test(av[1]);
+ multiname_required_test();
+
+ return 0;
+}
+
diff --git a/src/boost/libs/program_options/test/split_test.cpp b/src/boost/libs/program_options/test/split_test.cpp
new file mode 100644
index 000000000..eecd09343
--- /dev/null
+++ b/src/boost/libs/program_options/test/split_test.cpp
@@ -0,0 +1,189 @@
+// Copyright Sascha Ochsenknecht 2009.
+// 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 <boost/program_options/parsers.hpp>
+#include <boost/program_options/options_description.hpp>
+#include <boost/program_options/variables_map.hpp>
+#include <boost/program_options/cmdline.hpp>
+using namespace boost::program_options;
+
+#include <iostream>
+#include <sstream>
+#include <vector>
+#include <cassert>
+using namespace std;
+
+#include "minitest.hpp"
+
+void check_value(const string& option, const string& value)
+{
+ BOOST_CHECK(option == value);
+}
+
+void split_whitespace(const options_description& description)
+{
+
+ const char* cmdline = "prg --input input.txt \r --optimization 4 \t --opt \n option";
+
+ vector< string > tokens = split_unix(cmdline, " \t\n\r");
+
+ BOOST_REQUIRE(tokens.size() == 7);
+
+ check_value(tokens[0], "prg");
+ check_value(tokens[1], "--input");
+ check_value(tokens[2], "input.txt");
+ check_value(tokens[3], "--optimization");
+ check_value(tokens[4], "4");
+ check_value(tokens[5], "--opt");
+ check_value(tokens[6], "option");
+
+ variables_map vm;
+ store(command_line_parser(tokens).options(description).run(), vm);
+ notify(vm);
+}
+
+void split_equalsign(const options_description& description)
+{
+
+ const char* cmdline = "prg --input=input.txt --optimization=4 --opt=option";
+
+ vector< string > tokens = split_unix(cmdline, "= ");
+
+ BOOST_REQUIRE(tokens.size() == 7);
+ check_value(tokens[0], "prg");
+ check_value(tokens[1], "--input");
+ check_value(tokens[2], "input.txt");
+ check_value(tokens[3], "--optimization");
+ check_value(tokens[4], "4");
+ check_value(tokens[5], "--opt");
+ check_value(tokens[6], "option");
+
+ variables_map vm;
+ store(command_line_parser(tokens).options(description).run(), vm);
+ notify(vm);
+}
+
+void split_semi(const options_description& description)
+{
+
+ const char* cmdline = "prg;--input input.txt;--optimization 4;--opt option";
+
+ vector< string > tokens = split_unix(cmdline, "; ");
+
+ BOOST_REQUIRE(tokens.size() == 7);
+ check_value(tokens[0], "prg");
+ check_value(tokens[1], "--input");
+ check_value(tokens[2], "input.txt");
+ check_value(tokens[3], "--optimization");
+ check_value(tokens[4], "4");
+ check_value(tokens[5], "--opt");
+ check_value(tokens[6], "option");
+
+ variables_map vm;
+ store(command_line_parser(tokens).options(description).run(), vm);
+ notify(vm);
+}
+
+void split_quotes(const options_description& description)
+{
+ const char* cmdline = "prg --input \"input.txt input.txt\" --optimization 4 --opt \"option1 option2\"";
+
+ vector< string > tokens = split_unix(cmdline, " ");
+
+ BOOST_REQUIRE(tokens.size() == 7);
+ check_value(tokens[0], "prg");
+ check_value(tokens[1], "--input");
+ check_value(tokens[2], "input.txt input.txt");
+ check_value(tokens[3], "--optimization");
+ check_value(tokens[4], "4");
+ check_value(tokens[5], "--opt");
+ check_value(tokens[6], "option1 option2");
+
+ variables_map vm;
+ store(command_line_parser(tokens).options(description).run(), vm);
+ notify(vm);
+}
+
+void split_escape(const options_description& description)
+{
+ const char* cmdline = "prg --input \\\"input.txt\\\" --optimization 4 --opt \\\"option1\\ option2\\\"";
+
+ vector< string > tokens = split_unix(cmdline, " ");
+
+ BOOST_REQUIRE(tokens.size() == 7);
+ check_value(tokens[0], "prg");
+ check_value(tokens[1], "--input");
+ check_value(tokens[2], "\"input.txt\"");
+ check_value(tokens[3], "--optimization");
+ check_value(tokens[4], "4");
+ check_value(tokens[5], "--opt");
+ check_value(tokens[6], "\"option1 option2\"");
+
+ variables_map vm;
+ store(command_line_parser(tokens).options(description).run(), vm);
+ notify(vm);
+}
+
+
+void split_single_quote(const options_description& description)
+{
+ const char* cmdline = "prg --input 'input.txt input.txt' --optimization 4 --opt 'option1 option2'";
+
+ vector< string > tokens = split_unix(cmdline, " ", "'");
+
+ BOOST_REQUIRE(tokens.size() == 7);
+ check_value(tokens[0], "prg");
+ check_value(tokens[1], "--input");
+ check_value(tokens[2], "input.txt input.txt");
+ check_value(tokens[3], "--optimization");
+ check_value(tokens[4], "4");
+ check_value(tokens[5], "--opt");
+ check_value(tokens[6], "option1 option2");
+
+ variables_map vm;
+ store(command_line_parser(tokens).options(description).run(), vm);
+ notify(vm);
+}
+
+void split_defaults(const options_description& description)
+{
+ const char* cmdline = "prg --input \t \'input file.txt\' \t --optimization 4 --opt \\\"option1\\ option2\\\"";
+
+ vector< string > tokens = split_unix(cmdline);
+
+ BOOST_REQUIRE(tokens.size() == 7);
+ check_value(tokens[0], "prg");
+ check_value(tokens[1], "--input");
+ check_value(tokens[2], "input file.txt");
+ check_value(tokens[3], "--optimization");
+ check_value(tokens[4], "4");
+ check_value(tokens[5], "--opt");
+ check_value(tokens[6], "\"option1 option2\"");
+
+ variables_map vm;
+ store(command_line_parser(tokens).options(description).run(), vm);
+ notify(vm);
+}
+
+int main(int /*ac*/, char** /*av*/)
+{
+ options_description desc;
+ desc.add_options()
+ ("input,i", value<string>(), "the input file")
+ ("optimization,O", value<unsigned>(), "optimization level")
+ ("opt,o", value<string>(), "misc option")
+ ;
+
+ split_whitespace(desc);
+ split_equalsign(desc);
+ split_semi(desc);
+ split_quotes(desc);
+ split_escape(desc);
+ split_single_quote(desc);
+ split_defaults(desc);
+
+ return 0;
+}
diff --git a/src/boost/libs/program_options/test/test_convert.cpp b/src/boost/libs/program_options/test/test_convert.cpp
new file mode 100644
index 000000000..f03a19eb5
--- /dev/null
+++ b/src/boost/libs/program_options/test/test_convert.cpp
@@ -0,0 +1,146 @@
+// 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 <cstring>
+#include <cassert>
+#include <string>
+#include <fstream>
+#include <sstream>
+#include <iostream>
+#include <boost/progress.hpp>
+#include <boost/bind.hpp>
+#include <boost/ref.hpp>
+
+#include <boost/program_options/detail/convert.hpp>
+#include <boost/program_options/detail/utf8_codecvt_facet.hpp>
+
+#include "minitest.hpp"
+
+using namespace std;
+
+string file_content(const string& filename)
+{
+ ifstream ifs(filename.c_str());
+ assert(ifs);
+
+ stringstream ss;
+ ss << ifs.rdbuf();
+
+ return ss.str();
+}
+
+// A version of from_8_bit which does not use functional object, for
+// performance comparison.
+std::wstring from_8_bit_2(const std::string& s,
+ const codecvt<wchar_t, char, mbstate_t>& cvt)
+{
+ std::wstring result;
+
+
+ std::mbstate_t state = std::mbstate_t();
+
+ const char* from = s.data();
+ const char* from_end = s.data() + s.size();
+ // The interace of cvt is not really iterator-like, and it's
+ // not possible the tell the required output size without the conversion.
+ // All we can is convert data by pieces.
+ while(from != from_end) {
+
+ // std::basic_string does not provide non-const pointers to the data,
+ // so converting directly into string is not possible.
+ wchar_t buffer[32];
+
+ wchar_t* to_next = buffer;
+ // Try to convert remaining input.
+ std::codecvt_base::result r =
+ cvt.in(state, from, from_end, from, buffer, buffer + 32, to_next);
+
+ if (r == std::codecvt_base::error)
+ throw logic_error("character conversion failed");
+ // 'partial' is not an error, it just means not all source characters
+ // we converted. However, we need to check that at least one new target
+ // character was produced. If not, it means the source data is
+ // incomplete, and since we don't have extra data to add to source, it's
+ // error.
+ if (to_next == buffer)
+ throw logic_error("character conversion failed");
+
+ // Add converted characters
+ result.append(buffer, to_next);
+ }
+
+ return result;
+}
+
+
+void test_convert(const std::string& input,
+ const std::string& expected_output)
+{
+ boost::program_options::detail::utf8_codecvt_facet facet;
+
+ std::wstring output;
+ {
+ boost::progress_timer t;
+ for (int i = 0; i < 10000; ++i)
+ output = boost::from_8_bit(
+ input,
+ facet);
+ }
+
+ {
+ boost::progress_timer t;
+ for (int i = 0; i < 10000; ++i)
+ output = from_8_bit_2(
+ input,
+ facet);
+ }
+
+ BOOST_CHECK(output.size()*2 == expected_output.size());
+
+ for(unsigned i = 0; i < output.size(); ++i) {
+
+ {
+ unsigned low = output[i];
+ low &= 0xFF;
+ unsigned low2 = expected_output[2*i];
+ low2 &= 0xFF;
+ BOOST_CHECK(low == low2);
+ }
+ {
+ unsigned high = output[i];
+ high >>= 8;
+ high &= 0xFF;
+ unsigned high2 = expected_output[2*i+1];
+ BOOST_CHECK(high == high2);
+ }
+ }
+
+ string ref = boost::to_8_bit(output, facet);
+
+ BOOST_CHECK(ref == input);
+}
+
+int main(int ac, char* av[])
+{
+ std::string input = file_content("utf8.txt");
+ std::string expected = file_content("ucs2.txt");
+
+ test_convert(input, expected);
+
+ if (ac > 1) {
+ cout << "Trying to convert the command line argument\n";
+
+ locale::global(locale(""));
+ std::wstring w = boost::from_local_8_bit(av[1]);
+
+ cout << "Got something, printing decimal code point values\n";
+ for (unsigned i = 0; i < w.size(); ++i) {
+ cout << (unsigned)w[i] << "\n";
+ }
+
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/program_options/test/ucs2.txt b/src/boost/libs/program_options/test/ucs2.txt
new file mode 100644
index 000000000..c4c0fe723
--- /dev/null
+++ b/src/boost/libs/program_options/test/ucs2.txt
Binary files differ
diff --git a/src/boost/libs/program_options/test/unicode_test.cpp b/src/boost/libs/program_options/test/unicode_test.cpp
new file mode 100644
index 000000000..97d19f0b4
--- /dev/null
+++ b/src/boost/libs/program_options/test/unicode_test.cpp
@@ -0,0 +1,164 @@
+// 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 <boost/program_options/variables_map.hpp>
+#include <boost/program_options/options_description.hpp>
+#include <boost/program_options/parsers.hpp>
+#include <boost/program_options/detail/utf8_codecvt_facet.hpp>
+using namespace boost::program_options;
+// We'll use po::value everywhere to workaround vc6 bug.
+namespace po = boost::program_options;
+
+#include <boost/function.hpp>
+using namespace boost;
+
+#include <sstream>
+using namespace std;
+
+#include "minitest.hpp"
+
+// Test that unicode input is forwarded to unicode option without
+// problems.
+void test_unicode_to_unicode()
+{
+ options_description desc;
+
+ desc.add_options()
+ ("foo", po::wvalue<wstring>(), "unicode option")
+ ;
+
+ vector<wstring> args;
+ args.push_back(L"--foo=\x044F");
+
+ variables_map 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(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
+// local 8 bit string. To test this, make local 8 bit encoding
+// be utf8.
+void test_unicode_to_native()
+{
+ std::codecvt<wchar_t, char, mbstate_t>* facet =
+ new boost::program_options::detail::utf8_codecvt_facet;
+ locale::global(locale(locale(), facet));
+
+ options_description desc;
+
+ desc.add_options()
+ ("foo", po::value<string>(), "unicode option")
+ ;
+
+ vector<wstring> args;
+ args.push_back(L"--foo=\x044F");
+
+ variables_map vm;
+ store(wcommand_line_parser(args).options(desc).run(), vm);
+
+ BOOST_CHECK(vm["foo"].as<string>() == "\xD1\x8F");
+}
+
+void test_native_to_unicode()
+{
+ std::codecvt<wchar_t, char, mbstate_t>* facet =
+ new boost::program_options::detail::utf8_codecvt_facet;
+ locale::global(locale(locale(), facet));
+
+ options_description desc;
+
+ desc.add_options()
+ ("foo", po::wvalue<wstring>(), "unicode option")
+ ;
+
+ vector<string> args;
+ args.push_back("--foo=\xD1\x8F");
+
+ variables_map vm;
+ store(command_line_parser(args).options(desc).run(), vm);
+
+ BOOST_CHECK(vm["foo"].as<wstring>() == L"\x044F");
+}
+
+vector<wstring> sv(const wchar_t* array[], unsigned size)
+{
+ vector<wstring> r;
+ for (unsigned i = 0; i < size; ++i)
+ r.push_back(array[i]);
+ return r;
+}
+
+void check_value(const woption& option, const char* name, const wchar_t* value)
+{
+ BOOST_CHECK(option.string_key == name);
+ BOOST_REQUIRE(option.value.size() == 1);
+ BOOST_CHECK(option.value.front() == value);
+}
+
+void test_command_line()
+{
+ options_description desc;
+ desc.add_options()
+ ("foo,f", new untyped_value(), "")
+ // Explicit qualification is a workaround for vc6
+ ("bar,b", po::value<std::string>(), "")
+ ("baz", new untyped_value())
+ ("qux,plug*", new untyped_value())
+ ;
+
+ const wchar_t* cmdline4_[] = { L"--foo=1\u0FF52", L"-f4", L"--bar=11",
+ L"-b4", L"--plug3=10"};
+ vector<wstring> cmdline4 = sv(cmdline4_,
+ sizeof(cmdline4_)/sizeof(cmdline4_[0]));
+ vector<woption> a4 =
+ wcommand_line_parser(cmdline4).options(desc).run().options;
+
+ BOOST_REQUIRE(a4.size() == 5);
+
+ check_value(a4[0], "foo", L"1\u0FF52");
+ check_value(a4[1], "foo", L"4");
+ check_value(a4[2], "bar", L"11");
+ check_value(a4[4], "qux", L"10");
+}
+
+// Since we've already tested conversion between parser encoding and
+// option encoding, all we need to check for config file is that
+// when reading wistream, it generates proper UTF8 data.
+void test_config_file()
+{
+ std::codecvt<wchar_t, char, mbstate_t>* facet =
+ new boost::program_options::detail::utf8_codecvt_facet;
+ locale::global(locale(locale(), facet));
+
+ options_description desc;
+
+ desc.add_options()
+ ("foo", po::value<string>(), "unicode option")
+ ;
+
+ std::wstringstream stream(L"foo = \x044F");
+
+ variables_map vm;
+ store(parse_config_file(stream, desc), vm);
+
+ BOOST_CHECK(vm["foo"].as<string>() == "\xD1\x8F");
+}
+
+int main(int, char* [])
+{
+ test_unicode_to_unicode();
+ test_unicode_to_native();
+ test_native_to_unicode();
+ test_command_line();
+ test_config_file();
+ return 0;
+}
+
diff --git a/src/boost/libs/program_options/test/unrecognized_test.cpp b/src/boost/libs/program_options/test/unrecognized_test.cpp
new file mode 100644
index 000000000..7dfb38057
--- /dev/null
+++ b/src/boost/libs/program_options/test/unrecognized_test.cpp
@@ -0,0 +1,88 @@
+// Copyright Sascha Ochsenknecht 2009.
+// 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 <boost/program_options/cmdline.hpp>
+#include <boost/program_options/options_description.hpp>
+#include <boost/program_options/parsers.hpp>
+#include <boost/program_options/detail/cmdline.hpp>
+using namespace boost::program_options;
+using boost::program_options::detail::cmdline;
+
+#include <iostream>
+#include <sstream>
+#include <vector>
+#include <cassert>
+using namespace std;
+
+#include "minitest.hpp"
+
+
+// Test free function collect_unrecognized()
+//
+// it collects the tokens of all not registered options. It can be used
+// to pass them to an own parser implementation
+
+
+
+void test_unrecognize_cmdline()
+{
+ options_description desc;
+
+ string content = "prg --input input.txt --optimization 4 --opt option";
+ vector< string > tokens = split_unix(content);
+
+ cmdline cmd(tokens);
+ cmd.set_options_description(desc);
+ cmd.allow_unregistered();
+
+ vector< option > opts = cmd.run();
+ vector< string > result = collect_unrecognized(opts, include_positional);
+
+ BOOST_CHECK_EQUAL(result.size(), 7);
+ BOOST_CHECK_EQUAL(result[0], "prg");
+ BOOST_CHECK_EQUAL(result[1], "--input");
+ BOOST_CHECK_EQUAL(result[2], "input.txt");
+ BOOST_CHECK_EQUAL(result[3], "--optimization");
+ BOOST_CHECK_EQUAL(result[4], "4");
+ BOOST_CHECK_EQUAL(result[5], "--opt");
+ BOOST_CHECK_EQUAL(result[6], "option");
+}
+
+
+
+void test_unrecognize_config()
+{
+
+ options_description desc;
+
+ string content =
+ " input = input.txt\n"
+ " optimization = 4\n"
+ " opt = option\n"
+ ;
+
+ stringstream ss(content);
+ vector< option > opts = parse_config_file(ss, desc, true).options;
+ vector< string > result = collect_unrecognized(opts, include_positional);
+
+ BOOST_CHECK_EQUAL(result.size(), 6);
+ BOOST_CHECK_EQUAL(result[0], "input");
+ BOOST_CHECK_EQUAL(result[1], "input.txt");
+ BOOST_CHECK_EQUAL(result[2], "optimization");
+ BOOST_CHECK_EQUAL(result[3], "4");
+ BOOST_CHECK_EQUAL(result[4], "opt");
+ BOOST_CHECK_EQUAL(result[5], "option");
+}
+
+
+
+int main(int /*ac*/, char** /*av*/)
+{
+ test_unrecognize_cmdline();
+ test_unrecognize_config();
+
+ return 0;
+}
diff --git a/src/boost/libs/program_options/test/utf8.txt b/src/boost/libs/program_options/test/utf8.txt
new file mode 100644
index 000000000..d97d3601e
--- /dev/null
+++ b/src/boost/libs/program_options/test/utf8.txt
Binary files differ
diff --git a/src/boost/libs/program_options/test/variable_map_test.cpp b/src/boost/libs/program_options/test/variable_map_test.cpp
new file mode 100644
index 000000000..04b43473d
--- /dev/null
+++ b/src/boost/libs/program_options/test/variable_map_test.cpp
@@ -0,0 +1,290 @@
+// 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 <boost/program_options/variables_map.hpp>
+#include <boost/program_options/options_description.hpp>
+#include <boost/program_options/parsers.hpp>
+#include <boost/program_options/detail/utf8_codecvt_facet.hpp>
+using namespace boost::program_options;
+// We'll use po::value everywhere to workaround vc6 bug.
+namespace po = boost::program_options;
+
+#include <boost/function.hpp>
+using namespace boost;
+
+#include <sstream>
+using namespace std;
+
+#include "minitest.hpp"
+
+vector<string> sv(const char* array[], unsigned size)
+{
+ vector<string> r;
+ for (unsigned i = 0; i < size; ++i)
+ r.push_back(array[i]);
+ return r;
+}
+
+void test_variable_map()
+{
+ options_description desc;
+ desc.add_options()
+ ("foo,f", new untyped_value)
+ ("bar,b", po::value<string>())
+ ("biz,z", po::value<string>())
+ ("baz", new untyped_value())
+ ("output,o", new untyped_value(), "")
+ ;
+ const char* cmdline3_[] = { "--foo='12'", "--bar=11", "-z3", "-ofoo" };
+ vector<string> cmdline3 = sv(cmdline3_,
+ sizeof(cmdline3_)/sizeof(const char*));
+ parsed_options a3 = command_line_parser(cmdline3).options(desc).run();
+ variables_map vm;
+ store(a3, vm);
+ notify(vm);
+ BOOST_REQUIRE(vm.size() == 4);
+ BOOST_CHECK(vm["foo"].as<string>() == "'12'");
+ BOOST_CHECK(vm["bar"].as<string>() == "11");
+ BOOST_CHECK(vm.count("biz") == 1);
+ BOOST_CHECK(vm["biz"].as<string>() == "3");
+ BOOST_CHECK(vm["output"].as<string>() == "foo");
+
+ int i;
+ desc.add_options()
+ ("zee", bool_switch(), "")
+ ("zak", po::value<int>(&i), "")
+ ("opt", bool_switch(), "");
+
+ const char* cmdline4_[] = { "--zee", "--zak=13" };
+ vector<string> cmdline4 = sv(cmdline4_,
+ sizeof(cmdline4_)/sizeof(const char*));
+ parsed_options a4 = command_line_parser(cmdline4).options(desc).run();
+
+ variables_map vm2;
+ store(a4, vm2);
+ notify(vm2);
+ BOOST_REQUIRE(vm2.size() == 3);
+ BOOST_CHECK(vm2["zee"].as<bool>() == true);
+ BOOST_CHECK(vm2["zak"].as<int>() == 13);
+ BOOST_CHECK(vm2["opt"].as<bool>() == false);
+ BOOST_CHECK(i == 13);
+
+ options_description desc2;
+ desc2.add_options()
+ ("vee", po::value<string>()->default_value("42"))
+ ("voo", po::value<string>())
+ ("iii", po::value<int>()->default_value(123))
+ ;
+ const char* cmdline5_[] = { "--voo=1" };
+ vector<string> cmdline5 = sv(cmdline5_,
+ sizeof(cmdline5_)/sizeof(const char*));
+ parsed_options a5 = command_line_parser(cmdline5).options(desc2).run();
+
+ variables_map vm3;
+ store(a5, vm3);
+ notify(vm3);
+ BOOST_REQUIRE(vm3.size() == 3);
+ BOOST_CHECK(vm3["vee"].as<string>() == "42");
+ BOOST_CHECK(vm3["voo"].as<string>() == "1");
+ BOOST_CHECK(vm3["iii"].as<int>() == 123);
+
+ options_description desc3;
+ desc3.add_options()
+ ("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>())
+ ;
+ /* The -m option is implicit. It does not have value in inside the token,
+ and we should not grab the next token. */
+ const char* cmdline6_[] = { "--imp=1", "-m", "--foo=1" };
+ vector<string> cmdline6 = sv(cmdline6_,
+ sizeof(cmdline6_)/sizeof(const char*));
+ parsed_options a6 = command_line_parser(cmdline6).options(desc3).run();
+
+ variables_map vm4;
+ store(a6, vm4);
+ notify(vm4);
+ 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);
+}
+
+int stored_value;
+void notifier(const vector<int>& v)
+{
+ stored_value = v.front();
+}
+
+void test_semantic_values()
+{
+ options_description desc;
+ desc.add_options()
+ ("foo", new untyped_value())
+ ("bar", po::value<int>())
+ ("biz", po::value< vector<string> >())
+ ("baz", po::value< vector<string> >()->multitoken())
+ ("int", po::value< vector<int> >()->notifier(&notifier))
+ ;
+
+
+ parsed_options parsed(&desc);
+ vector<option>& options = parsed.options;
+ vector<string> v;
+ v.push_back("q");
+ options.push_back(option("foo", vector<string>(1, "1")));
+ options.push_back(option("biz", vector<string>(1, "a")));
+ options.push_back(option("baz", v));
+ options.push_back(option("bar", vector<string>(1, "1")));
+ options.push_back(option("biz", vector<string>(1, "b x")));
+ v.push_back("w");
+ options.push_back(option("baz", v));
+
+ variables_map vm;
+ store(parsed, vm);
+ notify(vm);
+ BOOST_REQUIRE(vm.count("biz") == 1);
+ BOOST_REQUIRE(vm.count("baz") == 1);
+ const vector<string> av = vm["biz"].as< vector<string> >();
+ const vector<string> av2 = vm["baz"].as< vector<string> >();
+ string exp1[] = { "a", "b x" };
+ BOOST_CHECK(av == vector<string>(exp1, exp1 + 2));
+ string exp2[] = { "q", "q", "w" };
+ BOOST_CHECK(av2 == vector<string>(exp2, exp2 + 3));
+
+ options.push_back(option("int", vector<string>(1, "13")));
+
+ variables_map vm2;
+ store(parsed, vm2);
+ notify(vm2);
+ BOOST_REQUIRE(vm2.count("int") == 1);
+ BOOST_CHECK(vm2["int"].as< vector<int> >() == vector<int>(1, 13));
+ BOOST_CHECK_EQUAL(stored_value, 13);
+
+ vector<option> saved_options = options;
+
+ options.push_back(option("bar", vector<string>(1, "2")));
+ variables_map vm3;
+ BOOST_CHECK_THROW(store(parsed, vm3), multiple_occurrences);
+
+ options = saved_options;
+ // Now try passing two int in one 'argv' element.
+ // This should not work.
+ options.push_back(option("int", vector<string>(1, "2 3")));
+ variables_map vm4;
+ BOOST_CHECK_THROW(store(parsed, vm4), validation_error);
+}
+
+void test_priority()
+{
+ options_description desc;
+ desc.add_options()
+ // Value of this option will be specified in two sources,
+ // and only first one should be used.
+ ("first", po::value< vector<int > >())
+ // Value of this option will have default value in the first source,
+ // and explicit assignment in the second, so the second should be used.
+ ("second", po::value< vector<int > >()->default_value(vector<int>(1, 1), ""))
+ ("aux", po::value< vector<int > >())
+ // This will have values in both sources, and values should be combined
+ ("include", po::value< vector<int> >()->composing())
+ ;
+
+ const char* cmdline1_[] = { "--first=1", "--aux=10", "--first=3", "--include=1" };
+ vector<string> cmdline1 = sv(cmdline1_,
+ sizeof(cmdline1_)/sizeof(const char*));
+
+ parsed_options p1 = command_line_parser(cmdline1).options(desc).run();
+
+ const char* cmdline2_[] = { "--first=12", "--second=7", "--include=7" };
+ vector<string> cmdline2 = sv(cmdline2_,
+ sizeof(cmdline2_)/sizeof(const char*));
+
+ parsed_options p2 = command_line_parser(cmdline2).options(desc).run();
+
+ variables_map vm;
+ store(p1, vm);
+
+ BOOST_REQUIRE(vm.count("first") == 1);
+ BOOST_REQUIRE(vm["first"].as< vector<int> >().size() == 2);
+ BOOST_CHECK_EQUAL(vm["first"].as< vector<int> >()[0], 1);
+ BOOST_CHECK_EQUAL(vm["first"].as< vector<int> >()[1], 3);
+
+ BOOST_REQUIRE(vm.count("second") == 1);
+ BOOST_REQUIRE(vm["second"].as< vector<int> >().size() == 1);
+ BOOST_CHECK_EQUAL(vm["second"].as< vector<int> >()[0], 1);
+
+ store(p2, vm);
+
+ // Value should not change.
+ BOOST_REQUIRE(vm.count("first") == 1);
+ BOOST_REQUIRE(vm["first"].as< vector<int> >().size() == 2);
+ BOOST_CHECK_EQUAL(vm["first"].as< vector<int> >()[0], 1);
+ BOOST_CHECK_EQUAL(vm["first"].as< vector<int> >()[1], 3);
+
+ // Value should change to 7
+ BOOST_REQUIRE(vm.count("second") == 1);
+ BOOST_REQUIRE(vm["second"].as< vector<int> >().size() == 1);
+ BOOST_CHECK_EQUAL(vm["second"].as< vector<int> >()[0], 7);
+
+ BOOST_REQUIRE(vm.count("include") == 1);
+ BOOST_REQUIRE(vm["include"].as< vector<int> >().size() == 2);
+ BOOST_CHECK_EQUAL(vm["include"].as< vector<int> >()[0], 1);
+ BOOST_CHECK_EQUAL(vm["include"].as< vector<int> >()[1], 7);
+}
+
+void test_multiple_assignments_with_different_option_description()
+{
+ // Test that if we store option twice into the same variable_map,
+ // and some of the options stored the first time are not present
+ // in the options descrription provided the second time, we don't crash.
+
+ options_description desc1("");
+ desc1.add_options()
+ ("help,h", "")
+ ("includes", po::value< vector<string> >()->composing(), "");
+ ;
+
+ options_description desc2("");
+ desc2.add_options()
+ ("output,o", "");
+
+ vector<string> input1;
+ input1.push_back("--help");
+ input1.push_back("--includes=a");
+ parsed_options p1 = command_line_parser(input1).options(desc1).run();
+
+ vector<string> input2;
+ input1.push_back("--output");
+ parsed_options p2 = command_line_parser(input2).options(desc2).run();
+
+ vector<string> input3;
+ input3.push_back("--includes=b");
+ parsed_options p3 = command_line_parser(input3).options(desc1).run();
+
+
+ variables_map vm;
+ store(p1, vm);
+ store(p2, vm);
+ store(p3, vm);
+
+ BOOST_REQUIRE(vm.count("help") == 1);
+ BOOST_REQUIRE(vm.count("includes") == 1);
+ BOOST_CHECK_EQUAL(vm["includes"].as< vector<string> >()[0], "a");
+ BOOST_CHECK_EQUAL(vm["includes"].as< vector<string> >()[1], "b");
+
+}
+
+int main(int, char* [])
+{
+ test_variable_map();
+ test_semantic_values();
+ test_priority();
+ test_multiple_assignments_with_different_option_description();
+ return 0;
+}
+
diff --git a/src/boost/libs/program_options/test/winmain.cpp b/src/boost/libs/program_options/test/winmain.cpp
new file mode 100644
index 000000000..0c3512f97
--- /dev/null
+++ b/src/boost/libs/program_options/test/winmain.cpp
@@ -0,0 +1,74 @@
+// 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)
+
+#if defined(_WIN32)
+#include <string>
+#include <vector>
+#include <cctype>
+#include <iostream>
+#include <stdlib.h>
+
+using namespace std;
+
+#include <boost/program_options/parsers.hpp>
+using namespace boost::program_options;
+
+void check_equal(const std::vector<string>& actual, char **expected, int n)
+{
+ if (actual.size() != n)
+ {
+ std::cerr << "Size mismatch between expected and actual data\n";
+ abort();
+ }
+ for (int i = 0; i < n; ++i)
+ {
+ if (actual[i] != expected[i])
+ {
+ std::cerr << "Unexpected content\n";
+ abort();
+ }
+ }
+}
+
+#include <boost/preprocessor/cat.hpp>
+
+void test_winmain()
+{
+
+#define C ,
+#define TEST(input, expected) \
+ char* BOOST_PP_CAT(e, __LINE__)[] = expected;\
+ vector<string> BOOST_PP_CAT(v, __LINE__) = split_winmain(input);\
+ check_equal(BOOST_PP_CAT(v, __LINE__), BOOST_PP_CAT(e, __LINE__),\
+ sizeof(BOOST_PP_CAT(e, __LINE__))/sizeof(char*));
+
+// The following expectations were obtained in Win2000 shell:
+ TEST("1 ", {"1"});
+ TEST("1\"2\" ", {"12"});
+ TEST("1\"2 ", {"12 "});
+ TEST("1\"\\\"2\" ", {"1\"2"});
+ TEST("\"1\" \"2\" ", {"1" C "2"});
+ TEST("1\\\" ", {"1\""});
+ TEST("1\\\\\" ", {"1\\ "});
+ TEST("1\\\\\\\" ", {"1\\\""});
+ TEST("1\\\\\\\\\" ", {"1\\\\ "});
+
+ TEST("1\" 1 ", {"1 1 "});
+ TEST("1\\\" 1 ", {"1\"" C "1"});
+ TEST("1\\1 ", {"1\\1"});
+ TEST("1\\\\1 ", {"1\\\\1"});
+}
+
+int main(int, char*[])
+{
+ test_winmain();
+ return 0;
+}
+#else
+int main(int, char*[])
+{
+ return 0;
+}
+#endif
diff --git a/src/boost/libs/program_options/test/winmain.py b/src/boost/libs/program_options/test/winmain.py
new file mode 100644
index 000000000..5c43242e7
--- /dev/null
+++ b/src/boost/libs/program_options/test/winmain.py
@@ -0,0 +1,39 @@
+
+from StringIO import StringIO
+import string
+
+testcases = r"""1 -> 1
+1"2" -> 12
+1"2 -> 12
+1"\"2" -> 1"2
+"1" "2" -> 1, 2
+1\" -> 1"
+1\\" -> 1\
+1\\\" -> 1\"
+1\\\\" -> 1\\
+1" 1 -> 1 1
+1\" 1 -> 1", 1
+1\1 -> 1\1
+1\\1 -> 1\\1
+"""
+
+#testcases = r"""1\\\\" -> 1\\
+#"""
+
+t = StringIO(testcases)
+
+def quote(s):
+ result = s.replace("\\", r"\\")
+ result = result.replace("\"", "\\\"")
+ return '"' + result + '"'
+
+
+for s in t:
+ s = string.strip(s)
+ (value, result) = string.split(s, "->")
+# print value, result
+ tokens = string.split(result, ",")
+ value = quote(value)
+ tokens = map(string.strip, tokens)
+ tokens = map(quote, tokens)
+ print "TEST(%s, {%s});" % (value, string.join(tokens, ","))