From 389f0fe004c205cdee9d7f9f7a4c880055bfb285 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 20 Nov 2017 15:03:40 +0200 Subject: Add support for dumping prerequisite-specific variables --- build2/dump.cxx | 157 +++++++++++++++++++++++++++++++++++++----------------- build2/parser.cxx | 9 ++-- 2 files changed, 115 insertions(+), 51 deletions(-) diff --git a/build2/dump.cxx b/build2/dump.cxx index 7e2676d..714ae05 100644 --- a/build2/dump.cxx +++ b/build2/dump.cxx @@ -53,7 +53,7 @@ namespace build2 } } - enum class variable_kind {scope, tt_pat, target}; + enum class variable_kind {scope, tt_pat, target, prerequisite}; static void dump_variable (ostream& os, @@ -91,25 +91,31 @@ namespace build2 // If this variable is overriden, print both the override and the // original values. // - if (var.override != nullptr && - var.name.rfind (".__override") == string::npos && - var.name.rfind (".__suffix") == string::npos && - var.name.rfind (".__prefix") == string::npos) + // @@ The override semantics for prerequisite-specific variables + // is still fuzzy/unimplemented, so ignore it for now. + // + if (k != variable_kind::prerequisite) { - lookup org (v, vm); + if (var.override != nullptr && + var.name.rfind (".__override") == string::npos && + var.name.rfind (".__suffix") == string::npos && + var.name.rfind (".__prefix") == string::npos) + { + lookup org (v, vm); - // The original is always from this scope/target, so depth is 1. - // - lookup l ( - s.find_override ( - var, make_pair (org, 1), k == variable_kind::target).first); + // The original is always from this scope/target, so depth is 1. + // + lookup l ( + s.find_override ( + var, make_pair (org, 1), k == variable_kind::target).first); - assert (l.defined ()); // We at least have the original. + assert (l.defined ()); // We at least have the original. - if (org != l) - { - dump_value (os, *l, l->type != var.type); - os << " # original: "; + if (org != l) + { + dump_value (os, *l, l->type != var.type); + os << " # original: "; + } } } @@ -206,60 +212,111 @@ namespace build2 stream_verb (os, 1); } - os << ind << t; - if (t.group != nullptr) - os << "->" << *t.group; + os << ind << t << " -> " << *t.group << endl; - os << ':'; + os << ind << t << ':'; - for (const prerequisite& p: t.prerequisites ()) + // First print target-specific variables, if any. + // + if (!t.vars.empty ()) { - os << ' '; + if (relative) + stream_verb (os, sv); // We want variable values in full. - // Print it as target if one has been cached. - // - if (const target* t = p.target.load (memory_order_relaxed)) // Serial. - os << *t; - else - os << p; + os << endl + << ind << '{'; + ind += " "; + dump_variables (os, ind, t.vars, s, variable_kind::target); + ind.resize (ind.size () - 2); + os << endl + << ind << '}'; + + if (relative) + stream_verb (os, 1); + + os << endl + << ind << t << ':'; } - // If the target has been matched to a rule, also print resolved + bool used (false); // Target header has been used to display prerequisites. + + // If the target has been matched to a rule, first print resolved // prerequisite targets. // + // Note: running serial and task_count is 0 before any operation has + // started. + // + if (size_t c = t.task_count.load (memory_order_relaxed)) { - size_t c (t.task_count.load (memory_order_relaxed)); // Running serial. - if (c == target::count_applied () || c == target::count_executed ()) { - bool first (true); + bool f (false); for (const target* pt: t.prerequisite_targets) { if (pt == nullptr) // Skipped. continue; - os << (first ? " | " : " ") << *pt; - first = false; + os << ' ' << *pt; + f = true; + } + + // Only omit '|' if we have no prerequisites nor targets. + // + if (f || !t.prerequisites ().empty ()) + { + os << " |"; + used = true; } } } - if (relative) - stream_verb (os, sv); // We want variable values in full. - - // Print target-specific variables. + // Print prerequisites. Those that have prerequisite-specific variables + // have to be printed as a separate dependency. // - if (!t.vars.empty ()) + const prerequisites& ps (t.prerequisites ()); + for (auto i (ps.begin ()), e (ps.end ()); i != e; ) { - os << endl - << ind << '{'; - ind += " "; - dump_variables (os, ind, t.vars, s, variable_kind::target); - ind.resize (ind.size () - 2); - os << endl - << ind << '}'; + const prerequisite& p (*i++); + bool ps (!p.vars.empty ()); // Has prerequisite-specific vars. + + if (ps && used) // If it has been used, get a new header. + os << endl + << ind << t << ':'; + + // Print it as a target if one has been cached. + // + if (const target* t = p.target.load (memory_order_relaxed)) // Serial. + os << ' ' << *t; + else + os << ' ' << p; + + if (ps) + { + if (relative) + stream_verb (os, sv); // We want variable values in full. + + os << ':' << endl + << ind << '{'; + ind += " "; + dump_variables (os, ind, p.vars, s, variable_kind::prerequisite); + ind.resize (ind.size () - 2); + os << endl + << ind << '}'; + + if (relative) + stream_verb (os, 1); + + if (i != e) // If we have another, get a new header. + os << endl + << ind << t << ':'; + } + + used = !ps; } + + if (relative) + stream_verb (os, sv); } static void @@ -289,7 +346,7 @@ namespace build2 ind += " "; - bool vb (false), sb (false); // Variable/scope block. + bool vb (false), sb (false), tb (false); // Variable/scope/target block. // Target type/pattern-sepcific variables. // @@ -330,6 +387,9 @@ namespace build2 // Targets. // + // Since targets can occupy multiple lines, we separate them with a + // blank line. + // for (const auto& pt: targets) { const target& t (*pt); @@ -337,7 +397,7 @@ namespace build2 if (&p != &t.base_scope ()) continue; - if (vb || sb) + if (vb || sb || tb) { os << endl; vb = sb = false; @@ -345,6 +405,7 @@ namespace build2 os << endl; dump_target (os, ind, t, p, true /* relative */); + tb = true; } ind.resize (ind.size () - 2); diff --git a/build2/parser.cxx b/build2/parser.cxx index 7c8695a..54aa93d 100644 --- a/build2/parser.cxx +++ b/build2/parser.cxx @@ -1890,10 +1890,10 @@ namespace build2 } else { - for (auto i (ns.begin ()), e (ns.end ()); i != e; ++i) + for (auto i (ns.begin ()), e (ns.end ()); i != e; ) { - name& n (*i); - name o (n.pair ? move (*++i) : name ()); + name& n (*i++); + name o (n.pair ? move (*i++) : name ()); const target* t (enter_target::find_target (*this, n, o, l, trace)); @@ -1905,6 +1905,9 @@ namespace build2 if (n.pair && !o.dir.empty ()) os << '@' << o.dir; os << '>' << endl; } + + if (i != e) + os << endl; } } -- cgit v1.1