aboutsummaryrefslogtreecommitdiff
path: root/build2/in
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2018-07-20 15:31:13 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2018-07-20 16:10:26 +0200
commitc1dc06dfd1d329f8c6499dbe2166725ab9c35e17 (patch)
tree97449ae7263490473a833944cfeb3d889a2f580d /build2/in
parentb4286df8c9bafdab1934cef99ccc0506ec4555e2 (diff)
Implement bash module
Diffstat (limited to 'build2/in')
-rw-r--r--build2/in/init.cxx2
-rw-r--r--build2/in/rule.cxx155
-rw-r--r--build2/in/rule.hxx23
-rw-r--r--build2/in/target.cxx2
4 files changed, 111 insertions, 71 deletions
diff --git a/build2/in/init.cxx b/build2/in/init.cxx
index a87f8b3..2583456 100644
--- a/build2/in/init.cxx
+++ b/build2/in/init.cxx
@@ -91,7 +91,7 @@ namespace build2
// Register rules.
//
{
- auto& r (rs.rules);
+ auto& r (bs.rules);
// There are rules that are "derived" from this generic in rule in
// order to provide extended preprocessing functionality (see the
diff --git a/build2/in/rule.cxx b/build2/in/rule.cxx
index 6be2e71..41f2f71 100644
--- a/build2/in/rule.cxx
+++ b/build2/in/rule.cxx
@@ -66,7 +66,15 @@ namespace build2
// Match prerequisite members.
//
- match_prerequisite_members (a, t);
+ match_prerequisite_members (a,
+ t,
+ [this] (action a,
+ const target& t,
+ const prerequisite_member& p,
+ include_type i)
+ {
+ return search (a, t, p, i);
+ });
switch (a)
{
@@ -79,66 +87,6 @@ namespace build2
}
}
- string rule::
- lookup (const location& l, const target& t, const string& n) const
- {
- if (auto x = t[n])
- {
- value v (*x);
-
- // For typed values call string() for conversion.
- //
- try
- {
- return convert<string> (
- v.type == nullptr
- ? move (v)
- : functions.call (&t.base_scope (),
- "string",
- vector_view<value> (&v, 1),
- l));
- }
- catch (const invalid_argument& e)
- {
- fail (l) << e <<
- info << "while substituting '" << n << "'" << endf;
- }
- }
- else
- fail (l) << "undefined variable '" << n << "'" << endf;
- }
-
- optional<string> rule::
- substitute (const location& l,
- const target& t,
- const string& n,
- bool strict) const
- {
- // In the lax mode scan the fragment to make sure it is a variable name
- // (that is, it can be expanded in a buildfile as just $<name>; see
- // lexer's variable mode for details).
- //
- if (!strict)
- {
- for (size_t i (0), e (n.size ()); i != e; )
- {
- bool f (i == 0); // First.
- char c (n[i++]);
- bool l (i == e); // Last.
-
- if (c == '_' || (f ? alpha (c) : alnum (c)))
- continue;
-
- if (c == '.' && !l)
- continue;
-
- return nullopt; // Ignore this substitution.
- }
- }
-
- return lookup (l, t, n);
- }
-
target_state rule::
perform_update (action a, const target& xt) const
{
@@ -265,9 +213,18 @@ namespace build2
if (p1 != string::npos && p2 != string::npos && p2 - p1 > 1)
{
string n (*s, p1 + 1, p2 - p1 - 1);
- string v (lookup (location (&ip, ln), t, n));
- if (s->compare (p2 + 1, string::npos, sha256 (v).string ()) == 0)
+ // Note that we have to call substitute(), not lookup() since it
+ // can be overriden with custom substitution semantics.
+ //
+ optional<string> v (
+ substitute (location (&ip, ln), a, t, n, strict));
+
+ assert (v); // Rule semantics change without version increment?
+
+ if (s->compare (p2 + 1,
+ string::npos,
+ sha256 (*v).string ()) == 0)
{
dd_skip++;
continue;
@@ -391,7 +348,7 @@ namespace build2
// pointing to the opening symbol and e -- to the closing.
//
string name (s, b + 1, e - b -1);
- if (optional<string> val = substitute (l, t, name, strict))
+ if (optional<string> val = substitute (l, a, t, name, strict))
{
// Save in depdb.
//
@@ -444,5 +401,75 @@ namespace build2
t.mtime (system_clock::now ());
return target_state::changed;
}
+
+ prerequisite_target rule::
+ search (action,
+ const target& t,
+ const prerequisite_member& p,
+ include_type i) const
+ {
+ return prerequisite_target (&build2::search (t, p), i);
+ }
+
+ string rule::
+ lookup (const location& l, action, const target& t, const string& n) const
+ {
+ if (auto x = t[n])
+ {
+ value v (*x);
+
+ // For typed values call string() for conversion.
+ //
+ try
+ {
+ return convert<string> (
+ v.type == nullptr
+ ? move (v)
+ : functions.call (&t.base_scope (),
+ "string",
+ vector_view<value> (&v, 1),
+ l));
+ }
+ catch (const invalid_argument& e)
+ {
+ fail (l) << e <<
+ info << "while substituting '" << n << "'" << endf;
+ }
+ }
+ else
+ fail (l) << "undefined variable '" << n << "'" << endf;
+ }
+
+ optional<string> rule::
+ substitute (const location& l,
+ action a,
+ const target& t,
+ const string& n,
+ bool strict) const
+ {
+ // In the lax mode scan the fragment to make sure it is a variable name
+ // (that is, it can be expanded in a buildfile as just $<name>; see
+ // lexer's variable mode for details).
+ //
+ if (!strict)
+ {
+ for (size_t i (0), e (n.size ()); i != e; )
+ {
+ bool f (i == 0); // First.
+ char c (n[i++]);
+ bool l (i == e); // Last.
+
+ if (c == '_' || (f ? alpha (c) : alnum (c)))
+ continue;
+
+ if (c == '.' && !l)
+ continue;
+
+ return nullopt; // Ignore this substitution.
+ }
+ }
+
+ return lookup (l, a, t, n);
+ }
}
}
diff --git a/build2/in/rule.hxx b/build2/in/rule.hxx
index 17fbaed..9c40e4f 100644
--- a/build2/in/rule.hxx
+++ b/build2/in/rule.hxx
@@ -41,23 +41,38 @@ namespace build2
virtual recipe
apply (action, target&) const override;
+ virtual target_state
+ perform_update (action, const target&) const;
+
+ // Customization hooks.
+ //
+
+ // Perform prerequisite search.
+ //
+ virtual prerequisite_target
+ search (action,
+ const target&,
+ const prerequisite_member&,
+ include_type) const;
+
// Perform variable lookup.
//
virtual string
- lookup (const location&, const target&, const string& name) const;
+ lookup (const location&,
+ action,
+ const target&,
+ const string& name) const;
// Perform variable substitution. Return nullopt if it should be
// ignored.
//
virtual optional<string>
substitute (const location&,
+ action,
const target&,
const string& name,
bool strict) const;
- target_state
- perform_update (action, const target&) const;
-
protected:
const string rule_id_;
const string program_;
diff --git a/build2/in/target.cxx b/build2/in/target.cxx
index ecf975f..fec1135 100644
--- a/build2/in/target.cxx
+++ b/build2/in/target.cxx
@@ -10,8 +10,6 @@ namespace build2
{
namespace in
{
- // in
- //
static const target*
in_search (const target& xt, const prerequisite_key& cpk)
{