From 557269660c1d9796a7cf9e911efb9262f645e359 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 22 Nov 2016 12:10:03 +0200 Subject: Use diagnostics facility from libbutl --- build2/diagnostics | 213 +++++++++++------------------------------------------ 1 file changed, 42 insertions(+), 171 deletions(-) (limited to 'build2/diagnostics') diff --git a/build2/diagnostics b/build2/diagnostics index 6b89903..a58e9c7 100644 --- a/build2/diagnostics +++ b/build2/diagnostics @@ -5,15 +5,14 @@ #ifndef BUILD2_DIAGNOSTICS #define BUILD2_DIAGNOSTICS -#include -#include +#include #include #include namespace build2 { - struct diag_record; + using butl::diag_record; // Throw this exception to terminate the build. The handler should // assume that the diagnostics has already been issued. @@ -109,150 +108,10 @@ namespace build2 os.iword (stream_verb_index) = static_cast (v + 1); } - // Diagnostic facility, base infrastructure (potentially reusable). + // Diagnostic facility, base infrastructure. // - extern ostream* diag_stream; - - template struct diag_prologue; - template struct diag_mark; - - typedef void (*diag_epilogue) (const diag_record&); - - struct diag_record - { - template - friend const diag_record& - operator<< (const diag_record& r, const T& x) - { - r.os << x; - return r; - } - - diag_record (): empty_ (true), epilogue_ (nullptr) {} - - template - explicit - diag_record (const diag_prologue& p) - : empty_ (true), epilogue_ (nullptr) { *this << p;} - - template - explicit - diag_record (const diag_mark& m) - : empty_ (true), epilogue_ (nullptr) { *this << m;} - - ~diag_record () noexcept (false); - - void - append (diag_epilogue e) const - { - if (e != nullptr) - { - assert (epilogue_ == nullptr); // No multiple epilogues support. - epilogue_ = e; - } - - if (empty_) - empty_ = false; - else - os << "\n "; - } - - // Move constructible-only type. - // - // Older versions of libstdc++ don't have the ostringstream move support - // and accuratly detecting its version is non-trivial. So we always use - // the pessimized implementation with libstdc++. Luckily, GCC doesn't seem - // to be needing move due to copy/move elision. - // - diag_record (diag_record&& r) -#ifndef __GLIBCXX__ - : os (move (r.os)) -#endif - { - empty_ = r.empty_; - epilogue_ = r.epilogue_; - - if (!empty_) - { -#ifdef __GLIBCXX__ - stream_verb (os, stream_verb (r.os)); - os << r.os.str (); -#endif - r.empty_ = true; - r.epilogue_ = nullptr; - } - } - - diag_record& operator= (diag_record&&) = delete; - - diag_record (const diag_record&) = delete; - diag_record& operator= (const diag_record&) = delete; - - public: - mutable std::ostringstream os; - - private: - mutable bool empty_; - mutable diag_epilogue epilogue_; - }; - - template - struct diag_prologue: B - { - diag_prologue (diag_epilogue e = nullptr): B (), epilogue_ (e) {} - - template - diag_prologue (A&&... a) - : B (forward (a)...), epilogue_ (nullptr) {} - - template - diag_prologue (diag_epilogue e, A&&... a) - : B (forward (a)...), epilogue_ (e) {} - - template - diag_record - operator<< (const T& x) const - { - diag_record r; - r.append (epilogue_); - B::operator() (r); - r << x; - return r; - } - - friend const diag_record& - operator<< (const diag_record& r, const diag_prologue& p) - { - r.append (p.epilogue_); - p (r); - return r; - } - - private: - diag_epilogue epilogue_; - }; - - template - struct diag_mark: B - { - diag_mark (): B () {} - - template - diag_mark (A&&... a): B (forward (a)...) {} - - template - diag_record - operator<< (const T& x) const - { - return B::operator() () << x; - } - - friend const diag_record& - operator<< (const diag_record& r, const diag_mark& m) - { - return r << m (); - } - }; + using butl::diag_stream; + using butl::diag_epilogue; // Diagnostic facility, project specifics. // @@ -274,7 +133,6 @@ namespace build2 const char* name_; const uint16_t sverb_; }; - typedef diag_prologue simple_prologue; class location { @@ -313,17 +171,19 @@ namespace build2 const location loc_; const uint16_t sverb_; }; - typedef diag_prologue location_prologue; struct basic_mark_base { + using simple_prologue = butl::diag_prologue; + using location_prologue = butl::diag_prologue; + explicit - basic_mark_base (uint16_t (*sverb) (), - const char* type, + basic_mark_base (const char* type, + uint16_t (*sverb) () = &stream_verb_map, const char* mod = nullptr, const char* name = nullptr, const void* data = nullptr, - diag_epilogue epilogue = nullptr) + diag_epilogue* epilogue = nullptr) : sverb_ (sverb), type_ (type), mod_ (mod), name_ (name), data_ (data), epilogue_ (epilogue) {} @@ -354,9 +214,9 @@ namespace build2 const char* mod_; const char* name_; const void* data_; - const diag_epilogue epilogue_; + diag_epilogue* const epilogue_; }; - typedef diag_mark basic_mark; + using basic_mark = butl::diag_mark; extern const basic_mark error; extern const basic_mark warn; @@ -374,36 +234,47 @@ namespace build2 trace_mark_base (const char* mod, const char* name, const void* data = nullptr) - : basic_mark_base ([]() {return stream_verb_max;}, - "trace", - mod, name, + : basic_mark_base ("trace", + []() {return stream_verb_max;}, + mod, + name, data) {} }; - typedef diag_mark trace_mark; - - typedef trace_mark tracer; + using trace_mark = butl::diag_mark; + using tracer = trace_mark; // fail // - template struct fail_mark_base: basic_mark_base { explicit - fail_mark_base (const void* data = nullptr) - : basic_mark_base (&stream_verb_map, - "error", - nullptr, nullptr, + fail_mark_base (const char* type, + const void* data = nullptr) + : basic_mark_base (type, + &stream_verb_map, + nullptr, + nullptr, data, - &epilogue) {} - - static void - epilogue (const diag_record&) {throw E ();} + [](const diag_record&) {throw failed ();}) {} }; + using fail_mark = butl::diag_mark; - template - using fail_mark = diag_mark>; + struct fail_end_base + { + [[noreturn]] void + operator() (const diag_record& r) const + { + // If we just throw then the record's destructor will see an active + // exception and will not flush the record. + // + r.flush (); + throw failed (); + } + }; + using fail_end = butl::diag_noreturn_end; - extern const fail_mark fail; + extern const fail_mark fail; + extern const fail_end endf; } #endif // BUILD2_DIAGNOSTICS -- cgit v1.1