Imported Upstream version 1.72.0
[platform/upstream/boost.git] / tools / bcp / copy_path.cpp
1 /*
2  *
3  * Copyright (c) 2003 Dr John Maddock
4  * Use, modification and distribution is subject to the
5  * Boost Software License, Version 1.0. (See accompanying file
6  * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7  *
8  * This file implements the following:
9  *    void bcp_implementation::copy_path(const fs::path& p)
10  *    void bcp_implementation::create_path(const fs::path& p)
11  */
12
13 #include "bcp_imp.hpp"
14 #include "fileview.hpp"
15 #include <boost/filesystem/operations.hpp>
16 #include <boost/filesystem/fstream.hpp>
17 #include <boost/regex.hpp>
18 #include <boost/assert.hpp>
19 #include <fstream>
20 #include <iterator>
21 #include <algorithm>
22 #include <iostream>
23
24 struct get_new_library_name
25 {
26    get_new_library_name(const std::string& n) : m_new_name(n) {}
27    template <class I>
28    std::string operator()(const boost::match_results<I>& what)
29    {
30       std::string s = what[0];
31       std::string::size_type n = s.find("boost");
32       if(n == std::string::npos)
33       {
34          s.insert(0, m_new_name);
35       }
36       else
37       {
38          s.replace(n, 5, m_new_name);
39       }
40       return s;
41    }
42 private:
43    std::string m_new_name;
44 };
45
46 void bcp_implementation::copy_path(const fs::path& p)
47 {
48    BOOST_ASSERT(!fs::is_directory(m_boost_path / p));
49    if(fs::exists(m_dest_path / p))
50    {
51       std::cout << "Copying (and overwriting) file: " << p.string() << "\n";
52      fs::remove(m_dest_path / p);
53    }
54    else
55       std::cout << "Copying file: " << p.string() << "\n";
56    //
57    // create the path to the new file if it doesn't already exist:
58    //
59    create_path(p.branch_path());
60    //
61    // do text based copy if requested:
62    //
63    if((p.leaf() == "Jamroot") && m_namespace_name.size())
64    {
65       static std::vector<char> v1, v2;
66       v1.clear();
67       v2.clear();
68       boost::filesystem::ifstream is((m_boost_path / p));
69       std::copy(std::istreambuf_iterator<char>(is), std::istreambuf_iterator<char>(), std::back_inserter(v1));
70
71       static boost::regex libname_matcher;
72       if(libname_matcher.empty())
73       {
74          libname_matcher.assign("boost_");
75       }
76
77       regex_replace(std::back_inserter(v2), v1.begin(), v1.end(), libname_matcher, m_namespace_name + "_");
78       std::swap(v1, v2);
79       v2.clear();
80
81       boost::filesystem::ofstream os;
82       if(m_unix_lines)
83          os.open((m_dest_path / p), std::ios_base::binary | std::ios_base::out);
84       else
85          os.open((m_dest_path / p), std::ios_base::out);
86       os.write(&*v1.begin(), v1.size());
87       os.close();
88    }
89    else if(m_namespace_name.size() && m_lib_names.size() && is_jam_file(p))
90    {
91       static std::vector<char> v1, v2;
92       v1.clear();
93       v2.clear();
94       boost::filesystem::ifstream is((m_boost_path / p));
95       std::copy(std::istreambuf_iterator<char>(is), std::istreambuf_iterator<char>(), std::back_inserter(v1));
96
97       static boost::regex libname_matcher;
98       if(libname_matcher.empty())
99       {
100          std::string re = "\\<";
101          re += *m_lib_names.begin();
102          for(std::set<std::string>::const_iterator i = ++m_lib_names.begin(); i != m_lib_names.end(); ++i)
103          {
104             re += "|" + *i;
105          }
106          re += "\\>";
107          libname_matcher.assign(re);
108       }
109
110       regex_replace(std::back_inserter(v2), v1.begin(), v1.end(), libname_matcher, get_new_library_name(m_namespace_name));
111       std::swap(v1, v2);
112       v2.clear();
113
114       boost::filesystem::ofstream os;
115       if(m_unix_lines)
116          os.open((m_dest_path / p), std::ios_base::binary | std::ios_base::out);
117       else
118          os.open((m_dest_path / p), std::ios_base::out);
119       os.write(&*v1.begin(), v1.size());
120       os.close();
121    }
122    else if(m_namespace_name.size() && is_source_file(p))
123    {
124       //
125       // v1 hold the current content, v2 is temp buffer.
126       // Each time we do a search and replace the new content
127       // ends up in v2: we then swap v1 and v2, and clear v2.
128       //
129       static std::vector<char> v1, v2;
130       v1.clear();
131       v2.clear();
132       boost::filesystem::ifstream is((m_boost_path / p));
133       std::copy(std::istreambuf_iterator<char>(is), std::istreambuf_iterator<char>(), std::back_inserter(v1));
134
135       static const boost::regex namespace_matcher(
136          "(?|"
137             "(namespace\\s+)boost(_\\w+)?(?:(\\s*::\\s*)phoenix)?"
138          "|"
139             "(namespace\\s+(?:detail::)?)(adstl|phoenix|rapidxml)\\>"
140          "|"
141             "()\\<boost((?:_(?!intrusive_tags)\\w+)?\\s*(?:::))(?:(\\s*)phoenix)?"
142          "|"
143             "()\\<((?:adstl|phoenix|rapidxml)\\s*(?:::))"
144          "|"
145          "(namespace\\s+\\w+\\s*=\\s*(?:::\\s*)?)boost(_\\w+)?(?:(\\s*::\\s*)phoenix)?"
146          "|"
147             "(namespace\\s+\\w+\\s*=\\s*(?:::\\s*)?(?:\\w+\\s*::\\s*)?)(adstl|phoenix|rapidxml)\\>"
148          "|"
149             "(^\\s*#\\s*define\\s+\\w+\\s+)boost((?:_\\w+)?\\s*)$"
150          "|"
151             "(^\\s*#\\s*define[^\\n]+)((?:adstl|phoenix|rapidxml)\\s*)$"
152          "|"
153             "()boost(_asio_detail_posix_thread_function|_regex_free_static_mutex)"
154          "|"
155          "()\\<(lw_thread_routine|at_thread_exit|on_process_enter|on_process_exit|on_thread_enter|on_thread_exit|tss_cleanup_implemented)\\>"
156          "|"
157             "(BOOST_CLASS_REQUIRE4?[^;]*)boost((?:_\\w+)?\\s*,)"
158          "|"
159             "(::tr1::|TR1_DECL\\s+)boost(_\\w+\\s*)" // math tr1
160          "|"
161             "(\\(\\s*)boost(\\s*\\))\\s*(\\(\\s*)phoenix(\\s*\\))"
162          "|"
163             "(\\(\\s*)boost(\\s*\\))"
164          "|"
165             "(BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE[^\\)]*)boost(\\))"
166          ")"
167       );
168
169       regex_replace(std::back_inserter(v2), v1.begin(), v1.end(), namespace_matcher, "$1" + m_namespace_name + "$2(?3$3" + m_namespace_name + "phoenix?4$4)", boost::regex_constants::format_all);
170       std::swap(v1, v2);
171       v2.clear();
172
173       if(m_namespace_alias)
174       {
175          static const boost::regex namespace_alias(
176             /*
177             "namespace\\s+" + m_namespace_name +
178             "\\s*"
179             "("
180                "\\{"
181                "(?:"
182                   "(?>[^\\{\\}/]+)"
183                   "(?>"
184                      "(?:"
185                         "(?1)"
186                         "|//[^\\n]+$"
187                         "|/[^/]"
188                         "|(?:^\\s*#[^\\n]*"
189                            "(?:(?<=\\\\)\\n[^\\n]*)*)"
190                      ")"
191                      "[^\\{\\}]+"
192                   ")*"
193                ")*"
194                "\\}"
195             ")"
196             */
197             /*
198             "(namespace\\s+" + m_namespace_name +
199             "\\s*\\{.*"
200             "\\})([^\\{\\};]*)\\z"
201             */
202             "(namespace)(\\s+)(" + m_namespace_name + ")"
203             "(adstl|phoenix|rapidxml)?(\\s*\\{)"
204             );
205          regex_replace(std::back_inserter(v2), v1.begin(), v1.end(), namespace_alias,
206             "$1 $3$4 {} $1 (?4$4:boost) = $3$4; $1$2$3$4$5", boost::regex_constants::format_all);
207          std::swap(v1, v2);
208          v2.clear();
209       }
210
211       boost::filesystem::ofstream os;
212       if(m_unix_lines)
213          os.open((m_dest_path / p), std::ios_base::binary | std::ios_base::out);
214       else
215          os.open((m_dest_path / p), std::ios_base::out);
216       if(v1.size())
217          os.write(&*v1.begin(), v1.size());
218       os.close();
219    }
220    else if(m_unix_lines && !is_binary_file(p))
221    {
222       boost::filesystem::ifstream is((m_boost_path / p));
223       std::istreambuf_iterator<char> isi(is);
224       std::istreambuf_iterator<char> end;
225
226       boost::filesystem::ofstream os((m_dest_path / p), std::ios_base::binary | std::ios_base::out);
227       std::ostreambuf_iterator<char> osi(os);
228
229       std::copy(isi, end, osi);
230    }
231    else
232    {
233       // binary copy:
234       fs::copy_file(m_boost_path / p, m_dest_path / p);
235    }
236 }
237
238 void bcp_implementation::create_path(const fs::path& p)
239 {
240    if(!fs::exists(m_dest_path / p))
241    {
242       // recurse then create the path:
243       create_path(p.branch_path());
244       fs::create_directory(m_dest_path / p);
245    }
246 }
247
248