aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--odb/context.hxx28
-rw-r--r--odb/parser.cxx44
-rw-r--r--odb/pragma.cxx152
-rw-r--r--odb/pragma.hxx39
-rw-r--r--odb/relational/schema.cxx63
-rw-r--r--odb/relational/type-processor.cxx37
-rw-r--r--odb/validator.cxx10
7 files changed, 201 insertions, 172 deletions
diff --git a/odb/context.hxx b/odb/context.hxx
index cb8e2ef..ea351de 100644
--- a/odb/context.hxx
+++ b/odb/context.hxx
@@ -6,6 +6,8 @@
#ifndef ODB_CONTEXT_HXX
#define ODB_CONTEXT_HXX
+#include <odb/gcc-fwd.hxx>
+
#include <map>
#include <set>
#include <stack>
@@ -67,6 +69,32 @@ enum class_kind
class_other
};
+// Semantic graph context types.
+//
+struct view_object
+{
+ tree node;
+ std::string name;
+ semantics::class_* object;
+};
+
+struct default_value
+{
+ enum kind_type
+ {
+ reset, // Default value reset.
+ null,
+ boolean,
+ number, // Integer of floating-point number. Value contains sign.
+ string,
+ enumerator // Value is the name, node is the tree node.
+ };
+
+ kind_type kind;
+ std::string value;
+ tree node;
+};
+
class context
{
public:
diff --git a/odb/parser.cxx b/odb/parser.cxx
index b615a2f..b8ea160 100644
--- a/odb/parser.cxx
+++ b/odb/parser.cxx
@@ -1902,49 +1902,23 @@ void parser::impl::
add_pragma (node& n, pragma const& p)
{
if (trace)
- ts << "\t\t pragma " << p.pragma_name << " (" << p.value << ")" << endl;
+ ts << "\t\t pragma " << p.pragma_name << endl;
// Convert '_' to '-' in the pragma name so we get foo-bar instead
// of foo_bar (that's the convention used).
//
- string kv (p.context_name);
- for (size_t i (0); i < kv.size (); ++i)
- if (kv[i] == '_')
- kv[i] = '-';
+ string k (p.context_name);
+ for (size_t i (0); i < k.size (); ++i)
+ if (k[i] == '_')
+ k[i] = '-';
- string kl (kv + "-loc");
- string kn (kv + "-node");
-
- if (p.mode == pragma::override)
+ if (p.add == 0)
{
- n.set (kv, p.value);
- n.set (kn, p.node);
- n.set (kl, p.loc);
+ n.set (k, p.value);
+ n.set (k + "-location", p.loc);
}
else
- {
- // Having three parallel vectors is not the most efficient
- // way to store this, but it is quite simple.
- //
- typedef vector<string> values;
- typedef vector<tree> nodes;
- typedef vector<location_t> locations;
-
- if (!n.count (kv))
- {
- n.set (kv, values ());
- n.set (kn, nodes ());
- n.set (kl, locations ());
- }
-
- values& vs (n.get<values> (kv));
- nodes& ns (n.get<nodes> (kn));
- locations& ls (n.get<locations> (kl));
-
- vs.push_back (p.value);
- ns.push_back (p.node);
- ls.push_back (p.loc);
- }
+ p.add (n, k, p.value, p.loc);
}
void parser::impl::
diff --git a/odb/pragma.cxx b/odb/pragma.cxx
index a6ec579..ea2a696 100644
--- a/odb/pragma.cxx
+++ b/odb/pragma.cxx
@@ -5,11 +5,35 @@
#include <odb/gcc.hxx>
+#include <vector>
+
#include <odb/error.hxx>
#include <odb/pragma.hxx>
#include <odb/cxx-lexer.hxx>
+#include <odb/context.hxx>
using namespace std;
+using namespace cutl;
+
+using container::any;
+
+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> ());
+}
// Lists of pragmas.
//
@@ -311,10 +335,9 @@ handle_pragma (cpp_reader* reader,
cpp_ttype tt;
string name (p); // Pragma name.
- string val; // Pragma string value.
- tree node (0); // Pragma tree node value.
+ any val; // Pragma value.
+ pragma::add_func adder (0); // Custom context adder.
location_t loc (input_location); // Pragma location.
- pragma::mode_type mode (pragma::override); // Pragma mode.
if (p == "table")
{
@@ -340,7 +363,7 @@ handle_pragma (cpp_reader* reader,
return;
}
- val = TREE_STRING_POINTER (t);
+ val = string (TREE_STRING_POINTER (t));
if (pragma_lex (&t) != CPP_CLOSE_PAREN)
{
@@ -366,6 +389,7 @@ handle_pragma (cpp_reader* reader,
return;
}
+ string v;
size_t pb (0);
bool punc (false);
@@ -374,7 +398,7 @@ handle_pragma (cpp_reader* reader,
tt = pragma_lex (&t))
{
if (punc && tt > CPP_LAST_PUNCTUATOR)
- val += ' ';
+ v += ' ';
punc = false;
@@ -389,29 +413,29 @@ handle_pragma (cpp_reader* reader,
{
case CPP_LESS:
{
- val += "< ";
+ v += "< ";
break;
}
case CPP_GREATER:
{
- val += " >";
+ v += " >";
break;
}
case CPP_COMMA:
{
- val += ", ";
+ v += ", ";
break;
}
case CPP_NAME:
{
- val += IDENTIFIER_POINTER (t);
+ v += IDENTIFIER_POINTER (t);
punc = true;
break;
}
default:
{
if (tt <= CPP_LAST_PUNCTUATOR)
- val += cxx_lexer::token_spelling[tt];
+ v += cxx_lexer::token_spelling[tt];
else
{
error () << "unexpected token '" << cxx_lexer::token_spelling[tt]
@@ -429,12 +453,14 @@ handle_pragma (cpp_reader* reader,
return;
}
- if (val.empty ())
+ if (v.empty ())
{
error () << "expected pointer name in db pragma " << p << endl;
return;
}
+ val = v;
+
tt = pragma_lex (&t);
}
else if (p == "abstract")
@@ -473,7 +499,7 @@ handle_pragma (cpp_reader* reader,
return;
}
- val = IDENTIFIER_POINTER (t);
+ val = string (IDENTIFIER_POINTER (t));
if (pragma_lex (&t) != CPP_CLOSE_PAREN)
{
@@ -507,7 +533,7 @@ handle_pragma (cpp_reader* reader,
return;
}
- val = TREE_STRING_POINTER (t);
+ val = string (TREE_STRING_POINTER (t));
if (pragma_lex (&t) != CPP_CLOSE_PAREN)
{
@@ -541,11 +567,10 @@ handle_pragma (cpp_reader* reader,
return;
}
- name = "objects"; // Change the context entry name.
- mode = pragma::accumulate;
- node = parse_scoped_name (t, tt, val, true, p);
+ view_object vo;
+ vo.node = parse_scoped_name (t, tt, vo.name, true, p);
- if (node == 0)
+ if (vo.node == 0)
return; // Diagnostics has already been issued.
if (tt != CPP_CLOSE_PAREN)
@@ -554,6 +579,10 @@ handle_pragma (cpp_reader* reader,
return;
}
+ val = vo;
+ name = "objects"; // Change the context entry name.
+ adder = &accumulate<view_object>;
+
tt = pragma_lex (&t);
}
else if (p == "id")
@@ -612,7 +641,7 @@ handle_pragma (cpp_reader* reader,
return;
}
- val = TREE_STRING_POINTER (t);
+ val = string (TREE_STRING_POINTER (t));
if (pragma_lex (&t) != CPP_CLOSE_PAREN)
{
@@ -648,16 +677,26 @@ handle_pragma (cpp_reader* reader,
tt = pragma_lex (&t);
- // An empty options specifier signals options reset.
- //
if (tt == CPP_STRING)
{
- val = TREE_STRING_POINTER (t);
+ string o (TREE_STRING_POINTER (t));
+
+ // Ignore empty options strings. Internally, we use them to
+ // indicate options reset (see below).
+ //
+ if (!o.empty ())
+ val = string (TREE_STRING_POINTER (t));
+
tt = pragma_lex (&t);
}
- // Empty options specifier signals options reset.
- //
- else if (tt != CPP_CLOSE_PAREN)
+ else if (tt == CPP_CLOSE_PAREN)
+ {
+ // Empty options specifier signals options reset. Encode it as an
+ // empty string.
+ //
+ val = string ();
+ }
+ else
{
error () << "options string expected in db pragma " << p << endl;
return;
@@ -669,7 +708,7 @@ handle_pragma (cpp_reader* reader,
return;
}
- mode = pragma::accumulate;
+ adder = &accumulate<string>;
tt = pragma_lex (&t);
}
else if (p == "type" ||
@@ -704,7 +743,7 @@ handle_pragma (cpp_reader* reader,
return;
}
- val = TREE_STRING_POINTER (t);
+ val = string (TREE_STRING_POINTER (t));
if (pragma_lex (&t) != CPP_CLOSE_PAREN)
{
@@ -756,34 +795,41 @@ handle_pragma (cpp_reader* reader,
tt = pragma_lex (&t);
- // Encode the kind of value we have in the first letter of
- // the string.
- //
+ default_value dv;
+
switch (tt)
{
case CPP_CLOSE_PAREN:
{
- // Default value override.
+ // Default value reset.
//
+ dv.kind = default_value::reset;
break;
}
case CPP_STRING:
{
- val = "s";
- val += TREE_STRING_POINTER (t);
+ dv.kind = default_value::string;
+ dv.value = TREE_STRING_POINTER (t);
tt = pragma_lex (&t);
break;
}
case CPP_NAME:
{
- // This can be the null, true, or false keyword or a enumerator
+ // This can be the null, true, or false keyword or an enumerator
// name.
//
string n (IDENTIFIER_POINTER (t));
- if (n == "null" || n == "true" || n == "false")
+ if (n == "null")
{
- val = n[0];
+ dv.kind = default_value::null;
+ tt = pragma_lex (&t);
+ break;
+ }
+ else if (n == "true" || n == "false")
+ {
+ dv.kind = default_value::boolean;
+ dv.value = n;
tt = pragma_lex (&t);
break;
}
@@ -793,26 +839,27 @@ handle_pragma (cpp_reader* reader,
{
// We have a potentially scopped enumerator name.
//
- string n;
- tree decl (parse_scoped_name (t, tt, n, false, p));
+ dv.node = parse_scoped_name (t, tt, dv.value, false, p);
- if (decl == 0)
+ if (dv.node == 0)
return; // Diagnostics has already been issued.
- node = decl;
- val = "e" + n;
+ dv.kind = default_value::enumerator;
break;
}
case CPP_MINUS:
case CPP_PLUS:
{
- val = (tt == CPP_MINUS ? "-" : "+");
+ if (tt == CPP_MINUS)
+ dv.value = "-";
+
tt = pragma_lex (&t);
if (tt != CPP_NUMBER)
{
- error () << "expected numeric constant after '" << val
- << "' in db pragma " << p << endl;
+ error () << "expected numeric constant after '"
+ << (tt == CPP_MINUS ? "-" : "+") << "' in db pragma "
+ << p << endl;
return;
}
@@ -828,10 +875,8 @@ handle_pragma (cpp_reader* reader,
return;
}
- if (val.empty ())
- val = "+";
-
- node = t;
+ dv.node = t;
+ dv.kind = default_value::number;
tt = pragma_lex (&t);
break;
}
@@ -848,6 +893,7 @@ handle_pragma (cpp_reader* reader,
return;
}
+ val = dv;
tt = pragma_lex (&t);
}
else if (p == "inverse")
@@ -874,7 +920,7 @@ handle_pragma (cpp_reader* reader,
return;
}
- val = IDENTIFIER_POINTER (t);
+ val = string (IDENTIFIER_POINTER (t));
if (pragma_lex (&t) != CPP_CLOSE_PAREN)
{
@@ -914,9 +960,15 @@ handle_pragma (cpp_reader* reader,
return;
}
+ // 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;
+
// Record this pragma.
//
- pragma prag (mode, p, name, val, node, loc, &check_spec_decl_type);
+ pragma prag (p, name, val, loc, &check_spec_decl_type, adder);
if (decl)
decl_pragmas_[decl].insert (prag);
@@ -1073,7 +1125,7 @@ handle_pragma_qualifier (cpp_reader* reader, string const& p)
// Record this pragma.
//
- pragma prag (pragma::override, p, p, "", 0, loc, &check_qual_decl_type);
+ pragma prag (p, p, any (true), loc, &check_qual_decl_type, 0);
if (decl)
decl_pragmas_[decl].insert (prag);
diff --git a/odb/pragma.hxx b/odb/pragma.hxx
index 5ff6165..ba4aab8 100644
--- a/odb/pragma.hxx
+++ b/odb/pragma.hxx
@@ -13,10 +13,11 @@
#include <vector>
#include <string>
+#include <cutl/container/any.hxx>
+#include <cutl/compiler/context.hxx>
+
struct pragma
{
- enum mode_type {override, accumulate};
-
// Check that the pragma is applicable to the declaration. Return true
// on success, complain and return false otherwise.
//
@@ -25,46 +26,50 @@ struct pragma
std::string const& prag_name,
location_t);
- pragma (mode_type m,
- std::string const& pn,
+ // Add the pragma value to the context.
+ //
+ typedef void (*add_func) (cutl::compiler::context&,
+ std::string const& key,
+ cutl::container::any const& value,
+ location_t);
+
+ pragma (std::string const& pn,
std::string const& cn,
- std::string const& v,
- tree n,
+ cutl::container::any const& v,
location_t l,
- check_func c)
- : mode (m),
- pragma_name (pn),
+ check_func c,
+ add_func a)
+ : pragma_name (pn),
context_name (cn),
value (v),
- node (n),
loc (l),
- check (c)
+ check (c),
+ add (a)
{
}
bool
operator< (pragma const& y) const
{
- if (mode == override)
+ if (add == 0)
return pragma_name < y.pragma_name;
else
return pragma_name < y.pragma_name ||
(pragma_name == y.pragma_name && loc < y.loc);
}
- mode_type mode;
std::string pragma_name; // Actual pragma name for diagnostics.
std::string context_name; // Context entry name.
- std::string value;
- tree node;
+ cutl::container::any value;
location_t loc;
check_func check;
+ add_func add;
};
typedef std::vector<pragma> pragma_list;
-// A set of pragmas. Insertion of a pragma with the same name and override
-// mode overrides the old value.
+// A set of pragmas. Insertion of a pragma with the same name and no
+// custom add function overrides the old value.
//
struct pragma_set: std::set<pragma>
{
diff --git a/odb/relational/schema.cxx b/odb/relational/schema.cxx
index c55837e..df871e7 100644
--- a/odb/relational/schema.cxx
+++ b/odb/relational/schema.cxx
@@ -25,56 +25,38 @@ namespace relational
void object_columns::
default_ (semantics::data_member& m)
{
- string s;
- tree n (0);
+ default_value* dv (0);
semantics::type& t (m.type ());
if (m.count ("default"))
- {
- s = m.get<string> ("default");
-
- // Empty string is a default value override which means
- // there is no default value.
- //
- if (s.empty ())
- return;
-
- if (m.count ("default-node"))
- n = m.get<tree> ("default-node");
- }
+ dv = &m.get<default_value> ("default");
else if (t.count ("default"))
- {
- s = t.get<string> ("default");
-
- if (s.empty ())
- return;
-
- if (t.count ("default-node"))
- n = t.get<tree> ("default-node");
- }
+ dv = &t.get<default_value> ("default");
else
return; // No default value for this column.
- // The first letter in the default value string identifies
- // the type of the value. See pragma.cxx for details.
- //
- switch (s[0])
+ switch (dv->kind)
{
- case 'n':
+ case default_value::reset:
+ {
+ // No default value.
+ break;
+ }
+ case default_value::null:
{
default_null (m);
break;
}
- case 't':
- case 'f':
+ case default_value::boolean:
{
- default_bool (m, s[0] == 't');
+ default_bool (m, dv->value == "true");
break;
}
- case '+':
- case '-':
+ case default_value::number:
{
+ tree n (dv->node);
+
switch (TREE_CODE (n))
{
case INTEGER_CST:
@@ -88,7 +70,7 @@ namespace relational
unsigned long long v ((h << width) + l);
- default_integer (m, v, s[0] == '-');
+ default_integer (m, v, dv->value == "-");
break;
}
case REAL_CST:
@@ -109,7 +91,7 @@ namespace relational
is >> v;
}
- if (s[0] == '-')
+ if (dv->value == "-")
v = -v;
default_float (m, v);
@@ -120,19 +102,16 @@ namespace relational
}
break;
}
-
- case 's':
+ case default_value::string:
{
- default_string (m, string (s, 1, string::npos));
+ default_string (m, dv->value);
break;
}
- case 'e':
+ case default_value::enumerator:
{
- default_enum (m, n, string (s, 1, string::npos));
+ default_enum (m, dv->node, dv->value);
break;
}
- default:
- assert (false);
}
}
diff --git a/odb/relational/type-processor.cxx b/odb/relational/type-processor.cxx
index 14b546e..a74af9b 100644
--- a/odb/relational/type-processor.cxx
+++ b/odb/relational/type-processor.cxx
@@ -411,7 +411,7 @@ namespace relational
// Mark id column as not null.
//
- t.set ("id-not-null", string ());
+ t.set ("id-not-null", true);
// Get the value type.
//
@@ -465,7 +465,7 @@ namespace relational
throw generation_failed ();
}
else
- t.set ("value-not-null", string ());
+ t.set ("value-not-null", true);
}
// Issue a warning if we are relaxing null-ness in the
@@ -517,7 +517,7 @@ namespace relational
t.set ("index-tree-type", it);
t.set ("index-tree-hint", ih);
- t.set ("index-not-null", string ());
+ t.set ("index-not-null", true);
}
// Get the key type for maps.
@@ -559,7 +559,7 @@ namespace relational
t.set ("key-tree-type", kt);
t.set ("key-tree-hint", kh);
- t.set ("key-not-null", string ());
+ t.set ("key-not-null", true);
}
}
@@ -581,7 +581,7 @@ namespace relational
// no concept of order in this construct.
//
if (ck == ck_ordered && m.count ("value-inverse"))
- m.set ("unordered", string ()); // Keep compatible with pragma.
+ m.set ("unordered", true);
// Issue an error if we have a null column in a set container.
// This can only happen if the value is declared as null in
@@ -1110,33 +1110,24 @@ namespace relational
virtual void
traverse_view (type& c)
{
- // Convert referenced objects from tree nodes to semantic graph
+ // Resolve referenced objects from tree nodes to semantic graph
// nodes.
//
if (c.count ("objects"))
{
using semantics::class_;
+ typedef vector<view_object> objects;
- typedef vector<tree> tree_nodes;
- typedef vector<class_*> class_nodes;
+ objects& objs (c.get<objects> ("objects"));
- strings names (c.get<strings> ("objects"));
- tree_nodes tnodes (c.get<tree_nodes> ("objects-node"));
-
- c.remove ("objects");
- c.remove ("objects-node");
-
- c.set ("objects", class_nodes ());
- class_nodes& nodes (c.get<class_nodes> ("objects"));
-
- for (size_t i (0); i < names.size (); ++i)
+ for (objects::iterator i (objs.begin ()); i < objs.end (); ++i)
{
- tree n (TYPE_MAIN_VARIANT (tnodes[i]));
+ tree n (TYPE_MAIN_VARIANT (i->node));
if (TREE_CODE (n) != RECORD_TYPE)
{
os << c.file () << ":" << c.line () << ":" << c.column () << ":"
- << " error: name '" << names[i] << "' in db pragma object "
+ << " error: name '" << i->name << "' in db pragma object "
<< " does not name a class" << endl;
throw generation_failed ();
@@ -1147,17 +1138,17 @@ namespace relational
if (!object (o))
{
os << c.file () << ":" << c.line () << ":" << c.column () << ":"
- << " error: name '" << names[i] << "' in db pragma object "
+ << " error: name '" << i->name << "' in db pragma object "
<< "does not name a persistent class" << endl;
os << o.file () << ":" << o.line () << ":" << o.column () << ":"
- << " info: class '" << names[i] << "' is defined here"
+ << " info: class '" << i->name << "' is defined here"
<< endl;
throw generation_failed ();
}
- nodes.push_back (&o);
+ i->object = &o;
}
}
}
diff --git a/odb/validator.cxx b/odb/validator.cxx
index 0494741..bf7784e 100644
--- a/odb/validator.cxx
+++ b/odb/validator.cxx
@@ -24,16 +24,16 @@ namespace
if (n.count (p + "null") && n.count (p + "not-null"))
{
- if (n.get<location_t> (p + "null-loc") <
- n.get<location_t> (p + "not-null-loc"))
+ if (n.get<location_t> (p + "null-location") <
+ n.get<location_t> (p + "not-null-location"))
{
n.remove (p + "null");
- n.remove (p + "null-loc");
+ n.remove (p + "null-location");
}
else
{
n.remove (p + "not-null");
- n.remove (p + "not-null-loc");
+ n.remove (p + "not-null-location");
}
}
}
@@ -334,7 +334,7 @@ namespace
valid_ = false;
}
else
- id->set ("not-null", string ());
+ id->set ("not-null", true);
}
// Check members.