diff options
Diffstat (limited to 'build/scope.cxx')
-rw-r--r-- | build/scope.cxx | 317 |
1 files changed, 0 insertions, 317 deletions
diff --git a/build/scope.cxx b/build/scope.cxx deleted file mode 100644 index dfddf20..0000000 --- a/build/scope.cxx +++ /dev/null @@ -1,317 +0,0 @@ -// file : build/scope.cxx -*- C++ -*- -// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd -// license : MIT; see accompanying LICENSE file - -#include <build/scope> - -#include <build/target> - -using namespace std; - -namespace build -{ - // scope - // - lookup<const value> scope:: - lookup (const target_type* tt, const string* name, const variable& var) const - { - using result = build::lookup<const value>; - - for (const scope* s (this); s != nullptr; ) - { - if (tt != nullptr && !s->target_vars.empty ()) - { - if (auto l = s->target_vars.lookup (*tt, *name, var)) - return l; - } - - if (auto r = s->vars.find (var)) - return result (r, &s->vars); - - switch (var.visibility) - { - case variable_visibility::scope: - s = nullptr; - break; - case variable_visibility::project: - s = s->root () ? nullptr : s->parent_scope (); - break; - case variable_visibility::normal: - s = s->parent_scope (); - break; - } - } - - return result (); - } - - value& scope:: - append (const variable& var) - { - auto l (operator[] (var)); - - if (l && l.belongs (*this)) // Existing variable in this scope. - return const_cast<value&> (*l); - - value& r (assign (var)); - - if (l) - r = *l; // Copy value from the outer scope. - - return r; - } - - const target_type* scope:: - find_target_type (const string& tt, const scope** rs) const - { - // Search scopes outwards, stopping at the project root. - // - for (const scope* s (this); - s != nullptr; - s = s->root () ? global_scope : s->parent_scope ()) - { - if (s->target_types.empty ()) - continue; - - auto i (s->target_types.find (tt)); - - if (i != s->target_types.end ()) - { - if (rs != nullptr) - *rs = s; - - return &i->second.get (); - } - } - - return nullptr; - } - - static const string dir_tt ("dir"); - static const string file_tt ("file"); - - const target_type* scope:: - find_target_type (name& n, const string*& ext) const - { - ext = nullptr; - - string& v (n.value); - - // First determine the target type. - // - const string* tt; - if (n.untyped ()) - { - // Empty name or '.' and '..' signify a directory. - // - if (v.empty () || v == "." || v == "..") - tt = &dir_tt; - else - //@@ TODO: derive type from extension. - // - tt = &file_tt; - } - else - tt = &n.type; - - const target_type* r (find_target_type (*tt)); - - if (r == nullptr) - return r; - - // Directories require special name processing. If we find that more - // targets deviate, then we should make this target-type-specific. - // - if (r->is_a<dir> () || r->is_a<fsdir> ()) - { - // The canonical representation of a directory name is with empty - // value. - // - if (!v.empty ()) - { - n.dir /= dir_path (v); // Move name value to dir. - v.clear (); - } - } - else - { - // Split the path into its directory part (if any) the name part, - // and the extension (if any). We cannot assume the name part is - // a valid filesystem name so we will have to do the splitting - // manually. - // - path::size_type i (path::traits::rfind_separator (v)); - - if (i != string::npos) - { - n.dir /= dir_path (v, i != 0 ? i : 1); // Special case: "/". - v = string (v, i + 1, string::npos); - } - - // Extract the extension. - // - string::size_type j (path::traits::find_extension (v)); - - if (j != string::npos) - { - ext = &extension_pool.find (v.c_str () + j + 1); - v.resize (j); - } - } - - return r; - } - - // scope_map - // - scope_map scopes; - scope* global_scope; - - auto scope_map:: - insert (const dir_path& k, scope* ns, bool parent, bool root) -> iterator - { - auto er (map_.emplace (k, nullptr)); - scope*& ps (er.first->second); - - if (er.second) - ps = ns == nullptr ? new scope : ns; - else if (ns != nullptr && ps != ns) - { - assert (ps->out_path_ == nullptr || ps->src_path_ == nullptr); - - if (!ps->empty ()) - fail << "attempt to replace non-empty scope " << k; - - // Un-parent ourselves. We will becomes a new parent below, - // if requested by the caller. - // - auto r (map_.find_prefix (k)); // The first entry is ourselves. - for (++r.first; r.first != r.second; ++r.first) - { - scope& c (*r.first->second); - - if (c.parent_ == ps) // No intermediate parent. - c.parent_ = ps->parent_; - } - - delete ps; - ps = ns; - er.second = true; - } - - scope& s (*ps); - - if (parent) - { - if (er.second) - { - scope* p (nullptr); - - // Update scopes of which we are a new parent/root (unless this - // is the global scope). Also find our parent while at it. - // - if (map_.size () > 1) - { - // The first entry is ourselves. - // - auto r (map_.find_prefix (k)); - for (++r.first; r.first != r.second; ++r.first) - { - scope& c (*r.first->second); - - // The child-parent relationship is based on the out hierarchy, - // thus the extra check. - // - if (c.out_path_ != nullptr && !c.out_path_->sub (k)) - continue; - - // 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.parent_; - - if (root && c.root_ == p->root_) // No intermediate root. - c.root_ = &s; - - if (p == c.parent_) // No intermediate parent. - c.parent_ = &s; - } - - // We couldn't get the parent from one of its old children - // so we have to find it ourselves. - // - if (p == nullptr) - p = &find (k.directory ()); - } - - s.parent_ = p; - s.root_ = root ? &s : (p != nullptr ? p->root_ : nullptr); - } - else if (root && !s.root ()) - { - // Upgrade to root scope. - // - auto r (map_.find_prefix (k)); - for (++r.first; r.first != r.second; ++r.first) - { - scope& c (*r.first->second); - - if (c.root_ == s.root_) // No intermediate root. - c.root_ = &s; - } - - s.root_ = &s; - } - } - else - assert (s.parent_ != nullptr); - - return er.first; - } - - // Find the most qualified scope that encompasses this path. - // - scope& scope_map:: - find (const dir_path& k) const - { - // Normally we would have a scope for the full path so try - // that before making any copies. - // - auto i (map_.find (k)), e (map_.end ()); - - if (i != e) - return *i->second; - - for (dir_path d (k.directory ());; d = d.directory ()) - { - auto i (map_.find (d)); - - if (i != e) - return *i->second; - - assert (!d.empty ()); // We should have the global scope. - } - } - - void scope_map:: - clear () - { - for (auto& p: map_) - { - scope* s (p.second); - - if (s->out_path_ == &p.first) - s->out_path_ = nullptr; - - if (s->src_path_ == &p.first) - s->src_path_ = nullptr; - - if (s->out_path_ == nullptr && s->src_path_ == nullptr) - delete s; - } - - map_.clear (); - } -} |