1 /* 2 ================================================================================ 3 PROJECT: 4 5 Eddy C++ Utilities Project 6 7 CONTENTS: 8 9 Definition of classes EDDY_DebugScope and EDDY_Debug. 10 11 NOTES: 12 13 These classes along with the #defined macros constitute a simple 14 debugging facility that supports assertions, messages, warnings, etc. 15 as well as a simple stack tracing functionality. These functionalities 16 are preprocessed out unless EDDY_OPTION_DEBUG is defined. This is 17 useful to allow expensive assertions and such during debugging and have 18 them automatically stripped out for release builds. 19 20 See also the notes under the "Class Definition" sections of this file. 21 22 PROGRAMMERS: 23 24 John Eddy (jpeddy@sandia.gov) (JE) 25 26 ORGANIZATION: 27 28 Sandia National Laboratories 29 30 COPYRIGHT: 31 32 See the LICENSE file in the top level JEGA directory. 33 34 VERSION: 35 36 1.0.0 37 38 CHANGES: 39 40 Thu May 22 13:52:29 2003 - Original Version (JE) 41 42 ================================================================================ 43 */ 44 45 46 /* 47 ================================================================================ 48 Document This File 49 ================================================================================ 50 */ 51 /** \file 52 * \brief Contains the definition classes EDDY_DebugScope and EDDY_Debug. 53 */ 54 55 56 57 58 /* 59 ================================================================================ 60 Prevent Multiple Inclusions 61 ================================================================================ 62 */ 63 #ifndef EDDY_UTILITIES_EDDY_DEBUGSCOPE_HPP 64 #define EDDY_UTILITIES_EDDY_DEBUGSCOPE_HPP 65 66 67 68 69 70 71 72 /* 73 ================================================================================ 74 Includes 75 ================================================================================ 76 */ 77 #include "config.hpp" 78 79 80 81 82 83 84 85 86 /* 87 ================================================================================ 88 Preprocessor Definitions and Macros 89 ================================================================================ 90 */ 91 #ifdef EDDY_OPTION_DEBUG 92 93 # include "../../config/include/current_function.hpp" 94 95 /// This macro causes a scope trace with messaging and program abort. 96 /** 97 * If \a a evaluates to true, this macro will print the message of \a b, 98 * print a scope trace, and abort the program. It will also inform of 99 * the file and line number where the problem occurred. 100 * 101 * \param a The logical test based on which to abort. 102 * \param b The message to report along with file and line. 103 */ 104 # define EDDY_DEBUG(a, b) \ 105 if(a) { \ 106 eddy::utilities::EDDY_Debug::_Report((b), __FILE__, __LINE__); \ 107 } 108 109 /// This macro causes a scope trace with messaging (but no abort). 110 /** 111 * If \a a evaluates to true, this macro will print the message of \a b and 112 * print a scope trace. It will also inform of the file and line 113 * number where the problem occurred. 114 * 115 * \param a The logical test based on which to warn. 116 * \param b The message to report along with file and line. 117 */ 118 # define EDDY_WARNING(a, b) \ 119 if(a) { \ 120 eddy::utilities::EDDY_Debug::_Warning((b), __FILE__, __LINE__); \ 121 } 122 123 /// This macro causes a scope trace and program abort. 124 /** 125 * If \a a evaluates to true, this macro will print a scope trace 126 * and abort the program. It will also inform of the file and line 127 * number where the problem occurred. 128 * 129 * \param a The logical description of the exceptional condition. 130 */ 131 # define EDDY_ASSERT(a) \ 132 if(!(a)) { \ 133 eddy::utilities::EDDY_Debug::_Assert(#a, __FILE__, __LINE__); \ 134 } 135 136 /// This macro enables catching of signal \a a. 137 /** 138 * When a signal is caught (such as SIGSEGV, etc.), this method will 139 * indicate which signal was caught, print a scope trace, and abort 140 * the program. The allowable signals are: 141 * 142 * -SIGSEGV - Illegal storage access. 143 * -SIGINT - CTRL+C interrupt. 144 * -SIGFPE - Floating-point error, such as overflow, division by zero, 145 * or invalid operation. 146 * -SIGILL - Illegal instruction. 147 * -SIGTERM - Termination request sent to the program. 148 * -SIGABRT - Abnormal termination. 149 * 150 * \param a The signal value to enable catching of by the EDDY_DEBUGSCOPE 151 * project. 152 */ 153 # define EDDY_DEBUGSIGNAL(a) \ 154 eddy::utilities::EDDY_Debug::_RegisterSignal(a); 155 156 /// This macro pushes \a a onto the scope trace stack. 157 /** 158 * This macro actually creates an object of type EDDY_DebugScope identified 159 * by \a a. \a a should be a string literal like "someclass::somefunc". 160 * In case of a scope trace, the text associated with this object will be 161 * printed in turn. This should appear at the head of each method or 162 * function. When this object goes out of scope (when the method or 163 * function exits), its destructor will be called (guaranteed by C++) and 164 * it will be removed from the scope trace stack. 165 * 166 * \param a The text to be associated with the newly created debug scope 167 * object. 168 */ 169 # define EDDY_DEBUGSCOPE(a) \ 170 eddy::utilities::EDDY_DebugScope otb_debugscope_(a); 171 172 /** 173 * \brief This macro pushes the name of the current function onto the scope 174 * trace stack. 175 * 176 * This macro uses the EDDY_DEBUGSCOPE macro with an argument of 177 * EDDY_CURRENT_FUNCTION. 178 */ 179 # define EDDY_FUNC_DEBUGSCOPE \ 180 EDDY_DEBUGSCOPE(EDDY_CURRENT_FUNCTION) 181 182 /// This macro causes a print of the scope trace. 183 /** 184 * This causes the printing of each EDDY_DebugScope object text 185 * in the order that they were pushed onto the stack. The text 186 * is printed to standard error. 187 */ 188 # define EDDY_TRACESCOPE \ 189 eddy::utilities::EDDY_DebugScope::_PrintScopeTrace(); 190 191 /// This macro causes a message to be presented on standard error. 192 /** 193 * If \a a evaluates to true, this macro will print the message of \a b. 194 * It will neither print a scope trace nor abort the program. It will 195 * inform of the file and line number where the message originated. 196 * 197 * \param a The logical test based on which to print a message. 198 * \param b The message to print along with file and line. 199 */ 200 # define EDDY_MESSAGE(a, b) \ 201 if(a) { \ 202 eddy::utilities::EDDY_Debug::_Message((b),__FILE__,__LINE__); \ 203 } 204 205 /// This macro causes execution of the statement \a a. 206 /** 207 * This macro doesn't cause abortion or scope tracing. It simply 208 * causes execution of the statement represented by \a a. 209 * 210 * \param a The statement to execute if debug scope is enabled and not 211 * otherwise. A semicolon will automatically appended. 212 */ 213 # define EDDY_DEBUGEXEC(a) a; 214 215 #else 216 217 /// Expands to nothing because EDDY_OPTION_DEBUG is not defined. 218 # define EDDY_DEBUG(a, b) 219 220 /// Expands to nothing because EDDY_OPTION_DEBUG is not defined. 221 # define EDDY_WARNING(a, b) 222 223 /// Expands to nothing because EDDY_OPTION_DEBUG is not defined. 224 # define EDDY_ASSERT(a) 225 226 /// Expands to nothing because EDDY_OPTION_DEBUG is not defined. 227 # define EDDY_DEBUGSIGNAL(a) 228 229 /// Expands to nothing because EDDY_OPTION_DEBUG is not defined. 230 # define EDDY_DEBUGSCOPE(a) 231 232 /// Expands to nothing because EDDY_OPTION_DEBUG is not defined. 233 # define EDDY_FUNC_DEBUGSCOPE 234 235 /// Expands to nothing because EDDY_OPTION_DEBUG is not defined. 236 # define EDDY_TRACESCOPE 237 238 /// Expands to nothing because EDDY_OPTION_DEBUG is not defined. 239 # define EDDY_MESSAGE(a, b) 240 241 /// Expands to nothing because EDDY_OPTION_DEBUG is not defined. 242 # define EDDY_DEBUGEXEC(a) 243 244 #endif 245 246 247 248 249 250 251 252 253 254 /* 255 ================================================================================ 256 Namespace Aliases 257 ================================================================================ 258 */ 259 260 261 262 263 264 265 266 267 /* 268 ================================================================================ 269 Begin Namespace 270 ================================================================================ 271 */ 272 namespace eddy { 273 namespace utilities { 274 275 276 277 278 279 280 /* 281 ================================================================================ 282 This Code is Only Compiled in DebugMode 283 ================================================================================ 284 */ 285 #ifdef EDDY_OPTION_DEBUG 286 287 288 289 290 291 /* 292 ================================================================================ 293 Forward Declares 294 ================================================================================ 295 */ 296 class EDDY_Debug; 297 class EDDY_DebugScope; 298 299 300 301 302 303 304 305 306 307 308 /* 309 ================================================================================ 310 Class Definition for EDDY_DebugScope 311 ================================================================================ 312 */ 313 314 /// Class used to manage the rudimentary scope tracing functionality. 315 /** 316 * This class only exists if EDDY_OPTION_DEBUG is defined. 317 * This class stores a list of strings which should describe methods or 318 * functions. When one of these is created, the string passed in is 319 * pushed onto the list and when it is destroyed, the string is popped 320 * off the list. In case of a scope trace, all the strings currently 321 * on the stack are printed out in reverse order. 322 */ 323 class EDDY_SL_IEDECL EDDY_DebugScope 324 { 325 /* 326 ============================================================================ 327 Member Data Declarations 328 ============================================================================ 329 */ 330 private: 331 332 /** 333 * \brief Pointer to the text spit out for this object 334 * in the event of a scope trace. 335 */ 336 const char* const _data; 337 338 /** 339 * \brief Pointer to the next of this type to show up 340 * in the event of a scope trace. 341 */ 342 EDDY_DebugScope* _next; 343 344 /** 345 * \brief Pointer to the very first of this type to show up 346 * in the event of a scope trace. 347 */ 348 static EDDY_DebugScope* _top; 349 350 /* 351 ============================================================================ 352 Mutators 353 ============================================================================ 354 */ 355 public: 356 357 358 359 360 361 /* 362 ============================================================================ 363 Accessors 364 ============================================================================ 365 */ 366 public: 367 368 369 370 371 372 /* 373 ============================================================================ 374 Public Methods 375 ============================================================================ 376 */ 377 public: 378 379 /// This method is in the expansion of the EDDY_TRACESCOPE macro. 380 /** 381 * It causes a listing of entered but not yet exited method and 382 * functions having an EDDY_DEBUGSCOPE statement. The listing is 383 * printed to the standard output. 384 */ 385 static 386 void 387 _PrintScopeTrace( 388 ) throw(); 389 390 /* 391 ============================================================================ 392 Subclass Visible Methods 393 ============================================================================ 394 */ 395 protected: 396 397 398 399 400 401 /* 402 ============================================================================ 403 Subclass Overridable Methods 404 ============================================================================ 405 */ 406 public: 407 408 409 protected: 410 411 412 private: 413 414 415 416 417 418 /* 419 ============================================================================ 420 Private Methods 421 ============================================================================ 422 */ 423 private: 424 425 426 427 428 429 /* 430 ============================================================================ 431 Structors 432 ============================================================================ 433 */ 434 public: 435 436 /// Constructs an EDDY_DebugScope object with _data = name 437 /** 438 * \param name The name to be associated with this stack entry. 439 */ 440 EDDY_DebugScope( 441 const char* name 442 ) throw(); 443 444 /// Destructs an EDDY_DebugScope object 445 /** 446 * This has the effect of removing it from the list of scope traced 447 * objects. 448 */ 449 ~EDDY_DebugScope( 450 ) throw(); 451 452 }; // class EDDY_DebugScope 453 454 455 456 457 458 /* 459 ================================================================================ 460 Class Definition for EDDY_Debug 461 ================================================================================ 462 */ 463 464 /// Class used to manage errors, warnings, etc. and show them to the user. 465 /** 466 * Like the EDDY_DebugScope class, this class only exists if EDDY_OPTION_DEBUG 467 * is defined. This class handles errors, warning, messages, etc. issued 468 * by the user in debug mode. It is part of this rudimentary debugging 469 * facility that supports assertions and scope tracing. 470 */ 471 class EDDY_SL_IEDECL EDDY_Debug 472 { 473 /* 474 ============================================================================ 475 Member Data Declarations 476 ============================================================================ 477 */ 478 private: 479 480 481 482 /* 483 ============================================================================ 484 Mutators 485 ============================================================================ 486 */ 487 public: 488 489 490 491 /* 492 ============================================================================ 493 Accessors 494 ============================================================================ 495 */ 496 public: 497 498 499 500 /* 501 ============================================================================ 502 Public Methods 503 ============================================================================ 504 */ 505 public: 506 507 /** 508 * \brief This method is in the expansion of the 509 * EDDY_DEBUG(cond, message) macro. 510 * 511 * It causes the supplied failure message \a message to appear. 512 * This method causes a scope trace print and program abort. 513 * 514 * \param message The message to display. 515 * \param fileName The name of the file in which the problem occurred. 516 * \param line The line number in the file on which the problem 517 * occurred. 518 */ 519 static 520 void 521 _Report( 522 const char* message, 523 const char* fileName, 524 long line 525 ) throw(); 526 527 528 /** 529 * \brief This method is in the expansion of the 530 * EDDY_WARNING(cond, message) macro. 531 * 532 * It causes the supplied warning message \a message to appear. 533 * This method causes a scope trace print (without program abort). 534 * 535 * \param message The message to display. 536 * \param fileName The name of the file in which the problem occurred. 537 * \param line The line number in the file on which the problem 538 * occurred. 539 */ 540 static 541 void 542 _Warning( 543 const char* message, 544 const char* fileName, 545 long line 546 ) throw(); 547 548 /** 549 * \brief This method is in the expansion of the 550 * EDDY_MESSAGE(cond, message) macro. 551 * 552 * It causes the supplied message \a message to appear. 553 * This method does not cause a scope trace or program abort. 554 * 555 * \param message The message to display. 556 * \param fileName The name of the file from which the message was 557 * sent. 558 * \param line The line number in the file from which the message was 559 * sent. 560 */ 561 static 562 void 563 _Message( 564 const char* message, 565 const char* fileName, 566 long line 567 ) throw(); 568 569 /// This method is in the expansion of the EDDY_ASSERT(cond) macro. 570 /** 571 * It causes the supplied message \a message which is the text 572 * equivalent of the \a cond if the EDDY_ASSERT macro is used to 573 * appear. This method causes a scope trace print and program abort. 574 * 575 * \param message The message to display. 576 * \param fileName The name of the file in which the problem occurred. 577 * \param line The line number in the file on which the problem 578 * occurred. 579 */ 580 static 581 void 582 _Assert( 583 const char* message, 584 const char* fileName, 585 long line 586 ) throw(); 587 588 /// This method is in the expansion of the EDDY_DEBUGSIGNAL(sig) macro. 589 /** 590 * The macro registers this function as a callback in the case of 591 * the supplied signal. 592 * 593 * \param val The value of the signal that was caught and sent here. 594 */ 595 static 596 void 597 _Signal( 598 int val 599 ) throw(); 600 601 /// This method is the expansion of EDDY_DEBUGSIGNAL(a) 602 /** 603 * This method registers the signal handler for \a sig as 604 * _Signal(int). 605 * 606 * \param sig The value of the signal that will be caught and sent to 607 * _Signal(int). 608 */ 609 static 610 void 611 _RegisterSignal( 612 int sig 613 ) throw(); 614 615 /* 616 ============================================================================ 617 Subclass Visible Methods 618 ============================================================================ 619 */ 620 protected: 621 622 623 624 625 626 /* 627 ============================================================================ 628 Subclass Overridable Methods 629 ============================================================================ 630 */ 631 public: 632 633 634 protected: 635 636 637 private: 638 639 640 641 642 643 /* 644 ============================================================================ 645 Private Methods 646 ============================================================================ 647 */ 648 private: 649 650 651 652 653 654 /* 655 ============================================================================ 656 Structors 657 ============================================================================ 658 */ 659 public: 660 661 private: 662 663 /// This constructor is private and has no implementation. 664 /** 665 * All methods of this class are static and thus it should not and 666 * can not be instantiated. 667 */ 668 EDDY_Debug( 669 ); 670 671 672 }; // class EDDY_Debug 673 674 675 676 #endif // #ifdef EDDY_OPTION_DEBUG 677 678 679 680 681 /* 682 ================================================================================ 683 End Namespace 684 ================================================================================ 685 */ 686 } // namespace utilities 687 } // namespace eddy 688 689 690 691 692 693 694 695 /* 696 ================================================================================ 697 Include Inlined Methods File 698 ================================================================================ 699 */ 700 #include "./inline/EDDY_DebugScope.hpp.inl" 701 702 703 704 705 /* 706 ================================================================================ 707 End of Multiple Inclusion Check 708 ================================================================================ 709 */ 710 #endif // EDDY_UTILITIES_EDDY_DEBUGSCOPE_HPP 711