summaryrefslogtreecommitdiff
path: root/tools/bcp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2013-06-25 22:59:01 +0000
committer <>2013-09-27 11:49:28 +0000
commit8c4528713d907ee2cfd3bfcbbad272c749867f84 (patch)
treec09e2ce80f47b90c85cc720f5139089ad9c8cfff /tools/bcp
downloadboost-tarball-8c4528713d907ee2cfd3bfcbbad272c749867f84.tar.gz
Imported from /home/lorry/working-area/delta_boost-tarball/boost_1_54_0.tar.bz2.boost_1_54_0baserock/morph
Diffstat (limited to 'tools/bcp')
-rw-r--r--tools/bcp/Jamfile.v237
-rw-r--r--tools/bcp/add_dependent_lib.cpp216
-rw-r--r--tools/bcp/add_path.cpp535
-rw-r--r--tools/bcp/bcp.hpp47
-rw-r--r--tools/bcp/bcp_imp.cpp295
-rw-r--r--tools/bcp/bcp_imp.hpp118
-rw-r--r--tools/bcp/copy_path.cpp245
-rw-r--r--tools/bcp/doc/Jamfile.v218
-rw-r--r--tools/bcp/doc/bcp.qbk212
-rw-r--r--tools/bcp/doc/html/index.html356
-rw-r--r--tools/bcp/file_types.cpp72
-rw-r--r--tools/bcp/fileview.cpp143
-rw-r--r--tools/bcp/fileview.hpp72
-rw-r--r--tools/bcp/index.html17
-rw-r--r--tools/bcp/licence_info.cpp721
-rw-r--r--tools/bcp/licence_info.hpp39
-rw-r--r--tools/bcp/main.cpp182
-rw-r--r--tools/bcp/output_licence_info.cpp410
-rw-r--r--tools/bcp/path_operations.cpp41
-rw-r--r--tools/bcp/scan_cvs_path.cpp147
-rw-r--r--tools/bcp/scan_licence.cpp275
-rw-r--r--tools/bcp/test/Jamfile.v225
22 files changed, 4223 insertions, 0 deletions
diff --git a/tools/bcp/Jamfile.v2 b/tools/bcp/Jamfile.v2
new file mode 100644
index 000000000..4f34b549a
--- /dev/null
+++ b/tools/bcp/Jamfile.v2
@@ -0,0 +1,37 @@
+# (C) Copyright John Maddock 2006.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+exe bcp
+ :
+ add_dependent_lib.cpp add_path.cpp bcp_imp.cpp copy_path.cpp file_types.cpp
+ fileview.cpp main.cpp path_operations.cpp scan_cvs_path.cpp
+ licence_info.cpp scan_licence.cpp output_licence_info.cpp
+ /boost/filesystem//boost_filesystem
+ /boost/regex//boost_regex
+ /boost/test//boost_prg_exec_monitor
+ :
+ :
+ release
+ ;
+
+install dist-bin
+ :
+ bcp
+ :
+ <install-type>EXE
+ <location>../../dist/bin
+ :
+ release
+ ;
+
+install dist-lib
+ :
+ bcp
+ :
+ <install-type>LIB
+ <location>../../dist/lib
+ :
+ release
+ ;
+
diff --git a/tools/bcp/add_dependent_lib.cpp b/tools/bcp/add_dependent_lib.cpp
new file mode 100644
index 000000000..bb1818a2e
--- /dev/null
+++ b/tools/bcp/add_dependent_lib.cpp
@@ -0,0 +1,216 @@
+/*
+ *
+ * Copyright (c) 2009 Dr John Maddock
+ * Use, modification and distribution is 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)
+ *
+ * This file implements the following:
+ * void bcp_implementation::add_path(const fs::path& p)
+ * void bcp_implementation::add_directory(const fs::path& p)
+ * void bcp_implementation::add_file(const fs::path& p)
+ * void bcp_implementation::add_dependent_lib(const std::string& libname, const fs::path& p, const fileview& view)
+ */
+
+#include "bcp_imp.hpp"
+#include "fileview.hpp"
+#include <boost/regex.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/exception.hpp>
+#include <iostream>
+
+//
+// This file contains the code required to work out whether the source/header file being scanned
+// is actually dependent upon some library's source code or not.
+//
+
+static std::map<std::string, boost::regex> scanner;
+
+static std::map<std::string, std::set<std::string> > free_function_names;
+static std::map<std::string, std::set<std::string> > class_names;
+static std::map<std::string, std::set<std::string> > variable_names;
+
+static void init_library_scanner(const fs::path& p, bool cvs_mode, const std::string& libname, bool recurse = false)
+{
+ /*
+ if(free_function_names.count(libname) == 0)
+ {
+ free_function_names[libname] = "[\\x0]";
+ class_names[libname] = "[\\x0]";
+ variable_names[libname] = "[\\x0]";
+ }
+ */
+ //
+ // Don't add files created by build system:
+ //
+ if((p.leaf() == "bin") || (p.leaf() == "bin-stage"))
+ return;
+ //
+ // Don't add version control directories:
+ //
+ if((p.leaf() == "CVS") || (p.leaf() == ".svn"))
+ return;
+ //
+ // don't add directories not under version control:
+ //
+ if(cvs_mode && !fs::exists(p / "CVS/Entries"))
+ return;
+ if(cvs_mode && !fs::exists(p / ".svn/entries"))
+ return;
+ //
+ // Enumerate files and directories:
+ //
+ fs::directory_iterator i(p);
+ fs::directory_iterator j;
+ while(i != j)
+ {
+ if(fs::is_directory(*i))
+ init_library_scanner(*i, cvs_mode, libname, true);
+ if(bcp_implementation::is_source_file(*i))
+ {
+ static boost::regex function_scanner(
+ "(?|" // Branch reset group
+ "(?:\\<\\w+\\>[^>;{},:]*)" // Return type
+ "(?:"
+ "(\\<\\w+\\>)" // Maybe class name
+ "\\s*"
+ "(?:<[^>;{]*>)?" // Maybe template specialisation
+ "::\\s*)?"
+ "(\\<(?!throw|if|while|for|catch)\\w+\\>)" // function name
+ "\\s*"
+ "\\("
+ "[^\\(\\);{}]*" // argument list
+ "\\)"
+ "\\s*"
+ "\\{" // start of definition
+ "|"
+ "(\\<\\w+\\>)" // Maybe class name
+ "\\s*"
+ "(?:<[^>;{]*>)?" // Maybe template specialisation
+ "::\\s*"
+ "~?\\1" // function name, same as class name
+ "\\s*"
+ "\\("
+ "[^\\(\\);{}]*" // argument list
+ "\\)"
+ "\\s*"
+ "\\{" // start of definition
+ ")" // end branch reset
+ );
+ fileview view(*i);
+ boost::regex_iterator<const char*> a(view.begin(), view.end(), function_scanner);
+ boost::regex_iterator<const char*> b;
+ while(a != b)
+ {
+ if((*a)[1].matched)
+ {
+ std::string n = a->str(1);
+ class_names[libname].insert(n);
+ }
+ else
+ {
+ std::string n = a->str(2);
+ free_function_names[libname].insert(n);
+ }
+ ++a;
+ }
+ }
+ ++i;
+ }
+
+ if(recurse == false)
+ {
+ //
+ // Build the regular expressions:
+ //
+ const char* e1 =
+ "^(?>[[:blank:]]*)(?!#)[^;{}\\r\\n]*"
+ "(?|"
+ "(?:class|struct)[^:;{}#]*"
+ "(";
+ // list of class names goes here...
+ const char* e2 =
+ ")\\s*(?:<[^;{>]*>\\s*)?(?::[^;{]*)?\\{"
+ "|"
+ "\\<(?!return)\\w+\\>[^:;{}#=<>!~%.\\w]*(";
+ // List of function names goes here...
+ const char* e3 =
+ ")\\s*\\([^;()]*\\)\\s*;)";
+
+ std::string class_name_list;
+ std::set<std::string>::const_iterator i = class_names[libname].begin(), j = class_names[libname].end();
+ if(i != j)
+ {
+ class_name_list = *i;
+ ++i;
+ while(i != j)
+ {
+ class_name_list += "|" + *i;
+ ++i;
+ }
+ }
+ else
+ {
+ class_name_list = "[\\x0]";
+ }
+ std::string function_name_list;
+ i = free_function_names[libname].begin();
+ j = free_function_names[libname].end();
+ if(i != j)
+ {
+ function_name_list = *i;
+ ++i;
+ while(i != j)
+ {
+ function_name_list += "|" + *i;
+ ++i;
+ }
+ }
+ else
+ {
+ function_name_list = "[\\x0]";
+ }
+
+ scanner[libname] = boost::regex(e1 + class_name_list + e2 + function_name_list + e3);
+ }
+}
+
+void bcp_implementation::add_dependent_lib(const std::string& libname, const fs::path& p, const fileview& view)
+{
+ //
+ // if the boost library libname has source associated with it
+ // then add the source to our list:
+ //
+ if(fs::exists(m_boost_path / "libs" / libname / "src"))
+ {
+ if(!m_dependencies.count(fs::path("libs") / libname / "src"))
+ {
+ if(scanner.count(libname) == 0)
+ init_library_scanner(m_boost_path / "libs" / libname / "src", m_cvs_mode, libname);
+ boost::cmatch what;
+ if(regex_search(view.begin(), view.end(), what, scanner[libname]))
+ {
+ std::cout << "INFO: tracking source dependencies of library " << libname
+ << " due to presence of \"" << what << "\" in file " << p << std::endl;
+ //std::cout << "Full text match was: " << what << std::endl;
+ m_dependencies[fs::path("libs") / libname / "src"] = p; // set up dependency tree
+ add_path(fs::path("libs") / libname / "src");
+
+ if(fs::exists(m_boost_path / "libs" / libname / "build"))
+ {
+ if(!m_dependencies.count(fs::path("libs") / libname / "build"))
+ {
+ m_dependencies[fs::path("libs") / libname / "build"] = p; // set up dependency tree
+ add_path(fs::path("libs") / libname / "build");
+ //m_dependencies[fs::path("boost-build.jam")] = p;
+ //add_path(fs::path("boost-build.jam"));
+ m_dependencies[fs::path("Jamroot")] = p;
+ add_path(fs::path("Jamroot"));
+ //m_dependencies[fs::path("tools/build")] = p;
+ //add_path(fs::path("tools/build"));
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tools/bcp/add_path.cpp b/tools/bcp/add_path.cpp
new file mode 100644
index 000000000..3643bdb6c
--- /dev/null
+++ b/tools/bcp/add_path.cpp
@@ -0,0 +1,535 @@
+/*
+ *
+ * Copyright (c) 2003 Dr John Maddock
+ * Use, modification and distribution is 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)
+ *
+ * This file implements the following:
+ * void bcp_implementation::add_path(const fs::path& p)
+ * void bcp_implementation::add_directory(const fs::path& p)
+ * void bcp_implementation::add_file(const fs::path& p)
+ * void bcp_implementation::add_dependent_lib(const std::string& libname, const fs::path& p, const fileview& view)
+ */
+
+#include "bcp_imp.hpp"
+#include "fileview.hpp"
+#include <boost/regex.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/exception.hpp>
+#include <iostream>
+
+
+void bcp_implementation::add_path(const fs::path& p)
+{
+ fs::path normalized_path = p;
+ normalized_path.normalize();
+ if(fs::exists(m_boost_path / normalized_path))
+ {
+ if(fs::is_directory(m_boost_path / normalized_path))
+ add_directory(normalized_path);
+ else
+ add_file(normalized_path);
+ }
+ else
+ {
+ std::cerr << "CAUTION: dependent file " << p.string() << " does not exist." << std::endl;
+ std::cerr << " Found while scanning file " << m_dependencies[p].string() << std::endl;
+ }
+}
+
+void bcp_implementation::add_directory(const fs::path& p)
+{
+ //
+ // Don't add files created by build system:
+ //
+ if((p.leaf() == "bin") || (p.leaf() == "bin-stage"))
+ return;
+ //
+ // Don't add version control directories:
+ //
+ if((p.leaf() == "CVS") || (p.leaf() == ".svn"))
+ return;
+ //
+ // don't add directories not under version control:
+ //
+ if(m_cvs_mode && !fs::exists(m_boost_path / p / "CVS/Entries"))
+ return;
+ if(m_svn_mode && !fs::exists(m_boost_path / p / ".svn/entries"))
+ return;
+ //
+ // enermerate files and directories:
+ //
+ fs::directory_iterator i(m_boost_path / p);
+ fs::directory_iterator j;
+ while(i != j)
+ {
+ //
+ // we need to convert *i back into
+ // a relative path, what follows is a hack:
+ //
+ std::string s(i->path().string());
+ if(m_boost_path.string().size())
+ s.erase(0, m_boost_path.string().size() + 1);
+ fs::path np = s;
+ if(!m_dependencies.count(np))
+ {
+ m_dependencies[np] = p; // set up dependency tree
+ add_path(np);
+ }
+ ++i;
+ }
+}
+
+void bcp_implementation::add_file(const fs::path& p)
+{
+ //
+ // if the file does not exist in cvs then don't do anything with it:
+ //
+ if((m_cvs_mode || m_svn_mode) && (m_cvs_paths.find(p) == m_cvs_paths.end()))
+ return;
+ //
+ // if we've already seen the file return:
+ //
+ if(m_copy_paths.find(p) != m_copy_paths.end())
+ return;
+ //
+ // add the file to our list:
+ //
+ m_copy_paths.insert(p);
+ //
+ // if this is a source file, scan for dependencies:
+ //
+ if(is_source_file(p))
+ {
+ add_file_dependencies(p, false);
+ }
+ if(is_jam_file(p) && m_namespace_name.size() && ((std::distance(p.begin(), p.end()) < 3) || (*p.begin() != "tools") || (*++p.begin() != "build")))
+ {
+ //
+ // We're doing a rename of namespaces and library names
+ // so scan for names of libraries:
+ //
+ static const boost::regex e(
+ "\\<lib\\s+(boost\\w+)\\s+[:;]"
+ );
+
+ fileview view(m_boost_path / p);
+ boost::regex_token_iterator<const char*> i(view.begin(), view.end(), e, 1);
+ boost::regex_token_iterator<const char*> j;
+ while(i != j)
+ {
+ m_lib_names.insert(*i);
+ ++i;
+ }
+ static const std::pair<fs::path, std::string> specials_library_names[] = {
+ std::pair<fs::path, std::string>("libs/python/build/Jamfile.v2", "boost_python"),
+ std::pair<fs::path, std::string>("libs/python/build/Jamfile.v2", "boost_python3"),
+ };
+
+ for(unsigned int n = 0; n < (sizeof(specials_library_names)/sizeof(specials_library_names[0])); ++n)
+ {
+ if(0 == compare_paths(specials_library_names[n].first, p))
+ {
+ m_lib_names.insert(specials_library_names[n].second);
+ }
+ }
+ }
+ //
+ // if this is a html file, scan for dependencies:
+ //
+ if(is_html_file(p))
+ {
+ static const boost::regex e(
+ "<(?:img[^>]*src=|link[^>]*href=)(\"[^\"]+\"|\\w+)[^>]*>"
+ );
+
+ fileview view(m_boost_path / p);
+ boost::regex_token_iterator<const char*> i(view.begin(), view.end(), e, 1);
+ boost::regex_token_iterator<const char*> j;
+ while(i != j)
+ {
+ //
+ // extract the dependent name:
+ //
+ std::string s(*i);
+ if(s[0] == '\"')
+ {
+ // remove quotes:
+ assert(s.size() > 2);
+ s.erase(0, 1);
+ s.erase(s.size() - 1);
+ }
+ //
+ // Remove any target suffix:
+ //
+ std::string::size_type n = s.find('#');
+ if(n != std::string::npos)
+ {
+ s.erase(n);
+ }
+ //
+ // if the name starts with ./ remove it
+ // or we'll get an error:
+ if(s.compare(0, 2, "./") == 0)
+ s.erase(0, 2);
+ if(s.find(':') == std::string::npos)
+ {
+ // only concatonate if it's a relative path
+ // rather than a URL:
+ fs::path dep(p.branch_path() / s);
+ if(!m_dependencies.count(dep))
+ {
+ m_dependencies[dep] = p; // set up dependency tree
+ add_path(dep);
+ }
+ }
+ ++i;
+ }
+ }
+ //
+ // now scan for "special" dependencies:
+ // anything that we can't automatically detect...
+ //
+static const std::pair<fs::path, fs::path>
+ specials[] = {
+ std::pair<fs::path, fs::path>("boost/filesystem/convenience.hpp", "boost/filesystem.hpp"),
+ std::pair<fs::path, fs::path>("boost/filesystem/exception.hpp", "boost/filesystem.hpp"),
+ std::pair<fs::path, fs::path>("boost/filesystem/fstream.hpp", "boost/filesystem.hpp"),
+ std::pair<fs::path, fs::path>("boost/filesystem/operations.hpp", "boost/filesystem.hpp"),
+ std::pair<fs::path, fs::path>("boost/filesystem/path.hpp", "boost/filesystem.hpp"),
+ std::pair<fs::path, fs::path>("boost/filesystem.hpp", "libs/filesystem/build"),
+ std::pair<fs::path, fs::path>("boost/filesystem.hpp", "libs/filesystem/v2"),
+ std::pair<fs::path, fs::path>("boost/filesystem.hpp", "libs/filesystem/v3"),
+ std::pair<fs::path, fs::path>("boost/config.hpp", "boost/config"),
+ std::pair<fs::path, fs::path>("tools/build/allyourbase.jam", "Jamrules"),
+ std::pair<fs::path, fs::path>("tools/build/allyourbase.jam", "project-root.jam"),
+ std::pair<fs::path, fs::path>("tools/build/allyourbase.jam", "boost-build.jam"),
+ std::pair<fs::path, fs::path>("tools/build/v1/allyourbase.jam", "Jamrules"),
+ std::pair<fs::path, fs::path>("tools/build/v1/allyourbase.jam", "project-root.jam"),
+ std::pair<fs::path, fs::path>("tools/build/v1/allyourbase.jam", "boost-build.jam"),
+ std::pair<fs::path, fs::path>("tools/build/v2/boost-build.jam", "Jamrules"),
+ std::pair<fs::path, fs::path>("tools/build/v2/boost-build.jam", "project-root.jam"),
+ std::pair<fs::path, fs::path>("tools/build/v2/boost-build.jam", "boost-build.jam"),
+ std::pair<fs::path, fs::path>("tools/build/v2/boost-build.jam", "Jamfile.v2"),
+ std::pair<fs::path, fs::path>("tools/build/v2/boost-build.jam", "boostcpp.jam"),
+ std::pair<fs::path, fs::path>("tools/build/v2/boost-build.jam", "bootstrap.bat"),
+ std::pair<fs::path, fs::path>("tools/build/v2/boost-build.jam", "bootstrap.sh"),
+ std::pair<fs::path, fs::path>("tools/build/v2/boost-build.jam", "Jamroot"),
+ std::pair<fs::path, fs::path>("tools/build/v2/boost-build.jam", "INSTALL"),
+ std::pair<fs::path, fs::path>("tools/build/v2/boost-build.jam", "LICENSE_1_0.txt"),
+ std::pair<fs::path, fs::path>("boost/preprocessor/iterate.hpp", "boost/preprocessor/iteration"),
+ std::pair<fs::path, fs::path>("boost/preprocessor/slot/slot.hpp", "boost/preprocessor/slot/detail"),
+ std::pair<fs::path, fs::path>("boost/function.hpp", "boost/function/detail"),
+ std::pair<fs::path, fs::path>("boost/regex/config.hpp", "boost/regex/user.hpp"),
+ std::pair<fs::path, fs::path>("boost/signals/signal_template.hpp", "boost/function"),
+ std::pair<fs::path, fs::path>("boost/mpl/list.hpp", "boost/mpl/list"),
+ std::pair<fs::path, fs::path>("boost/mpl/list_c.hpp", "boost/mpl/list"),
+ std::pair<fs::path, fs::path>("boost/mpl/vector.hpp", "boost/mpl/vector"),
+ std::pair<fs::path, fs::path>("boost/mpl/deque.hpp", "boost/mpl/vector"),
+ std::pair<fs::path, fs::path>("boost/mpl/vector_c.hpp", "boost/mpl/vector"),
+ std::pair<fs::path, fs::path>("boost/mpl/map.hpp", "boost/mpl/map"),
+ std::pair<fs::path, fs::path>("boost/mpl/set.hpp", "boost/mpl/set"),
+ std::pair<fs::path, fs::path>("boost/mpl/set_c.hpp", "boost/mpl/set"),
+ std::pair<fs::path, fs::path>("boost/mpl/aux_/include_preprocessed.hpp", "boost/mpl/aux_/preprocessed"),
+ std::pair<fs::path, fs::path>("boost/mpl/vector/aux_/include_preprocessed.hpp", "boost/mpl/vector/aux_/preprocessed"),
+ std::pair<fs::path, fs::path>("boost/mpl/set/aux_/include_preprocessed.hpp", "boost/mpl/set/aux_/preprocessed"),
+ std::pair<fs::path, fs::path>("boost/mpl/map/aux_/include_preprocessed.hpp", "boost/mpl/map/aux_/preprocessed"),
+ std::pair<fs::path, fs::path>("boost/mpl/list/aux_/include_preprocessed.hpp", "boost/mpl/list/aux_/preprocessed"),
+ std::pair<fs::path, fs::path>("libs/graph/src/python/visitor.hpp", "libs/graph/src/python"),
+ std::pair<fs::path, fs::path>("boost/test/detail/config.hpp", "libs/test/src"),
+ std::pair<fs::path, fs::path>("boost/test/detail/config.hpp", "libs/test/build"),
+ std::pair<fs::path, fs::path>("boost/typeof.hpp", "boost/typeof/incr_registration_group.hpp"),
+ std::pair<fs::path, fs::path>("boost/function_types/detail/pp_loop.hpp", "boost/function_types/detail/pp_cc_loop"),
+ std::pair<fs::path, fs::path>("boost/function_types/components.hpp", "boost/function_types/detail/components_impl"),
+ std::pair<fs::path, fs::path>("boost/function_types/detail/pp_loop.hpp", "boost/function_types/detail"),
+ std::pair<fs::path, fs::path>("boost/math/tools/rational.hpp", "boost/math/tools/detail"),
+ std::pair<fs::path, fs::path>("boost/proto/repeat.hpp", "boost/proto/detail/local.hpp"),
+ std::pair<fs::path, fs::path>("boost/signals/signal_template.hpp", "boost/function"),
+ std::pair<fs::path, fs::path>("boost/preprocessor/slot/counter.hpp", "boost/preprocessor/slot/detail/counter.hpp"),
+ std::pair<fs::path, fs::path>("boost/graph/distributed/detail/tag_allocator.hpp", "libs/graph_parallel"),
+ std::pair<fs::path, fs::path>("boost/graph/distributed/mpi_process_group.hpp", "libs/graph_parallel"),
+ };
+
+ for(unsigned int n = 0; n < (sizeof(specials)/sizeof(specials[0])); ++n)
+ {
+ if(0 == compare_paths(specials[n].first, p))
+ {
+ if(!m_dependencies.count(specials[n].second))
+ {
+ m_dependencies[specials[n].second] = p; // set up dependency tree
+ add_path(specials[n].second);
+ }
+ }
+ }
+
+}
+
+void bcp_implementation::add_file_dependencies(const fs::path& p, bool scanfile)
+{
+ static const boost::regex e(
+ "^[[:blank:]]*(?://@bcp[[:blank:]]+([^\\n]*)\n)?#[[:blank:]]*include[[:blank:]]*[\"<]([^\">]+)[\">]"
+ );
+
+ if(!m_dependencies.count(p))
+ m_dependencies[p] = p; // set terminal dependency
+
+ fileview view;
+ if(scanfile)
+ view.open(p);
+ else
+ view.open(m_boost_path / p);
+ if(m_license_mode && !scanfile)
+ scan_license(p, view);
+ const int subs[] = { 1, 2 };
+ boost::regex_token_iterator<const char*> i(view.begin(), view.end(), e, subs);
+ boost::regex_token_iterator<const char*> j;
+ while(i != j)
+ {
+ //
+ // *i contains the name of the include file,
+ // check first for a file of that name in the
+ // same directory as the file we are scanning,
+ // and if that fails, then check the boost-root:
+ //
+ fs::path include_file;
+ try{
+ std::string discart_message = *i;
+ ++i;
+ if(discart_message.size())
+ {
+ // The include is optional and should be discarded:
+ std::cout << "Optional functionality won't be copied: " << discart_message << std::endl;
+ std::cout << "Add the file " << *i << " to the list of dependencies to extract to copy this functionality." << std::endl;
+ ++i;
+ continue;
+ }
+ include_file = i->str();
+ fs::path test_file(m_boost_path / p.branch_path() / include_file);
+ if(fs::exists(test_file) && !fs::is_directory(test_file) && (p.branch_path().string() != "boost"))
+ {
+ if(!m_dependencies.count(p.branch_path() / include_file))
+ {
+ m_dependencies[p.branch_path() / include_file] = p;
+ add_path(p.branch_path() / include_file);
+ }
+ }
+ else if(fs::exists(m_boost_path / include_file))
+ {
+ if(!m_dependencies.count(include_file))
+ {
+ m_dependencies[include_file] = p;
+ add_path(include_file);
+ }
+ }
+ ++i;
+ }
+ catch(const fs::filesystem_error&)
+ {
+ std::cerr << "Can't parse filename " << *i << " included by file " << p.string() << std::endl;
+ ++i;
+ continue;
+ }
+ }
+ //
+ // Now we need to scan for Boost.Preprocessor includes that
+ // are included via preprocessor iteration:
+ //
+ static const boost::regex ppfiles("^[[:blank:]]*#[[:blank:]]*define[[:blank:]]+(?:BOOST_PP_FILENAME|BOOST_PP_ITERATION_PARAMS|BOOST_PP_INDIRECT_SELF)(?:[^\\n]|\\\\\\n)+?[\"<]([^\">]+)[\">]");
+ i = boost::regex_token_iterator<const char*>(view.begin(), view.end(), ppfiles, 1);
+ while(i != j)
+ {
+ //
+ // *i contains the name of the include file,
+ // check first for a file of that name in the
+ // same directory as the file we are scanning,
+ // and if that fails, then check the boost-root:
+ //
+ fs::path include_file;
+ try{
+ include_file = i->str();
+ }
+ catch(const fs::filesystem_error&)
+ {
+ std::cerr << "Can't parse filename " << *i << " included by file " << p.string() << std::endl;
+ ++i;
+ continue;
+ }
+ fs::path test_file(m_boost_path / p.branch_path() / include_file);
+ if(fs::exists(test_file) && !fs::is_directory(test_file) && (p.branch_path().string() != "boost"))
+ {
+ if(!m_dependencies.count(p.branch_path() / include_file))
+ {
+ m_dependencies[p.branch_path() / include_file] = p;
+ add_path(p.branch_path() / include_file);
+ }
+ }
+ else if(fs::exists(m_boost_path / include_file))
+ {
+ if(!m_dependencies.count(include_file))
+ {
+ m_dependencies[include_file] = p;
+ add_path(include_file);
+ }
+ }
+ else
+ {
+ std::cerr << "CAUTION: Boost.Preprocessor iterated file " << include_file.string() << " does not exist." << std::endl;
+ }
+ ++i;
+ }
+
+ //
+ // Scan for any #include MACRO includes that we don't recognise.
+ //
+ // Begin by declaring all of the macros that get #included that
+ // we know about and are correctly handled as special cases:
+ //
+ static const std::string known_macros[] = {
+ "AUX778076_INCLUDE_STRING",
+ "BOOST_PP_STRINGIZE(boost/mpl/aux_/preprocessed/AUX778076_PREPROCESSED_HEADER)",
+ "BOOST_USER_CONFIG",
+ "BOOST_COMPILER_CONFIG",
+ "BOOST_STDLIB_CONFIG",
+ "BOOST_PLATFORM_CONFIG",
+ "BOOST_PP_FILENAME_1",
+ "BOOST_PP_ITERATION_PARAMS_1",
+ "BOOST_PP_FILENAME_2",
+ "BOOST_PP_ITERATION_PARAMS_2",
+ "BOOST_PP_FILENAME_3",
+ "BOOST_PP_ITERATION_PARAMS_3",
+ "BOOST_PP_FILENAME_4",
+ "BOOST_PP_ITERATION_PARAMS_4",
+ "BOOST_PP_FILENAME_5",
+ "BOOST_PP_ITERATION_PARAMS_5",
+ "BOOST_PP_INDIRECT_SELF",
+ "BOOST_PP_INCLUDE_SELF()",
+ "BOOST_PP_ITERATE",
+ "BOOST_PP_LOCAL_ITERATE",
+ "BOOST_PP_ITERATE()",
+ "BOOST_PP_LOCAL_ITERATE()",
+ "BOOST_PP_ASSIGN_SLOT(1)",
+ "BOOST_PP_ASSIGN_SLOT(2)",
+ "BOOST_PP_ASSIGN_SLOT(3)",
+ "BOOST_PP_ASSIGN_SLOT(4)",
+ "BOOST_PP_ASSIGN_SLOT(5)",
+ "BOOST_ABI_PREFIX",
+ "BOOST_ABI_SUFFIX",
+ "BOOST_PP_STRINGIZE(boost/mpl/aux_/preprocessed/AUX_PREPROCESSED_HEADER)",
+ "BOOST_PP_STRINGIZE(boost/mpl/list/AUX778076_HEADER)",
+ "BOOST_PP_STRINGIZE(boost/mpl/list/AUX778076_LIST_C_HEADER)",
+ "BOOST_PP_STRINGIZE(boost/mpl/list/AUX778076_LIST_HEADER)",
+ "BOOST_PP_STRINGIZE(boost/mpl/map/aux_/preprocessed/AUX778076_HEADER)",
+ "BOOST_PP_STRINGIZE(boost/mpl/map/AUX778076_MAP_HEADER)",
+ "BOOST_PP_STRINGIZE(boost/mpl/set/aux_/preprocessed/AUX778076_HEADER)",
+ "BOOST_PP_STRINGIZE(boost/mpl/set/AUX778076_SET_HEADER)",
+ "BOOST_PP_STRINGIZE(boost/mpl/set/AUX778076_SET_C_HEADER)",
+ "BOOST_PP_STRINGIZE(boost/mpl/vector/AUX778076_VECTOR_HEADER)",
+ "BOOST_PP_STRINGIZE(boost/mpl/vector/aux_/preprocessed/AUX778076_HEADER)",
+ "BOOST_PP_STRINGIZE(boost/mpl/vector/AUX778076_DEQUE_HEADER)",
+ "BOOST_PP_STRINGIZE(boost/mpl/vector/AUX778076_VECTOR_C_HEADER)",
+ "BOOST_REGEX_USER_CONFIG",
+ "BGL_PYTHON_EVENTS_HEADER",
+ "B1",
+ "B2",
+ "BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()",
+ "BOOST_SLIST_HEADER",
+ "BOOST_HASH_SET_HEADER",
+ "BOOST_HASH_MAP_HEADER",
+ "BOOST_INTRUSIVE_INVARIANT_ASSERT_INCLUDE",
+ "BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT_INCLUDE",
+ "BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT_INCLUDE",
+ "BOOST_FT_loop",
+ "BOOST_FT_AL_PREPROCESSED",
+ "BOOST_FT_AL_INCLUDE_FILE",
+ "__FILE__",
+ "BOOST_FT_cc_file",
+ "BOOST_FT_variate_file",
+ "BOOST_USER_CONFIG",
+ "BOOST_HEADER()",
+ "BOOST_TR1_STD_HEADER(utility)",
+ "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(tuple))",
+ "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(random))",
+ "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(array))",
+ "BOOST_TR1_HEADER(cmath)",
+ "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(complex))",
+ "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(functional))",
+ "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(memory))",
+ "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(regex))",
+ "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(type_traits))",
+ "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(unordered_map))",
+ "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(unordered_set))",
+ "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(utility))",
+ "BOOST_PROTO_LOCAL_ITERATE()",
+ "BOOST_SIGNAL_FUNCTION_N_HEADER",
+ "BOOST_PP_UPDATE_COUNTER()",
+ };
+
+ static const boost::regex indirect_includes("^[[:blank:]]*#[[:blank:]]*include[[:blank:]]+([^\"<][^\n]*?)[[:blank:]]*$");
+ i = boost::regex_token_iterator<const char*>(view.begin(), view.end(), indirect_includes, 1);
+ while(i != j)
+ {
+ const std::string* known_macros_end = known_macros + sizeof(known_macros)/sizeof(known_macros[0]);
+ if(known_macros_end == std::find(known_macros, known_macros_end, i->str()))
+ {
+ std::cerr << "CAUTION: don't know how to trace depenencies through macro: \"" << *i << "\" in file: " << p.string() << std::endl;
+ }
+ ++i;
+ }
+ //
+ // if the file contains a cpp_main / unit_test_main / test_main
+ // it is dependent upon Boost.test even if it doesn't
+ // include any of the Boost.test headers directly.
+ //
+ static const boost::regex m("^\\s*int\\s+(?:cpp_main|test_main|unit_test_main)");
+ boost::cmatch what;
+ if(boost::regex_search(view.begin(), view.end(), what, m))
+ {
+ add_dependent_lib("test", p, view);
+ }
+ if(!scanfile)
+ {
+ //
+ // grab the name of the library to which the header belongs,
+ // and if that library has source then add the source to our
+ // list:
+ //
+ // this regex catches boost/libname.hpp or boost/libname/whatever:
+ //
+ static const boost::regex lib1("boost/([^\\./]+)(?!detail).*");
+ boost::smatch swhat;
+ std::string gs(p.generic_string());
+ if(boost::regex_match(gs, swhat, lib1))
+ {
+ add_dependent_lib(swhat.str(1), p, view);
+ }
+ //
+ // and this one catches boost/x/y/whatever (for example numeric/ublas):
+ //
+ static const boost::regex lib2("boost/([^/]+/[^/]+)/(?!detail).*");
+ gs = p.generic_string();
+ if(boost::regex_match(gs, swhat, lib2))
+ {
+ add_dependent_lib(swhat.str(1), p, view);
+ }
+ }
+ if(m_list_namespaces)
+ {
+ //
+ // scan for top level namespaces and add to our list:
+ //
+ static const boost::regex namespace_scanner(
+ "^(?<!\\\\\\n)[[:blank:]]*+namespace\\s++(\\w++)\\s++(\\{[^{}]*(?:(?2)[^{}]*)*\\})"
+ );
+ i = boost::regex_token_iterator<const char*>(view.begin(), view.end(), namespace_scanner, 1);
+ while(i != j)
+ {
+ if(m_top_namespaces.count(*i) == 0)
+ {
+ //std::cout << *i << " (Found in " << p << ")" << std::endl;
+ m_top_namespaces[*i] = p;
+ }
+ ++i;
+ }
+ }
+}
diff --git a/tools/bcp/bcp.hpp b/tools/bcp/bcp.hpp
new file mode 100644
index 000000000..bec63641c
--- /dev/null
+++ b/tools/bcp/bcp.hpp
@@ -0,0 +1,47 @@
+/*
+ *
+ * Copyright (c) 2003 Dr John Maddock
+ * Use, modification and distribution is 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)
+ *
+ */
+
+#include <boost/shared_ptr.hpp>
+
+#if defined(BOOST_FILESYSTEM_VERSION) && (BOOST_FILESYSTEM_VERSION != 3)
+# error "This library must be built with Boost.Filesystem version 3"
+#else
+#define BOOST_FILESYSTEM_VERSION 3
+#endif
+
+class bcp_application;
+typedef boost::shared_ptr<bcp_application> pbcp_application;
+
+class bcp_application
+{
+public:
+ virtual ~bcp_application();
+
+ virtual void enable_list_mode() = 0;
+ virtual void enable_summary_list_mode() = 0;
+ virtual void enable_cvs_mode() = 0;
+ virtual void enable_svn_mode() = 0;
+ virtual void enable_unix_lines() = 0;
+ virtual void enable_scan_mode() = 0;
+ virtual void enable_license_mode() = 0;
+ virtual void enable_bsl_convert_mode() = 0;
+ virtual void enable_bsl_summary_mode() = 0;
+ virtual void set_boost_path(const char* p) = 0;
+ virtual void set_destination(const char* p) = 0;
+ virtual void add_module(const char* p) = 0;
+ virtual void set_namespace(const char* name) = 0;
+ virtual void set_namespace_alias(bool) = 0;
+ virtual void set_namespace_list(bool) = 0;
+
+ virtual int run() = 0;
+
+ static pbcp_application create();
+};
+
+
diff --git a/tools/bcp/bcp_imp.cpp b/tools/bcp/bcp_imp.cpp
new file mode 100644
index 000000000..cfce21576
--- /dev/null
+++ b/tools/bcp/bcp_imp.cpp
@@ -0,0 +1,295 @@
+/*
+ *
+ * Copyright (c) 2003 Dr John Maddock
+ * Use, modification and distribution is 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)
+ *
+ * This file implements the bcp_implementation virtuals.
+ */
+
+#include "bcp_imp.hpp"
+#include "licence_info.hpp"
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/fstream.hpp>
+#include <iostream>
+#include <stdexcept>
+#include <boost/regex.hpp>
+#include <string>
+
+bcp_implementation::bcp_implementation()
+ : m_list_mode(false), m_list_summary_mode(false), m_license_mode(false), m_cvs_mode(false),
+ m_svn_mode(false), m_unix_lines(false), m_scan_mode(false), m_bsl_convert_mode(false),
+ m_bsl_summary_mode(false), m_namespace_alias(false), m_list_namespaces(false)
+{
+}
+
+bcp_implementation::~bcp_implementation()
+{
+}
+
+bcp_application::~bcp_application()
+{
+}
+
+void bcp_implementation::enable_list_mode()
+{
+ m_list_mode = true;
+}
+
+void bcp_implementation::enable_summary_list_mode()
+{
+ m_list_mode = true;
+ m_list_summary_mode = true;
+}
+
+void bcp_implementation::enable_cvs_mode()
+{
+ m_cvs_mode = true;
+}
+
+void bcp_implementation::enable_svn_mode()
+{
+ m_svn_mode = true;
+}
+
+void bcp_implementation::enable_scan_mode()
+{
+ m_scan_mode = true;
+}
+
+void bcp_implementation::enable_license_mode()
+{
+ m_license_mode = true;
+}
+
+void bcp_implementation::enable_bsl_convert_mode()
+{
+ m_bsl_convert_mode = true;
+}
+
+void bcp_implementation::enable_bsl_summary_mode()
+{
+ m_bsl_summary_mode = true;
+}
+
+void bcp_implementation::enable_unix_lines()
+{
+ m_unix_lines = true;
+}
+
+void bcp_implementation::set_boost_path(const char* p)
+{
+ // Hack to strip trailing slashes from the path
+ m_boost_path = (fs::path(p) / "boost").parent_path();
+ fs::path check = m_boost_path / "boost" / "version.hpp";
+ if(!fs::exists(check))
+ {
+ std::string s = "The Boost path appears to have been incorrectly set: could not find boost/version.hpp in ";
+ s += m_boost_path.string();
+ std::runtime_error e(s);
+ throw e;
+ }
+}
+
+void bcp_implementation::set_destination(const char* p)
+{
+ m_dest_path = fs::path(p);
+}
+
+void bcp_implementation::add_module(const char* p)
+{
+ m_module_list.push_back(p);
+}
+
+void bcp_implementation::set_namespace(const char* name)
+{
+ m_namespace_name = name;
+}
+
+void bcp_implementation::set_namespace_alias(bool b)
+{
+ m_namespace_alias = b;
+}
+
+void bcp_implementation::set_namespace_list(bool b)
+{
+ m_list_namespaces = b;
+ m_list_mode = b;
+}
+
+fs::path get_short_path(const fs::path& p)
+{
+ // truncate path no more than "x/y":
+ std::string s = p.generic_string();
+ std::string::size_type n = s.find('/');
+ if(n != std::string::npos)
+ {
+ n = s.find('/', n+1);
+ if(n != std::string::npos)
+ s.erase(n);
+ }
+ return s;
+}
+
+int bcp_implementation::run()
+{
+ //
+ // check output path is OK:
+ //
+ if(!m_list_mode && !m_license_mode && !fs::exists(m_dest_path))
+ {
+ std::string msg("Destination path does not exist: ");
+ msg.append(m_dest_path.string());
+ std::runtime_error e(msg);
+ boost::throw_exception(e);
+ }
+ //
+ // Check Boost path is OK if it hasn't been checked already:
+ //
+ if(m_boost_path == "")
+ {
+ set_boost_path("");
+ }
+ // start by building a list of permitted files
+ // if m_cvs_mode is true:
+ if(m_cvs_mode)
+ {
+ std::cerr << "CAUTION: Boost is no longer in CVS, cvs mode may not work anymore!!!" << std::endl;
+ scan_cvs_path(fs::path());
+ }
+ if(m_svn_mode)
+ {
+ scan_svn_path(fs::path());
+ }
+ //
+ // if in license mode, try to load more/blanket_permission.txt
+ //
+ fs::path blanket_permission(m_boost_path / "more" / "blanket-permission.txt");
+ if (fs::exists(blanket_permission)) {
+ fs::ifstream in(blanket_permission);
+ std::string line;
+ while (std::getline(in, line)) {
+ static const boost::regex e("([^(]+)\\(");
+ boost::smatch result;
+ if (boost::regex_search(line, result, e))
+ m_bsl_authors.insert(format_authors_name(result[1]));
+ }
+ }
+
+ //
+ // scan through modules looking for the equivalent
+ // file to add to our list:
+ //
+ std::list<std::string>::const_iterator i = m_module_list.begin();
+ std::list<std::string>::const_iterator j = m_module_list.end();
+ while(i != j)
+ {
+ //
+ // convert *i to a path - could be native or portable:
+ //
+ fs::path module;
+ fs::path exmodule;
+ module = fs::path(*i);
+ exmodule = fs::path(*i + ".hpp");
+
+ if(m_scan_mode)
+ {
+ // in scan mode each module must be a real file:
+ add_file_dependencies(module, true);
+ }
+ else
+ {
+ int count = 0;
+ if(fs::exists(m_boost_path / "tools" / module))
+ {
+ add_path(fs::path("tools") / module);
+ ++count;
+ }
+ if(fs::exists(m_boost_path / "libs" / module))
+ {
+ add_path(fs::path("libs") / module);
+ ++count;
+ }
+ if(fs::exists(m_boost_path / "boost" / module))
+ {
+ add_path(fs::path("boost") / module);
+ ++count;
+ }
+ if(fs::exists(m_boost_path / "boost" / exmodule))
+ {
+ add_path(fs::path("boost") / exmodule);
+ ++count;
+ }
+ if(fs::exists(m_boost_path / module))
+ {
+ add_path(module);
+ ++count;
+ }
+ }
+ ++i;
+ }
+ //
+ // now perform output:
+ //
+ if(m_list_namespaces)
+ {
+ // List the namespaces, in two lists, headers and source files
+ // first, then everything else afterwards:
+ //
+ boost::regex important_file("boost/.*|libs/[^/]*/(?:[^/]*/)?/src/.*");
+ std::map<std::string, fs::path>::const_iterator i, j;
+ i = m_top_namespaces.begin();
+ j = m_top_namespaces.end();
+ std::cout << "\n\nThe top level namespaces found for header and source files were:\n";
+ while(i != j)
+ {
+ if(regex_match(i->second.generic_string(), important_file))
+ std::cout << i->first << " (from " << i->second << ")" << std::endl;
+ ++i;
+ }
+
+ i = m_top_namespaces.begin();
+ std::cout << "\n\nThe top level namespaces found for all other source files were:\n";
+ while(i != j)
+ {
+ if(!regex_match(i->second.generic_string(), important_file))
+ std::cout << i->first << " (from " << i->second << ")" << std::endl;
+ ++i;
+ }
+ return 0;
+ }
+ std::set<fs::path, path_less>::iterator m, n;
+ std::set<fs::path, path_less> short_paths;
+ m = m_copy_paths.begin();
+ n = m_copy_paths.end();
+ if(!m_license_mode)
+ {
+ while(m != n)
+ {
+ if(m_list_summary_mode)
+ {
+ fs::path p = get_short_path(*m);
+ if(short_paths.find(p) == short_paths.end())
+ {
+ short_paths.insert(p);
+ std::cout << p.string() << "\n";
+ }
+ }
+ else if(m_list_mode)
+ std::cout << m->string() << "\n";
+ else
+ copy_path(*m);
+ ++m;
+ }
+ }
+ else
+ output_license_info();
+ return 0;
+}
+
+pbcp_application bcp_application::create()
+{
+ pbcp_application result(static_cast<bcp_application*>(new bcp_implementation()));
+ return result;
+}
diff --git a/tools/bcp/bcp_imp.hpp b/tools/bcp/bcp_imp.hpp
new file mode 100644
index 000000000..9f4591519
--- /dev/null
+++ b/tools/bcp/bcp_imp.hpp
@@ -0,0 +1,118 @@
+/*
+ *
+ * Copyright (c) 2003 Dr John Maddock
+ * Use, modification and distribution is 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)
+ *
+ */
+
+#include "bcp.hpp"
+#include <string>
+#include <cstring>
+#include <list>
+#include <set>
+#include <map>
+#include <boost/filesystem/path.hpp>
+
+namespace fs = boost::filesystem;
+
+class fileview;
+
+//
+//path operations:
+//
+int compare_paths(const fs::path& a, const fs::path& b);
+inline bool equal_paths(const fs::path& a, const fs::path& b)
+{ return compare_paths(a, b) == 0; }
+
+struct path_less
+{
+ bool operator()(const fs::path& a, const fs::path& b)const
+ { return compare_paths(a, b) < 0; }
+};
+
+struct license_data
+{
+ std::set<fs::path, path_less> files;
+ std::set<std::string> authors;
+};
+
+class bcp_implementation
+ : public bcp_application
+{
+public:
+ bcp_implementation();
+ ~bcp_implementation();
+ static bool is_source_file(const fs::path& p);
+ static bool is_html_file(const fs::path& p);
+ static bool is_jam_file(const fs::path& p);
+private:
+ //
+ // the following are the overridden virtuals from the base class:
+ //
+ void enable_list_mode();
+ void enable_summary_list_mode();
+ void enable_cvs_mode();
+ void enable_svn_mode();
+ void enable_unix_lines();
+ void enable_scan_mode();
+ void enable_license_mode();
+ void enable_bsl_convert_mode();
+ void enable_bsl_summary_mode();
+ void set_boost_path(const char* p);
+ void set_destination(const char* p);
+ void add_module(const char* p);
+ void set_namespace(const char* name);
+ void set_namespace_alias(bool);
+ void set_namespace_list(bool);
+
+ virtual int run();
+
+ // internal helper functions:
+ bool is_binary_file(const fs::path& p);
+ void scan_cvs_path(const fs::path& p);
+ void scan_svn_path(const fs::path& p);
+ void add_path(const fs::path& p);
+ void add_directory(const fs::path& p);
+ void add_file(const fs::path& p);
+ void copy_path(const fs::path& p);
+ void add_file_dependencies(const fs::path& p, bool scanfile);
+ void add_dependent_lib(const std::string& libname, const fs::path& p, const fileview& view);
+ void create_path(const fs::path& p);
+ // license code:
+ void scan_license(const fs::path& p, const fileview& v);
+ void output_license_info();
+
+ std::list<std::string> m_module_list; // the modules to process
+ bool m_list_mode; // list files only
+ bool m_list_summary_mode; // list file summary only
+ bool m_license_mode; // generate license information for files listed
+ bool m_cvs_mode; // check cvs for files
+ bool m_svn_mode; // check svn for files
+ bool m_unix_lines; // fix line endings
+ bool m_scan_mode; // scan non-boost files.
+ bool m_bsl_convert_mode; // try to convert to the BSL
+ bool m_bsl_summary_mode; // summarise BSL issues only
+ bool m_namespace_alias; // make "boost" a namespace alias when doing a namespace rename.
+ bool m_list_namespaces; // list all the top level namespaces found.
+ fs::path m_boost_path; // the path to the boost root
+ fs::path m_dest_path; // the path to copy to
+ std::map<fs::path, bool, path_less> m_cvs_paths; // valid files under cvs control
+ std::set<fs::path, path_less> m_copy_paths; // list of files to copy
+ std::map<int, license_data> m_license_data; // licenses in use
+ std::set<fs::path, path_less> m_unknown_licenses; // files with no known license
+ std::set<fs::path, path_less> m_unknown_authors; // files with no known copyright/author
+ std::set<fs::path, path_less> m_can_migrate_to_bsl; // files that can migrate to the BSL
+ std::set<fs::path, path_less> m_cannot_migrate_to_bsl; // files that cannot migrate to the BSL
+ std::set<std::string> m_bsl_authors; // authors giving blanket permission to use the BSL
+ std::set<std::string> m_authors_for_bsl_migration; // authors we need for BSL migration
+ std::map<fs::path, std::pair<std::string, std::string>, path_less>
+ m_converted_to_bsl;
+ std::map<std::string, std::set<fs::path, path_less> > m_author_data; // all the authors
+ std::map<fs::path, fs::path, path_less> m_dependencies; // dependency information
+ std::string m_namespace_name; // namespace rename.
+ std::set<std::string> m_lib_names; // List of library binary names
+ std::map<std::string, fs::path> m_top_namespaces; // List of top level namespace names
+};
+
diff --git a/tools/bcp/copy_path.cpp b/tools/bcp/copy_path.cpp
new file mode 100644
index 000000000..ded5d181c
--- /dev/null
+++ b/tools/bcp/copy_path.cpp
@@ -0,0 +1,245 @@
+/*
+ *
+ * Copyright (c) 2003 Dr John Maddock
+ * Use, modification and distribution is 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)
+ *
+ * This file implements the following:
+ * void bcp_implementation::copy_path(const fs::path& p)
+ * void bcp_implementation::create_path(const fs::path& p)
+ */
+
+#include "bcp_imp.hpp"
+#include "fileview.hpp"
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/fstream.hpp>
+#include <boost/regex.hpp>
+#include <fstream>
+#include <iterator>
+#include <algorithm>
+#include <iostream>
+
+struct get_new_library_name
+{
+ get_new_library_name(const std::string& n) : m_new_name(n) {}
+ template <class I>
+ std::string operator()(const boost::match_results<I>& what)
+ {
+ std::string s = what[0];
+ std::string::size_type n = s.find("boost");
+ if(n == std::string::npos)
+ {
+ s.insert(0, m_new_name);
+ }
+ else
+ {
+ s.replace(n, 5, m_new_name);
+ }
+ return s;
+ }
+private:
+ std::string m_new_name;
+};
+
+void bcp_implementation::copy_path(const fs::path& p)
+{
+ assert(!fs::is_directory(m_boost_path / p));
+ if(fs::exists(m_dest_path / p))
+ {
+ std::cout << "Copying (and overwriting) file: " << p.string() << "\n";
+ fs::remove(m_dest_path / p);
+ }
+ else
+ std::cout << "Copying file: " << p.string() << "\n";
+ //
+ // create the path to the new file if it doesn't already exist:
+ //
+ create_path(p.branch_path());
+ //
+ // do text based copy if requested:
+ //
+ if(p.leaf() == "Jamroot")
+ {
+ static std::vector<char> v1, v2;
+ v1.clear();
+ v2.clear();
+ boost::filesystem::ifstream is((m_boost_path / p));
+ std::copy(std::istreambuf_iterator<char>(is), std::istreambuf_iterator<char>(), std::back_inserter(v1));
+
+ static boost::regex libname_matcher;
+ if(libname_matcher.empty())
+ {
+ libname_matcher.assign("boost_");
+ }
+
+ regex_replace(std::back_inserter(v2), v1.begin(), v1.end(), libname_matcher, m_namespace_name + "_");
+ std::swap(v1, v2);
+ v2.clear();
+
+ boost::filesystem::ofstream os;
+ if(m_unix_lines)
+ os.open((m_dest_path / p), std::ios_base::binary | std::ios_base::out);
+ else
+ os.open((m_dest_path / p), std::ios_base::out);
+ os.write(&*v1.begin(), v1.size());
+ os.close();
+ }
+ else if(m_namespace_name.size() && m_lib_names.size() && is_jam_file(p))
+ {
+ static std::vector<char> v1, v2;
+ v1.clear();
+ v2.clear();
+ boost::filesystem::ifstream is((m_boost_path / p));
+ std::copy(std::istreambuf_iterator<char>(is), std::istreambuf_iterator<char>(), std::back_inserter(v1));
+
+ static boost::regex libname_matcher;
+ if(libname_matcher.empty())
+ {
+ std::string re = "\\<";
+ re += *m_lib_names.begin();
+ for(std::set<std::string>::const_iterator i = ++m_lib_names.begin(); i != m_lib_names.end(); ++i)
+ {
+ re += "|" + *i;
+ }
+ re += "\\>";
+ libname_matcher.assign(re);
+ }
+
+ regex_replace(std::back_inserter(v2), v1.begin(), v1.end(), libname_matcher, get_new_library_name(m_namespace_name));
+ std::swap(v1, v2);
+ v2.clear();
+
+ boost::filesystem::ofstream os;
+ if(m_unix_lines)
+ os.open((m_dest_path / p), std::ios_base::binary | std::ios_base::out);
+ else
+ os.open((m_dest_path / p), std::ios_base::out);
+ os.write(&*v1.begin(), v1.size());
+ os.close();
+ }
+ else if(m_namespace_name.size() && is_source_file(p))
+ {
+ //
+ // v1 hold the current content, v2 is temp buffer.
+ // Each time we do a search and replace the new content
+ // ends up in v2: we then swap v1 and v2, and clear v2.
+ //
+ static std::vector<char> v1, v2;
+ v1.clear();
+ v2.clear();
+ boost::filesystem::ifstream is((m_boost_path / p));
+ std::copy(std::istreambuf_iterator<char>(is), std::istreambuf_iterator<char>(), std::back_inserter(v1));
+
+ static const boost::regex namespace_matcher(
+ "(?|"
+ "(namespace\\s+)boost(_\\w+)?(?:(\\s*::\\s*)phoenix)?"
+ "|"
+ "(namespace\\s+(?:detail::)?)(adstl|phoenix|rapidxml)\\>"
+ "|"
+ "()\\<boost((?:_(?!intrusive_tags)\\w+)?\\s*(?:::))(?:(\\s*)phoenix)?"
+ "|"
+ "()\\<((?:adstl|phoenix|rapidxml)\\s*(?:::))"
+ "|"
+ "(namespace\\s+\\w+\\s*=\\s*(?:::\\s*)?)boost(_\\w+)?(?:(\\s*::\\s*)phoenix)?"
+ "|"
+ "(namespace\\s+\\w+\\s*=\\s*(?:::\\s*)?(?:\\w+\\s*::\\s*)?)(adstl|phoenix|rapidxml)\\>"
+ "|"
+ "(^\\s*#\\s*define\\s+\\w+\\s+)boost((?:_\\w+)?\\s*)$"
+ "|"
+ "(^\\s*#\\s*define[^\\n]+)((?:adstl|phoenix|rapidxml)\\s*)$"
+ "|"
+ "()boost(_asio_detail_posix_thread_function|_regex_free_static_mutex)"
+ "|"
+ "()(lw_thread_routine|at_thread_exit|on_process_enter|on_process_exit|on_thread_enter|on_thread_exit|tss_cleanup_implemented)"
+ "|"
+ "(BOOST_CLASS_REQUIRE4?[^;]*)boost((?:_\\w+)?\\s*,)"
+ "|"
+ "(::tr1::|TR1_DECL\\s+)boost(_\\w+\\s*)" // math tr1
+ "|"
+ "(\\(\\s*)boost(\\s*\\))\\s*(\\(\\s*)phoenix(\\s*\\))"
+ "|"
+ "(\\(\\s*)boost(\\s*\\))"
+ ")"
+ );
+
+ regex_replace(std::back_inserter(v2), v1.begin(), v1.end(), namespace_matcher, "$1" + m_namespace_name + "$2(?3$3" + m_namespace_name + "phoenix?4$4)", boost::regex_constants::format_all);
+ std::swap(v1, v2);
+ v2.clear();
+
+ if(m_namespace_alias)
+ {
+ static const boost::regex namespace_alias(
+ /*
+ "namespace\\s+" + m_namespace_name +
+ "\\s*"
+ "("
+ "\\{"
+ "(?:"
+ "(?>[^\\{\\}/]+)"
+ "(?>"
+ "(?:"
+ "(?1)"
+ "|//[^\\n]+$"
+ "|/[^/]"
+ "|(?:^\\s*#[^\\n]*"
+ "(?:(?<=\\\\)\\n[^\\n]*)*)"
+ ")"
+ "[^\\{\\}]+"
+ ")*"
+ ")*"
+ "\\}"
+ ")"
+ */
+ /*
+ "(namespace\\s+" + m_namespace_name +
+ "\\s*\\{.*"
+ "\\})([^\\{\\};]*)\\z"
+ */
+ "(namespace)(\\s+)(" + m_namespace_name + ")"
+ "(adstl|phoenix|rapidxml)?(\\s*\\{)"
+ );
+ regex_replace(std::back_inserter(v2), v1.begin(), v1.end(), namespace_alias,
+ "$1 $3$4 {} $1 (?4$4:boost) = $3$4; $1$2$3$4$5", boost::regex_constants::format_all);
+ std::swap(v1, v2);
+ v2.clear();
+ }
+
+ boost::filesystem::ofstream os;
+ if(m_unix_lines)
+ os.open((m_dest_path / p), std::ios_base::binary | std::ios_base::out);
+ else
+ os.open((m_dest_path / p), std::ios_base::out);
+ if(v1.size())
+ os.write(&*v1.begin(), v1.size());
+ os.close();
+ }
+ else if(m_unix_lines && !is_binary_file(p))
+ {
+ boost::filesystem::ifstream is((m_boost_path / p));
+ std::istreambuf_iterator<char> isi(is);
+ std::istreambuf_iterator<char> end;
+
+ boost::filesystem::ofstream os((m_dest_path / p), std::ios_base::binary | std::ios_base::out);
+ std::ostreambuf_iterator<char> osi(os);
+
+ std::copy(isi, end, osi);
+ }
+ else
+ {
+ // binary copy:
+ fs::copy_file(m_boost_path / p, m_dest_path / p);
+ }
+}
+
+void bcp_implementation::create_path(const fs::path& p)
+{
+ if(!fs::exists(m_dest_path / p))
+ {
+ // recurse then create the path:
+ create_path(p.branch_path());
+ fs::create_directory(m_dest_path / p);
+ }
+}
+
+
diff --git a/tools/bcp/doc/Jamfile.v2 b/tools/bcp/doc/Jamfile.v2
new file mode 100644
index 000000000..95f18e40d
--- /dev/null
+++ b/tools/bcp/doc/Jamfile.v2
@@ -0,0 +1,18 @@
+
+# Copyright John Maddock 2005. 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)
+
+using quickbook ;
+
+xml bcp : bcp.qbk ;
+boostbook standalone
+ :
+ bcp
+ :
+ # How far down we chunk nested sections, basically all of them:
+ <xsl:param>chunk.section.depth=0
+ # Path for links to Boost:
+ <xsl:param>boost.root=../../../..
+ ;
+
diff --git a/tools/bcp/doc/bcp.qbk b/tools/bcp/doc/bcp.qbk
new file mode 100644
index 000000000..2d6b1cfed
--- /dev/null
+++ b/tools/bcp/doc/bcp.qbk
@@ -0,0 +1,212 @@
+
+[article BCP
+ [quickbook 1.4]
+ [copyright 2009 John Maddock]
+ [purpose Regular Expressions]
+ [license
+ 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])
+ ]
+ [authors [Maddock, John]]
+ [category text]
+ [/last-revision $Date: 2008-02-21 12:58:15 +0000 (Thu, 21 Feb 2008) $]
+]
+
+[section:overview Overview]
+
+The bcp utility is a tool for extracting subsets of Boost, it's useful for Boost authors who want to distribute
+their library separately from Boost, and for Boost users who want to distribute a subset of Boost with their application.
+
+bcp can also report on which parts of Boost your code is dependent on, and what licences are used by those dependencies.
+
+[endsect]
+
+[section:examples Examples]
+
+[pre
+bcp scoped_ptr /foo
+]
+
+Copies boost/scoped_ptr.hpp and dependencies to /foo.
+
+[pre
+bcp boost/regex.hpp /foo
+]
+
+Copies boost/regex.hpp and all dependencies including the regex source code (in libs/regex/src) and
+build files (in libs/regex/build) to /foo. Does not copy the regex documentation, test, or example code.
+Also does not copy the Boost.Build system.
+
+[pre
+bcp regex /foo
+]
+
+Copies the full regex lib (in libs/regex) including dependencies (such as the boost.test source required
+by the regex test programs) to /foo. Does not copy the Boost.Build system.
+
+[pre
+bcp --namespace=myboost --namespace-alias regex config build /foo
+]
+
+Copies the full regex lib (in libs\/regex) plus the config lib (libs\/config) and the build system (tools\/build)
+to \/foo including all the dependencies. Also renames the boost namespace to /myboost/ and changes the filenames
+of binary libraries to begin with the prefix "myboost" rather than "boost". The --namespace-alias option makes
+`namespace boost` an alias of the new name.
+
+[pre
+bcp --scan --boost=/boost foo.cpp bar.cpp boost
+]
+
+Scans the [non-boost] files foo.cpp and bar.cpp for boost dependencies and copies those dependencies to the sub-directory boost.
+
+[pre
+bcp --report regex.hpp boost-regex-report.html
+]
+
+Creates a HTML report called boost-regex-report.html for the boost module regex.hpp. The report contains license information, author details, and file dependencies.
+
+[endsect]
+
+[section:syntax Syntax]
+
+[section:main Behaviour Selection]
+
+[pre
+bcp --list \[options\] module-list
+]
+
+Outputs a list of all the files in module-list including dependencies.
+
+[pre
+bcp \[options\] module-list output-path
+]
+
+Copies all the files found in module-list to output-path
+
+[pre
+bcp --report \[options\] module-list html-file
+]
+
+Outputs a html report file containing:
+
+* All the licenses in effect, plus the files using each license, and the copyright holders using each license.
+* Any files with no recognizable license (please report these to the boost mailing lists).
+* Any files with no recognizable copyright holders (please report these to the boost mailing lists).
+* All the copyright holders and the files on which they hold copyright.
+* File dependency information - indicates the reason for the inclusion of any particular file in the dependencies found.
+
+[endsect]
+
+[section:options Options]
+
+[pre
+--boost=path
+]
+
+Sets the location of the boost tree to path. If this option is not provided then the current path is assumed to be
+the root directory of the Boost tree.
+
+[pre --namespace=newname ]
+
+When copying files, all occurances of the boost namespace will get renamed to "newname". Also
+renames Boost binaries to use "newname" rather than "boost" as a prefix.
+
+Often used in conjunction with the --namespace-alias option, this allows two different Boost versions to be
+used in the same program, but not in the same translation unit.
+
+[pre --namespace-alias]
+
+When used in conjunction with the --namespace option, then `namespace boost` will be declared as an alias
+of the new namespace name. This allows existing code that relies on Boost code being in `namespace boost`
+to compile unchanged, while retaining the "strong versioning" that can be achieved with a namespace change.
+
+[pre
+--scan
+]
+
+Treats the module list as a list of (probably non-boost) files to scan for boost dependencies,
+the files listed in the module list are not copied (or listed), only the boost files upon which they depend.
+
+[pre
+--svn
+]
+
+Only copy files under svn version control.
+
+[pre
+--unix-lines
+]
+
+Make sure that all copied files use Unix style line endings.
+
+[endsect]
+
+[section:module module-list]
+
+When the --scan option is not used then a list of boost files or library names to copy, this can be:
+
+# The name of a tool: for example "build" will find "tools/build".
+# The name of a library: for example "regex".
+# The title of a header: for example "scoped_ptr" will find "boost/scoped_ptr.hpp".
+# The name of a header: for example "scoped_ptr.hpp" will find "boost/scoped_ptr.hpp".
+# The name of a file: for example "boost/regex.hpp".
+
+When the --scan option is used, then a list of (probably non-boost) files to scan for boost dependencies,
+the files in the module list are not therefore copied/listed.
+
+[endsect]
+
+[section:output output-path]
+
+The path to which files will be copied (this path must exist).
+
+[endsect]
+
+[section Dependencies]
+
+File dependencies are found as follows:
+
+* C++ source files are scanned for #includes, all #includes present in the boost source tree will then be scanned for
+their dependencies and so on.
+* C++ source files are associated with the name of a library, if that library has source code
+(and possibly build data), then include that source in the dependencies.
+* C++ source files are checked for dependencies on Boost.test (for example to see if they use cpp_main as an entry point).
+* HTML files are scanned for immediate dependencies (images and style sheets, but not links).
+
+It should be noted that in practice bcp can produce a rather "fat" list of dependencies, reasons for this include:
+
+* It searches for library names first, so using "regex" as a name will give you everything in the
+libs/regex directory and everything that depends on. This can be a long list as all the regex test and example
+programs will get scanned for their dependencies. If you want a more minimal list, then try using the
+names of the headers you are actually including, or use the --scan option to scan your source code.
+* If you include the header of a library with separate source, then you get that libraries source and all
+it's dependencies. This is deliberate and in general those extra dependencies are needed.
+* When you include a header, bcp doesn't know what compiler you're using, so it follows all
+possible preprocessor paths. If you're distributing a subset of Boost with you're application then that
+is what you want to have happen in general.
+
+The last point above can result in a substantial increase in the number of headers found compared to most
+peoples expectations. For example bcp finds 274 header dependencies for boost/shared_ptr.hpp: by
+running bcp in report mode we can see why all these headers have been found as dependencies:
+
+* All of the Config library headers get included (52 headers, would be about 6 for one compiler only).
+* A lot of MPL and type traits code that includes workarounds for broken compilers that you may or may not need.
+Tracing back through the code shows that most of these aren't needed unless the user has
+defined BOOST_SP_USE_QUICK_ALLOCATOR, however bcp isn't aware of whether that preprocessor path will be
+taken or not, so the headers get included just in case. This adds about 48 headers (type traits), plus another 49 from MPL.
+* The Preprocessor library gets used heavily by MPL: this adds another 96 headers.
+* The Shared Pointer library contains a lot of platform specific code, split up into around 22 headers:
+normally your compiler would need only a couple of these files.
+
+As you can see the number of dependencies found are much larger than those used by any single compiler,
+however if you want to distribute a subset of Boost that's usable in any configuration, by any compiler,
+on any platform then that's exactly what you need. If you want to figure out which Boost headers are
+being used by your specific compiler then the best way to find out is to prepocess the code and scan
+the output for boost header includes. You should be aware that the result will be very platform and compiler
+specific, and may not contain all the headers needed if you so much as change a compiler switch
+(for example turn on threading support).
+
+[endsect]
+[endsect]
+
diff --git a/tools/bcp/doc/html/index.html b/tools/bcp/doc/html/index.html
new file mode 100644
index 000000000..bf59356f0
--- /dev/null
+++ b/tools/bcp/doc/html/index.html
@@ -0,0 +1,356 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
+<title>BCP</title>
+<link rel="stylesheet" href="../../../../doc/src/boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.77.1">
+<link rel="home" href="index.html" title="BCP">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%"><tr>
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../boost.png"></td>
+<td align="center"><a href="../../../../index.html">Home</a></td>
+<td align="center"><a href="../../../../libs/libraries.htm">Libraries</a></td>
+<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
+<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
+<td align="center"><a href="../../../../more/index.htm">More</a></td>
+</tr></table>
+<hr>
+<div class="spirit-nav"></div>
+<div class="article">
+<div class="titlepage">
+<div>
+<div><h2 class="title">
+<a name="bcp"></a>BCP</h2></div>
+<div><div class="authorgroup"><div class="author"><h3 class="author">
+<span class="firstname">John</span> <span class="surname">Maddock</span>
+</h3></div></div></div>
+<div><p class="copyright">Copyright &#169; 2009 John Maddock</p></div>
+<div><div class="legalnotice">
+<a name="bcp.legal"></a><p>
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
+ </p>
+</div></div>
+</div>
+<hr>
+</div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><span class="section"><a href="index.html#bcp.overview">Overview</a></span></dt>
+<dt><span class="section"><a href="index.html#bcp.examples">Examples</a></span></dt>
+<dt><span class="section"><a href="index.html#bcp.syntax">Syntax</a></span></dt>
+<dd><dl>
+<dt><span class="section"><a href="index.html#bcp.syntax.main">Behaviour Selection</a></span></dt>
+<dt><span class="section"><a href="index.html#bcp.syntax.options">Options</a></span></dt>
+<dt><span class="section"><a href="index.html#bcp.syntax.module">module-list</a></span></dt>
+<dt><span class="section"><a href="index.html#bcp.syntax.output">output-path</a></span></dt>
+<dt><span class="section"><a href="index.html#bcp.syntax.dependencies">Dependencies</a></span></dt>
+</dl></dd>
+</dl>
+</div>
+<div class="section bcp_overview">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="bcp.overview"></a><a class="link" href="index.html#bcp.overview" title="Overview">Overview</a>
+</h2></div></div></div>
+<p>
+ The bcp utility is a tool for extracting subsets of Boost, it's useful for
+ Boost authors who want to distribute their library separately from Boost, and
+ for Boost users who want to distribute a subset of Boost with their application.
+ </p>
+<p>
+ bcp can also report on which parts of Boost your code is dependent on, and
+ what licences are used by those dependencies.
+ </p>
+</div>
+<div class="section bcp_examples">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="bcp.examples"></a><a class="link" href="index.html#bcp.examples" title="Examples">Examples</a>
+</h2></div></div></div>
+<pre class="programlisting">bcp scoped_ptr /foo
+</pre>
+<p>
+ Copies boost/scoped_ptr.hpp and dependencies to /foo.
+ </p>
+<pre class="programlisting">bcp boost/regex.hpp /foo
+</pre>
+<p>
+ Copies boost/regex.hpp and all dependencies including the regex source code
+ (in libs/regex/src) and build files (in libs/regex/build) to /foo. Does not
+ copy the regex documentation, test, or example code. Also does not copy the
+ Boost.Build system.
+ </p>
+<pre class="programlisting">bcp regex /foo
+</pre>
+<p>
+ Copies the full regex lib (in libs/regex) including dependencies (such as the
+ boost.test source required by the regex test programs) to /foo. Does not copy
+ the Boost.Build system.
+ </p>
+<pre class="programlisting">bcp --namespace=myboost --namespace-alias regex config build /foo
+</pre>
+<p>
+ Copies the full regex lib (in libs/regex) plus the config lib (libs/config)
+ and the build system (tools/build) to /foo including all the dependencies.
+ Also renames the boost namespace to <span class="emphasis"><em>myboost</em></span> and changes
+ the filenames of binary libraries to begin with the prefix "myboost"
+ rather than "boost". The --namespace-alias option makes <code class="computeroutput"><span class="keyword">namespace</span> <span class="identifier">boost</span></code>
+ an alias of the new name.
+ </p>
+<pre class="programlisting">bcp --scan --boost=/boost foo.cpp bar.cpp boost
+</pre>
+<p>
+ Scans the [non-boost] files foo.cpp and bar.cpp for boost dependencies and
+ copies those dependencies to the sub-directory boost.
+ </p>
+<pre class="programlisting">bcp --report regex.hpp boost-regex-report.html
+</pre>
+<p>
+ Creates a HTML report called boost-regex-report.html for the boost module regex.hpp.
+ The report contains license information, author details, and file dependencies.
+ </p>
+</div>
+<div class="section bcp_syntax">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="bcp.syntax"></a><a class="link" href="index.html#bcp.syntax" title="Syntax">Syntax</a>
+</h2></div></div></div>
+<div class="toc"><dl>
+<dt><span class="section"><a href="index.html#bcp.syntax.main">Behaviour Selection</a></span></dt>
+<dt><span class="section"><a href="index.html#bcp.syntax.options">Options</a></span></dt>
+<dt><span class="section"><a href="index.html#bcp.syntax.module">module-list</a></span></dt>
+<dt><span class="section"><a href="index.html#bcp.syntax.output">output-path</a></span></dt>
+<dt><span class="section"><a href="index.html#bcp.syntax.dependencies">Dependencies</a></span></dt>
+</dl></div>
+<div class="section bcp_syntax_main">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="bcp.syntax.main"></a><a class="link" href="index.html#bcp.syntax.main" title="Behaviour Selection">Behaviour Selection</a>
+</h3></div></div></div>
+<pre class="programlisting">bcp --list [options] module-list
+</pre>
+<p>
+ Outputs a list of all the files in module-list including dependencies.
+ </p>
+<pre class="programlisting">bcp [options] module-list output-path
+</pre>
+<p>
+ Copies all the files found in module-list to output-path
+ </p>
+<pre class="programlisting">bcp --report [options] module-list html-file
+</pre>
+<p>
+ Outputs a html report file containing:
+ </p>
+<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
+<li class="listitem">
+ All the licenses in effect, plus the files using each license, and the
+ copyright holders using each license.
+ </li>
+<li class="listitem">
+ Any files with no recognizable license (please report these to the boost
+ mailing lists).
+ </li>
+<li class="listitem">
+ Any files with no recognizable copyright holders (please report these
+ to the boost mailing lists).
+ </li>
+<li class="listitem">
+ All the copyright holders and the files on which they hold copyright.
+ </li>
+<li class="listitem">
+ File dependency information - indicates the reason for the inclusion
+ of any particular file in the dependencies found.
+ </li>
+</ul></div>
+</div>
+<div class="section bcp_syntax_options">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="bcp.syntax.options"></a><a class="link" href="index.html#bcp.syntax.options" title="Options">Options</a>
+</h3></div></div></div>
+<pre class="programlisting">--boost=path
+</pre>
+<p>
+ Sets the location of the boost tree to path. If this option is not provided
+ then the current path is assumed to be the root directory of the Boost tree.
+ </p>
+<pre class="programlisting">--namespace=newname </pre>
+<p>
+ When copying files, all occurances of the boost namespace will get renamed
+ to "newname". Also renames Boost binaries to use "newname"
+ rather than "boost" as a prefix.
+ </p>
+<p>
+ Often used in conjunction with the --namespace-alias option, this allows
+ two different Boost versions to be used in the same program, but not in the
+ same translation unit.
+ </p>
+<pre class="programlisting">--namespace-alias</pre>
+<p>
+ When used in conjunction with the --namespace option, then <code class="computeroutput"><span class="keyword">namespace</span> <span class="identifier">boost</span></code>
+ will be declared as an alias of the new namespace name. This allows existing
+ code that relies on Boost code being in <code class="computeroutput"><span class="keyword">namespace</span>
+ <span class="identifier">boost</span></code> to compile unchanged, while
+ retaining the "strong versioning" that can be achieved with a namespace
+ change.
+ </p>
+<pre class="programlisting">--scan
+</pre>
+<p>
+ Treats the module list as a list of (probably non-boost) files to scan for
+ boost dependencies, the files listed in the module list are not copied (or
+ listed), only the boost files upon which they depend.
+ </p>
+<pre class="programlisting">--svn
+</pre>
+<p>
+ Only copy files under svn version control.
+ </p>
+<pre class="programlisting">--unix-lines
+</pre>
+<p>
+ Make sure that all copied files use Unix style line endings.
+ </p>
+</div>
+<div class="section bcp_syntax_module">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="bcp.syntax.module"></a><a class="link" href="index.html#bcp.syntax.module" title="module-list">module-list</a>
+</h3></div></div></div>
+<p>
+ When the --scan option is not used then a list of boost files or library
+ names to copy, this can be:
+ </p>
+<div class="orderedlist"><ol class="orderedlist" type="1">
+<li class="listitem">
+ The name of a tool: for example "build" will find "tools/build".
+ </li>
+<li class="listitem">
+ The name of a library: for example "regex".
+ </li>
+<li class="listitem">
+ The title of a header: for example "scoped_ptr" will find "boost/scoped_ptr.hpp".
+ </li>
+<li class="listitem">
+ The name of a header: for example "scoped_ptr.hpp" will find
+ "boost/scoped_ptr.hpp".
+ </li>
+<li class="listitem">
+ The name of a file: for example "boost/regex.hpp".
+ </li>
+</ol></div>
+<p>
+ When the --scan option is used, then a list of (probably non-boost) files
+ to scan for boost dependencies, the files in the module list are not therefore
+ copied/listed.
+ </p>
+</div>
+<div class="section bcp_syntax_output">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="bcp.syntax.output"></a><a class="link" href="index.html#bcp.syntax.output" title="output-path">output-path</a>
+</h3></div></div></div>
+<p>
+ The path to which files will be copied (this path must exist).
+ </p>
+</div>
+<div class="section bcp_syntax_dependencies">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="bcp.syntax.dependencies"></a><a class="link" href="index.html#bcp.syntax.dependencies" title="Dependencies">Dependencies</a>
+</h3></div></div></div>
+<p>
+ File dependencies are found as follows:
+ </p>
+<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
+<li class="listitem">
+ C++ source files are scanned for #includes, all #includes present in
+ the boost source tree will then be scanned for their dependencies and
+ so on.
+ </li>
+<li class="listitem">
+ C++ source files are associated with the name of a library, if that library
+ has source code (and possibly build data), then include that source in
+ the dependencies.
+ </li>
+<li class="listitem">
+ C++ source files are checked for dependencies on Boost.test (for example
+ to see if they use cpp_main as an entry point).
+ </li>
+<li class="listitem">
+ HTML files are scanned for immediate dependencies (images and style sheets,
+ but not links).
+ </li>
+</ul></div>
+<p>
+ It should be noted that in practice bcp can produce a rather "fat"
+ list of dependencies, reasons for this include:
+ </p>
+<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
+<li class="listitem">
+ It searches for library names first, so using "regex" as a
+ name will give you everything in the libs/regex directory and everything
+ that depends on. This can be a long list as all the regex test and example
+ programs will get scanned for their dependencies. If you want a more
+ minimal list, then try using the names of the headers you are actually
+ including, or use the --scan option to scan your source code.
+ </li>
+<li class="listitem">
+ If you include the header of a library with separate source, then you
+ get that libraries source and all it's dependencies. This is deliberate
+ and in general those extra dependencies are needed.
+ </li>
+<li class="listitem">
+ When you include a header, bcp doesn't know what compiler you're using,
+ so it follows all possible preprocessor paths. If you're distributing
+ a subset of Boost with you're application then that is what you want
+ to have happen in general.
+ </li>
+</ul></div>
+<p>
+ The last point above can result in a substantial increase in the number of
+ headers found compared to most peoples expectations. For example bcp finds
+ 274 header dependencies for boost/shared_ptr.hpp: by running bcp in report
+ mode we can see why all these headers have been found as dependencies:
+ </p>
+<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
+<li class="listitem">
+ All of the Config library headers get included (52 headers, would be
+ about 6 for one compiler only).
+ </li>
+<li class="listitem">
+ A lot of MPL and type traits code that includes workarounds for broken
+ compilers that you may or may not need. Tracing back through the code
+ shows that most of these aren't needed unless the user has defined BOOST_SP_USE_QUICK_ALLOCATOR,
+ however bcp isn't aware of whether that preprocessor path will be taken
+ or not, so the headers get included just in case. This adds about 48
+ headers (type traits), plus another 49 from MPL.
+ </li>
+<li class="listitem">
+ The Preprocessor library gets used heavily by MPL: this adds another
+ 96 headers.
+ </li>
+<li class="listitem">
+ The Shared Pointer library contains a lot of platform specific code,
+ split up into around 22 headers: normally your compiler would need only
+ a couple of these files.
+ </li>
+</ul></div>
+<p>
+ As you can see the number of dependencies found are much larger than those
+ used by any single compiler, however if you want to distribute a subset of
+ Boost that's usable in any configuration, by any compiler, on any platform
+ then that's exactly what you need. If you want to figure out which Boost
+ headers are being used by your specific compiler then the best way to find
+ out is to prepocess the code and scan the output for boost header includes.
+ You should be aware that the result will be very platform and compiler specific,
+ and may not contain all the headers needed if you so much as change a compiler
+ switch (for example turn on threading support).
+ </p>
+</div>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"><p><small>Last revised: April 18, 2013 at 12:30:13 GMT</small></p></td>
+<td align="right"><div class="copyright-footer"></div></td>
+</tr></table>
+<hr>
+<div class="spirit-nav"></div>
+</body>
+</html>
diff --git a/tools/bcp/file_types.cpp b/tools/bcp/file_types.cpp
new file mode 100644
index 000000000..297d304cf
--- /dev/null
+++ b/tools/bcp/file_types.cpp
@@ -0,0 +1,72 @@
+/*
+ *
+ * Copyright (c) 2003 Dr John Maddock
+ * Use, modification and distribution is 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)
+ *
+ * This file implements the following:
+ * void bcp_implementation::is_source_file(const fs::path& p)
+ * void bcp_implementation::is_html_file(const fs::path& p)
+ * void bcp_implementation::is_binary_file(const fs::path& p)
+ */
+
+#include "bcp_imp.hpp"
+#include <boost/regex.hpp>
+
+bool bcp_implementation::is_source_file(const fs::path& p)
+{
+ static const boost::regex e(
+ ".*\\."
+ "(?:"
+ "c|cxx|h|hxx|inc|inl|.?pp|yy?"
+ ")",
+ boost::regex::perl | boost::regex::icase
+ );
+ return boost::regex_match(p.filename().generic_string(), e);
+}
+
+bool bcp_implementation::is_html_file(const fs::path& p)
+{
+ static const boost::regex e(
+ ".*\\."
+ "(?:"
+ "html?|css"
+ ")"
+ );
+ return boost::regex_match(p.filename().generic_string(), e);
+}
+
+bool bcp_implementation::is_binary_file(const fs::path& p)
+{
+ if(m_cvs_mode || m_svn_mode)
+ {
+ std::map<fs::path, bool, path_less>::iterator pos = m_cvs_paths.find(p);
+ if(pos != m_cvs_paths.end()) return pos->second;
+ }
+ static const boost::regex e(
+ ".*\\."
+ "(?:"
+ "c|cxx|cpp|h|hxx|hpp|inc|html?|css|mak|in"
+ ")"
+ "|"
+ "(Jamfile|makefile|configure)",
+ boost::regex::perl | boost::regex::icase);
+ return !boost::regex_match(p.leaf().generic_string(), e);
+
+}
+
+bool bcp_implementation::is_jam_file(const fs::path& p)
+{
+ static const boost::regex e(
+ ".*\\."
+ "(?:"
+ "jam|v2"
+ ")"
+ "|"
+ "(Jamfile|Jamroot)\\.?",
+ boost::regex::perl | boost::regex::icase
+ );
+ return boost::regex_match(p.filename().generic_string(), e);
+}
+
diff --git a/tools/bcp/fileview.cpp b/tools/bcp/fileview.cpp
new file mode 100644
index 000000000..36e785062
--- /dev/null
+++ b/tools/bcp/fileview.cpp
@@ -0,0 +1,143 @@
+/*
+ *
+ * Copyright (c) 2003 Dr John Maddock
+ * Use, modification and distribution is 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)
+ *
+ * This file implements the fileview class
+ */
+
+#include "fileview.hpp"
+#include <boost/filesystem/fstream.hpp>
+#include <vector>
+#include <algorithm>
+#include <string>
+#include <fstream>
+#include <istream>
+#include <stdexcept>
+
+struct fileview::implementation
+{
+ std::vector<char> m_data;
+};
+
+
+// construct:
+fileview::fileview()
+{
+ pimpl.reset(new implementation());
+}
+
+fileview::fileview(const boost::filesystem::path& p)
+{
+ pimpl.reset(new implementation());
+ open(p);
+}
+
+fileview::~fileview()
+{
+}
+
+fileview::fileview(const fileview& )
+{
+}
+
+fileview& fileview::operator=(const fileview& that)
+{
+ pimpl = that.pimpl;
+ return *this;
+}
+
+void fileview::close()
+{
+ cow();
+ pimpl->m_data.clear();
+}
+
+void fileview::open(const boost::filesystem::path& p)
+{
+ cow();
+ boost::filesystem::ifstream is(p);
+ if(!is)
+ {
+ std::string msg("Bad file name: ");
+ msg += p.string();
+ std::runtime_error e(msg);
+ boost::throw_exception(e);
+ }
+ std::istreambuf_iterator<char> in(is);
+ std::istreambuf_iterator<char> end;
+ std::copy(in, end, std::back_inserter(pimpl->m_data));
+}
+
+// iterators:
+fileview::const_iterator fileview::begin() const
+{
+ return pimpl->m_data.size() ? &(pimpl->m_data[0]) : 0;
+}
+
+fileview::const_iterator fileview::end() const
+{
+ return begin() + pimpl->m_data.size();
+}
+
+#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+fileview::const_reverse_iterator fileview::rbegin() const
+{
+ return const_reverse_iterator(end());
+}
+
+fileview::const_reverse_iterator fileview::rend() const
+{
+ return const_reverse_iterator(begin());
+}
+#endif
+
+// capacity:
+fileview::size_type fileview::size() const
+{
+ return pimpl->m_data.size();
+}
+
+fileview::size_type fileview::max_size() const
+{
+ return pimpl->m_data.max_size();
+}
+
+bool fileview::empty() const
+{
+ return pimpl->m_data.empty();
+}
+
+// element access:
+fileview::const_reference fileview::operator[](fileview::size_type n) const
+{
+ return pimpl->m_data[n];
+}
+
+fileview::const_reference fileview::at(size_type n) const
+{
+ return pimpl->m_data.at(n);
+}
+
+fileview::const_reference fileview::front() const
+{
+ return pimpl->m_data.front();
+}
+
+fileview::const_reference fileview::back() const
+{
+ return pimpl->m_data.back();
+}
+
+void fileview::swap(fileview& that)
+{
+ pimpl.swap(that.pimpl);
+}
+
+void fileview::cow()
+{
+ if(!pimpl.unique())
+ pimpl.reset(new implementation(*pimpl));
+}
diff --git a/tools/bcp/fileview.hpp b/tools/bcp/fileview.hpp
new file mode 100644
index 000000000..fe76f84ea
--- /dev/null
+++ b/tools/bcp/fileview.hpp
@@ -0,0 +1,72 @@
+/*
+ *
+ * Copyright (c) 2003 Dr John Maddock
+ * Use, modification and distribution is 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)
+ *
+ */
+
+#if defined(BOOST_FILESYSTEM_VERSION) && (BOOST_FILESYSTEM_VERSION != 3)
+# error "This library must be built with Boost.Filesystem version 3"
+#else
+#define BOOST_FILESYSTEM_VERSION 3
+#endif
+
+#include <boost/shared_ptr.hpp>
+#include <boost/filesystem/path.hpp>
+
+class fileview
+{
+public:
+ // types:
+ typedef const char& reference;
+ typedef reference const_reference;
+ typedef const char* iterator; // See _lib.container.requirements_
+ typedef iterator const_iterator; // See _lib.container.requirements_
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef char value_type;
+ typedef const char* pointer;
+ typedef pointer const_pointer;
+#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+#endif
+
+ // construct:
+ fileview();
+ fileview(const boost::filesystem::path& p);
+ ~fileview();
+ fileview(const fileview& that);
+ fileview& operator=(const fileview& that);
+ void close();
+ void open(const boost::filesystem::path& p);
+
+ // iterators:
+ const_iterator begin() const;
+ const_iterator end() const;
+#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+ const_reverse_iterator rbegin() const;
+ const_reverse_iterator rend() const;
+#endif
+
+ // capacity:
+ size_type size() const;
+ size_type max_size() const;
+ bool empty() const;
+
+ // element access:
+ const_reference operator[](size_type n) const;
+ const_reference at(size_type n) const;
+ const_reference front() const;
+ const_reference back() const;
+ void swap(fileview& that);
+
+private:
+ void cow();
+ struct implementation;
+ boost::shared_ptr<implementation> pimpl;
+};
+
+
diff --git a/tools/bcp/index.html b/tools/bcp/index.html
new file mode 100644
index 000000000..34e938c60
--- /dev/null
+++ b/tools/bcp/index.html
@@ -0,0 +1,17 @@
+<html>
+ <head>
+ <meta http-equiv="refresh" content="0; URL=doc/html/index.html">
+ </head>
+ <body>
+ <p>
+ Automatic redirection failed, please go to <a href="doc/html/index.html">doc/html/index.html</a>.
+ </p>
+ <p>Copyright&nbsp;John Maddock 2007</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>
+
+
+
+
diff --git a/tools/bcp/licence_info.cpp b/tools/bcp/licence_info.cpp
new file mode 100644
index 000000000..0e527fa48
--- /dev/null
+++ b/tools/bcp/licence_info.cpp
@@ -0,0 +1,721 @@
+/*
+ *
+ * Copyright (c) 2003 Dr John Maddock
+ * Use, modification and distribution is 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)
+ *
+ * boostinspect:noascii
+ */
+
+#include "licence_info.hpp"
+
+
+std::pair<const license_info*, int> get_licenses()
+{
+ static const char* generic_author_sig =
+ "(?:"
+ "(?:"
+ "Copyright|\\(c\\)|\xA9"
+ ")[[:blank:]]+"
+ "){1,2}"
+ "(?:"
+ "\\d[^[:alpha:]]+"
+ "([[:alpha:]]"
+ "(?:"
+ "(?!Use\\b|Permission\\b|All\\b|<P|(?:-\\s*)\\w+(?:://|@)|\\\\"
+ ")[^\\n\\d]"
+ ")+"
+ ")"
+ "|"
+ "([[:alpha:]][^\\n\\d]+"
+ "(?:\\n[^\\n\\d]+"
+ ")??"
+ ")(?:19|20)\\d{2}"
+ ")"
+ "|"
+ "Authors:[[:blank:]]+"
+ "([[:alpha:]][^\\n\\d]+"
+ "|"
+ "((?:The|This) code is considered to be in the public domain)"
+ ")";
+
+ static const char* generic_author_format =
+ "(?1$1)(?2$2)(?3$3)(?4Public Domain)";
+
+ static const license_info licenses[] =
+ {
+ license_info( boost::regex("distributed\\W+under"
+ "(\\W+the)?[^\"[:word:]]+Boost\\W+Software\\W+License\\W+Version\\W+1.0", boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Boost Software License, Version 1.0"
+ ,
+ "<P>Copyright (c) <I>Date</I> <I>Author</I></P>"
+ "<P>Distributed under the "
+ "Boost Software License, Version 1.0. (See accompanying file "
+ "LICENSE_1_0.txt or copy at <a href=\"http://www.boost.org/LICENSE_1_0.txt\">http://www.boost.org/LICENSE_1_0.txt)</a></P>"
+ )
+ ,
+ license_info( boost::regex("Use\\W+\\modification\\W+and\\W+distribution(\\W+is|\\W+are)\\W+subject\\W+to"
+ "(\\W+the)?[^\"[:word:]]+Boost\\W+Software\\W+License\\W+Version\\W+1.0", boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Boost Software License, Version 1.0 (variant #1)"
+ ,
+ "<P>Copyright (c) <I>Date</I> <I>Author</I></P>"
+ "<P>Use, modification and distribution is subject to the "
+ "Boost Software License, Version 1.0. (See accompanying file "
+ "LICENSE_1_0.txt or copy at <a href=\"http://www.boost.org/LICENSE_1_0.txt\">http://www.boost.org/LICENSE_1_0.txt)</a></P>"
+ )
+ ,
+ license_info( boost::regex("(?!is)\\w\\w\\W+subject\\W+to"
+ "(\\W+the)?[^\"[:word:]]+Boost\\W+Software\\W+License\\W+Version\\W+1.0", boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Boost Software License, Version 1.0 (variant #2)"
+ ,
+ "<P>Copyright (c) <I>Date</I> <I>Author</I></P>"
+ "<P>Subject to the "
+ "Boost Software License, Version 1.0. (See accompanying file "
+ "LICENSE_1_0.txt or copy at <a href=\"http://www.boost.org/LICENSE_1_0.txt\">http://www.boost.org/LICENSE_1_0.txt)</a></P>"
+ )
+ ,
+ license_info( boost::regex("Copyright\\W+(c)\\W+2001\\W+2002\\W+Python\\W+Software\\W+Foundation\\W+All\\W+Rights\\W+Reserved", boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Python Software License"
+ ,
+ "<p>Copyright (c) 2001, 2002 Python Software Foundation;</p>"
+ "<P>All Rights Reserved</P>"
+ )
+ ,
+ license_info( boost::regex("Permission\\W+to\\W+use\\W+copy\\W+modify\\W+distribute\\W+and\\W+sell\\W+this\\W+software\\W+and\\W+its\\W+documentation"
+ "\\W+for\\W+any\\W+purpose\\W+is\\W+hereby\\W+granted\\W+without\\W+fee"
+ "\\W+provided\\W+that\\W+the\\W+above\\W+copyright\\W+notice\\W+appears?\\W+in\\W+all\\W+copies\\W+and"
+ "\\W+that\\W+both\\W+(the|that)\\W+copyright\\W+notice\\W+and\\W+this\\W+permission\\W+notice\\W+appears?"
+ "\\W+in\\W+supporting\\W+documentation[^<>]{1, 100}\\W+no\\W+representations"
+ "\\W+(are\\W+made\\W+)?about\\W+the\\W+suitability\\W+of\\W+this\\W+software\\W+for\\W+any\\W+purpose"
+ "\\W+It\\W+is\\W+provided\\W+as\\W+is\\W+without\\W+express\\W+or\\W+implied\\W+warranty"
+ , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "SGI Style License"
+ ,
+ "<P>Copyright (c) <I>Date</I><BR>"
+ "<I>Author</I><BR>"
+ "<BR>"
+ "Permission to use, copy, modify, distribute and sell this software "
+ "and its documentation for any purpose is hereby granted without fee, "
+ "provided that the above copyright notice appear in all copies and "
+ "that both that copyright notice and this permission notice appear "
+ "in supporting documentation. <I>Author</I> makes no representations "
+ "about the suitability of this software for any purpose. "
+ "It is provided \"as is\" without express or implied warranty.</P>"
+ )
+ ,
+ license_info( boost::regex("Permission\\W+to\\W+use\\W+copy\\W+modify\\W+distribute\\W+and\\W+sell\\W+this\\W+software"
+ "\\W+for\\W+any\\W+purpose\\W+is\\W+hereby\\W+granted\\W+without\\W+fee"
+ "\\W+provided\\W+that\\W+the\\W+above\\W+copyright\\W+notice\\W+appears?\\W+in\\W+all\\W+copies\\W+and"
+ "\\W+that\\W+both\\W+(the|that)\\W+copyright\\W+notice\\W+and\\W+this\\W+permission\\W+notice\\W+appears?"
+ "\\W+in\\W+supporting\\W+documentation[^<>]{1, 100}\\W+no\\W+representations"
+ "\\W+(are\\W+made\\W+)?about\\W+the\\W+suitability\\W+of\\W+this\\W+software\\W+for\\W+any\\W+purpose"
+ "\\W+It\\W+is\\W+provided\\W+as\\W+is\\W+without\\W+express(ed)?\\W+or\\W+implied\\W+warranty", boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Old style Boost license #1"
+ ,
+ "<P>Copyright (c) <I>Date</I><BR>"
+ "<I>Author</I><BR>"
+ "<BR>"
+ "Permission to use, copy, modify, distribute and sell this software "
+ "for any purpose is hereby granted without fee, "
+ "provided that the above copyright notice appear in all copies and "
+ "that both that copyright notice and this permission notice appears? "
+ "in supporting documentation. <I>Author</I> makes no representations "
+ "about the suitability of this software for any purpose. "
+ "It is provided \"as is\" without express or implied warranty.</P>"
+ )
+ ,
+ license_info(
+ boost::regex(
+ "Permission\\W+to\\W+copy\\W+use\\W+modify\\W+sell\\W+and\\W+distribute\\W+this\\W+software"
+ "\\W+is\\W+granted\\W+provided\\W+this\\W+copyright\\W+notice\\W+appears\\W+in\\W+all\\W+copies"
+ "\\W+This\\W+software\\W+is\\W+provided\\W+as\\W+is\\W+without\\W+express\\W+or\\W+implied"
+ "\\W+warranty\\W+and\\W+with\\W+no\\W+claim\\W+as\\W+to\\W+its\\W+suitability\\W+for\\W+any\\W+purpose"
+ , boost::regex::perl | boost::regex::icase
+ )
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Old style Boost license #2"
+ ,
+ "<P>Copyright (c) <I>Date</I> <I>Author</I>.<BR><BR>\n"
+ "Permission to copy, use, modify, sell and distribute this software<BR>\n"
+ "is granted provided this copyright notice appears in all copies.<BR>\n"
+ "This software is provided \"as is\" without express or implied<BR>\n"
+ "warranty, and with no claim as to its suitability for any purpose.</P>\n"
+ )
+ ,
+ license_info(
+ boost::regex(
+ "Permission\\W+to\\W+copy\\W+use[^\"[:word:]]+modify\\W+sell\\W+and\\W+distribute\\W+this\\W+software\\W+is\\W+granted\\W+provided"
+ "\\W+this\\W+copyright\\W+notice\\W+appears\\W+in\\W+all\\W+copies\\W+This\\W+software\\W+is"
+ "\\W+provided\\W+as\\W+is\\W+without\\W+express\\W+or\\W+implied\\W+warranty\\W+and\\W+with"
+ "\\W+no\\W+claim\\W+at\\W+to\\W+its\\W+suitability\\W+for\\W+any\\W+purpose"
+ , boost::regex::perl | boost::regex::icase
+ )
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Old style Boost license #3"
+ ,
+ "<P>(C) Copyright <I>Author</I> <I>Date</I>. Permission to copy, use, "
+ "modify, sell, and distribute this software is granted provided "
+ "this copyright notice appears in all copies. This software is "
+ "provided \"as is\" without express or implied warranty, and with "
+ "no claim at to its suitability for any purpose.</p>\n"
+ )
+ ,
+ license_info( boost::regex("Permission\\W+to\\W+copy\\W+use\\W+sell\\W+and\\W+distribute\\W+this\\W+software\\W+is\\W+granted"
+ "\\W+provided\\W+this\\W+copyright\\W+notice\\W+appears\\W+in\\W+all\\W+copies"
+ "\\W+Permission\\W+to\\W+modify\\W+the\\W+code\\W+and\\W+to\\W+distribute\\W+modified\\W+code\\W+is\\W+granted"
+ "\\W+provided\\W+this\\W+copyright\\W+notice\\W+appears\\W+in\\W+all\\W+copies\\W+and\\W+a\\W+notice"
+ "\\W+that\\W+the\\W+code\\W+was\\W+modified\\W+is\\W+included\\W+with\\W+the\\W+copyright\\W+notice"
+ "\\W+This\\W+software\\W+is\\W+provided\\W+as\\W+is\\W+without\\W+express\\W+or\\W+implied\\W+warranty\\W+and\\W+with\\W+no\\W+claim\\W+as\\W+to\\W+its\\W+suitability\\W+for\\W+any\\W+purpose"
+ , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Old style Boost license #4"
+ ,
+ "<P>Copyright (C) <I>Date Author</I><BR>"
+ "<BR>"
+ "Permission to copy, use, sell and distribute this software is granted\n"
+ "provided this copyright notice appears in all copies.\n"
+ "Permission to modify the code and to distribute modified code is granted\n"
+ "provided this copyright notice appears in all copies, and a notice\n"
+ "that the code was modified is included with the copyright notice.</P>\n"
+ "<P>This software is provided \"as is\" without express or implied warranty,\n"
+ "and with no claim as to its suitability for any purpose.</P>"
+ )
+ ,
+ license_info( boost::regex("This\\W+file\\W+is\\W+part\\W+of\\W+the\\W+(Boost\\W+Graph|Generic\\W+Graph\\W+Component)\\W+Library"
+ "\\W+You\\W+should\\W+have\\W+received\\W+a\\W+copy\\W+of\\W+the\\W+License\\W+Agreement\\W+for\\W+the"
+ "\\W+(Boost|Generic)\\W+Graph\\W+(Component\\W+)?Library\\W+along\\W+with\\W+the\\W+software;\\W+see\\W+the\\W+file\\W+LICENSE"
+ "(\\W+If\\W+not\\W+contact\\W+Office\\W+of\\W+Research\\W+University\\W+of\\W+Notre\\W+Dame\\W+Notre"
+ "\\W+Dame\\W+IN\\W+46556)?"
+ "\\W+Permission\\W+to\\W+modify\\W+the\\W+code\\W+and\\W+to\\W+distribute(\\W+modified|\\W+the)\\W+code\\W+is"
+ "\\W+granted\\W+provided\\W+the\\W+text\\W+of\\W+this\\W+NOTICE\\W+is\\W+retained\\W+a\\W+notice\\W+(that|if)"
+ "\\W+the\\W+code\\W+was\\W+modified\\W+is\\W+included\\W+with\\W+the\\W+above\\W+COPYRIGHT\\W+NOTICE\\W+and"
+ "\\W+with\\W+the\\W+COPYRIGHT\\W+NOTICE\\W+in\\W+the\\W+LICENSE\\W+file\\W+and\\W+that\\W+the\\W+LICENSE"
+ "\\W+file\\W+is\\W+distributed\\W+with\\W+the\\W+modified\\W+code\\W+"
+ "\\W+LICENSOR\\W+MAKES\\W+NO\\W+REPRESENTATIONS\\W+OR\\W+WARRANTIES\\W+EXPRESS\\W+OR\\W+IMPLIED"
+ "\\W+By\\W+way\\W+of\\W+example\\W+but\\W+not\\W+limitation\\W+Licensor\\W+MAKES\\W+NO"
+ "\\W+REPRESENTATIONS\\W+OR\\W+WARRANTIES\\W+OF\\W+MERCHANTABILITY\\W+OR\\W+FITNESS\\W+FOR\\W+ANY"
+ "\\W+PARTICULAR\\W+PURPOSE\\W+OR\\W+THAT\\W+THE\\W+USE\\W+OF\\W+THE\\W+LICENSED\\W+SOFTWARE\\W+COMPONENTS"
+ "\\W+OR\\W+DOCUMENTATION\\W+WILL\\W+NOT\\W+INFRINGE\\W+ANY\\W+PATENTS\\W+COPYRIGHTS\\W+TRADEMARKS"
+ "\\W+OR\\W+OTHER\\W+RIGHTS"
+ , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Boost.Graph license (Notre Dame)"
+ ,
+ "<P>Copyright <I>Date</I> University of Notre Dame.<BR>"
+ "Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek</P>"
+ "<P>This file is part of the Boost Graph Library</P>"
+ "<P>You should have received a copy of the <A href=\"http://www.boost.org/libs/graph/LICENCE\">License Agreement</a> for the "
+ "Boost Graph Library along with the software; see the file <A href=\"http://www.boost.org/libs/graph/LICENCE\">LICENSE</a>. "
+ "If not, contact Office of Research, University of Notre Dame, Notre "
+ "Dame, IN 46556.</P>"
+ "<P>Permission to modify the code and to distribute modified code is "
+ "granted, provided the text of this NOTICE is retained, a notice that "
+ "the code was modified is included with the above COPYRIGHT NOTICE and "
+ "with the COPYRIGHT NOTICE in the <A href=\"http://www.boost.org/libs/graph/LICENCE\">LICENSE</a> file, and that the <A href=\"http://www.boost.org/libs/graph/LICENCE\">LICENSE</a> "
+ "file is distributed with the modified code.</P>"
+ "<P>LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.<BR> "
+ "By way of example, but not limitation, Licensor MAKES NO "
+ "REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY "
+ "PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS "
+ "OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS "
+ "OR OTHER RIGHTS.</P>"
+ )
+ ,
+ license_info( boost::regex("This\\W+file\\W+is\\W+part\\W+of\\W+the\\W+(Boost\\W+Graph|Generic\\W+Graph\\W+Component)\\W+Library"
+ "\\W+You\\W+should\\W+have\\W+received\\W+a\\W+copy\\W+of\\W+the\\W+License\\W+Agreement\\W+for\\W+the"
+ "\\W+(Boost|Generic)\\W+Graph\\W+(Component\\W+)?Library\\W+along\\W+with\\W+the\\W+software;\\W+see\\W+the\\W+file\\W+LICENSE"
+ "(\\W+If\\W+not\\W+contact\\W+Office\\W+of\\W+Research\\W+Indiana\\W+University\\W+Bloomington\\W+IN\\W+47405)?"
+ "\\W+Permission\\W+to\\W+modify\\W+the\\W+code\\W+and\\W+to\\W+distribute(\\W+modified|\\W+the)\\W+code\\W+is"
+ "\\W+granted\\W+provided\\W+the\\W+text\\W+of\\W+this\\W+NOTICE\\W+is\\W+retained\\W+a\\W+notice\\W+(that|if)"
+ "\\W+the\\W+code\\W+was\\W+modified\\W+is\\W+included\\W+with\\W+the\\W+above\\W+COPYRIGHT\\W+NOTICE\\W+and"
+ "\\W+with\\W+the\\W+COPYRIGHT\\W+NOTICE\\W+in\\W+the\\W+LICENSE\\W+file\\W+and\\W+that\\W+the\\W+LICENSE"
+ "\\W+file\\W+is\\W+distributed\\W+with\\W+the\\W+modified\\W+code\\W+"
+ "\\W+LICENSOR\\W+MAKES\\W+NO\\W+REPRESENTATIONS\\W+OR\\W+WARRANTIES\\W+EXPRESS\\W+OR\\W+IMPLIED"
+ "\\W+By\\W+way\\W+of\\W+example\\W+but\\W+not\\W+limitation\\W+Licensor\\W+MAKES\\W+NO"
+ "\\W+REPRESENTATIONS\\W+OR\\W+WARRANTIES\\W+OF\\W+MERCHANTABILITY\\W+OR\\W+FITNESS\\W+FOR\\W+ANY"
+ "\\W+PARTICULAR\\W+PURPOSE\\W+OR\\W+THAT\\W+THE\\W+USE\\W+OF\\W+THE\\W+LICENSED\\W+SOFTWARE\\W+COMPONENTS"
+ "\\W+OR\\W+DOCUMENTATION\\W+WILL\\W+NOT\\W+INFRINGE\\W+ANY\\W+PATENTS\\W+COPYRIGHTS\\W+TRADEMARKS"
+ "\\W+OR\\W+OTHER\\W+RIGHTS"
+ , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Boost.Graph license (Indiana University)"
+ ,
+ "<P>Copyright <I>Date</I> Indiana University.<BR>"
+ "Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek</P>"
+ "<P>This file is part of the Boost Graph Library</P>"
+ "<P>You should have received a copy of the <A href=\"http://www.boost.org/libs/graph/LICENCE\">License Agreement</a> for the "
+ "Boost Graph Library along with the software; see the file <A href=\"http://www.boost.org/libs/graph/LICENCE\">LICENSE</a>. "
+ "If not, contact Office of Research, Indiana University, Bloomington,"
+ "IN 47404.</P>"
+ "<P>Permission to modify the code and to distribute modified code is "
+ "granted, provided the text of this NOTICE is retained, a notice that "
+ "the code was modified is included with the above COPYRIGHT NOTICE and "
+ "with the COPYRIGHT NOTICE in the <A href=\"http://www.boost.org/libs/graph/LICENCE\">LICENSE</a> file, and that the <A href=\"http://www.boost.org/libs/graph/LICENCE\">LICENSE</a> "
+ "file is distributed with the modified code.</P>"
+ "<P>LICENSOR MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED.<BR> "
+ "By way of example, but not limitation, Licensor MAKES NO "
+ "REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY "
+ "PARTICULAR PURPOSE OR THAT THE USE OF THE LICENSED SOFTWARE COMPONENTS "
+ "OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS, COPYRIGHTS, TRADEMARKS "
+ "OR OTHER RIGHTS.</P>"
+ )
+ ,
+ license_info( boost::regex("Permission\\W+to\\W+copy\\W+use\\W+modify\\W+sell\\W+and\\W+distribute\\W+this\\W+software\\W+is"
+ "[^\"[:word:]]+granted\\W+provided\\W+this\\W+copyright\\W+notice\\W+appears\\W+in\\W+all\\W+copies\\W+and"
+ "\\W+modified\\W+version\\W+are\\W+clearly\\W+marked\\W+as\\W+such\\W+This\\W+software\\W+is\\W+provided"
+ "\\W+as\\W+is\\W+without\\W+express\\W+or\\W+implied\\W+warranty\\W+and\\W+with\\W+no\\W+claim\\W+as\\W+to\\W+its"
+ "\\W+suitability\\W+for\\W+any\\W+purpose"
+ , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Old style Boost license #5"
+ ,
+ "<P>Copyright (C) <I>Date Author</I></P>"
+ "<p>Permission to copy, use, modify, sell and distribute this software is "
+ "granted, provided this copyright notice appears in all copies and "
+ "modified version are clearly marked as such. This software is provided "
+ "\"as is\" without express or implied warranty, and with no claim as to its "
+ "suitability for any purpose.</P>"
+ )
+ ,
+ license_info( boost::regex("This\\W+file\\W+can\\W+be\\W+redistributed\\W+and\\W+or\\W+modified\\W+under\\W+the\\W+terms\\W+found"
+ "\\W+in\\W+copyright\\W+html"
+ "\\W+This\\W+software\\W+and\\W+its\\W+documentation\\W+is\\W+provided\\W+as\\W+is\\W+without\\W+express\\W+or"
+ "\\W+implied\\W+warranty\\W+and\\W+with\\W+no\\W+claim\\W+as\\W+to\\W+its\\W+suitability\\W+for\\W+any\\W+purpose"
+ , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Boost.Pool license"
+ ,
+ "<P>This file can be redistributed and/or modified under the terms found "
+ "in <a href=\"http://www.boost.org/libs/pool/doc/copyright.html\">copyright.html</a></P>\n"
+ "<P>This software and its documentation is provided \"as is\" without express or "
+ "implied warranty, and with no claim as to its suitability for any purpose</P>"
+ )
+ ,
+ license_info(boost::regex("Permission\\W+to\\W+use\\W+copy\\W+modify\\W+sell\\W+and\\W+distribute\\W+this\\W+software"
+ "\\W+is\\W+hereby\\W+granted\\W+without\\W+fee\\W+provided\\W+that\\W+the\\W+above\\W+copyright\\W+notice"
+ "\\W+appears\\W+in\\W+all\\W+copies\\W+and\\W+that\\W+both\\W+that\\W+copyright\\W+notice\\W+and\\W+this"
+ "\\W+permission\\W+notice\\W+appear\\W+in\\W+supporting\\W+documentation"
+ "[^<>]{1,100}\\W+(make\\W+any\\W+representation|makes\\W+no\\W+representations)\\W+about\\W+the\\W+suitability\\W+of\\W+this"
+ "\\W+software\\W+for\\W+any\\W+purpose\\W+It\\W+is\\W+provided\\W+as\\W+is\\W+without\\W+express\\W+or"
+ "\\W+implied\\W+warranty"
+ , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Old style Boost license #6"
+ ,
+ "<P>Copyright <I>Author Data</I></P>"
+ "<P>Permission to use, copy, modify, sell, and distribute this software "
+ "is hereby granted without fee provided that the above copyright notice "
+ "appears in all copies and that both that copyright notice and this "
+ "permission notice appear in supporting documentation, "
+ "<I>Author</I> makes no representations about the suitability of this "
+ "software for any purpose. It is provided \"as is\" without express or "
+ "implied warranty.</P>"
+ )
+ ,
+ license_info( boost::regex("Permission\\W+to\\W+copy"
+ "[^\"[:word:]]+use\\W+modify\\W+sell\\W+and\\W+distribute\\W+this\\W+software\\W+is\\W+granted\\W+provided"
+ "\\W+this\\W+copyright\\W+notice\\W+appears\\W+in\\W+all\\W+copies\\W+of\\W+the\\W+source\\W+This"
+ "\\W+software\\W+is\\W+provided\\W+as\\W+is\\W+without\\W+express\\W+or\\W+implied\\W+warranty"
+ "\\W+and\\W+with\\W+no\\W+claim\\W+as\\W+to\\W+its\\W+suitability\\W+for\\W+any\\W+purpose"
+ , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Old style Boost license #7"
+ ,
+ "<P>Copyright <I>Author Date</I>. Permission to copy, "
+ "use, modify, sell and distribute this software is granted provided "
+ "this copyright notice appears in all copies of the source. This "
+ "software is provided \"as is\" without express or implied warranty, "
+ "and with no claim as to its suitability for any purpose."
+ )
+ ,
+ license_info(boost::regex("This\\W+software\\W+is\\W+provided\\W+as-is\\W+without\\W+any\\W+express\\W+or\\W+implied"
+ "\\W+warranty\\W+In\\W+no\\W+event\\W+will\\W+the\\W+copyright\\W+holder\\W+be\\W+held\\W+liable\\W+for"
+ "\\W+any\\W+damages\\W+arising\\W+from\\W+the\\W+use\\W+of\\W+this\\W+software"
+ "\\W+Permission\\W+is\\W+granted\\W+to\\W+anyone\\W+to\\W+use\\W+this\\W+software\\W+for\\W+any\\W+purpose"
+ "\\W+including\\W+commercial\\W+applications\\W+and\\W+to\\W+alter\\W+it\\W+and\\W+redistribute"
+ "\\W+it\\W+freely\\W+subject\\W+to\\W+the\\W+following\\W+restrictions:"
+ "\\W+1\\W+The\\W+origin\\W+of\\W+this\\W+software\\W+must\\W+not\\W+be\\W+misrepresented;\\W+you\\W+must"
+ "\\W+not\\W+claim\\W+that\\W+you\\W+wrote\\W+the\\W+original\\W+software\\W+If\\W+you\\W+use\\W+this"
+ "\\W+software\\W+in\\W+a\\W+product\\W+an\\W+acknowledgment\\W+in\\W+the\\W+product\\W+documentation"
+ "\\W+would\\W+be\\W+appreciated\\W+but\\W+is\\W+not\\W+required"
+ "\\W+2\\W+Altered\\W+source\\W+versions\\W+must\\W+be\\W+plainly\\W+marked\\W+as\\W+such\\W+and\\W+must"
+ "\\W+not\\W+be\\W+misrepresented\\W+as\\W+being\\W+the\\W+original\\W+software"
+ "\\W+3\\W+This\\W+notice\\W+may\\W+not\\W+be\\W+removed\\W+or\\W+altered\\W+from\\W+any\\W+source"
+ "\\W+distribution"
+ , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Old style Boost license #8"
+ ,
+ "<P>Phoenix V0.9<BR>Copyright (c) <I>Date</I> Joel de Guzman</P>"
+ "<P>This software is provided 'as-is', without any express or implied "
+ "warranty. In no event will the copyright holder be held liable for "
+ "any damages arising from the use of this software.</P>"
+ "<P>Permission is granted to anyone to use this software for any purpose, "
+ "including commercial applications, and to alter it and redistribute "
+ "it freely, subject to the following restrictions:</P>"
+ "<P>1. The origin of this software must not be misrepresented; you must "
+ "not claim that you wrote the original software. If you use this "
+ "software in a product, an acknowledgment in the product documentation "
+ "would be appreciated but is not required.</P>"
+ "2. Altered source versions must be plainly marked as such, and must "
+ "not be misrepresented as being the original software. </P>"
+ "<P>3. This notice may not be removed or altered from any source "
+ "distribution. "
+ )
+ ,
+ license_info( boost::regex("Permission\\W+to\\W+use\\W+copy\\W+modify\\W+sell\\W+and\\W+distribute\\W+this\\W+software"
+ "\\W+is\\W+hereby\\W+granted\\W+without\\W+fee\\W+provided\\W+that\\W+the\\W+above\\W+copyright\\W+notice"
+ "\\W+appears\\W+in\\W+all\\W+copies\\W+and\\W+that\\W+both\\W+that\\W+copyright\\W+notice\\W+and\\W+this"
+ "\\W+permission\\W+notice\\W+appear\\W+in\\W+supporting\\W+documentation"
+ "\\W+None\\W+of\\W+the\\W+above\\W+authors\\W+nor.{1,100}make\\W+any"
+ "\\W+representation\\W+about\\W+the\\W+suitability\\W+of\\W+this\\W+software\\W+for\\W+any"
+ "\\W+purpose\\W+It\\W+is\\W+provided\\W+as\\W+is\\W+without\\W+express\\W+or\\W+implied\\W+warranty"
+ , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Old style Boost license #9"
+ ,
+ "<P>Copyright <I> Author Date</I><BR>"
+ "Permission to use, copy, modify, sell, and distribute this software "
+ "is hereby granted without fee provided that the above copyright notice "
+ "appears in all copies and that both that copyright notice and this "
+ "permission notice appear in supporting documentation, <BR>"
+ "None of the above authors nor <I>Author's Organisation</I> make any "
+ "representation about the suitability of this software for any "
+ "purpose. It is provided \"as is\" without express or implied warranty."
+ )
+ ,
+ license_info( boost::regex("Permission\\W+to\\W+use\\W+copy\\W+modify\\W+and\\W+distribute\\W+this\\W+software\\W+for\\W+any"
+ "\\W+purpose\\W+is\\W+hereby\\W+granted\\W+without\\W+fee\\W+provided\\W+that\\W+this\\W+copyright\\W+and"
+ "\\W+permissions\\W+notice\\W+appear\\W+in\\W+all\\W+copies\\W+and\\W+derivatives"
+ "\\W+This\\W+software\\W+is\\W+provided\\W+as\\W+is\\W+without\\W+express\\W+or\\W+implied\\W+warranty"
+ , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Old style Boost license #10"
+ ,
+ "<P>Copyright <I>Author Date</I>. All rights reserved.</P>"
+ "<P>Permission to use, copy, modify, and distribute this software for any "
+ "purpose is hereby granted without fee, provided that this copyright and "
+ "permissions notice appear in all copies and derivatives.</P>"
+ "<P>This software is provided \"as is\" without express or implied warranty.</P>"
+ )
+ ,
+ license_info( boost::regex("This\\W+material\\W+is\\W+provided\\W+as\\W+is\\W+with\\W+absolutely\\W+no\\W+warranty\\W+expressed"
+ "\\W+or\\W+implied\\W+Any\\W+use\\W+is\\W+at\\W+your\\W+own\\W+risk"
+ "\\W+Permission\\W+to\\W+use\\W+or\\W+copy\\W+this\\W+software\\W+for\\W+any\\W+purpose\\W+is\\W+hereby\\W+granted"
+ "\\W+without\\W+fee\\W+provided\\W+the\\W+above\\W+notices\\W+are\\W+retained\\W+on\\W+all\\W+copies"
+ "\\W+Permission\\W+to\\W+modify\\W+the\\W+code\\W+and\\W+to\\W+distribute\\W+modified\\W+code\\W+is\\W+granted"
+ "\\W+provided\\W+the\\W+above\\W+notices\\W+are\\W+retained\\W+and\\W+a\\W+notice\\W+that\\W+the\\W+code\\W+was"
+ "\\W+modified\\W+is\\W+included\\W+with\\W+the\\W+above\\W+copyright\\W+notice"
+ , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Old style Boost license #11"
+ ,
+ "<P>This material is provided \"as is\", with absolutely no warranty expressed "
+ "or implied. Any use is at your own risk.</P>"
+ "<P>Permission to use or copy this software for any purpose is hereby granted "
+ "without fee, provided the above notices are retained on all copies. "
+ "Permission to modify the code and to distribute modified code is granted, "
+ "provided the above notices are retained, and a notice that the code was "
+ "modified is included with the above copyright notice.</P>"
+ )
+ ,
+ license_info( boost::regex("Permission\\W+to\\W+copy\\W+use\\W+and\\W+distribute\\W+this\\W+software\\W+is\\W+granted\\W+provided"
+ "\\W+that\\W+this\\W+copyright\\W+notice\\W+appears\\W+in\\W+all\\W+copies"
+ "\\W+Permission\\W+to\\W+modify\\W+the\\W+code\\W+and\\W+to\\W+distribute\\W+modified\\W+code\\W+is\\W+granted"
+ "\\W+provided\\W+that\\W+this\\W+copyright\\W+notice\\W+appears\\W+in\\W+all\\W+copies\\W+and\\W+a\\W+notice"
+ "\\W+that\\W+the\\W+code\\W+was\\W+modified\\W+is\\W+included\\W+with\\W+the\\W+copyright\\W+notice"
+ "\\W+This\\W+software\\W+is\\W+provided\\W+as\\W+is\\W+without\\W+express\\W+or\\W+implied\\W+warranty\\W+and"
+ "\\W+with\\W+no\\W+claim\\W+as\\W+to\\W+its\\W+suitability\\W+for\\W+any\\W+purpose"
+ , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Old style Boost license #12"
+ ,
+ "<P>Copyright (C) <I>Date Author</I></P><P>Permission to copy, use, and distribute this software is granted, provided "
+ "that this copyright notice appears in all copies.<BR>"
+ "Permission to modify the code and to distribute modified code is granted, "
+ "provided that this copyright notice appears in all copies, and a notice "
+ "that the code was modified is included with the copyright notice.</P>"
+ "<P>This software is provided \"as is\" without express or implied warranty, and "
+ "with no claim as to its suitability for any purpose.</P>"
+ )
+ ,
+ license_info( boost::regex("Permission\\W+to\\W+copy\\W+and\\W+use\\W+this\\W+software\\W+is\\W+granted"
+ "\\W+provided\\W+this\\W+copyright\\W+notice\\W+appears\\W+in\\W+all\\W+copies"
+ "\\W+Permission\\W+to\\W+modify\\W+the\\W+code\\W+and\\W+to\\W+distribute\\W+modified\\W+code\\W+is\\W+granted"
+ "\\W+provided\\W+this\\W+copyright\\W+notice\\W+appears\\W+in\\W+all\\W+copies\\W+and\\W+a\\W+notice"
+ "\\W+that\\W+the\\W+code\\W+was\\W+modified\\W+is\\W+included\\W+with\\W+the\\W+copyright\\W+notice"
+ "\\W+This\\W+software\\W+is\\W+provided\\W+as\\W+is\\W+without\\W+express\\W+or\\W+implied\\W+warranty"
+ "\\W+and\\W+with\\W+no\\W+claim\\W+as\\W+to\\W+its\\W+suitability\\W+for\\W+any\\W+purpose"
+ , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Old style Boost license #13"
+ ,
+ "<P>Copyright (C) <I>Date Author</I></P>"
+ "<P>Permission to copy and use this software is granted, "
+ "provided this copyright notice appears in all copies. "
+ "Permission to modify the code and to distribute modified code is granted, "
+ "provided this copyright notice appears in all copies, and a notice "
+ "that the code was modified is included with the copyright notice.</P>"
+ "<P>This software is provided \"as is\" without express or implied warranty, "
+ "and with no claim as to its suitability for any purpose.</P>"
+ )
+ ,
+ license_info( boost::regex("Copyright\\W+Kevlin\\W+Henney\\W+2000\\W+All\\W+rights\\W+reserved\\W+"
+ "Permission\\W+to\\W+use\\W+copy\\W+modify\\W+and\\W+distribute\\W+this\\W+software\\W+for\\W+any"
+ "\\W+purpose\\W+is\\W+hereby\\W+granted\\W+without\\W+fee\\W+provided\\W+that\\W+this\\W+copyright\\W+and"
+ "\\W+permissions\\W+notice\\W+appear\\W+in\\W+all\\W+copies\\W+and\\W+derivatives\\W+and\\W+that\\W+no"
+ "\\W+charge\\W+may\\W+be\\W+made\\W+for\\W+the\\W+software\\W+and\\W+its\\W+documentation\\W+except\\W+to\\W+cover"
+ "\\W+cost\\W+of\\W+distribution"
+ "\\W+This\\W+software\\W+is\\W+provided\\W+as\\W+is\\W+without\\W+express\\W+or\\W+implied\\W+warranty\\W+"
+ , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Old style Boost license #14"
+ ,
+ "<P>Copyright The Author, The Date. All rights reserved.</P>"
+ "<P>Permission to use, copy, modify, and distribute this software for any"
+ " purpose is hereby granted without fee, provided that this copyright and"
+ " permissions notice appear in all copies and derivatives, and that no"
+ " charge may be made for the software and its documentation except to cover"
+ " cost of distribution.</P>"
+ "<P>This software is provided \"as is\" without express or implied warranty.</P>"
+ )
+ ,
+ license_info( boost::regex("preprocessed\\W+version\\W+of\\W+boost/mpl/.*\\.hpp\\W+header\\W+see\\W+the\\W+original\\W+for\\W+copyright\\W+information", boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "SGI Style Licence (MPL preprocessed file)"
+ ,
+ "<P>Copyright (c) <I>Date</I><BR>"
+ "<I>Author</I><BR>"
+ "<BR>"
+ "Permission to use, copy, modify, distribute and sell this software "
+ "and its documentation for any purpose is hereby granted without fee, "
+ "provided that the above copyright notice appear in all copies and "
+ "that both that copyright notice and this permission notice appear "
+ "in supporting documentation. <I>Author</I> makes no representations "
+ "about the suitability of this software for any purpose. "
+ "It is provided \"as is\" without express or implied warranty.</P>"
+ )
+ ,
+ license_info( boost::regex(
+ "This\\W+file\\W+is\\W+part\\W+of\\W+jam\\W+"
+ "License\\W+is\\W+hereby\\W+granted\\W+to\\W+use\\W+this\\W+software\\W+and\\W+distribute\\W+it\\W+"
+ "freely\\W+as\\W+long\\W+as\\W+this\\W+copyright\\W+notice\\W+is\\W+retained\\W+and\\W+modifications\\W+"
+ "are\\W+clearly\\W+marked\\W+"
+ "ALL\\W+WARRANTIES\\W+ARE\\W+HEREBY\\W+DISCLAIMED"
+ "|"
+ "This\\W+file\\W+is\\W+part\\W+of\\W+Jam\\W+see\\W+jam\\.c\\W+for\\W+Copyright\\W+information"
+ "|This file has been donated to Jam"
+ "|Generated by mkjambase from Jambase" , boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig + std::string("|(Craig\\W+W\\W+McPheeters\\W+Alias\\W+Wavefront)|(Generated by mkjambase from Jambase)"), boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format + std::string("(?4Craig W. McPheeters, Alias|Wavefront)(?5Christopher Seiwald and Perforce Software, Inc)")
+ ,
+ "Perforce Jam License"
+ ,
+ "<P>Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.</P>"
+ "<P>This file is part of jam.</P>"
+ "<P>License is hereby granted to use this software and distribute it "
+ "freely, as long as this copyright notice is retained and modifications "
+ " are clearly marked.</P>"
+ "<P>ALL WARRANTIES ARE HEREBY DISCLAIMED</P>"
+ )
+ ,
+ license_info( boost::regex(
+ "Permission\\W+is\\W+granted\\W+to\\W+anyone\\W+to\\W+use\\W+this\\W+software\\W+for\\W+any\\W+"
+ "purpose\\W+on\\W+any\\W+computer\\W+system\\W+and\\W+to\\W+redistribute\\W+it\\W+freely\\W+"
+ "subject\\W+to\\W+the\\W+following\\W+restrictions\\W+"
+ "1\\W+The\\W+author\\W+is\\W+not\\W+responsible\\W+for\\W+the\\W+consequences\\W+of\\W+use\\W+of\\W+"
+ "this\\W+software\\W+no\\W+matter\\W+how\\W+awful\\W+even\\W+if\\W+they\\W+arise\\W+"
+ "from\\W+defects\\W+in\\W+it\\W+"
+ "2\\W+The\\W+origin\\W+of\\W+this\\W+software\\W+must\\W+not\\W+be\\W+misrepresented\\W+either\\W+"
+ "by\\W+explicit\\W+claim\\W+or\\W+by\\W+omission\\W+"
+ "3\\W+Altered\\W+versions\\W+must\\W+be\\W+plainly\\W+marked\\W+as\\W+such\\W+and\\W+must\\W+not\\W+"
+ "be\\W+misrepresented\\W+as\\W+being\\W+the\\W+original\\W+software"
+ "|Definitions\\W+etc\\W+for\\W+regexp\\W+3\\W+routines", boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig + std::string("|(Definitions\\W+etc\\W+for\\W+regexp\\W+3\\W+routines)"), boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format + std::string("(?4University of Toronto)")
+ ,
+ "BSD Regex License"
+ ,
+ "<P>Copyright (c) 1986 by University of Toronto.</P>"
+ "<P>Written by Henry Spencer. Not derived from licensed software.</P>"
+ "<P>Permission is granted to anyone to use this software for any"
+ "purpose on any computer system, and to redistribute it freely,"
+ "subject to the following restrictions:</P>"
+ "<P>The author is not responsible for the consequences of use of"
+ "this software, no matter how awful, even if they arise"
+ "from defects in it.</P>"
+ "<p>The origin of this software must not be misrepresented, either"
+ "by explicit claim or by omission.</p>"
+ "<p>Altered versions must be plainly marked as such, and must not"
+ "be misrepresented as being the original software.</P>"
+ )
+ ,
+ license_info( boost::regex(
+ "Skeleton\\W+parser\\W+for\\W+Yacc\\W+like\\W+parsing\\W+with\\W+Bison\\W+"
+ "Copyright.{0,100}Free\\W+Software\\W+Foundation\\W+Inc\\W+"
+ "\\W+This\\W+program\\W+is\\W+free\\W+software\\W+you\\W+can\\W+redistribute\\W+it\\W+and\\W+or\\W+modify\\W+"
+ "it\\W+under\\W+the\\W+terms\\W+of\\W+the\\W+GNU\\W+General\\W+Public\\W+License\\W+as\\W+published\\W+by\\W+"
+ "the\\W+Free\\W+Software\\W+Foundation\\W+either\\W+version\\W+2\\W+or\\W+at\\W+your\\W+option\\W+"
+ "any\\W+later\\W+version"
+ "|"
+ // this part matches the start of jamgramtab.h which is under the same licence
+ // but bison does not output it's usual licence declaration:
+ "\\{\\s*\"!\"\\s*,\\s*_BANG_t\\s*\\}", boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig + std::string("|(\\{\\s*\"!\"\\s*,\\s*_BANG_t\\s*\\})"), boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format + std::string("(?4Free Software Foundation, Inc)")
+ ,
+ "GNU Parser Licence"
+ ,
+ "<P>Skeleton parser for Yacc-like parsing with Bison,<BR>"
+ "Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc.</P>"
+ "<P>This program is free software; you can redistribute it and/or modify"
+ "it under the terms of the GNU General Public License as published by"
+ "the Free Software Foundation; either version 2, or (at your option)"
+ "any later version.</P>"
+ "<P>This program is distributed in the hope that it will be useful,"
+ "but WITHOUT ANY WARRANTY; without even the implied warranty of"
+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"
+ "GNU General Public License for more details.</P>"
+ "<P>You should have received a copy of the GNU General Public License"
+ "along with this program; if not, write to the Free Software"
+ "Foundation, Inc., 59 Temple Place - Suite 330,"
+ "Boston, MA 02111-1307, USA.</P>"
+ "<P>As a special exception, when this file is copied by Bison into a"
+ "Bison output file, you may use that output file without restriction."
+ "This special exception was added by the Free Software Foundation"
+ "in version 1.24 of Bison.</P>"
+ )
+ ,
+ license_info( boost::regex(
+ "(?:The|This)\\W+code\\W+is\\W+considered\\W+to\\W+be\\W+in\\W+the\\W+public\\W+domain", boost::regex::perl | boost::regex::icase)
+ ,
+ boost::regex(generic_author_sig, boost::regex::perl | boost::regex::icase)
+ ,
+ generic_author_format
+ ,
+ "Public Domain"
+ ,
+ "<P>The code has no license terms, it has been explicity placed in the\n"
+ "public domain by it's author(s).</P>"
+ )
+ ,
+ };
+ return std::pair<const license_info*, int>(licenses, static_cast<int>(sizeof(licenses)/sizeof(licenses[0])));
+}
+
+std::string format_authors_name(const std::string& name)
+{
+ // put name into a consistent format, so that we don't get too much
+ // of a proliferation of names (lots of versions of the same basic form).
+
+ static const boost::regex e("(^)?[^-(<a-zA-ZÀ-þ]+(([(<].*)?$)?");
+ static const char* formatter = "(?1:(?2: ))";
+
+ return boost::regex_replace(name, e, formatter, boost::match_default | boost::format_all);
+}
+
diff --git a/tools/bcp/licence_info.hpp b/tools/bcp/licence_info.hpp
new file mode 100644
index 000000000..e4ced2572
--- /dev/null
+++ b/tools/bcp/licence_info.hpp
@@ -0,0 +1,39 @@
+/*
+ *
+ * Copyright (c) 2003 Dr John Maddock
+ * Use, modification and distribution is 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)
+ *
+ */
+
+#include <boost/regex.hpp>
+#include <utility>
+
+struct license_info
+{
+ boost::regex license_signature;
+ boost::regex copyright_signature;
+ std::string copyright_formatter;
+ std::string license_name;
+ std::string license_text;
+ //
+ // we should really be able to initialize license_info as an
+ // aggregate, but some compilers reject this, so use a constructor
+ //instead:
+ //
+ license_info(const boost::regex& e1,
+ const boost::regex& e2,
+ const std::string& s1,
+ const std::string& s2,
+ const std::string& s3)
+ : license_signature(e1),
+ copyright_signature(e2),
+ copyright_formatter(s1),
+ license_name(s2),
+ license_text(s3){}
+};
+
+std::pair<const license_info*, int> get_licenses();
+
+std::string format_authors_name(const std::string& name);
diff --git a/tools/bcp/main.cpp b/tools/bcp/main.cpp
new file mode 100644
index 000000000..aab15029d
--- /dev/null
+++ b/tools/bcp/main.cpp
@@ -0,0 +1,182 @@
+/*
+ *
+ * Copyright (c) 2003 Dr John Maddock
+ * Use, modification and distribution is 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)
+ *
+ * This file implements the cpp_main entry point
+ */
+
+
+#include <iostream>
+#include <cstring>
+#include <string>
+#include <list>
+#include "bcp.hpp"
+#include <boost/filesystem/path.hpp>
+#include <boost/version.hpp>
+
+#ifdef BOOST_NO_STDC_NAMESPACE
+namespace std{
+ using ::strcmp;
+ using ::strncmp;
+}
+#endif
+
+void show_usage()
+{
+ std::cout <<
+ "Usage:\n"
+ " bcp --list [options] module-list\n"
+ " bcp --list-short [options] module-list\n"
+ " bcp --report [options] module-list html-file\n"
+ " bcp [options] module-list output-path\n"
+ "\n"
+ "Options:\n"
+ " --boost=path sets the location of the boost tree to path\n"
+ " --scan treat the module list as a list of (possibly non-boost)\n"
+ " files to scan for boost dependencies\n"
+ " --svn only copy files under cvs version control\n"
+ " --unix-lines make sure that all copied files use Unix style line endings\n"
+ " --namespace=name rename the boost namespace to name (also changes library names).\n"
+ " --namespace-alias Makes namespace boost an alias of the namespace set with --namespace.\n"
+ "\n"
+ "module-list: a list of boost files or library names to copy\n"
+ "html-file: the name of a html file to which the report will be written\n"
+ "output-path: the path to which files will be copied\n";
+}
+
+bool filesystem_name_check( const std::string & )
+{
+ return true;
+}
+
+int cpp_main(int argc, char* argv[])
+{
+ //
+ // Before anything else replace Boost.filesystem's file
+ // name checker with one that does nothing (we only deal
+ // with files that already exist, if they're not portable
+ // names it's too late for us to do anything about it).
+ //
+ /*boost::filesystem::path::default_name_check(filesystem_name_check);*/
+ //
+ // without arguments just show help:
+ //
+ if(argc < 2)
+ {
+ std::cout << "Error: insufficient arguments, don't know what to do." << std::endl;
+ show_usage();
+ return 1;
+ }
+ //
+ // create the application object:
+ //
+ pbcp_application papp(bcp_application::create());
+ //
+ // work through args, and tell the application
+ // object what ir needs to do:
+ //
+ bool list_mode = false;
+ std::list<const char*> positional_args;
+ for(int i = 1; i < argc; ++i)
+ {
+ if(0 == std::strcmp("-h", argv[i])
+ || 0 == std::strcmp("--help", argv[i]))
+ {
+ show_usage();
+ return 0;
+ }
+ if(0 == std::strcmp("-v", argv[i])
+ || 0 == std::strcmp("--version", argv[i]))
+ {
+ std::cout << "bcp " << (BOOST_VERSION / 100000) << "." << (BOOST_VERSION / 100 % 1000) << "." << (BOOST_VERSION % 100) << std::endl;
+ std::cout << __DATE__ << std::endl;
+ return 0;
+ }
+ else if(0 == std::strcmp("--list", argv[i]))
+ {
+ list_mode = true;
+ papp->enable_list_mode();
+ }
+ else if(0 == std::strcmp("--list-short", argv[i]))
+ {
+ list_mode = true;
+ papp->enable_summary_list_mode();
+ }
+ else if(0 == std::strcmp("--report", argv[i]))
+ {
+ papp->enable_license_mode();
+ }
+ else if(0 == std::strcmp("--cvs", argv[i]))
+ {
+ papp->enable_cvs_mode();
+ }
+ else if(0 == std::strcmp("--svn", argv[i]))
+ {
+ papp->enable_svn_mode();
+ }
+ else if(0 == std::strcmp("--scan", argv[i]))
+ {
+ papp->enable_scan_mode();
+ }
+ else if(0 == std::strcmp("--bsl-convert", argv[i]))
+ {
+ papp->enable_bsl_convert_mode();
+ }
+ else if(0 == std::strcmp("--bsl-summary", argv[i]))
+ {
+ papp->enable_bsl_summary_mode();
+ }
+ else if(0 == std::strcmp("--unix-lines", argv[i]))
+ {
+ papp->enable_unix_lines();
+ }
+ else if(0 == std::strncmp("--boost=", argv[i], 8))
+ {
+ papp->set_boost_path(argv[i] + 8);
+ }
+ else if(0 == std::strncmp("--namespace=", argv[i], 12))
+ {
+ papp->set_namespace(argv[i] + 12);
+ }
+ else if(0 == std::strncmp("--namespace-alias", argv[i], 17))
+ {
+ papp->set_namespace_alias(true);
+ }
+ else if(0 == std::strncmp("--list-namespaces", argv[i], 17))
+ {
+ list_mode = true;
+ papp->set_namespace_list(true);
+ }
+ else if(argv[i][0] == '-')
+ {
+ std::cout << "Error: Unknown argument " << argv[i] << std::endl;
+ show_usage();
+ return 1;
+ }
+ else
+ {
+ positional_args.push_back(argv[i]);
+ }
+ }
+ //
+ // Handle positional args last:
+ //
+ for(std::list<const char*>::const_iterator i = positional_args.begin();
+ i != positional_args.end(); ++i)
+ {
+ if(!list_mode && (i == --positional_args.end()))
+ papp->set_destination(*i);
+ else
+ papp->add_module(*i);
+ }
+ //
+ // run the application object:
+ //
+ return papp->run();
+}
+
+
+
diff --git a/tools/bcp/output_licence_info.cpp b/tools/bcp/output_licence_info.cpp
new file mode 100644
index 000000000..d42268fdb
--- /dev/null
+++ b/tools/bcp/output_licence_info.cpp
@@ -0,0 +1,410 @@
+/*
+ *
+ * Copyright (c) 2003 Dr John Maddock
+ * Use, modification and distribution is 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)
+ *
+ */
+
+#include "licence_info.hpp"
+#include "bcp_imp.hpp"
+#include "fileview.hpp"
+#include <fstream>
+#include <iomanip>
+#include <cstring>
+#include <stdexcept>
+#include <boost/lexical_cast.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/throw_exception.hpp>
+
+//
+// split_path is a small helper for outputting a path name,
+// complete with a link to that path:
+//
+struct split_path
+{
+ const fs::path& root;
+ const fs::path& file;
+ split_path(const fs::path& r, const fs::path& f)
+ : root(r), file(f){}
+private:
+ split_path& operator=(const split_path&);
+};
+
+std::ostream& operator << (std::ostream& os, const split_path& p)
+{
+ os << "<a href=\"" << (p.root / p.file).string() << "\">" << p.file.string() << "</a>";
+ return os;
+}
+
+std::string make_link_target(const std::string& s)
+{
+ // convert an arbitrary string into something suitable
+ // for an <a> name:
+ std::string result;
+ for(unsigned i = 0; i < s.size(); ++i)
+ {
+ result.append(1, static_cast<std::string::value_type>(std::isalnum(s[i]) ? s[i] : '_'));
+ }
+ return result;
+}
+
+
+void bcp_implementation::output_license_info()
+{
+ std::pair<const license_info*, int> licenses = get_licenses();
+
+ std::map<int, license_data>::const_iterator i, j;
+ i = m_license_data.begin();
+ j = m_license_data.end();
+
+ std::ofstream os(m_dest_path.string().c_str());
+ if(!os)
+ {
+ std::string msg("Error opening ");
+ msg += m_dest_path.string();
+ msg += " for output.";
+ std::runtime_error e(msg);
+ boost::throw_exception(e);
+ }
+ os <<
+ "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n"
+ "<html>\n"
+ "<head>\n"
+ "<title>Boost Licence Dependency Information";
+ if(m_module_list.size() == 1)
+ {
+ os << " for " << *(m_module_list.begin());
+ }
+ os <<
+ "</title>\n"
+ "</head>\n"
+ "<body>\n"
+ "<H1>Boost Licence Dependency Information";
+ if(m_module_list.size() == 1)
+ {
+ os << " for " << *(m_module_list.begin());
+ }
+ os <<
+ "</H1>\n"
+ "<H2>Contents</h2>\n"
+ "<pre><a href=\"#input\">Input Information</a>\n";
+ if(!m_bsl_summary_mode)
+ os << "<a href=\"#summary\">Licence Summary</a>\n";
+ os << "<a href=\"#details\">Licence Details</a>\n";
+
+ while(i != j)
+ {
+ // title:
+ os << " <A href=\"#" << make_link_target(licenses.first[i->first].license_name)
+ << "\">" << licenses.first[i->first].license_name << "</a>\n";
+ ++i;
+ }
+
+ os << "<a href=\"#files\">Files with no recognised license</a>\n"
+ "<a href=\"#authors\">Files with no recognised copyright holder</a>\n";
+ if(!m_bsl_summary_mode)
+ {
+ os <<
+ "Moving to the Boost Software License...\n"
+ " <a href=\"#bsl-converted\">Files that can be automatically converted to the Boost Software License</a>\n"
+ " <a href=\"#to-bsl\">Files that can be manually converted to the Boost Software License</a>\n"
+ " <a href=\"#not-to-bsl\">Files that can <b>NOT</b> be moved to the Boost Software License</a>\n"
+ " <a href=\"#need-bsl-authors\">Authors we need to move to the Boost Software License</a>\n"
+ "<a href=\"#copyright\">Copyright Holder Information</a>\n";
+ }
+ os <<
+ "<a href=\"#depend\">File Dependency Information</a>\n"
+ "</pre>";
+
+ //
+ // input Information:
+ //
+ os << "<a name=\"input\"></a><h2>Input Information</h2>\n";
+ if(m_scan_mode)
+ os << "<P>The following files were scanned for boost dependencies:<BR>";
+ else
+ os << "<P>The following Boost modules were checked:<BR>";
+
+ std::list<std::string>::const_iterator si = m_module_list.begin();
+ std::list<std::string>::const_iterator sj = m_module_list.end();
+ while(si != sj)
+ {
+ os << *si << "<BR>";
+ ++si;
+ }
+ os << "</p><p>The Boost path was: <code>" << m_boost_path.string() << "</code></P>";
+ //
+ // extract the boost version number from the boost directory tree,
+ // not from this app (which may have been built from a previous
+ // version):
+ //
+ fileview version_file(m_boost_path / "boost/version.hpp");
+ static const boost::regex version_regex(
+ "^[[:blank:]]*#[[:blank:]]*define[[:blank:]]+BOOST_VERSION[[:blank:]]+(\\d+)");
+ boost::cmatch what;
+ if(boost::regex_search(version_file.begin(), version_file.end(), what, version_regex))
+ {
+ int version = boost::lexical_cast<int>(what.str(1));
+ os << "<p>The Boost version is: " << version / 100000 << "." << version / 100 % 1000 << "." << version % 100 << "</P>\n";
+ }
+
+ //
+ // output each license:
+ //
+ i = m_license_data.begin();
+ j = m_license_data.end();
+ if(!m_bsl_summary_mode)
+ {
+ //
+ // start with the summary:
+ //
+ os << "<a name=\"summary\"></a><h2>Licence Summary</h2>\n";
+ while(i != j)
+ {
+ // title:
+ os <<
+ "<H3>" << licenses.first[i->first].license_name << "</H3>\n";
+ // license text:
+ os << "<BLOCKQUOTE>" << licenses.first[i->first].license_text << "</BLOCKQUOTE>";
+ // Copyright holders:
+ os << "<P>This license is used by " << i->second.authors.size()
+ << " authors and " << i->second.files.size()
+ << " files <a href=\"#" << make_link_target(licenses.first[i->first].license_name) << "\">(see details)</a>";
+ os << "</P></BLOCKQUOTE>\n";
+ ++i;
+ }
+ }
+ //
+ // and now the details:
+ //
+ i = m_license_data.begin();
+ j = m_license_data.end();
+ int license_index = 0;
+ os << "<a name=\"details\"></a><h2>Licence Details</h2>\n";
+ while(i != j)
+ {
+ // title:
+ os <<
+ "<H3><A name=\"" << make_link_target(licenses.first[i->first].license_name)
+ << "\"></a>" << licenses.first[i->first].license_name << "</H3>\n";
+ // license text:
+ os << "<BLOCKQUOTE>" << licenses.first[i->first].license_text << "</BLOCKQUOTE>";
+ if(!m_bsl_summary_mode || (license_index >= 3))
+ {
+ // Copyright holders:
+ os << "<P>This license is used by the following " << i->second.authors.size() << " copyright holders:</P>\n<BLOCKQUOTE><P>";
+ std::set<std::string>::const_iterator x, y;
+ x = i->second.authors.begin();
+ y = i->second.authors.end();
+ while(x != y)
+ {
+ os << *x << "<BR>\n";
+ ++x;
+ }
+ os << "</P></BLOCKQUOTE>\n";
+ // Files using this license:
+ os << "<P>This license applies to the following " << i->second.files.size() << " files:</P>\n<BLOCKQUOTE><P>";
+ std::set<fs::path, path_less>::const_iterator m, n;
+ m = i->second.files.begin();
+ n = i->second.files.end();
+ while(m != n)
+ {
+ os << split_path(m_boost_path, *m) << "<br>\n";
+ ++m;
+ }
+ os << "</P></BLOCKQUOTE>\n";
+ }
+ else
+ {
+ os << "<P>This license is used by " << i->second.authors.size() << " authors (list omitted for brevity).</P>\n";
+ os << "<P>This license applies to " << i->second.files.size() << " files (list omitted for brevity).</P>\n";
+ }
+ ++license_index;
+ ++i;
+ }
+ //
+ // Output list of files not found to be under license control:
+ //
+ os << "<h2><a name=\"files\"></a>Files With No Recognisable Licence</h2>\n"
+ "<P>The following " << m_unknown_licenses.size() << " files had no recognisable license information:</P><BLOCKQUOTE><P>\n";
+ std::set<fs::path, path_less>::const_iterator i2, j2;
+ i2 = m_unknown_licenses.begin();
+ j2 = m_unknown_licenses.end();
+ while(i2 != j2)
+ {
+ os << split_path(m_boost_path, *i2) << "<br>\n";
+ ++i2;
+ }
+ os << "</p></BLOCKQUOTE>";
+ //
+ // Output list of files with no found copyright holder:
+ //
+ os << "<h2><a name=\"authors\"></a>Files With No Recognisable Copyright Holder</h2>\n"
+ "<P>The following " << m_unknown_authors.size() << " files had no recognisable copyright holder:</P>\n<BLOCKQUOTE><P>";
+ i2 = m_unknown_authors.begin();
+ j2 = m_unknown_authors.end();
+ while(i2 != j2)
+ {
+ os << split_path(m_boost_path, *i2) << "<br>\n";
+ ++i2;
+ }
+ os << "</p></BLOCKQUOTE>";
+ if(!m_bsl_summary_mode)
+ {
+ //
+ // Output list of files that have been moved over to the Boost
+ // Software License, along with enough information for human
+ // verification.
+ //
+ os << "<h2><a name=\"bsl-converted\"></a>Files that can be automatically converted to the Boost Software License</h2>\n"
+ << "<P>The following " << m_converted_to_bsl.size() << " files can be automatically converted to the Boost Software License, but require manual verification before they can be committed to CVS:</P>\n";
+ if (!m_converted_to_bsl.empty())
+ {
+ typedef std::map<fs::path, std::pair<std::string, std::string>, path_less>
+ ::const_iterator conv_iterator;
+ conv_iterator i = m_converted_to_bsl.begin(),
+ ie = m_converted_to_bsl.end();
+ int file_num = 1;
+ while (i != ie)
+ {
+ os << "<P>[" << file_num << "] File: <tt>" << split_path(m_boost_path, i->first)
+ << "</tt><br>\n<table border=\"1\">\n <tr>\n <td><pre>"
+ << i->second.first << "</pre></td>\n <td><pre>"
+ << i->second.second << "</pre></td>\n </tr>\n</table>\n";
+ ++i;
+ ++file_num;
+ }
+ }
+ //
+ // Output list of files that could be moved over to the Boost Software License
+ //
+ os << "<h2><a name=\"to-bsl\"></a>Files that could be converted to the Boost Software License</h2>\n"
+ "<P>The following " << m_can_migrate_to_bsl.size() << " files could be manually converted to the Boost Software License, but have not yet been:</P>\n<BLOCKQUOTE><P>";
+ i2 = m_can_migrate_to_bsl.begin();
+ j2 = m_can_migrate_to_bsl.end();
+ while(i2 != j2)
+ {
+ os << split_path(m_boost_path, *i2) << "<br>\n";
+ ++i2;
+ }
+ os << "</p></BLOCKQUOTE>";
+ //
+ // Output list of files that can not be moved over to the Boost Software License
+ //
+ os << "<h2><a name=\"not-to-bsl\"></a>Files that can NOT be converted to the Boost Software License</h2>\n"
+ "<P>The following " << m_cannot_migrate_to_bsl.size() << " files cannot be converted to the Boost Software License because we need the permission of more authors:</P>\n<BLOCKQUOTE><P>";
+ i2 = m_cannot_migrate_to_bsl.begin();
+ j2 = m_cannot_migrate_to_bsl.end();
+ while(i2 != j2)
+ {
+ os << split_path(m_boost_path, *i2) << "<br>\n";
+ ++i2;
+ }
+ os << "</p></BLOCKQUOTE>";
+ //
+ // Output list of authors that we need permission for to move to the BSL
+ //
+ os << "<h2><a name=\"need-bsl-authors\"></a>Authors we need for the BSL</h2>\n"
+ "<P>Permission of the following authors is needed before we can convert to the Boost Software License. The list of authors that have given their permission is contained in <code>more/blanket-permission.txt</code>.</P>\n<BLOCKQUOTE><P>";
+ std::copy(m_authors_for_bsl_migration.begin(), m_authors_for_bsl_migration.end(),
+ std::ostream_iterator<std::string>(os, "<br>\n"));
+ os << "</p></BLOCKQUOTE>";
+ //
+ // output a table of copyright information:
+ //
+ os << "<H2><a name=\"copyright\"></a>Copyright Holder Information</H2><table border=\"1\">\n";
+ std::map<std::string, std::set<fs::path, path_less> >::const_iterator ad, ead;
+ ad = m_author_data.begin();
+ ead = m_author_data.end();
+ while(ad != ead)
+ {
+ os << "<tr><td>" << ad->first << "</td><td>";
+ std::set<fs::path, path_less>::const_iterator fi, efi;
+ fi = ad->second.begin();
+ efi = ad->second.end();
+ while(fi != efi)
+ {
+ os << split_path(m_boost_path, *fi) << " ";
+ ++fi;
+ }
+ os << "</td></tr>\n";
+ ++ad;
+ }
+ os << "</table>\n";
+ }
+
+ //
+ // output file dependency information:
+ //
+ os << "<H2><a name=\"depend\"></a>File Dependency Information</H2><BLOCKQUOTE><pre>\n";
+ std::map<fs::path, fs::path, path_less>::const_iterator dep, last_dep;
+ std::set<fs::path, path_less>::const_iterator fi, efi;
+ fi = m_copy_paths.begin();
+ efi = m_copy_paths.end();
+ // if in summary mode, just figure out the "bad" files and print those only:
+ std::set<fs::path, path_less> bad_paths;
+ if(m_bsl_summary_mode)
+ {
+ bad_paths.insert(m_unknown_licenses.begin(), m_unknown_licenses.end());
+ bad_paths.insert(m_unknown_authors.begin(), m_unknown_authors.end());
+ bad_paths.insert(m_can_migrate_to_bsl.begin(), m_can_migrate_to_bsl.end());
+ bad_paths.insert(m_cannot_migrate_to_bsl.begin(), m_cannot_migrate_to_bsl.end());
+ typedef std::map<fs::path, std::pair<std::string, std::string>, path_less>
+ ::const_iterator conv_iterator;
+ conv_iterator i = m_converted_to_bsl.begin(),
+ ie = m_converted_to_bsl.end();
+ while(i != ie)
+ {
+ bad_paths.insert(i->first);
+ ++i;
+ }
+ fi = bad_paths.begin();
+ efi = bad_paths.end();
+ os << "<P>For brevity, only files not under the BSL are shown</P>\n";
+ }
+ while(fi != efi)
+ {
+ os << split_path(m_boost_path, *fi);
+ dep = m_dependencies.find(*fi);
+ last_dep = m_dependencies.end();
+ std::set<fs::path, path_less> seen_deps;
+ if (dep != last_dep)
+ while(true)
+ {
+ os << " -> ";
+ if(fs::exists(m_boost_path / dep->second))
+ os << split_path(m_boost_path, dep->second);
+ else if(fs::exists(dep->second))
+ os << split_path(fs::path(), dep->second);
+ else
+ os << dep->second.string();
+ if(seen_deps.find(dep->second) != seen_deps.end())
+ {
+ os << " <I>(Circular dependency!)</I>";
+ break; // circular dependency!!!
+ }
+ seen_deps.insert(dep->second);
+ last_dep = dep;
+ dep = m_dependencies.find(dep->second);
+ if((dep == m_dependencies.end()) || (0 == compare_paths(dep->second, last_dep->second)))
+ break;
+ }
+ os << "\n";
+ ++fi;
+ }
+ os << "</pre></BLOCKQUOTE>\n";
+
+ os << "</body></html>\n";
+
+ if(!os)
+ {
+ std::string msg("Error writing to ");
+ msg += m_dest_path.string();
+ msg += ".";
+ std::runtime_error e(msg);
+ boost::throw_exception(e);
+ }
+
+}
diff --git a/tools/bcp/path_operations.cpp b/tools/bcp/path_operations.cpp
new file mode 100644
index 000000000..aebbc4e6f
--- /dev/null
+++ b/tools/bcp/path_operations.cpp
@@ -0,0 +1,41 @@
+/*
+ *
+ * Copyright (c) 2003 Dr John Maddock
+ * Use, modification and distribution is 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)
+ *
+ * This file implements path comparisons
+ */
+
+
+#include "bcp_imp.hpp"
+#include <cctype>
+
+#ifdef BOOST_NO_STDC_NAMESPACE
+namespace std{
+ using ::tolower;
+}
+#endif
+
+
+int compare_paths(const fs::path& a, const fs::path& b)
+{
+ const std::string& as = a.generic_string();
+ const std::string& bs = b.generic_string();
+ std::string::const_iterator i, j, k, l;
+ i = as.begin();
+ j = as.end();
+ k = bs.begin();
+ l = bs.end();
+ while(i != j)
+ {
+ if(k == l)
+ return -1;
+ int r = std::tolower(*i) - std::tolower(*k);
+ if(r) return r;
+ ++i;
+ ++k;
+ }
+ return (k == l) ? 0 : 1;
+}
diff --git a/tools/bcp/scan_cvs_path.cpp b/tools/bcp/scan_cvs_path.cpp
new file mode 100644
index 000000000..6d2eb3a60
--- /dev/null
+++ b/tools/bcp/scan_cvs_path.cpp
@@ -0,0 +1,147 @@
+/*
+ *
+ * Copyright (c) 2003-7 John Maddock
+ * Copyright (c) 2007 Bjorn Roald
+ * Use, modification and distribution is 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)
+ *
+ * This file implements the following:
+ * void bcp_implementation::scan_cvs_path(const fs::path& p)
+ */
+
+
+
+#include "bcp_imp.hpp"
+#include "fileview.hpp"
+#include <boost/regex.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/detail/workaround.hpp>
+#include <iostream>
+
+void bcp_implementation::scan_cvs_path(const fs::path& p)
+{
+ //
+ // scan through the cvs admin files to build a list
+ // of all the files under cvs version control
+ // and whether they are text or binary:
+ //
+ static const char* file_list[] = { "CVS/Entries", "CVS/Entries.Log" };
+ static const boost::regex file_expression("^(?:A\\s+)?/([^/\\n]+)/[^/\\n]*/[^/\\n]*/[^k/\\n]*(kb[^/\\n]*)?/[^/\\n]*");
+ static const boost::regex dir_expression("^(?:A\\s+)?D/([^/\\n]+)/");
+ static const int file_subs[] = {1,2,};
+
+ for(std::size_t entry = 0; entry < sizeof(file_list)/sizeof(file_list[0]); ++entry)
+ {
+ fs::path entries(m_boost_path / p / file_list[entry]);
+ if(fs::exists(entries))
+ {
+ fileview view(entries);
+ boost::regex_token_iterator<const char*> i(view.begin(), view.end(), dir_expression, 1);
+ boost::regex_token_iterator<const char*> j;
+ while(i != j)
+ {
+ fs::path recursion_dir(p / i->str());
+ scan_cvs_path(recursion_dir);
+ ++i;
+ }
+ #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570))
+ std::vector<int> v(file_subs, file_subs + 2);
+ i = boost::regex_token_iterator<const char*>(view.begin(), view.end(), file_expression, v);
+ #else
+ i = boost::regex_token_iterator<const char*>(view.begin(), view.end(), file_expression, file_subs);
+ #endif
+ while(i != j)
+ {
+ fs::path file = p / i->str();
+ ++i;
+ bool binary = i->length() ? true : false;
+ ++i;
+ m_cvs_paths[file] = binary;
+ }
+
+ }
+ }
+}
+
+void bcp_implementation::scan_svn_path(const fs::path& p)
+{
+ //
+ // scan through the svn entries files to build a list
+ // of all the files under svn version control
+ // and whether they are text or binary:
+ //
+ static const boost::regex entry_expression("^\\f([^\\f]*)");
+ static const boost::regex entry_line_expression("\\n[[:blank:]]*([^\\n]*)");
+ // static const boost::regex
+ // mime_type_expression("\\nsvn:mime-type\\nV [[digit]]*\\n([^/]*)[^\\n]*");
+
+ fs::path entries(m_boost_path / p / ".svn" / "entries");
+ if(fs::exists(entries))
+ {
+ fileview view(entries);
+ boost::cregex_token_iterator
+ i(view.begin(), view.end(), entry_expression, 1), j;
+
+ while(i != j) // entries
+ {
+ std::string entr = i->str();
+ boost::sregex_token_iterator
+ atr_it(entr.begin(), entr.end(), entry_line_expression, 1), atr_j;
+
+ if(atr_it != atr_j)
+ {
+ std::string name = atr_it->str(); // name of file or directory
+ fs::path fpath = p / name;
+ if(++atr_it != atr_j)
+ {
+ std::string kind = atr_it->str();
+ if(kind == "file")
+ {
+ // find if binary, we asume text unless mime type is
+ // set in property file
+ bool binary = false; //
+
+ // skip some lines type | example
+ if( ++atr_it != atr_j && // revnum |
+ ++atr_it != atr_j && // url |
+ ++atr_it != atr_j && // repos |
+ ++atr_it != atr_j && // scedule attr |
+ ++atr_it != atr_j && // text timestamp | 2007-09-02T...
+ ++atr_it != atr_j && // checksum | 58f4bfa7860...
+ ++atr_it != atr_j && // cmt_date | 2007-05-09T...
+ ++atr_it != atr_j && // cmt_rev | 37654
+ ++atr_it != atr_j && // cmt_author | dgregor
+ ++atr_it != atr_j ) // has_props | has-props
+ {
+ if(atr_it->str() == "has-props")
+ {
+ // we need to check properties file for mime-type
+ // that does not start with "text/", if found file is binary
+ fs::path properties(m_boost_path / p / ".svn" / "prop-base"
+ / (name + ".svn-base") );
+ if(fs::exists(properties))
+ {
+ fileview prop(properties);
+
+ static const boost::regex mime_type(
+ "svn:mime-type[[:blank:]]*(?:\\n|\\r|\\r\\n)[^\\r\\n]*(?:\\n|\\r|\\r\\n)[[:blank:]]*text/");
+ binary = regex_search(prop.begin(), prop.end(), mime_type) ? false : true;
+ }
+ }
+ }
+ m_cvs_paths[fpath] = binary;
+ } // kind == "file"
+ else if(kind == "dir")
+ {
+ scan_svn_path(fpath); // recursion for directory entries
+ }
+ // else
+ // std::cerr << "WARNING: unknown entry kind for entry " << name
+ // << "in " << entries << std::endl;
+ }
+ }
+ ++i;
+ } // while
+ }
+}
diff --git a/tools/bcp/scan_licence.cpp b/tools/bcp/scan_licence.cpp
new file mode 100644
index 000000000..c061583a2
--- /dev/null
+++ b/tools/bcp/scan_licence.cpp
@@ -0,0 +1,275 @@
+/*
+ *
+ * Copyright (c) 2003 Dr John Maddock
+ * Use, modification and distribution is 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)
+ *
+ */
+
+#include "licence_info.hpp"
+#include "bcp_imp.hpp"
+#include "fileview.hpp"
+#include <fstream>
+#include <iostream>
+
+
+const int boost_license_lines = 3;
+static const std::string boost_license_text[boost_license_lines] = {
+ "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)"
+};
+
+fileview::const_iterator
+context_before_license(const fileview& v, fileview::const_iterator start,
+ int context_lines = 3)
+{
+ char last_char = '\0';
+ while (start != v.begin() && context_lines >= 0) {
+ if ((*start == '\r') || (*start == '\n')
+ && ((last_char == *start) || ((last_char != '\r') && (last_char != '\n'))))
+ --context_lines;
+
+ last_char = *start;
+ --start;
+ }
+
+ // Unless we hit the beginning, we need to step forward one to start
+ // on the next line.
+ if (start != v.begin()) ++start;
+
+ return start;
+}
+
+fileview::const_iterator
+context_after_license(const fileview& v, fileview::const_iterator end,
+ int context_lines = 3)
+{
+ char last_char = '\0';
+ while (end != v.end() && context_lines >= 0) {
+ if (*end == '\r' || *end == '\n'
+ && (last_char == *end || (last_char != '\r' && last_char != '\n')))
+ --context_lines;
+
+ last_char = *end;
+ ++end;
+ }
+
+ return end;
+}
+
+static std::string
+find_prefix(const fileview& v, fileview::const_iterator start_of_line)
+{
+ while (start_of_line != v.begin()
+ && *start_of_line != '\n'
+ && *start_of_line != '\r')
+ --start_of_line;
+ if (start_of_line != v.begin())
+ ++start_of_line;
+
+ fileview::const_iterator first_noncomment_char = start_of_line;
+ while (*first_noncomment_char == '/'
+ || *first_noncomment_char == '*'
+ || *first_noncomment_char == ' '
+ || *first_noncomment_char == '#')
+ ++first_noncomment_char;
+
+ return std::string(start_of_line, first_noncomment_char);
+}
+
+static std::string
+html_escape(fileview::const_iterator first, fileview::const_iterator last)
+{
+ std::string result;
+ while (first != last) {
+ switch (*first) {
+ case '<': result += "&lt;"; break;
+ case '>': result += "&gt;"; break;
+ case '&': result += "&amp;"; break;
+ default: result += *first;
+ }
+ ++first;
+ }
+ return result;
+}
+
+static bool is_non_bsl_license(int index)
+{
+ return index > 2;
+}
+
+void bcp_implementation::scan_license(const fs::path& p, const fileview& v)
+{
+ std::pair<const license_info*, int> licenses = get_licenses();
+ //
+ // scan file for all the licenses in the list:
+ //
+ int license_count = 0;
+ int author_count = 0;
+ int nonbsl_author_count = 0;
+ bool has_non_bsl_license = false;
+ fileview::const_iterator start_of_license = v.begin(),
+ end_of_license = v.end();
+ bool start_in_middle_of_line = false;
+
+ for(int i = 0; i < licenses.second; ++i)
+ {
+ boost::match_results<fileview::const_iterator> m;
+ if(boost::regex_search(v.begin(), v.end(), m, licenses.first[i].license_signature))
+ {
+ start_of_license = m[0].first;
+ end_of_license = m[0].second;
+
+ if (is_non_bsl_license(i) && i < licenses.second - 1)
+ has_non_bsl_license = true;
+
+ // add this license to the list:
+ m_license_data[i].files.insert(p);
+ ++license_count;
+ //
+ // scan for the associated copyright declarations:
+ //
+ boost::regex_iterator<const char*> cpy(v.begin(), v.end(), licenses.first[i].copyright_signature);
+ boost::regex_iterator<const char*> ecpy;
+ while(cpy != ecpy)
+ {
+#if 0
+ // Not dealing with copyrights because we don't have the years
+ if ((*cpy)[0].first < start_of_license)
+ start_of_license = (*cpy)[0].first;
+ if ((*cpy)[0].second > end_of_license)
+ end_of_license = (*cpy)[0].second;
+#endif
+
+ // extract the copy holders as a list:
+ std::string author_list = cpy->format(licenses.first[i].copyright_formatter, boost::format_all);
+ // now enumerate that list for all the names:
+ static const boost::regex author_separator("(?:\\s*,(?!\\s*(?:inc|ltd)\\b)\\s*|\\s+(,\\s*)?(and|&)\\s+)|by\\s+", boost::regex::perl | boost::regex::icase);
+ boost::regex_token_iterator<std::string::const_iterator> atr(author_list.begin(), author_list.end(), author_separator, -1);
+ boost::regex_token_iterator<std::string::const_iterator> eatr;
+ while(atr != eatr)
+ {
+ // get the reformatted authors name:
+ std::string name = format_authors_name(*atr);
+ // add to list of authors for this file:
+ if(name.size() && name[0] != '-')
+ {
+ m_license_data[i].authors.insert(name);
+ // add file to author index:
+ m_author_data[name].insert(p);
+ ++author_count;
+
+ // If this is not the Boost Software License (license 0), and the author hasn't given
+ // blanket permission, note this for the report.
+ if (has_non_bsl_license
+ && m_bsl_authors.find(name) == m_bsl_authors.end()) {
+ ++nonbsl_author_count;
+ m_authors_for_bsl_migration.insert(name);
+ }
+ }
+ ++atr;
+ }
+ ++cpy;
+ }
+
+ while (start_of_license != v.begin()
+ && *start_of_license != '\r'
+ && *start_of_license != '\n'
+ && *start_of_license != '.')
+ --start_of_license;
+
+ if (start_of_license != v.begin()) {
+ if (*start_of_license == '.')
+ start_in_middle_of_line = true;
+ ++start_of_license;
+ }
+
+ while (end_of_license != v.end()
+ && *end_of_license != '\r'
+ && *end_of_license != '\n')
+ ++end_of_license;
+ }
+ }
+ if(license_count == 0)
+ m_unknown_licenses.insert(p);
+ if(license_count && !author_count)
+ m_unknown_authors.insert(p);
+
+ if (has_non_bsl_license) {
+ bool converted = false;
+ if (nonbsl_author_count == 0
+ && license_count == 1) {
+ // Grab a few lines of context
+ fileview::const_iterator context_start =
+ context_before_license(v, start_of_license);
+ fileview::const_iterator context_end =
+ context_after_license(v, end_of_license);
+
+ // TBD: For files that aren't C++ code, this will have to
+ // change.
+ std::string prefix = find_prefix(v, start_of_license);
+
+ // Create enough information to permit manual verification of
+ // the correctness of the transformation
+ std::string before_conversion =
+ html_escape(context_start, start_of_license);
+ before_conversion += "<b>";
+ before_conversion += html_escape(start_of_license, end_of_license);
+ before_conversion += "</b>";
+ before_conversion += html_escape(end_of_license, context_end);
+
+ std::string after_conversion =
+ html_escape(context_start, start_of_license);
+ if (start_in_middle_of_line)
+ after_conversion += '\n';
+
+ after_conversion += "<b>";
+ for (int i = 0; i < boost_license_lines; ++i) {
+ if (i > 0) after_conversion += '\n';
+ after_conversion += prefix + boost_license_text[i];
+ }
+ after_conversion += "</b>";
+ after_conversion += html_escape(end_of_license, context_end);
+
+ m_converted_to_bsl[p] =
+ std::make_pair(before_conversion, after_conversion);
+
+ // Perform the actual conversion
+ if (m_bsl_convert_mode) {
+ try{
+ std::ofstream out((m_boost_path / p).string().c_str());
+ if (!out) {
+ std::string msg("Cannot open file for license conversion: ");
+ msg += p.string();
+ std::runtime_error e(msg);
+ boost::throw_exception(e);
+ }
+
+ out << std::string(v.begin(), start_of_license);
+ if (start_in_middle_of_line)
+ out << std::endl;
+
+ for (int j = 0; j < boost_license_lines; ++j) {
+ if (j > 0) out << std::endl;
+ out << prefix << boost_license_text[j];
+ }
+ out << std::string(end_of_license, v.end());
+
+ converted = true;
+ }
+ catch(const std::exception& e)
+ {
+ std::cerr << e.what() << std::endl;
+ }
+ }
+ }
+
+ if (!converted) {
+ if (nonbsl_author_count > 0) m_cannot_migrate_to_bsl.insert(p);
+ else m_can_migrate_to_bsl.insert(p);
+ }
+ }
+}
+
diff --git a/tools/bcp/test/Jamfile.v2 b/tools/bcp/test/Jamfile.v2
new file mode 100644
index 000000000..bea522489
--- /dev/null
+++ b/tools/bcp/test/Jamfile.v2
@@ -0,0 +1,25 @@
+# (C) Copyright John Maddock 2006.
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+
+path-constant boost-path : ../../.. ;
+
+run
+ # sources
+ ../add_dependent_lib.cpp ../add_path.cpp ../bcp_imp.cpp ../copy_path.cpp ../file_types.cpp
+ ../fileview.cpp ../main.cpp ../path_operations.cpp ../scan_cvs_path.cpp
+ ../licence_info.cpp ../scan_licence.cpp ../output_licence_info.cpp
+ /boost/filesystem//boost_filesystem
+ /boost/regex//boost_regex
+ /boost/test//boost_prg_exec_monitor
+ : # args
+ --boost=$(boost-path) --list boost
+ : # input-files
+ : # requirements
+ release
+ : # target-name
+ bcp-test
+ : # default-build
+ release
+ ;
+