aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build/algorithm.cxx4
-rw-r--r--build/dump.cxx97
-rw-r--r--build/scope4
-rw-r--r--build/target5
-rw-r--r--build/target-type6
-rw-r--r--build/target.cxx45
-rw-r--r--build/variable10
7 files changed, 145 insertions, 26 deletions
diff --git a/build/algorithm.cxx b/build/algorithm.cxx
index 615d4b7..bf10b84 100644
--- a/build/algorithm.cxx
+++ b/build/algorithm.cxx
@@ -85,9 +85,7 @@ namespace build
size_t oi (o - 1); // Operation index in rule_map.
scope& bs (t.base_scope ());
- for (auto tt (&t.type ());
- tt != nullptr && !t.recipe (ra);
- tt = tt->base)
+ for (auto tt (&t.type ()); tt != nullptr; tt = tt->base)
{
// Search scopes outwards, stopping at the project root.
//
diff --git a/build/dump.cxx b/build/dump.cxx
index 6b6debe..e426f0b 100644
--- a/build/dump.cxx
+++ b/build/dump.cxx
@@ -18,32 +18,76 @@ using namespace std;
namespace build
{
- static bool
- dump_variables (ostream& os, string& ind, const variable_map& vars)
+ static void
+ dump_variable (ostream& os, const variable& var, const value_ptr& val)
{
- bool r (false);
+ os << var.name << " = ";
- for (const auto& e: vars)
+ if (val == nullptr)
+ os << "[null]";
+ else
{
- const variable& var (e.first);
- const value_ptr& val (e.second);
+ //@@ TODO: assuming it is a list.
+ //
+ os << dynamic_cast<list_value&> (*val);
+ }
+ }
+ static void
+ dump_variables (ostream& os, string& ind, const variable_map& vars)
+ {
+ for (const auto& e: vars)
+ {
os << endl
- << ind << var.name << " = ";
+ << ind;
- if (val == nullptr)
- os << "[null]";
- else
+ dump_variable (os, e.first, e.second);
+ }
+ }
+
+ static void
+ dump_variables (ostream& os, string& ind, const variable_type_map& vtm)
+ {
+ for (const auto& vt: vtm)
+ {
+ const target_type& t (vt.first);
+ const variable_pattern_map& vpm (vt.second);
+
+ for (const auto& vp: vpm)
{
- //@@ TODO: assuming it is a list.
- //
- os << dynamic_cast<list_value&> (*val);
- }
+ const string p (vp.first);
+ const variable_map& vars (vp.second);
- r = true;
- }
+ os << endl
+ << ind;
+
+ if (t.id != target::static_type.id)
+ os << t.name << '{';
+
+ os << p;
+
+ if (t.id != target::static_type.id)
+ os << '}';
+
+ os << ':';
- return r;
+ if (vars.size () == 1)
+ {
+ os << ' ';
+ dump_variable (os, vars.begin ()->first, vars.begin ()->second);
+ }
+ else
+ {
+ os << endl
+ << ind << '{';
+ ind += " ";
+ dump_variables (os, ind, vars);
+ ind.resize (ind.size () - 2);
+ os << endl
+ << ind << '}';
+ }
+ }
+ }
}
static void
@@ -120,9 +164,24 @@ namespace build
bool vb (false), sb (false); // Variable/scope block.
- // Variables.
+ // Target type/pattern-sepcific variables.
+ //
+ if (!p.target_vars.empty ())
+ {
+ dump_variables (os, ind, p.target_vars);
+ vb = true;
+ }
+
+ // Scope variables.
//
- vb = dump_variables (os, ind, p.vars);
+ if (!p.vars.empty ())
+ {
+ if (vb)
+ os << endl;
+
+ dump_variables (os, ind, p.vars);
+ vb = true;
+ }
// Nested scopes of which we are a parent.
//
diff --git a/build/scope b/build/scope
index eb2dafc..9fb8061 100644
--- a/build/scope
+++ b/build/scope
@@ -104,6 +104,10 @@ namespace build
return append (variable_pool.find (name));
}
+ // Target type/pattern-specific variables.
+ //
+ variable_type_map target_vars;
+
// Prerequisite cache.
//
public:
diff --git a/build/target b/build/target
index 6ee65f4..f777268 100644
--- a/build/target
+++ b/build/target
@@ -259,8 +259,9 @@ namespace build
variable_map vars;
// Lookup, including in groups to which this target belongs and
- // then in outer scopes. If you only want to lookup in this target,
- // do it on the the variables map directly.
+ // then in outer scopes (including target type/pattern-specific
+ // variables). If you only want to lookup in this target, do it
+ // on the the variable map directly.
//
value_proxy
operator[] (const variable&) const;
diff --git a/build/target-type b/build/target-type
index d5e7971..154714c 100644
--- a/build/target-type
+++ b/build/target-type
@@ -42,6 +42,12 @@ namespace build
is_a () const {return is_a (typeid (T));}
};
+ inline bool
+ operator< (const target_type& x, const target_type& y)
+ {
+ return x.id < y.id;
+ }
+
inline std::ostream&
operator<< (std::ostream& os, const target_type& tt)
{
diff --git a/build/target.cxx b/build/target.cxx
index df7e2aa..cdcc6b0 100644
--- a/build/target.cxx
+++ b/build/target.cxx
@@ -85,7 +85,50 @@ namespace build
if (group != nullptr)
return (*group)[var];
- return base_scope ()[var];
+ // Cannot simply delegate to scope's operator[] since we also
+ // need to check target type/pattern-specific variables.
+ //
+ const target_type& btt (type ());
+
+ for (const scope* s (&base_scope ()); s != nullptr; s = s->parent_scope ())
+ {
+ if (!s->target_vars.empty ())
+ {
+ // Search across target type hierarchy.
+ //
+ for (auto tt (&btt); tt != nullptr; tt = tt->base)
+ {
+ auto i (s->target_vars.find (*tt));
+
+ if (i == s->target_vars.end ())
+ continue;
+
+ //@@ TODO: match pattern. For now, we only handle '*'.
+
+ auto j (i->second.find ("*"));
+
+ if (j == i->second.end ())
+ continue;
+
+ auto k (j->second.find (var));
+
+ if (k != j->second.end ())
+ {
+ // Note that we use the scope's vars, not from target_vars.
+ // We use it to identify whether the variable belongs to a
+ // specific scope/target.
+ //
+ return value_proxy (&const_cast<value_ptr&> (k->second), &s->vars);
+ }
+ }
+ }
+
+ auto i (s->vars.find (var));
+ if (i != s->vars.end ())
+ return value_proxy (&const_cast<value_ptr&> (i->second), &s->vars);
+ }
+
+ return value_proxy (nullptr, nullptr);
}
value_proxy target::
diff --git a/build/variable b/build/variable
index 809e7d2..998a853 100644
--- a/build/variable
+++ b/build/variable
@@ -5,18 +5,20 @@
#ifndef BUILD_VARIABLE
#define BUILD_VARIABLE
+#include <map>
#include <string>
#include <memory> // unique_ptr
#include <cstddef> // nullptr_t
#include <utility> // move(), pair, make_pair()
#include <cassert>
-#include <functional> // hash
+#include <functional> // hash, reference_wrapper
#include <typeindex>
#include <unordered_set>
#include <butl/prefix-map>
#include <build/types>
+#include <build/target-type>
namespace build
{
@@ -340,6 +342,12 @@ namespace build
return find_prefix (variable_pool.find (ns));
}
};
+
+ // Target type/pattern-specific variables.
+ //
+ using variable_pattern_map = std::map<std::string, variable_map>;
+ using variable_type_map = std::map<std::reference_wrapper<const target_type>,
+ variable_pattern_map>;
}
#include <build/variable.ixx>