aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/diagnostics.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'libbuild2/diagnostics.cxx')
-rw-r--r--libbuild2/diagnostics.cxx195
1 files changed, 141 insertions, 54 deletions
diff --git a/libbuild2/diagnostics.cxx b/libbuild2/diagnostics.cxx
index bc74db3..d91150b 100644
--- a/libbuild2/diagnostics.cxx
+++ b/libbuild2/diagnostics.cxx
@@ -82,39 +82,26 @@ namespace build2
dr << r;
}
- template <typename L> // L can be target_key, path, or string.
- static void
- print_diag_impl (const char* p,
- const L* l, bool lempty,
- vector<target_key>&& rs,
- const char* c)
- {
- assert (rs.size () > 1);
- // The overall plan is as follows:
- //
- // 1. Collect the printed names for all the group members.
- //
- // Note if the printed representation is irregular (see
- // to_stream(target_key) for details). We will print such members each
- // on a separate line.
- //
- // 2. Move the names so that we end up with contiguous partitions of
- // targets with the same name.
- //
- // 3. Print the partitions, one per line.
- //
- vector<pair<optional<string>, const target_key*>> ns;
- ns.reserve (rs.size ());
+ static inline bool
+ print_diag_cmp (const pair<optional<string>, const target_key*>& x,
+ const pair<optional<string>, const target_key*>& y)
+ {
+ return (x.second->dir->compare (*y.second->dir) == 0 &&
+ x.first->compare (*y.first) == 0);
+ }
- // Use the diag_record's ostringstream so that we get the appropriate
- // stream verbosity, etc.
- //
- diag_record dr (text);
- ostringstream& os (dr.os);
- stream_verbosity sv (stream_verb (os));
+ // Return true if we have multiple partitions (see below for details).
+ //
+ static bool
+ print_diag_collect (const vector<target_key>& tks,
+ ostringstream& os,
+ stream_verbosity sv,
+ vector<pair<optional<string>, const target_key*>>& ns)
+ {
+ ns.reserve (tks.size ());
- for (const target_key& k: rs)
+ for (const target_key& k: tks)
{
bool r;
if (auto p = k.type->print)
@@ -130,16 +117,9 @@ namespace build2
// Partition.
//
- auto cmp = [] (const pair<optional<string>, const target_key*>& x,
- const pair<optional<string>, const target_key*>& y)
- {
- return (x.second->dir->compare (*y.second->dir) == 0 &&
- x.first->compare (*y.first) == 0);
- };
-
// While at it also determine whether we have multiple partitions.
//
- optional<string> ml;
+ bool ml (false);
for (auto b (ns.begin ()), e (ns.end ()); b != e; )
{
const pair<optional<string>, const target_key*>& x (*b++);
@@ -149,25 +129,24 @@ namespace build2
//
b = stable_partition (
b, e,
- [&cmp, &x] (const pair<optional<string>, const target_key*>& y)
+ [&x] (const pair<optional<string>, const target_key*>& y)
{
- return (x.first && y.first && cmp (x, y));
+ return (x.first && y.first && print_diag_cmp (x, y));
});
if (!ml && b != e)
- ml = string ();
+ ml = true;
}
- // Print.
- //
- os << p << ' ';
-
- if (l != nullptr)
- os << *l << (lempty ? "" : " ") << (c == nullptr ? "->" : c) << ' ';
-
- if (ml)
- ml = string (os.str ().size (), ' '); // Indentation.
+ return ml;
+ }
+ static void
+ print_diag_print (const vector<pair<optional<string>, const target_key*>>& ns,
+ ostringstream& os,
+ stream_verbosity sv,
+ const optional<string>& ml)
+ {
for (auto b (ns.begin ()), i (b), e (ns.end ()); i != e; )
{
if (i != b)
@@ -185,7 +164,7 @@ namespace build2
// Calculate the number of members in this partition.
//
size_t n (1);
- for (auto j (i + 1); j != e && j->first && cmp (*i, *j); ++j)
+ for (auto j (i + 1); j != e && j->first && print_diag_cmp (*i, *j); ++j)
++n;
// Similar code to to_stream(target_key).
@@ -232,6 +211,95 @@ namespace build2
}
}
+ template <typename L> // L can be target_key, path, or string.
+ static void
+ print_diag_impl (const char* p,
+ const L* l, bool lempty,
+ vector<target_key>&& rs,
+ const char* c)
+ {
+ assert (rs.size () > 1);
+
+ // The overall plan is as follows:
+ //
+ // 1. Collect the printed names for all the group members.
+ //
+ // Note if the printed representation is irregular (see
+ // to_stream(target_key) for details). We will print such members each
+ // on a separate line.
+ //
+ // 2. Move the names around so that we end up with contiguous partitions
+ // of targets with the same name.
+ //
+ // 3. Print the partitions, one per line.
+ //
+ // The steps 1-2 are performed by print_diag_impl_common() above.
+ //
+ vector<pair<optional<string>, const target_key*>> ns;
+
+ // Use the diag_record's ostringstream so that we get the appropriate
+ // stream verbosity, etc.
+ //
+ diag_record dr (text);
+ ostringstream& os (dr.os);
+ stream_verbosity sv (stream_verb (os));
+
+ optional<string> ml;
+ if (print_diag_collect (rs, os, sv, ns))
+ ml = string ();
+
+ // Print.
+ //
+ os << p << ' ';
+
+ if (l != nullptr)
+ os << *l << (lempty ? "" : " ") << (c == nullptr ? "->" : c) << ' ';
+
+ if (ml)
+ ml = string (os.str ().size (), ' '); // Indentation.
+
+ print_diag_print (ns, os, sv, ml);
+ }
+
+ template <typename R> // R can be target_key, path, or string.
+ static void
+ print_diag_impl (const char* p,
+ vector<target_key>&& ls, const R& r,
+ const char* c)
+ {
+ assert (ls.size () > 1);
+
+ // As above but for the group on the LHS.
+ //
+ vector<pair<optional<string>, const target_key*>> ns;
+
+ diag_record dr (text);
+ ostringstream& os (dr.os);
+ stream_verbosity sv (stream_verb (os));
+
+ optional<string> ml;
+ if (print_diag_collect (ls, os, sv, ns))
+ ml = string ();
+
+ // Print.
+ //
+ os << p << ' ';
+
+ if (ml)
+ ml = string (os.str ().size (), ' '); // Indentation.
+
+ print_diag_print (ns, os, sv, ml);
+
+ // @@ TODO: make sure `->` is aligned with longest line printed by
+ // print_diag_print(). Currently it can look like this:
+ //
+ // ln /tmp/hello-gcc/hello/hello/{hxx cxx}{hello-types}
+ // /tmp/hello-gcc/hello/hello/{hxx cxx}{hello-stubs}
+ // /tmp/hello-gcc/hello/hello/cxx{hello-ext} -> ./
+ //
+ os << ' ' << (c == nullptr ? "->" : c) << ' ' << r;
+ }
+
void
print_diag_impl (const char* p,
target_key* l, vector<target_key>&& rs,
@@ -361,7 +429,9 @@ namespace build2
}
void
- print_diag (const char* p, const target& l, const dir_path& r, const char* c)
+ print_diag (const char* p,
+ const target& l, const path_name_view& r,
+ const char* c)
{
// @@ TODO: out qualification stripping: only do if p.out is subdir of t
// (also below)?
@@ -370,11 +440,28 @@ namespace build2
}
void
+ print_diag (const char* p, const target& l, const dir_path& r, const char* c)
+ {
+ print_diag (p, l.key (), r, c);
+ }
+
+ void
+ print_diag (const char* p, target_key&& l, const dir_path& r, const char* c)
+ {
+ text << p << ' ' << l << ' ' << (c == nullptr ? "->" : c) << ' ' << r;
+ }
+
+ void
print_diag (const char* p,
- const target& l, const path_name_view& r,
+ vector<target_key>&& ls, const dir_path& r,
const char* c)
{
- text << p << ' ' << l << ' ' << (c == nullptr ? "->" : c) << ' ' << r;
+ assert (!ls.empty ());
+
+ if (ls.size () == 1)
+ print_diag (p, move (ls.front ()), r, c);
+ else
+ print_diag_impl<dir_path> (p, move (ls), r, c);
}
void