aboutsummaryrefslogtreecommitdiff
path: root/build/target.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'build/target.cxx')
-rw-r--r--build/target.cxx56
1 files changed, 46 insertions, 10 deletions
diff --git a/build/target.cxx b/build/target.cxx
index 9b20273..22c9ad4 100644
--- a/build/target.cxx
+++ b/build/target.cxx
@@ -137,7 +137,7 @@ namespace build
{
if (!s->target_vars.empty ())
{
- auto find_specific = [&var, s] (const target& t) -> result
+ auto find_specific = [this, &var, s] (const target& t) -> result
{
// Search across target type hierarchy.
//
@@ -148,15 +148,51 @@ namespace build
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;
-
- if (auto p = j->second.find (var))
- return result (p, &j->second);
+ // Try to match the pattern, starting from the longest values
+ // so that the more "specific" patterns (i.e., those that cover
+ // fewer characters with the wildcard) take precedence. See
+ // tests/variable/type-pattern.
+ //
+ const variable_pattern_map& m (i->second);
+
+ for (auto j (m.rbegin ()); j != m.rend (); ++j)
+ {
+ const string& p (j->first);
+
+ size_t nn (name.size ());
+ size_t pn (p.size ());
+
+ if (nn < pn - 1) // One for '*'.
+ continue;
+
+ size_t w (p.find ('*'));
+ assert (w != string::npos);
+
+ // Compare prefix.
+ //
+ if (w != 0 &&
+ name.compare (0, w, p, 0, w) != 0)
+ continue;
+
+ ++w; // First suffix character.
+ pn -= w; // Suffix length.
+
+ // Compare suffix.
+ //
+ if (pn != 0 &&
+ name.compare (nn - pn, pn, p, w, pn) != 0)
+ continue;
+
+ // Ok, this pattern matches. But is there a variable?
+ //
+ if (const value* v = j->second.find (var))
+ {
+ //@@ TODO: should we detect ambiguity? 'foo-*' '*-foo' and
+ // 'foo-foo'? Right now the last defined will be used.
+ //
+ return result (v, &j->second);
+ }
+ }
}
return result ();