diff options
Diffstat (limited to '')
-rw-r--r-- | src/boost/tools/bcp/add_dependent_lib.cpp | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/src/boost/tools/bcp/add_dependent_lib.cpp b/src/boost/tools/bcp/add_dependent_lib.cpp new file mode 100644 index 000000000..48529142f --- /dev/null +++ b/src/boost/tools/bcp/add_dependent_lib.cpp @@ -0,0 +1,230 @@ +/* + * + * 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*(?:BOOST[_A-Z]+\\s*)?" + "\\{" // start of definition + "|" + "(\\<\\w+\\>)" // Maybe class name + "\\s*" + "(?:<[^>;{]*>)?" // Maybe template specialisation + "::\\s*" + "~?\\1" // function name, same as class name + "\\s*" + "\\(" + "[^\\(\\);{}]*" // argument list + "\\)" + "\\s*(?:BOOST[_A-Z]+\\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*(?:BOOST[_A-Z]+\\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")); + } + } + if(fs::exists(m_boost_path / "libs" / libname / "config")) + { + if(!m_dependencies.count(fs::path("libs") / libname / "config")) + { + m_dependencies[fs::path("libs") / libname / "config"] = p; // set up dependency tree + add_path(fs::path("libs") / libname / "config"); + //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")); + } + } + } + } + } +} |