]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/wave/util/cpp_include_paths.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / wave / util / cpp_include_paths.hpp
CommitLineData
7c673cae
FG
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
20effc67
TL
11#if !defined(BOOST_CPP_INCLUDE_PATHS_HPP_AF620DA4_B3D2_4221_AD91_8A1ABFFB6944_INCLUDED)
12#define BOOST_CPP_INCLUDE_PATHS_HPP_AF620DA4_B3D2_4221_AD91_8A1ABFFB6944_INCLUDED
7c673cae
FG
13
14#include <string>
15#include <list>
16#include <utility>
17
b32b8144 18#include <boost/assert.hpp>
7c673cae
FG
19#include <boost/wave/wave_config.hpp>
20#include <boost/wave/util/filesystem_compatibility.hpp>
21
22#if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
23#include <boost/multi_index_container.hpp>
24#include <boost/multi_index/member.hpp>
25#include <boost/multi_index/ordered_index.hpp>
26#endif
27
28#if BOOST_WAVE_SERIALIZATION != 0
29#include <boost/serialization/serialization.hpp>
30#include <boost/serialization/utility.hpp>
31#include <boost/serialization/collections_save_imp.hpp>
32#include <boost/serialization/collections_load_imp.hpp>
33#include <boost/serialization/split_free.hpp>
34#endif
35
36#include <boost/filesystem/path.hpp>
37#include <boost/filesystem/operations.hpp>
38
39// this must occur after all of the includes and before any code appears
40#ifdef BOOST_HAS_ABI_HEADERS
41#include BOOST_ABI_PREFIX
42#endif
43
44///////////////////////////////////////////////////////////////////////////////
45namespace boost { namespace wave { namespace util {
46
47#if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
48///////////////////////////////////////////////////////////////////////////////
49// Tags for accessing both sides of a bidirectional map
50struct from {};
51struct to {};
52
53///////////////////////////////////////////////////////////////////////////////
54// The class template bidirectional_map wraps the specification
55// of a bidirectional map based on multi_index_container.
56template<typename FromType, typename ToType>
57struct bidirectional_map
58{
59 typedef std::pair<FromType, ToType> value_type;
60
61#if defined(BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS) || \
b32b8144 62 (defined(BOOST_MSVC) && (BOOST_MSVC == 1600) ) || \
7c673cae 63 (defined(BOOST_INTEL_CXX_VERSION) && \
b32b8144 64 (defined(_MSC_VER) && (BOOST_INTEL_CXX_VERSION <= 700)))
7c673cae
FG
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<
b32b8144
FG
73 boost::multi_index::tag<from>,
74 boost::multi_index::member_offset<value_type, FromType, from_offset>
7c673cae
FG
75 >,
76 boost::multi_index::ordered_non_unique<
b32b8144
FG
77 boost::multi_index::tag<to>,
78 boost::multi_index::member_offset<value_type, ToType, to_offset>
7c673cae
FG
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>,
b32b8144 90 boost::multi_index::member<value_type, FromType, &value_type::first>
7c673cae
FG
91 >,
92 boost::multi_index::ordered_non_unique<
b32b8144
FG
93 boost::multi_index::tag<to>,
94 boost::multi_index::member<value_type, ToType, &value_type::second>
7c673cae
FG
95 >
96 >
97 > type;
98
99#endif
100};
101#endif // BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
102
103#if BOOST_WAVE_SERIALIZATION != 0
104struct 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//
b32b8144
FG
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.
7c673cae 125//
b32b8144
FG
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
7c673cae 129// searched only if it is requested explicitly with a call to the function
b32b8144 130// 'add_include_path(".")'.
7c673cae 131//
b32b8144
FG
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
7c673cae
FG
135// after.
136//
137///////////////////////////////////////////////////////////////////////////////
138class include_paths
139{
140private:
b32b8144 141 typedef std::list<std::pair<boost::filesystem::path, std::string> >
7c673cae
FG
142 include_list_type;
143 typedef include_list_type::value_type include_value_type;
144
145#if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
b32b8144 146 typedef bidirectional_map<std::string, std::string>::type
7c673cae
FG
147 pragma_once_set_type;
148#endif
149
150public:
151 include_paths()
152 : was_sys_include_path(false),
153 current_dir(initial_path()),
154 current_rel_dir(initial_path())
155 {}
b32b8144 156
7c673cae
FG
157 bool add_include_path(char const *path_, bool is_system = false)
158 {
b32b8144 159 return add_include_path(path_, (is_system || was_sys_include_path) ?
7c673cae
FG
160 system_include_paths : user_include_paths);
161 }
162 void set_sys_include_delimiter() { was_sys_include_path = true; }
b32b8144 163 bool find_include_file (std::string &s, std::string &dir, bool is_system,
7c673cae
FG
164 char const *current_file) const;
165 void set_current_directory(char const *path_);
b32b8144 166 boost::filesystem::path get_current_directory() const
7c673cae
FG
167 { return current_dir; }
168
169protected:
b32b8144 170 bool find_include_file (std::string &s, std::string &dir,
7c673cae
FG
171 include_list_type const &pathes, char const *) const;
172 bool add_include_path(char const *path_, include_list_type &pathes_);
173
174private:
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
182public:
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 }
b32b8144 188 bool add_pragma_once_header(std::string const &filename,
7c673cae
FG
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;
b32b8144 198
7c673cae
FG
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
208private:
209 pragma_once_set_type pragma_once_files;
210#endif
211
212#if BOOST_WAVE_SERIALIZATION != 0
213public:
214 BOOST_STATIC_CONSTANT(unsigned int, version = 0x10);
215 BOOST_STATIC_CONSTANT(unsigned int, version_mask = 0x0f);
216
217private:
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)) {
b32b8144 235 BOOST_WAVE_THROW(preprocess_exception, incompatible_config,
7c673cae
FG
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 {
b32b8144 250 BOOST_WAVE_THROW(preprocess_exception, incompatible_config,
7c673cae
FG
251 "user include paths", load_filepos());
252 return;
253 }
254 if (system_paths != system_include_paths)
255 {
b32b8144 256 BOOST_WAVE_THROW(preprocess_exception, incompatible_config,
7c673cae
FG
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///////////////////////////////////////////////////////////////////////////////
b32b8144 268// Add an include path to one of the search lists (user include path or system
7c673cae
FG
269// include path).
270inline
271bool include_paths::add_include_path (
272 char const *path_, include_list_type &pathes_)
273{
274 namespace fs = boost::filesystem;
275 if (path_) {
20effc67 276 fs::path newpath = util::complete_path(create_path(path_), current_dir);
7c673cae
FG
277
278 if (!fs::exists(newpath) || !fs::is_directory(newpath)) {
20effc67
TL
279 // the given path does not form a name of a valid file system directory
280 // item
7c673cae
FG
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
292inline
b32b8144 293bool include_paths::find_include_file (std::string &s, std::string &dir,
7c673cae
FG
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
b32b8144 302#if BOOST_WAVE_SUPPORT_INCLUDE_NEXT != 0
7c673cae 303 if (0 != current_file) {
20effc67 304 // re-locate the directory of the current file (#include_next handling)
7c673cae 305
20effc67
TL
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.
7c673cae
FG
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()));
b32b8144 315 if (std::equal(currpath.begin(), currpath.end(), file_path.begin()))
7c673cae
FG
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 }
b32b8144 330
7c673cae
FG
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///////////////////////////////////////////////////////////////////////////////
b32b8144 347// Find an include file by searching the user and system includes in the
7c673cae 348// correct sequence (as it was configured by the user of the driver program)
b32b8144
FG
349inline bool
350include_paths::find_include_file (std::string &s, std::string &dir,
7c673cae
FG
351 bool is_system, char const *current_file) const
352{
353 namespace fs = boost::filesystem;
354
20effc67 355 // if not system include (<...>), then search current directory first
7c673cae 356 if (!is_system) {
20effc67
TL
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));
7c673cae
FG
360 if (!currpath.has_root_directory()) {
361 currpath = create_path(current_dir.string());
362 currpath /= create_path(s);
363 }
b32b8144 364
7c673cae 365 if (fs::exists(currpath) && 0 == current_file) {
20effc67
TL
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));
7c673cae
FG
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;
b32b8144 377 }
7c673cae 378
20effc67 379 // iterate all user include file directories to find the file
7c673cae
FG
380 if (find_include_file(s, dir, user_include_paths, current_file))
381 return true;
382
20effc67 383 // ... fall through
7c673cae
FG
384 }
385 else {
20effc67
TL
386 // if set_sys_include_delimiter() was called, then user include files
387 // are searched in the user search path only
7c673cae
FG
388 return find_include_file(s, dir, user_include_paths, current_file);
389 }
b32b8144 390
20effc67
TL
391 // if nothing found, fall through
392 // ...
7c673cae
FG
393 }
394
20effc67 395 // iterate all system include file directories to find the file
7c673cae
FG
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
402inline bool
b32b8144
FG
403as_relative_to(boost::filesystem::path const& path,
404 boost::filesystem::path const& base, boost::filesystem::path& result)
7c673cae
FG
405{
406 if (path.has_root_path()) {
b32b8144 407 if (path.root_path() == base.root_path())
7c673cae
FG
408 return as_relative_to(path.relative_path(), base.relative_path(), result);
409
410 result = path; // that's our result
b32b8144 411 }
7c673cae
FG
412 else {
413 if (base.has_root_path()) {
414 // cannot find relative path from a relative path and a rooted base
415 return false;
b32b8144 416 }
7c673cae
FG
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() ) {
b32b8144 422 if (*path_it != *base_it)
7c673cae
FG
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///////////////////////////////////////////////////////////////////////////////
438inline
439void include_paths::set_current_directory(char const *path_)
440{
441 namespace fs = boost::filesystem;
b32b8144 442
7c673cae
FG
443 fs::path filepath (create_path(path_));
444 fs::path filename = util::complete_path(filepath, current_dir);
b32b8144
FG
445
446 BOOST_ASSERT(!(fs::exists(filename) && fs::is_directory(filename)));
447
448 current_rel_dir.clear();
449 if (!as_relative_to(branch_path(filepath), current_dir, current_rel_dir))
450 current_rel_dir = branch_path(filepath);
451 current_dir = branch_path(filename);
7c673cae
FG
452}
453
454///////////////////////////////////////////////////////////////////////////////
455}}} // namespace boost::wave::util
456
457#if BOOST_WAVE_SERIALIZATION != 0
458///////////////////////////////////////////////////////////////////////////////
459namespace boost { namespace serialization {
460
461///////////////////////////////////////////////////////////////////////////////
462// Serialization support for boost::filesystem::path
463template<class Archive>
b32b8144 464inline void save (Archive & ar, boost::filesystem::path const& p,
7c673cae
FG
465 const unsigned int /* file_version */)
466{
467 using namespace boost::serialization;
468 std::string path_str(p.native_file_string());
469 ar & make_nvp("filepath", path_str);
470}
471
472template<class Archive>
473inline void load (Archive & ar, boost::filesystem::path &p,
474 const unsigned int /* file_version */)
475{
476 using namespace boost::serialization;
477 std::string path_str;
478 ar & make_nvp("filepath", path_str);
479 p = wave::util::create_path(path_str);
480}
481
482// split non-intrusive serialization function member into separate
483// non intrusive save/load member functions
484template<class Archive>
485inline void serialize (Archive & ar, boost::filesystem::path &p,
486 const unsigned int file_version)
487{
488 boost::serialization::split_free(ar, p, file_version);
489}
490
491///////////////////////////////////////////////////////////////////////////////
492// Serialization support for the used multi_index
493template<class Archive>
494inline void save (Archive & ar,
495 const typename boost::wave::util::bidirectional_map<
496 std::string, std::string
497 >::type &t,
498 const unsigned int /* file_version */)
499{
500 boost::serialization::stl::save_collection<
b32b8144 501 Archive,
7c673cae
FG
502 typename boost::wave::util::bidirectional_map<
503 std::string, std::string
504 >::type
505 >(ar, t);
506}
507
508template<class Archive>
509inline void load (Archive & ar,
510 typename boost::wave::util::bidirectional_map<std::string, std::string>::type &t,
511 const unsigned int /* file_version */)
512{
513 typedef typename boost::wave::util::bidirectional_map<
514 std::string, std::string
515 >::type map_type;
516 boost::serialization::stl::load_collection<
517 Archive, map_type,
518 boost::serialization::stl::archive_input_unique<Archive, map_type>,
519 boost::serialization::stl::no_reserve_imp<map_type>
520 >(ar, t);
521}
522
523// split non-intrusive serialization function member into separate
524// non intrusive save/load member functions
525template<class Archive>
b32b8144 526inline void serialize (Archive & ar,
7c673cae
FG
527 typename boost::wave::util::bidirectional_map<
528 std::string, std::string
529 >::type &t,
530 const unsigned int file_version)
531{
532 boost::serialization::split_free(ar, t, file_version);
533}
534
535///////////////////////////////////////////////////////////////////////////////
536}} // namespace boost::serialization
537
b32b8144 538BOOST_CLASS_VERSION(boost::wave::util::include_paths,
7c673cae
FG
539 boost::wave::util::include_paths::version);
540
541#endif // BOOST_WAVE_SERIALIZATION != 0
542
543// the suffix header occurs after all of the code
544#ifdef BOOST_HAS_ABI_HEADERS
545#include BOOST_ABI_SUFFIX
546#endif
547
20effc67 548#endif // !defined(BOOST_CPP_INCLUDE_PATHS_HPP_AF620DA4_B3D2_4221_AD91_8A1ABFFB6944_INCLUDED)