aboutsummaryrefslogtreecommitdiff
path: root/odb/processor.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'odb/processor.cxx')
-rw-r--r--odb/processor.cxx273
1 files changed, 194 insertions, 79 deletions
diff --git a/odb/processor.cxx b/odb/processor.cxx
index f059d0b..f4cff89 100644
--- a/odb/processor.cxx
+++ b/odb/processor.cxx
@@ -20,6 +20,26 @@ using namespace std;
namespace
{
+ // Find name hint for this type decl.
+ //
+ static semantics::names*
+ find_hint (semantics::unit& u, tree decl)
+ {
+ semantics::names* r (0);
+
+ for (tree ot (DECL_ORIGINAL_TYPE (decl));
+ ot != 0;
+ ot = decl ? DECL_ORIGINAL_TYPE (decl) : 0)
+ {
+ if ((r = u.find_hint (ot)))
+ break;
+
+ decl = TYPE_NAME (ot);
+ }
+
+ return r;
+ }
+
// Indirect (dynamic) context values.
//
static semantics::type*
@@ -218,8 +238,8 @@ namespace
e.push_back (cxx_token (0, CPP_KEYWORD, "this"));
e.push_back (cxx_token (0, CPP_DOT));
e.push_back (cxx_token (0, CPP_NAME, n));
- e.push_back (cxx_token (0, CPP_OPEN_PAREN, n));
- e.push_back (cxx_token (0, CPP_CLOSE_PAREN, n));
+ e.push_back (cxx_token (0, CPP_OPEN_PAREN));
+ e.push_back (cxx_token (0, CPP_CLOSE_PAREN));
// See if it returns by value.
//
@@ -279,8 +299,8 @@ namespace
e.push_back (cxx_token (0, CPP_KEYWORD, "this"));
e.push_back (cxx_token (0, CPP_DOT));
e.push_back (cxx_token (0, CPP_NAME, n));
- e.push_back (cxx_token (0, CPP_OPEN_PAREN, n));
- e.push_back (cxx_token (0, CPP_CLOSE_PAREN, n));
+ e.push_back (cxx_token (0, CPP_OPEN_PAREN));
+ e.push_back (cxx_token (0, CPP_CLOSE_PAREN));
return found_best;
}
@@ -316,9 +336,9 @@ namespace
e.push_back (cxx_token (0, CPP_KEYWORD, "this"));
e.push_back (cxx_token (0, CPP_DOT));
e.push_back (cxx_token (0, CPP_NAME, n));
- e.push_back (cxx_token (0, CPP_OPEN_PAREN, n));
+ e.push_back (cxx_token (0, CPP_OPEN_PAREN));
e.push_back (cxx_token (0, CPP_QUERY));
- e.push_back (cxx_token (0, CPP_CLOSE_PAREN, n));
+ e.push_back (cxx_token (0, CPP_CLOSE_PAREN));
// Continue searching in case there is version that returns a
// non-const reference which we prefer for efficiency.
@@ -982,17 +1002,7 @@ namespace
// Find the hint.
//
- semantics::names* wh (0);
-
- for (tree ot (DECL_ORIGINAL_TYPE (decl));
- ot != 0;
- ot = decl ? DECL_ORIGINAL_TYPE (decl) : 0)
- {
- if ((wh = unit.find_hint (ot)))
- break;
-
- decl = TYPE_NAME (ot);
- }
+ semantics::names* wh (find_hint (unit, decl));
t.set ("wrapper-type", wt);
t.set ("wrapper-hint", wh);
@@ -1531,15 +1541,7 @@ namespace
// Find the hint.
//
- for (tree ot (DECL_ORIGINAL_TYPE (decl));
- ot != 0;
- ot = decl ? DECL_ORIGINAL_TYPE (decl) : 0)
- {
- if ((vh = unit.find_hint (ot)))
- break;
-
- decl = TYPE_NAME (ot);
- }
+ vh = find_hint (unit, decl);
}
catch (operation_failed const&)
{
@@ -1598,15 +1600,7 @@ namespace
// Find the hint.
//
- for (tree ot (DECL_ORIGINAL_TYPE (decl));
- ot != 0;
- ot = decl ? DECL_ORIGINAL_TYPE (decl) : 0)
- {
- if ((ih = unit.find_hint (ot)))
- break;
-
- decl = TYPE_NAME (ot);
- }
+ ih = find_hint (unit, decl);
}
catch (operation_failed const&)
{
@@ -1640,15 +1634,7 @@ namespace
// Find the hint.
//
- for (tree ot (DECL_ORIGINAL_TYPE (decl));
- ot != 0;
- ot = decl ? DECL_ORIGINAL_TYPE (decl) : 0)
- {
- if ((kh = unit.find_hint (ot)))
- break;
-
- decl = TYPE_NAME (ot);
- }
+ kh = find_hint (unit, decl);
}
catch (operation_failed const&)
{
@@ -3016,60 +3002,189 @@ namespace
tree access_; // odb::access node.
};
+
+ static void
+ check_to_from (const cxx_tokens& ex, const char* c, location_t l)
+ {
+ // Make sure we have one and only one placeholder (?).
+ //
+ bool r (false);
+
+ for (cxx_tokens::const_iterator i (ex.begin ()), e (ex.end ()); i != e;)
+ {
+ if (i->type == CPP_OPEN_PAREN)
+ {
+ if (++i != e && i->type == CPP_QUERY)
+ {
+ if (++i != e && i->type == CPP_CLOSE_PAREN)
+ {
+ if (r)
+ {
+ error (l) << "multiple '(?)' expressions in the '" << c << "' "
+ << "clause of db pragma map" << endl;
+ throw operation_failed ();
+ }
+ else
+ r = true;
+ }
+ }
+ }
+ else
+ ++i;
+ }
+
+ if (!r)
+ {
+ error (l) << "no '(?)' expression in the '" << c << "' clause "
+ << "of db pragma map" << endl;
+
+ throw operation_failed ();
+ }
+ }
}
-void
-process (options const& ops,
- features& f,
- semantics::unit& unit,
- semantics::path const&)
+static void
+process1 (semantics::unit& u)
{
- try
+ // Process custom C++ type mapping.
+ //
+
+ // Create an empty list if we don't have one. This makes the
+ // rest of the code simpler.
+ //
+ if (!u.count ("custom-cxx-types"))
+ u.set ("custom-cxx-types", custom_cxx_types ());
+
+ custom_cxx_types & cts (u.get<custom_cxx_types> ("custom-cxx-types"));
+ custom_cxx_type_map& ctm (u.set ("custom-cxx-type-map",
+ custom_cxx_type_map ()));
+
+ for (custom_cxx_types::iterator i (cts.begin ()); i != cts.end (); ++i)
{
- auto_ptr<context> ctx (create_context (cerr, unit, ops, f, 0));
+ custom_cxx_type& ct (*i);
- // Common processing.
+ // type
//
+ if (ct.type_node == 0)
{
- traversal::unit unit;
- traversal::defines unit_defines;
- typedefs unit_typedefs (true);
- traversal::namespace_ ns;
- class_ c;
-
- unit >> unit_defines >> ns;
- unit_defines >> c;
- unit >> unit_typedefs >> c;
-
- traversal::defines ns_defines;
- typedefs ns_typedefs (true);
+ error (ct.loc) << "'type' clause expected in db pragma map" << endl;
+ throw operation_failed ();
+ }
- ns >> ns_defines >> ns;
- ns_defines >> c;
- ns >> ns_typedefs >> c;
+ ct.type = dynamic_cast<semantics::type*> (
+ u.find (TYPE_MAIN_VARIANT (ct.type_node)));
+ ct.type_hint = u.find_hint (ct.type_node);
- unit.dispatch (ctx->unit);
+ // as
+ //
+ if (ct.as_node == 0)
+ {
+ error (ct.loc) << "'as' clause expected in db pragma map" << endl;
+ throw operation_failed ();
}
- // Database-specific processing.
+ ct.as = dynamic_cast<semantics::type*> (
+ u.find (TYPE_MAIN_VARIANT (ct.as_node)));
+ ct.as_hint = u.find_hint (ct.as_node);
+
+ // to
//
- switch (ops.database ()[0])
{
- case database::common:
+ cxx_tokens& e (ct.to);
+
+ if (e.empty ())
{
- break;
+ e.push_back (cxx_token (0, CPP_OPEN_PAREN));
+ e.push_back (cxx_token (0, CPP_QUERY));
+ e.push_back (cxx_token (0, CPP_CLOSE_PAREN));
}
- case database::mssql:
- case database::mysql:
- case database::oracle:
- case database::pgsql:
- case database::sqlite:
+ else
+ check_to_from (e, "to", ct.loc);
+ }
+
+ // to
+ //
+ {
+ cxx_tokens& e (ct.from);
+
+ if (e.empty ())
{
- relational::process ();
- break;
+ e.push_back (cxx_token (0, CPP_OPEN_PAREN));
+ e.push_back (cxx_token (0, CPP_QUERY));
+ e.push_back (cxx_token (0, CPP_CLOSE_PAREN));
}
+ else
+ check_to_from (e, "from", ct.loc);
+ }
+
+ // Enter into the map.
+ //
+ ctm[ct.type] = &ct;
+ }
+}
+
+static void
+process2 (options const& ops, features& f, semantics::unit& u)
+{
+ auto_ptr<context> ctx (create_context (cerr, u, ops, f, 0));
+
+ // Common processing.
+ //
+ {
+ traversal::unit unit;
+ traversal::defines unit_defines;
+ typedefs unit_typedefs (true);
+ traversal::namespace_ ns;
+ class_ c;
+
+ unit >> unit_defines >> ns;
+ unit_defines >> c;
+ unit >> unit_typedefs >> c;
+
+ traversal::defines ns_defines;
+ typedefs ns_typedefs (true);
+
+ ns >> ns_defines >> ns;
+ ns_defines >> c;
+ ns >> ns_typedefs >> c;
+
+ unit.dispatch (ctx->unit);
+ }
+
+ // Database-specific processing.
+ //
+ switch (ops.database ()[0])
+ {
+ case database::common:
+ {
+ break;
+ }
+ case database::mssql:
+ case database::mysql:
+ case database::oracle:
+ case database::pgsql:
+ case database::sqlite:
+ {
+ relational::process ();
+ break;
}
}
+}
+
+void
+process (options const& ops,
+ features& f,
+ semantics::unit& u,
+ semantics::path const&,
+ unsigned short pass)
+{
+ try
+ {
+ if (pass == 1)
+ process1 (u);
+ else if (pass == 2)
+ process2 (ops, f, u);
+ }
catch (operation_failed const&)
{
// Processing failed. Diagnostics has already been issued.