231 lines
7.8 KiB
C++
231 lines
7.8 KiB
C++
/*
|
|
*
|
|
* 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"));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|