1 /************************************************************************** 2 Copyright: 3 (C) 2008 - 2012 Alexander Shaduri <ashaduri 'at' gmail.com> 4 License: See LICENSE_zlib.txt file 5 ***************************************************************************/ 6 /// \file 7 /// \author Alexander Shaduri 8 /// \ingroup hz 9 /// \weakgroup hz 10 /// @{ 11 12 #ifndef HZ_DEBUG_H 13 #define HZ_DEBUG_H 14 15 #include "hz_config.h" // feature macros 16 17 #include <cstdio> // std::fprintf(), std::vfprintf() 18 19 #ifndef __GNUC__ 20 #include <cstdarg> // std::va_start, va_list macro and friends 21 #endif 22 23 24 /* 25 #include <cassert> 26 #ifndef ASSERT // assert() is undefined if NDEBUG is defined. 27 # define ASSERT(a) assert(a) 28 #endif 29 */ 30 31 /** 32 \file 33 This file is a link between libhz (and its users) and libdebug. 34 It provides a way to write in libdebug-like API without actually 35 using libdebug. 36 37 Note that it provides only output functions. The setup functions 38 cannot be emulated (but you probably won't need them in libraries 39 anyway). 40 */ 41 42 43 // Use libdebug as is 44 #if defined(HZ_USE_LIBDEBUG) && (HZ_USE_LIBDEBUG) 45 46 // only output functions 47 #include "libdebug/libdebug_mini.h" 48 49 50 #else 51 52 // undef them in case libdebug was included 53 #ifdef debug_out_dump 54 #undef debug_out_dump 55 #endif 56 #ifdef debug_out_info 57 #undef debug_out_info 58 #endif 59 #ifdef debug_out_warn 60 #undef debug_out_warn 61 #endif 62 #ifdef debug_out_error 63 #undef debug_out_error 64 #endif 65 #ifdef debug_out_fatal 66 #undef debug_out_fatal 67 #endif 68 69 #ifdef debug_print_dump 70 #undef debug_print_dump 71 #endif 72 #ifdef debug_print_info 73 #undef debug_print_info 74 #endif 75 #ifdef debug_print_warn 76 #undef debug_print_warn 77 #endif 78 #ifdef debug_print_error 79 #undef debug_print_error 80 #endif 81 #ifdef debug_print_fatal 82 #undef debug_print_fatal 83 #endif 84 85 #ifdef DBG_FILE 86 #undef DBG_FILE 87 #endif 88 #ifdef DBG_LINE 89 #undef DBG_LINE 90 #endif 91 #ifdef DBG_FUNC_NAME 92 #undef DBG_FUNC_NAME 93 #endif 94 #ifdef DBG_FUNC_PRNAME 95 #undef DBG_FUNC_PRNAME 96 #endif 97 #ifdef DBG_FUNC 98 #undef DBG_FUNC 99 #endif 100 #ifdef DBG_FUNC_MSG 101 #undef DBG_FUNC_MSG 102 #endif 103 104 #ifdef DBG_POS 105 #undef DBG_POS 106 #endif 107 108 #ifdef DBG_TRACE_POINT_MSG 109 #undef DBG_TRACE_POINT_MSG 110 #endif 111 #ifdef DBG_TRACE_POINT_AUTO 112 #undef DBG_TRACE_POINT_AUTO 113 #endif 114 115 #ifdef DBG_FUNCTION_ENTER_MSG 116 #undef DBG_FUNCTION_ENTER_MSG 117 #endif 118 #ifdef DBG_FUNCTION_EXIT_MSG 119 #undef DBG_FUNCTION_EXIT_MSG 120 #endif 121 122 #ifdef DBG_ASSERT_MSG 123 #undef DBG_ASSERT_MSG 124 #endif 125 #ifdef DBG_ASSERT 126 #undef DBG_ASSERT 127 #endif 128 129 130 // emulate libdebug API through std::cerr 131 #if defined(HZ_EMULATE_LIBDEBUG) && HZ_EMULATE_LIBDEBUG 132 133 #include <iostream> 134 #include <cstdio> 135 #include <string> 136 137 // cerr / stderr have no buffering, so no need to sync them with each other. 138 139 140 #define debug_out_dump(domain, output) \ 141 std::cerr << "<dump> [" << (domain) << "] " << output 142 143 #define debug_out_info(domain, output) \ 144 std::cerr << "<info> [" << (domain) << "] " << output 145 146 #define debug_out_warn(domain, output) \ 147 std::cerr << "<warn> [" << (domain) << "] " << output 148 149 #define debug_out_error(domain, output) \ 150 std::cerr << "<error> [" << (domain) << "] " << output 151 152 #define debug_out_fatal(domain, output) \ 153 std::cerr << "<fatal> [" << (domain) << "] " << output 154 155 156 157 #ifdef __GNUC__ 158 159 // The "trim trailing comma" and "##" extensions are GNU features (works with intel too). 160 // The ## part is needed to avoid requirement of at least one argument after "format". 161 162 #define debug_print_dump(domain, format, ...) \ 163 std::fprintf(stderr, (std::string("<dump> [") + (domain) + "] " + format).c_str(), ## __VA_ARGS__) 164 165 #define debug_print_info(domain, format, ...) \ 166 std::fprintf(stderr, (std::string("<info> [") + (domain) + "] " + format).c_str(), ## __VA_ARGS__) 167 168 #define debug_print_warn(domain, format, ...) \ 169 std::fprintf(stderr, (std::string("<warn> [") + (domain) + "] " + format).c_str(), ## __VA_ARGS__) 170 171 #define debug_print_error(domain, format, ...) \ 172 std::fprintf(stderr, (std::string("<error> [") + (domain) + "] " + format).c_str(), ## __VA_ARGS__) 173 174 #define debug_print_fatal(domain, format, ...) \ 175 std::fprintf(stderr, (std::string("<fatal> [") + (domain) + "] " + format).c_str(), ## __VA_ARGS__) 176 177 178 179 #else // non-gcc compilers: 180 181 namespace hz { 182 namespace internal { debug_print_impl(const std::string & header,const char * format,...)183 inline void debug_print_impl(const std::string& header, const char* format, ...) 184 { 185 std::va_list ap; 186 va_start(ap, format); 187 std::vfprintf(stderr, (header + format).c_str(), ap); 188 va_end(ap); 189 } 190 } 191 } 192 193 #define debug_print_dump(domain, ...) \ 194 hz::internal::debug_print_impl(std::string("<dump> [") + (domain) + "] ", __VA_ARGS__) 195 196 #define debug_print_info(domain, ...) \ 197 hz::internal::debug_print_impl(std::string("<info> [") + (domain) + "] ", __VA_ARGS__) 198 199 #define debug_print_warn(domain, ...) \ 200 hz::internal::debug_print_impl(std::string("<warn> [") + (domain) + "] ", __VA_ARGS__) 201 202 #define debug_print_error(domain, ...) \ 203 hz::internal::debug_print_impl(std::string("<error> [") + (domain) + "] ", __VA_ARGS__) 204 205 #define debug_print_fatal(domain, ...) \ 206 hz::internal::debug_print_impl(std::string("<fatal> [") + (domain) + "] ", __VA_ARGS__) 207 208 209 #endif 210 211 212 213 #define DBG_FILE __FILE__ 214 #define DBG_LINE __LINE__ 215 216 217 #if defined HAVE_CXX___func__ && HAVE_CXX___func__ 218 #define DBG_FUNC_NAME __func__ 219 #elif defined HAVE_CXX___FUNCTION__ && HAVE_CXX___FUNCTION__ 220 #define DBG_FUNC_NAME __FUNCTION__ 221 #else 222 #define DBG_FUNC_NAME "unknown" 223 #endif 224 225 #ifdef __GNUC__ 226 #define DBG_FUNC_PRNAME __PRETTY_FUNCTION__ 227 #else 228 #define DBG_FUNC_PRNAME DBG_FUNC_NAME 229 #endif 230 231 232 #include <string> 233 234 namespace hz { 235 namespace internal { format_function_msg(const std::string & func,bool add_suffix)236 inline std::string format_function_msg(const std::string& func, bool add_suffix) 237 { 238 // if it's "bool<unnamed>::A::func(int)" or "bool test::A::func(int)", 239 // remove the return type and parameters. 240 std::string::size_type endpos = func.find('('); 241 if (endpos == std::string::npos) 242 endpos = func.size(); 243 244 // search for first space (after the parameter), or "<unnamed>". 245 std::string::size_type pos = func.find_first_of(" >"); 246 if (pos != std::string::npos) { 247 if (func[pos] == '>') 248 pos += 2; // skip :: 249 ++pos; // skip whatever character we're over 250 // debug_out_info("default", "pos: " << pos << ", endpos: " << endpos << "\n"); 251 return func.substr(pos >= endpos ? 0 : pos, endpos - pos) + (add_suffix ? "(): " : "()"); 252 } 253 return func.substr(0, endpos) + (add_suffix ? "(): " : "()"); 254 } 255 } 256 } 257 258 #define DBG_FUNC (hz::internal::format_function_msg(DBG_FUNC_PRNAME, false).c_str()) 259 260 #define DBG_FUNC_MSG (hz::internal::format_function_msg(DBG_FUNC_PRNAME, true).c_str()) 261 262 263 // Note: DBG_POS is not an object if emulated or disabled! Only valid for outputting to streams. 264 #define DBG_POS "(function: " << DBG_FUNC_NAME << "(), file: " << DBG_FILE \ 265 << ", line: " << DBG_LINE << ")" 266 267 268 #define DBG_TRACE_POINT_MSG(a) debug_out_dump("default", "Trace point \"" << #a << "\" reached at " << DBG_POS << ".\n") 269 #define DBG_TRACE_POINT_AUTO debug_out_dump("default", "Trace point reached at " << DBG_POS << ".\n") 270 271 #define DBG_FUNCTION_ENTER_MSG debug_out_dump("default", "ENTER: \"" << DBG_FUNC << "\"\n") 272 #define DBG_FUNCTION_EXIT_MSG debug_out_dump("default", "EXIT: \"" << DBG_FUNC << "\"\n") 273 274 275 #define DBG_ASSERT_MSG(cond, msg) \ 276 if (true) { \ 277 if (!(cond)) \ 278 debug_out_error("default", (msg) << "\n"); \ 279 } else (void)0 280 281 #define DBG_ASSERT(cond) \ 282 if (true) { \ 283 if (!(cond)) \ 284 debug_out_error("default", "ASSERTION FAILED: " << #cond << " at " << DBG_POS << "\n"); \ 285 } else (void)0 286 287 288 // No output at all 289 #else 290 291 // do/while block is needed to: 292 // 1. make " if(a) debug_out_info(); f(); " work correctly. 293 // 2. require terminating semicolon. 294 #define debug_out_dump(domain, output) if(true){}else(void)0 295 #define debug_out_info(domain, output) if(true){}else(void)0 296 #define debug_out_warn(domain, output) if(true){}else(void)0 297 #define debug_out_error(domain, output) if(true){}else(void)0 298 #define debug_out_fatal(domain, output) if(true){}else(void)0 299 300 #define debug_print_dump(domain, format, ...) if(true){}else(void)0 301 #define debug_print_info(domain, format, ...) if(true){}else(void)0 302 #define debug_print_warn(domain, format, ...) if(true){}else(void)0 303 #define debug_print_error(domain, format, ...) if(true){}else(void)0 304 #define debug_print_fatal(domain, format, ...) if(true){}else(void)0 305 306 #define DBG_FILE "" 307 #define DBG_LINE 0 308 309 #define DBG_FUNC_NAME "" 310 #define DBG_FUNC_PRNAME "" 311 #define DBG_FUNC "" 312 #define DBG_FUNC_MSG "" 313 314 // Note: DBG_POS is not an object if emulated or disabled! 315 #define DBG_POS "" 316 317 #define DBG_TRACE_POINT_MSG(a) if(true){}else(void)0 318 #define DBG_TRACE_POINT_AUTO if(true){}else(void)0 319 320 #define DBG_FUNCTION_ENTER_MSG if(true){}else(void)0 321 #define DBG_FUNCTION_EXIT_MSG if(true){}else(void)0 322 323 #define DBG_ASSERT_MSG(cond, msg) if(true){}else(void)0 324 #define DBG_ASSERT(cond) if(true){}else(void)0 325 326 #endif 327 328 329 // other stuff, emulated or not 330 331 // #ifdef debug_begin 332 // #undef debug_begin 333 // #endif 334 #define debug_begin() if(true){}else(void)0 335 336 // #ifdef debug_end 337 // #undef debug_end 338 // #endif 339 #define debug_end() if(true){}else(void)0 340 341 342 #define debug_indent_inc(...) if(true){}else(void)0 343 #define debug_indent_dec(...) if(true){}else(void)0 344 #define debug_indent_reset() if(true){}else(void)0 345 346 #define debug_indent "" 347 #define debug_unindent "" 348 #define debug_resindent "" 349 350 351 352 #endif 353 354 355 356 357 358 359 360 361 362 363 364 #endif 365 366 /// @} 367