/* Mantra - http://www.neuromancy.net/mantra * (c) 2007-2009 - The Neuromancy Society * * This code is released under the Artistic License 2.0. If you have not * received a copy of the license with this source code, you may find * this license at: * http://www.opensource.org/licenses/artistic-license-2.0.php * * $Id: nibble0.h 617 2010-03-11 06:29:57Z prez $ */ #ifndef MANTRA_TRACE_NIBBLE0_H #define MANTRA_TRACE_NIBBLE0_H 1 #ifndef ENABLE_MANTRA_TRACE #define MT_CP(x,...) do {} while (0) #define MT_COM(x,...) do {} while (0) #define MT_FUNC(...) do {} while (0) #define MT_RET(...) return __VA_ARGS__ #define MT_EB { #define MT_EE } #define MT_FB(...) do { #define MT_FE(...) return __VA_ARGS__; } while(0) #else // ENABLE_MANTRA_TRACE #include #include #include #include #include #include #include #include #include // CheckPoint -- MT_CP(format, args) // Args are separated by '%' signs. #define MT_CP(x,...) \ do { \ MT_ISON(checkpoint) \ { \ mantra::trace::trace_guard tg = t->guard(); \ mantra::trace::checkpoint(t, BOOST_PP_IF(BOOST_PP_TUPLE_SIZE((__VA_ARGS__)), \ boost::format(x) %, boost::format("%1%") % x) __VA_ARGS__); \ } \ } while (0) // Comment -- MT_COM(format, args) // Args are separated by '%' signs. #define MT_COM(x,...) \ do { \ MT_ISON(comment) \ { \ mantra::trace::trace_guard tg = t->guard(); \ mantra::trace::comment(t, BOOST_PP_IF(BOOST_PP_TUPLE_SIZE((__VA_ARGS__)), \ boost::format(x) %, boost::format("%1%") % x) __VA_ARGS__); \ } \ } while (0) // FunctionTrace -- MT_FUNC(args); #define MT_FUNC(...) \ mantra::trace::function __mantra_ft(mantra::trace::tss::get(), \ __FILE__, __LINE__, BOOST_CURRENT_FUNCTION); \ __mantra_ft BOOST_PP_EXPR_IF(BOOST_PP_TUPLE_SIZE((__VA_ARGS__)), <<) __VA_ARGS__ \ << mantra::trace::function::end_args() // FunctionTrace (return) -- MT_RET(value); #define MT_RET(...) \ do { \ BOOST_PP_EXPR_IF(BOOST_PP_TUPLE_SIZE((__VA_ARGS__)), return) \ __mantra_ft.end(__LINE__ \ BOOST_PP_COMMA_IF(BOOST_PP_TUPLE_SIZE((__VA_ARGS__))) __VA_ARGS__); \ BOOST_PP_EXPR_IF(BOOST_PP_NOT(BOOST_PP_TUPLE_SIZE((__VA_ARGS__))), return;) \ } while (0) // Exceptions (begin) -- MT_EB // Exceptions (end) -- MT_EE // NOTE: This syntax is weird, but necessary. #define MT_EB try { #define MT_EE \ } catch(...) { \ boost::exception_ptr e(boost::current_exception()); \ mantra::trace::exception(__FILE__, __LINE__, e); \ throw; \ } // GCC doesn't realize rethrow is always going to throw, so it complains // about control reaching end of non-void return func if the below is used // instead of just throw for the above MT_EE macro. Since they are functionally // equivalent, we can just let it slide for now. // boost::rethrow_exception(e); // Combination of MT_FUNC and MT_EB / MT_RET and MT_EE #define MT_FB(...) do { MT_EB MT_FUNC(__VA_ARGS__) #define MT_FE(...) MT_RET(__VA_ARGS__); MT_EE } while (0) namespace mantra { namespace trace { // 0x0001 MANTRA_API void comment(tss *tss, const boost::format &fmt); // 0x0002 MANTRA_API void checkpoint(tss *tss, const boost::format &fmt); // 0x0004 MANTRA_API void exception(const char *file, unsigned int line, const boost::exception_ptr &e); // 0x0008 class MANTRA_API function { public: function(tss *tss, const char *file, unsigned int line, const char *func); ~function(); struct end_args {}; function &operator<<(const end_args &in); template function &operator<<(T &in) { return append(in); } template function &operator<<(const T &in) { return append(in); } void end(int line) { return_line_ = line; } template T &end(int line, T &in) { return end2(line, in); } template const T &end(int line, const T &in) { return end2(line, in); } private: tss *tss_; const char *file_; unsigned int line_; const char *func_; std::vector args_; unsigned int return_line_; dynamic_arg return_value_; bool tracing_; template function &append(T &in); template T &end2(int line, T &in); }; // --------------------------------------------------------------------------- // Inline Functions // --------------------------------------------------------------------------- inline function::function(tss *t, const char *file, unsigned int line, const char *func) : tss_(t), file_(file), line_(line), func_(func), return_line_(0u) { if (tss_) tracing_ = trace::codetype_check(tss_->codetype(), tracetype::function); } template inline function &function::append(T &in) { if (tss_ && !tss_->in_trace() && tracing_) { trace_guard tg = tss_->guard(); args_.push_back(dynamic_arg(in)); } return *this; } template inline T &function::end2(int line, T &in) { end(line); tss_ = tss::get(); if (!tss_ || tss_->in_trace()) return in; tracing_ = trace::codetype_check(tss_->codetype(), tracetype::function); if (tracing_) { trace_guard tg = tss_->guard(); return_value_ = dynamic_arg(in); } return in; } } } // namespace mantra::trace #endif // ENABLE_MANTRA_TRACE #endif // MANTRA_TRACE_NIBBLE0_H