aboutsummaryrefslogtreecommitdiff
path: root/build/scope.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'build/scope.cxx')
-rw-r--r--build/scope.cxx66
1 files changed, 66 insertions, 0 deletions
diff --git a/build/scope.cxx b/build/scope.cxx
index 0f99b0e..7165663 100644
--- a/build/scope.cxx
+++ b/build/scope.cxx
@@ -9,4 +9,70 @@ using namespace std;
namespace build
{
scope_map scopes;
+ scope* root_scope;
+
+ scope& scope_map::
+ operator[] (const path& k)
+ {
+ auto er (emplace (k, scope ()));
+ scope& s (er.first->second);
+
+ if (er.second)
+ {
+ scope* p (nullptr);
+
+ // Update scopes of which we are a new parent.
+ //
+ for (auto r (find_prefix (k)); r.first != r.second; ++r.first)
+ {
+ scope& c (r.first->second);
+
+ // The first scope of which we are a parent is the least
+ // (shortest) one which means there is no other scope
+ // between it and our parent.
+ //
+ if (p == nullptr)
+ p = &c;
+ else if (p != &c) // A scope with an intermediate parent.
+ continue;
+
+ c.parent (s);
+ }
+
+ // We couldn't get the parent from one of its old children
+ // so we have to find it ourselves (unless this is is the
+ // root scope).
+ //
+ if (p == nullptr && size () != 1)
+ p = &find (k);
+
+ s.init (er.first, p);
+ }
+
+ return s;
+ }
+
+ // Find the most qualified scope that encompasses this path.
+ //
+ scope& scope_map::
+ find (const path& k)
+ {
+ // Normally we would have a scope for the full path so try
+ // that before making any copies.
+ //
+ auto i (base::find (k));
+
+ if (i != end ())
+ return i->second;
+
+ for (path d (k.directory ());; d = d.directory ())
+ {
+ auto i (base::find (k));
+
+ if (i != end ())
+ return i->second;
+
+ assert (d.empty ()); // We should have the root scope.
+ }
+ }
}