aboutsummaryrefslogtreecommitdiff
path: root/build2/target.ixx
diff options
context:
space:
mode:
Diffstat (limited to 'build2/target.ixx')
-rw-r--r--build2/target.ixx95
1 files changed, 74 insertions, 21 deletions
diff --git a/build2/target.ixx b/build2/target.ixx
index d89ed08..5cf5ca9 100644
--- a/build2/target.ixx
+++ b/build2/target.ixx
@@ -21,6 +21,11 @@ namespace build2
if (target == nullptr)
return prerequisite;
+ // An ad hoc group member cannot be used as a prerequisite (use the whole
+ // group instead).
+ //
+ assert (!target->adhoc_member ());
+
// The use of the group's prerequisite scope is debatable.
//
scope& s (prerequisite.get ().scope);
@@ -36,24 +41,32 @@ namespace build2
inline auto prerequisite_members_range<T>::iterator::
operator++ () -> iterator&
{
- if (g_.count != 0)
+ if (k_ != nullptr) // Iterating over an ad hoc group.
+ k_ = k_->member;
+ else if (r_->members_)
{
- if (++j_ <= g_.count)
- return *this;
-
- // Switch back to prerequisite iteration mode.
+ // Get the target if one has been resolved and see if it's an ad hoc
+ // group. If so, switch to the ad hoc mode.
//
- g_.count = 0;
+ target* t (g_.count != 0
+ ? j_ != 0 ? g_.members[j_ - 1] : nullptr // enter_group()
+ : i_->get ().target);
+ if (t != nullptr && t->member != nullptr)
+ k_ = t->member;
}
- ++i_;
+ if (k_ == nullptr && g_.count != 0) // Iterating over a normal group.
+ {
+ if (++j_ > g_.count)
+ g_.count = 0;
+ }
- // Switch to member iteration mode.
- //
- if (r_->members_ && i_ != r_->e_ && i_->get ().type.see_through)
+ if (k_ == nullptr && g_.count == 0) // Iterating over the range.
{
- bool r (switch_members ());
- assert (r); // Group could not be resolved.
+ ++i_;
+
+ if (r_->members_ && i_ != r_->e_ && i_->get ().type.see_through)
+ switch_mode ();
}
return *this;
@@ -61,25 +74,65 @@ namespace build2
template <typename T>
inline bool prerequisite_members_range<T>::iterator::
- switch_members ()
+ enter_group ()
{
- do
+ // First see if we are about to enter an ad hoc group (the same code as in
+ // operator++() above).
+ //
+ target* t (g_.count != 0
+ ? j_ != 0 ? g_.members[j_ - 1] : nullptr
+ : i_->get ().target);
+
+ if (t != nullptr && t->member != nullptr)
+ k_ = t->member;
+ else
{
+ // Otherwise assume it is a normal group.
+ //
g_ = resolve_group_members (r_->a_, search (*i_));
- // If members are not know, iterate over the group as itself.
- //
- if (g_.members == nullptr)
+ if (g_.members == nullptr) // Members are not know.
{
g_.count = 0;
return false;
}
+
+ if (g_.count != 0) // Group is not empty.
+ j_ = 0; // Account for the increment that will follow.
}
- while (g_.count == 0 && // Skip empty groups.
- ++i_ != r_->e_ &&
- i_->get ().type.see_through);
- j_ = 1; // Start from the first group member.
+
return true;
}
+
+ template <typename T>
+ inline void prerequisite_members_range<T>::iterator::
+ leave_group ()
+ {
+ // First see if we are about to enter an ad hoc group (the same code as in
+ // operator++() above).
+ //
+ if (k_ == nullptr)
+ {
+ target* t (g_.count != 0
+ ? j_ != 0 ? g_.members[j_ - 1] : nullptr
+ : i_->get ().target);
+ if (t != nullptr && t->member != nullptr)
+ k_ = t->member;
+ }
+
+ if (k_ != nullptr)
+ {
+ // Skip until the last element (next increment will reach the end).
+ //
+ for (; k_->member != nullptr; k_ = k_->member) ;
+ }
+ else
+ {
+ // Pretend we are on the last member of a normal group.
+ //
+ j_ = 0;
+ g_.count = 1;
+ }
+ }
}