3 * Copyright (c) 2009 Dr John Maddock
4 * Use, modification and distribution is subject to the
5 * Boost Software License, Version 1.0. (See accompanying file
6 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 * This file implements the following:
9 * void bcp_implementation::add_path(const fs::path& p)
10 * void bcp_implementation::add_directory(const fs::path& p)
11 * void bcp_implementation::add_file(const fs::path& p)
12 * void bcp_implementation::add_dependent_lib(const std::string& libname, const fs::path& p, const fileview& view)
15 #include "bcp_imp.hpp"
16 #include "fileview.hpp"
17 #include <boost/regex.hpp>
18 #include <boost/filesystem/operations.hpp>
19 #include <boost/filesystem/exception.hpp>
23 // This file contains the code required to work out whether the source/header file being scanned
24 // is actually dependent upon some library's source code or not.
27 static std::map
<std::string
, boost::regex
> scanner
;
29 static std::map
<std::string
, std::set
<std::string
> > free_function_names
;
30 static std::map
<std::string
, std::set
<std::string
> > class_names
;
31 static std::map
<std::string
, std::set
<std::string
> > variable_names
;
33 static void init_library_scanner(const fs::path
& p
, bool cvs_mode
, const std::string
& libname
, bool recurse
= false)
36 if(free_function_names.count(libname) == 0)
38 free_function_names[libname] = "[\\x0]";
39 class_names[libname] = "[\\x0]";
40 variable_names[libname] = "[\\x0]";
44 // Don't add files created by build system:
46 if((p
.leaf() == "bin") || (p
.leaf() == "bin-stage"))
49 // Don't add version control directories:
51 if((p
.leaf() == "CVS") || (p
.leaf() == ".svn"))
54 // don't add directories not under version control:
56 if(cvs_mode
&& !fs::exists(p
/ "CVS/Entries"))
58 if(cvs_mode
&& !fs::exists(p
/ ".svn/entries"))
61 // Enumerate files and directories:
63 fs::directory_iterator
i(p
);
64 fs::directory_iterator j
;
67 if(fs::is_directory(*i
))
68 init_library_scanner(*i
, cvs_mode
, libname
, true);
69 if(bcp_implementation::is_source_file(*i
))
71 static boost::regex
function_scanner(
72 "(?|" // Branch reset group
73 "(?:\\<\\w+\\>[^>;{},:]*)" // Return type
75 "(\\<\\w+\\>)" // Maybe class name
77 "(?:<[^>;{]*>)?" // Maybe template specialisation
79 "(\\<(?!throw|if|while|for|catch)\\w+\\>)" // function name
82 "[^\\(\\);{}]*" // argument list
84 "\\s*(?:BOOST[_A-Z]+\\s*)?"
85 "\\{" // start of definition
87 "(\\<\\w+\\>)" // Maybe class name
89 "(?:<[^>;{]*>)?" // Maybe template specialisation
91 "~?\\1" // function name, same as class name
94 "[^\\(\\);{}]*" // argument list
96 "\\s*(?:BOOST[_A-Z]+\\s*)?"
97 "\\{" // start of definition
98 ")" // end branch reset
101 boost::regex_iterator
<const char*> a(view
.begin(), view
.end(), function_scanner
);
102 boost::regex_iterator
<const char*> b
;
107 std::string n
= a
->str(1);
108 class_names
[libname
].insert(n
);
112 std::string n
= a
->str(2);
113 free_function_names
[libname
].insert(n
);
124 // Build the regular expressions:
127 "^(?>[[:blank:]]*)(?!#)[^;{}\\r\\n]*"
129 "(?:class|struct)[^:;{}#]*"
131 // list of class names goes here...
133 ")\\s*(?:<[^;{>]*>\\s*)?(?::[^;{]*)?\\{"
135 "\\<(?!return)\\w+\\>[^:;{}#=<>!~%.\\w]*(";
136 // List of function names goes here...
138 ")\\s*\\([^;()]*\\)\\s*(?:BOOST[_A-Z]+\\s*)?;)";
140 std::string class_name_list
;
141 std::set
<std::string
>::const_iterator i
= class_names
[libname
].begin(), j
= class_names
[libname
].end();
144 class_name_list
= *i
;
148 class_name_list
+= "|" + *i
;
154 class_name_list
= "[\\x0]";
156 std::string function_name_list
;
157 i
= free_function_names
[libname
].begin();
158 j
= free_function_names
[libname
].end();
161 function_name_list
= *i
;
165 function_name_list
+= "|" + *i
;
171 function_name_list
= "[\\x0]";
174 scanner
[libname
] = boost::regex(e1
+ class_name_list
+ e2
+ function_name_list
+ e3
);
178 void bcp_implementation::add_dependent_lib(const std::string
& libname
, const fs::path
& p
, const fileview
& view
)
181 // if the boost library libname has source associated with it
182 // then add the source to our list:
184 if(fs::exists(m_boost_path
/ "libs" / libname
/ "src"))
186 if(!m_dependencies
.count(fs::path("libs") / libname
/ "src"))
188 if(scanner
.count(libname
) == 0)
189 init_library_scanner(m_boost_path
/ "libs" / libname
/ "src", m_cvs_mode
, libname
);
191 if(regex_search(view
.begin(), view
.end(), what
, scanner
[libname
]))
193 std::cout
<< "INFO: tracking source dependencies of library " << libname
194 << " due to presence of \"" << what
<< "\" in file " << p
<< std::endl
;
195 //std::cout << "Full text match was: " << what << std::endl;
196 m_dependencies
[fs::path("libs") / libname
/ "src"] = p
; // set up dependency tree
197 add_path(fs::path("libs") / libname
/ "src");
199 if(fs::exists(m_boost_path
/ "libs" / libname
/ "build"))
201 if(!m_dependencies
.count(fs::path("libs") / libname
/ "build"))
203 m_dependencies
[fs::path("libs") / libname
/ "build"] = p
; // set up dependency tree
204 add_path(fs::path("libs") / libname
/ "build");
205 //m_dependencies[fs::path("boost-build.jam")] = p;
206 //add_path(fs::path("boost-build.jam"));
207 m_dependencies
[fs::path("Jamroot")] = p
;
208 add_path(fs::path("Jamroot"));
209 //m_dependencies[fs::path("tools/build")] = p;
210 //add_path(fs::path("tools/build"));
213 if(fs::exists(m_boost_path
/ "libs" / libname
/ "config"))
215 if(!m_dependencies
.count(fs::path("libs") / libname
/ "config"))
217 m_dependencies
[fs::path("libs") / libname
/ "config"] = p
; // set up dependency tree
218 add_path(fs::path("libs") / libname
/ "config");
219 //m_dependencies[fs::path("boost-build.jam")] = p;
220 //add_path(fs::path("boost-build.jam"));
221 m_dependencies
[fs::path("Jamroot")] = p
;
222 add_path(fs::path("Jamroot"));
223 //m_dependencies[fs::path("tools/build")] = p;
224 //add_path(fs::path("tools/build"));