From 49d5628e35593a5300d39596286c768d7aa435b6 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 7 Jul 2015 09:18:22 +0200 Subject: Rework module architecture Now the target type and rule maps are in scopes (builtins -- in global scope). We also now have the map of loaded modules in the root scope of each project. --- build/scope.cxx | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) (limited to 'build/scope.cxx') diff --git a/build/scope.cxx b/build/scope.cxx index 5bd2b62..4645979 100644 --- a/build/scope.cxx +++ b/build/scope.cxx @@ -4,6 +4,8 @@ #include +#include + using namespace std; namespace build @@ -40,6 +42,104 @@ namespace build return r; } + const target_type* scope:: + find_target_type (const char* 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; + } + + 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 char* tt; + if (n.type.empty ()) + { + // Empty name or '.' and '..' signify a directory. + // + if (v.empty () || v == "." || v == "..") + tt = "dir"; + else + //@@ TODO: derive type from extension. + // + tt = "file"; + } + else + tt = n.type.c_str (); + + 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 () || r->is_a ()) + { + // 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; -- cgit v1.1