// file : cli/generator.cxx // author : Boris Kolpackov // copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC // license : GNU GPL v2; see accompanying LICENSE file #include // std::toupper, std::is{alpha,upper,lower} #include #include #include #include #include #include #include #include #include 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 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 (); } }