* Bugfix: InstrucIter no longer used for int_function iteration.
[dyninst.git] / dyninstAPI / src / InstrucIter-Function.C
1
2 #include "common/h/Types.h"
3 #include "arch.h"
4 #include "InstrucIter-Function.h"
5 #include "function.h"
6 #include "image-func.h"
7 #include <sstream>
8 #include <ostream>
9 #include <string>
10 #include <algorithm>
11
12
13 InstrucIter makeIter(int_basicBlock* fromThis)
14 {
15   return InstrucIter(fromThis);
16 }
17
18 std::string dumpSubIter(const InstrucIter& dumpIt)
19 {
20   std::stringstream retVal;
21   retVal << "     - " << dumpIt.begin() << ":" << dumpIt.end();
22   return retVal.str();
23 }
24
25
26 void InstrucIterFunction::debugPrint() const
27 {
28   cerr << " *** II_Function contains " << endl;
29   std::transform(subIters.begin(), subIters.end(), 
30                  std::ostream_iterator<std::string>(cerr, "\n"),
31                  dumpSubIter);
32   cerr << " *** Current address is " << **(this) << endl;
33 }
34
35
36 InstrucIterFunction::InstrucIterFunction(int_function* func) : InstrucIter()
37 {
38   assert(func);
39   std::transform(func->blocks().begin(), func->blocks().end(), std::back_inserter(subIters), makeIter);
40   currentBlock = subIters.begin();
41 }
42
43 InstrucIterFunction::InstrucIterFunction(Address start, int_function* func) : InstrucIter()
44 {
45   assert(func);
46   std::transform(func->blocks().begin(), func->blocks().end(), std::back_inserter(subIters), makeIter);
47   setCurrentAddress(start);
48 }
49
50 InstrucIterFunction::InstrucIterFunction(const InstrucIterFunction& ii) : InstrucIter(ii)
51 {
52   subIters.clear();
53   std::copy(ii.subIters.begin(), ii.subIters.end(), std::back_inserter(subIters));
54   // We can't just copy the iterator because it's over a different range
55   // so we'll find where we should be by address
56   setCurrentAddress(*ii);
57 }
58
59 Address InstrucIterFunction::operator++()
60 {
61   if(currentBlock != subIters.end())
62   {
63     // Increment if not at end of block already
64     if(**currentBlock != currentBlock->end())
65     {
66       ++(*currentBlock);
67     }
68     // If at end of block (either because we were set there, or because we just
69     // incremented, then go ahead to the beginning of the next block
70     if(**currentBlock == currentBlock->end())
71     {
72       ++currentBlock;
73       if(currentBlock != subIters.end())
74       {
75         currentBlock->setCurrentAddress(currentBlock->begin());
76       }
77     }
78   }
79   return **this;
80 }
81
82 Address InstrucIterFunction::operator++(int)
83 {
84   Address ret = **this;
85   ++(*this);
86   return ret;
87 }
88
89 Address InstrucIterFunction::operator--()
90 {
91   if(currentBlock->hasPrev())
92   {
93     --(*currentBlock);
94   }
95   else if(currentBlock != subIters.begin())
96   {
97     --currentBlock;
98     currentBlock->setCurrentAddress(currentBlock->end());
99   }
100   return **this;
101 }
102
103 Address InstrucIterFunction::operator--(int)
104 {
105   Address ret = **this;
106   --(*this);
107   return ret;
108 }
109
110
111 Address InstrucIterFunction::operator*() const
112 {
113   if(currentBlock != subIters.end())
114   {
115     return **currentBlock;
116   }
117   else
118   {
119     return 0;
120   }
121 }
122
123 instruction InstrucIterFunction::getInstruction()
124 {
125   assert(currentBlock != subIters.end());
126   return currentBlock->getInstruction();
127 }
128
129 instruction* InstrucIterFunction::getInsnPtr()
130 {
131   if(currentBlock != subIters.end())
132   {
133     return currentBlock->getInsnPtr();
134   }
135   return NULL;
136 }
137
138 bool InstrucIterFunction::hasMore()
139 {
140   return currentBlock != subIters.end();
141 }
142
143 bool InstrucIterFunction::hasPrev()
144 {
145   return currentBlock != subIters.begin() || currentBlock->hasPrev();
146 }
147
148 Address InstrucIterFunction::peekNext()
149 {
150   assert(hasMore());
151   if(currentBlock->hasMore())
152   {
153     return currentBlock->peekNext();
154   }
155   else
156   {
157     subIterContT::iterator nextBlock = currentBlock;
158     ++nextBlock;
159     if(nextBlock != subIters.end())
160     {
161       return nextBlock->begin();
162     }
163   }
164   return 0;
165 }
166
167 Address InstrucIterFunction::peekPrev()
168 {
169   assert(hasPrev());
170   if(currentBlock->hasPrev())
171   {
172     return currentBlock->peekPrev();
173   }
174   else
175   {
176     subIterContT::iterator prevBlock = currentBlock;
177     --prevBlock;
178     return prevBlock->end();
179   }
180 }
181
182 void InstrucIterFunction::setCurrentAddress(Address a)
183 {
184   subIterContT::iterator tmpBlock = subIters.begin();
185   while(tmpBlock != subIters.end())
186   {
187     if(tmpBlock->containsAddress(a))
188     {
189       currentBlock = tmpBlock;
190       currentBlock->setCurrentAddress(a);
191       break;
192     }
193   }
194   debugPrint();
195 }
196
197 Address InstrucIterFunction::getCurrentAddress()
198 {
199   assert(currentBlock != subIters.end());
200   return currentBlock->getCurrentAddress();
201 }