77 lines
1.9 KiB
C++
77 lines
1.9 KiB
C++
#include "io.hpp"
|
|
#include "iterator.hpp"
|
|
#include "string.hpp"
|
|
#include "view.hpp"
|
|
|
|
#include <iostream>
|
|
#include <cstdlib>
|
|
#include <fstream>
|
|
|
|
|
|
enum {
|
|
ARG_SELF,
|
|
ARG_SRC,
|
|
ARG_DST,
|
|
|
|
MIN_ARGS = ARG_SRC+1,
|
|
};
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void process (std::ostream &dst, const std::experimental::filesystem::path&);
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
struct include {
|
|
template <typename IteratorA, typename IteratorB>
|
|
void
|
|
operator() (std::ostream &dst, util::view<IteratorA,IteratorB> data)
|
|
{
|
|
if (data.size () < 3)
|
|
throw std::invalid_argument ("invalid argument for include");
|
|
|
|
if (data[0] != '"' || data[data.size()-1] != '"')
|
|
throw std::invalid_argument ("invalid path specification");
|
|
|
|
process (dst, {data.begin () + 1, data.end () - 1});
|
|
}
|
|
};
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
process (std::ostream &dst, const std::experimental::filesystem::path &src)
|
|
{
|
|
auto data = util::slurp<char> (src);
|
|
include handler;
|
|
|
|
for (const auto &l: util::tokeniser (data.data (), '\n')) {
|
|
if (l.empty () || l[0] != '#') {
|
|
dst << l << '\n';
|
|
continue;
|
|
}
|
|
|
|
auto space = std::find (l.begin (), l.end (), ' ');
|
|
handler (dst, util::view{space+1,l.end()});
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
int
|
|
main (const int argc, const char **argv)
|
|
{
|
|
if (argc < 2) {
|
|
std::cerr << argv[ARG_SELF] << " <src> [dst]\n";
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
std::experimental::filesystem::path src = argv[ARG_SRC];
|
|
|
|
if (argc == 3) {
|
|
std::ofstream dst (argv[ARG_DST]);
|
|
process (dst, src);
|
|
} else {
|
|
process (std::cout, src);
|
|
};
|
|
}; |