1 /* -*- Mode: C; tab-width: 4 -*- 2 * 3 * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 //--------------------------------------------------------------------------------------------------------------------------- 19 /*! @header DebugServices 20 21 Debugging Library 22 */ 23 24 #ifndef __DEBUG_SERVICES__ 25 #define __DEBUG_SERVICES__ 26 27 #include <stdarg.h> 28 29 #include "CommonServices.h" 30 31 #if( TARGET_OS_VXWORKS ) 32 #include "logLib.h" 33 #endif 34 35 #if 0 36 #pragma mark == Settings == 37 #endif 38 39 //=========================================================================================================================== 40 // Settings 41 //=========================================================================================================================== 42 43 // General 44 45 #if( !defined( DEBUG ) ) 46 #define DEBUG 0 47 #endif 48 49 #if( defined( NDEBUG ) && DEBUG ) 50 #error NDEBUG defined and DEBUG is also enabled...they need to be in-sync 51 #endif 52 53 // AssertMacros.h/Debugging.h overrides. 54 55 #if( !defined( DEBUG_OVERRIDE_APPLE_MACROS ) ) 56 #define DEBUG_OVERRIDE_APPLE_MACROS 1 57 #endif 58 59 // Routine name. Uses ISO __func__ where possible. Otherwise, uses the best thing that is available (if anything). 60 61 #if( defined( __MWERKS__ ) || ( __GNUC__ > 2 ) || ( ( __GNUC__ == 2 ) && ( __GNUC_MINOR__ >= 9 ) ) ) 62 #define __ROUTINE__ __func__ 63 #elif( defined( __GNUC__ ) ) 64 #define __ROUTINE__ __PRETTY_FUNCTION__ 65 #elif( defined( _MSC_VER ) && !defined( _WIN32_WCE ) ) 66 #define __ROUTINE__ __FUNCTION__ 67 #else 68 #define __ROUTINE__ "" 69 #endif 70 71 // Variable argument macro support. Use ANSI C99 __VA_ARGS__ where possible. Otherwise, use the next best thing. 72 73 #if( defined( __GNUC__ ) ) 74 #if( ( __GNUC__ > 3 ) || ( ( __GNUC__ == 3 ) && ( __GNUC_MINOR__ >= 3) ) ) 75 #define DEBUG_C99_VA_ARGS 1 76 #define DEBUG_GNU_VA_ARGS 0 77 #else 78 #define DEBUG_C99_VA_ARGS 0 79 #define DEBUG_GNU_VA_ARGS 1 80 #endif 81 #elif( defined( __MWERKS__ ) ) 82 #define DEBUG_C99_VA_ARGS 1 83 #define DEBUG_GNU_VA_ARGS 0 84 #else 85 #define DEBUG_C99_VA_ARGS 0 86 #define DEBUG_GNU_VA_ARGS 0 87 #endif 88 89 #if 0 90 #pragma mark == Output == 91 #endif 92 93 //--------------------------------------------------------------------------------------------------------------------------- 94 /*! @defined DEBUG_FPRINTF_ENABLED 95 96 @abstract Enables ANSI C fprintf output. 97 */ 98 99 #if( !defined( DEBUG_FPRINTF_ENABLED ) ) 100 #if( !TARGET_API_MAC_OSX_KERNEL && !TARGET_OS_WINDOWS_CE ) 101 #define DEBUG_FPRINTF_ENABLED 1 102 #else 103 #define DEBUG_FPRINTF_ENABLED 0 104 #endif 105 #else 106 #if( TARGET_API_MAC_OSX_KERNEL || TARGET_OS_WINDOWS_CE ) 107 #error fprintf enabled, but not supported on Mac OS X kernel or Windows CE 108 #endif 109 #endif 110 111 //--------------------------------------------------------------------------------------------------------------------------- 112 /*! @defined DEBUG_MAC_OS_X_IOLOG_ENABLED 113 114 @abstract Enables IOLog (Mac OS X Kernel) output. 115 */ 116 117 #if( !defined( DEBUG_MAC_OS_X_IOLOG_ENABLED ) ) 118 #define DEBUG_MAC_OS_X_IOLOG_ENABLED TARGET_API_MAC_OSX_KERNEL 119 #endif 120 121 //--------------------------------------------------------------------------------------------------------------------------- 122 /*! @defined DEBUG_KPRINTF_ENABLED 123 124 @abstract Enables kprintf (Mac OS X Kernel) output. 125 */ 126 127 #if( !defined( DEBUG_KPRINTF_ENABLED ) ) 128 #define DEBUG_KPRINTF_ENABLED TARGET_API_MAC_OSX_KERNEL 129 #endif 130 131 //--------------------------------------------------------------------------------------------------------------------------- 132 /*! @defined DEBUG_IDEBUG_ENABLED 133 134 @abstract Enables iDebug (Mac OS X user and Kernel) output. 135 136 @discussion 137 138 For Mac OS X kernel development, iDebug is enabled by default because we can dynamically check for the presence 139 of iDebug via some exported IOKit symbols. Mac OS X app usage doesn't allow dynamic detection because it relies 140 on statically linking to the iDebugServices.cp file so for Mac OS X app usage, you have to manually enable iDebug. 141 */ 142 143 #if( !defined( DEBUG_IDEBUG_ENABLED ) ) 144 #define DEBUG_IDEBUG_ENABLED TARGET_API_MAC_OSX_KERNEL 145 #endif 146 147 //--------------------------------------------------------------------------------------------------------------------------- 148 /*! @defined DEBUG_CORE_SERVICE_ASSERTS_ENABLED 149 150 @abstract Controls whether Core Services assert handling is enabled. Enabling requires CoreServices framework. 151 */ 152 153 #if( !defined( DEBUG_CORE_SERVICE_ASSERTS_ENABLED ) ) 154 #if( defined( __DEBUGGING__ ) ) 155 #define DEBUG_CORE_SERVICE_ASSERTS_ENABLED 1 156 #else 157 #define DEBUG_CORE_SERVICE_ASSERTS_ENABLED 0 158 #endif 159 #endif 160 161 //--------------------------------------------------------------------------------------------------------------------------- 162 /*! @typedef DebugOutputType 163 164 @abstract Type of debug output (i.e. where the output goes). 165 */ 166 167 typedef uint32_t DebugOutputType; 168 169 #define kDebugOutputTypeNone 0x6E6F6E65U // 'none' - no params 170 #define kDebugOutputTypeCustom 0x63757374U // 'cust' - 1st param = function ptr, 2nd param = context 171 #define kDebugOutputTypeFPrintF 0x66707269U // 'fpri' - 1st param = DebugOutputTypeFlags [, 2nd param = filename] 172 #define kDebugOutputTypeiDebug 0x69646267U // 'idbg' - no params 173 #define kDebugOutputTypeKPrintF 0x6B707266U // 'kprf' - no params 174 #define kDebugOutputTypeMacOSXIOLog 0x696C6F67U // 'ilog' - no params 175 #define kDebugOutputTypeMacOSXLog 0x786C6F67U // 'xlog' - no params 176 #define kDebugOutputTypeWindowsDebugger 0x77696E64U // 'wind' - no params 177 #define kDebugOutputTypeWindowsEventLog 0x7765766CU // 'wevl' - 1st param = C-string name, 2nd param = HMODULE or NULL. 178 179 // Console meta output kind - Any kind of Console output (in horizontal order of preference): 180 // 181 // Mac OS X = ANSI printf (viewable in Console.app) 182 // Mac OS X Kernel = IOLog (/var/log/system.log) or kprintf (serial). 183 // Windows = ANSI printf (Console window) or OutputDebugString (debugger). 184 // Other = ANSI printf (viewer varies). 185 186 #define kDebugOutputTypeMetaConsole 0x434F4E53U // 'CONS' - no params 187 188 //--------------------------------------------------------------------------------------------------------------------------- 189 /*! @typedef DebugOutputTypeFlags 190 191 @abstract Flags controlling how the output type is configured. 192 193 @constant kDebugOutputTypeFlagsTypeMask Bit mask for the output type (e.g. stdout, stderr, file, etc.). 194 @constant kDebugOutputTypeFlagsStdOut fprintf should go to stdout. 195 @constant kDebugOutputTypeFlagsStdErr fprintf should go to stderr. 196 @constant kDebugOutputTypeFlagsFile fprintf should go to a specific file (filename passed as va_arg). 197 */ 198 199 typedef unsigned int DebugOutputTypeFlags; 200 201 #define kDebugOutputTypeFlagsTypeMask 0xF 202 #define kDebugOutputTypeFlagsStdOut 1 203 #define kDebugOutputTypeFlagsStdErr 2 204 #define kDebugOutputTypeFlagsFile 10 205 206 //--------------------------------------------------------------------------------------------------------------------------- 207 /*! @typedef DebugOutputFunctionPtr 208 209 @abstract Function ptr for a custom callback to print debug output. 210 */ 211 212 typedef void ( *DebugOutputFunctionPtr )( char *inData, size_t inSize, void *inContext ); 213 214 //=========================================================================================================================== 215 // Constants 216 //=========================================================================================================================== 217 218 #if 0 219 #pragma mark == Flags == 220 #endif 221 222 //--------------------------------------------------------------------------------------------------------------------------- 223 /*! @typedef DebugFlags 224 225 @abstract Flags controlling how output is printed. 226 */ 227 228 typedef uint32_t DebugFlags; 229 230 #define kDebugFlagsNone 0 231 #define kDebugFlagsNoAddress ( 1 << 0 ) 232 #define kDebugFlagsNoOffset ( 1 << 1 ) 233 #define kDebugFlags32BitOffset ( 1 << 2 ) 234 #define kDebugFlagsNoASCII ( 1 << 3 ) 235 #define kDebugFlagsNoNewLine ( 1 << 4 ) 236 #define kDebugFlags8BitSeparator ( 1 << 5 ) 237 #define kDebugFlags16BitSeparator ( 1 << 6 ) 238 #define kDebugFlagsNo32BitSeparator ( 1 << 7 ) 239 #define kDebugFlagsNo16ByteHexPad ( 1 << 8 ) 240 #define kDebugFlagsNoByteCount ( 1 << 9 ) 241 242 //--------------------------------------------------------------------------------------------------------------------------- 243 /*! @enum DebugTaskLevelFlags 244 245 @abstract Flags indicating the task level. 246 */ 247 248 enum 249 { 250 kDebugInterruptLevelShift = 0, 251 kDebugInterruptLevelMask = 0x00000007, 252 kDebugInVBLTaskMask = 0x00000010, 253 kDebugInDeferredTaskMask = 0x00000020, 254 kDebugInSecondaryInterruptHandlerMask = 0x00000040, 255 kDebugPageFaultFatalMask = 0x00000100, // There should be a "kPageFaultFatalMask" in Debugging.h. 256 kDebugMPTaskLevelMask = 0x00000200, // There should be a "kMPTaskLevelMask" in Debugging.h. 257 kDebugInterruptDepthShift = 16, 258 kDebugInterruptDepthMask = 0x00FF0000 259 }; 260 261 #define DebugExtractTaskLevelInterruptLevel( LEVEL ) \ 262 ( ( ( LEVEL ) & kDebugInterruptLevelMask ) >> kDebugInterruptLevelShift ) 263 264 #define DebugExtractTaskLevelInterruptDepth( LEVEL ) \ 265 ( ( ( LEVEL ) & kDebugInterruptDepthMask ) >> kDebugInterruptDepthShift ) 266 267 #if 0 268 #pragma mark == Levels == 269 #endif 270 271 //=========================================================================================================================== 272 // Constants & Types - Levels 273 //=========================================================================================================================== 274 275 //--------------------------------------------------------------------------------------------------------------------------- 276 /*! @typedef DebugLevel 277 278 @abstract Level used to control debug logging. 279 */ 280 281 typedef int32_t DebugLevel; 282 283 // Levels 284 285 #define kDebugLevelMask 0x0000FFFF 286 #define kDebugLevelChatty 100 287 #define kDebugLevelVerbose 500 288 #define kDebugLevelTrace 800 289 #define kDebugLevelInfo 1000 290 #define kDebugLevelNotice 3000 291 #define kDebugLevelWarning 5000 292 #define kDebugLevelAssert 6000 293 #define kDebugLevelRequire 7000 294 #define kDebugLevelError 8000 295 #define kDebugLevelCritical 9000 296 #define kDebugLevelAlert 10000 297 #define kDebugLevelEmergency 11000 298 #define kDebugLevelTragic 12000 299 #define kDebugLevelMax 0x0000FFFF 300 301 // Level Flags 302 303 #define kDebugLevelFlagMask 0xFFFF0000 304 #define kDebugLevelFlagStackTrace 0x00010000 305 #define kDebugLevelFlagDebugBreak 0x00020000 306 307 //--------------------------------------------------------------------------------------------------------------------------- 308 /*! @typedef LogLevel 309 310 @abstract Level used to control which events are logged. 311 */ 312 313 typedef int32_t LogLevel; 314 315 #define kLogLevelUninitialized -1L 316 #define kLogLevelAll 0L 317 #define kLogLevelChatty 100L 318 #define kLogLevelVerbose 500L 319 #define kLogLevelTrace 800L 320 #define kLogLevelInfo 1000L 321 #define kLogLevelNotice 3000L 322 #define kLogLevelWarning 4000L 323 #define kLogLevelAssert 6000L 324 #define kLogLevelRequire 7000L 325 #define kLogLevelError 8000L 326 #define kLogLevelCritical 9000L 327 #define kLogLevelAlert 10000L 328 #define kLogLevelEmergency 11000L 329 #define kLogLevelTragic 12000L 330 #define kLogLevelOff 0x0000FFFEL 331 332 #if 0 333 #pragma mark == Properties == 334 #endif 335 336 //--------------------------------------------------------------------------------------------------------------------------- 337 /*! @typedef DebugPropertyTag 338 339 @abstract Tag for properties. 340 */ 341 342 typedef uint32_t DebugPropertyTag; 343 344 #define kDebugPropertyTagPrintLevelMin 0x6D696E70U // 'minp' Get: 1st param = DebugLevel * 345 // Set: 1st param = DebugLevel 346 347 #define kDebugPropertyTagPrintLevel kDebugPropertyTagPrintLevelMin 348 349 #define kDebugPropertyTagPrintLevelMax 0x706D786CU // 'maxp' Get: 1st param = DebugLevel * 350 // Set: 1st param = DebugLevel 351 352 #define kDebugPropertyTagBreakLevel 0x62726B6CU // 'brkl' Get: 1st param = DebugLevel * 353 // Set: 1st param = DebugLevel 354 #if 0 355 #pragma mark == General macros == 356 #endif 357 358 //--------------------------------------------------------------------------------------------------------------------------- 359 /*! @defined DEBUG_UNUSED 360 361 @abstract Macro to mark a paramter as unused to avoid unused parameter warnings. 362 363 @discussion 364 365 There is no universally supported pragma/attribute for indicating a variable is unused. DEBUG_UNUSED lets us 366 indicate a variable is unused in a manner that is supported by most compilers. 367 */ 368 369 #define DEBUG_UNUSED( X ) (void)( X ) 370 371 //--------------------------------------------------------------------------------------------------------------------------- 372 /*! @defined DEBUG_USE_ONLY 373 374 @abstract Macro to mark a variable as used only when debugging is enabled. 375 376 @discussion 377 378 Variables are sometimes needed only for debugging. When debugging is turned off, these debug-only variables generate 379 compiler warnings about unused variables. To eliminate these warnings, use these macros to indicate variables that 380 are only used for debugging. 381 */ 382 383 #if( DEBUG ) 384 #define DEBUG_USE_ONLY( X ) 385 #else 386 #define DEBUG_USE_ONLY( X ) (void)( X ) 387 #endif 388 389 //--------------------------------------------------------------------------------------------------------------------------- 390 /*! @defined DEBUG_LOCAL 391 392 @abstract Macros to make variables and functions static when debugging is off, but extern when debugging is on. 393 394 @discussion 395 396 Rather than using "static" directly, using this macros allows you to access these variables external while 397 debugging without being penalized for production builds. 398 */ 399 400 #if( DEBUG ) 401 #define DEBUG_LOCAL 402 #else 403 #define DEBUG_LOCAL static 404 #endif 405 406 //--------------------------------------------------------------------------------------------------------------------------- 407 /*! @defined DEBUG_STATIC 408 409 @abstract Macros to make variables and functions static when debugging is off, but extern when debugging is on. 410 411 @discussion 412 413 Rather than using "static" directly, using this macros allows you to access these variables external while 414 debugging without being penalized for production builds. 415 */ 416 417 #if( DEBUG ) 418 #define DEBUG_STATIC 419 #else 420 #define DEBUG_STATIC static 421 #endif 422 423 //--------------------------------------------------------------------------------------------------------------------------- 424 /*! @defined DEBUG_EXPORT 425 426 @abstract Macros to export variables. 427 428 @discussion 429 430 "__private_extern__" is a hack for IOKit to allow symbols to be exported from compilation units, but 431 // not exported outside a driver (IOKit uses a lame global namespace for symbols). This still does not 432 // solve the problem of multiple drivers in the same dependency chain since they share symbols. 433 */ 434 435 #if( TARGET_API_MAC_OSX_KERNEL ) 436 #define DEBUG_EXPORT __private_extern__ 437 #else 438 #define DEBUG_EXPORT extern 439 #endif 440 441 //--------------------------------------------------------------------------------------------------------------------------- 442 /*! @defined debug_add 443 444 @abstract Macro to add (or subtract if negative) a value when debugging is on. Does nothing if debugging is off. 445 */ 446 447 #if( DEBUG ) 448 #define debug_add( A, B ) ( A ) += ( B ) 449 #else 450 #define debug_add( A, B ) 451 #endif 452 453 //--------------------------------------------------------------------------------------------------------------------------- 454 /*! @defined debug_perform 455 456 @abstract Macro to perform something in debug-only builds. 457 */ 458 459 #if( DEBUG ) 460 #define debug_perform( X ) do { X; } while( 0 ) 461 #else 462 #define debug_perform( X ) 463 #endif 464 465 //--------------------------------------------------------------------------------------------------------------------------- 466 /*! @function translate_errno 467 468 @abstract Returns 0 if the test success. If the test fails, returns errno if non-zero and othewise the alternate error. 469 */ 470 471 #define translate_errno( TEST, ERRNO, ALTERNATE_ERROR ) ( ( TEST ) ? 0 : ( ERRNO ) ? ( ERRNO ) : ( ALTERNATE_ERROR ) ) 472 473 #if 0 474 #pragma mark == Compile Time macros == 475 #endif 476 477 //--------------------------------------------------------------------------------------------------------------------------- 478 /*! @defined check_compile_time 479 480 @abstract Performs a compile-time check of something such as the size of an int. 481 482 @discussion 483 484 This declares an array with a size that is determined by a compile-time expression. If the expression evaluates 485 to 0, the array has a size of -1, which is illegal and generates a compile-time error. 486 487 For example: 488 489 check_compile_time( sizeof( int ) == 4 ); 490 491 Note: This only works with compile-time expressions. 492 Note: This only works in places where extern declarations are allowed (e.g. global scope). 493 494 References: 495 496 <http://www.jaggersoft.com/pubs/CVu11_3.html> 497 <http://www.jaggersoft.com/pubs/CVu11_5.html> 498 499 Note: The following macros differ from the macros on the www.jaggersoft.com web site because those versions do not 500 work with GCC due to GCC allow a zero-length array. Using a -1 condition turned out to be more portable. 501 */ 502 503 #define check_compile_time( X ) extern int debug_compile_time_name[ ( X ) ? 1 : -1 ] 504 505 //--------------------------------------------------------------------------------------------------------------------------- 506 /*! @defined check_compile_time_code 507 508 @abstract Perform a compile-time check, suitable for placement in code, of something such as the size of an int. 509 510 @discussion 511 512 This creates a switch statement with an existing case for 0 and an additional case using the result of a 513 compile-time expression. A switch statement cannot have two case labels with the same constant so if the 514 compile-time expression evaluates to 0, it is illegal and generates a compile-time error. If the compile-time 515 expression does not evaluate to 0, the resulting value is used as the case label and it compiles without error. 516 517 For example: 518 519 check_compile_time_code( sizeof( int ) == 4 ); 520 521 Note: This only works with compile-time expressions. 522 Note: This does not work in a global scope so it must be inside a function. 523 524 References: 525 526 <http://www.jaggersoft.com/pubs/CVu11_3.html> 527 <http://www.jaggersoft.com/pubs/CVu11_5.html> 528 */ 529 530 #define check_compile_time_code( X ) switch( 0 ) { case 0: case X:; } 531 532 #if 0 533 #pragma mark == check macros == 534 #endif 535 536 //--------------------------------------------------------------------------------------------------------------------------- 537 /*! @defined check 538 539 @abstract Check that an expression is true (non-zero). 540 541 @discussion 542 543 If expression evalulates to false, this prints debugging information (actual expression string, file, line number, 544 function name, etc.) using the default debugging output method. 545 546 Code inside check() statements is not compiled into production builds. 547 */ 548 549 #if( DEBUG_OVERRIDE_APPLE_MACROS ) 550 #undef check 551 #endif 552 #if( !defined( check ) ) 553 #if( DEBUG ) 554 #define check( X ) \ 555 do \ 556 { \ 557 if( !( X ) ) \ 558 { \ 559 debug_print_assert( 0, #X, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ 560 } \ 561 } while( 0 ) 562 #else 563 #define check( X ) 564 #endif 565 #endif 566 567 //--------------------------------------------------------------------------------------------------------------------------- 568 /*! @defined check_string 569 570 @abstract Check that an expression is true (non-zero) with an explanation. 571 572 @discussion 573 574 If expression evalulates to false, this prints debugging information (actual expression string, file, line number, 575 function name, etc.) and a custom explanation string using the default debugging output method. 576 577 Code inside check_string() statements is not compiled into production builds. 578 */ 579 580 #if( DEBUG_OVERRIDE_APPLE_MACROS ) 581 #undef check_string 582 #endif 583 #if( !defined( check_string ) ) 584 #if( DEBUG ) 585 #define check_string( X, STR ) \ 586 do \ 587 { \ 588 if( !( X ) ) \ 589 { \ 590 debug_print_assert( 0, #X, STR, __FILE__, __LINE__, __ROUTINE__ ); \ 591 } \ 592 \ 593 } while( 0 ) 594 #else 595 #define check_string( X, STR ) 596 #endif 597 #endif 598 599 //--------------------------------------------------------------------------------------------------------------------------- 600 /*! @defined check_noerr 601 602 @abstract Check that an error code is noErr (0). 603 604 @discussion 605 606 If the error code is non-0, this prints debugging information (actual expression string, file, line number, 607 function name, etc.) using the default debugging output method. 608 609 Code inside check_noerr() statements is not compiled into production builds. 610 */ 611 612 #if( DEBUG_OVERRIDE_APPLE_MACROS ) 613 #undef check_noerr 614 #endif 615 #if( !defined( check_noerr ) ) 616 #if( DEBUG ) 617 #define check_noerr( ERR ) \ 618 do \ 619 { \ 620 int_least32_t localErr; \ 621 \ 622 localErr = (int_least32_t)( ERR ); \ 623 if( localErr != 0 ) \ 624 { \ 625 debug_print_assert( localErr, NULL, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ 626 } \ 627 \ 628 } while( 0 ) 629 #else 630 #define check_noerr( ERR ) 631 #endif 632 #endif 633 634 //--------------------------------------------------------------------------------------------------------------------------- 635 /*! @defined check_noerr_string 636 637 @abstract Check that an error code is noErr (0) with an explanation. 638 639 @discussion 640 641 If the error code is non-0, this prints debugging information (actual expression string, file, line number, 642 function name, etc.) and a custom explanation string using the default debugging output method. 643 644 Code inside check_noerr_string() statements is not compiled into production builds. 645 */ 646 647 #if( DEBUG_OVERRIDE_APPLE_MACROS ) 648 #undef check_noerr_string 649 #endif 650 #if( !defined( check_noerr_string ) ) 651 #if( DEBUG ) 652 #define check_noerr_string( ERR, STR ) \ 653 do \ 654 { \ 655 int_least32_t localErr; \ 656 \ 657 localErr = (int_least32_t)( ERR ); \ 658 if( localErr != 0 ) \ 659 { \ 660 debug_print_assert( localErr, NULL, STR, __FILE__, __LINE__, __ROUTINE__ ); \ 661 } \ 662 \ 663 } while( 0 ) 664 #else 665 #define check_noerr_string( ERR, STR ) 666 #endif 667 #endif 668 669 //--------------------------------------------------------------------------------------------------------------------------- 670 /*! @defined check_translated_errno 671 672 @abstract Check a condition and prints errno (if non-zero) to the log. 673 674 @discussion 675 676 Code inside check_translated_errno() statements is not compiled into production builds. 677 */ 678 679 #if( !defined( check_translated_errno ) ) 680 #if( DEBUG ) 681 #define check_translated_errno( TEST, ERRNO, ALTERNATE_ERROR ) \ 682 do \ 683 { \ 684 if( !( TEST ) ) \ 685 { \ 686 int_least32_t localErr; \ 687 \ 688 localErr = (int_least32_t)( ERRNO ); \ 689 localErr = ( localErr != 0 ) ? localErr : (int_least32_t)( ALTERNATE_ERROR ); \ 690 debug_print_assert( localErr, #TEST, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ 691 } \ 692 \ 693 } while( 0 ) 694 #else 695 #define check_translated_errno( TEST, ERRNO, ALTERNATE_ERROR ) 696 #endif 697 #endif 698 699 //--------------------------------------------------------------------------------------------------------------------------- 700 /*! @defined check_ptr_overlap 701 702 @abstract Checks that two ptrs do not overlap. 703 */ 704 705 #define check_ptr_overlap( P1, P1_SIZE, P2, P2_SIZE ) \ 706 do \ 707 { \ 708 check( !( ( (uintptr_t)( P1 ) >= (uintptr_t)( P2 ) ) && \ 709 ( (uintptr_t)( P1 ) < ( ( (uintptr_t)( P2 ) ) + ( P2_SIZE ) ) ) ) ); \ 710 check( !( ( (uintptr_t)( P2 ) >= (uintptr_t)( P1 ) ) && \ 711 ( (uintptr_t)( P2 ) < ( ( (uintptr_t)( P1 ) ) + ( P1_SIZE ) ) ) ) ); \ 712 \ 713 } while( 0 ) 714 715 #if 0 716 #pragma mark == require macros == 717 #endif 718 719 //--------------------------------------------------------------------------------------------------------------------------- 720 /*! @defined require 721 722 @abstract Requires that an expression evaluate to true. 723 724 @discussion 725 726 If expression evalulates to false, this prints debugging information (actual expression string, file, line number, 727 function name, etc.) using the default debugging output method then jumps to a label. 728 */ 729 730 #if( DEBUG_OVERRIDE_APPLE_MACROS ) 731 #undef require 732 #endif 733 #if( !defined( require ) ) 734 #define require( X, LABEL ) \ 735 do \ 736 { \ 737 if( !( X ) ) \ 738 { \ 739 debug_print_assert( 0, #X, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ 740 goto LABEL; \ 741 } \ 742 \ 743 } while( 0 ) 744 #endif 745 746 //--------------------------------------------------------------------------------------------------------------------------- 747 /*! @defined require_string 748 749 @abstract Requires that an expression evaluate to true with an explanation. 750 751 @discussion 752 753 If expression evalulates to false, this prints debugging information (actual expression string, file, line number, 754 function name, etc.) and a custom explanation string using the default debugging output method then jumps to a label. 755 */ 756 757 #if( DEBUG_OVERRIDE_APPLE_MACROS ) 758 #undef require_string 759 #endif 760 #if( !defined( require_string ) ) 761 #define require_string( X, LABEL, STR ) \ 762 do \ 763 { \ 764 if( !( X ) ) \ 765 { \ 766 debug_print_assert( 0, #X, STR, __FILE__, __LINE__, __ROUTINE__ ); \ 767 goto LABEL; \ 768 } \ 769 \ 770 } while( 0 ) 771 #endif 772 773 //--------------------------------------------------------------------------------------------------------------------------- 774 /*! @defined require_quiet 775 776 @abstract Requires that an expression evaluate to true. 777 778 @discussion 779 780 If expression evalulates to false, this jumps to a label. No debugging information is printed. 781 */ 782 783 #if( DEBUG_OVERRIDE_APPLE_MACROS ) 784 #undef require_quiet 785 #endif 786 #if( !defined( require_quiet ) ) 787 #define require_quiet( X, LABEL ) \ 788 do \ 789 { \ 790 if( !( X ) ) \ 791 { \ 792 goto LABEL; \ 793 } \ 794 \ 795 } while( 0 ) 796 #endif 797 798 //--------------------------------------------------------------------------------------------------------------------------- 799 /*! @defined require_noerr 800 801 @abstract Require that an error code is noErr (0). 802 803 @discussion 804 805 If the error code is non-0, this prints debugging information (actual expression string, file, line number, 806 function name, etc.) using the default debugging output method then jumps to a label. 807 */ 808 809 #if( DEBUG_OVERRIDE_APPLE_MACROS ) 810 #undef require_noerr 811 #endif 812 #if( !defined( require_noerr ) ) 813 #define require_noerr( ERR, LABEL ) \ 814 do \ 815 { \ 816 int_least32_t localErr; \ 817 \ 818 localErr = (int_least32_t)( ERR ); \ 819 if( localErr != 0 ) \ 820 { \ 821 debug_print_assert( localErr, NULL, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ 822 goto LABEL; \ 823 } \ 824 \ 825 } while( 0 ) 826 #endif 827 828 //--------------------------------------------------------------------------------------------------------------------------- 829 /*! @defined require_noerr_string 830 831 @abstract Require that an error code is noErr (0). 832 833 @discussion 834 835 If the error code is non-0, this prints debugging information (actual expression string, file, line number, 836 function name, etc.), and a custom explanation string using the default debugging output method using the 837 default debugging output method then jumps to a label. 838 */ 839 840 #if( DEBUG_OVERRIDE_APPLE_MACROS ) 841 #undef require_noerr_string 842 #endif 843 #if( !defined( require_noerr_string ) ) 844 #define require_noerr_string( ERR, LABEL, STR ) \ 845 do \ 846 { \ 847 int_least32_t localErr; \ 848 \ 849 localErr = (int_least32_t)( ERR ); \ 850 if( localErr != 0 ) \ 851 { \ 852 debug_print_assert( localErr, NULL, STR, __FILE__, __LINE__, __ROUTINE__ ); \ 853 goto LABEL; \ 854 } \ 855 \ 856 } while( 0 ) 857 #endif 858 859 //--------------------------------------------------------------------------------------------------------------------------- 860 /*! @defined require_noerr_action_string 861 862 @abstract Require that an error code is noErr (0). 863 864 @discussion 865 866 If the error code is non-0, this prints debugging information (actual expression string, file, line number, 867 function name, etc.), and a custom explanation string using the default debugging output method using the 868 default debugging output method then executes an action and jumps to a label. 869 */ 870 871 #if( DEBUG_OVERRIDE_APPLE_MACROS ) 872 #undef require_noerr_action_string 873 #endif 874 #if( !defined( require_noerr_action_string ) ) 875 #define require_noerr_action_string( ERR, LABEL, ACTION, STR ) \ 876 do \ 877 { \ 878 int_least32_t localErr; \ 879 \ 880 localErr = (int_least32_t)( ERR ); \ 881 if( localErr != 0 ) \ 882 { \ 883 debug_print_assert( localErr, NULL, STR, __FILE__, __LINE__, __ROUTINE__ ); \ 884 { ACTION; } \ 885 goto LABEL; \ 886 } \ 887 \ 888 } while( 0 ) 889 #endif 890 891 //--------------------------------------------------------------------------------------------------------------------------- 892 /*! @defined require_noerr_quiet 893 894 @abstract Require that an error code is noErr (0). 895 896 @discussion 897 898 If the error code is non-0, this jumps to a label. No debugging information is printed. 899 */ 900 901 #if( DEBUG_OVERRIDE_APPLE_MACROS ) 902 #undef require_noerr_quiet 903 #endif 904 #if( !defined( require_noerr_quiet ) ) 905 #define require_noerr_quiet( ERR, LABEL ) \ 906 do \ 907 { \ 908 if( ( ERR ) != 0 ) \ 909 { \ 910 goto LABEL; \ 911 } \ 912 \ 913 } while( 0 ) 914 #endif 915 916 //--------------------------------------------------------------------------------------------------------------------------- 917 /*! @defined require_noerr_action 918 919 @abstract Require that an error code is noErr (0) with an action to execute otherwise. 920 921 @discussion 922 923 If the error code is non-0, this prints debugging information (actual expression string, file, line number, 924 function name, etc.) using the default debugging output method then executes an action and jumps to a label. 925 */ 926 927 #if( DEBUG_OVERRIDE_APPLE_MACROS ) 928 #undef require_noerr_action 929 #endif 930 #if( !defined( require_noerr_action ) ) 931 #define require_noerr_action( ERR, LABEL, ACTION ) \ 932 do \ 933 { \ 934 int_least32_t localErr; \ 935 \ 936 localErr = (int_least32_t)( ERR ); \ 937 if( localErr != 0 ) \ 938 { \ 939 debug_print_assert( localErr, NULL, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ 940 { ACTION; } \ 941 goto LABEL; \ 942 } \ 943 \ 944 } while( 0 ) 945 #endif 946 947 //--------------------------------------------------------------------------------------------------------------------------- 948 /*! @defined require_noerr_action_quiet 949 950 @abstract Require that an error code is noErr (0) with an action to execute otherwise. 951 952 @discussion 953 954 If the error code is non-0, this executes an action and jumps to a label. No debugging information is printed. 955 */ 956 957 #if( DEBUG_OVERRIDE_APPLE_MACROS ) 958 #undef require_noerr_action_quiet 959 #endif 960 #if( !defined( require_noerr_action_quiet ) ) 961 #define require_noerr_action_quiet( ERR, LABEL, ACTION ) \ 962 do \ 963 { \ 964 if( ( ERR ) != 0 ) \ 965 { \ 966 { ACTION; } \ 967 goto LABEL; \ 968 } \ 969 \ 970 } while( 0 ) 971 #endif 972 973 //--------------------------------------------------------------------------------------------------------------------------- 974 /*! @defined require_action 975 976 @abstract Requires that an expression evaluate to true with an action to execute otherwise. 977 978 @discussion 979 980 If expression evalulates to false, this prints debugging information (actual expression string, file, line number, 981 function name, etc.) using the default debugging output method then executes an action and jumps to a label. 982 */ 983 984 #if( DEBUG_OVERRIDE_APPLE_MACROS ) 985 #undef require_action 986 #endif 987 #if( !defined( require_action ) ) 988 #define require_action( X, LABEL, ACTION ) \ 989 do \ 990 { \ 991 if( !( X ) ) \ 992 { \ 993 debug_print_assert( 0, #X, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ 994 { ACTION; } \ 995 goto LABEL; \ 996 } \ 997 \ 998 } while( 0 ) 999 #endif 1000 1001 //--------------------------------------------------------------------------------------------------------------------------- 1002 /*! @defined require_action_quiet 1003 1004 @abstract Requires that an expression evaluate to true with an action to execute otherwise. 1005 1006 @discussion 1007 1008 If expression evalulates to false, this executes an action and jumps to a label. No debugging information is printed. 1009 */ 1010 1011 #if( DEBUG_OVERRIDE_APPLE_MACROS ) 1012 #undef require_action_quiet 1013 #endif 1014 #if( !defined( require_action_quiet ) ) 1015 #define require_action_quiet( X, LABEL, ACTION ) \ 1016 do \ 1017 { \ 1018 if( !( X ) ) \ 1019 { \ 1020 { ACTION; } \ 1021 goto LABEL; \ 1022 } \ 1023 \ 1024 } while( 0 ) 1025 #endif 1026 1027 //--------------------------------------------------------------------------------------------------------------------------- 1028 /*! @defined require_action_string 1029 1030 @abstract Requires that an expression evaluate to true with an explanation and action to execute otherwise. 1031 1032 @discussion 1033 1034 If expression evalulates to false, this prints debugging information (actual expression string, file, line number, 1035 function name, etc.) and a custom explanation string using the default debugging output method then executes an 1036 action and jumps to a label. 1037 */ 1038 1039 #if( DEBUG_OVERRIDE_APPLE_MACROS ) 1040 #undef require_action_string 1041 #endif 1042 #if( !defined( require_action_string ) ) 1043 #define require_action_string( X, LABEL, ACTION, STR ) \ 1044 do \ 1045 { \ 1046 if( !( X ) ) \ 1047 { \ 1048 debug_print_assert( 0, #X, STR, __FILE__, __LINE__, __ROUTINE__ ); \ 1049 { ACTION; } \ 1050 goto LABEL; \ 1051 } \ 1052 \ 1053 } while( 0 ) 1054 1055 #endif 1056 1057 //--------------------------------------------------------------------------------------------------------------------------- 1058 /*! @defined require_throw 1059 1060 @abstract Requires that an expression evaluates to true or an exception is thrown. 1061 1062 @discussion 1063 1064 If the expression evaluates to false, this prints debugging information (actual expression string, file, 1065 line number, function name, etc.) using the default debugging output method then throws an exception. 1066 */ 1067 1068 #if( defined( __cplusplus ) ) 1069 #define require_throw( X ) \ 1070 do \ 1071 { \ 1072 if( !( X ) ) \ 1073 { \ 1074 debug_print_assert( 0, #X, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ 1075 throw kUnknownErr; \ 1076 } \ 1077 \ 1078 } while( 0 ) 1079 #endif 1080 1081 #if 0 1082 #pragma mark == Design-By-Contract macros == 1083 #endif 1084 1085 //=========================================================================================================================== 1086 // Design-By-Contract macros 1087 //=========================================================================================================================== 1088 1089 #define ensure( X ) check( X ) 1090 #define ensure_string( X, STR ) check_string( X, STR ) 1091 #define ensure_noerr( ERR ) check_noerr( ERR ) 1092 #define ensure_noerr_string( ERR, STR ) check_noerr_string( ERR, STR ) 1093 #define ensure_translated_errno( TEST, ERRNO, ALTERNATE_ERROR ) check_translated_errno( TEST, ERRNO, ALTERNATE_ERROR ) 1094 1095 // Note: Design-By-Contract "require" macros are already defined elsewhere. 1096 1097 #if 0 1098 #pragma mark == Expect macros == 1099 #endif 1100 1101 //=========================================================================================================================== 1102 // Expect macros 1103 //=========================================================================================================================== 1104 1105 // Expect macros allow code to include runtime checking of things that should not happen in shipping code (e.g. internal 1106 // programmer errors, such as a NULL parameter where it is not allowed). Once the code has been verified to work correctly 1107 // without asserting, the DEBUG_EXPECT_VERIFIED conditional can be set to eliminate the error checking entirely. It can 1108 // also be useful to measure the cost of error checking code by profiling with it enable and with it disabled. 1109 1110 #if( DEBUG_EXPECT_VERIFIED ) 1111 #define require_expect 1112 #define require_string_expect 1113 #define require_quiet_expect 1114 #define require_noerr_expect 1115 #define require_noerr_string_expect 1116 #define require_noerr_action_string_expect 1117 #define require_noerr_quiet_expect 1118 #define require_noerr_action_expect 1119 #define require_noerr_action_quiet_expect 1120 #define require_action_expect 1121 #define require_action_quiet_expect 1122 #define require_action_string_expect 1123 #else 1124 #define require_expect require 1125 #define require_string_expect require_string 1126 #define require_quiet_expect require_quiet 1127 #define require_noerr_expect require_noerr 1128 #define require_noerr_string_expect require_noerr_string 1129 #define require_noerr_action_string_expect require_noerr_action_string 1130 #define require_noerr_quiet_expect require_noerr_quiet 1131 #define require_noerr_action_expect require_noerr_action 1132 #define require_noerr_action_quiet_expect require_noerr_action_quiet 1133 #define require_action_expect require_action 1134 #define require_action_quiet_expect require_action_quiet 1135 #define require_action_string_expect require_action_string 1136 #endif 1137 1138 #if 0 1139 #pragma mark == Output macros == 1140 #endif 1141 1142 //--------------------------------------------------------------------------------------------------------------------------- 1143 /*! @defined debug_string 1144 1145 @abstract Prints a debugging C string. 1146 */ 1147 1148 #if( DEBUG_OVERRIDE_APPLE_MACROS ) 1149 #undef debug_string 1150 #endif 1151 #if( !defined( debug_string ) ) 1152 #if( DEBUG ) 1153 #define debug_string( STR ) \ 1154 do \ 1155 { \ 1156 debug_print_assert( 0, NULL, STR, __FILE__, __LINE__, __ROUTINE__ ); \ 1157 \ 1158 } while( 0 ) 1159 #else 1160 #define debug_string( STR ) 1161 #endif 1162 #endif 1163 1164 //--------------------------------------------------------------------------------------------------------------------------- 1165 /*! @defined debug_print_assert 1166 1167 @abstract Prints an assertion. 1168 */ 1169 1170 #if( DEBUG ) 1171 #define debug_print_assert( ERROR_CODE, ASSERT_STRING, MESSAGE, FILENAME, LINE_NUMBER, FUNCTION ) \ 1172 DebugPrintAssert( ERROR_CODE, ASSERT_STRING, MESSAGE, FILENAME, LINE_NUMBER, FUNCTION ) 1173 #else 1174 #define debug_print_assert( ERROR_CODE, ASSERT_STRING, MESSAGE, FILENAME, LINE_NUMBER, FUNCTION ) 1175 #endif 1176 1177 //--------------------------------------------------------------------------------------------------------------------------- 1178 /*! @defined dlog 1179 1180 @abstract Prints a debug-only message. 1181 */ 1182 1183 #if( DEBUG ) 1184 #if( DEBUG_C99_VA_ARGS ) 1185 #define dlog( ... ) DebugPrintF( __VA_ARGS__ ) 1186 #elif( DEBUG_GNU_VA_ARGS ) 1187 #define dlog( ARGS... ) DebugPrintF( ## ARGS ) 1188 #else 1189 #define dlog DebugPrintF 1190 #endif 1191 #else 1192 #if( DEBUG_C99_VA_ARGS ) 1193 #define dlog( ... ) 1194 #elif( DEBUG_GNU_VA_ARGS ) 1195 #define dlog( ARGS... ) 1196 #else 1197 #define dlog while( 0 ) 1198 #endif 1199 #endif 1200 1201 //--------------------------------------------------------------------------------------------------------------------------- 1202 /*! @defined dlogv 1203 1204 @abstract Prints a debug-only message. 1205 */ 1206 1207 #if( DEBUG ) 1208 #define dlogv( LEVEL, FORMAT, LIST ) DebugPrintFVAList( ( LEVEL ), ( FORMAT ), ( LIST ) ) 1209 #else 1210 #define dlogv( LEVEL, FORMAT, LIST ) 1211 #endif 1212 1213 //--------------------------------------------------------------------------------------------------------------------------- 1214 /*! @defined dlogmem 1215 1216 @abstract Prints a debug-only dump of memory. 1217 */ 1218 1219 #if( DEBUG ) 1220 #define dlogmem( LEVEL, PTR, SIZE ) \ 1221 DebugHexDump( ( LEVEL ), 0, NULL, 0, 0, NULL, 0, ( PTR ), ( PTR ), ( SIZE ), kDebugFlagsNone, NULL, 0 ) 1222 #else 1223 #define dlogmem( LEVEL, PTR, SIZE ) 1224 #endif 1225 1226 //--------------------------------------------------------------------------------------------------------------------------- 1227 /*! @defined DebugNSLog 1228 1229 @abstract Debug-only macro for the Cocoa NSLog function. 1230 */ 1231 1232 #if( DEBUG ) 1233 #if( DEBUG_C99_VA_ARGS ) 1234 #define DebugNSLog( ... ) NSLog( __VA_ARGS__ ) 1235 #elif( DEBUG_GNU_VA_ARGS ) 1236 #define DebugNSLog( ARGS... ) NSLog( ## ARGS ) 1237 #else 1238 #define DebugNSLog NSLog 1239 #endif 1240 #else 1241 #if( DEBUG_C99_VA_ARGS ) 1242 #define DebugNSLog( ... ) 1243 #elif( DEBUG_GNU_VA_ARGS ) 1244 #define DebugNSLog( ARGS... ) 1245 #else 1246 #define DebugNSLog while( 0 ) 1247 #endif 1248 #endif 1249 1250 //--------------------------------------------------------------------------------------------------------------------------- 1251 /*! @defined DebugLogMsg 1252 1253 @abstract Debug-only macro for the VxWorks logMsg function. 1254 */ 1255 1256 #if( TARGET_OS_VXWORKS ) 1257 #if( DEBUG ) 1258 #define DebugLogMsg( LEVEL, FORMAT, P1, P2, P3, P4, P5, P6 ) \ 1259 do \ 1260 { \ 1261 if( ( inLevel >= gDebugPrintLevelMin ) || ( inLevel <= gDebugPrintLevelMax ) ) \ 1262 { \ 1263 logMsg( ( FORMAT ), ( P1 ), ( P2 ), ( P3 ), ( P4 ), ( P5 ), ( P6 ) ); \ 1264 } \ 1265 \ 1266 } while( 0 ) 1267 #else 1268 #define DebugLogMsg( LEVEL, FORMAT, P1, P2, P3, P4, P5, P6 ) 1269 #endif 1270 #else 1271 #define DebugLogMsg dlog 1272 #endif 1273 1274 #if 0 1275 #pragma mark == Routines - General == 1276 #endif 1277 1278 #ifdef __cplusplus 1279 extern "C" { 1280 #endif 1281 1282 //--------------------------------------------------------------------------------------------------------------------------- 1283 /*! @function DebugInitialize 1284 1285 @abstract Initializes the debugging library for a specific kind of output. 1286 1287 @param inType 1288 @param varArg Variable number parameters, controlled by the "inType" parameter. 1289 */ 1290 1291 #if( DEBUG ) 1292 DEBUG_EXPORT OSStatus DebugInitialize( DebugOutputType inType, ... ); 1293 #endif 1294 1295 #if( DEBUG ) 1296 #if( DEBUG_C99_VA_ARGS ) 1297 #define debug_initialize( ... ) DebugInitialize( __VA_ARGS__ ) 1298 #elif( DEBUG_GNU_VA_ARGS ) 1299 #define debug_initialize( ARGS... ) DebugInitialize( ## ARGS ) 1300 #else 1301 #define debug_initialize DebugInitialize 1302 #endif 1303 #else 1304 #if( DEBUG_C99_VA_ARGS ) 1305 #define debug_initialize( ... ) 1306 #elif( DEBUG_GNU_VA_ARGS ) 1307 #define debug_initialize( ARGS... ) 1308 #else 1309 #define debug_initialize while( 0 ) 1310 #endif 1311 #endif 1312 1313 //--------------------------------------------------------------------------------------------------------------------------- 1314 /*! @function DebugFinalize 1315 1316 @abstract Releases any resources used by the debugging library 1317 */ 1318 1319 #if( DEBUG ) 1320 DEBUG_EXPORT void DebugFinalize( void ); 1321 #endif 1322 1323 #if( DEBUG ) 1324 #define debug_terminate() DebugFinalize() 1325 #else 1326 #define debug_terminate() 1327 #endif 1328 1329 //--------------------------------------------------------------------------------------------------------------------------- 1330 /*! @function DebugGetProperty 1331 1332 @abstract Gets the specified property from the debugging library. 1333 */ 1334 1335 #if( DEBUG ) 1336 DEBUG_EXPORT OSStatus DebugGetProperty( DebugPropertyTag inTag, ... ); 1337 #endif 1338 1339 #if( DEBUG ) 1340 #if( DEBUG_C99_VA_ARGS ) 1341 #define debug_get_property( ... ) DebugGetProperty( __VA_ARGS__ ) 1342 #elif( DEBUG_GNU_VA_ARGS ) 1343 #define debug_get_property( ARGS... ) DebugGetProperty( ## ARGS ) 1344 #else 1345 #define debug_get_property DebugGetProperty 1346 #endif 1347 #else 1348 #if( DEBUG_C99_VA_ARGS ) 1349 #define debug_get_property( ... ) 1350 #elif( DEBUG_GNU_VA_ARGS ) 1351 #define debug_get_property( ARGS... ) 1352 #else 1353 #define debug_get_property while( 0 ) 1354 #endif 1355 #endif 1356 1357 //--------------------------------------------------------------------------------------------------------------------------- 1358 /*! @function DebugSetProperty 1359 1360 @abstract Sets the specified property from the debugging library. 1361 */ 1362 1363 #if( DEBUG ) 1364 DEBUG_EXPORT OSStatus DebugSetProperty( DebugPropertyTag inTag, ... ); 1365 #endif 1366 1367 #if( DEBUG ) 1368 #if( DEBUG_C99_VA_ARGS ) 1369 #define debug_set_property( ... ) DebugSetProperty( __VA_ARGS__ ) 1370 #elif( DEBUG_GNU_VA_ARGS ) 1371 #define debug_set_property( ARGS... ) DebugSetProperty( ## ARGS ) 1372 #else 1373 #define debug_set_property DebugSetProperty 1374 #endif 1375 #else 1376 #if( DEBUG_C99_VA_ARGS ) 1377 #define debug_set_property( ... ) 1378 #elif( DEBUG_GNU_VA_ARGS ) 1379 #define debug_set_property( ARGS... ) 1380 #else 1381 #define debug_set_property while( 0 ) 1382 #endif 1383 #endif 1384 1385 #if 0 1386 #pragma mark == Routines - Debugging Output == 1387 #endif 1388 1389 //--------------------------------------------------------------------------------------------------------------------------- 1390 /*! @function DebugPrintF 1391 1392 @abstract Prints a debug message with printf-style formatting. 1393 1394 @param inLevel Error that generated this assert or noErr. 1395 1396 @param inFormatString 1397 C string containing assertion text. 1398 1399 @param VAR_ARG 1400 Variable number of arguments depending on the format string. 1401 1402 @result Number of bytes printed or -1 on error. 1403 */ 1404 1405 #if( DEBUG ) 1406 DEBUG_EXPORT size_t DebugPrintF( DebugLevel inLevel, const char *inFormat, ... ); 1407 #endif 1408 1409 //--------------------------------------------------------------------------------------------------------------------------- 1410 /*! @function DebugPrintFVAList 1411 1412 @abstract va_list version of DebugPrintF. See DebugPrintF for more info. 1413 */ 1414 1415 #if( DEBUG ) 1416 DEBUG_EXPORT size_t DebugPrintFVAList( DebugLevel inLevel, const char *inFormat, va_list inArgs ); 1417 #endif 1418 1419 //--------------------------------------------------------------------------------------------------------------------------- 1420 /*! @function DebugPrintAssert 1421 1422 @abstract Prints a message describing the reason the (e.g. an assert failed), an optional error message, 1423 an optional source filename, an optional source line number. 1424 1425 @param inErrorCode Error that generated this assert or noErr. 1426 @param inAssertString C string containing assertion text. 1427 @param inMessage C string containing a message about the assert. 1428 @param inFileName C string containing path of file where the error occurred. 1429 @param inLineNumber Line number in source file where the error occurred. 1430 @param inFunction C string containing name of function where assert occurred. 1431 1432 @discussion 1433 1434 Example output: 1435 1436 [ASSERT] assert: "dataPtr != NULL" allocate memory for object failed 1437 [ASSERT] where: "MyFile.c", line 123, ("MyFunction") 1438 1439 OR 1440 1441 [ASSERT] error: -6728 (kNoMemoryErr) 1442 [ASSERT] where: "MyFile.c", line 123, ("MyFunction") 1443 */ 1444 1445 #if( DEBUG ) 1446 DEBUG_EXPORT void 1447 DebugPrintAssert( 1448 int_least32_t inErrorCode, 1449 const char * inAssertString, 1450 const char * inMessage, 1451 const char * inFilename, 1452 int_least32_t inLineNumber, 1453 const char * inFunction ); 1454 #endif 1455 1456 #if 0 1457 #pragma mark == Routines - Utilities == 1458 #endif 1459 1460 //--------------------------------------------------------------------------------------------------------------------------- 1461 /*! @function DebugSNPrintF 1462 1463 @abstract Debugging versions of standard C snprintf with extra features. 1464 1465 @param sbuffer Buffer to receive result. Null terminated unless the buffer size is 0. 1466 @param buflen Size of the buffer including space for the null terminator. 1467 @param fmt printf-style format string. 1468 @param VAR_ARG Variable number of arguments depending on the format string. 1469 1470 @result Number of characters written (minus the null terminator). 1471 1472 @discussion 1473 1474 Extra features over the standard C snprintf: 1475 <pre> 1476 64-bit support for %d (%lld), %i (%lli), %u (%llu), %o (%llo), %x (%llx), and %b (%llb). 1477 %@ - Cocoa/CoreFoundation object. Param is the object. Strings are used directly. Others use CFCopyDescription. 1478 %a - Network Address: %.4a=IPv4, %.6a=Ethernet, %.8a Fibre Channel, %.16a=IPv6. Arg=ptr to network address. 1479 %#a - IPv4 or IPv6 mDNSAddr. Arg=ptr to mDNSAddr. 1480 %##a - IPv4 (if AF_INET defined) or IPv6 (if AF_INET6 defined) sockaddr. Arg=ptr to sockaddr. 1481 %b - Binary representation of integer (e.g. 01101011). Modifiers and arg=the same as %d, %x, etc. 1482 %C - Mac-style FourCharCode (e.g. 'APPL'). Arg=32-bit value to print as a Mac-style FourCharCode. 1483 %H - Hex Dump (e.g. "\x6b\xa7" -> "6B A7"). 1st arg=ptr, 2nd arg=size, 3rd arg=max size. 1484 %#H - Hex Dump & ASCII (e.g. "\x41\x62" -> "6B A7 'Ab'"). 1st arg=ptr, 2nd arg=size, 3rd arg=max size. 1485 %m - Error Message (e.g. 0 -> "kNoErr"). Modifiers and error code arg=the same as %d, %x, etc. 1486 %#s - Pascal-style length-prefixed string. Arg=ptr to string. 1487 %##s - DNS label-sequence name. Arg=ptr to name. 1488 %S - UTF-16 string, 0x0000 terminated. Host order if no BOM. Precision is UTF-16 count. Precision includes BOM. 1489 %#S - Big Endian UTF-16 string (unless BOM overrides). Otherwise, the same as %S. 1490 %##S - Little Endian UTF-16 string (unless BOM overrides). Otherwise, the same as %S. 1491 %U - Universally Unique Identifier (UUID) (e.g. 6ba7b810-9dad-11d1-80b4-00c04fd430c8). Arg=ptr to 16-byte UUID. 1492 </pre> 1493 */ 1494 1495 #if( DEBUG ) 1496 DEBUG_EXPORT size_t DebugSNPrintF(char *sbuffer, size_t buflen, const char *fmt, ...); 1497 #endif 1498 1499 //--------------------------------------------------------------------------------------------------------------------------- 1500 /*! @function DebugSNPrintFVAList 1501 1502 @abstract va_list version of DebugSNPrintF. See DebugSNPrintF for more info. 1503 */ 1504 1505 #if( DEBUG ) 1506 DEBUG_EXPORT size_t DebugSNPrintFVAList(char *sbuffer, size_t buflen, const char *fmt, va_list arg); 1507 #endif 1508 1509 //--------------------------------------------------------------------------------------------------------------------------- 1510 /*! @function DebugGetErrorString 1511 1512 @abstract Gets an error string from an error code. 1513 1514 @param inStatus Error code to get the string for. 1515 @param inBuffer Optional buffer to copy the string to for non-static strings. May be null. 1516 @param inBufferSize Size of optional buffer. May be 0. 1517 1518 @result C string containing error string for the error code. Guaranteed to be a valid, static string. If a 1519 buffer is supplied, the return value will always be a pointer to the supplied buffer, which will 1520 contain the best available description of the error code. If a buffer is not supplied, the return 1521 value will be the best available description of the error code that can be represented as a static 1522 string. This allows code that cannot use a temporary buffer to hold the result to still get a useful 1523 error string in most cases, but also allows code that can use a temporary buffer to get the best 1524 available description. 1525 */ 1526 1527 #if( DEBUG ) 1528 DEBUG_EXPORT const char * DebugGetErrorString( int_least32_t inErrorCode, char *inBuffer, size_t inBufferSize ); 1529 #endif 1530 1531 //--------------------------------------------------------------------------------------------------------------------------- 1532 /*! @function DebugHexDump 1533 1534 @abstract Hex dumps data to a string or to the output device. 1535 */ 1536 1537 #if( DEBUG ) 1538 DEBUG_EXPORT size_t 1539 DebugHexDump( 1540 DebugLevel inLevel, 1541 int inIndent, 1542 const char * inLabel, 1543 size_t inLabelSize, 1544 int inLabelMinWidth, 1545 const char * inType, 1546 size_t inTypeSize, 1547 const void * inDataStart, 1548 const void * inData, 1549 size_t inDataSize, 1550 DebugFlags inFlags, 1551 char * outBuffer, 1552 size_t inBufferSize ); 1553 #endif 1554 1555 #if( DEBUG ) 1556 #define dloghex( LEVEL, INDENT, LABEL, LABEL_SIZE, LABEL_MIN_SIZE, TYPE, TYPE_SIZE, DATA_START, DATA, DATA_SIZE, FLAGS, BUFFER, BUFFER_SIZE ) \ 1557 DebugHexDump( ( LEVEL ), (INDENT), ( LABEL ), ( LABEL_SIZE ), ( LABEL_MIN_SIZE ), ( TYPE ), ( TYPE_SIZE ), \ 1558 ( DATA_START ), ( DATA ), ( DATA_SIZE ), ( FLAGS ), ( BUFFER ), ( BUFFER_SIZE ) ) 1559 #else 1560 #define dloghex( LEVEL, INDENT, LABEL, LABEL_SIZE, LABEL_MIN_SIZE, TYPE, TYPE_SIZE, DATA_START, DATA, DATA_SIZE, FLAGS, BUFFER, BUFFER_SIZE ) 1561 #endif 1562 1563 //--------------------------------------------------------------------------------------------------------------------------- 1564 /*! @function DebugTaskLevel 1565 1566 @abstract Returns the current task level. 1567 1568 @result Current task level 1569 1570 @discussion 1571 1572 Bit masks to isolate portions of the result (note that some masks may also need bit shifts to right justify): 1573 <pre> 1574 kDebugInterruptLevelMask - Indicates the current interrupt level (> 0 means interrupt time). 1575 kDebugInVBLTaskMask - Indicates if a VBL task is currently being executed. 1576 kDebugInDeferredTaskMask - Indicates if a Deferred Task is currently being executed. 1577 kDebugInSecondaryInterruptHandlerMask - Indicates if a Secondary Interrupt Handler is currently being executed. 1578 kDebugPageFaultFatalMask - Indicates if it is unsafe to cause a page fault (worse than interrupt time). 1579 kDebugMPTaskLevelMask - Indicates if being called from an MP task. 1580 kDebugInterruptDepthMask - 0 means task level, 1 means in interrupt, > 1 means in nested interrupt. 1581 </pre> 1582 1583 Helpers: 1584 <pre> 1585 DebugExtractTaskLevelInterruptDepth() - Macro to extract interrupt depth from task level value. 1586 </pre> 1587 */ 1588 1589 #if( DEBUG ) 1590 DEBUG_EXPORT uint32_t DebugTaskLevel( void ); 1591 #endif 1592 1593 //--------------------------------------------------------------------------------------------------------------------------- 1594 /*! @function DebugServicesTest 1595 1596 @abstract Unit test. 1597 */ 1598 1599 #if( DEBUG ) 1600 DEBUG_EXPORT OSStatus DebugServicesTest( void ); 1601 #endif 1602 1603 #ifdef __cplusplus 1604 } 1605 #endif 1606 1607 #endif // __DEBUG_SERVICES__ 1608