From 530e8914ba00ce0e7ee89ba30d2b88f2c09f43c9 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sat, 16 Dec 2017 14:14:15 +0200 Subject: Split stream verbosity into components (path, extension) Use to make sure structured result output always contains absolute target path. --- build2/b.cxx | 13 ++++---- build2/diagnostics.hxx | 81 ++++++++++++++++++++++++++++++++++--------------- build2/dump.cxx | 51 +++++++++++++++---------------- build2/name.cxx | 6 ++-- build2/parser.cxx | 7 ----- build2/prerequisite.cxx | 2 +- build2/spec.cxx | 2 +- build2/target-key.hxx | 5 ++- build2/target.cxx | 26 +++++++++------- build2/utility.cxx | 2 +- 10 files changed, 111 insertions(+), 84 deletions(-) (limited to 'build2') diff --git a/build2/b.cxx b/build2/b.cxx index 0d88f5f..7bb9484 100644 --- a/build2/b.cxx +++ b/build2/b.cxx @@ -105,16 +105,17 @@ namespace build2 // Let's go with the portable one for now and see how it goes (we // can always add a format version, e.g., --structured-result=2). - // Set the stream verbosity to 0 to suppress extension printing by - // default (this can still be overriden by the target type's print - // function as is the case for file{}, for example). + // Set the stream extension verbosity to 0 to suppress extension + // printing by default (this can still be overriden by the target + // type's print function as is the case for file{}, for example). + // And set the path verbosity to 1 to always print absolute. // - uint16_t v (stream_verb (cout)); - stream_verb (cout, 0); + stream_verbosity sv (stream_verb (cout)); + stream_verb (cout, stream_verbosity (1, 0)); cout << ' ' << at.as_target () << endl; - stream_verb (cout, v); + stream_verb (cout, sv); } } } diff --git a/build2/diagnostics.hxx b/build2/diagnostics.hxx index 65b1834..9a020d3 100644 --- a/build2/diagnostics.hxx +++ b/build2/diagnostics.hxx @@ -69,44 +69,75 @@ namespace build2 template inline void l5 (const F& f) {if (verb >= 5) f ();} template inline void l6 (const F& f) {if (verb >= 6) f ();} - // Stream verbosity level. It is determined by the diagnostic type (e.g., - // trace always has maximum verbosity) as well as the program verbosity. It - // is used to decide whether to print relative/absolute paths, and default + // Stream verbosity level. Determined by the diagnostic type (e.g., trace + // always has maximum verbosity) as well as the program verbosity. It is + // used to decide whether to print relative/absolute paths and default // target extensions. // - // 0 - minimum - // 1 - intermediate - // 2 - maximum - // // Currently we have the following program to stream verbosity mapping: // - // fail/error/warn/info <2:0 2:1 >2:2 - // trace *:2 + // fail/error/warn/info <2:{0,0} 2:{0,1} >2:{1,2} + // trace *:{1,2} // // A stream that hasn't been (yet) assigned any verbosity explicitly (e.g., // ostringstream) defaults to maximum. // - const uint16_t stream_verb_min = 0; - const uint16_t stream_verb_max = 2; + struct stream_verbosity + { + union + { + struct + { + // 0 - print relative. + // 1 - print absolute. + // + uint16_t path: 1; + + // 0 - don't print. + // 1 - print if specified. + // 2 - print as 'foo.?' if unspecified and 'foo.' if specified as + // "no extension" (empty). + // + uint16_t extension: 2; + }; + uint16_t value_; + }; + + constexpr + stream_verbosity (uint16_t p, uint16_t e): path (p), extension (e) {} + + explicit + stream_verbosity (uint16_t v = 0): value_ (v) {} + }; + + constexpr stream_verbosity stream_verb_max = {1, 2}; // Default program to stream verbosity mapping, as outlined above. // - inline uint16_t - stream_verb_map () {return verb < 2 ? 0 : (verb > 2 ? 2 : 1);} + inline stream_verbosity + stream_verb_map () + { + return + verb < 2 ? stream_verbosity (0, 0) : + verb > 2 ? stream_verbosity (1, 2) : + /* */ stream_verbosity (0, 1); + } extern const int stream_verb_index; - inline uint16_t + inline stream_verbosity stream_verb (ostream& os) { - uint16_t v (static_cast (os.iword (stream_verb_index))); - return v == 0 ? stream_verb_max : v - 1; + long v (os.iword (stream_verb_index)); + return v == 0 + ? stream_verb_max + : stream_verbosity (static_cast (v - 1)); } inline void - stream_verb (ostream& os, uint16_t v) + stream_verb (ostream& os, stream_verbosity v) { - os.iword (stream_verb_index) = static_cast (v + 1); + os.iword (stream_verb_index) = static_cast (v.value_) + 1; } // Diagnostic facility, base infrastructure. @@ -187,7 +218,7 @@ namespace build2 simple_prologue_base (const char* type, const char* mod, const char* name, - uint16_t sverb) + stream_verbosity sverb) : type_ (type), mod_ (mod), name_ (name), sverb_ (sverb) {} void @@ -197,7 +228,7 @@ namespace build2 const char* type_; const char* mod_; const char* name_; - const uint16_t sverb_; + const stream_verbosity sverb_; }; class location @@ -224,7 +255,7 @@ namespace build2 const char* mod, const char* name, const location& l, - uint16_t sverb) + stream_verbosity sverb) : type_ (type), mod_ (mod), name_ (name), loc_ (l), sverb_ (sverb) {} @@ -233,7 +264,7 @@ namespace build2 const char* mod, const char* name, path&& f, - uint16_t sverb) + stream_verbosity sverb) : type_ (type), mod_ (mod), name_ (name), file_ (move (f)), loc_ (&file_), sverb_ (sverb) {} @@ -247,7 +278,7 @@ namespace build2 const char* name_; const path file_; const location loc_; - const uint16_t sverb_; + const stream_verbosity sverb_; }; struct basic_mark_base @@ -259,7 +290,7 @@ namespace build2 basic_mark_base (const char* type, const void* data = nullptr, diag_epilogue* epilogue = &diag_frame::apply, - uint16_t (*sverb) () = &stream_verb_map, + stream_verbosity (*sverb) () = &stream_verb_map, const char* mod = nullptr, const char* name = nullptr) : sverb_ (sverb), @@ -296,7 +327,7 @@ namespace build2 } protected: - uint16_t (*sverb_) (); + stream_verbosity (*sverb_) (); const char* type_; const char* mod_; const char* name_; diff --git a/build2/dump.cxx b/build2/dump.cxx index 714ae05..3f5aced 100644 --- a/build2/dump.cxx +++ b/build2/dump.cxx @@ -194,22 +194,18 @@ namespace build2 string& ind, const target& t, const scope& s, - bool relative) + bool rel) { // If requested, print the target and its prerequisites relative to the // scope. To achieve this we are going to temporarily lower the stream - // verbosity to level 1. The drawback of doing this is that we also lower - // the verbosity of extension printing (it wouldn't have been bad at all - // to get 'foo.?' for unassigned and 'foo.' for empty). + // path verbosity to level 0. // - // @@ Actually, all those foo.? look rather hairy... - // @@ Can't we change level to a bit mask? - // - uint16_t sv; - if (relative) + stream_verbosity osv, nsv; + if (rel) { - sv = stream_verb (os); - stream_verb (os, 1); + osv = nsv = stream_verb (os); + nsv.path = 0; + stream_verb (os, nsv); } if (t.group != nullptr) @@ -221,8 +217,8 @@ namespace build2 // if (!t.vars.empty ()) { - if (relative) - stream_verb (os, sv); // We want variable values in full. + if (rel) + stream_verb (os, osv); // We want variable values in full. os << endl << ind << '{'; @@ -232,8 +228,8 @@ namespace build2 os << endl << ind << '}'; - if (relative) - stream_verb (os, 1); + if (rel) + stream_verb (os, nsv); os << endl << ind << t << ':'; @@ -293,8 +289,8 @@ namespace build2 if (ps) { - if (relative) - stream_verb (os, sv); // We want variable values in full. + if (rel) + stream_verb (os, osv); // We want variable values in full. os << ':' << endl << ind << '{'; @@ -304,8 +300,8 @@ namespace build2 os << endl << ind << '}'; - if (relative) - stream_verb (os, 1); + if (rel) + stream_verb (os, nsv); if (i != e) // If we have another, get a new header. os << endl @@ -315,12 +311,15 @@ namespace build2 used = !ps; } - if (relative) - stream_verb (os, sv); + if (rel) + stream_verb (os, osv); } static void - dump_scope (ostream& os, string& ind, scope_map::const_iterator& i) + dump_scope (ostream& os, + string& ind, + scope_map::const_iterator& i, + bool rel) { const scope& p (i->second); const dir_path& d (i->first); @@ -335,7 +334,7 @@ namespace build2 os << ind << dir_path::traits::directory_separator; else { - dir_path rd (relative (d)); + const dir_path& rd (rel ? relative (d) : d); os << ind << (rd.empty () ? dir_path (".") : rd); } @@ -381,7 +380,7 @@ namespace build2 os << endl; // Extra newline between scope blocks. os << endl; - dump_scope (os, ind, i); + dump_scope (os, ind, i, true /* relative */); sb = true; } @@ -426,7 +425,7 @@ namespace build2 // string ind; ostream& os (*diag_stream); - dump_scope (os, ind, i); + dump_scope (os, ind, i, false /* relative */); os << endl; } @@ -439,7 +438,7 @@ namespace build2 string ind (cind); ostream& os (*diag_stream); - dump_scope (os, ind, i); + dump_scope (os, ind, i, false /* relative */); os << endl; } diff --git a/build2/name.cxx b/build2/name.cxx index f71c7c1..5621101 100644 --- a/build2/name.cxx +++ b/build2/name.cxx @@ -96,11 +96,11 @@ namespace build2 os << v; }; - uint16_t dv (stream_verb (os)); // Directory verbosity. + uint16_t dv (stream_verb (os).path); // Directory verbosity. auto write_dir = [dv, quote, &os, &write_string] (const dir_path& d) { - const string& s (dv < 2 + const string& s (dv < 1 ? diag_relative (d) : d.representation ()); if (quote) @@ -133,7 +133,7 @@ namespace build2 // Note: relative() may return empty. // - const dir_path& rd (dv < 2 ? relative (n.dir) : n.dir); // Relative. + const dir_path& rd (dv < 1 ? relative (n.dir) : n.dir); // Relative. const dir_path& pd (v ? rd : t ? rd.directory () : dir_path ()); diff --git a/build2/parser.cxx b/build2/parser.cxx index 1f2ab9d..48902b8 100644 --- a/build2/parser.cxx +++ b/build2/parser.cxx @@ -1883,11 +1883,6 @@ namespace build2 // 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) @@ -1918,8 +1913,6 @@ namespace build2 } } - relative_base = orb; - if (tt != type::eos) next (t, tt); // Swallow newline. } diff --git a/build2/prerequisite.cxx b/build2/prerequisite.cxx index 6233ec4..b8c1791 100644 --- a/build2/prerequisite.cxx +++ b/build2/prerequisite.cxx @@ -34,7 +34,7 @@ namespace build2 // const dir_path& s (pk.scope->out_path ()); - if (stream_verb (os) < 2) + if (stream_verb (os).path < 1) { const string& r (diag_relative (s, false)); diff --git a/build2/spec.cxx b/build2/spec.cxx index da581c8..0e5bd75 100644 --- a/build2/spec.cxx +++ b/build2/spec.cxx @@ -19,7 +19,7 @@ namespace build2 // Avoid printing './' in './@...', similar to what we do for the // {target,prerequisite}_key. // - if (stream_verb (os) < 2) + if (stream_verb (os).path < 1) { const string& r (diag_relative (s.src_base, false)); diff --git a/build2/target-key.hxx b/build2/target-key.hxx index f37713e..d9ae57c 100644 --- a/build2/target-key.hxx +++ b/build2/target-key.hxx @@ -72,14 +72,13 @@ namespace build2 operator!= (const target_key& x, const target_key& y) {return !(x == y);} // If the target type has a custom print function, call that. Otherwise, - // call to_stream() with the current stream verbosity as a third argument. - // Both are defined in target.cxx. + // call to_stream(). Both are defined in target.cxx. // ostream& operator<< (ostream&, const target_key&); ostream& - to_stream (ostream&, const target_key&, uint16_t ext_verb); + to_stream (ostream&, const target_key&, optional = nullopt); } namespace std diff --git a/build2/target.cxx b/build2/target.cxx index 99c002b..90b2511 100644 --- a/build2/target.cxx +++ b/build2/target.cxx @@ -307,7 +307,7 @@ namespace build2 r << "assuming target "; to_stream (r.os, target_key {&t.type (), &t.dir, &t.out, &t.name, ext}, - 2); // Always print the extension. + stream_verb_max); // Always print the extension. r << " is the same as the one with "; if (!k.ext) @@ -382,7 +382,7 @@ namespace build2 to_stream ( r.os, target_key {&t->type (), &t->dir, &t->out, &t->name, ext}, - 2); // Always print the extension. + stream_verb_max); // Always print the extension. r << " is the same as the one with "; if (!e) @@ -416,9 +416,11 @@ namespace build2 } ostream& - to_stream (ostream& os, const target_key& k, uint16_t ev) + to_stream (ostream& os, const target_key& k, optional osv) { - uint16_t dv (stream_verb (os)); // Directory verbosity. + stream_verbosity sv (osv ? *osv : stream_verb (os)); + uint16_t dv (sv.path); + uint16_t ev (sv.extension); // If the name is empty, then we want to print the last component of the // directory inside {}, e.g., dir{bar/}, not bar/dir{}. @@ -427,12 +429,12 @@ namespace build2 // Note: relative() returns empty for './'. // - const dir_path& rd (dv < 2 ? relative (*k.dir) : *k.dir); // Relative. + const dir_path& rd (dv < 1 ? relative (*k.dir) : *k.dir); // Relative. const dir_path& pd (n ? rd : rd.directory ()); // Parent. if (!pd.empty ()) { - if (dv < 2) + if (dv < 1) os << diag_relative (pd); else os << pd.representation (); @@ -472,7 +474,7 @@ namespace build2 // if (!k.out->empty ()) { - if (dv < 2) + if (dv < 1) { // Don't print '@./'. // @@ -666,15 +668,17 @@ namespace build2 void target_print_0_ext_verb (ostream& os, const target_key& k) { - uint16_t v (stream_verb (os)); - to_stream (os, k, v < 2 ? 0 : v); // Remap 1 to 0. + stream_verbosity sv (stream_verb (os)); + if (sv.extension == 1) sv.extension = 0; // Remap 1 to 0. + to_stream (os, k, sv); } void target_print_1_ext_verb (ostream& os, const target_key& k) { - uint16_t v (stream_verb (os)); - to_stream (os, k, v < 1 ? 1 : v); // Remap 0 to 1. + stream_verbosity sv (stream_verb (os)); + if (sv.extension == 0) sv.extension = 1; // Remap 0 to 1. + to_stream (os, k, sv); } // type info diff --git a/build2/utility.cxx b/build2/utility.cxx index d11b46d..df19b92 100644 --- a/build2/utility.cxx +++ b/build2/utility.cxx @@ -38,7 +38,7 @@ namespace std { using namespace build2; - return os << (stream_verb (os) < 2 + return os << (stream_verb (os).path < 1 ? diag_relative (p) : p.representation ()); } -- cgit v1.1