aboutsummaryrefslogtreecommitdiff
path: root/build/target.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'build/target.cxx')
-rw-r--r--build/target.cxx140
1 files changed, 109 insertions, 31 deletions
diff --git a/build/target.cxx b/build/target.cxx
index 6fdfb7b..f09a858 100644
--- a/build/target.cxx
+++ b/build/target.cxx
@@ -13,39 +13,12 @@ using namespace std;
namespace build
{
- // target_type
- //
- const target_type*
- resolve_target_type (const std::string name);
-
// target
//
ostream&
operator<< (ostream& os, const target& t)
{
- os << t.type ().name << '{';
-
- if (!t.dir.empty ())
- {
- string s (diag_relative_work (t.dir));
-
- if (s != ".")
- {
- os << s;
-
- if (!t.name.empty () && s.back () != path::traits::directory_separator)
- os << path::traits::directory_separator;
- }
- }
-
- os << t.name;
-
- if (t.ext != nullptr && !t.ext->empty ())
- os << '.' << *t.ext;
-
- os << '}';
-
- return os;
+ return os << target_set::key {&t.type (), &t.dir, &t.name, &t.ext};
}
static target*
@@ -59,6 +32,8 @@ namespace build
// target_set
//
+ target_set targets;
+
auto target_set::
find (const key& k, tracer& trace) const -> iterator
{
@@ -99,22 +74,125 @@ namespace build
const std::string* ext,
tracer& trace)
{
- iterator i (find (key {&tt.id, &dir, &name, &ext}, trace));
+ iterator i (find (key {&tt, &dir, &name, &ext}, trace));
if (i != end ())
return pair<target&, bool> (**i, false);
unique_ptr<target> t (tt.factory (move (dir), move (name), ext));
i = map_.emplace (
- make_pair (key {&tt.id, &t->dir, &t->name, &t->ext},
+ make_pair (key {&tt, &t->dir, &t->name, &t->ext},
move (t))).first;
return pair<target&, bool> (**i, true);
}
- target_set targets;
+ ostream&
+ operator<< (ostream& os, const target_set::key& k)
+ {
+ os << k.type->name << '{';
+
+ if (!k.dir->empty ())
+ {
+ string s (diag_relative_work (*k.dir));
+
+ if (s != ".")
+ {
+ os << s;
+
+ if (!k.name->empty () &&
+ s.back () != path::traits::directory_separator)
+ os << path::traits::directory_separator;
+ }
+ }
+
+ os << *k.name;
+
+ if (*k.ext != nullptr && !(*k.ext)->empty ())
+ os << '.' << **k.ext;
+
+ os << '}';
+
+ return os;
+ }
+
+ //
+ //
target_type_map target_types;
+ const target_type* target_type_map::
+ find (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 ();
+
+ auto i (find (tt));
+ if (i == end ())
+ return nullptr;
+
+ const target_type& ti (i->second);
+
+ // Directories require special name processing. If we find that more
+ // targets deviate, then we should make this target-type-specific.
+ //
+ if (ti.id == dir::static_type.id || ti.id == fsdir::static_type.id)
+ {
+ // The canonical representation of a directory name is with empty
+ // value.
+ //
+ if (!v.empty ())
+ {
+ n.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 /= 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 &ti;
+ }
+
// path_target
//
timestamp path_target::