diff options
Diffstat (limited to 'build2/target.ixx')
-rw-r--r-- | build2/target.ixx | 95 |
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; + } + } } |