LCOV - code coverage report
Current view: top level - usr/include/boost/wave/util - cpp_include_paths.hpp (source / functions) Hit Total Coverage
Test: ROSE Lines: 0 96 0.0 %
Date: 2022-12-08 13:48:47 Functions: 0 8 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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/assert.hpp>
      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             : ///////////////////////////////////////////////////////////////////////////////
      45             : namespace 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
      50             : struct from {};
      51             : struct to {};
      52             : 
      53             : ///////////////////////////////////////////////////////////////////////////////
      54             : //  The class template bidirectional_map wraps the specification
      55             : //  of a bidirectional map based on multi_index_container.
      56             : template<typename FromType, typename ToType>
      57             : struct bidirectional_map
      58             : {
      59             :     typedef std::pair<FromType, ToType> value_type;
      60             : 
      61             : #if defined(BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS) || \
      62             :     (defined(BOOST_MSVC) && (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           0 :     include_paths()
     152           0 :     :   was_sys_include_path(false),
     153             :         current_dir(initial_path()),
     154           0 :         current_rel_dir(initial_path())
     155           0 :     {}
     156             : 
     157           0 :     bool add_include_path(char const *path_, bool is_system = false)
     158             :     {
     159           0 :         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           0 :     bool has_pragma_once(std::string const &filename)
     184             :     {
     185           0 :         using boost::multi_index::get;
     186           0 :         return get<from>(pragma_once_files).find(filename) != pragma_once_files.end();
     187             :     }
     188           0 :     bool add_pragma_once_header(std::string const &filename,
     189             :         std::string const& guard_name)
     190             :     {
     191           0 :         typedef pragma_once_set_type::value_type value_type;
     192           0 :         return pragma_once_files.insert(value_type(filename, guard_name)).second;
     193             :     }
     194           0 :     bool remove_pragma_once_header(std::string const& guard_name)
     195             :     {
     196           0 :         typedef pragma_once_set_type::index_iterator<to>::type to_iterator;
     197           0 :         typedef std::pair<to_iterator, to_iterator> range_type;
     198             : 
     199           0 :         range_type r = pragma_once_files.get<to>().equal_range(guard_name);
     200           0 :         if (r.first != r.second) {
     201             :             using boost::multi_index::get;
     202           0 :             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           0 : bool include_paths::add_include_path (
     272             :     char const *path_, include_list_type &pathes_)
     273             : {
     274           0 :     namespace fs = boost::filesystem;
     275           0 :     if (path_) {
     276           0 :     fs::path newpath = util::complete_path(create_path(path_), current_dir);
     277             : 
     278           0 :         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           0 :             return false;
     282             :         }
     283             : 
     284           0 :         pathes_.push_back (include_value_type(newpath, path_));
     285           0 :         return true;
     286             :     }
     287             :     return false;
     288             : }
     289             : 
     290             : ///////////////////////////////////////////////////////////////////////////////
     291             : //  Find an include file by traversing the list of include directories
     292             : inline
     293           0 : 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           0 :     namespace fs = boost::filesystem;
     297           0 :     typedef include_list_type::const_iterator const_include_list_iter_t;
     298             : 
     299           0 :     const_include_list_iter_t it = pathes.begin();
     300           0 :     const_include_list_iter_t include_paths_end = pathes.end();
     301             : 
     302             : #if BOOST_WAVE_SUPPORT_INCLUDE_NEXT != 0
     303           0 :     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           0 :         fs::path file_path (create_path(current_file));
     313           0 :         for (/**/; it != include_paths_end; ++it) {
     314           0 :             fs::path currpath (create_path((*it).first.string()));
     315           0 :             if (std::equal(currpath.begin(), currpath.end(), file_path.begin()))
     316             :             {
     317           0 :                 ++it;     // start searching with the next directory
     318           0 :                 break;
     319             :             }
     320             :         }
     321             :     }
     322             : #endif
     323             : 
     324           0 :     for (/**/; it != include_paths_end; ++it) {
     325           0 :         fs::path currpath (create_path(s));
     326           0 :         if (!currpath.has_root_directory()) {
     327           0 :             currpath = create_path((*it).first.string());
     328           0 :             currpath /= create_path(s);      // append filename
     329             :         }
     330             : 
     331           0 :         if (fs::exists(currpath)) {
     332           0 :             fs::path dirpath (create_path(s));
     333           0 :             if (!dirpath.has_root_directory()) {
     334           0 :                 dirpath = create_path((*it).second);
     335           0 :                 dirpath /= create_path(s);
     336             :             }
     337             : 
     338           0 :             dir = dirpath.string();
     339           0 :             s = normalize(currpath).string();    // found the required file
     340           0 :             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           0 : include_paths::find_include_file (std::string &s, std::string &dir,
     351             :     bool is_system, char const *current_file) const
     352             : {
     353           0 :     namespace fs = boost::filesystem;
     354             : 
     355             : // if not system include (<...>), then search current directory first
     356           0 :     if (!is_system) {
     357           0 :         if (!was_sys_include_path) {  // set_sys_include_delimiter() not called
     358             :         // first have a look at the current directory
     359           0 :             fs::path currpath (create_path(s));
     360           0 :             if (!currpath.has_root_directory()) {
     361           0 :                 currpath = create_path(current_dir.string());
     362           0 :                 currpath /= create_path(s);
     363             :             }
     364             : 
     365           0 :             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           0 :                 fs::path dirpath (create_path(s));
     369           0 :                 if (!dirpath.has_root_directory()) {
     370           0 :                     dirpath = create_path(current_rel_dir.string());
     371           0 :                     dirpath /= create_path(s);
     372             :                 }
     373             : 
     374           0 :                 dir = dirpath.string();
     375           0 :                 s = normalize(currpath).string();    // found in local directory
     376           0 :                 return true;
     377             :             }
     378             : 
     379             :         // iterate all user include file directories to find the file
     380           0 :             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           0 :             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           0 :     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           0 : as_relative_to(boost::filesystem::path const& path,
     404             :     boost::filesystem::path const& base, boost::filesystem::path& result)
     405             : {
     406           0 :     if (path.has_root_path()) {
     407           0 :         if (path.root_path() == base.root_path())
     408           0 :             return as_relative_to(path.relative_path(), base.relative_path(), result);
     409             : 
     410           0 :         result = path;    // that's our result
     411             :     }
     412             :     else {
     413           0 :         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           0 :             typedef boost::filesystem::path::const_iterator path_iterator;
     419           0 :             path_iterator path_it = path.begin();
     420           0 :             path_iterator base_it = base.begin();
     421           0 :             while (path_it != path.end() && base_it != base.end() ) {
     422           0 :                 if (*path_it != *base_it)
     423             :                     break;
     424           0 :                 ++path_it; ++base_it;
     425             :             }
     426             : 
     427           0 :             for (/**/; base_it != base.end(); ++base_it)
     428           0 :                 result /= "..";
     429             : 
     430           0 :             for (/**/; path_it != path.end(); ++path_it)
     431           0 :                 result /= *path_it;
     432             :         }
     433             :     }
     434             :     return true;
     435             : }
     436             : 
     437             : ///////////////////////////////////////////////////////////////////////////////
     438             : inline
     439           0 : void include_paths::set_current_directory(char const *path_)
     440             : {
     441           0 :     namespace fs = boost::filesystem;
     442             : 
     443           0 :     fs::path filepath (create_path(path_));
     444           0 :     fs::path filename = util::complete_path(filepath, current_dir);
     445             : 
     446           0 :     BOOST_ASSERT(!(fs::exists(filename) && fs::is_directory(filename)));
     447             : 
     448           0 :     current_rel_dir.clear();
     449           0 :     if (!as_relative_to(branch_path(filepath), current_dir, current_rel_dir))
     450           0 :         current_rel_dir = branch_path(filepath);
     451           0 :     current_dir = branch_path(filename);
     452           0 : }
     453             : 
     454             : ///////////////////////////////////////////////////////////////////////////////
     455             : }}}   // namespace boost::wave::util
     456             : 
     457             : #if BOOST_WAVE_SERIALIZATION != 0
     458             : ///////////////////////////////////////////////////////////////////////////////
     459             : namespace boost { namespace serialization {
     460             : 
     461             : ///////////////////////////////////////////////////////////////////////////////
     462             : //  Serialization support for boost::filesystem::path
     463             : template<class Archive>
     464             : inline void save (Archive & ar, boost::filesystem::path const& p,
     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             : 
     472             : template<class Archive>
     473             : inline 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
     484             : template<class Archive>
     485             : inline 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
     493             : template<class Archive>
     494             : inline 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<
     501             :         Archive,
     502             :         typename boost::wave::util::bidirectional_map<
     503             :             std::string, std::string
     504             :         >::type
     505             :     >(ar, t);
     506             : }
     507             : 
     508             : template<class Archive>
     509             : inline 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
     525             : template<class Archive>
     526             : inline void serialize (Archive & ar,
     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             : 
     538             : BOOST_CLASS_VERSION(boost::wave::util::include_paths,
     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             : 
     548             : #endif // !defined(CPP_INCLUDE_PATHS_HPP_AF620DA4_B3D2_4221_AD91_8A1ABFFB6944_INCLUDED)

Generated by: LCOV version 1.14