From f7bba792a10864f0a64a2a579306e3b20602c1dc Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 29 Mar 2016 17:14:01 +0200 Subject: Reset build state for each meta-operation --- build2/b.cxx | 282 ++++++++++++++++++++++++++++++----------------------------- 1 file changed, 144 insertions(+), 138 deletions(-) (limited to 'build2/b.cxx') diff --git a/build2/b.cxx b/build2/b.cxx index b80fe5b..1770d2d 100644 --- a/build2/b.cxx +++ b/build2/b.cxx @@ -65,7 +65,7 @@ main (int argc, char* argv[]) // and buildspecs in any order (it is really handy to just add -v at the // end of the command line). // - strings vars; + strings cmd_vars; string args; try { @@ -115,7 +115,7 @@ main (int argc, char* argv[]) if (strchr (s, '=') != nullptr) // Covers =, +=, and =+. { - vars.push_back (s); + cmd_vars.push_back (s); continue; } @@ -224,39 +224,6 @@ main (int argc, char* argv[]) trace << "home dir: " << home; } - // Initialize the dependency state. - // - reset (); - - // Parse the command line variables. - // - for (const string& v: vars) - { - istringstream is (v); - is.exceptions (istringstream::failbit | istringstream::badbit); - lexer l (is, path ("")); - - // This should be a name followed by =, +=, or =+. - // - token t (l.next ()); - token_type tt (l.next ().type); - - if (t.type != token_type::name || - (tt != token_type::assign && - tt != token_type::prepend && - tt != token_type::append)) - { - fail << "expected variable assignment instead of '" << v << "'" << - info << "use double '--' to treat this argument as buildspec"; - } - - parser p; - t = p.parse_variable (l, *global_scope, t.value, tt); - - if (t.type != token_type::eos) - fail << "unexpected " << t << " in variable assignment '" << v << "'"; - } - // Parse the buildspec. // buildspec bspec; @@ -278,24 +245,77 @@ main (int argc, char* argv[]) if (bspec.empty ()) bspec.push_back (metaopspec ()); // Default meta-operation. - for (metaopspec& ms: bspec) + // If not NULL, then lifted points to the operation that has been "lifted" + // to the meta-operaion (see the logic below for details). Skip is the + // position of the next operation. Dirty indicated whether we managed to + // execute anything before lifting an operation. + // + opspec* lifted (nullptr); + size_t skip (0); + bool dirty (true); + + for (auto mit (bspec.begin ()); mit != bspec.end (); ) { - if (ms.empty ()) - ms.push_back (opspec ()); // Default operation. + vector_view opspecs; + const string& mname (lifted == nullptr ? mit->name : lifted->name); + + if (lifted == nullptr) + { + metaopspec& ms (*mit); + + if (ms.empty ()) + ms.push_back (opspec ()); // Default operation. + + // Continue where we left off after lifting an operation. + // + opspecs.assign (ms.data () + skip, ms.size () - skip); + + // Reset since unless we lift another operation, we move to the + // next meta-operation (see bottom of the loop). + // + skip = 0; + + // This can happen if we have lifted the last operation in opspecs. + // + if (opspecs.empty ()) + { + ++mit; + continue; + } + } + else + opspecs.assign (lifted, 1); + + // Reset the build state for each meta-operation since there is no + // guarantee their assumptions (e.g., in the load callback) are + // compatible. + // + if (dirty) + { + reset (cmd_vars); + dirty = false; + } meta_operation_id mid (0); // Not yet translated. const meta_operation_info* mif (nullptr); - bool lifted (false); // See below. - - for (opspec& os: ms) + for (auto oit (opspecs.begin ()); oit != opspecs.end (); ++oit) { - const path p (""); - const location l (&p, 1, 0); //@@ TODO + opspec& os (*oit); + + // A lifted meta-operation will always have default operation. + // + const string& oname (lifted == nullptr ? os.name : string ()); + + if (lifted != nullptr) + lifted = nullptr; // Clear for the next iteration. if (os.empty ()) // Default target: dir{}. os.push_back (targetspec (name ("dir", string ()))); + const path p (""); + const location l (&p, 1, 0); //@@ TODO + operation_id oid (0); // Not yet translated. const operation_info* oif (nullptr); @@ -312,21 +332,6 @@ main (int argc, char* argv[]) action_targets tgs; tgs.reserve (os.size ()); - // If the previous operation was lifted to meta-operation, - // end the meta-operation batch. - // - if (lifted) - { - if (mif->meta_operation_post != nullptr) - mif->meta_operation_post (); - - l5 ([&]{trace << "end meta-operation batch " << mif->name << ", id " - << static_cast (mid);}); - - mid = 0; - lifted = false; - } - for (targetspec& ts: os) { name& tn (ts.name); @@ -585,50 +590,34 @@ main (int argc, char* argv[]) // known. // { - const auto& mn (ms.name); - const auto& on (os.name); - meta_operation_id m (0); operation_id o (0); - if (!on.empty ()) + if (!oname.empty ()) { - m = meta_operation_table.find (on); + m = meta_operation_table.find (oname); if (m != 0) { - if (!mn.empty ()) - fail (l) << "nested meta-operation " << mn - << '(' << on << ')'; + if (!mname.empty ()) + fail (l) << "nested meta-operation " << mname + << '(' << oname << ')'; - if (!lifted) // If this is the first target. - { - // End the previous meta-operation batch if there was one - // and start a new one. - // - if (mid != 0) - { - assert (oid == 0); + l5 ([&]{trace << "lifting operation " << oname + << ", id " << uint16_t (m);}); - if (mif->meta_operation_post != nullptr) - mif->meta_operation_post (); - - l5 ([&]{trace << "end meta-operation batch " << mif->name - << ", id " << static_cast (mid);}); - mid = 0; - } - - lifted = true; // Flag to also end it; see above. - } + lifted = &os; + skip = lifted - mit->data () + 1; + break; // Out of targetspec loop. } else { - o = operation_table.find (on); + o = operation_table.find (oname); if (o == 0) { diag_record dr; - dr << fail (l) << "unknown operation " << on; + dr << fail (l) << "unknown operation " << oname; // If we guessed src_root and didn't load anything during // bootstrap, then this is probably a meta-operation that @@ -642,14 +631,14 @@ main (int argc, char* argv[]) } } - if (!mn.empty ()) + if (!mname.empty ()) { - m = meta_operation_table.find (mn); + m = meta_operation_table.find (mname); if (m == 0) { diag_record dr; - dr << fail (l) << "unknown meta-operation " << mn; + dr << fail (l) << "unknown meta-operation " << mname; // Same idea as for the operation case above. // @@ -684,6 +673,7 @@ main (int argc, char* argv[]) mif->meta_operation_pre (); current_mif = mif; + dirty = true; } // // Otherwise, check that all the targets in a meta-operation @@ -834,78 +824,94 @@ main (int argc, char* argv[]) } } - if (pre_oid != 0) + // We don't do anything if we lifted the first operation. + // + if (oid != 0) { - l5 ([&]{trace << "start pre-operation batch " << pre_oif->name - << ", id " << static_cast (pre_oid);}); + if (pre_oid != 0) + { + l5 ([&]{trace << "start pre-operation batch " << pre_oif->name + << ", id " << static_cast (pre_oid);}); - if (mif->operation_pre != nullptr) - mif->operation_pre (pre_oid); // Cannot be translated. + if (mif->operation_pre != nullptr) + mif->operation_pre (pre_oid); // Cannot be translated. - current_inner_oif = pre_oif; - current_outer_oif = oif; - current_mode = pre_oif->mode; - dependency_count = 0; + current_inner_oif = pre_oif; + current_outer_oif = oif; + current_mode = pre_oif->mode; + dependency_count = 0; - action a (mid, pre_oid, oid); + action a (mid, pre_oid, oid); - mif->match (a, tgs); - mif->execute (a, tgs, true); // Run quiet. + mif->match (a, tgs); + mif->execute (a, tgs, true); // Run quiet. - if (mif->operation_post != nullptr) - mif->operation_post (pre_oid); + if (mif->operation_post != nullptr) + mif->operation_post (pre_oid); - l5 ([&]{trace << "end pre-operation batch " << pre_oif->name - << ", id " << static_cast (pre_oid);}); - } + l5 ([&]{trace << "end pre-operation batch " << pre_oif->name + << ", id " << static_cast (pre_oid);}); + } - current_inner_oif = oif; - current_outer_oif = nullptr; - current_mode = oif->mode; - dependency_count = 0; + current_inner_oif = oif; + current_outer_oif = nullptr; + current_mode = oif->mode; + dependency_count = 0; - action a (mid, oid, 0); + action a (mid, oid, 0); - mif->match (a, tgs); - mif->execute (a, tgs, verb == 0); + mif->match (a, tgs); + mif->execute (a, tgs, verb == 0); - if (post_oid != 0) - { - l5 ([&]{trace << "start post-operation batch " << post_oif->name - << ", id " << static_cast (post_oid);}); + if (post_oid != 0) + { + l5 ([&]{trace << "start post-operation batch " << post_oif->name + << ", id " << static_cast (post_oid);}); - if (mif->operation_pre != nullptr) - mif->operation_pre (post_oid); // Cannot be translated. + if (mif->operation_pre != nullptr) + mif->operation_pre (post_oid); // Cannot be translated. - current_inner_oif = post_oif; - current_outer_oif = oif; - current_mode = post_oif->mode; - dependency_count = 0; + current_inner_oif = post_oif; + current_outer_oif = oif; + current_mode = post_oif->mode; + dependency_count = 0; - action a (mid, post_oid, oid); + action a (mid, post_oid, oid); - mif->match (a, tgs); - mif->execute (a, tgs, true); // Run quiet. + mif->match (a, tgs); + mif->execute (a, tgs, true); // Run quiet. + + if (mif->operation_post != nullptr) + mif->operation_post (post_oid); + + l5 ([&]{trace << "end post-operation batch " << post_oif->name + << ", id " << static_cast (post_oid);}); + } if (mif->operation_post != nullptr) - mif->operation_post (post_oid); + mif->operation_post (oid); - l5 ([&]{trace << "end post-operation batch " << post_oif->name - << ", id " << static_cast (post_oid);}); + l5 ([&]{trace << "end operation batch " << oif->name + << ", id " << static_cast (oid);}); } - if (mif->operation_post != nullptr) - mif->operation_post (oid); - - l5 ([&]{trace << "end operation batch " << oif->name - << ", id " << static_cast (oid);}); + // If this operation has been lifted, break out. + // + if (lifted == &os) + break; } - if (mif->meta_operation_post != nullptr) - mif->meta_operation_post (); + if (mid != 0) + { + if (mif->meta_operation_post != nullptr) + mif->meta_operation_post (); + + l5 ([&]{trace << "end meta-operation batch " << mif->name + << ", id " << static_cast (mid);}); + } - l5 ([&]{trace << "end meta-operation batch " << mif->name - << ", id " << static_cast (mid);}); + if (lifted == nullptr && skip == 0) + ++mit; } } catch (const failed&) -- cgit v1.1