]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * | |
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) | |
7 | * | |
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) | |
13 | */ | |
14 | ||
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> | |
20 | #include <iostream> | |
21 | ||
22 | // | |
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. | |
25 | // | |
26 | ||
27 | static std::map<std::string, boost::regex> scanner; | |
28 | ||
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; | |
32 | ||
33 | static void init_library_scanner(const fs::path& p, bool cvs_mode, const std::string& libname, bool recurse = false) | |
34 | { | |
35 | /* | |
36 | if(free_function_names.count(libname) == 0) | |
37 | { | |
38 | free_function_names[libname] = "[\\x0]"; | |
39 | class_names[libname] = "[\\x0]"; | |
40 | variable_names[libname] = "[\\x0]"; | |
41 | } | |
42 | */ | |
43 | // | |
44 | // Don't add files created by build system: | |
45 | // | |
46 | if((p.leaf() == "bin") || (p.leaf() == "bin-stage")) | |
47 | return; | |
48 | // | |
49 | // Don't add version control directories: | |
50 | // | |
51 | if((p.leaf() == "CVS") || (p.leaf() == ".svn")) | |
52 | return; | |
53 | // | |
54 | // don't add directories not under version control: | |
55 | // | |
56 | if(cvs_mode && !fs::exists(p / "CVS/Entries")) | |
57 | return; | |
58 | if(cvs_mode && !fs::exists(p / ".svn/entries")) | |
59 | return; | |
60 | // | |
61 | // Enumerate files and directories: | |
62 | // | |
63 | fs::directory_iterator i(p); | |
64 | fs::directory_iterator j; | |
65 | while(i != j) | |
66 | { | |
67 | if(fs::is_directory(*i)) | |
68 | init_library_scanner(*i, cvs_mode, libname, true); | |
69 | if(bcp_implementation::is_source_file(*i)) | |
70 | { | |
71 | static boost::regex function_scanner( | |
72 | "(?|" // Branch reset group | |
73 | "(?:\\<\\w+\\>[^>;{},:]*)" // Return type | |
74 | "(?:" | |
75 | "(\\<\\w+\\>)" // Maybe class name | |
76 | "\\s*" | |
77 | "(?:<[^>;{]*>)?" // Maybe template specialisation | |
78 | "::\\s*)?" | |
79 | "(\\<(?!throw|if|while|for|catch)\\w+\\>)" // function name | |
80 | "\\s*" | |
81 | "\\(" | |
82 | "[^\\(\\);{}]*" // argument list | |
83 | "\\)" | |
84 | "\\s*(?:BOOST[_A-Z]+\\s*)?" | |
85 | "\\{" // start of definition | |
86 | "|" | |
87 | "(\\<\\w+\\>)" // Maybe class name | |
88 | "\\s*" | |
89 | "(?:<[^>;{]*>)?" // Maybe template specialisation | |
90 | "::\\s*" | |
91 | "~?\\1" // function name, same as class name | |
92 | "\\s*" | |
93 | "\\(" | |
94 | "[^\\(\\);{}]*" // argument list | |
95 | "\\)" | |
96 | "\\s*(?:BOOST[_A-Z]+\\s*)?" | |
97 | "\\{" // start of definition | |
98 | ")" // end branch reset | |
99 | ); | |
100 | fileview view(*i); | |
101 | boost::regex_iterator<const char*> a(view.begin(), view.end(), function_scanner); | |
102 | boost::regex_iterator<const char*> b; | |
103 | while(a != b) | |
104 | { | |
105 | if((*a)[1].matched) | |
106 | { | |
107 | std::string n = a->str(1); | |
108 | class_names[libname].insert(n); | |
109 | } | |
110 | else | |
111 | { | |
112 | std::string n = a->str(2); | |
113 | free_function_names[libname].insert(n); | |
114 | } | |
115 | ++a; | |
116 | } | |
117 | } | |
118 | ++i; | |
119 | } | |
120 | ||
121 | if(recurse == false) | |
122 | { | |
123 | // | |
124 | // Build the regular expressions: | |
125 | // | |
126 | const char* e1 = | |
127 | "^(?>[[:blank:]]*)(?!#)[^;{}\\r\\n]*" | |
128 | "(?|" | |
129 | "(?:class|struct)[^:;{}#]*" | |
130 | "("; | |
131 | // list of class names goes here... | |
132 | const char* e2 = | |
133 | ")\\s*(?:<[^;{>]*>\\s*)?(?::[^;{]*)?\\{" | |
134 | "|" | |
135 | "\\<(?!return)\\w+\\>[^:;{}#=<>!~%.\\w]*("; | |
136 | // List of function names goes here... | |
137 | const char* e3 = | |
138 | ")\\s*\\([^;()]*\\)\\s*(?:BOOST[_A-Z]+\\s*)?;)"; | |
139 | ||
140 | std::string class_name_list; | |
141 | std::set<std::string>::const_iterator i = class_names[libname].begin(), j = class_names[libname].end(); | |
142 | if(i != j) | |
143 | { | |
144 | class_name_list = *i; | |
145 | ++i; | |
146 | while(i != j) | |
147 | { | |
148 | class_name_list += "|" + *i; | |
149 | ++i; | |
150 | } | |
151 | } | |
152 | else | |
153 | { | |
154 | class_name_list = "[\\x0]"; | |
155 | } | |
156 | std::string function_name_list; | |
157 | i = free_function_names[libname].begin(); | |
158 | j = free_function_names[libname].end(); | |
159 | if(i != j) | |
160 | { | |
161 | function_name_list = *i; | |
162 | ++i; | |
163 | while(i != j) | |
164 | { | |
165 | function_name_list += "|" + *i; | |
166 | ++i; | |
167 | } | |
168 | } | |
169 | else | |
170 | { | |
171 | function_name_list = "[\\x0]"; | |
172 | } | |
173 | ||
174 | scanner[libname] = boost::regex(e1 + class_name_list + e2 + function_name_list + e3); | |
175 | } | |
176 | } | |
177 | ||
178 | void bcp_implementation::add_dependent_lib(const std::string& libname, const fs::path& p, const fileview& view) | |
179 | { | |
180 | // | |
181 | // if the boost library libname has source associated with it | |
182 | // then add the source to our list: | |
183 | // | |
184 | if(fs::exists(m_boost_path / "libs" / libname / "src")) | |
185 | { | |
186 | if(!m_dependencies.count(fs::path("libs") / libname / "src")) | |
187 | { | |
188 | if(scanner.count(libname) == 0) | |
189 | init_library_scanner(m_boost_path / "libs" / libname / "src", m_cvs_mode, libname); | |
190 | boost::cmatch what; | |
191 | if(regex_search(view.begin(), view.end(), what, scanner[libname])) | |
192 | { | |
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"); | |
198 | ||
199 | if(fs::exists(m_boost_path / "libs" / libname / "build")) | |
200 | { | |
201 | if(!m_dependencies.count(fs::path("libs") / libname / "build")) | |
202 | { | |
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")); | |
211 | } | |
212 | } | |
213 | if(fs::exists(m_boost_path / "libs" / libname / "config")) | |
214 | { | |
215 | if(!m_dependencies.count(fs::path("libs") / libname / "config")) | |
216 | { | |
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")); | |
225 | } | |
226 | } | |
227 | } | |
228 | } | |
229 | } | |
230 | } |