Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/wave/util/cpp_include_paths.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
1 /*============================================================================= | |
2 Boost.Wave: A Standard compliant C++ preprocessor library | |
3 | |
4 http://www.boost.org/ | |
5 | |
6 Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost | |
7 Software License, Version 1.0. (See accompanying file | |
8 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
9 =============================================================================*/ | |
10 | |
11 #if !defined(CPP_INCLUDE_PATHS_HPP_AF620DA4_B3D2_4221_AD91_8A1ABFFB6944_INCLUDED) | |
12 #define CPP_INCLUDE_PATHS_HPP_AF620DA4_B3D2_4221_AD91_8A1ABFFB6944_INCLUDED | |
13 | |
14 #include <string> | |
15 #include <list> | |
16 #include <utility> | |
17 | |
18 #include <boost/wave/wave_config.hpp> | |
19 #include <boost/wave/util/filesystem_compatibility.hpp> | |
20 | |
21 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0 | |
22 #include <boost/multi_index_container.hpp> | |
23 #include <boost/multi_index/member.hpp> | |
24 #include <boost/multi_index/ordered_index.hpp> | |
25 #endif | |
26 | |
27 #if BOOST_WAVE_SERIALIZATION != 0 | |
28 #include <boost/serialization/serialization.hpp> | |
29 #include <boost/serialization/utility.hpp> | |
30 #include <boost/serialization/collections_save_imp.hpp> | |
31 #include <boost/serialization/collections_load_imp.hpp> | |
32 #include <boost/serialization/split_free.hpp> | |
33 #endif | |
34 | |
35 #include <boost/filesystem/path.hpp> | |
36 #include <boost/filesystem/operations.hpp> | |
37 | |
38 // this must occur after all of the includes and before any code appears | |
39 #ifdef BOOST_HAS_ABI_HEADERS | |
40 #include BOOST_ABI_PREFIX | |
41 #endif | |
42 | |
43 /////////////////////////////////////////////////////////////////////////////// | |
44 namespace boost { namespace wave { namespace util { | |
45 | |
46 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0 | |
47 /////////////////////////////////////////////////////////////////////////////// | |
48 // Tags for accessing both sides of a bidirectional map | |
49 struct from {}; | |
50 struct to {}; | |
51 | |
52 /////////////////////////////////////////////////////////////////////////////// | |
53 // The class template bidirectional_map wraps the specification | |
54 // of a bidirectional map based on multi_index_container. | |
55 template<typename FromType, typename ToType> | |
56 struct bidirectional_map | |
57 { | |
58 typedef std::pair<FromType, ToType> value_type; | |
59 | |
60 #if defined(BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS) || \ | |
61 (defined(BOOST_MSVC) && \ | |
62 ( (BOOST_MSVC < 1300) || (BOOST_MSVC == 1600) )) || \ | |
63 (defined(BOOST_INTEL_CXX_VERSION) && \ | |
64 (defined(_MSC_VER) && (BOOST_INTEL_CXX_VERSION <= 700))) | |
65 | |
66 BOOST_STATIC_CONSTANT(unsigned, from_offset = offsetof(value_type, first)); | |
67 BOOST_STATIC_CONSTANT(unsigned, to_offset = offsetof(value_type, second)); | |
68 | |
69 typedef boost::multi_index::multi_index_container< | |
70 value_type, | |
71 boost::multi_index::indexed_by< | |
72 boost::multi_index::ordered_unique< | |
73 boost::multi_index::tag<from>, | |
74 boost::multi_index::member_offset<value_type, FromType, from_offset> | |
75 >, | |
76 boost::multi_index::ordered_non_unique< | |
77 boost::multi_index::tag<to>, | |
78 boost::multi_index::member_offset<value_type, ToType, to_offset> | |
79 > | |
80 > | |
81 > type; | |
82 | |
83 #else | |
84 | |
85 typedef boost::multi_index::multi_index_container< | |
86 value_type, | |
87 boost::multi_index::indexed_by< | |
88 boost::multi_index::ordered_unique< | |
89 boost::multi_index::tag<from>, | |
90 boost::multi_index::member<value_type, FromType, &value_type::first> | |
91 >, | |
92 boost::multi_index::ordered_non_unique< | |
93 boost::multi_index::tag<to>, | |
94 boost::multi_index::member<value_type, ToType, &value_type::second> | |
95 > | |
96 > | |
97 > type; | |
98 | |
99 #endif | |
100 }; | |
101 #endif // BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0 | |
102 | |
103 #if BOOST_WAVE_SERIALIZATION != 0 | |
104 struct load_filepos | |
105 { | |
106 static unsigned int get_line() { return 0; } | |
107 static unsigned int get_column() { return 0; } | |
108 static std::string get_file() { return "<loading-state>"; } | |
109 }; | |
110 #endif | |
111 | |
112 /////////////////////////////////////////////////////////////////////////////// | |
113 // | |
114 // include_paths - controlling the include path search order | |
115 // | |
116 // General notes: | |
117 // | |
118 // Any directories specified with the 'add_include_path()' function before | |
119 // the function 'set_sys_include_delimiter()' is called are searched only | |
120 // for the case of '#include "file"' directives, they are not searched for | |
121 // '#include <file>' directives. If additional directories are specified | |
122 // with the 'add_include_path()' function after a call to the function | |
123 // 'set_sys_include_delimiter()', these directories are searched for all | |
124 // '#include' directives. | |
125 // | |
126 // In addition, a call to the function 'set_sys_include_delimiter()' | |
127 // inhibits the use of the current directory as the first search directory | |
128 // for '#include "file"' directives. Therefore, the current directory is | |
129 // searched only if it is requested explicitly with a call to the function | |
130 // 'add_include_path(".")'. | |
131 // | |
132 // Calling both functions, the 'set_sys_include_delimiter()' and | |
133 // 'add_include_path(".")' allows you to control precisely which | |
134 // directories are searched before the current one and which are searched | |
135 // after. | |
136 // | |
137 /////////////////////////////////////////////////////////////////////////////// | |
138 class include_paths | |
139 { | |
140 private: | |
141 typedef std::list<std::pair<boost::filesystem::path, std::string> > | |
142 include_list_type; | |
143 typedef include_list_type::value_type include_value_type; | |
144 | |
145 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0 | |
146 typedef bidirectional_map<std::string, std::string>::type | |
147 pragma_once_set_type; | |
148 #endif | |
149 | |
150 public: | |
151 include_paths() | |
152 : was_sys_include_path(false), | |
153 current_dir(initial_path()), | |
154 current_rel_dir(initial_path()) | |
155 {} | |
156 | |
157 bool add_include_path(char const *path_, bool is_system = false) | |
158 { | |
159 return add_include_path(path_, (is_system || was_sys_include_path) ? | |
160 system_include_paths : user_include_paths); | |
161 } | |
162 void set_sys_include_delimiter() { was_sys_include_path = true; } | |
163 bool find_include_file (std::string &s, std::string &dir, bool is_system, | |
164 char const *current_file) const; | |
165 void set_current_directory(char const *path_); | |
166 boost::filesystem::path get_current_directory() const | |
167 { return current_dir; } | |
168 | |
169 protected: | |
170 bool find_include_file (std::string &s, std::string &dir, | |
171 include_list_type const &pathes, char const *) const; | |
172 bool add_include_path(char const *path_, include_list_type &pathes_); | |
173 | |
174 private: | |
175 include_list_type user_include_paths; | |
176 include_list_type system_include_paths; | |
177 bool was_sys_include_path; // saw a set_sys_include_delimiter() | |
178 boost::filesystem::path current_dir; | |
179 boost::filesystem::path current_rel_dir; | |
180 | |
181 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0 | |
182 public: | |
183 bool has_pragma_once(std::string const &filename) | |
184 { | |
185 using boost::multi_index::get; | |
186 return get<from>(pragma_once_files).find(filename) != pragma_once_files.end(); | |
187 } | |
188 bool add_pragma_once_header(std::string const &filename, | |
189 std::string const& guard_name) | |
190 { | |
191 typedef pragma_once_set_type::value_type value_type; | |
192 return pragma_once_files.insert(value_type(filename, guard_name)).second; | |
193 } | |
194 bool remove_pragma_once_header(std::string const& guard_name) | |
195 { | |
196 typedef pragma_once_set_type::index_iterator<to>::type to_iterator; | |
197 typedef std::pair<to_iterator, to_iterator> range_type; | |
198 | |
199 range_type r = pragma_once_files.get<to>().equal_range(guard_name); | |
200 if (r.first != r.second) { | |
201 using boost::multi_index::get; | |
202 get<to>(pragma_once_files).erase(r.first, r.second); | |
203 return true; | |
204 } | |
205 return false; | |
206 } | |
207 | |
208 private: | |
209 pragma_once_set_type pragma_once_files; | |
210 #endif | |
211 | |
212 #if BOOST_WAVE_SERIALIZATION != 0 | |
213 public: | |
214 BOOST_STATIC_CONSTANT(unsigned int, version = 0x10); | |
215 BOOST_STATIC_CONSTANT(unsigned int, version_mask = 0x0f); | |
216 | |
217 private: | |
218 friend class boost::serialization::access; | |
219 template<typename Archive> | |
220 void save(Archive & ar, const unsigned int version) const | |
221 { | |
222 using namespace boost::serialization; | |
223 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0 | |
224 ar & make_nvp("pragma_once_files", pragma_once_files); | |
225 #endif | |
226 ar & make_nvp("user_include_paths", user_include_paths); | |
227 ar & make_nvp("system_include_paths", system_include_paths); | |
228 ar & make_nvp("was_sys_include_path", was_sys_include_path); | |
229 } | |
230 template<typename Archive> | |
231 void load(Archive & ar, const unsigned int loaded_version) | |
232 { | |
233 using namespace boost::serialization; | |
234 if (version != (loaded_version & ~version_mask)) { | |
235 BOOST_WAVE_THROW(preprocess_exception, incompatible_config, | |
236 "cpp_include_path state version", load_filepos()); | |
237 return; | |
238 } | |
239 | |
240 #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0 | |
241 ar & make_nvp("pragma_once_files", pragma_once_files); | |
242 #endif | |
243 // verify that the old include paths match the current ones | |
244 include_list_type user_paths, system_paths; | |
245 ar & make_nvp("user_include_paths", user_paths); | |
246 ar & make_nvp("system_include_paths", system_paths); | |
247 | |
248 if (user_paths != user_include_paths) | |
249 { | |
250 BOOST_WAVE_THROW(preprocess_exception, incompatible_config, | |
251 "user include paths", load_filepos()); | |
252 return; | |
253 } | |
254 if (system_paths != system_include_paths) | |
255 { | |
256 BOOST_WAVE_THROW(preprocess_exception, incompatible_config, | |
257 "system include paths", load_filepos()); | |
258 return; | |
259 } | |
260 | |
261 ar & make_nvp("was_sys_include_path", was_sys_include_path); | |
262 } | |
263 BOOST_SERIALIZATION_SPLIT_MEMBER() | |
264 #endif | |
265 }; | |
266 | |
267 /////////////////////////////////////////////////////////////////////////////// | |
268 // Add an include path to one of the search lists (user include path or system | |
269 // include path). | |
270 inline | |
271 bool include_paths::add_include_path ( | |
272 char const *path_, include_list_type &pathes_) | |
273 { | |
274 namespace fs = boost::filesystem; | |
275 if (path_) { | |
276 fs::path newpath = util::complete_path(create_path(path_), current_dir); | |
277 | |
278 if (!fs::exists(newpath) || !fs::is_directory(newpath)) { | |
279 // the given path does not form a name of a valid file system directory | |
280 // item | |
281 return false; | |
282 } | |
283 | |
284 pathes_.push_back (include_value_type(newpath, path_)); | |
285 return true; | |
286 } | |
287 return false; | |
288 } | |
289 | |
290 /////////////////////////////////////////////////////////////////////////////// | |
291 // Find an include file by traversing the list of include directories | |
292 inline | |
293 bool include_paths::find_include_file (std::string &s, std::string &dir, | |
294 include_list_type const &pathes, char const *current_file) const | |
295 { | |
296 namespace fs = boost::filesystem; | |
297 typedef include_list_type::const_iterator const_include_list_iter_t; | |
298 | |
299 const_include_list_iter_t it = pathes.begin(); | |
300 const_include_list_iter_t include_paths_end = pathes.end(); | |
301 | |
302 #if BOOST_WAVE_SUPPORT_INCLUDE_NEXT != 0 | |
303 if (0 != current_file) { | |
304 // re-locate the directory of the current file (#include_next handling) | |
305 | |
306 // #include_next does not distinguish between <file> and "file" | |
307 // inclusion, nor does it check that the file you specify has the same | |
308 // name as the current file. It simply looks for the file named, starting | |
309 // with the directory in the search path after the one where the current | |
310 // file was found. | |
311 | |
312 fs::path file_path (create_path(current_file)); | |
313 for (/**/; it != include_paths_end; ++it) { | |
314 fs::path currpath (create_path((*it).first.string())); | |
315 if (std::equal(currpath.begin(), currpath.end(), file_path.begin())) | |
316 { | |
317 ++it; // start searching with the next directory | |
318 break; | |
319 } | |
320 } | |
321 } | |
322 #endif | |
323 | |
324 for (/**/; it != include_paths_end; ++it) { | |
325 fs::path currpath (create_path(s)); | |
326 if (!currpath.has_root_directory()) { | |
327 currpath = create_path((*it).first.string()); | |
328 currpath /= create_path(s); // append filename | |
329 } | |
330 | |
331 if (fs::exists(currpath)) { | |
332 fs::path dirpath (create_path(s)); | |
333 if (!dirpath.has_root_directory()) { | |
334 dirpath = create_path((*it).second); | |
335 dirpath /= create_path(s); | |
336 } | |
337 | |
338 dir = dirpath.string(); | |
339 s = normalize(currpath).string(); // found the required file | |
340 return true; | |
341 } | |
342 } | |
343 return false; | |
344 } | |
345 | |
346 /////////////////////////////////////////////////////////////////////////////// | |
347 // Find an include file by searching the user and system includes in the | |
348 // correct sequence (as it was configured by the user of the driver program) | |
349 inline bool | |
350 include_paths::find_include_file (std::string &s, std::string &dir, | |
351 bool is_system, char const *current_file) const | |
352 { | |
353 namespace fs = boost::filesystem; | |
354 | |
355 // if not system include (<...>), then search current directory first | |
356 if (!is_system) { | |
357 if (!was_sys_include_path) { // set_sys_include_delimiter() not called | |
358 // first have a look at the current directory | |
359 fs::path currpath (create_path(s)); | |
360 if (!currpath.has_root_directory()) { | |
361 currpath = create_path(current_dir.string()); | |
362 currpath /= create_path(s); | |
363 } | |
364 | |
365 if (fs::exists(currpath) && 0 == current_file) { | |
366 // if 0 != current_path (#include_next handling) it can't be | |
367 // the file in the current directory | |
368 fs::path dirpath (create_path(s)); | |
369 if (!dirpath.has_root_directory()) { | |
370 dirpath = create_path(current_rel_dir.string()); | |
371 dirpath /= create_path(s); | |
372 } | |
373 | |
374 dir = dirpath.string(); | |
375 s = normalize(currpath).string(); // found in local directory | |
376 return true; | |
377 } | |
378 | |
379 // iterate all user include file directories to find the file | |
380 if (find_include_file(s, dir, user_include_paths, current_file)) | |
381 return true; | |
382 | |
383 // ... fall through | |
384 } | |
385 else { | |
386 // if set_sys_include_delimiter() was called, then user include files | |
387 // are searched in the user search path only | |
388 return find_include_file(s, dir, user_include_paths, current_file); | |
389 } | |
390 | |
391 // if nothing found, fall through | |
392 // ... | |
393 } | |
394 | |
395 // iterate all system include file directories to find the file | |
396 return find_include_file (s, dir, system_include_paths, current_file); | |
397 } | |
398 | |
399 /////////////////////////////////////////////////////////////////////////////// | |
400 // Set current directory from a given file name | |
401 | |
402 inline bool | |
403 as_relative_to(boost::filesystem::path const& path, | |
404 boost::filesystem::path const& base, boost::filesystem::path& result) | |
405 { | |
406 if (path.has_root_path()) { | |
407 if (path.root_path() == base.root_path()) | |
408 return as_relative_to(path.relative_path(), base.relative_path(), result); | |
409 | |
410 result = path; // that's our result | |
411 } | |
412 else { | |
413 if (base.has_root_path()) { | |
414 // cannot find relative path from a relative path and a rooted base | |
415 return false; | |
416 } | |
417 else { | |
418 typedef boost::filesystem::path::const_iterator path_iterator; | |
419 path_iterator path_it = path.begin(); | |
420 path_iterator base_it = base.begin(); | |
421 while (path_it != path.end() && base_it != base.end() ) { | |
422 if (*path_it != *base_it) | |
423 break; | |
424 ++path_it; ++base_it; | |
425 } | |
426 | |
427 for (/**/; base_it != base.end(); ++base_it) | |
428 result /= ".."; | |
429 | |
430 for (/**/; path_it != path.end(); ++path_it) | |
431 result /= *path_it; | |
432 } | |
433 } | |
434 return true; | |
435 } | |
436 | |
437 /////////////////////////////////////////////////////////////////////////////// | |
438 inline | |
439 void include_paths::set_current_directory(char const *path_) | |
440 { | |
441 namespace fs = boost::filesystem; | |
442 | |
443 fs::path filepath (create_path(path_)); | |
444 fs::path filename = util::complete_path(filepath, current_dir); | |
445 if (fs::exists(filename) && fs::is_directory(filename)) { | |
446 current_rel_dir.clear(); | |
447 if (!as_relative_to(filepath, current_dir, current_rel_dir)) | |
448 current_rel_dir = filepath; | |
449 current_dir = filename; | |
450 } | |
451 else { | |
452 current_rel_dir.clear(); | |
453 if (!as_relative_to(branch_path(filepath), current_dir, current_rel_dir)) | |
454 current_rel_dir = branch_path(filepath); | |
455 current_dir = branch_path(filename); | |
456 } | |
457 } | |
458 | |
459 /////////////////////////////////////////////////////////////////////////////// | |
460 }}} // namespace boost::wave::util | |
461 | |
462 #if BOOST_WAVE_SERIALIZATION != 0 | |
463 /////////////////////////////////////////////////////////////////////////////// | |
464 namespace boost { namespace serialization { | |
465 | |
466 /////////////////////////////////////////////////////////////////////////////// | |
467 // Serialization support for boost::filesystem::path | |
468 template<class Archive> | |
469 inline void save (Archive & ar, boost::filesystem::path const& p, | |
470 const unsigned int /* file_version */) | |
471 { | |
472 using namespace boost::serialization; | |
473 std::string path_str(p.native_file_string()); | |
474 ar & make_nvp("filepath", path_str); | |
475 } | |
476 | |
477 template<class Archive> | |
478 inline void load (Archive & ar, boost::filesystem::path &p, | |
479 const unsigned int /* file_version */) | |
480 { | |
481 using namespace boost::serialization; | |
482 std::string path_str; | |
483 ar & make_nvp("filepath", path_str); | |
484 p = wave::util::create_path(path_str); | |
485 } | |
486 | |
487 // split non-intrusive serialization function member into separate | |
488 // non intrusive save/load member functions | |
489 template<class Archive> | |
490 inline void serialize (Archive & ar, boost::filesystem::path &p, | |
491 const unsigned int file_version) | |
492 { | |
493 boost::serialization::split_free(ar, p, file_version); | |
494 } | |
495 | |
496 /////////////////////////////////////////////////////////////////////////////// | |
497 // Serialization support for the used multi_index | |
498 template<class Archive> | |
499 inline void save (Archive & ar, | |
500 const typename boost::wave::util::bidirectional_map< | |
501 std::string, std::string | |
502 >::type &t, | |
503 const unsigned int /* file_version */) | |
504 { | |
505 boost::serialization::stl::save_collection< | |
506 Archive, | |
507 typename boost::wave::util::bidirectional_map< | |
508 std::string, std::string | |
509 >::type | |
510 >(ar, t); | |
511 } | |
512 | |
513 template<class Archive> | |
514 inline void load (Archive & ar, | |
515 typename boost::wave::util::bidirectional_map<std::string, std::string>::type &t, | |
516 const unsigned int /* file_version */) | |
517 { | |
518 typedef typename boost::wave::util::bidirectional_map< | |
519 std::string, std::string | |
520 >::type map_type; | |
521 boost::serialization::stl::load_collection< | |
522 Archive, map_type, | |
523 boost::serialization::stl::archive_input_unique<Archive, map_type>, | |
524 boost::serialization::stl::no_reserve_imp<map_type> | |
525 >(ar, t); | |
526 } | |
527 | |
528 // split non-intrusive serialization function member into separate | |
529 // non intrusive save/load member functions | |
530 template<class Archive> | |
531 inline void serialize (Archive & ar, | |
532 typename boost::wave::util::bidirectional_map< | |
533 std::string, std::string | |
534 >::type &t, | |
535 const unsigned int file_version) | |
536 { | |
537 boost::serialization::split_free(ar, t, file_version); | |
538 } | |
539 | |
540 /////////////////////////////////////////////////////////////////////////////// | |
541 }} // namespace boost::serialization | |
542 | |
543 BOOST_CLASS_VERSION(boost::wave::util::include_paths, | |
544 boost::wave::util::include_paths::version); | |
545 | |
546 #endif // BOOST_WAVE_SERIALIZATION != 0 | |
547 | |
548 // the suffix header occurs after all of the code | |
549 #ifdef BOOST_HAS_ABI_HEADERS | |
550 #include BOOST_ABI_SUFFIX | |
551 #endif | |
552 | |
553 #endif // !defined(CPP_INCLUDE_PATHS_HPP_AF620DA4_B3D2_4221_AD91_8A1ABFFB6944_INCLUDED) |