summaryrefslogtreecommitdiff
path: root/icetray/tool/icetraySql.cpp
blob: 3b3d1d9a159a7089807ce80bf5e42c5acecf41c4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include <iostream>
#include <fstream>
#include <boost/program_options.hpp>
#include <filesystem>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <compileTimeFormatter.h>

namespace po = boost::program_options;
namespace fs = std::filesystem;

AdHocFormatter(CPPHeader,
		R"C(#include "%?.h"

const IceTray::StaticSqlSource )C");
AdHocFormatter(CPPNS, "%?::");
AdHocFormatter(CPPOpen, R"C(%?
__attribute__((init_priority(209))) (R"SQL()C");
AdHocFormatter(CPPConnectorOpts, R"C(, "%?", {%?})C");
AdHocFormatter(CPPConnectorOpt, R"C({ "%?", "%?" },)C");
AdHocFormatter(CPPConnectorOptFlag, R"C({ "%?", "" },)C");
AdHocFormatter(CPPClose, R"C()SQL")C");
AdHocFormatter(CPPFooter, R"C();

)C");
AdHocFormatter(HHeader,
		R"H(#include <staticSqlSource.h>

)H");
AdHocFormatter(HDeclartion, "extern const IceTray::StaticSqlSource %?;\n");
AdHocFormatter(HFooter, "\n");

AdHocFormatter(OpenNamespace, "namespace %? {\n");
AdHocFormatter(CloseNamespace, "} // %?\n");

int
main(int argc, char ** argv)
{
	po::options_description opts("IceTray SQL-to-C++ precompiler");
	fs::path sql, cpp, h, base;
	std::string sqlns, connector;

	opts.add_options()
		("help,h", "Show this help message")
		("sql", po::value(&sql)->required(), "Path of SQL script")
		("cpp", po::value(&cpp)->required(), "Path of C++ file to write")
		("h", po::value(&h)->required(), "Path of header file to write")
		("basedir,d", po::value(&base)->default_value(fs::current_path()), "Base directory of SQL scripts (namespaces are created relative to here)")
		("namespace", po::value(&sqlns), "Namespace to create SqlSource in")
		("connector,c", po::value(&connector), "Specifiy a default connector name")
		;

	po::positional_options_description p;
	p.add("sql", 1);
	p.add("cpp", 1);
	p.add("h", 1);

	po::variables_map vm;
	po::store(po::command_line_parser(argc, argv).options(opts).positional(p).run(), vm);

	if (vm.count("help")) {
		std::cout << opts << std::endl;
		return 1;
	}
	po::notify(vm);

	std::vector<std::string> sqlnsparts;
	boost::algorithm::split(sqlnsparts, sqlns, boost::algorithm::is_any_of(":"), boost::algorithm::token_compress_on);
	auto r = fs::canonical(sql).lexically_relative(fs::canonical(base)).parent_path();
	if (!r.empty()) {
		std::copy(r.begin(), r.end(), std::back_inserter(sqlnsparts));
	}

	std::ifstream sqlin(sql);
	std::ofstream cppout(cpp);
	std::ofstream hout(h);

	CPPHeader::write(cppout, sql.filename().string());
	std::for_each(sqlnsparts.begin(), sqlnsparts.end(), [&cppout](const auto & nsp) {
		CPPNS::write(cppout, nsp);
	});
	CPPOpen::write(cppout, sql.stem().string());
	std::string buf;
	std::stringstream map;
	while (!std::getline(sqlin, buf).eof()) {
		if (boost::algorithm::starts_with(buf, "-- libdbpp-")) {
			connector = buf.substr(11);
		}
		else if (boost::algorithm::starts_with(buf, "-- libdbpp:")) {
			auto opt = buf.substr(11);
			auto colon = opt.find(':');
			if (colon != std::string::npos) {
				CPPConnectorOpt::write(map, opt.substr(0, colon), opt.substr(colon + 1));
			}
			else {
				CPPConnectorOptFlag::write(map, opt);
			}
		}
		else {
			cppout << buf << std::endl;
		}
	}
	CPPClose::write(cppout);
	if (!connector.empty() && !map.str().empty()) {
		CPPConnectorOpts::write(cppout, connector, map.str());
	}
	CPPFooter::write(cppout);

	HHeader::write(hout);
	std::for_each(sqlnsparts.begin(), sqlnsparts.end(), [&hout](const auto & nsp) {
		OpenNamespace::write(hout, nsp);
	});
	HDeclartion::write(hout, sql.stem().string());
	std::for_each(sqlnsparts.begin(), sqlnsparts.end(), [&hout](const auto & nsp) {
		CloseNamespace::write(hout, nsp);
	});
	HFooter::write(hout);

	return 0;
}