mirror of
https://github.com/bolero-MURAKAMI/Sprout.git
synced 2024-11-14 10:39:05 +00:00
418 lines
13 KiB
C++
418 lines
13 KiB
C++
|
/*=============================================================================
|
|||
|
Copyright (c) 2011-2014 Bolero MURAKAMI
|
|||
|
https://github.com/bolero-MURAKAMI/Sprout
|
|||
|
|
|||
|
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)
|
|||
|
=============================================================================*/
|
|||
|
|
|||
|
#include <cstdlib>
|
|||
|
#include <iostream>
|
|||
|
#include <sstream>
|
|||
|
#include <fstream>
|
|||
|
#include <string>
|
|||
|
#include <vector>
|
|||
|
#include <utility>
|
|||
|
#include <iterator>
|
|||
|
#include <algorithm>
|
|||
|
#include <boost/wave.hpp>
|
|||
|
#include <boost/wave/preprocessing_hooks.hpp>
|
|||
|
#include <boost/wave/cpplexer/cpp_lex_token.hpp>
|
|||
|
#include <boost/wave/cpplexer/cpp_lex_iterator.hpp>
|
|||
|
#include <boost/graph/adjacency_list.hpp>
|
|||
|
#include <boost/graph/depth_first_search.hpp>
|
|||
|
#include <boost/graph/graphviz.hpp>
|
|||
|
#include <boost/filesystem.hpp>
|
|||
|
#include <boost/range.hpp>
|
|||
|
#include <boost/algorithm/string.hpp>
|
|||
|
#include "../sprig/algorithm/string.hpp"
|
|||
|
#include "../sprig/graph/depth_first_search.hpp"
|
|||
|
|
|||
|
class include_graph_hooks
|
|||
|
: public boost::wave::context_policies::default_preprocessing_hooks
|
|||
|
{
|
|||
|
private:
|
|||
|
typedef boost::wave::context_policies::default_preprocessing_hooks base_type;
|
|||
|
public:
|
|||
|
// <20>O<EFBFBD><4F><EFBFBD>t<EFBFBD>̃m<CC83>[<5B>h
|
|||
|
struct node_type {
|
|||
|
boost::filesystem::path absolute;
|
|||
|
boost::filesystem::path filename;
|
|||
|
bool has_include_guard;
|
|||
|
public:
|
|||
|
node_type(boost::filesystem::path const& absolute, boost::filesystem::path const& filename)
|
|||
|
: absolute(absolute), filename(filename), has_include_guard(false)
|
|||
|
{}
|
|||
|
operator boost::filesystem::path const&() const {
|
|||
|
return filename;
|
|||
|
}
|
|||
|
operator std::string() const {
|
|||
|
return filename.generic_string();
|
|||
|
}
|
|||
|
friend bool operator==(node_type const& lhs, node_type const& rhs) {
|
|||
|
return lhs.absolute == rhs.absolute;
|
|||
|
}
|
|||
|
friend bool operator==(node_type const& lhs, boost::filesystem::path const& rhs) {
|
|||
|
return lhs.absolute == rhs;
|
|||
|
}
|
|||
|
friend bool operator==(boost::filesystem::path const& lhs, node_type const& rhs) {
|
|||
|
return lhs == rhs.absolute;
|
|||
|
}
|
|||
|
friend bool operator!=(node_type const& lhs, node_type const& rhs) {
|
|||
|
return !(lhs == rhs);
|
|||
|
}
|
|||
|
friend bool operator!=(node_type const& lhs, boost::filesystem::path const& rhs) {
|
|||
|
return !(lhs == rhs);
|
|||
|
}
|
|||
|
friend bool operator!=(boost::filesystem::path const& lhs, node_type const& rhs) {
|
|||
|
return !(lhs == rhs);
|
|||
|
}
|
|||
|
template<typename Elem, typename Traits>
|
|||
|
friend std::basic_ostream<Elem, Traits>& operator<<(std::basic_ostream<Elem, Traits>& lhs, node_type const& rhs) {
|
|||
|
return lhs << rhs.filename.generic_string();
|
|||
|
}
|
|||
|
};
|
|||
|
typedef std::pair<int, int> edge_type;
|
|||
|
typedef boost::adjacency_list<
|
|||
|
boost::vecS,
|
|||
|
boost::vecS,
|
|||
|
boost::bidirectionalS,
|
|||
|
boost::no_property
|
|||
|
> graph_type;
|
|||
|
private:
|
|||
|
std::vector<node_type> node_list_;
|
|||
|
std::vector<edge_type> edge_list_;
|
|||
|
std::vector<int> current_list_;
|
|||
|
int current_;
|
|||
|
public:
|
|||
|
explicit include_graph_hooks(boost::filesystem::path const& start)
|
|||
|
: node_list_{node_type{boost::filesystem::absolute(start), start.filename()}}
|
|||
|
, edge_list_{}
|
|||
|
, current_list_{0}
|
|||
|
, current_(0)
|
|||
|
{}
|
|||
|
std::vector<node_type> const&
|
|||
|
nodes() const {
|
|||
|
return node_list_;
|
|||
|
}
|
|||
|
std::vector<edge_type> const&
|
|||
|
edges() const {
|
|||
|
return edge_list_;
|
|||
|
}
|
|||
|
// <20>O<EFBFBD><4F><EFBFBD>t<EFBFBD><74><EFBFBD><EFBFBD>
|
|||
|
template<typename Graph>
|
|||
|
Graph make_graph() const {
|
|||
|
return Graph(edge_list_.begin(), edge_list_.end(), node_list_.size());
|
|||
|
}
|
|||
|
graph_type make_graph() const {
|
|||
|
return make_graph<graph_type>();
|
|||
|
}
|
|||
|
// graphviz <20>o<EFBFBD><6F>
|
|||
|
void write_graphviz(std::ostream& out) const {
|
|||
|
boost::write_graphviz(
|
|||
|
out,
|
|||
|
make_graph<graph_type>(),
|
|||
|
boost::make_label_writer(&node_list_[0])
|
|||
|
);
|
|||
|
}
|
|||
|
// <20><><EFBFBD>C<EFBFBD><43><EFBFBD>N<EFBFBD><4E><EFBFBD>[<5B>h<EFBFBD>K<EFBFBD>[<5B>h<EFBFBD><68><EFBFBD>o
|
|||
|
template<typename OutputIterator>
|
|||
|
void collect_no_include_guard_files(OutputIterator result) const {
|
|||
|
std::copy_if(
|
|||
|
node_list_.begin() + 1, node_list_.end(), result,
|
|||
|
[](node_type const& e) { return !e.has_include_guard; }
|
|||
|
);
|
|||
|
}
|
|||
|
// <20>z<EFBFBD>C<C283><43><EFBFBD>N<EFBFBD><4E><EFBFBD>[<5B>h<EFBFBD><68><EFBFBD>o
|
|||
|
template<typename OutputIterator>
|
|||
|
void collect_circulated_includes(OutputIterator result) const {
|
|||
|
boost::depth_first_search(
|
|||
|
make_graph<graph_type>(),
|
|||
|
boost::visitor(sprig::make_back_edge_recorder(result))
|
|||
|
);
|
|||
|
}
|
|||
|
// <20>Ǘ<EFBFBD><C797>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD>o
|
|||
|
template<typename OutputIterator>
|
|||
|
void collect_isolated_files(OutputIterator result, boost::filesystem::path const& path) const {
|
|||
|
typedef boost::filesystem::recursive_directory_iterator iterator;
|
|||
|
for (auto it = iterator(path), last = iterator(); it != last; ++it) {
|
|||
|
if (!boost::filesystem::is_directory(*it)) {
|
|||
|
boost::filesystem::path abspath(boost::filesystem::absolute(*it));
|
|||
|
auto found = std::find(node_list_.begin(), node_list_.end(), abspath);
|
|||
|
if (found == node_list_.end()) { // <20>C<EFBFBD><43><EFBFBD>N<EFBFBD><4E><EFBFBD>[<5B>h<EFBFBD><68><EFBFBD><EFBFBD><EFBFBD>Ă<EFBFBD><C482>Ȃ<EFBFBD><C882>Ȃ<EFBFBD><C882>Ό<EFBFBD><CE8C>ʂɒlj<C992>
|
|||
|
*result++ = abspath.generic_string();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
public:
|
|||
|
// <20>C<EFBFBD><43><EFBFBD>N<EFBFBD><4E><EFBFBD>[<5B>h<EFBFBD>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>p<EFBFBD>X<EFBFBD>ݒ菈<DD92><E88F88><EFBFBD><EFBFBD><EFBFBD>t<EFBFBD>b<EFBFBD>N
|
|||
|
template<typename Context>
|
|||
|
bool locate_include_file(
|
|||
|
Context& ctx,
|
|||
|
std::string& file_path,
|
|||
|
bool is_system,
|
|||
|
char const* current_name,
|
|||
|
std::string& dir_path,
|
|||
|
std::string& native_name
|
|||
|
)
|
|||
|
{
|
|||
|
std::string filename = is_system ? ('<' + file_path + '>') : ('\"' + file_path + '\"');
|
|||
|
if (!base_type::locate_include_file(ctx, file_path, is_system, current_name, dir_path, native_name)) {
|
|||
|
return false;
|
|||
|
}
|
|||
|
dir_path = filename; // <20>C<EFBFBD><43><EFBFBD>N<EFBFBD><4E><EFBFBD>[<5B>h<EFBFBD>f<EFBFBD>B<EFBFBD><42><EFBFBD>N<EFBFBD>e<EFBFBD>B<EFBFBD>u<EFBFBD>̃e<CC83>L<EFBFBD>X<EFBFBD>g<EFBFBD>ŏ㏑<C58F><E38F91>
|
|||
|
return true;
|
|||
|
}
|
|||
|
// <20>C<EFBFBD><43><EFBFBD>N<EFBFBD><4E><EFBFBD>[<5B>h<EFBFBD>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD>͊J<CD8A>n<EFBFBD><6E><EFBFBD>t<EFBFBD>b<EFBFBD>N
|
|||
|
template<typename Context>
|
|||
|
void opened_include_file(
|
|||
|
Context const& /*ctx*/,
|
|||
|
std::string const& relname,
|
|||
|
std::string const& absname,
|
|||
|
bool /*is_system_include*/
|
|||
|
)
|
|||
|
{
|
|||
|
boost::filesystem::path abspath(boost::filesystem::absolute(absname));
|
|||
|
auto found = std::find(node_list_.begin(), node_list_.end(), abspath);
|
|||
|
auto to = std::distance(node_list_.begin(), found);
|
|||
|
if (found == node_list_.end()) { // <20>ŏ<EFBFBD><C58F>̃C<CC83><43><EFBFBD>N<EFBFBD><4E><EFBFBD>[<5B>h<EFBFBD>Ȃ<EFBFBD><C882>m<CE83>[<5B>h<EFBFBD>ɒlj<C992>
|
|||
|
node_list_.emplace_back(abspath, relname);
|
|||
|
}
|
|||
|
edge_list_.emplace_back(current_list_.back(), to);
|
|||
|
current_list_.push_back(to); // <20>J<EFBFBD><4A><EFBFBD><EFBFBD><EFBFBD>g<EFBFBD><67><EFBFBD>X<EFBFBD>V
|
|||
|
current_ = to;
|
|||
|
}
|
|||
|
// <20>C<EFBFBD><43><EFBFBD>N<EFBFBD><4E><EFBFBD>[<5B>h<EFBFBD>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD>͊<EFBFBD><CD8A><EFBFBD><EFBFBD><EFBFBD><EFBFBD>t<EFBFBD>b<EFBFBD>N
|
|||
|
template<typename Context>
|
|||
|
void returning_from_include_file(Context const& /*ctx*/) {
|
|||
|
current_ = current_list_.back();
|
|||
|
current_list_.pop_back(); // <20>J<EFBFBD><4A><EFBFBD><EFBFBD><EFBFBD>g<EFBFBD><67><EFBFBD>߂<EFBFBD>
|
|||
|
}
|
|||
|
// <20>C<EFBFBD><43><EFBFBD>N<EFBFBD><4E><EFBFBD>[<5B>h<EFBFBD>K<EFBFBD>[<5B>h<EFBFBD><68><EFBFBD>o<EFBFBD><6F><EFBFBD>t<EFBFBD>b<EFBFBD>N
|
|||
|
template<typename Context>
|
|||
|
void detected_include_guard(
|
|||
|
Context const& /*ctx*/,
|
|||
|
std::string const& /*filename*/,
|
|||
|
std::string const& /*include_guard*/
|
|||
|
)
|
|||
|
{
|
|||
|
node_list_.at(current_).has_include_guard = true;
|
|||
|
}
|
|||
|
template<typename Context, typename Token>
|
|||
|
void detected_pragma_once(
|
|||
|
Context const& /*ctx*/,
|
|||
|
Token const& /*pragma_token*/,
|
|||
|
std::string const& /*filename*/
|
|||
|
)
|
|||
|
{
|
|||
|
node_list_.at(current_).has_include_guard = true;
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
// <20>V<EFBFBD>X<EFBFBD>e<EFBFBD><65><EFBFBD>C<EFBFBD><43><EFBFBD>N<EFBFBD><4E><EFBFBD>[<5B>h<EFBFBD>p<EFBFBD>X<EFBFBD>̎擾
|
|||
|
template<typename OutputIterator>
|
|||
|
void collect_sysinclude_paths(OutputIterator result, std::string const& command = "g++") {
|
|||
|
{
|
|||
|
std::ofstream ofs("_collect_sysinclude_paths.cpp");
|
|||
|
}
|
|||
|
std::system((command + " -v -E _collect_sysinclude_paths.cpp 1> /dev/null 2> _collect_sysinclude_paths").c_str());
|
|||
|
{
|
|||
|
std::ifstream ifs("_collect_sysinclude_paths");
|
|||
|
std::string text(
|
|||
|
std::istreambuf_iterator<char>(ifs.rdbuf()),
|
|||
|
std::istreambuf_iterator<char>()
|
|||
|
);
|
|||
|
auto rng = boost::make_iterator_range(text);
|
|||
|
rng = sprig::find_skip(rng, boost::algorithm::first_finder("#include <...>")); // <20>C<EFBFBD><43><EFBFBD>N<EFBFBD><4E><EFBFBD>[<5B>h<EFBFBD>p<EFBFBD>X<EFBFBD>̎n<CC8E>_<EFBFBD>܂ŃX<C583>L<EFBFBD>b<EFBFBD>v
|
|||
|
rng = sprig::find_skip(rng, boost::algorithm::first_finder("\n"));
|
|||
|
while (boost::algorithm::starts_with(rng, " ")) {
|
|||
|
auto found = sprig::find_between(
|
|||
|
rng,
|
|||
|
boost::algorithm::token_finder(boost::algorithm::is_space(), boost::algorithm::token_compress_on),
|
|||
|
boost::algorithm::first_finder("\n")
|
|||
|
);
|
|||
|
*result++ = std::string(boost::begin(found), boost::end(found));
|
|||
|
rng = boost::make_iterator_range(boost::end(found), boost::end(rng));
|
|||
|
rng = sprig::find_skip(rng, boost::algorithm::first_finder("\n"));
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
int main(int argc, const char* argv[]) {
|
|||
|
std::string src;
|
|||
|
std::string text;
|
|||
|
|
|||
|
if (argc >= 2) {
|
|||
|
src = argv[1];
|
|||
|
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓<EFBFBD><CC93>e<EFBFBD><65><EFBFBD>S<EFBFBD><53> text <20>ɓǂݍ<C782><DD8D><EFBFBD>
|
|||
|
std::ifstream ifs(argv[1]);
|
|||
|
text = std::string(
|
|||
|
std::istreambuf_iterator<char>(ifs.rdbuf()),
|
|||
|
std::istreambuf_iterator<char>()
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
try {
|
|||
|
// <20>v<EFBFBD><76><EFBFBD>v<EFBFBD><76><EFBFBD>Z<EFBFBD>b<EFBFBD>T<EFBFBD><54><EFBFBD>p<EFBFBD><70>
|
|||
|
typedef boost::wave::context<
|
|||
|
std::string::iterator,
|
|||
|
boost::wave::cpplexer::lex_iterator<boost::wave::cpplexer::lex_token<> >,
|
|||
|
boost::wave::iteration_context_policies::load_file_to_string,
|
|||
|
::include_graph_hooks
|
|||
|
> context_type;
|
|||
|
context_type ctx(text.begin(), text.end(), src.c_str(), ::include_graph_hooks(src));
|
|||
|
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD>Q<EFBFBD>[<5B>W<EFBFBD>̐ݒ<CC90>
|
|||
|
ctx.set_language(
|
|||
|
boost::wave::language_support(
|
|||
|
boost::wave::support_cpp11
|
|||
|
| boost::wave::support_option_include_guard_detection // <20>C<EFBFBD><43><EFBFBD>N<EFBFBD><4E><EFBFBD>[<5B>h<EFBFBD>K<EFBFBD>[<5B>h<EFBFBD><68><EFBFBD>o
|
|||
|
)
|
|||
|
);
|
|||
|
// <20>C<EFBFBD><43><EFBFBD>N<EFBFBD><4E><EFBFBD>[<5B>h<EFBFBD>p<EFBFBD>X<EFBFBD>̐ݒ<CC90>
|
|||
|
{
|
|||
|
std::vector<std::string> list;
|
|||
|
::collect_sysinclude_paths(std::back_inserter(list));
|
|||
|
std::cout
|
|||
|
<< "sysinclude paths :\n"
|
|||
|
;
|
|||
|
for (auto&& e : list) {
|
|||
|
std::cout
|
|||
|
<< " " << e << "\n"
|
|||
|
;
|
|||
|
ctx.add_sysinclude_path(e.c_str());
|
|||
|
}
|
|||
|
std::cout
|
|||
|
<< std::flush
|
|||
|
;
|
|||
|
}
|
|||
|
|
|||
|
if (!src.empty()) {
|
|||
|
// <20>v<EFBFBD><76><EFBFBD>v<EFBFBD><76><EFBFBD>Z<EFBFBD>X<EFBFBD>𑖂点<F0919682><E782B9>
|
|||
|
for (auto&& e : ctx) {
|
|||
|
//std::cout << e.get_value();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
for ( ; ;) {
|
|||
|
std::cout
|
|||
|
<< "> "
|
|||
|
<< std::flush
|
|||
|
;
|
|||
|
std::string line;
|
|||
|
std::getline(std::cin, line);
|
|||
|
if (line.empty()) {
|
|||
|
break;
|
|||
|
}
|
|||
|
std::vector<std::string> tokens;
|
|||
|
boost::algorithm::split(tokens, line, boost::algorithm::is_space());
|
|||
|
if (tokens.at(0) == "find") {
|
|||
|
// <20>C<EFBFBD><43><EFBFBD>N<EFBFBD><4E><EFBFBD>[<5B>h<EFBFBD>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
if (tokens.size() < 2) {
|
|||
|
std::cout
|
|||
|
<< "missing parameter.\n"
|
|||
|
<< std::flush
|
|||
|
;
|
|||
|
continue;
|
|||
|
}
|
|||
|
std::cout
|
|||
|
<< "find <" << tokens.at(1) << "> :\n"
|
|||
|
;
|
|||
|
std::string filepath(tokens.at(1));
|
|||
|
std::string dirpath;
|
|||
|
if (!ctx.find_include_file(filepath, dirpath, true, 0)) {
|
|||
|
std::cout
|
|||
|
<< " not found\n"
|
|||
|
<< std::flush
|
|||
|
;
|
|||
|
continue;
|
|||
|
}
|
|||
|
std::cout
|
|||
|
<< " " << filepath << "\n"
|
|||
|
<< std::flush
|
|||
|
;
|
|||
|
} else if (tokens.at(0) == "graph") {
|
|||
|
// <20>O<EFBFBD><4F><EFBFBD>t<EFBFBD>o<EFBFBD><6F>
|
|||
|
std::cout
|
|||
|
<< "graph output > out.graph.dot\n"
|
|||
|
;
|
|||
|
std::ofstream ofs("out.graph.dot");
|
|||
|
ctx.get_hooks().write_graphviz(ofs);
|
|||
|
std::cout
|
|||
|
<< std::flush
|
|||
|
;
|
|||
|
} else if (tokens.at(0) == "noguard") {
|
|||
|
// <20><><EFBFBD>C<EFBFBD><43><EFBFBD>N<EFBFBD><4E><EFBFBD>[<5B>h<EFBFBD>K<EFBFBD>[<5B>h<EFBFBD><68><EFBFBD>o<EFBFBD><6F>
|
|||
|
std::vector<::include_graph_hooks::node_type> list;
|
|||
|
ctx.get_hooks().collect_no_include_guard_files(std::back_inserter(list));
|
|||
|
std::cout
|
|||
|
<< "no include guarde files (" << list.size() << ") :\n"
|
|||
|
;
|
|||
|
for (auto const& e : list) {
|
|||
|
std::cout
|
|||
|
<< " " << e << "\n"
|
|||
|
;
|
|||
|
}
|
|||
|
std::cout
|
|||
|
<< std::flush
|
|||
|
;
|
|||
|
} else if (tokens.at(0) == "circulated") {
|
|||
|
// <20>z<EFBFBD>C<C283><43><EFBFBD>N<EFBFBD><4E><EFBFBD>[<5B>h<EFBFBD><68><EFBFBD>o<EFBFBD><6F>
|
|||
|
std::vector<typename boost::graph_traits<::include_graph_hooks::graph_type>::edge_descriptor> list;
|
|||
|
ctx.get_hooks().collect_circulated_includes(std::back_inserter(list));
|
|||
|
auto g = ctx.get_hooks().make_graph();
|
|||
|
std::cout
|
|||
|
<< "circulated includes (" << list.size() << ") :\n"
|
|||
|
;
|
|||
|
for (auto const& e : list) {
|
|||
|
std::cout
|
|||
|
<< " " << boost::source(e, g) << "[" << ctx.get_hooks().nodes()[boost::source(e, g)] << "]\n"
|
|||
|
<< " -> " << boost::target(e, g) << "[" << ctx.get_hooks().nodes()[boost::target(e, g)] << "]\n"
|
|||
|
;
|
|||
|
}
|
|||
|
std::cout
|
|||
|
<< std::flush
|
|||
|
;
|
|||
|
} else if (tokens.at(0) == "isolated") {
|
|||
|
// Sprout <20>̌Ǘ<CC8C><C797>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD>o<EFBFBD><6F>
|
|||
|
std::cout
|
|||
|
<< "isolated files output > out.isolated.txt\n"
|
|||
|
;
|
|||
|
std::ofstream ofs("out.isolated.txt");
|
|||
|
// Sprout <20>̃V<CC83>X<EFBFBD>e<EFBFBD><65><EFBFBD>C<EFBFBD><43><EFBFBD>N<EFBFBD><4E><EFBFBD>|<7C>h<EFBFBD>p<EFBFBD>X<EFBFBD><58><EFBFBD>擾
|
|||
|
std::string filepath("sprout/config.hpp");
|
|||
|
std::string dirpath;
|
|||
|
if (!ctx.find_include_file(filepath, dirpath, true, 0)) {
|
|||
|
std::cerr
|
|||
|
<< "#error sprout not found\n"
|
|||
|
<< std::flush
|
|||
|
;
|
|||
|
continue;
|
|||
|
}
|
|||
|
dirpath = boost::filesystem::path(filepath).parent_path().generic_string();
|
|||
|
// <20><><EFBFBD>X<EFBFBD>g<EFBFBD>o<EFBFBD><6F>
|
|||
|
std::vector<std::string> list;
|
|||
|
ctx.get_hooks().collect_isolated_files(std::back_inserter(list), dirpath);
|
|||
|
std::sort(list.begin(), list.end());
|
|||
|
std::copy(list.begin(), list.end(), std::ostream_iterator<std::string>(ofs, "\n"));
|
|||
|
std::cout
|
|||
|
<< std::flush
|
|||
|
;
|
|||
|
} else {
|
|||
|
std::cout
|
|||
|
<< "invalid command\n"
|
|||
|
<< std::flush
|
|||
|
;
|
|||
|
}
|
|||
|
}
|
|||
|
} catch (boost::wave::cpp_exception& e) {
|
|||
|
// <20>v<EFBFBD><76><EFBFBD>v<EFBFBD><76><EFBFBD>Z<EFBFBD>X<EFBFBD>ŃG<C583><47><EFBFBD>[<5B><><EFBFBD><EFBFBD>
|
|||
|
std::cerr
|
|||
|
<< "#error " << e.file_name() << "(" << e.line_no() << "):" << e.description() << "\n"
|
|||
|
<< std::flush
|
|||
|
;
|
|||
|
}
|
|||
|
}
|