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