summaryrefslogtreecommitdiff
path: root/odb/generator.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2010-03-30 11:05:46 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2010-03-30 11:05:46 +0200
commitb143a4a1a028d3147b9b603e77866780b34ee828 (patch)
tree521e0d3602a08970cf477e3f139cc40f9dd01af2 /odb/generator.cxx
parentcf80396f8b6147e9048c1f3bd50b3086f754d037 (diff)
Add code generator infrastructure
Diffstat (limited to 'odb/generator.cxx')
-rw-r--r--odb/generator.cxx156
1 files changed, 156 insertions, 0 deletions
diff --git a/odb/generator.cxx b/odb/generator.cxx
new file mode 100644
index 0000000..3548802
--- /dev/null
+++ b/odb/generator.cxx
@@ -0,0 +1,156 @@
+// file : cli/generator.cxx
+// author : Boris Kolpackov <boris@codesynthesis.com>
+// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
+// license : GNU GPL v2; see accompanying LICENSE file
+
+#include <cctype> // std::toupper, std::is{alpha,upper,lower}
+#include <string>
+#include <fstream>
+#include <iostream>
+
+#include <cutl/fs/auto-remove.hxx>
+
+#include <cutl/compiler/code-stream.hxx>
+#include <cutl/compiler/cxx-indenter.hxx>
+
+#include <context.hxx>
+#include <generator.hxx>
+
+using namespace std;
+using namespace cutl;
+
+using semantics::path;
+
+namespace
+{
+ static char const cxx_header[] =
+ "// This code was generated by ODB, an object persistence compiler\n"
+ "// for C++.\n"
+ "//\n\n";
+
+ /*
+ string
+ make_guard (string const& file, context& ctx)
+ {
+ string g (file);
+
+ // Split words, e.g., "FooBar" to "Foo_Bar" and convert everything
+ // to upper case.
+ //
+ string r;
+ for (string::size_type i (0), n (g.size ()); i < n - 1; ++i)
+ {
+ char c1 (g[i]);
+ char c2 (g[i + 1]);
+
+ r += toupper (c1);
+
+ if (isalpha (c1) && isalpha (c2) && islower (c1) && isupper (c2))
+ r += "_";
+ }
+ r += std::toupper (g[g.size () - 1]);
+
+ return ctx.escape (r);
+ }
+ */
+
+ void
+ open (ifstream& ifs, string const& path)
+ {
+ ifs.open (path.c_str (), ios_base::in | ios_base::binary);
+
+ if (!ifs.is_open ())
+ {
+ cerr << path << ": error: unable to open in read mode" << endl;
+ throw generator::failed ();
+ }
+ }
+}
+
+generator::
+generator ()
+{
+}
+
+void generator::
+generate (options const& ops, semantics::unit& unit, path const& p)
+{
+ try
+ {
+ path file (p.leaf ());
+ string base (file.base ().string ());
+
+ fs::auto_removes auto_rm;
+
+ // C++ output.
+ //
+ string cxx_name (base + ops.odb_file_suffix () + ops.cxx_suffix ());
+ path cxx_path (cxx_name);
+
+ if (!ops.output_dir ().empty ())
+ {
+ path dir (ops.output_dir ());
+ cxx_path = dir / cxx_path;
+ }
+
+ //
+ //
+ ofstream cxx (cxx_path.string ().c_str ());
+
+ if (!cxx.is_open ())
+ {
+ cerr << "error: unable to open '" << cxx_path << "' in write mode"
+ << endl;
+ throw failed ();
+ }
+
+ auto_rm.add (cxx_path);
+
+ // Print headers.
+ //
+ cxx << cxx_header;
+
+ typedef compiler::ostream_filter<compiler::cxx_indenter, char> cxx_filter;
+
+ // Include settings.
+ //
+ bool br (ops.include_with_brackets ());
+ string ip (ops.include_prefix ());
+
+ if (!ip.empty () && ip[ip.size () - 1] != '/')
+ ip.append ("/");
+
+ // CXX
+ //
+ {
+ cxx_filter filt (cxx);
+ context ctx (cxx, unit, ops);
+
+ cxx << "#include " << (br ? '<' : '"') << ip << file <<
+ (br ? '>' : '"') << endl
+ << endl;
+
+ // generate_source (ctx);
+ }
+
+ auto_rm.cancel ();
+ }
+ catch (const generation_failed&)
+ {
+ // Code generation failed. Diagnostics has already been issued.
+ //
+ throw failed ();
+ }
+ catch (semantics::invalid_path const& e)
+ {
+ cerr << "error: '" << e.path () << "' is not a valid filesystem path"
+ << endl;
+ throw failed ();
+ }
+ catch (fs::error const&)
+ {
+ // Auto-removal of generated files failed. Ignore it.
+ //
+ throw failed ();
+ }
+}