aboutsummaryrefslogtreecommitdiff
path: root/src/target.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/target.cpp402
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>
16using namespace Bu;
17
18Target::Target( bool bExplicit ) :
19 bExplicit( bExplicit ),
20 bRun( false ),
21 iDepCount( 0 )
22{
23}
24
25Target::Target( const Bu::FString &sOutput, bool bExplicit ) :
26 bExplicit( bExplicit ),
27 lsOutput( sOutput ),
28 iDepCount( 0 )
29{
30}
31
32Target::~Target()
33{
34}
35
36void Target::addInput( const Bu::FString &sInput )
37{
38 lsInput.append( sInput );
39}
40
41const StrList &Target::getInputList() const
42{
43 return lsInput;
44}
45
46void 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
64void Target::addRequires( const Bu::FString &sReq )
65{
66 lsRequires.append( sReq );
67}
68
69void Target::addRequires( const AstBranch *pBr )
70{
71 lbRequires.append( pBr );
72}
73
74const StrList &Target::getRequiresList() const
75{
76 return lsRequires;
77}
78
79void 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
113void Target::addOutput( const Bu::FString &sOutput )
114{
115 lsOutput.append( sOutput );
116}
117
118const StrList &Target::getOutputList() const
119{
120 return lsOutput;
121}
122
123void Target::setPrefix( const Bu::FString &sPrefix )
124{
125 this->sPrefix = sPrefix;
126}
127
128const Bu::FString &Target::getPrefix() const
129{
130 return sPrefix;
131}
132
133void Target::setRule( const Bu::FString &sRule )
134{
135 this->sRule = sRule;
136}
137
138const Bu::FString &Target::getRule() const
139{
140 return sRule;
141}
142
143bool Target::hasRule() const
144{
145 return !sRule.isEmpty();
146}
147
148bool Target::isExplicit() const
149{
150 return bExplicit;
151}
152
153void Target::addDep( Target *pDep )
154{
155 lDeps.append( pDep );
156}
157
158const TargetList &Target::getDepList() const
159{
160 return lDeps;
161}
162
163void 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
177void Target::addProfile( const class Profile *pSrc )
178{
179 hProfiles.insert( pSrc->getName(), new Profile( *pSrc ) );
180}
181
182bool Target::hasProfile( const Bu::FString &sName ) const
183{
184 return hProfiles.has( sName );
185}
186
187const Profile *Target::getProfile( const Bu::FString &sName ) const
188{
189 return hProfiles.get( sName );
190}
191
192void Target::setVars( const VarHash &hNewVars )
193{
194 hVars = hNewVars;
195}
196
197const VarHash &Target::getVars() const
198{
199 return hVars;
200}
201
202void Target::setDisplay( const Bu::FString &sNewDisplay )
203{
204 if( !sDisplay )
205 sDisplay = sNewDisplay;
206}
207
208const Bu::FString &Target::getDisplay() const
209{
210 return sDisplay;
211}
212
213void 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
252void 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
263bool Target::hasRun()
264{
265 return bRun;
266}
267
268void 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
303void 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
334void 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
344void 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
359int Target::getDepCount() const
360{
361 return iDepCount;
362}
363
364void 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
383Bu::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
398template<> Bu::Formatter &Bu::operator<< <Target>( Bu::Formatter &f, const Target *t )
399{
400 return f << (*t);
401}
402