diff options
Diffstat (limited to '')
-rw-r--r-- | src/target.cpp | 402 |
1 files changed, 402 insertions, 0 deletions
diff --git a/src/target.cpp b/src/target.cpp new file mode 100644 index 0000000..f3e54b7 --- /dev/null +++ b/src/target.cpp | |||
@@ -0,0 +1,402 @@ | |||
1 | #include "target.h" | ||
2 | #include "variable.h" | ||
3 | #include "condition.h" | ||
4 | #include "astleaf.h" | ||
5 | #include "astbranch.h" | ||
6 | #include "runner.h" | ||
7 | #include "context.h" | ||
8 | #include "profile.h" | ||
9 | #include "view.h" | ||
10 | |||
11 | #include <bu/membuf.h> | ||
12 | #include <bu/formatter.h> | ||
13 | #include <bu/heap.h> | ||
14 | |||
15 | #include <bu/sio.h> | ||
16 | using namespace Bu; | ||
17 | |||
18 | Target::Target( bool bExplicit ) : | ||
19 | bExplicit( bExplicit ), | ||
20 | bRun( false ), | ||
21 | iDepCount( 0 ) | ||
22 | { | ||
23 | } | ||
24 | |||
25 | Target::Target( const Bu::FString &sOutput, bool bExplicit ) : | ||
26 | bExplicit( bExplicit ), | ||
27 | lsOutput( sOutput ), | ||
28 | iDepCount( 0 ) | ||
29 | { | ||
30 | } | ||
31 | |||
32 | Target::~Target() | ||
33 | { | ||
34 | } | ||
35 | |||
36 | void Target::addInput( const Bu::FString &sInput ) | ||
37 | { | ||
38 | lsInput.append( sInput ); | ||
39 | } | ||
40 | |||
41 | const StrList &Target::getInputList() const | ||
42 | { | ||
43 | return lsInput; | ||
44 | } | ||
45 | |||
46 | void Target::resetInputList( const StrList &lInputs ) | ||
47 | { | ||
48 | lsInput = lInputs; | ||
49 | if( lsInput.getSize() == 1 ) | ||
50 | { | ||
51 | hVars.insert("INPUT", lsInput.first() ); | ||
52 | } | ||
53 | else | ||
54 | { | ||
55 | Variable vInput( Variable::typeList ); | ||
56 | for( StrList::iterator i = lsInput.begin(); i; i++ ) | ||
57 | { | ||
58 | vInput.append( Variable( *i ) ); | ||
59 | } | ||
60 | hVars.insert("INPUT", vInput ); | ||
61 | } | ||
62 | } | ||
63 | |||
64 | void Target::addRequires( const Bu::FString &sReq ) | ||
65 | { | ||
66 | lsRequires.append( sReq ); | ||
67 | } | ||
68 | |||
69 | void Target::addRequires( const AstBranch *pBr ) | ||
70 | { | ||
71 | lbRequires.append( pBr ); | ||
72 | } | ||
73 | |||
74 | const StrList &Target::getRequiresList() const | ||
75 | { | ||
76 | return lsRequires; | ||
77 | } | ||
78 | |||
79 | void Target::buildRequires( Runner &r ) | ||
80 | { | ||
81 | r.getContext().getView()->buildRequires( *this ); | ||
82 | r.getContext().pushScope( hVars ); | ||
83 | for( AstBranchList::iterator i = lbRequires.begin(); i; i++ ) | ||
84 | { | ||
85 | Variable v = r.execExpr( (*(*i)->getBranchBegin()).begin() ); | ||
86 | if( v.getType() == Variable::typeList ) | ||
87 | { | ||
88 | for( VarList::iterator j = v.begin(); j; j++ ) | ||
89 | { | ||
90 | Bu::FString sReq = (*j).toString(); | ||
91 | addRequires( sReq ); | ||
92 | try | ||
93 | { | ||
94 | addDep( r.getContext().getTarget( sReq ) ); | ||
95 | } | ||
96 | catch(...) { } | ||
97 | } | ||
98 | } | ||
99 | else | ||
100 | { | ||
101 | Bu::FString sReq = v.toString(); | ||
102 | addRequires( sReq ); | ||
103 | try | ||
104 | { | ||
105 | addDep( r.getContext().getTarget( sReq ) ); | ||
106 | } | ||
107 | catch(...) { } | ||
108 | } | ||
109 | } | ||
110 | r.getContext().popScope(); | ||
111 | } | ||
112 | |||
113 | void Target::addOutput( const Bu::FString &sOutput ) | ||
114 | { | ||
115 | lsOutput.append( sOutput ); | ||
116 | } | ||
117 | |||
118 | const StrList &Target::getOutputList() const | ||
119 | { | ||
120 | return lsOutput; | ||
121 | } | ||
122 | |||
123 | void Target::setPrefix( const Bu::FString &sPrefix ) | ||
124 | { | ||
125 | this->sPrefix = sPrefix; | ||
126 | } | ||
127 | |||
128 | const Bu::FString &Target::getPrefix() const | ||
129 | { | ||
130 | return sPrefix; | ||
131 | } | ||
132 | |||
133 | void Target::setRule( const Bu::FString &sRule ) | ||
134 | { | ||
135 | this->sRule = sRule; | ||
136 | } | ||
137 | |||
138 | const Bu::FString &Target::getRule() const | ||
139 | { | ||
140 | return sRule; | ||
141 | } | ||
142 | |||
143 | bool Target::hasRule() const | ||
144 | { | ||
145 | return !sRule.isEmpty(); | ||
146 | } | ||
147 | |||
148 | bool Target::isExplicit() const | ||
149 | { | ||
150 | return bExplicit; | ||
151 | } | ||
152 | |||
153 | void Target::addDep( Target *pDep ) | ||
154 | { | ||
155 | lDeps.append( pDep ); | ||
156 | } | ||
157 | |||
158 | const TargetList &Target::getDepList() const | ||
159 | { | ||
160 | return lDeps; | ||
161 | } | ||
162 | |||
163 | void Target::addProfile( const class AstBranch *pProfRoot ) | ||
164 | { | ||
165 | Profile *pProf = new Profile( pProfRoot ); | ||
166 | hProfiles.insert( pProf->getName(), pProf ); | ||
167 | /* | ||
168 | hProfiles.insert( | ||
169 | dynamic_cast<const AstLeaf *>( | ||
170 | (*pProfRoot->getBranchBegin()).first() | ||
171 | )->getStrValue(), | ||
172 | pProfRoot | ||
173 | ); | ||
174 | */ | ||
175 | } | ||
176 | |||
177 | void Target::addProfile( const class Profile *pSrc ) | ||
178 | { | ||
179 | hProfiles.insert( pSrc->getName(), new Profile( *pSrc ) ); | ||
180 | } | ||
181 | |||
182 | bool Target::hasProfile( const Bu::FString &sName ) const | ||
183 | { | ||
184 | return hProfiles.has( sName ); | ||
185 | } | ||
186 | |||
187 | const Profile *Target::getProfile( const Bu::FString &sName ) const | ||
188 | { | ||
189 | return hProfiles.get( sName ); | ||
190 | } | ||
191 | |||
192 | void Target::setVars( const VarHash &hNewVars ) | ||
193 | { | ||
194 | hVars = hNewVars; | ||
195 | } | ||
196 | |||
197 | const VarHash &Target::getVars() const | ||
198 | { | ||
199 | return hVars; | ||
200 | } | ||
201 | |||
202 | void Target::setDisplay( const Bu::FString &sNewDisplay ) | ||
203 | { | ||
204 | if( !sDisplay ) | ||
205 | sDisplay = sNewDisplay; | ||
206 | } | ||
207 | |||
208 | const Bu::FString &Target::getDisplay() const | ||
209 | { | ||
210 | return sDisplay; | ||
211 | } | ||
212 | |||
213 | void Target::process( class Runner &r, const Bu::FString &sProfile ) | ||
214 | { | ||
215 | r.getContext().getView()->beginTarget( sProfile, *this ); | ||
216 | bRun = true; | ||
217 | bool bShouldExec = false; | ||
218 | |||
219 | for( TargetList::iterator i = lDeps.begin(); i; i++ ) | ||
220 | { | ||
221 | if( (*i)->bRun ) | ||
222 | continue; | ||
223 | |||
224 | // TODO: This is important, in the future, it may be possible for a | ||
225 | // target to be triggered by multiple dependant targets, to cover for | ||
226 | // this the below mergeUnder should be *TEMPORARY* and the target | ||
227 | // that was marged to be reset post processing. | ||
228 | (*i)->mergeUnder( hVars ); | ||
229 | (*i)->process( r, sProfile ); | ||
230 | } | ||
231 | try | ||
232 | { | ||
233 | bShouldExec = hProfiles.get( sProfile )->shouldExec( r, *this ); | ||
234 | } | ||
235 | catch( Bu::HashException &e ) | ||
236 | { | ||
237 | } | ||
238 | |||
239 | if( !bShouldExec ) | ||
240 | { | ||
241 | r.getContext().getView()->skipTarget( sProfile, *this ); | ||
242 | } | ||
243 | else | ||
244 | { | ||
245 | r.getContext().getView()->processTarget( sProfile, *this ); | ||
246 | r.execProfile( this, sProfile ); | ||
247 | } | ||
248 | |||
249 | r.getContext().getView()->endTarget(); | ||
250 | } | ||
251 | |||
252 | void Target::mergeUnder( const VarHash &hNewVars ) | ||
253 | { | ||
254 | for( VarHash::const_iterator i = hNewVars.begin(); i; i++ ) | ||
255 | { | ||
256 | if( !hVars.has( i.getKey() ) ) | ||
257 | { | ||
258 | hVars.insert( i.getKey(), i.getValue() ); | ||
259 | } | ||
260 | } | ||
261 | } | ||
262 | |||
263 | bool Target::hasRun() | ||
264 | { | ||
265 | return bRun; | ||
266 | } | ||
267 | |||
268 | void Target::mergeUnder( const Target *pSrc ) | ||
269 | { | ||
270 | // If either are explicit, then it's explicit | ||
271 | bExplicit = bExplicit || pSrc->bExplicit; | ||
272 | |||
273 | merge( lsInput, pSrc->lsInput ); | ||
274 | merge( lsRequires, pSrc->lsRequires ); | ||
275 | merge( lsOutput, pSrc->lsOutput ); | ||
276 | |||
277 | if( !sPrefix ) | ||
278 | sPrefix = pSrc->sPrefix; | ||
279 | |||
280 | sRule = pSrc->sRule; | ||
281 | |||
282 | mergeUnder( pSrc->hVars ); | ||
283 | |||
284 | // Deps? They should be computed much after merging anyway, peh! | ||
285 | |||
286 | for( ProfileHash::const_iterator i = pSrc->hProfiles.begin(); i; i++ ) | ||
287 | { | ||
288 | if( !hProfiles.has( i.getKey() ) ) | ||
289 | { | ||
290 | hProfiles.insert( i.getKey(), i.getValue() ); | ||
291 | } | ||
292 | } | ||
293 | |||
294 | if( !sDisplay ) | ||
295 | sDisplay = pSrc->sDisplay; | ||
296 | |||
297 | // Now we need to reset our vars. | ||
298 | hVars.insert("INPUT", lsInput ); | ||
299 | hVars.insert("REQUIRES", lsRequires ); | ||
300 | hVars.insert("OUTPUT", lsOutput ); | ||
301 | } | ||
302 | |||
303 | void Target::merge( StrList &lOut, const StrList &lIn ) | ||
304 | { | ||
305 | Bu::Heap<Bu::FString> hStr; | ||
306 | for( StrList::const_iterator i = lOut.begin(); i; i++ ) | ||
307 | { | ||
308 | hStr.enqueue( *i ); | ||
309 | } | ||
310 | for( StrList::const_iterator i = lIn.begin(); i; i++ ) | ||
311 | { | ||
312 | hStr.enqueue( *i ); | ||
313 | } | ||
314 | |||
315 | lOut.clear(); | ||
316 | |||
317 | if( hStr.isEmpty() ) | ||
318 | return; | ||
319 | |||
320 | lOut.append( hStr.dequeue() ); | ||
321 | while( !hStr.isEmpty() ) | ||
322 | { | ||
323 | if( hStr.peek() == lOut.last() ) | ||
324 | { | ||
325 | hStr.dequeue(); | ||
326 | } | ||
327 | else | ||
328 | { | ||
329 | lOut.append( hStr.dequeue() ); | ||
330 | } | ||
331 | } | ||
332 | } | ||
333 | |||
334 | void Target::resetRun( bool bHasRun ) | ||
335 | { | ||
336 | bRun = bHasRun; | ||
337 | |||
338 | for( TargetList::iterator i = lDeps.begin(); i; i++ ) | ||
339 | { | ||
340 | (*i)->resetRun( bHasRun ); | ||
341 | } | ||
342 | } | ||
343 | |||
344 | void Target::setDepCount() | ||
345 | { | ||
346 | bRun = true; | ||
347 | iDepCount = 1; | ||
348 | for( TargetList::iterator i = lDeps.begin(); i; i++ ) | ||
349 | { | ||
350 | if( (*i)->bRun ) | ||
351 | { | ||
352 | continue; | ||
353 | } | ||
354 | (*i)->setDepCount(); | ||
355 | iDepCount += (*i)->getDepCount(); | ||
356 | } | ||
357 | } | ||
358 | |||
359 | int Target::getDepCount() const | ||
360 | { | ||
361 | return iDepCount; | ||
362 | } | ||
363 | |||
364 | void Target::collapseDeps() | ||
365 | { | ||
366 | if( lDeps.getSize() <= 1 ) | ||
367 | return; | ||
368 | Bu::Hash<ptrdiff_t, bool> hDep; | ||
369 | for( TargetList::iterator i = lDeps.begin(); i; i++ ) | ||
370 | { | ||
371 | if( hDep.has( (ptrdiff_t)*i ) ) | ||
372 | { | ||
373 | lDeps.erase( i ); | ||
374 | i--; | ||
375 | } | ||
376 | else | ||
377 | { | ||
378 | hDep.insert( (ptrdiff_t)*i, true ); | ||
379 | } | ||
380 | } | ||
381 | } | ||
382 | |||
383 | Bu::Formatter &operator<<( Bu::Formatter &f, const Target &t ) | ||
384 | { | ||
385 | f.incIndent(); | ||
386 | f << f.nl << "Input = " << t.lsInput << "," << f.nl | ||
387 | << "Requires = " << t.lsRequires << "," << f.nl | ||
388 | << "Output = \"" << t.lsOutput << "\"," << f.nl | ||
389 | << "Prefix = \"" << t.sPrefix << "\"," << f.nl | ||
390 | << "Rule = \"" << t.sRule << "\"," << f.nl | ||
391 | << "Explicit = " << t.bExplicit << "," << f.nl | ||
392 | << "Vars = " << t.hVars | ||
393 | << f.nl; | ||
394 | f.decIndent(); | ||
395 | return f; | ||
396 | } | ||
397 | |||
398 | template<> Bu::Formatter &Bu::operator<< <Target>( Bu::Formatter &f, const Target *t ) | ||
399 | { | ||
400 | return f << (*t); | ||
401 | } | ||
402 | |||