1 | /* |
2 | * |
3 | * Copyright (c) 2003 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 | void bcp_implementation::add_path(const fs::path& p) |
24 | { |
25 | fs::path normalized_path = p; |
26 | normalized_path.normalize(); |
27 | if(fs::exists(p: m_boost_path / normalized_path)) |
28 | { |
29 | if(fs::is_directory(p: m_boost_path / normalized_path)) |
30 | add_directory(p: normalized_path); |
31 | else |
32 | add_file(p: normalized_path); |
33 | } |
34 | else |
35 | { |
36 | std::cerr << "CAUTION: dependent file " << p.string() << " does not exist." << std::endl; |
37 | std::cerr << " Found while scanning file " << m_dependencies[p].string() << std::endl; |
38 | } |
39 | } |
40 | |
41 | void bcp_implementation::add_directory(const fs::path& p) |
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(m_cvs_mode && !fs::exists(p: m_boost_path / p / "CVS/Entries" )) |
57 | return; |
58 | if(m_svn_mode && !fs::exists(p: m_boost_path / p / ".svn/entries" )) |
59 | return; |
60 | // |
61 | // enermerate files and directories: |
62 | // |
63 | fs::directory_iterator i(m_boost_path / p); |
64 | fs::directory_iterator j; |
65 | while(i != j) |
66 | { |
67 | // |
68 | // we need to convert *i back into |
69 | // a relative path, what follows is a hack: |
70 | // |
71 | std::string s(i->path().string()); |
72 | if(m_boost_path.string().size()) |
73 | s.erase(pos: 0, n: m_boost_path.string().size() + 1); |
74 | fs::path np = s; |
75 | if(!m_dependencies.count(x: np)) |
76 | { |
77 | m_dependencies[np] = p; // set up dependency tree |
78 | add_path(p: np); |
79 | } |
80 | ++i; |
81 | } |
82 | } |
83 | |
84 | void bcp_implementation::add_file(const fs::path& p) |
85 | { |
86 | // |
87 | // if the file does not exist in cvs then don't do anything with it: |
88 | // |
89 | if((m_cvs_mode || m_svn_mode) && (m_cvs_paths.find(x: p) == m_cvs_paths.end())) |
90 | return; |
91 | // |
92 | // if we've already seen the file return: |
93 | // |
94 | if(m_copy_paths.find(x: p) != m_copy_paths.end()) |
95 | return; |
96 | // |
97 | // add the file to our list: |
98 | // |
99 | m_copy_paths.insert(x: p); |
100 | // |
101 | // if this is a source file, scan for dependencies: |
102 | // |
103 | if(is_source_file(p)) |
104 | { |
105 | add_file_dependencies(p, scanfile: false); |
106 | } |
107 | if(is_jam_file(p) && m_namespace_name.size() && ((std::distance(first: p.begin(), last: p.end()) < 3) || (*p.begin() != "tools" ) || (*++p.begin() != "build" ))) |
108 | { |
109 | // |
110 | // We're doing a rename of namespaces and library names |
111 | // so scan for names of libraries: |
112 | // |
113 | static const boost::regex e( |
114 | "\\<lib\\s+(boost\\w+)\\s+[:;]" |
115 | ); |
116 | |
117 | fileview view(m_boost_path / p); |
118 | boost::regex_token_iterator<const char*> i(view.begin(), view.end(), e, 1); |
119 | boost::regex_token_iterator<const char*> j; |
120 | while(i != j) |
121 | { |
122 | m_lib_names.insert(x: *i); |
123 | ++i; |
124 | } |
125 | static const std::pair<fs::path, std::string> specials_library_names[] = { |
126 | std::pair<fs::path, std::string>("libs/python/build/Jamfile.v2" , "boost_python" ), |
127 | std::pair<fs::path, std::string>("libs/python/build/Jamfile.v2" , "boost_python3" ), |
128 | }; |
129 | |
130 | for(unsigned int n = 0; n < (sizeof(specials_library_names)/sizeof(specials_library_names[0])); ++n) |
131 | { |
132 | if(0 == compare_paths(a: specials_library_names[n].first, b: p)) |
133 | { |
134 | m_lib_names.insert(x: specials_library_names[n].second); |
135 | } |
136 | } |
137 | } |
138 | // |
139 | // if this is a html file, scan for dependencies: |
140 | // |
141 | if(is_html_file(p)) |
142 | { |
143 | static const boost::regex e( |
144 | "<(?:img[^>]*src=|link[^>]*href=)(\"[^\"]+\"|\\w+)[^>]*>" |
145 | ); |
146 | |
147 | fileview view(m_boost_path / p); |
148 | boost::regex_token_iterator<const char*> i(view.begin(), view.end(), e, 1); |
149 | boost::regex_token_iterator<const char*> j; |
150 | while(i != j) |
151 | { |
152 | // |
153 | // extract the dependent name: |
154 | // |
155 | std::string s(*i); |
156 | if(s[0] == '\"') |
157 | { |
158 | // remove quotes: |
159 | assert(s.size() > 2); |
160 | s.erase(pos: 0, n: 1); |
161 | s.erase(pos: s.size() - 1); |
162 | } |
163 | // |
164 | // Remove any target suffix: |
165 | // |
166 | std::string::size_type n = s.find(c: '#'); |
167 | if(n != std::string::npos) |
168 | { |
169 | s.erase(pos: n); |
170 | } |
171 | // |
172 | // if the name starts with ./ remove it |
173 | // or we'll get an error: |
174 | if(s.compare(pos: 0, n1: 2, s: "./" ) == 0) |
175 | s.erase(pos: 0, n: 2); |
176 | if(s.find(c: ':') == std::string::npos) |
177 | { |
178 | // only concatonate if it's a relative path |
179 | // rather than a URL: |
180 | fs::path dep(p.branch_path() / s); |
181 | if(!m_dependencies.count(x: dep)) |
182 | { |
183 | m_dependencies[dep] = p; // set up dependency tree |
184 | add_path(p: dep); |
185 | } |
186 | } |
187 | ++i; |
188 | } |
189 | } |
190 | // |
191 | // now scan for "special" dependencies: |
192 | // anything that we can't automatically detect... |
193 | // |
194 | static const std::pair<fs::path, fs::path> |
195 | specials[] = { |
196 | std::pair<fs::path, fs::path>("boost/atomic/capabilities.hpp" , "boost/atomic/detail" ), |
197 | std::pair<fs::path, fs::path>("boost/chrono/chrono.hpp" , "libs/chrono/src" ), |
198 | std::pair<fs::path, fs::path>("boost/chrono/chrono.hpp" , "libs/chrono/build" ), |
199 | std::pair<fs::path, fs::path>("boost/cerrno.hpp" , "libs/system/build" ), |
200 | std::pair<fs::path, fs::path>("boost/cerrno.hpp" , "libs/system/src" ), |
201 | std::pair<fs::path, fs::path>("libs/thread/build" , "boost/system" ), |
202 | std::pair<fs::path, fs::path>("libs/thread/build" , "boost/cerrno.hpp" ), |
203 | std::pair<fs::path, fs::path>("libs/thread/build" , "boost/chrono" ), |
204 | std::pair<fs::path, fs::path>("boost/filesystem/convenience.hpp" , "boost/filesystem.hpp" ), |
205 | std::pair<fs::path, fs::path>("boost/filesystem/exception.hpp" , "boost/filesystem.hpp" ), |
206 | std::pair<fs::path, fs::path>("boost/filesystem/fstream.hpp" , "boost/filesystem.hpp" ), |
207 | std::pair<fs::path, fs::path>("boost/filesystem/operations.hpp" , "boost/filesystem.hpp" ), |
208 | std::pair<fs::path, fs::path>("boost/filesystem/path.hpp" , "boost/filesystem.hpp" ), |
209 | std::pair<fs::path, fs::path>("boost/filesystem.hpp" , "libs/filesystem/build" ), |
210 | std::pair<fs::path, fs::path>("boost/filesystem.hpp" , "libs/filesystem/v2" ), |
211 | std::pair<fs::path, fs::path>("boost/filesystem.hpp" , "libs/filesystem/v3" ), |
212 | std::pair<fs::path, fs::path>("boost/config.hpp" , "boost/config" ), |
213 | std::pair<fs::path, fs::path>("tools/build/boost-build.jam" , "Jamrules" ), |
214 | std::pair<fs::path, fs::path>("tools/build/boost-build.jam" , "project-root.jam" ), |
215 | std::pair<fs::path, fs::path>("tools/build/boost-build.jam" , "boost-build.jam" ), |
216 | std::pair<fs::path, fs::path>("tools/build/boost-build.jam" , "Jamfile.v2" ), |
217 | std::pair<fs::path, fs::path>("tools/build/boost-build.jam" , "boostcpp.jam" ), |
218 | std::pair<fs::path, fs::path>("tools/build/boost-build.jam" , "bootstrap.bat" ), |
219 | std::pair<fs::path, fs::path>("tools/build/boost-build.jam" , "bootstrap.sh" ), |
220 | std::pair<fs::path, fs::path>("tools/build/boost-build.jam" , "Jamroot" ), |
221 | std::pair<fs::path, fs::path>("tools/build/boost-build.jam" , "INSTALL" ), |
222 | std::pair<fs::path, fs::path>("tools/build/boost-build.jam" , "LICENSE_1_0.txt" ), |
223 | std::pair<fs::path, fs::path>("boost/preprocessor/iterate.hpp" , "boost/preprocessor/iteration" ), |
224 | std::pair<fs::path, fs::path>("boost/preprocessor/slot/slot.hpp" , "boost/preprocessor/slot/detail" ), |
225 | std::pair<fs::path, fs::path>("boost/function.hpp" , "boost/function/detail" ), |
226 | std::pair<fs::path, fs::path>("boost/regex/config.hpp" , "boost/regex/user.hpp" ), |
227 | std::pair<fs::path, fs::path>("boost/signals/signal_template.hpp" , "boost/function" ), |
228 | std::pair<fs::path, fs::path>("boost/mpl/list.hpp" , "boost/mpl/list" ), |
229 | std::pair<fs::path, fs::path>("boost/mpl/list_c.hpp" , "boost/mpl/list" ), |
230 | std::pair<fs::path, fs::path>("boost/mpl/vector.hpp" , "boost/mpl/vector" ), |
231 | std::pair<fs::path, fs::path>("boost/mpl/deque.hpp" , "boost/mpl/vector" ), |
232 | std::pair<fs::path, fs::path>("boost/mpl/vector_c.hpp" , "boost/mpl/vector" ), |
233 | std::pair<fs::path, fs::path>("boost/mpl/map.hpp" , "boost/mpl/map" ), |
234 | std::pair<fs::path, fs::path>("boost/mpl/set.hpp" , "boost/mpl/set" ), |
235 | std::pair<fs::path, fs::path>("boost/mpl/set_c.hpp" , "boost/mpl/set" ), |
236 | std::pair<fs::path, fs::path>("boost/mpl/aux_/include_preprocessed.hpp" , "boost/mpl/aux_/preprocessed" ), |
237 | std::pair<fs::path, fs::path>("boost/mpl/vector/aux_/include_preprocessed.hpp" , "boost/mpl/vector/aux_/preprocessed" ), |
238 | std::pair<fs::path, fs::path>("boost/mpl/set/aux_/include_preprocessed.hpp" , "boost/mpl/set/aux_/preprocessed" ), |
239 | std::pair<fs::path, fs::path>("boost/mpl/map/aux_/include_preprocessed.hpp" , "boost/mpl/map/aux_/preprocessed" ), |
240 | std::pair<fs::path, fs::path>("boost/mpl/list/aux_/include_preprocessed.hpp" , "boost/mpl/list/aux_/preprocessed" ), |
241 | std::pair<fs::path, fs::path>("libs/graph/src/python/visitor.hpp" , "libs/graph/src/python" ), |
242 | std::pair<fs::path, fs::path>("boost/test/detail/config.hpp" , "libs/test/src" ), |
243 | std::pair<fs::path, fs::path>("boost/test/detail/config.hpp" , "libs/test/build" ), |
244 | std::pair<fs::path, fs::path>("boost/typeof.hpp" , "boost/typeof/incr_registration_group.hpp" ), |
245 | std::pair<fs::path, fs::path>("boost/function_types/detail/pp_loop.hpp" , "boost/function_types/detail/pp_cc_loop" ), |
246 | std::pair<fs::path, fs::path>("boost/function_types/components.hpp" , "boost/function_types/detail/components_impl" ), |
247 | std::pair<fs::path, fs::path>("boost/function_types/detail/pp_loop.hpp" , "boost/function_types/detail" ), |
248 | std::pair<fs::path, fs::path>("boost/math/tools/rational.hpp" , "boost/math/tools/detail" ), |
249 | std::pair<fs::path, fs::path>("boost/proto/repeat.hpp" , "boost/proto/detail/local.hpp" ), |
250 | std::pair<fs::path, fs::path>("boost/signals/signal_template.hpp" , "boost/function" ), |
251 | std::pair<fs::path, fs::path>("boost/preprocessor/slot/counter.hpp" , "boost/preprocessor/slot/detail/counter.hpp" ), |
252 | std::pair<fs::path, fs::path>("boost/graph/distributed/detail/tag_allocator.hpp" , "libs/graph_parallel" ), |
253 | std::pair<fs::path, fs::path>("boost/graph/distributed/mpi_process_group.hpp" , "libs/graph_parallel" ), |
254 | }; |
255 | |
256 | for(unsigned int n = 0; n < (sizeof(specials)/sizeof(specials[0])); ++n) |
257 | { |
258 | if(0 == compare_paths(a: specials[n].first, b: p)) |
259 | { |
260 | if(!m_dependencies.count(x: specials[n].second)) |
261 | { |
262 | m_dependencies[specials[n].second] = p; // set up dependency tree |
263 | add_path(p: specials[n].second); |
264 | } |
265 | } |
266 | } |
267 | |
268 | } |
269 | |
270 | void bcp_implementation::add_file_dependencies(const fs::path& p, bool scanfile) |
271 | { |
272 | static const boost::regex e( |
273 | "^[[:blank:]]*(?://@bcp[[:blank:]]+([^\\n]*)\n)?#[[:blank:]]*include[[:blank:]]*[\"<]([^\">]+)[\">]" |
274 | ); |
275 | |
276 | if(!m_dependencies.count(x: p)) |
277 | m_dependencies[p] = p; // set terminal dependency |
278 | |
279 | fileview view; |
280 | if(scanfile) |
281 | view.open(p); |
282 | else |
283 | view.open(p: m_boost_path / p); |
284 | if(m_license_mode && !scanfile) |
285 | scan_license(p, v: view); |
286 | const int subs[] = { 1, 2 }; |
287 | boost::regex_token_iterator<const char*> i(view.begin(), view.end(), e, subs); |
288 | boost::regex_token_iterator<const char*> j; |
289 | while(i != j) |
290 | { |
291 | // |
292 | // *i contains the name of the include file, |
293 | // check first for a file of that name in the |
294 | // same directory as the file we are scanning, |
295 | // and if that fails, then check the boost-root: |
296 | // |
297 | fs::path include_file; |
298 | try{ |
299 | std::string discart_message = *i; |
300 | ++i; |
301 | if(discart_message.size()) |
302 | { |
303 | // The include is optional and should be discarded: |
304 | std::cout << "Optional functionality won't be copied: " << discart_message << std::endl; |
305 | std::cout << "Add the file " << *i << " to the list of dependencies to extract to copy this functionality." << std::endl; |
306 | ++i; |
307 | continue; |
308 | } |
309 | include_file = i->str(); |
310 | fs::path test_file(m_boost_path / p.branch_path() / include_file); |
311 | if(fs::exists(p: test_file) && !fs::is_directory(p: test_file) && (p.branch_path().string() != "boost" )) |
312 | { |
313 | if(!m_dependencies.count(x: p.branch_path() / include_file)) |
314 | { |
315 | m_dependencies[p.branch_path() / include_file] = p; |
316 | add_path(p: p.branch_path() / include_file); |
317 | } |
318 | } |
319 | else if(fs::exists(p: m_boost_path / include_file)) |
320 | { |
321 | if(!m_dependencies.count(x: include_file)) |
322 | { |
323 | m_dependencies[include_file] = p; |
324 | add_path(p: include_file); |
325 | } |
326 | } |
327 | ++i; |
328 | } |
329 | catch(const fs::filesystem_error&) |
330 | { |
331 | std::cerr << "Can't parse filename " << *i << " included by file " << p.string() << std::endl; |
332 | ++i; |
333 | continue; |
334 | } |
335 | } |
336 | // |
337 | // Now we need to scan for Boost.Preprocessor includes that |
338 | // are included via preprocessor iteration: |
339 | // |
340 | static const boost::regex ppfiles("^[[:blank:]]*#[[:blank:]]*define[[:blank:]]+(?:BOOST_PP_FILENAME|BOOST_PP_ITERATION_PARAMS|BOOST_PP_INDIRECT_SELF)(?:[^\\n]|\\\\\\n)+?[\"<]([^\">]+)[\">]" ); |
341 | i = boost::regex_token_iterator<const char*>(view.begin(), view.end(), ppfiles, 1); |
342 | while(i != j) |
343 | { |
344 | // |
345 | // *i contains the name of the include file, |
346 | // check first for a file of that name in the |
347 | // same directory as the file we are scanning, |
348 | // and if that fails, then check the boost-root: |
349 | // |
350 | fs::path include_file; |
351 | try{ |
352 | include_file = i->str(); |
353 | } |
354 | catch(const fs::filesystem_error&) |
355 | { |
356 | std::cerr << "Can't parse filename " << *i << " included by file " << p.string() << std::endl; |
357 | ++i; |
358 | continue; |
359 | } |
360 | fs::path test_file(m_boost_path / p.branch_path() / include_file); |
361 | if(fs::exists(p: test_file) && !fs::is_directory(p: test_file) && (p.branch_path().string() != "boost" )) |
362 | { |
363 | if(!m_dependencies.count(x: p.branch_path() / include_file)) |
364 | { |
365 | m_dependencies[p.branch_path() / include_file] = p; |
366 | add_path(p: p.branch_path() / include_file); |
367 | } |
368 | } |
369 | else if(fs::exists(p: m_boost_path / include_file)) |
370 | { |
371 | if(!m_dependencies.count(x: include_file)) |
372 | { |
373 | m_dependencies[include_file] = p; |
374 | add_path(p: include_file); |
375 | } |
376 | } |
377 | else |
378 | { |
379 | std::cerr << "CAUTION: Boost.Preprocessor iterated file " << include_file.string() << " does not exist." << std::endl; |
380 | } |
381 | ++i; |
382 | } |
383 | |
384 | // |
385 | // Scan for any #include MACRO includes that we don't recognise. |
386 | // |
387 | // Begin by declaring all of the macros that get #included that |
388 | // we know about and are correctly handled as special cases: |
389 | // |
390 | static const std::string known_macros[] = { |
391 | "AUX778076_INCLUDE_STRING" , |
392 | "BOOST_PP_STRINGIZE(boost/mpl/aux_/preprocessed/AUX778076_PREPROCESSED_HEADER)" , |
393 | "BOOST_USER_CONFIG" , |
394 | "BOOST_COMPILER_CONFIG" , |
395 | "BOOST_STDLIB_CONFIG" , |
396 | "BOOST_PLATFORM_CONFIG" , |
397 | "BOOST_PP_FILENAME_1" , |
398 | "BOOST_PP_ITERATION_PARAMS_1" , |
399 | "BOOST_PP_FILENAME_2" , |
400 | "BOOST_PP_ITERATION_PARAMS_2" , |
401 | "BOOST_PP_FILENAME_3" , |
402 | "BOOST_PP_ITERATION_PARAMS_3" , |
403 | "BOOST_PP_FILENAME_4" , |
404 | "BOOST_PP_ITERATION_PARAMS_4" , |
405 | "BOOST_PP_FILENAME_5" , |
406 | "BOOST_PP_ITERATION_PARAMS_5" , |
407 | "BOOST_PP_INDIRECT_SELF" , |
408 | "BOOST_PP_INCLUDE_SELF()" , |
409 | "BOOST_PP_ITERATE" , |
410 | "BOOST_PP_LOCAL_ITERATE" , |
411 | "BOOST_PP_ITERATE()" , |
412 | "BOOST_PP_LOCAL_ITERATE()" , |
413 | "BOOST_PP_ASSIGN_SLOT(1)" , |
414 | "BOOST_PP_ASSIGN_SLOT(2)" , |
415 | "BOOST_PP_ASSIGN_SLOT(3)" , |
416 | "BOOST_PP_ASSIGN_SLOT(4)" , |
417 | "BOOST_PP_ASSIGN_SLOT(5)" , |
418 | "BOOST_ABI_PREFIX" , |
419 | "BOOST_ABI_SUFFIX" , |
420 | "BOOST_PP_STRINGIZE(boost/mpl/aux_/preprocessed/AUX_PREPROCESSED_HEADER)" , |
421 | "BOOST_PP_STRINGIZE(boost/mpl/list/AUX778076_HEADER)" , |
422 | "BOOST_PP_STRINGIZE(boost/mpl/list/AUX778076_LIST_C_HEADER)" , |
423 | "BOOST_PP_STRINGIZE(boost/mpl/list/AUX778076_LIST_HEADER)" , |
424 | "BOOST_PP_STRINGIZE(boost/mpl/map/aux_/preprocessed/AUX778076_HEADER)" , |
425 | "BOOST_PP_STRINGIZE(boost/mpl/map/AUX778076_MAP_HEADER)" , |
426 | "BOOST_PP_STRINGIZE(boost/mpl/set/aux_/preprocessed/AUX778076_HEADER)" , |
427 | "BOOST_PP_STRINGIZE(boost/mpl/set/AUX778076_SET_HEADER)" , |
428 | "BOOST_PP_STRINGIZE(boost/mpl/set/AUX778076_SET_C_HEADER)" , |
429 | "BOOST_PP_STRINGIZE(boost/mpl/vector/AUX778076_VECTOR_HEADER)" , |
430 | "BOOST_PP_STRINGIZE(boost/mpl/vector/aux_/preprocessed/AUX778076_HEADER)" , |
431 | "BOOST_PP_STRINGIZE(boost/mpl/vector/AUX778076_DEQUE_HEADER)" , |
432 | "BOOST_PP_STRINGIZE(boost/mpl/vector/AUX778076_VECTOR_C_HEADER)" , |
433 | "BOOST_REGEX_USER_CONFIG" , |
434 | "BGL_PYTHON_EVENTS_HEADER" , |
435 | "B1" , |
436 | "B2" , |
437 | "BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()" , |
438 | "BOOST_SLIST_HEADER" , |
439 | "BOOST_HASH_SET_HEADER" , |
440 | "BOOST_HASH_MAP_HEADER" , |
441 | "BOOST_INTRUSIVE_INVARIANT_ASSERT_INCLUDE" , |
442 | "BOOST_INTRUSIVE_SAFE_HOOK_DEFAULT_ASSERT_INCLUDE" , |
443 | "BOOST_INTRUSIVE_SAFE_HOOK_DESTRUCTOR_ASSERT_INCLUDE" , |
444 | "BOOST_FT_loop" , |
445 | "BOOST_FT_AL_PREPROCESSED" , |
446 | "BOOST_FT_AL_INCLUDE_FILE" , |
447 | "__FILE__" , |
448 | "BOOST_FT_cc_file" , |
449 | "BOOST_FT_variate_file" , |
450 | "BOOST_USER_CONFIG" , |
451 | "BOOST_HEADER()" , |
452 | "BOOST_TR1_STD_HEADER(utility)" , |
453 | "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(tuple))" , |
454 | "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(random))" , |
455 | "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(array))" , |
456 | "BOOST_TR1_HEADER(cmath)" , |
457 | "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(complex))" , |
458 | "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(functional))" , |
459 | "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(memory))" , |
460 | "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(regex))" , |
461 | "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(type_traits))" , |
462 | "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(unordered_map))" , |
463 | "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(unordered_set))" , |
464 | "BOOST_TR1_STD_HEADER(BOOST_TR1_PATH(utility))" , |
465 | "BOOST_PROTO_LOCAL_ITERATE()" , |
466 | "BOOST_SIGNAL_FUNCTION_N_HEADER" , |
467 | "BOOST_PP_UPDATE_COUNTER()" , |
468 | }; |
469 | |
470 | static const boost::regex indirect_includes("^[[:blank:]]*#[[:blank:]]*include[[:blank:]]+([^\"<][^\n]*?)[[:blank:]]*$" ); |
471 | i = boost::regex_token_iterator<const char*>(view.begin(), view.end(), indirect_includes, 1); |
472 | while(i != j) |
473 | { |
474 | const std::string* known_macros_end = known_macros + sizeof(known_macros)/sizeof(known_macros[0]); |
475 | if(known_macros_end == std::find(first: known_macros, last: known_macros_end, val: i->str())) |
476 | { |
477 | std::cerr << "CAUTION: don't know how to trace depenencies through macro: \"" << *i << "\" in file: " << p.string() << std::endl; |
478 | } |
479 | ++i; |
480 | } |
481 | // |
482 | // if the file contains a cpp_main / unit_test_main / test_main |
483 | // it is dependent upon Boost.test even if it doesn't |
484 | // include any of the Boost.test headers directly. |
485 | // |
486 | static const boost::regex m("^\\s*int\\s+(?:cpp_main|test_main|unit_test_main)" ); |
487 | boost::cmatch what; |
488 | if(boost::regex_search(first: view.begin(), last: view.end(), m&: what, e: m)) |
489 | { |
490 | add_dependent_lib(libname: "test" , p, view); |
491 | } |
492 | if(!scanfile) |
493 | { |
494 | // |
495 | // grab the name of the library to which the header belongs, |
496 | // and if that library has source then add the source to our |
497 | // list: |
498 | // |
499 | // this regex catches boost/libname.hpp or boost/libname/whatever: |
500 | // |
501 | static const boost::regex lib1("boost/([^\\./]+)(?!detail).*" ); |
502 | boost::smatch swhat; |
503 | std::string gs(p.generic_string()); |
504 | if(boost::regex_match(s: gs, m&: swhat, e: lib1)) |
505 | { |
506 | add_dependent_lib(libname: swhat.str(sub: 1), p, view); |
507 | } |
508 | // |
509 | // and this one catches boost/x/y/whatever (for example numeric/ublas): |
510 | // |
511 | static const boost::regex lib2("boost/([^/]+/[^/]+)/(?!detail).*" ); |
512 | gs = p.generic_string(); |
513 | if(boost::regex_match(s: gs, m&: swhat, e: lib2)) |
514 | { |
515 | add_dependent_lib(libname: swhat.str(sub: 1), p, view); |
516 | } |
517 | } |
518 | if(m_list_namespaces) |
519 | { |
520 | // |
521 | // scan for top level namespaces and add to our list: |
522 | // |
523 | static const boost::regex namespace_scanner( |
524 | "^(?<!\\\\\\n)[[:blank:]]*+namespace\\s++(\\w++)\\s++(\\{[^{}]*(?:(?2)[^{}]*)*\\})" |
525 | ); |
526 | i = boost::regex_token_iterator<const char*>(view.begin(), view.end(), namespace_scanner, 1); |
527 | while(i != j) |
528 | { |
529 | if(m_top_namespaces.count(x: *i) == 0) |
530 | { |
531 | //std::cout << *i << " (Found in " << p << ")" << std::endl; |
532 | m_top_namespaces[*i] = p; |
533 | } |
534 | ++i; |
535 | } |
536 | } |
537 | } |
538 | |