diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2020-08-10 13:40:27 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2020-08-10 13:40:27 +0200 |
commit | 9d8ba565d1fd454369506a525997fceb5adae349 (patch) | |
tree | da10d155660ff59cfd82ee7bb45d4503e26c198d | |
parent | 600da2b97e937b9c96791c291cb5e08cd8526bdd (diff) |
Allow holes in group_view array
-rw-r--r-- | libbuild2/algorithm.cxx | 10 | ||||
-rw-r--r-- | libbuild2/target.hxx | 8 | ||||
-rw-r--r-- | libbuild2/target.ixx | 35 | ||||
-rw-r--r-- | libbuild2/target.txx | 10 |
4 files changed, 50 insertions, 13 deletions
diff --git a/libbuild2/algorithm.cxx b/libbuild2/algorithm.cxx index e1f30e0..75540ff 100644 --- a/libbuild2/algorithm.cxx +++ b/libbuild2/algorithm.cxx @@ -2390,8 +2390,16 @@ namespace build2 group_view gv (g.group_members (a)); if (gv.count != 0) { - ep = gv.members[0]->as<file> ().path () + ".d"; + for (size_t i (0); i != gv.count; ++i) + { + if (const target* m = gv.members[i]) + { + ep = m->as<file> ().path () + ".d"; + break; + } + } + assert (!ep.empty ()); if (rmfile (ctx, ep, 3)) er = target_state::changed; } diff --git a/libbuild2/target.hxx b/libbuild2/target.hxx index 55b8270..17a99d3 100644 --- a/libbuild2/target.hxx +++ b/libbuild2/target.hxx @@ -55,6 +55,14 @@ namespace build2 // A view of target group members. // + // Note that the members array may have "holes" (NULL pointers) and count is + // the number of elements in this array (and not necessarily the number of + // group members). + // + // Note that members being NULL and count being 0 have different meaning: + // the former means group members are not known while the latter means it's + // an empty group. + // struct group_view { const target* const* members; // NULL means not yet known. diff --git a/libbuild2/target.ixx b/libbuild2/target.ixx index 94c54c0..f9db558 100644 --- a/libbuild2/target.ixx +++ b/libbuild2/target.ixx @@ -399,9 +399,14 @@ namespace build2 if (k_ == nullptr && g_.count != 0) // Iterating over a normal group. { - if (g_.members == nullptr || // Special case, see leave_group(). - ++j_ > g_.count) + if (g_.members == nullptr) // Special case, see leave_group(). g_.count = 0; + else + { + for (++j_; j_ <= g_.count && g_.members[j_ - 1] == nullptr; ++j_) ; + if (j_ > g_.count) + g_.count = 0; + } } if (k_ == nullptr && g_.count == 0) // Iterating over the range. @@ -443,8 +448,11 @@ namespace build2 return false; } - if (g_.count != 0) // Group is not empty. - j_ = 0; // Account for the increment that will follow. + // Note: 0-based to account for the increment that will follow. + // + for (j_ = 0; j_ != g_.count && g_.members[j_] == nullptr; ++j_) ; + if (j_ == g_.count) + g_.count = 0; } return true; @@ -474,10 +482,21 @@ namespace build2 inline bool prerequisite_members_range<T>::iterator:: group () const { - return - k_ != nullptr ? k_->adhoc_member != nullptr : /* ad hoc */ - g_.count != 0 ? g_.members != nullptr && j_ < g_.count : /* explicit */ - false; + // Ad hoc. + // + if (k_ != nullptr) + return k_->adhoc_member; + + // Explicit. + // + if (g_.count != 0 && g_.members != nullptr) + { + size_t j (j_ + 1); + for (; j <= g_.count && g_.members[j - 1] == nullptr; ++j) ; + return j <= g_.count; + } + + return false; } inline auto diff --git a/libbuild2/target.txx b/libbuild2/target.txx index 777653a..d304daa 100644 --- a/libbuild2/target.txx +++ b/libbuild2/target.txx @@ -28,11 +28,13 @@ namespace build2 return; } - if (g_.count != 0) // Skip empty see through groups. - { - j_ = 1; // Start from the first group member. + // Skip empty see through groups. + // + for (j_ = 1; j_ <= g_.count && g_.members[j_ - 1] == nullptr; ++j_) ; + if (j_ <= g_.count) break; - } + + g_.count = 0; } while (++i_ != r_->e_ && i_->type.see_through); } |