From 9964a9aca03b38c2959994e0fdc91014da252cb8 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 20 Nov 2017 13:11:59 +0200 Subject: Implement dump directive It can be used to print (to stderr) a human-readable representation of the current scope or a list of targets. For example: dump # Dump current scope. dump lib{foo} details/exe{bar} # Dump two targets. This is primarily useful for debugging as well as to write build system tests. --- build2/parser.cxx | 109 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 100 insertions(+), 9 deletions(-) (limited to 'build2/parser.cxx') diff --git a/build2/parser.cxx b/build2/parser.cxx index 1863f67..7c8695a 100644 --- a/build2/parser.cxx +++ b/build2/parser.cxx @@ -9,6 +9,7 @@ #include // path_search(), path_match() +#include #include #include #include @@ -112,6 +113,40 @@ namespace build2 tracer& tr) : p_ (&p), t_ (p.target_) { + // Find or insert. + // + auto r (process_target (p, n, o, loc)); + p.target_ = &targets.insert (*r.first, // target type + move (n.dir), + move (o.dir), + move (n.value), + move (r.second), // extension + implied, + tr).first; + } + + static const target* + find_target (parser& p, + name& n, // If n.pair, then o is out dir. + name& o, + const location& loc, + tracer& tr) + { + auto r (process_target (p, n, o, loc)); + return targets.find (*r.first, // target type + n.dir, + o.dir, + n.value, + r.second, // extension + tr); + } + + static pair> + process_target (parser& p, + name& n, // If n.pair, then o is out dir. + name& o, + const location& loc) + { optional e; const target_type* ti (p.scope_->find_target_type (n, e)); @@ -148,16 +183,9 @@ namespace build2 out = o.dir.relative () ? od / o.dir : move (o.dir); out.normalize (); } + o.dir = move (out); // Result. - // Find or insert. - // - p.target_ = &targets.insert (*ti, - move (d), - move (out), - move (n.value), - move (e), - implied, - tr).first; + return make_pair (ti, move (e)); } ~enter_target () @@ -348,6 +376,10 @@ namespace build2 { f = &parser::parse_diag; } + else if (n == "dump") + { + f = &parser::parse_dump; + } else if (n == "source") { f = &parser::parse_source; @@ -1823,6 +1855,65 @@ namespace build2 next (t, tt); // Swallow newline. } + void parser:: + parse_dump (token& t, type& tt) + { + // dump [...] + // + // If there are no targets, then we dump the current scope. + // + tracer trace ("parser::parse_dump", &path_); + + const location l (get_location (t)); + next (t, tt); + names ns (tt != type::newline && tt != type::eos + ? parse_names (t, tt, pattern_mode::ignore) + : names ()); + + text (l) << "dump:"; + + // Dump directly into diag_stream. + // + ostream& os (*diag_stream); + + // Print directories as absolute. + // + const dir_path* orb (relative_base); + relative_base = &empty_dir_path; + + if (ns.empty ()) + { + if (scope_ != nullptr) + dump (*scope_, " "); // Indent two spaces. + else + os << " " << endl; + } + else + { + for (auto i (ns.begin ()), e (ns.end ()); i != e; ++i) + { + name& n (*i); + name o (n.pair ? move (*++i) : name ()); + + const target* t (enter_target::find_target (*this, n, o, l, trace)); + + if (t != nullptr) + dump (*t, " "); // Indent two spaces. + else + { + os << " ' << endl; + } + } + } + + relative_base = orb; + + if (tt != type::eos) + next (t, tt); // Swallow newline. + } + string parser:: parse_variable_name (names&& ns, const location& l) { -- cgit v1.1