123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548 |
- /*=============================================================================
- Boost.Wave: A Standard compliant C++ preprocessor library
- http://www.boost.org/
- Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
- Software License, Version 1.0. (See accompanying file
- LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- =============================================================================*/
- #if !defined(BOOST_CPP_INCLUDE_PATHS_HPP_AF620DA4_B3D2_4221_AD91_8A1ABFFB6944_INCLUDED)
- #define BOOST_CPP_INCLUDE_PATHS_HPP_AF620DA4_B3D2_4221_AD91_8A1ABFFB6944_INCLUDED
- #include <string>
- #include <list>
- #include <utility>
- #include <boost/assert.hpp>
- #include <boost/wave/wave_config.hpp>
- #include <boost/wave/util/filesystem_compatibility.hpp>
- #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
- #include <boost/multi_index_container.hpp>
- #include <boost/multi_index/member.hpp>
- #include <boost/multi_index/ordered_index.hpp>
- #endif
- #if BOOST_WAVE_SERIALIZATION != 0
- #include <boost/serialization/serialization.hpp>
- #include <boost/serialization/utility.hpp>
- #include <boost/serialization/collections_save_imp.hpp>
- #include <boost/serialization/collections_load_imp.hpp>
- #include <boost/serialization/split_free.hpp>
- #endif
- #include <boost/filesystem/path.hpp>
- #include <boost/filesystem/operations.hpp>
- // this must occur after all of the includes and before any code appears
- #ifdef BOOST_HAS_ABI_HEADERS
- #include BOOST_ABI_PREFIX
- #endif
- ///////////////////////////////////////////////////////////////////////////////
- namespace boost { namespace wave { namespace util {
- #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
- ///////////////////////////////////////////////////////////////////////////////
- // Tags for accessing both sides of a bidirectional map
- struct from {};
- struct to {};
- ///////////////////////////////////////////////////////////////////////////////
- // The class template bidirectional_map wraps the specification
- // of a bidirectional map based on multi_index_container.
- template<typename FromType, typename ToType>
- struct bidirectional_map
- {
- typedef std::pair<FromType, ToType> value_type;
- #if defined(BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS) || \
- (defined(BOOST_MSVC) && (BOOST_MSVC == 1600) ) || \
- (defined(BOOST_INTEL_CXX_VERSION) && \
- (defined(_MSC_VER) && (BOOST_INTEL_CXX_VERSION <= 700)))
- BOOST_STATIC_CONSTANT(unsigned, from_offset = offsetof(value_type, first));
- BOOST_STATIC_CONSTANT(unsigned, to_offset = offsetof(value_type, second));
- typedef boost::multi_index::multi_index_container<
- value_type,
- boost::multi_index::indexed_by<
- boost::multi_index::ordered_unique<
- boost::multi_index::tag<from>,
- boost::multi_index::member_offset<value_type, FromType, from_offset>
- >,
- boost::multi_index::ordered_non_unique<
- boost::multi_index::tag<to>,
- boost::multi_index::member_offset<value_type, ToType, to_offset>
- >
- >
- > type;
- #else
- typedef boost::multi_index::multi_index_container<
- value_type,
- boost::multi_index::indexed_by<
- boost::multi_index::ordered_unique<
- boost::multi_index::tag<from>,
- boost::multi_index::member<value_type, FromType, &value_type::first>
- >,
- boost::multi_index::ordered_non_unique<
- boost::multi_index::tag<to>,
- boost::multi_index::member<value_type, ToType, &value_type::second>
- >
- >
- > type;
- #endif
- };
- #endif // BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
- #if BOOST_WAVE_SERIALIZATION != 0
- struct load_filepos
- {
- static unsigned int get_line() { return 0; }
- static unsigned int get_column() { return 0; }
- static std::string get_file() { return "<loading-state>"; }
- };
- #endif
- ///////////////////////////////////////////////////////////////////////////////
- //
- // include_paths - controlling the include path search order
- //
- // General notes:
- //
- // Any directories specified with the 'add_include_path()' function before
- // the function 'set_sys_include_delimiter()' is called are searched only
- // for the case of '#include "file"' directives, they are not searched for
- // '#include <file>' directives. If additional directories are specified
- // with the 'add_include_path()' function after a call to the function
- // 'set_sys_include_delimiter()', these directories are searched for all
- // '#include' directives.
- //
- // In addition, a call to the function 'set_sys_include_delimiter()'
- // inhibits the use of the current directory as the first search directory
- // for '#include "file"' directives. Therefore, the current directory is
- // searched only if it is requested explicitly with a call to the function
- // 'add_include_path(".")'.
- //
- // Calling both functions, the 'set_sys_include_delimiter()' and
- // 'add_include_path(".")' allows you to control precisely which
- // directories are searched before the current one and which are searched
- // after.
- //
- ///////////////////////////////////////////////////////////////////////////////
- class include_paths
- {
- private:
- typedef std::list<std::pair<boost::filesystem::path, std::string> >
- include_list_type;
- typedef include_list_type::value_type include_value_type;
- #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
- typedef bidirectional_map<std::string, std::string>::type
- pragma_once_set_type;
- #endif
- public:
- include_paths()
- : was_sys_include_path(false),
- current_dir(initial_path()),
- current_rel_dir(initial_path())
- {}
- bool add_include_path(char const *path_, bool is_system = false)
- {
- return add_include_path(path_, (is_system || was_sys_include_path) ?
- system_include_paths : user_include_paths);
- }
- void set_sys_include_delimiter() { was_sys_include_path = true; }
- bool find_include_file (std::string &s, std::string &dir, bool is_system,
- char const *current_file) const;
- void set_current_directory(char const *path_);
- boost::filesystem::path get_current_directory() const
- { return current_dir; }
- protected:
- bool find_include_file (std::string &s, std::string &dir,
- include_list_type const &pathes, char const *) const;
- bool add_include_path(char const *path_, include_list_type &pathes_);
- private:
- include_list_type user_include_paths;
- include_list_type system_include_paths;
- bool was_sys_include_path; // saw a set_sys_include_delimiter()
- boost::filesystem::path current_dir;
- boost::filesystem::path current_rel_dir;
- #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
- public:
- bool has_pragma_once(std::string const &filename)
- {
- using boost::multi_index::get;
- return get<from>(pragma_once_files).find(filename) != pragma_once_files.end();
- }
- bool add_pragma_once_header(std::string const &filename,
- std::string const& guard_name)
- {
- typedef pragma_once_set_type::value_type value_type;
- return pragma_once_files.insert(value_type(filename, guard_name)).second;
- }
- bool remove_pragma_once_header(std::string const& guard_name)
- {
- typedef pragma_once_set_type::index_iterator<to>::type to_iterator;
- typedef std::pair<to_iterator, to_iterator> range_type;
- range_type r = pragma_once_files.get<to>().equal_range(guard_name);
- if (r.first != r.second) {
- using boost::multi_index::get;
- get<to>(pragma_once_files).erase(r.first, r.second);
- return true;
- }
- return false;
- }
- private:
- pragma_once_set_type pragma_once_files;
- #endif
- #if BOOST_WAVE_SERIALIZATION != 0
- public:
- BOOST_STATIC_CONSTANT(unsigned int, version = 0x10);
- BOOST_STATIC_CONSTANT(unsigned int, version_mask = 0x0f);
- private:
- friend class boost::serialization::access;
- template<typename Archive>
- void save(Archive & ar, const unsigned int version) const
- {
- using namespace boost::serialization;
- #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
- ar & make_nvp("pragma_once_files", pragma_once_files);
- #endif
- ar & make_nvp("user_include_paths", user_include_paths);
- ar & make_nvp("system_include_paths", system_include_paths);
- ar & make_nvp("was_sys_include_path", was_sys_include_path);
- }
- template<typename Archive>
- void load(Archive & ar, const unsigned int loaded_version)
- {
- using namespace boost::serialization;
- if (version != (loaded_version & ~version_mask)) {
- BOOST_WAVE_THROW(preprocess_exception, incompatible_config,
- "cpp_include_path state version", load_filepos());
- return;
- }
- #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
- ar & make_nvp("pragma_once_files", pragma_once_files);
- #endif
- // verify that the old include paths match the current ones
- include_list_type user_paths, system_paths;
- ar & make_nvp("user_include_paths", user_paths);
- ar & make_nvp("system_include_paths", system_paths);
- if (user_paths != user_include_paths)
- {
- BOOST_WAVE_THROW(preprocess_exception, incompatible_config,
- "user include paths", load_filepos());
- return;
- }
- if (system_paths != system_include_paths)
- {
- BOOST_WAVE_THROW(preprocess_exception, incompatible_config,
- "system include paths", load_filepos());
- return;
- }
- ar & make_nvp("was_sys_include_path", was_sys_include_path);
- }
- BOOST_SERIALIZATION_SPLIT_MEMBER()
- #endif
- };
- ///////////////////////////////////////////////////////////////////////////////
- // Add an include path to one of the search lists (user include path or system
- // include path).
- inline
- bool include_paths::add_include_path (
- char const *path_, include_list_type &pathes_)
- {
- namespace fs = boost::filesystem;
- if (path_) {
- fs::path newpath = util::complete_path(create_path(path_), current_dir);
- if (!fs::exists(newpath) || !fs::is_directory(newpath)) {
- // the given path does not form a name of a valid file system directory
- // item
- return false;
- }
- pathes_.push_back (include_value_type(newpath, path_));
- return true;
- }
- return false;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // Find an include file by traversing the list of include directories
- inline
- bool include_paths::find_include_file (std::string &s, std::string &dir,
- include_list_type const &pathes, char const *current_file) const
- {
- namespace fs = boost::filesystem;
- typedef include_list_type::const_iterator const_include_list_iter_t;
- const_include_list_iter_t it = pathes.begin();
- const_include_list_iter_t include_paths_end = pathes.end();
- #if BOOST_WAVE_SUPPORT_INCLUDE_NEXT != 0
- if (0 != current_file) {
- // re-locate the directory of the current file (#include_next handling)
- // #include_next does not distinguish between <file> and "file"
- // inclusion, nor does it check that the file you specify has the same
- // name as the current file. It simply looks for the file named, starting
- // with the directory in the search path after the one where the current
- // file was found.
- fs::path file_path (create_path(current_file));
- for (/**/; it != include_paths_end; ++it) {
- fs::path currpath (create_path((*it).first.string()));
- if (std::equal(currpath.begin(), currpath.end(), file_path.begin()))
- {
- ++it; // start searching with the next directory
- break;
- }
- }
- }
- #endif
- for (/**/; it != include_paths_end; ++it) {
- fs::path currpath (create_path(s));
- if (!currpath.has_root_directory()) {
- currpath = create_path((*it).first.string());
- currpath /= create_path(s); // append filename
- }
- if (fs::exists(currpath)) {
- fs::path dirpath (create_path(s));
- if (!dirpath.has_root_directory()) {
- dirpath = create_path((*it).second);
- dirpath /= create_path(s);
- }
- dir = dirpath.string();
- s = normalize(currpath).string(); // found the required file
- return true;
- }
- }
- return false;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // Find an include file by searching the user and system includes in the
- // correct sequence (as it was configured by the user of the driver program)
- inline bool
- include_paths::find_include_file (std::string &s, std::string &dir,
- bool is_system, char const *current_file) const
- {
- namespace fs = boost::filesystem;
- // if not system include (<...>), then search current directory first
- if (!is_system) {
- if (!was_sys_include_path) { // set_sys_include_delimiter() not called
- // first have a look at the current directory
- fs::path currpath(create_path(s));
- if (!currpath.has_root_directory()) {
- currpath = create_path(current_dir.string());
- currpath /= create_path(s);
- }
- if (fs::exists(currpath) && 0 == current_file) {
- // if 0 != current_path (#include_next handling) it can't be
- // the file in the current directory
- fs::path dirpath(create_path(s));
- if (!dirpath.has_root_directory()) {
- dirpath = create_path(current_rel_dir.string());
- dirpath /= create_path(s);
- }
- dir = dirpath.string();
- s = normalize(currpath).string(); // found in local directory
- return true;
- }
- // iterate all user include file directories to find the file
- if (find_include_file(s, dir, user_include_paths, current_file))
- return true;
- // ... fall through
- }
- else {
- // if set_sys_include_delimiter() was called, then user include files
- // are searched in the user search path only
- return find_include_file(s, dir, user_include_paths, current_file);
- }
- // if nothing found, fall through
- // ...
- }
- // iterate all system include file directories to find the file
- return find_include_file (s, dir, system_include_paths, current_file);
- }
- ///////////////////////////////////////////////////////////////////////////////
- // Set current directory from a given file name
- inline bool
- as_relative_to(boost::filesystem::path const& path,
- boost::filesystem::path const& base, boost::filesystem::path& result)
- {
- if (path.has_root_path()) {
- if (path.root_path() == base.root_path())
- return as_relative_to(path.relative_path(), base.relative_path(), result);
- result = path; // that's our result
- }
- else {
- if (base.has_root_path()) {
- // cannot find relative path from a relative path and a rooted base
- return false;
- }
- else {
- typedef boost::filesystem::path::const_iterator path_iterator;
- path_iterator path_it = path.begin();
- path_iterator base_it = base.begin();
- while (path_it != path.end() && base_it != base.end() ) {
- if (*path_it != *base_it)
- break;
- ++path_it; ++base_it;
- }
- for (/**/; base_it != base.end(); ++base_it)
- result /= "..";
- for (/**/; path_it != path.end(); ++path_it)
- result /= *path_it;
- }
- }
- return true;
- }
- ///////////////////////////////////////////////////////////////////////////////
- inline
- void include_paths::set_current_directory(char const *path_)
- {
- namespace fs = boost::filesystem;
- fs::path filepath (create_path(path_));
- fs::path filename = util::complete_path(filepath, current_dir);
- BOOST_ASSERT(!(fs::exists(filename) && fs::is_directory(filename)));
- current_rel_dir.clear();
- if (!as_relative_to(branch_path(filepath), current_dir, current_rel_dir))
- current_rel_dir = branch_path(filepath);
- current_dir = branch_path(filename);
- }
- ///////////////////////////////////////////////////////////////////////////////
- }}} // namespace boost::wave::util
- #if BOOST_WAVE_SERIALIZATION != 0
- ///////////////////////////////////////////////////////////////////////////////
- namespace boost { namespace serialization {
- ///////////////////////////////////////////////////////////////////////////////
- // Serialization support for boost::filesystem::path
- template<class Archive>
- inline void save (Archive & ar, boost::filesystem::path const& p,
- const unsigned int /* file_version */)
- {
- using namespace boost::serialization;
- std::string path_str(p.native_file_string());
- ar & make_nvp("filepath", path_str);
- }
- template<class Archive>
- inline void load (Archive & ar, boost::filesystem::path &p,
- const unsigned int /* file_version */)
- {
- using namespace boost::serialization;
- std::string path_str;
- ar & make_nvp("filepath", path_str);
- p = wave::util::create_path(path_str);
- }
- // split non-intrusive serialization function member into separate
- // non intrusive save/load member functions
- template<class Archive>
- inline void serialize (Archive & ar, boost::filesystem::path &p,
- const unsigned int file_version)
- {
- boost::serialization::split_free(ar, p, file_version);
- }
- ///////////////////////////////////////////////////////////////////////////////
- // Serialization support for the used multi_index
- template<class Archive>
- inline void save (Archive & ar,
- const typename boost::wave::util::bidirectional_map<
- std::string, std::string
- >::type &t,
- const unsigned int /* file_version */)
- {
- boost::serialization::stl::save_collection<
- Archive,
- typename boost::wave::util::bidirectional_map<
- std::string, std::string
- >::type
- >(ar, t);
- }
- template<class Archive>
- inline void load (Archive & ar,
- typename boost::wave::util::bidirectional_map<std::string, std::string>::type &t,
- const unsigned int /* file_version */)
- {
- typedef typename boost::wave::util::bidirectional_map<
- std::string, std::string
- >::type map_type;
- boost::serialization::stl::load_collection<
- Archive, map_type,
- boost::serialization::stl::archive_input_unique<Archive, map_type>,
- boost::serialization::stl::no_reserve_imp<map_type>
- >(ar, t);
- }
- // split non-intrusive serialization function member into separate
- // non intrusive save/load member functions
- template<class Archive>
- inline void serialize (Archive & ar,
- typename boost::wave::util::bidirectional_map<
- std::string, std::string
- >::type &t,
- const unsigned int file_version)
- {
- boost::serialization::split_free(ar, t, file_version);
- }
- ///////////////////////////////////////////////////////////////////////////////
- }} // namespace boost::serialization
- BOOST_CLASS_VERSION(boost::wave::util::include_paths,
- boost::wave::util::include_paths::version);
- #endif // BOOST_WAVE_SERIALIZATION != 0
- // the suffix header occurs after all of the code
- #ifdef BOOST_HAS_ABI_HEADERS
- #include BOOST_ABI_SUFFIX
- #endif
- #endif // !defined(BOOST_CPP_INCLUDE_PATHS_HPP_AF620DA4_B3D2_4221_AD91_8A1ABFFB6944_INCLUDED)
|