macro: trivial preprocessor for includes

This commit is contained in:
Danny Robson 2018-01-30 12:52:58 +11:00
parent 8682381618
commit 18a7790a2a
2 changed files with 78 additions and 1 deletions

View File

@ -425,7 +425,7 @@ target_link_libraries(cruft-util dl)
############################################################################### ###############################################################################
foreach (tool json-clean json-schema json-validate scratch) foreach (tool json-clean json-schema json-validate macro scratch)
add_executable (util_${tool} tools/${tool}.cpp) add_executable (util_${tool} tools/${tool}.cpp)
set_target_properties (util_${tool} PROPERTIES OUTPUT_NAME ${tool}) set_target_properties (util_${tool} PROPERTIES OUTPUT_NAME ${tool})
target_link_libraries (util_${tool} cruft-util) target_link_libraries (util_${tool} cruft-util)

77
tools/macro.cpp Normal file
View File

@ -0,0 +1,77 @@
#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);
};
};