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 | |||
