summaryrefslogtreecommitdiff
path: root/odb/pragma.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'odb/pragma.cxx')
-rw-r--r--odb/pragma.cxx4444
1 files changed, 0 insertions, 4444 deletions
diff --git a/odb/pragma.cxx b/odb/pragma.cxx
deleted file mode 100644
index bd1d848..0000000
--- a/odb/pragma.cxx
+++ /dev/null
@@ -1,4444 +0,0 @@
-// file : odb/pragma.cxx
-// license : GNU GPL v3; see accompanying LICENSE file
-
-#include <odb/gcc.hxx>
-
-#include <cctype> // std::isalnum
-#include <limits>
-#include <vector>
-#include <sstream>
-
-#include <odb/diagnostics.hxx>
-#include <odb/lookup.hxx>
-#include <odb/pragma.hxx>
-#include <odb/cxx-token.hxx>
-#include <odb/cxx-lexer.hxx>
-
-#include <odb/context.hxx>
-#include <odb/relational/context.hxx>
-
-using namespace std;
-using namespace cutl;
-
-using container::any;
-
-virt_declarations virt_declarations_;
-loc_pragmas loc_pragmas_;
-decl_pragmas decl_pragmas_;
-ns_loc_pragmas ns_loc_pragmas_;
-
-database pragma_db_;
-multi_database pragma_multi_;
-
-template <typename X>
-void
-accumulate (compiler::context& ctx, string const& k, any const& v, location_t)
-{
- // Empty values are used to indicate that this pragma must be ignored.
- //
- if (v.empty ())
- return;
-
- typedef vector<X> container;
-
- container& c (ctx.count (k)
- ? ctx.get<container> (k)
- : ctx.set (k, container ()));
-
- c.push_back (v.value<X> ());
-}
-
-// Parse a qualified string. It can be in one of the following formats:
-//
-// "foo.bar.baz" (can have empty leading component, e.g., ".bar.baz")
-// "foo"."bar"."baz" (can have empty leading component, e.g., ""."bar"."baz")
-// ."foo.bar" (used to specify unqualifed names with periods)
-//
-// Empty leading components means fully qualified (similar to ::foo in C++).
-//
-static bool
-parse_qname (cxx_lexer& l,
- cpp_ttype& tt,
- string& tl,
- tree& tn,
- string const& p, // Pragma name for diagnostic.
- qname& name,
- bool* expr = 0, // If specified, detect an expression
- string* expr_str = 0) // and store it here.
-{
- assert (tt == CPP_STRING || tt == CPP_DOT);
-
- // Handle the special case of unqualified name which can contain periods.
- //
- if (tt == CPP_DOT)
- {
- tt = l.next (tl, &tn);
-
- if (tt != CPP_STRING)
- {
- error (l) << "name expected after '.' in db pragma " << p << endl;
- return false;
- }
-
- name = tl;
- tt = l.next (tl, &tn);
- return true;
- }
-
- name.clear ();
- string str (tl);
-
- // See what comes after the string.
- //
- tt = l.next (tl, &tn);
-
- if (tt == CPP_DOT)
- {
- name.append (str);
-
- for (; tt == CPP_DOT; tt = l.next (tl, &tn))
- {
- tt = l.next (tl, &tn);
-
- if (tt != CPP_STRING)
- {
- error (l) << "name expected after '.' in db pragma " << p << endl;
- return false;
- }
-
- name.append (tl);
- }
-
- return true;
- }
-
- if (expr != 0 && tt == CPP_PLUS)
- {
- *expr = true;
- *expr_str = str;
- return true;
- }
-
- // Scan the string looking for '.' as well as for non-identifier
- // characters if we need to detect expressions.
- //
- string::size_type prev (string::npos);
-
- for (size_t i (0); i < str.size (); ++i)
- {
- char c (str[i]);
-
- if (c == '.')
- {
- if (prev == string::npos)
- name.append (string (str, 0, i));
- else
- name.append (string (str, prev + 1, i - prev - 1));
-
- prev = i;
- }
- else if (expr != 0 && !(isalnum (c) || c == '_'))
- {
- *expr = true;
- *expr_str = str;
- return true;
- }
- }
-
- if (prev == string::npos)
- name.append (str);
- else
- name.append (string (str, prev + 1, string::npos));
-
- return true;
-}
-
-static bool
-parse_expression (cxx_lexer& l,
- cpp_ttype& tt,
- string& tl,
- tree& tn,
- cxx_tokens& ts,
- string const& prag)
-{
- // Keep reading tokens until we see a mis-matching ')' or ',' while
- // keeping track of the '()' and '{}' balance.
- //
- size_t p_balance (0), b_balance (0);
-
- for (; tt != CPP_EOF; tt = l.next (tl, &tn))
- {
- bool done (false);
- cxx_token ct (l.location (), tt);
-
- switch (tt)
- {
- case CPP_OPEN_BRACE:
- {
- b_balance++;
- break;
- }
- case CPP_CLOSE_BRACE:
- {
- b_balance--;
- break;
- }
- case CPP_OPEN_PAREN:
- {
- p_balance++;
- break;
- }
- case CPP_CLOSE_PAREN:
- {
- if (p_balance == 0 && b_balance == 0)
- done = true;
- else
- p_balance--;
- break;
- }
- case CPP_COMMA:
- {
- if (p_balance == 0 && b_balance == 0)
- done = true;
- else
- break;
- }
- case CPP_STRING:
- {
- ct.literal = tl;
- break;
- }
- case CPP_NAME:
- //case CPP_KEYWORD: see default:
- {
- ct.literal = tl;
- break;
- }
- case CPP_NUMBER:
- {
- switch (TREE_CODE (tn))
- {
- case INTEGER_CST:
- {
- tree type (TREE_TYPE (tn));
- unsigned long long v (integer_value (tn));
-
- ostringstream os;
- os << v;
-
- if (type == long_long_integer_type_node)
- os << "LL";
- else if (type == long_long_unsigned_type_node)
- os << "ULL";
- else if (type == long_integer_type_node)
- os << "L";
- else if (type == long_unsigned_type_node)
- os << "UL";
- else if (
- TYPE_UNSIGNED (type) &&
- TYPE_PRECISION (type) >= TYPE_PRECISION (integer_type_node))
- os << "U";
-
- ct.literal = os.str ();
- break;
- }
- case REAL_CST:
- {
- tree type (TREE_TYPE (tn));
- REAL_VALUE_TYPE val (TREE_REAL_CST (tn));
-
- // This is the best we can do. val cannot be INF or NaN.
- //
- char tmp[256];
- real_to_decimal (tmp, &val, sizeof (tmp), 0, true);
- istringstream is (tmp);
- ostringstream os;
-
- if (type == float_type_node)
- {
- float f;
- is >> f;
- os << f << 'F';
- }
- else
- {
- double d;
- is >> d;
- os << d;
- }
-
- ct.literal = os.str ();
- break;
- }
- default:
- {
- error (l) << "unexpected numeric constant in db pragma "
- << prag << endl;
- return false;
- }
- }
-
- break;
- }
- default:
- {
- // CPP_KEYWORD is not in the cpp_ttype enumeration.
- //
- if (tt == CPP_KEYWORD)
- ct.literal = tl;
-
- break;
- }
- }
-
- if (done)
- break;
-
- // We don't store the tree node in ct since we converted numbers to
- // string literals.
- //
- ts.push_back (ct);
- }
-
- return true;
-}
-
-static string
-parse_scoped_name (cxx_lexer& l,
- cpp_ttype& tt,
- string& tl,
- tree& tn,
- string const& prag)
-{
- try
- {
- return lookup::parse_scoped_name (l, tt, tl, tn);
- }
- catch (lookup::invalid_name const&)
- {
- error (l) << "invalid name in db pragma " << prag << endl;
- return "";
- }
-}
-
-static tree
-resolve_scoped_name (cxx_lexer& l,
- cpp_ttype& tt,
- string& tl,
- tree& tn,
- tree start_scope,
- string& name,
- bool is_type,
- string const& prag,
- bool trailing_scope = false,
- cpp_ttype* prev_tt = 0)
-{
- try
- {
- cpp_ttype ptt; // Not used.
- tree r (
- lookup::resolve_scoped_name (
- l, tt, tl, tn, ptt, start_scope, name, is_type, trailing_scope));
-
- if (prev_tt != 0)
- *prev_tt = ptt;
-
- return r;
- }
- catch (lookup::invalid_name const&)
- {
- error (l) << "invalid name in db pragma " << prag << endl;
- return 0;
- }
- catch (lookup::unable_to_resolve const& e)
- {
- if (e.last ())
- error (l) << "unable to resolve " << (is_type ? "type " : "") << "name "
- << "'" << e.name () << "' in db pragma " << prag << endl;
- else
- error (l) << "unable to resolve name '" << e.name () << "' in db pragma "
- << prag << endl;
-
- return 0;
- }
-}
-
-// Resolve a data member in the specified scope taking into account virtual
-// member declarations.
-//
-declaration
-resolve_data_member (tree scope,
- const cxx_tokens& name,
- string& decl_name, // Note: appended to.
- string const& prag)
-{
- declaration decl;
-
- if (name.size () == 1 && name.back ().type == CPP_NAME)
- {
- virt_declarations::iterator i (virt_declarations_.find (scope));
-
- if (i != virt_declarations_.end ())
- {
- string const& n (name.back ().literal);
-
- virt_declaration_set::const_iterator j (i->second.find (n, FIELD_DECL));
-
- if (j != i->second.end ())
- {
- decl = declaration (*j);
- decl_name += n;
- }
- }
- }
-
- if (!decl)
- {
- cxx_tokens_lexer l;
- l.start (name);
-
- tree tn;
- string tl;
- cpp_ttype tt (l.next (tl));
-
- tree d (resolve_scoped_name (
- l, tt, tl, tn, scope, decl_name, false, prag));
-
- if (d == 0)
- return decl; // Diagnostics has already been issued.
-
- decl = declaration (d);
- }
-
- return decl;
-}
-
-static bool
-check_spec_decl_type (declaration const& d,
- string const& name,
- string const& p,
- location_t l)
-{
- gcc_tree_code_type tc (d.tree_code ());
- bool type (TREE_CODE_CLASS (tc) == tcc_type);
-
- if (p == "no_id")
- {
- // No_id can be used on objects only.
- //
- if (tc != RECORD_TYPE)
- {
- error (l) << "name '" << name << "' in db pragma " << p << " does "
- << "not refer to a class" << endl;
- return false;
- }
- }
- else if (p == "id" ||
- p == "auto" ||
- p == "column" ||
- p == "inverse" ||
- p == "on_delete" ||
- p == "points_to" ||
- p == "section" ||
- p == "load" ||
- p == "update" ||
- p == "version" ||
- p == "index" ||
- p == "unique" ||
- p == "get" ||
- p == "set" ||
- p == "access")
- {
- if (tc != FIELD_DECL)
- {
- error (l) << "name '" << name << "' in db pragma " << p << " does "
- << "not refer to a data member" << endl;
- return false;
- }
- }
- else if (p == "transient")
- {
- // Transient can be used for both data members and classes (object,
- // view, or composite value).
- //
- if (tc != FIELD_DECL && tc != RECORD_TYPE)
- {
- error (l) << "name '" << name << "' in db pragma " << p << " does "
- << "not refer to a data member or class" << endl;
- return false;
- }
- }
- else if (p == "added")
- {
- // Added can be used for data members only.
- //
- if (tc != FIELD_DECL)
- {
- error (l) << "name '" << name << "' in db pragma " << p << " does "
- << "not refer to a data member" << endl;
- return false;
- }
- }
- else if (p == "deleted")
- {
- // Deleted can be used for both data members and classes (object,
- // view of composite value).
- //
- if (tc != FIELD_DECL && tc != RECORD_TYPE)
- {
- error (l) << "name '" << name << "' in db pragma " << p << " does "
- << "not refer to a data member or class" << endl;
- return false;
- }
- }
- else if (p == "readonly")
- {
- // Readonly can be used for both data members and classes (object or
- // composite value).
- //
- if (tc != FIELD_DECL && tc != RECORD_TYPE)
- {
- error (l) << "name '" << name << "' in db pragma " << p << " does "
- << "not refer to a data member or class" << endl;
- return false;
- }
- }
- else if (p == "abstract" ||
- p == "callback" ||
- p == "query" ||
- p == "object" ||
- p == "optimistic" ||
- p == "polymorphic" ||
- p == "definition" ||
- p == "sectionable" ||
- p == "bulk")
- {
- if (tc != RECORD_TYPE)
- {
- error (l) << "name '" << name << "' in db pragma " << p << " does "
- << "not refer to a class" << endl;
- return false;
- }
- }
- else if (p == "pointer")
- {
- // Table can be used for namespaces and classes (object or view).
- //
- if (tc != NAMESPACE_DECL && tc != RECORD_TYPE)
- {
- error (l) << "name '" << name << "' in db pragma " << p << " does "
- << "not refer to a class" << endl;
- return false;
- }
- }
- else if (p == "table")
- {
- // Table can be used for namespaces, members (container), and types
- // (container, object, or view).
- //
- if (tc != NAMESPACE_DECL && tc != FIELD_DECL && !type)
- {
- error (l) << "name '" << name << "' in db pragma " << p << " does "
- << "not refer to a namespace, type, or data member" << endl;
- return false;
- }
- }
- else if (p == "session")
- {
- // Session can be used only for namespaces and objects.
- //
- if (tc != NAMESPACE_DECL && tc != RECORD_TYPE)
- {
- error (l) << "name '" << name << "' in db pragma " << p << " does "
- << "not refer to a namespace or class" << endl;
- return false;
- }
- }
- else if (p == "schema")
- {
- // For now schema can be used only for namespaces and objects.
- //
- if (tc != NAMESPACE_DECL && tc != RECORD_TYPE)
- {
- error (l) << "name '" << name << "' in db pragma " << p << " does "
- << "not refer to a namespace or class" << endl;
- return false;
- }
- }
- else if (p == "type" ||
- p == "id_type" ||
- p == "value_type" ||
- p == "index_type" ||
- p == "key_type")
- {
- // Type can be used for both members and types.
- //
- if (tc != FIELD_DECL && !type)
- {
- error (l) << "name '" << name << "' in db pragma " << p << " does "
- << "not refer to a type or data member" << endl;
- return false;
- }
- }
- else if (p == "default")
- {
- // Default can be used for both members and types.
- //
- if (tc != FIELD_DECL && !type)
- {
- error (l) << "name '" << name << "' in db pragma " << p << " does "
- << "not refer to a type or data member" << endl;
- return false;
- }
- }
- else if (p == "value_column" ||
- p == "index_column" ||
- p == "key_column" ||
- p == "id_column")
- {
- // Container columns can be used for both members (container) and
- // types (container).
- //
- if (tc != FIELD_DECL && !type)
- {
- error (l) << "name '" << name << "' in db pragma " << p << " does "
- << "not refer to a type or data member" << endl;
- return false;
- }
- }
- else if (p == "options" ||
- p == "value_options" ||
- p == "index_options" ||
- p == "key_options" ||
- p == "id_options")
- {
- // Options can be used for both members and types.
- //
- if (tc != FIELD_DECL && !type)
- {
- error (l) << "name '" << name << "' in db pragma " << p << " does "
- << "not refer to a type or data member" << endl;
- return false;
- }
- }
- else if (p == "null" ||
- p == "not_null" ||
- p == "key_null" ||
- p == "key_not_null" ||
- p == "value_null" ||
- p == "value_not_null")
- {
- // Null pragmas can be used for both members and types (values,
- // containers, and pointers).
- //
- if (tc != FIELD_DECL && !type)
- {
- error (l) << "name '" << name << "' in db pragma " << p << " does "
- << "not refer to a type or data member" << endl;
- return false;
- }
- }
- else if (p == "unordered")
- {
- // Unordered can be used for both members (container) and
- // types (container).
- //
- if (tc != FIELD_DECL && !type)
- {
- error (l) << "name '" << name << "' in db pragma " << p << " does "
- << "not refer to a type or data member" << endl;
- return false;
- }
- }
- else if (p == "virtual")
- {
- // Virtual is specified for a member.
- //
- if (tc != FIELD_DECL)
- {
- error (l) << "name '" << name << "' in db pragma " << p << " does "
- << "not refer to a data member" << endl;
- return false;
- }
- }
- else if (p == "simple" ||
- p == "container")
- {
- // Apply to both members and types.
- //
- if (tc != FIELD_DECL && !type)
- {
- error (l) << "name '" << name << "' in db pragma " << p << " does "
- << "not refer to a type or data member" << endl;
- return false;
- }
- }
- else
- {
- error (l) << "unknown db pragma " << p << endl;
- return false;
- }
-
- return true;
-}
-
-static void
-add_pragma (pragma const& prag, declaration const& decl, bool ns)
-{
- if (decl)
- decl_pragmas_[decl].insert (prag);
- else
- {
- tree scope (current_scope ());
-
- if (!ns)
- {
- if (!CLASS_TYPE_P (scope))
- scope = global_namespace;
-
- loc_pragmas_[scope].push_back (prag);
- }
- else
- ns_loc_pragmas_.push_back (ns_loc_pragma (scope, prag));
- }
-}
-
-static void
-handle_pragma (cxx_lexer& l,
- string db,
- string p,
- string const& qualifier,
- any& qualifier_value,
- declaration const& decl,
- string const& decl_name,
- bool ns) // True if this is a position namespace pragma.
-{
- cpp_ttype tt;
- string tl;
- tree tn;
-
- // See if there is a database prefix. The db argument may already
- // contain it.
- //
- if (db.empty () &&
- (p == "mysql" ||
- p == "sqlite" ||
- p == "pgsql" ||
- p == "oracle" ||
- p == "mssql"))
- {
- tt = l.next (tl);
-
- if (tt != CPP_COLON)
- {
- error (l) << "':' expected after database prefix " << p << endl;
- return;
- }
-
- // Specifier prefix.
- //
- db = p;
- tt = l.next (p);
-
- if (tt != CPP_NAME && tt != CPP_KEYWORD)
- {
- error (l) << "expected specifier after databas prefix " << db << endl;
- return;
- }
- }
-
- string name (p); // Pragma name.
- any val; // Pragma value.
- pragma::add_func adder (0); // Custom context adder.
- location_t loc (l.location ()); // Pragma location.
-
- if (qualifier == "model")
- {
- // version(unsigned long long base,
- // unsigned long long current,
- // open|closed)
- //
-
- // Make sure we've got the correct declaration type.
- //
- assert (decl == global_namespace);
-
- if (p == "version")
- {
- if (l.next (tl, &tn) != CPP_OPEN_PAREN)
- {
- error (l) << "'(' expected after db pragma " << p << endl;
- return;
- }
-
- model_version v;
-
- // base
- //
- if (l.next (tl, &tn) != CPP_NUMBER || TREE_CODE (tn) != INTEGER_CST)
- {
- error (l) << "unsigned integer expected as base version" << endl;
- return;
- }
-
- v.base = integer_value (tn);
-
- if (v.base == 0)
- {
- error (l) << "base version cannot be zero" << endl;
- return;
- }
-
- // current
- //
- if (l.next (tl, &tn) != CPP_COMMA)
- {
- error (l) << "current version expected after base version" << endl;
- return;
- }
-
- if (l.next (tl, &tn) != CPP_NUMBER || TREE_CODE (tn) != INTEGER_CST)
- {
- error (l) << "unsigned integer expected as current version" << endl;
- return;
- }
-
- v.current = integer_value (tn);
-
- if (v.current == 0)
- {
- error (l) << "current version cannot be zero" << endl;
- return;
- }
-
- if (v.base > v.current)
- {
- error (l) << "current version should be greater than or equal to " <<
- "base version" << endl;
- return;
- }
-
- // open|closed
- //
- tt = l.next (tl, &tn);
- if (tt == CPP_COMMA)
- {
- if (l.next (tl, &tn) != CPP_NAME || (tl != "open" && tl != "closed"))
- {
- error (l) << "open or closed expected after current version" << endl;
- return;
- }
-
- v.open = (tl == "open");
- tt = l.next (tl, &tn);
- }
- else
- v.open = true;
-
- if (tt != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma " << p << endl;
- return;
- }
-
- name = "model-version";
- val = v;
- tt = l.next (tl, &tn);
- }
- else
- {
- error (l) << "unknown db pragma " << p << endl;
- return;
- }
- }
- else if (qualifier == "map")
- {
- // type("<regex>") | type(<name>)
- // as("<subst>") | as(<name>)
- // to("<subst>") | to(<expr>)
- // from("<subst>") | from(<expr>)
- //
-
- if (p != "type" &&
- p != "as" &&
- p != "to" &&
- p != "from")
- {
- error (l) << "unknown db pragma " << p << endl;
- return;
- }
-
- // Make sure we've got the correct declaration type.
- //
- assert (decl == global_namespace);
-
- if (l.next (tl, &tn) != CPP_OPEN_PAREN)
- {
- error (l) << "'(' expected after db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
-
- if (qualifier_value.type_info () == typeid (custom_cxx_type))
- {
- // C++ type mapping.
- //
- custom_cxx_type& ct (qualifier_value.value<custom_cxx_type> ());
-
- if (p == "type" || p == "as")
- {
- // Can be built-in type (e.g., bool).
- //
- if (tt == CPP_NAME || tt == CPP_KEYWORD || tt == CPP_SCOPE)
- {
- string name;
- tree decl (
- resolve_scoped_name (
- l, tt, tl, tn, current_scope (), name, true, p));
-
- if (decl == 0)
- return; // Diagnostics has already been issued.
-
- if (TREE_CODE (decl) != TYPE_DECL)
- {
- error (loc) << "name '" << name << "' in db pragma "
- << p << " does not refer to a type" << endl;
- return;
- }
-
- (p == "type" ? ct.type_node : ct.as_node) = TREE_TYPE (decl);
- (p == "type" ? ct.type_name : ct.as_name) = name;
- }
- else
- {
- error (l) << "type name expected in db pragma " << p << endl;
- return;
- }
- }
- else if (p == "to" || p == "from")
- {
- if (tt != CPP_CLOSE_PAREN) // Empty expression is ok.
- {
- if (!parse_expression (
- l, tt, tl, tn, (p == "to" ? ct.to : ct.from), p))
- return; // Diagnostics has already been issued.
- }
- }
- }
- else
- {
- using relational::custom_db_type;
-
- // Database type mapping.
- //
- custom_db_type& ct (qualifier_value.value<custom_db_type> ());
-
- if (p == "type")
- {
- if (tt != CPP_STRING)
- {
- error (l) << "type name regex expected in db pragma " << p << endl;
- return;
- }
-
- try
- {
- // Make it case-insensitive.
- //
- ct.type.assign (tl, true);
- }
- catch (regex_format const& e)
- {
- error (l) << "invalid regex: '" << e.regex () << "' in db pragma "
- << p << ": " << e.description () << endl;
- return;
- }
- }
- else if (p == "as")
- {
- if (tt != CPP_STRING)
- {
- error (l) << "type name expected in db pragma " << p << endl;
- return;
- }
-
- ct.as = tl;
- }
- else if (p == "to")
- {
- if (tt != CPP_STRING)
- {
- error (l) << "expression expected in db pragma " << p << endl;
- return;
- }
-
- ct.to = tl;
- }
- else if (p == "from")
- {
- if (tt != CPP_STRING)
- {
- error (l) << "expression expected in db pragma " << p << endl;
- return;
- }
-
- ct.from = tl;
- }
-
- tt = l.next (tl, &tn);
- }
-
- if (tt != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma " << p << endl;
- return;
- }
-
- name.clear (); // We don't need to add anything for this pragma.
- tt = l.next (tl, &tn);
- }
- else if (qualifier == "index")
- {
- // unique
- // type("<type>")
- // method("<method>")
- // options("<options>")
- // member(<name>[, "<options>"])
- // members(<name>[, <name>...])
- //
-
- if (p != "unique" &&
- p != "type" &&
- p != "method" &&
- p != "options" &&
- p != "member" &&
- p != "members")
- {
- error (l) << "unknown db pragma " << p << endl;
- return;
- }
-
- using relational::index;
- index& in (qualifier_value.value<index> ());
-
- if (p == "unique")
- in.type = "UNIQUE";
- else
- {
- if (l.next (tl, &tn) != CPP_OPEN_PAREN)
- {
- error (l) << "'(' expected after db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
-
- if (p == "type")
- {
- if (tt != CPP_STRING)
- {
- error (l) << "index type expected in db pragma " << p << endl;
- return;
- }
-
- in.type = tl;
- tt = l.next (tl, &tn);
- }
- else if (p == "method")
- {
- if (tt != CPP_STRING)
- {
- error (l) << "index method expected in db pragma " << p << endl;
- return;
- }
-
- in.method = tl;
- tt = l.next (tl, &tn);
- }
- else if (p == "options")
- {
- if (tt != CPP_STRING)
- {
- error (l) << "index options expected in db pragma " << p << endl;
- return;
- }
-
- in.options = tl;
- tt = l.next (tl, &tn);
- }
- else if (p == "member")
- {
- if (tt != CPP_NAME)
- {
- error (l) << "data member name expected in db pragma " << p << endl;
- return;
- }
-
- index::member m;
- m.loc = loc;
- m.name = tl;
-
- tt = l.next (tl, &tn);
-
- // Parse nested members if any.
- //
- for (; tt == CPP_DOT; tt = l.next (tl, &tn))
- {
- if (l.next (tl, &tn) != CPP_NAME)
- {
- error (l) << "name expected after '.' in db pragma " << p << endl;
- return;
- }
-
- m.name += '.';
- m.name += tl;
- }
-
- // Parse member options, if any.
- //
- if (tt == CPP_COMMA)
- {
- if (l.next (tl, &tn) != CPP_STRING)
- {
- error (l) << "index member options expected in db pragma " << p
- << endl;
- return;
- }
-
- m.options = tl;
- tt = l.next (tl, &tn);
- }
-
- in.members.push_back (m);
- }
- else if (p == "members")
- {
- for (;;)
- {
- if (tt != CPP_NAME)
- {
- error (l) << "data member name expected in db pragma " << p
- << endl;
- return;
- }
-
- index::member m;
- m.loc = l.location ();
- m.name = tl;
-
- tt = l.next (tl, &tn);
-
- // Parse nested members if any.
- //
- for (; tt == CPP_DOT; tt = l.next (tl, &tn))
- {
- if (l.next (tl, &tn) != CPP_NAME)
- {
- error (l) << "name expected after '.' in db pragma " << p
- << endl;
- return;
- }
-
- m.name += '.';
- m.name += tl;
- }
-
- in.members.push_back (m);
-
- if (tt == CPP_COMMA)
- tt = l.next (tl, &tn);
- else
- break;
- }
- }
-
- if (tt != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma " << p << endl;
- return;
- }
- }
-
- name.clear (); // We don't need to add anything for this pragma.
- tt = l.next (tl, &tn);
- }
- else if (p == "index" ||
- p == "unique")
- {
- // index
- // unique
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- tt = l.next (tl, &tn);
- }
- else if (p == "get" ||
- p == "set" ||
- p == "access")
- {
- // get(name|expr)
- // set(name|expr)
- // access(name|expr)
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- if (l.next (tl, &tn) != CPP_OPEN_PAREN)
- {
- error (l) << "'(' expected after db pragma " << p << endl;
- return;
- }
-
- member_access ma (loc, p == "set" ? "modifier" : "accessor", false);
-
- tt = l.next (tl, &tn);
- if (tt != CPP_CLOSE_PAREN) // Empty expression are ok.
- {
- if (!parse_expression (l, tt, tl, tn, ma.expr, p))
- return; // Diagnostics has already been issued.
-
- if (tt != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma " << p << endl;
- return;
- }
- }
-
- val = ma;
-
- // Convert access to the get/set pair.
- //
- if (p == "access")
- {
- if (db.empty () || db == pragma_db_.string ())
- add_pragma (
- pragma (p, "get", val, loc, &check_spec_decl_type, 0), decl, ns);
-
- ma.kind = "modifier";
- val = ma;
- name = "set";
- }
-
- tt = l.next (tl, &tn);
- }
- else if (p == "table")
- {
- // table (<name>)
- // table (<name> [= "<alias>"] [type] [: "<cond>"] (view only)
- //
- // <name> := "name" | "name.name" | "name"."name"
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- if (l.next (tl, &tn) != CPP_OPEN_PAREN)
- {
- error (l) << "'(' expected after db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
-
- if (tt != CPP_STRING && tt != CPP_DOT)
- {
- error (l) << "table name expected in db pragma " << p << endl;
- return;
- }
-
- // The table specifier is used for both objects and views. In case
- // of an object, the context values is just a string. In case of a
- // view, the context value is a view_object entry. The problem is
- // that at this stage we don't know whether we are dealing with an
- // object or a view. To resolve this in a somewhat hackish way, we
- // are going to create both a string and a view_object entry.
- //
- view_object vo;
- vo.kind = view_object::table;
-
- if (!parse_qname (l, tt, tl, tn, p, vo.tbl_name))
- return; // Diagnostics has already been issued.
-
- if (tt == CPP_EQ)
- {
- // We have an alias.
- //
- if (l.next (tl, &tn) != CPP_STRING)
- {
- error (l) << "table alias expected after '=' in db pragma " << p
- << endl;
- return;
- }
-
- vo.alias = tl;
- tt = l.next (tl, &tn);
- }
-
- if (tt == CPP_NAME)
- {
- // We have a JOIN type.
- //
- if (tl == "left")
- vo.join = view_object::left;
- else if (tl == "right")
- vo.join = view_object::right;
- else if (tl == "full")
- vo.join = view_object::full;
- else if (tl == "inner")
- vo.join = view_object::inner;
- else if (tl == "cross")
- vo.join = view_object::cross;
- else
- {
- error (l) << "unknown join type '" << tl << "'" << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
- }
- else
- vo.join = view_object::left;
-
- if (tt == CPP_COLON)
- {
- // We have a condition.
- //
- if (vo.join == view_object::cross)
- {
- error (l)
- << "no join condition can be specified for a cross join" << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
-
- if (!parse_expression (l, tt, tl, tn, vo.cond, p))
- return; // Diagnostics has already been issued.
-
- if (vo.cond.empty ())
- {
- error (l) << "join condition expected after ':' in db pragma " << p
- << endl;
- return;
- }
- }
-
- if (tt != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma " << p << endl;
- return;
- }
-
- // Add the "table" pragma.
- //
- if (vo.alias.empty () && vo.cond.empty ())
- {
- if (db.empty () || db == pragma_db_.string ())
- {
- add_pragma (
- pragma (p, name, vo.tbl_name, loc, &check_spec_decl_type, 0),
- decl,
- ns);
- }
- }
-
- vo.scope = current_scope ();
- vo.loc = loc;
- val = vo;
- name = "objects";
- adder = &accumulate<view_object>;
-
- tt = l.next (tl, &tn);
- }
- else if (p == "session")
- {
- // session
- // session (true|false)
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- tt = l.next (tl, &tn);
-
- if (tt == CPP_OPEN_PAREN)
- {
- tt = l.next (tl, &tn);
-
- if (tt != CPP_KEYWORD || (tl != "true" && tl != "false"))
- {
- error (l) << "true or false expected in db pragma " << p << endl;
- return;
- }
-
- val = (tl == "true");
-
- tt = l.next (tl, &tn);
- if (tt != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
- }
- }
- else if (p == "schema")
- {
- // schema (<name>)
- //
- // <name> := "name" | "name.name" | "name"."name"
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- if (l.next (tl, &tn) != CPP_OPEN_PAREN)
- {
- error (l) << "'(' expected after db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
-
- if (tt != CPP_STRING && tt != CPP_DOT)
- {
- error (l) << "table name expected in db pragma " << p << endl;
- return;
- }
-
- qname s;
- if (!parse_qname (l, tt, tl, tn, p, s))
- return; // Diagnostics has already been issued.
-
- if (tt != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma " << p << endl;
- return;
- }
-
- val = s;
- tt = l.next (tl, &tn);
- }
- else if (p == "pointer")
- {
- // pointer (qname)
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- if (l.next (tl, &tn) != CPP_OPEN_PAREN)
- {
- error (l) << "'(' expected after db pragma " << p << endl;
- return;
- }
-
- class_pointer cp;
- size_t pb (0);
- bool punc (false);
-
- for (tt = l.next (tl, &tn);
- tt != CPP_EOF && (tt != CPP_CLOSE_PAREN || pb != 0);
- tt = l.next (tl, &tn))
- {
- if (punc && tt > CPP_LAST_PUNCTUATOR)
- cp.name += ' ';
-
- punc = false;
-
- if (tt == CPP_OPEN_PAREN)
- pb++;
- else if (tt == CPP_CLOSE_PAREN)
- pb--;
-
- // @@ Need to handle literals, at least integer.
- //
- switch (tt)
- {
- case CPP_LESS:
- {
- cp.name += "< ";
- break;
- }
- case CPP_GREATER:
- {
- cp.name += " >";
- break;
- }
- case CPP_COMMA:
- {
- cp.name += ", ";
- break;
- }
- case CPP_NAME:
- // case CPP_KEYWORD: // see default:
- {
- cp.name += tl;
- punc = true;
- break;
- }
- default:
- {
- if (tt == CPP_KEYWORD)
- {
- cp.name += tl;
- punc = true;
- }
- else if (tt <= CPP_LAST_PUNCTUATOR)
- cp.name += cxx_lexer::token_spelling[tt];
- else
- {
- error (l) << "unexpected token '" << cxx_lexer::token_spelling[tt]
- << "' in db pragma " << p << endl;
- return;
- }
- break;
- }
- }
- }
-
- if (tt != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma " << p << endl;
- return;
- }
-
- if (cp.name.empty ())
- {
- error (l) << "expected pointer name in db pragma " << p << endl;
- return;
- }
-
- cp.scope = current_scope ();
- cp.loc = loc;
- val = cp;
-
- tt = l.next (tl, &tn);
- }
- else if (p == "abstract")
- {
- // abstract
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- tt = l.next (tl, &tn);
- }
- else if (p == "optimistic")
- {
- // optimistic
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- tt = l.next (tl, &tn);
- }
- else if (p == "polymorphic")
- {
- // polymorphic
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- tt = l.next (tl, &tn);
- }
- else if (p == "definition")
- {
- // definition
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- val = l.location ();
- tt = l.next (tl, &tn);
- }
- else if (p == "sectionable")
- {
- // sectionable
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- tt = l.next (tl, &tn);
- }
- else if (p == "callback")
- {
- // callback (name)
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- if (l.next (tl, &tn) != CPP_OPEN_PAREN)
- {
- error (l) << "'(' expected after db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
-
- if (tt != CPP_NAME)
- {
- error (l) << "member function name expected in db pragma " << p << endl;
- return;
- }
-
- val = tl;
-
- if (l.next (tl, &tn) != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
- }
- else if (p == "bulk")
- {
- // bulk (batch-size)
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- if (l.next (tl, &tn) != CPP_OPEN_PAREN)
- {
- error (l) << "'(' expected after db pragma " << p << endl;
- return;
- }
-
- // base
- //
- if (l.next (tl, &tn) != CPP_NUMBER || TREE_CODE (tn) != INTEGER_CST)
- {
- error (l) << "unsigned integer expected as batch size" << endl;
- return;
- }
-
- unsigned long long b (integer_value (tn));
-
- if (b == 0 || b == 1)
- {
- error (l) << "batch size has to be greater than 1" << endl;
- return;
- }
-
- val = b;
-
- if (l.next (tl, &tn) != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
- }
- else if (p == "query")
- {
- // query ()
- // query ("statement")
- // query (expr)
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- if (l.next (tl, &tn) != CPP_OPEN_PAREN)
- {
- error (l) << "'(' expected after db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
-
- view_query vq;
-
- bool s (false);
- string str;
-
- if (tt == CPP_STRING)
- {
- s = true;
- str = tl;
- tt = l.next (tl, &tn);
- }
-
- if (tt == CPP_CLOSE_PAREN)
- {
- if (s)
- vq.literal = str;
- else
- {
- // Empty query() pragma indicates that the statement will be
- // provided at runtime. Encode this case as empty literal
- // and expression.
- //
- }
- }
- else
- {
- // Expression.
- //
- if (s)
- vq.expr.push_back (cxx_token (0, CPP_STRING, str));
-
- if (!parse_expression (l, tt, tl, tn, vq.expr, p))
- return; // Diagnostics has already been issued.
- }
-
- // Disallow query(, distinct).
- //
- if (tt == CPP_COMMA && vq.expr.empty ())
- {
- error (l) << "query expression expected in db pragma " << p << endl;
- return;
- }
-
- // The query expression can be omitted with the modifier in its
- // place. Handle this case.
- //
- if (vq.expr.size () == 1 && vq.expr.front ().type == CPP_NAME)
- {
- string const& n (vq.expr.front ().literal);
-
- if (n == "distinct")
- vq.distinct = true;
- else if (n == "for_update")
- vq.for_update = true;
-
- if (vq.distinct || vq.for_update)
- vq.expr.clear ();
- }
-
- if (tt == CPP_COMMA)
- {
- do
- {
- if (l.next (tl, &tn) != CPP_NAME)
- {
- error (l) << "result modifier expected in db pragma " << p << endl;
- return;
- }
-
- if (tl == "distinct")
- vq.distinct = true;
- else if (tl == "for_update")
- vq.for_update = true;
- else
- {
- error (l) << "unknown result modifier '" << tl << "'" << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
-
- } while (tt == CPP_COMMA);
- }
-
- if (tt != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma " << p << endl;
- return;
- }
-
- vq.scope = current_scope ();
- vq.loc = loc;
- val = vq;
- tt = l.next (tl, &tn);
- }
- else if (p == "object")
- {
- // object (fq-name [ = name] [type] [: expr])
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- if (l.next (tl, &tn) != CPP_OPEN_PAREN)
- {
- error (l) << "'(' expected after db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
-
- if (tt != CPP_NAME && tt != CPP_SCOPE)
- {
- error (l) << "type name expected in db pragma " << p << endl;
- return;
- }
-
- view_object vo;
- vo.kind = view_object::object;
- vo.obj_node = resolve_scoped_name (
- l, tt, tl, tn, current_scope (), vo.obj_name, true, p);
-
- if (vo.obj_node == 0)
- return; // Diagnostics has already been issued.
-
- // Get the actual type if this is a TYPE_DECL. Also get the main variant.
- //
- if (TREE_CODE (vo.obj_node) == TYPE_DECL)
- vo.obj_node = TREE_TYPE (vo.obj_node);
-
- if (TYPE_P (vo.obj_node)) // Can be a template.
- vo.obj_node = TYPE_MAIN_VARIANT (vo.obj_node);
-
- if (tt == CPP_EQ)
- {
- // We have an alias.
- //
- if (l.next (tl, &tn) != CPP_NAME)
- {
- error (l) << "alias name expected after '=' in db pragma " << p
- << endl;
- return;
- }
-
- vo.alias = tl;
- tt = l.next (tl, &tn);
- }
-
- if (tt == CPP_NAME)
- {
- // We have a JOIN type.
- //
- if (tl == "left")
- vo.join = view_object::left;
- else if (tl == "right")
- vo.join = view_object::right;
- else if (tl == "full")
- vo.join = view_object::full;
- else if (tl == "inner")
- vo.join = view_object::inner;
- else if (tl == "cross")
- vo.join = view_object::cross;
- else
- {
- error (l) << "unknown join type '" << tl << "'" << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
- }
- else
- vo.join = view_object::left;
-
- if (tt == CPP_COLON)
- {
- // We have a condition.
- //
- if (vo.join == view_object::cross)
- {
- error (l)
- << "no join condition can be specified for a cross join" << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
-
- if (!parse_expression (l, tt, tl, tn, vo.cond, p))
- return; // Diagnostics has already been issued.
-
- if (vo.cond.empty ())
- {
- error (l) << "join condition expected after ':' in db pragma " << p
- << endl;
- return;
- }
- }
-
- if (tt != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma " << p << endl;
- return;
- }
-
- vo.scope = current_scope ();
- vo.loc = loc;
- val = vo;
- name = "objects"; // Change the context entry name.
- adder = &accumulate<view_object>;
-
- tt = l.next (tl, &tn);
- }
- else if (p == "id")
- {
- // id[(member-path)]
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- string name;
-
- tt = l.next (tl, &tn);
- if (tt == CPP_OPEN_PAREN)
- {
- if (l.next (tl, &tn) != CPP_NAME)
- {
- error (l) << "data member name expected in db pragma " << p
- << endl;
- return;
- }
-
- name = tl;
-
- for (tt = l.next (tl, &tn); tt == CPP_DOT; tt = l.next (tl, &tn))
- {
- if (l.next (tl, &tn) != CPP_NAME)
- {
- error (l) << "name expected after '.' in db pragma " << p << endl;
- return;
- }
-
- name += '.';
- name += tl;
- }
-
- if (tt != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
- }
-
- val = name;
- }
- else if (p == "no_id")
- {
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- name = "id";
- val = false;
-
- tt = l.next (tl, &tn);
- }
- else if (p == "auto")
- {
- // auto
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- tt = l.next (tl, &tn);
- }
- else if (p == "column")
- {
- // column ("<name>")
- // column ("<name>.<name>") (view only)
- // column ("<name>"."<name>") (view only)
- // column (fq-name) (view only)
- // column (expr) (view only)
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- if (l.next (tl, &tn) != CPP_OPEN_PAREN)
- {
- error (l) << "'(' expected after db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
-
- bool expr (false);
- string expr_str;
- if (tt == CPP_STRING || tt == CPP_DOT)
- {
- qname qn;
-
- if (!parse_qname (l, tt, tl, tn, p, qn, &expr, &expr_str))
- return; // Diagnostics has already been issued.
-
- if (tt == CPP_CLOSE_PAREN)
- {
- table_column tc;
- tc.expr = expr;
-
- if (expr)
- tc.column = expr_str;
- else
- {
- tc.table = qn.qualifier ();
- tc.column = qn.uname ();
- }
-
- val = tc;
- }
- else if (!expr)
- {
- error (l) << "column name, expression, or data member name expected "
- << "in db pragma " << p << endl;
- return;
- }
- }
-
- if (val.empty ())
- {
- // We have an expression.
- //
- column_expr e;
-
- if (expr)
- {
- e.push_back (column_expr_part ());
- e.back ().kind = column_expr_part::literal;
- e.back ().value = expr_str;
-
- if (tt != CPP_PLUS)
- {
- error (l) << "'+' or ')' expected in db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
- }
-
- for (;;)
- {
- if (tt == CPP_STRING)
- {
- e.push_back (column_expr_part ());
- e.back ().kind = column_expr_part::literal;
- e.back ().value = tl;
-
- tt = l.next (tl, &tn);
- }
- else if (tt == CPP_NAME || tt == CPP_SCOPE)
- {
- string name (parse_scoped_name (l, tt, tl, tn, p));
-
- if (name.empty ())
- return; // Diagnostics has already been issued.
-
- // Resolve nested members if any.
- //
- for (; tt == CPP_DOT; tt = l.next (tl, &tn))
- {
- if (l.next (tl, &tn) != CPP_NAME)
- {
- error (l) << "name expected after '.' in db pragma " << p
- << endl;
- return;
- }
-
- name += '.';
- name += tl;
- }
-
- e.push_back (column_expr_part ());
- e.back ().kind = column_expr_part::reference;
- e.back ().value = name;
- e.back ().scope = current_scope ();
- e.back ().loc = loc;
- }
- else
- {
- error (l) << "column name, expression, or data member name expected "
- << "in db pragma " << p << endl;
- return;
- }
-
- if (tt == CPP_PLUS)
- tt = l.next (tl, &tn);
- else if (tt == CPP_CLOSE_PAREN)
- break;
- else
- {
- error (l) << "'+' or ')' expected in db pragma " << p << endl;
- return;
- }
- }
-
- e.loc = loc;
- val = e;
- name = "column-expr";
- }
-
- tt = l.next (tl, &tn);
- }
- else if (p == "value_column" ||
- p == "index_column" ||
- p == "key_column" ||
- p == "id_column")
- {
- // value_column ("<name>")
- // index_column ("<name>")
- // key_column ("<name>")
- // id_column ("<name>")
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- if (l.next (tl, &tn) != CPP_OPEN_PAREN)
- {
- error (l) << "'(' expected after db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
-
- if (tt != CPP_STRING)
- {
- error (l) << "column name expected in db pragma " << p << endl;
- return;
- }
-
- val = tl;
-
- if (l.next (tl, &tn) != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
- }
- else if (p == "options" ||
- p == "value_options" ||
- p == "index_options" ||
- p == "key_options" ||
- p == "id_options")
- {
- // options (["<name>"])
- // value_options (["<name>"])
- // index_options (["<name>"])
- // key_options (["<name>"])
- // id_options (["<name>"])
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- if (l.next (tl, &tn) != CPP_OPEN_PAREN)
- {
- error (l) << "'(' expected after db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
-
- if (tt == CPP_STRING)
- {
- // Ignore empty options strings. Internally, we use them to
- // indicate options reset (see below).
- //
- if (!tl.empty ())
- val = tl;
-
- tt = l.next (tl, &tn);
- }
- else if (tt == CPP_CLOSE_PAREN)
- {
- // Empty options specifier signals options reset. Encode it as an
- // empty string.
- //
- val = string ();
- }
- else
- {
- error (l) << "options string expected in db pragma " << p << endl;
- return;
- }
-
- if (tt != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma " << p << endl;
- return;
- }
-
- adder = &accumulate<string>;
- tt = l.next (tl, &tn);
- }
- else if (p == "type" ||
- p == "id_type" ||
- p == "value_type" ||
- p == "index_type" ||
- p == "key_type")
- {
- // type ("<type>")
- // id_type ("<type>")
- // value_type ("<type>")
- // index_type ("<type>")
- // key_type ("<type>")
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- if (l.next (tl, &tn) != CPP_OPEN_PAREN)
- {
- error (l) << "'(' expected after db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
-
- if (tt != CPP_STRING)
- {
- error (l) << "type name expected in db pragma " << p << endl;
- return;
- }
-
- val = tl;
-
- if (l.next (tl, &tn) != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
- }
- else if (p == "null" ||
- p == "not_null" ||
- p == "key_null" ||
- p == "key_not_null" ||
- p == "value_null" ||
- p == "value_not_null")
- {
- // null
- // not_null
- // key_null
- // key_not_null
- // value_null
- // value_not_null
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- tt = l.next (tl, &tn);
- }
- else if (p == "default")
- {
- // default () (<empty>)
- // default (null) (n)
- // default (true|false) (t|f)
- // default ([+|-]<number>) (-|+)
- // default ("string") (s)
- // default (<enumerator>) (e)
- //
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- if (l.next (tl, &tn) != CPP_OPEN_PAREN)
- {
- error (l) << "'(' expected after db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
-
- default_value dv;
-
- switch (tt)
- {
- case CPP_CLOSE_PAREN:
- {
- // Default value reset.
- //
- dv.kind = default_value::reset;
- break;
- }
- case CPP_STRING:
- {
- dv.kind = default_value::string;
- dv.literal = tl;
- tt = l.next (tl, &tn);
- break;
- }
- case CPP_NAME:
- {
- // This can be null or an enumerator name.
- //
- if (tl == "null")
- {
- dv.kind = default_value::null;
- tt = l.next (tl, &tn);
- break;
- }
- }
- // Fall through.
- case CPP_SCOPE:
- {
- // We have a potentially scopped enumerator name.
- //
- dv.enum_value = resolve_scoped_name (
- l, tt, tl, tn, current_scope (), dv.literal, false, p);
-
- if (dv.enum_value == 0)
- return; // Diagnostics has already been issued.
-
- dv.kind = default_value::enumerator;
- break;
- }
- case CPP_MINUS:
- case CPP_PLUS:
- {
- if (tt == CPP_MINUS)
- dv.literal = "-";
-
- tt = l.next (tl, &tn);
-
- if (tt != CPP_NUMBER)
- {
- error (l) << "expected numeric constant after '"
- << (tt == CPP_MINUS ? "-" : "+") << "' in db pragma "
- << p << endl;
- return;
- }
- }
- // Fall through.
- case CPP_NUMBER:
- {
- switch (TREE_CODE (tn))
- {
- case INTEGER_CST:
- {
- dv.int_value = integer_value (tn);
- dv.kind = default_value::integer;
- break;
- }
- case REAL_CST:
- {
- REAL_VALUE_TYPE d (TREE_REAL_CST (tn));
-
- if (REAL_VALUE_ISINF (d))
- dv.float_value = numeric_limits<double>::infinity ();
- else if (REAL_VALUE_ISNAN (d))
- dv.float_value = numeric_limits<double>::quiet_NaN ();
- else
- {
- char tmp[256];
- real_to_decimal (tmp, &d, sizeof (tmp), 0, true);
- istringstream is (tmp);
- is >> dv.float_value;
- }
-
- if (dv.literal == "-")
- dv.float_value = -dv.float_value;
-
- dv.kind = default_value::floating;
- break;
- }
- default:
- {
- error (l) << "unexpected numeric constant in db pragma " << p
- << endl;
- return;
- }
- }
-
- tt = l.next (tl, &tn);
- break;
- }
- default:
- {
- // This can be the true or false keyword.
- //
- if (tt == CPP_KEYWORD && (tl == "true" || tl == "false"))
- {
- dv.kind = default_value::boolean;
- dv.literal = tl;
- tt = l.next (tl, &tn);
- }
- else
- {
- error (l) << "unexpected expression in db pragma " << p << endl;
- return;
- }
-
- break;
- }
- }
-
- if (tt != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma " << p << endl;
- return;
- }
-
- val = dv;
- tt = l.next (tl, &tn);
- }
- else if (p == "inverse")
- {
- // inverse (name)
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- if (l.next (tl, &tn) != CPP_OPEN_PAREN)
- {
- error (l) << "'(' expected after db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
-
- if (tt != CPP_NAME)
- {
- error (l) << "member name expected in db pragma " << p << endl;
- return;
- }
-
- string name (tl);
-
- tt = l.next (tl, &tn);
-
- // Parse nested members if any.
- //
- for (; tt == CPP_DOT; tt = l.next (tl, &tn))
- {
- if (l.next (tl, &tn) != CPP_NAME)
- {
- error (l) << "name expected after '.' in db pragma " << p << endl;
- return;
- }
-
- name += '.';
- name += tl;
- }
-
- if (tt != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma " << p << endl;
- return;
- }
-
- val = name;
- tt = l.next (tl, &tn);
- }
- else if (p == "on_delete")
- {
- // on_delete (cascade|set_null)
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- if (l.next (tl, &tn) != CPP_OPEN_PAREN)
- {
- error (l) << "'(' expected after db pragma " << p << endl;
- return;
- }
-
- if (l.next (tl, &tn) != CPP_NAME || (tl != "cascade" && tl != "set_null"))
- {
- error (l) << "cascade or set_null expected after '('" << endl;
- return;
- }
-
- using semantics::relational::foreign_key;
- val = (tl == "cascade" ? foreign_key::cascade : foreign_key::set_null);
-
- if (l.next (tl, &tn) != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
- }
- else if (p == "points_to")
- {
- // points_to(<fq-name>)
- //
-
- tree type;
- string type_name;
-
- string p (tl);
- location_t loc (l.location ());
-
- if (l.next (tl, &tn) != CPP_OPEN_PAREN)
- {
- error (l) << "'(' expected after db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
-
- if (tt == CPP_NAME || tt == CPP_SCOPE)
- {
- type = resolve_scoped_name (
- l, tt, tl, tn, current_scope (), type_name, true, p);
-
- if (type == 0)
- return; // Diagnostics has already been issued.
-
- // Get the actual type if this is a TYPE_DECL. Also get the main
- // variant.
- //
- if (TREE_CODE (type) == TYPE_DECL)
- type = TREE_TYPE (type);
-
- if (TYPE_P (type)) // Can be a template.
- type = TYPE_MAIN_VARIANT (type);
-
- if (TREE_CODE (type) != RECORD_TYPE)
- {
- error (loc) << "name '" << type_name << "' in db pragma " << p
- << " does not refer to a class" << endl;
- return;
- }
-
- val = type;
- }
- else
- {
- error (l) << "class name expected in db pragma " << p << endl;
- return;
- }
-
- if (tt != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
- }
- else if (p == "section")
- {
- // section (name)
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- if (l.next (tl, &tn) != CPP_OPEN_PAREN)
- {
- error (l) << "'(' expected after db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
-
- if (tt != CPP_NAME)
- {
- error (l) << "member name expected in db pragma " << p << endl;
- return;
- }
-
- name = "section-member";
- val = tl;
-
- if (l.next (tl, &tn) != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
- }
- else if (p == "load")
- {
- // load (eager|lazy)
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- if (l.next (tl, &tn) != CPP_OPEN_PAREN)
- {
- error (l) << "'(' expected after db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
-
- if (tt != CPP_NAME || (tl != "eager" && tl != "lazy"))
- {
- error (l) << "eager or lazy expected in db pragma " << p << endl;
- return;
- }
-
- name = "section-load";
- val = (tl == "eager"
- ? user_section::load_eager
- : user_section::load_lazy);
-
- if (l.next (tl, &tn) != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
- }
- else if (p == "update")
- {
- // update (always|change|manual)
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- if (l.next (tl, &tn) != CPP_OPEN_PAREN)
- {
- error (l) << "'(' expected after db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
-
- if (tt != CPP_NAME ||
- (tl != "always" && tl != "change" && tl != "manual"))
- {
- error (l) << "always, change, or manual expected in db pragma " <<
- p << endl;
- return;
- }
-
- name = "section-update";
-
- if (tl == "always")
- val = user_section::update_always;
- else if (tl == "change")
- val = user_section::update_change;
- else
- val = user_section::update_manual;
-
- if (l.next (tl, &tn) != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
- }
- else if (p == "unordered")
- {
- // unordered
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- tt = l.next (tl, &tn);
- }
- else if (p == "readonly")
- {
- // readonly
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- tt = l.next (tl, &tn);
- }
- else if (p == "transient")
- {
- // transient
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- tt = l.next (tl, &tn);
- }
- else if (p == "added" || p == "deleted")
- {
- // added (unsigned long long version)
- // deleted (unsigned long long version)
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- char const* n (p == "added" ? "addition" : "deletion");
-
- if (l.next (tl, &tn) != CPP_OPEN_PAREN)
- {
- error (l) << "'(' expected after db pragma " << p << endl;
- return;
- }
-
- if (l.next (tl, &tn) != CPP_NUMBER || TREE_CODE (tn) != INTEGER_CST)
- {
- error (l) << "unsigned integer expected as " << n << " version" << endl;
- return;
- }
-
- unsigned long long v (integer_value (tn));
-
- if (v == 0)
- {
- error (l) << n << " version cannot be zero" << endl;
- return;
- }
-
- if (l.next (tl, &tn) != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma " << p << endl;
- return;
- }
-
- val = v;
- tt = l.next (tl, &tn);
- }
- else if (p == "version")
- {
- // version
- //
-
- // Make sure we've got the correct declaration type.
- //
- if (decl && !check_spec_decl_type (decl, decl_name, p, loc))
- return;
-
- tt = l.next (tl, &tn);
- }
- else if (p == "virtual")
- {
- // Stray virtual specifier (i.e., without explicit member name).
- //
- error (l) << "virtual member declaration requires name" << endl;
- return;
- }
- else if (p == "before" || p == "after")
- {
- // Stray before/after specifier (i.e., without preceding virtual).
- //
- error (l) << p << " specifier must follow virtual" << endl;
- return;
- }
- else
- {
- error (l) << "unknown db pragma " << p << endl;
- return;
- }
-
- // Add the pragma unless was indicated otherwise.
- //
- if (!name.empty () && (db.empty () || db == pragma_db_.string ()))
- {
- // If the value is not specified and we don't use a custom adder,
- // then make it bool (flag).
- //
- if (adder == 0 && val.empty ())
- val = true;
-
- // Convert '_' to '-' in the context name so we get foo-bar instead
- // of foo_bar (that's the convention used).
- //
- for (size_t i (0); i < name.size (); ++i)
- if (name[i] == '_')
- name[i] = '-';
-
- // Record this pragma.
- //
- add_pragma (
- pragma (p, name, val, loc, &check_spec_decl_type, adder), decl, ns);
- }
-
- // Mark the type or member as simple value or container, depending
- // on the pragma. For static multi-database support we only do it
- // if the pragma applies to this database since in this case we can
- // have different mappings for different databases (e.g., composite
- // in one and simple in another). For dynamic multi-database support
- // we do this regardless of the database since here the mapping
- // should the consistent.
- //
- // @@ Did we add new simple value or container pragmas and forgot to
- // account for them here?
- //
- if ((qualifier == "value" || qualifier == "member") &&
- (pragma_multi_ == multi_database::dynamic || db.empty () ||
- db == pragma_db_.string ()))
- {
- // We assume a data member is simple only if the database type was
- // specified explicitly.
- //
- if (name == "type" ||
- name == "id-type" ||
- (qualifier == "value" &&
- (name == "null" ||
- name == "not-null" ||
- name == "default" ||
- name == "options")))
- {
- add_pragma (pragma (p, "simple", true, loc, &check_spec_decl_type, 0),
- decl,
- false);
- }
- else if (name == "table" ||
- name == "value-type" ||
- name == "index-type" ||
- name == "key-type" ||
-
- name == "key-null" ||
- name == "key-not-null" ||
- name == "value-null" ||
- name == "value-not-null" ||
-
- name == "value-column" ||
- name == "index-column" ||
- name == "key-column" ||
- name == "index-column" ||
-
- name == "value-options" ||
- name == "index-options" ||
- name == "key-options" ||
- name == "index-options" ||
-
- name == "unordered")
- {
- add_pragma (pragma (p, "container", true, loc, &check_spec_decl_type, 0),
- decl,
- false);
- }
- }
-
- // See if there are any more pragmas.
- //
- if (tt == CPP_NAME || tt == CPP_KEYWORD)
- {
- handle_pragma (l,
- "",
- tl,
- qualifier,
- qualifier_value,
- decl,
- decl_name,
- ns);
- }
- else if (tt != CPP_EOF)
- error (l) << "unexpected text after " << p << " in db pragma" << endl;
-}
-
-//
-// Qualifiers.
-//
-
-static bool
-check_qual_decl_type (declaration const& d,
- string const& name,
- string const& p,
- location_t l)
-{
- gcc_tree_code_type tc (d.tree_code ());
- bool type (TREE_CODE_CLASS (tc) == tcc_type);
-
- if (p == "model" ||
- p == "map")
- {
- assert (d == global_namespace);
- }
- else if (p == "index")
- {
- if (tc != RECORD_TYPE)
- {
- // For an index, name is not empty only if the class name was
- // specified explicitly. Otherwise, the index definition scope
- // is assumed.
- //
- if (name.empty ())
- {
- error (l) << "db pragma " << p << " outside of a class scope" << endl;
- info (l) << "use the db pragma " << p << "(<class-name>) syntax "
- << " instead" << endl;
- }
- else
- error (l) << "name '" << name << "' in db pragma " << p << " does "
- << "not refer to a class" << endl;
- return false;
- }
- }
- else if (p == "namespace")
- {
- if (tc != NAMESPACE_DECL)
- {
- error (l) << "name '" << name << "' in db pragma " << p << " does "
- << "not refer to a namespace" << endl;
- return false;
- }
- }
- else if (p == "object" ||
- p == "view")
- {
- if (tc != RECORD_TYPE)
- {
- error (l) << "name '" << name << "' in db pragma " << p << " does "
- << "not refer to a class" << endl;
- return false;
- }
- }
- else if (p == "value")
- {
- if (!type)
- {
- error (l) << "name '" << name << "' in db pragma " << p << " does "
- << "not refer to a type" << endl;
- return false;
- }
- }
- else if (p == "member")
- {
- if (tc != FIELD_DECL)
- {
- error (l) << "name '" << name << "' in db pragma " << p << " does "
- << "not refer to a data member" << endl;
- return false;
- }
- }
- else
- {
- error (l) << "unknown db pragma " << p << endl;
- return false;
- }
-
- return true;
-}
-
-static void
-add_qual_entry (compiler::context& ctx,
- string const& k,
- any const& v,
- location_t l)
-{
- // Store the TYPE_DECL node that was referred to in the pragma. This
- // can be used later as a name hint in case the type is a template
- // instantiation. Also store the pragma location which is used as
- // the "definition point" for this instantiation.
- //
- ctx.set ("tree-node", v);
- ctx.set ("location", l);
-
- ctx.set (k, true);
-}
-
-static void
-handle_pragma_qualifier (cxx_lexer& l, string p)
-{
- cpp_ttype tt;
- string tl;
- tree tn;
-
- declaration decl;
- tree orig_decl (0); // Original declarations as used in the pragma.
- string decl_name;
-
- // Check for a database prefix.
- //
- string db;
-
- if (p == "mysql" ||
- p == "sqlite" ||
- p == "pgsql" ||
- p == "oracle" ||
- p == "mssql")
- {
- tt = l.next (tl);
-
- if (tt == CPP_COLON)
- {
- // Specifier prefix.
- //
- db = p;
- tt = l.next (p);
- }
- else
- {
- // Qualifier prefix. Ignore the rest if the databases don't match.
- //
- if (p != pragma_db_.string ())
- return;
-
- p = tl;
- }
-
- if (tt != CPP_NAME && tt != CPP_KEYWORD)
- {
- error (l) << "expected specifier after db " << db << " pragma" << endl;
- return;
- }
-
- // Make sure a qualifier prefix is not used before a specifier.
- //
- if (!db.empty () &&
- (p == "model" ||
- p == "map" ||
- p == "namespace" ||
- p == "object" ||
- p == "view" ||
- p == "value" ||
- p == "member"))
- {
- error (l) << "specifier prefix '" << db << ":' used before qualifier " <<
- p << endl;
- return;
- }
- }
-
- //
- //
- string name (p); // Pragma name.
- any val; // Pragma value.
- location_t loc (l.location ()); // Pragma location.
- pragma::add_func adder (0); // Custom context adder.
- bool ns (false); // Namespace location pragma.
-
- cxx_tokens saved_tokens; // Saved token sequence to be replayed.
-
- // Pragma qualifiers.
- //
- if (p == "model")
- {
- orig_decl = global_namespace;
- decl = declaration (orig_decl);
- tt = l.next (tl, &tn);
- }
- else if (p == "map")
- {
- // map type("<regex>") as("<subst>") [to("<subst>")] [from("<subst>")]
- // map type(<c++-type>) as(<c++-type>) [to(<expr>)] [from(<expr>)]
- //
-
- // The thing that determines whether this is a database or C++ type
- // mapping is what we have inside 'type'. So to handle this we are
- // going to pre-scan the pragma looking for 'type' and saving the
- // tokens. Once we determine what this is, we replay the saved
- // tokens to actually parse them.
- //
-
- // Determine what this is by scanning the pragma until we see
- // the 'type' qualifier or EOF.
- //
- bool db (true);
-
- bool done (false);
- size_t balance (0);
- for (tt = l.next (tl, &tn);
- !(done && balance == 0) && tt != CPP_EOF;
- tt = l.next (tl, &tn))
- {
- saved_tokens.push_back (cxx_token (l.location (), tt, tl, tn));
-
- switch (tt)
- {
- case CPP_OPEN_PAREN:
- {
- balance++;
- continue;
- }
- case CPP_CLOSE_PAREN:
- {
- if (balance > 0)
- balance--;
- else
- {
- error (l) << "unbalanced parenthesis in db pragma " << p << endl;
- return;
- }
- continue;
- }
- case CPP_NAME:
- {
- if (balance == 0 && tl == "type")
- break;
-
- continue;
- }
- default:
- continue;
- }
-
- tt = l.next (tl, &tn);
- saved_tokens.push_back (cxx_token (l.location (), tt, tl, tn));
-
- if (tt == CPP_OPEN_PAREN)
- {
- balance++;
-
- tt = l.next (tl, &tn);
- saved_tokens.push_back (cxx_token (l.location (), tt, tl, tn));
-
- db = (tt == CPP_STRING);
- }
-
- done = true; // Scan until the closing ')'.
- }
-
- if (balance != 0)
- {
- error (l) << "unbalanced parenthesis in db pragma " << p << endl;
- return;
- }
-
- orig_decl = global_namespace;
- decl = declaration (orig_decl);
-
- if (db)
- {
- using relational::custom_db_type;
-
- custom_db_type ct;
- ct.loc = loc;
- val = ct;
- name = "custom-db-types";
- adder = &accumulate<custom_db_type>;
- }
- else
- {
- custom_cxx_type ct;
- ct.loc = loc;
- ct.scope = current_scope ();
- val = ct;
- name = "custom-cxx-types";
- adder = &accumulate<custom_cxx_type>;
- }
- }
- else if (p == "index")
- {
- // Index can be both a qualifier and a specifier. Things are complicated
- // by the fact that when it is a specifier, it belongs to a member which
- // means that the actual qualifier ('member') can be omitted. So we need
- // to distinguish between cases like these:
- //
- // #pragma db index type("INTEGER") // specifier
- // #pragma db index type("UNIQUE") member(foo_) // qualifier
- //
- // The thing that determines whether this is a qualifier or a specifier
- // is the presence of the 'member' or 'members' specifier. So to handle
- // this we are going to pre-scan the pragma looking for 'member' or
- // 'members' and saving the tokens. Once we determine what this is,
- // we replay the saved tokens to actually parse them.
- //
- tt = l.next (tl, &tn);
-
- if (tt != CPP_OPEN_PAREN)
- {
- // Determine what this is by scanning the pragma until we see
- // the 'member' qualifier or EOF.
- //
- bool qual (false);
- size_t balance (0);
-
- for (; tt != CPP_EOF; tt = l.next (tl, &tn))
- {
- switch (tt)
- {
- case CPP_OPEN_PAREN:
- {
- balance++;
- break;
- }
- case CPP_CLOSE_PAREN:
- {
- if (balance > 0)
- balance--;
- else
- {
- error (l) << "unbalanced parenthesis in db pragma " << p << endl;
- return;
- }
- break;
- }
- case CPP_NAME:
- {
- if (balance == 0 && (tl == "member" || tl == "members"))
- qual = true;
- break;
- }
- default:
- break;
- }
-
- if (qual)
- break;
-
- saved_tokens.push_back (cxx_token (l.location (), tt, tl, tn));
- }
-
- if (balance != 0)
- {
- error (l) << "unbalanced parenthesis in db pragma " << p << endl;
- return;
- }
-
- if (qual)
- {
- // This is a qualifer. The saved tokens sequence contains tokens
- // until the first 'member' or 'members' specifier. So we will
- // first need to re-play these tokens and then continue parsing
- // as if we just saw the 'member' or 'members' specifier. The
- // token type (tt) and token literal (tl) variables should contain
- // the correct values.
- //
-
- // Also check that no specifier prefix was used for this qualifer.
- //
- if (!db.empty ())
- {
- error (loc) << "specifier prefix '" << db << ":' used before " <<
- "qualifier index" << endl;
- return;
- }
-
- orig_decl = current_scope ();
- decl = declaration (orig_decl);
- }
- else
- {
- // This is a specifier. The saved tokens sequence contains all the
- // tokens in this pragma until EOF.
- //
- cxx_tokens_lexer l;
- l.start (saved_tokens, loc);
- handle_pragma (
- l, db, "index", "member", val, declaration (), "", false);
- return;
- }
- }
-
- relational::index in;
- in.loc = loc;
-
- if (tt == CPP_OPEN_PAREN)
- {
- // Specifier with the class fq-name, index name, or both.
- //
- // index(<fq-name>)
- // index("<name>")
- // index(<fq-name>::"<name>")
- //
- tt = l.next (tl, &tn);
-
- // Resolve class name, if any.
- //
- if (tt == CPP_NAME || tt == CPP_SCOPE)
- {
- cpp_ttype ptt;
- orig_decl = resolve_scoped_name (
- l, tt, tl, tn, current_scope (), decl_name, true, p, true, &ptt);
-
- if (orig_decl == 0)
- return; // Diagnostics has already been issued.
-
- // Get the actual type if this is a TYPE_DECL. Also get the main
- // variant.
- //
- if (TREE_CODE (orig_decl) == TYPE_DECL)
- orig_decl = TREE_TYPE (orig_decl);
-
- if (TYPE_P (orig_decl)) // Can be a template.
- decl = declaration (TYPE_MAIN_VARIANT (orig_decl));
- else
- decl = declaration (orig_decl);
-
- if (tt == CPP_STRING && ptt != CPP_SCOPE)
- {
- error (l) << "'::' expected before index name in db pragma " << p
- << endl;
- return;
- }
-
- if (tt != CPP_STRING && ptt == CPP_SCOPE)
- {
- error (l) << "index name expected after '::' in db pragma " << p
- << endl;
- return;
- }
- }
- else
- {
- orig_decl = current_scope ();
- decl = declaration (orig_decl);
- }
-
- // Make sure we've got the correct declaration type.
- //
- if (!check_qual_decl_type (decl, decl_name, p, loc))
- return;
-
- if (tt == CPP_STRING)
- {
- in.name = tl;
- tt = l.next (tl, &tn);
- }
-
- if (tt != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
- }
-
- val = in;
- adder = &accumulate<relational::index>;
- }
- else if (p == "namespace")
- {
- // namespace [(<identifier>)]
- // namespace () (refers to global namespace)
- //
-
- tt = l.next (tl, &tn);
-
- if (tt == CPP_OPEN_PAREN)
- {
- tt = l.next (tl, &tn);
-
- if (tt == CPP_NAME || tt == CPP_SCOPE)
- {
- orig_decl = resolve_scoped_name (
- l, tt, tl, tn, current_scope (), decl_name, false, p);
-
- if (orig_decl == 0)
- return; // Diagnostics has already been issued.
-
- // Make sure we've got the correct declaration type.
- //
- if (!check_qual_decl_type (orig_decl, decl_name, p, loc))
- return;
-
- // Resolve namespace aliases if any.
- //
- orig_decl = ORIGINAL_NAMESPACE (orig_decl);
- decl = declaration (orig_decl);
-
- if (tt != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
- }
- else if (tt == CPP_CLOSE_PAREN)
- {
- orig_decl = global_namespace;
- decl = declaration (orig_decl);
- tt = l.next (tl, &tn);
- }
- else
- {
- error (l) << "data member name expected in db pragma " << p << endl;
- return;
- }
- }
- else
- {
- // Make sure we are in a namespace scope.
- //
- if (TREE_CODE (current_scope ()) != NAMESPACE_DECL)
- {
- error (l) << "db pragma " << p << " is not in a namespace scope"
- << endl;
- return;
- }
-
- ns = true;
- }
- }
- else if (p == "object" ||
- p == "view" ||
- p == "value")
- {
- // object [(<identifier>)]
- // view [(<identifier>)]
- // value [(<identifier>)]
- //
-
- tt = l.next (tl, &tn);
-
- if (tt == CPP_OPEN_PAREN)
- {
- tt = l.next (tl, &tn);
-
- // Can be built-in type (e.g., bool).
- //
- if (tt == CPP_NAME || tt == CPP_KEYWORD || tt == CPP_SCOPE)
- {
- orig_decl = resolve_scoped_name (
- l, tt, tl, tn, current_scope (), decl_name, true, p);
-
- if (orig_decl == 0)
- return; // Diagnostics has already been issued.
-
- // Get the actual type if this is a TYPE_DECL. Also get the main
- // variant.
- //
- if (TREE_CODE (orig_decl) == TYPE_DECL)
- orig_decl = TREE_TYPE (orig_decl);
-
- if (TYPE_P (orig_decl)) // Can be a template.
- decl = declaration (TYPE_MAIN_VARIANT (orig_decl));
- else
- decl = declaration (orig_decl);
-
- // Make sure we've got the correct declaration type.
- //
- if (!check_qual_decl_type (decl, decl_name, p, loc))
- return;
-
- if (tt != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
- }
- else
- {
- error (l) << "type name expected in db pragma " << p << endl;
- return;
- }
- }
- }
- else if (p == "member")
- {
- // member [(<identifier>)]
- //
-
- tt = l.next (tl, &tn);
-
- if (tt == CPP_OPEN_PAREN)
- {
- tt = l.next (tl, &tn);
-
- if (tt != CPP_NAME && tt != CPP_SCOPE)
- {
- error (l) << "data member name expected in db pragma " << p << endl;
- return;
- }
-
- // We need to see if this is a virtual data member declaration. Also,
- // if it is not, then the name can still refer to one so we need to
- // take extra steps to handle that. But first, we save the name and
- // look for the 'virtual' specifier.
- //
- cxx_tokens name_tokens;
- for (; tt != CPP_CLOSE_PAREN && tt != CPP_EOF; tt = l.next (tl, &tn))
- name_tokens.push_back (cxx_token (l.location (), tt, tl, tn));
-
- if (tt != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma " << p << endl;
- return;
- }
-
- // Now scan the remainder of the pragma looking for the 'virtual'
- // keyword and saving the tokens in between for later.
- //
- bool virt (false);
- size_t balance (0);
- for (tt = l.next (tl, &tn); tt != CPP_EOF; tt = l.next (tl, &tn))
- {
- switch (tt)
- {
- case CPP_OPEN_PAREN:
- {
- balance++;
- break;
- }
- case CPP_CLOSE_PAREN:
- {
- if (balance > 0)
- balance--;
- else
- {
- error (l) << "unbalanced parenthesis in db pragma " << p << endl;
- return;
- }
- break;
- }
- default:
- {
- if (balance == 0 && tt == CPP_KEYWORD && tl == "virtual")
- virt = true;
- break;
- }
- }
-
- if (virt)
- break;
-
- saved_tokens.push_back (cxx_token (l.location (), tt, tl, tn));
- }
-
- if (balance != 0)
- {
- error (l) << "unbalanced parenthesis in db pragma " << p << endl;
- return;
- }
-
- // Regardless of whether this is a virtual member declaration or a
- // reference, resolve its scope name (if one is specified), which
- // should be a class. We will need it in both cases.
- //
- tree scope;
- if (name_tokens.size () > 2) // scope::name
- {
- size_t n (name_tokens.size ());
-
- if (name_tokens[n - 2].type != CPP_SCOPE ||
- name_tokens[n - 1].type != CPP_NAME)
- {
- error (l) << "invalid name in db pragma " << p << endl;
- return;
- }
-
- cxx_tokens scope_tokens (1, name_tokens.back ());
- name_tokens.pop_back (); // ::
- name_tokens.pop_back (); // name
- name_tokens.swap (scope_tokens);
-
- cxx_tokens_lexer l;
- l.start (scope_tokens);
-
- tree tn;
- string tl;
- cpp_ttype tt (l.next (tl));
-
- scope = resolve_scoped_name (
- l, tt, tl, tn, current_scope (), decl_name, true, p);
-
- if (scope == 0)
- return; // Diagnostics has already been issued.
-
- scope = TYPE_MAIN_VARIANT (TREE_TYPE (scope));
-
- if (tt != CPP_EOF)
- {
- error (l) << "invalid name in db pragma " << p << endl;
- return;
- }
-
- decl_name += "::";
- }
- else
- scope = current_scope ();
-
- if (virt)
- {
- // Should be a single name.
- //
- if (name_tokens.size () > 1 || name_tokens.back ().type != CPP_NAME)
- {
- location_t l (name_tokens.back ().loc);
- error (l) << "invalid name in db pragma " << p << endl;
- return;
- }
- string const& name (name_tokens.back ().literal);
-
- // Parse the remainder of the virtual specifier.
- //
- // virtual(<fq-name>)
- //
- tree type;
- string type_name;
- location_t ord (loc);
- int ord_bias (0);
- {
- string p (tl);
- location_t loc (l.location ());
-
- if (l.next (tl, &tn) != CPP_OPEN_PAREN)
- {
- error (l) << "'(' expected after db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
-
- // Can be built-in type (e.g., bool).
- //
- if (tt == CPP_NAME || tt == CPP_KEYWORD || tt == CPP_SCOPE)
- {
- type = resolve_scoped_name (
- l, tt, tl, tn, current_scope (), type_name, true, p);
-
- if (type == 0)
- return; // Diagnostics has already been issued.
-
- if (TREE_CODE (type) != TYPE_DECL)
- {
- error (loc) << "name '" << type_name << "' in db pragma "
- << p << " does not refer to a type" << endl;
- return;
- }
-
- type = TREE_TYPE (type);
- }
- else
- {
- error (l) << "type name expected in db pragma " << p << endl;
- return;
- }
-
- if (tt != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma " << p << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
-
- // See if we have before/after specifiers.
- //
- if (tt == CPP_NAME && tl == "before")
- {
- // before[(<member>)]
- //
- // Before without the member name means first.
- //
- tt = l.next (tl, &tn);
-
- if (tt == CPP_OPEN_PAREN)
- {
- if (l.next (tl, &tn) != CPP_NAME)
- {
- error (l) << "')' member name expected in db pragma before"
- << endl;
- }
-
- string dn;
- cxx_tokens ts (1, cxx_token (l.location (), CPP_NAME, tl));
- declaration d (resolve_data_member (scope, ts, dn, "before"));
-
- if (!d)
- return; // Diagnostics has already been issued.
-
- if (d.virt)
- {
- ord = d.decl.virt->ord;
- ord_bias = d.decl.virt->ord_bias - 1;
- }
- else
- {
- ord = real_source_location (d.decl.real);
- ord_bias = -1;
- }
-
- if (l.next (tl, &tn) != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma before"
- << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
- }
- else
- ord = 0;
- }
-
- if (tt == CPP_NAME && tl == "after")
- {
- // after[(<member>)]
- //
- // Before without the member name means last.
- //
- tt = l.next (tl, &tn);
-
- if (tt == CPP_OPEN_PAREN)
- {
- if (l.next (tl, &tn) != CPP_NAME)
- {
- error (l) << "')' member name expected in db pragma after"
- << endl;
- }
-
- string dn;
- cxx_tokens ts (1, cxx_token (l.location (), CPP_NAME, tl));
- declaration d (resolve_data_member (scope, ts, dn, "after"));
-
- if (!d)
- return; // Diagnostics has already been issued.
-
- if (d.virt)
- {
- ord = d.decl.virt->ord;
- ord_bias = d.decl.virt->ord_bias + 1;
- }
- else
- {
- ord = real_source_location (d.decl.real);
- ord_bias = 1;
- }
-
- if (l.next (tl, &tn) != CPP_CLOSE_PAREN)
- {
- error (l) << "')' expected at the end of db pragma after"
- << endl;
- return;
- }
-
- tt = l.next (tl, &tn);
- }
- else
- ord = ~location_t (0);
- }
- }
-
- pair<virt_declaration_set::const_iterator, bool> r (
- virt_declarations_[scope].insert (
- virt_declaration (loc, ord, ord_bias, name, FIELD_DECL, type)));
-
- if (!r.second)
- {
- error (loc) << "virtual data member declaration '" << name
- << "' conflicts with a previous declaration" << endl;
-
- info (r.first->loc) << "'" << name << "' was previously "
- << "declared here" << endl;
- return;
- }
-
- decl_name += name;
- decl = declaration (*r.first);
-
- // Mark it as virtual using the standard pragma machinery.
- //
- add_pragma (
- pragma ("virtual", "virtual", true, loc, &check_spec_decl_type, 0),
- decl,
- false);
- }
- else
- {
- // Not a virtual member declaration.
- //
- decl = resolve_data_member (scope, name_tokens, decl_name, p);
-
- if (!decl)
- return; // Diagnostics has already been issued.
-
- // Make sure we've got the correct declaration type.
- //
- if (!check_qual_decl_type (decl, decl_name, p, loc))
- return;
- }
- }
- }
- //
- // The member qualifier can be omitted so we need to also handle all
- // the member pragmas here.
- //
- else if (p == "id" ||
- p == "auto" ||
- p == "unique" ||
- p == "get" ||
- p == "set" ||
- p == "access" ||
- p == "column" ||
- p == "value_column" ||
- p == "index_column" ||
- p == "key_column" ||
- p == "id_column" ||
- p == "options" ||
- p == "value_options" ||
- p == "index_options" ||
- p == "key_options" ||
- p == "id_options" ||
- p == "type" ||
- p == "id_type" ||
- p == "value_type" ||
- p == "index_type" ||
- p == "key_type" ||
- p == "table" ||
- p == "null" ||
- p == "not_null" ||
- p == "key_null" ||
- p == "key_not_null" ||
- p == "value_null" ||
- p == "value_not_null" ||
- p == "default" ||
- p == "section" ||
- p == "load" ||
- p == "update" ||
- p == "inverse" ||
- p == "on_delete" ||
- p == "points_to" ||
- p == "unordered" ||
- p == "readonly" ||
- p == "transient" ||
- p == "added" ||
- p == "deleted" ||
- p == "version" ||
- p == "virtual")
- {
- handle_pragma (l, db, p, "member", val, declaration (), "", false);
- return;
- }
- else
- {
- error (l) << "unknown db pragma " << p << endl;
- return;
- }
-
- // Record this pragma. Delay this until after we process the
- // specifiers for value (see comment below for the reason).
- //
- if (adder == 0)
- val = orig_decl;
-
- pragma prag (p,
- name, // For now no need to translate '_' to '-'.
- val,
- loc,
- &check_qual_decl_type,
- adder != 0 ? adder : &add_qual_entry);
-
- tree scope;
- if (!decl)
- {
- scope = current_scope ();
-
- if (!ns && !CLASS_TYPE_P (scope))
- scope = global_namespace;
- }
-
- any* pval;
- if (p != "value")
- {
- if (decl)
- pval = &decl_pragmas_[decl].insert (prag).value;
- else
- {
- if (!ns)
- {
- pragma_list& pl (loc_pragmas_[scope]);
- pl.push_back (prag);
- pval = &pl.back ().value;
- }
- else
- {
- ns_loc_pragmas_.push_back (ns_loc_pragma (scope, prag));
- pval = &ns_loc_pragmas_.back ().pragma.value;
- }
- }
- }
- else
- pval = &val;
-
- // See if there are any saved tokens to replay.
- //
- if (!saved_tokens.empty ())
- {
- cxx_tokens_lexer l;
- l.start (saved_tokens);
-
- string tl;
- cpp_ttype tt (l.next (tl));
-
- if (tt == CPP_NAME || tt == CPP_KEYWORD)
- {
- handle_pragma (l, "", tl, p, *pval, decl, decl_name, ns);
-
- if (errorcount != 0) // Avoid parsing the rest if there was an error.
- return;
- }
- else if (tt != CPP_EOF)
- {
- error (l) << "unexpected text after " << p << " in db pragma" << endl;
- return;
- }
- }
-
- size_t count (0);
- if (tt == CPP_NAME || tt == CPP_KEYWORD)
- {
- if (decl)
- count = decl_pragmas_[decl].size ();
- else
- count = loc_pragmas_[scope].size ();
-
- handle_pragma (l, "", tl, p, *pval, decl, decl_name, ns);
- }
- else if (tt != CPP_EOF)
- {
- error (l) << "unexpected text after " << p << " in db pragma" << endl;
- return;
- }
-
- // Record the value pragma. Here things are complicated by the fact
- // that we use the value pragma by itself to signify a composite value
- // type declaration. Consider this example:
- //
- // #pragma db value pgsql:type("POINT")
- // class point {...};
- //
- // Should this class be considered composite value type in other
- // databases (because that's what would happen by default)? Probably
- // not. So to overcome this we are going to detect and ignore cases
- // where (a) some specifiers followed the value qualifier but (b)
- // none of them are for the database that we are compiling for.
- //
- if (p == "value")
- {
- if (decl)
- {
- pragma_set& ps (decl_pragmas_[decl]);
-
- if (tt == CPP_EOF || ps.size () > count)
- ps.insert (prag);
- }
- else
- {
- pragma_list& pl (loc_pragmas_[scope]);
-
- if (tt == CPP_EOF || pl.size () > count)
- pl.push_back (prag);
- }
- }
-}
-
-/*
-extern "C" void
-handle_pragma_db_mysql (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "mysql");
-}
-
-extern "C" void
-handle_pragma_db_sqlite (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "sqlite");
-}
-
-extern "C" void
-handle_pragma_db_pgsql (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "pgsql");
-}
-
-extern "C" void
-handle_pragma_db_oracle (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "oracle");
-}
-
-extern "C" void
-handle_pragma_db_mssql (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "mssql");
-}
-
-extern "C" void
-handle_pragma_db_model (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "model");
-}
-
-extern "C" void
-handle_pragma_db_map (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "map");
-}
-
-extern "C" void
-handle_pragma_db_namespace (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "namespace");
-}
-
-extern "C" void
-handle_pragma_db_object (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "object");
-}
-
-extern "C" void
-handle_pragma_db_view (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "view");
-}
-
-extern "C" void
-handle_pragma_db_value (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "value");
-}
-
-extern "C" void
-handle_pragma_db_member (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "member");
-}
-
-extern "C" void
-handle_pragma_db_id (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "id");
-}
-
-extern "C" void
-handle_pragma_db_auto (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "auto");
-}
-
-extern "C" void
-handle_pragma_db_column (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "column");
-}
-
-extern "C" void
-handle_pragma_db_vcolumn (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "value_column");
-}
-
-extern "C" void
-handle_pragma_db_icolumn (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "index_column");
-}
-
-extern "C" void
-handle_pragma_db_kcolumn (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "key_column");
-}
-
-extern "C" void
-handle_pragma_db_idcolumn (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "id_column");
-}
-
-extern "C" void
-handle_pragma_db_options (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "options");
-}
-
-extern "C" void
-handle_pragma_db_voptions (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "value_options");
-}
-
-extern "C" void
-handle_pragma_db_ioptions (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "index_options");
-}
-
-extern "C" void
-handle_pragma_db_koptions (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "key_options");
-}
-
-extern "C" void
-handle_pragma_db_idoptions (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "id_options");
-}
-
-extern "C" void
-handle_pragma_db_type (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "type");
-}
-
-extern "C" void
-handle_pragma_db_id_type (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "id_type");
-}
-
-extern "C" void
-handle_pragma_db_vtype (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "value_type");
-}
-
-extern "C" void
-handle_pragma_db_itype (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "index_type");
-}
-
-extern "C" void
-handle_pragma_db_ktype (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "key_type");
-}
-
-extern "C" void
-handle_pragma_db_table (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "table");
-}
-
-extern "C" void
-handle_pragma_db_null (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "null");
-}
-
-extern "C" void
-handle_pragma_db_not_null (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "not_null");
-}
-
-extern "C" void
-handle_pragma_db_value_null (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "value_null");
-}
-
-extern "C" void
-handle_pragma_db_value_not_null (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "value_not_null");
-}
-
-extern "C" void
-handle_pragma_db_key_null (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "key_null");
-}
-
-extern "C" void
-handle_pragma_db_key_not_null (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "key_not_null");
-}
-
-extern "C" void
-handle_pragma_db_default (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "default");
-}
-
-extern "C" void
-handle_pragma_db_section (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "section");
-}
-
-extern "C" void
-handle_pragma_db_load (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "load");
-}
-
-extern "C" void
-handle_pragma_db_update (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "update");
-}
-
-extern "C" void
-handle_pragma_db_inverse (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "inverse");
-}
-
-extern "C" void
-handle_pragma_db_on_delete (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "on_delete");
-}
-
-extern "C" void
-handle_pragma_db_points_to (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "points_to");
-}
-
-extern "C" void
-handle_pragma_db_unordered (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "unordered");
-}
-
-extern "C" void
-handle_pragma_db_readonly (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "readonly");
-}
-
-extern "C" void
-handle_pragma_db_transient (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "transient");
-}
-
-extern "C" void
-handle_pragma_db_added (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "added");
-}
-
-extern "C" void
-handle_pragma_db_deleted (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "deleted");
-}
-
-extern "C" void
-handle_pragma_db_version (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "version");
-}
-
-extern "C" void
-handle_pragma_db_virtual (cpp_reader* r)
-{
- handle_pragma_qualifier (r, "virtual");
-}
-*/
-
-extern "C" void
-handle_pragma_db (cpp_reader*)
-{
- cxx_pragma_lexer l;
- l.start ();
-
- string tl;
- cpp_ttype tt (l.next (tl));
-
- if (tt != CPP_NAME && tt != CPP_KEYWORD)
- {
- error (l) << "expected specifier after db pragma" << endl;
- return;
- }
-
- handle_pragma_qualifier (l, tl);
-}
-
-extern "C" void
-register_odb_pragmas (void*, void*)
-{
- // GCC has a limited number of pragma slots and we have exhausted them.
- // A workaround is to make 'db' a pragma rather than a namespace. This
- // way we only have one pragma but the drawback of this approach is the
- // fact that the specifier or qualifier name will now be macro-expanded
- // (though this happens anyway if we have multiple specifiers in a single
- // pragma). Once the GCC folks fix this, we can go back to the namespace
- // approach.
- //
- c_register_pragma_with_expansion (0, "db", handle_pragma_db);
-
- /*
- c_register_pragma_with_expansion ("db", "mysql", handle_pragma_db_mysql);
- c_register_pragma_with_expansion ("db", "sqlite", handle_pragma_db_sqlite);
- c_register_pragma_with_expansion ("db", "pgsql", handle_pragma_db_pgsql);
- c_register_pragma_with_expansion ("db", "oracle", handle_pragma_db_oracle);
- c_register_pragma_with_expansion ("db", "mssql", handle_pragma_db_mssql);
- c_register_pragma_with_expansion ("db", "model", handle_pragma_db_model);
- c_register_pragma_with_expansion ("db", "map", handle_pragma_db_map);
- c_register_pragma_with_expansion ("db", "namespace", handle_pragma_db_namespace);
- c_register_pragma_with_expansion ("db", "object", handle_pragma_db_object);
- c_register_pragma_with_expansion ("db", "view", handle_pragma_db_view);
- c_register_pragma_with_expansion ("db", "value", handle_pragma_db_value);
- c_register_pragma_with_expansion ("db", "member", handle_pragma_db_member);
- c_register_pragma_with_expansion ("db", "id", handle_pragma_db_id);
- c_register_pragma_with_expansion ("db", "auto", handle_pragma_db_auto);
- c_register_pragma_with_expansion ("db", "column", handle_pragma_db_column);
- c_register_pragma_with_expansion ("db", "value_column", handle_pragma_db_vcolumn);
- c_register_pragma_with_expansion ("db", "index_column", handle_pragma_db_icolumn);
- c_register_pragma_with_expansion ("db", "key_column", handle_pragma_db_kcolumn);
- c_register_pragma_with_expansion ("db", "id_column", handle_pragma_db_idcolumn);
- c_register_pragma_with_expansion ("db", "options", handle_pragma_db_options);
- c_register_pragma_with_expansion ("db", "value_options", handle_pragma_db_voptions);
- c_register_pragma_with_expansion ("db", "index_options", handle_pragma_db_ioptions);
- c_register_pragma_with_expansion ("db", "key_options", handle_pragma_db_koptions);
- c_register_pragma_with_expansion ("db", "id_options", handle_pragma_db_idoptions);
- c_register_pragma_with_expansion ("db", "type", handle_pragma_db_type);
- c_register_pragma_with_expansion ("db", "id_type", handle_pragma_db_id_type);
- c_register_pragma_with_expansion ("db", "value_type", handle_pragma_db_vtype);
- c_register_pragma_with_expansion ("db", "index_type", handle_pragma_db_itype);
- c_register_pragma_with_expansion ("db", "key_type", handle_pragma_db_ktype);
- c_register_pragma_with_expansion ("db", "table", handle_pragma_db_table);
- c_register_pragma_with_expansion ("db", "null", handle_pragma_db_null);
- c_register_pragma_with_expansion ("db", "not_null", handle_pragma_db_not_null);
- c_register_pragma_with_expansion ("db", "key_null", handle_pragma_db_key_null);
- c_register_pragma_with_expansion ("db", "key_not_null", handle_pragma_db_key_not_null);
- c_register_pragma_with_expansion ("db", "value_null", handle_pragma_db_value_null);
- c_register_pragma_with_expansion ("db", "value_not_null", handle_pragma_db_value_not_null);
- c_register_pragma_with_expansion ("db", "default", handle_pragma_db_default);
- c_register_pragma_with_expansion ("db", "section", handle_pragma_db_section);
- c_register_pragma_with_expansion ("db", "load", handle_pragma_db_load);
- c_register_pragma_with_expansion ("db", "update", handle_pragma_db_update);
- c_register_pragma_with_expansion ("db", "inverse", handle_pragma_db_inverse);
- c_register_pragma_with_expansion ("db", "on_delete", handle_pragma_db_on_delete);
- c_register_pragma_with_expansion ("db", "points_to", handle_pragma_db_points_to);
- c_register_pragma_with_expansion ("db", "unordered", handle_pragma_db_unordered);
- c_register_pragma_with_expansion ("db", "readonly", handle_pragma_db_readonly);
- c_register_pragma_with_expansion ("db", "transient", handle_pragma_db_transient);
- c_register_pragma_with_expansion ("db", "added", handle_pragma_db_added);
- c_register_pragma_with_expansion ("db", "deleted", handle_pragma_db_deleted);
- c_register_pragma_with_expansion ("db", "version", handle_pragma_db_version);
- c_register_pragma_with_expansion ("db", "virtual", handle_pragma_db_virtual);
- */
-}
-
-void
-post_process_pragmas ()
-{
- // Make sure object, view, and composite class template instantiations
- // are fully instantiated.
- //
- for (decl_pragmas::iterator i (decl_pragmas_.begin ()),
- e (decl_pragmas_.end ()); i != e; ++i)
- {
- if (i->first.virt)
- continue;
-
- tree type (i->first.decl.real);
-
- if (!(CLASS_TYPE_P (type) && CLASSTYPE_TEMPLATE_INSTANTIATION (type)))
- continue;
-
- // Check whether this is an object, view, or composite value type.
- //
- pragma const* p (0);
- string diag_name;
-
- for (pragma_set::iterator j (i->second.begin ()), e (i->second.end ());
- j != e; ++j)
- {
- string const& name (j->second.context_name);
-
- if (name == "object")
- {
- p = &j->second;
- diag_name = "persistent object";
- break;
- }
- else if (name == "view")
- {
- p = &j->second;
- diag_name = "view";
- break;
- }
- else if (name == "value")
- {
- p = &j->second;
- diag_name = "composite value";
- break;
- }
- // We don't want to instantiate simple values since they may be
- // incomplete.
- //
- else if (name == "simple" || name == "container")
- {
- p = 0;
- break;
- }
- }
-
- if (p == 0)
- continue;
-
- // Make sure it is instantiated.
- //
- tree decl (TYPE_NAME (p->value.value<tree> ()));
- location_t loc (real_source_location (decl));
-
- // Reset input location so that we get nice diagnostics in case
- // of an error.
- //
- input_location = loc;
-
- if (instantiate_class_template (type) == error_mark_node ||
- errorcount != 0 ||
- !COMPLETE_TYPE_P (type))
- {
- error (loc) << "unable to instantiate " << diag_name << " class template"
- << endl;
- throw pragmas_failed ();
- }
- }
-}