Mercurial > hg > vamp-build-and-test
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DEPENDENCIES/generic/include/boost/wave/util/cpp_include_paths.hpp Tue Aug 05 11:11:38 2014 +0100 @@ -0,0 +1,553 @@ +/*============================================================================= + 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(CPP_INCLUDE_PATHS_HPP_AF620DA4_B3D2_4221_AD91_8A1ABFFB6944_INCLUDED) +#define CPP_INCLUDE_PATHS_HPP_AF620DA4_B3D2_4221_AD91_8A1ABFFB6944_INCLUDED + +#include <string> +#include <list> +#include <utility> + +#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 < 1300) || (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); + if (fs::exists(filename) && fs::is_directory(filename)) { + current_rel_dir.clear(); + if (!as_relative_to(filepath, current_dir, current_rel_dir)) + current_rel_dir = filepath; + current_dir = filename; + } + else { + 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(CPP_INCLUDE_PATHS_HPP_AF620DA4_B3D2_4221_AD91_8A1ABFFB6944_INCLUDED)