aboutsummaryrefslogtreecommitdiff
path: root/build2/target.ixx
blob: e2ac111793d246bb970fad0b81cd0af5759a29e9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// file      : build2/target.ixx -*- C++ -*-
// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
// license   : MIT; see accompanying LICENSE file

namespace build2
{
  // prerequisite_member
  //
  inline prerequisite prerequisite_member::
  as_prerequisite () const
  {
    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 ());

    return prerequisite_type (*target);
  }

  // prerequisite_members
  //
  group_view
  resolve_group_members (action, target&); // <build2/algorithm>

  template <typename T>
  inline auto prerequisite_members_range<T>::iterator::
  operator++ () -> iterator&
  {
    if (k_ != nullptr) // Iterating over an ad hoc group.
      k_ = k_->member;
    else if (r_->members_)
    {
      // 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.
      //
      target* t (g_.count != 0
                 ? j_ != 0 ? g_.members[j_ - 1] : nullptr // enter_group()
                 : i_->target);
      if (t != nullptr && t->member != nullptr)
        k_ = t->member;
    }

    if (k_ == nullptr && g_.count != 0) // Iterating over a normal group.
    {
      if (g_.members == nullptr || // leave_group()
          ++j_ > g_.count)
        g_.count = 0;
    }

    if (k_ == nullptr && g_.count == 0) // Iterating over the range.
    {
      ++i_;

      if (r_->members_ && i_ != r_->e_ && i_->type.see_through)
        switch_mode ();
    }

    return *this;
  }

  template <typename T>
  inline bool prerequisite_members_range<T>::iterator::
  enter_group ()
  {
    // 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_->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 (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.
    }


    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_->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;
      g_.members = nullptr; // Ugly "special case signal" for operator++.
    }
  }
}