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
23void 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
41void 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
84void 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 //
194static 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
270void 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

source code of boost/tools/bcp/add_path.cpp