1 /* -*- Mode: C; tab-width: 4 -*- 2 * 3 * Copyright (c) 1997-2004, 2020-2021 Apple 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 * https://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 To Do: 18 19 - Use StackWalk on Windows to optionally print stack frames. 20 */ 21 22 #if 0 23 #pragma mark == Includes == 24 #endif 25 26 //=========================================================================================================================== 27 // Includes 28 //=========================================================================================================================== 29 30 #if ( !KERNEL ) 31 #include <ctype.h> 32 #include <stdio.h> 33 #include <string.h> 34 #endif 35 36 #include "CommonServices.h" 37 38 #include "DebugServices.h" 39 40 #if ( DEBUG ) 41 42 #if ( TARGET_OS_WIN32 ) 43 #include <time.h> 44 45 #if ( !TARGET_OS_WINDOWS_CE ) 46 #include <fcntl.h> 47 #include <io.h> 48 #endif 49 #endif 50 51 #if ( DEBUG_IDEBUG_ENABLED && TARGET_API_MAC_OSX_KERNEL ) 52 #include <IOKit/IOLib.h> 53 #endif 54 55 // If MDNS_DEBUGMSGS is defined (even if defined 0), it is aware of mDNS and it is probably safe to include mDNSEmbeddedAPI.h. 56 57 #if ( defined( MDNS_DEBUGMSGS ) ) 58 #include "mDNSEmbeddedAPI.h" 59 #endif 60 61 #if 0 62 #pragma mark == Macros == 63 #endif 64 65 //=========================================================================================================================== 66 // Macros 67 //=========================================================================================================================== 68 69 #define DebugIsPrint( C ) ( ( ( C ) >= 0x20 ) && ( ( C ) <= 0x7E ) ) 70 71 #if 0 72 #pragma mark == Prototypes == 73 #endif 74 75 //=========================================================================================================================== 76 // Prototypes 77 //=========================================================================================================================== 78 79 static OSStatus DebugPrint( DebugLevel inLevel, char *inData, size_t inSize ); 80 81 // fprintf 82 83 #if ( DEBUG_FPRINTF_ENABLED ) 84 static OSStatus DebugFPrintFInit( DebugOutputTypeFlags inFlags, const char *inFilename ); 85 static void DebugFPrintFPrint( char *inData, size_t inSize ); 86 #endif 87 88 // iDebug (Mac OS X user and kernel) 89 90 #if ( DEBUG_IDEBUG_ENABLED ) 91 static OSStatus DebugiDebugInit( void ); 92 static void DebugiDebugPrint( char *inData, size_t inSize ); 93 #endif 94 95 // kprintf (Mac OS X Kernel) 96 97 #if ( DEBUG_KPRINTF_ENABLED ) 98 static void DebugKPrintFPrint( char *inData, size_t inSize ); 99 #endif 100 101 // Mac OS X IOLog (Mac OS X Kernel) 102 103 #if ( DEBUG_MAC_OS_X_IOLOG_ENABLED ) 104 static void DebugMacOSXIOLogPrint( char *inData, size_t inSize ); 105 #endif 106 107 // Mac OS X Log 108 109 #if ( TARGET_OS_MAC ) 110 static OSStatus DebugMacOSXLogInit( void ); 111 static void DebugMacOSXLogPrint( char *inData, size_t inSize ); 112 #endif 113 114 // Windows Debugger 115 116 #if ( TARGET_OS_WIN32 ) 117 static void DebugWindowsDebuggerPrint( char *inData, size_t inSize ); 118 #endif 119 120 // Windows Event Log 121 122 #if ( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE ) 123 static OSStatus DebugWindowsEventLogInit( const char *inName, HMODULE inModule ); 124 static void DebugWindowsEventLogPrint( DebugLevel inLevel, char *inData, size_t inSize ); 125 #endif 126 127 // DebugLib support 128 129 #if ( DEBUG_CORE_SERVICE_ASSERTS_ENABLED ) 130 static pascal void 131 DebugAssertOutputHandler( 132 OSType inComponentSignature, 133 UInt32 inOptions, 134 const char * inAssertionString, 135 const char * inExceptionString, 136 const char * inErrorString, 137 const char * inFileName, 138 long inLineNumber, 139 void * inValue, 140 ConstStr255Param inOutputMsg ); 141 #endif 142 143 // Utilities 144 145 static char * DebugNumVersionToString( uint32_t inVersion, char *inString ); 146 147 #if ( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE ) 148 static void DebugWinEnableConsole( void ); 149 #endif 150 151 #if ( TARGET_OS_WIN32 ) 152 static TCHAR * 153 DebugWinCharToTCharString( 154 const char * inCharString, 155 size_t inCharCount, 156 TCHAR * outTCharString, 157 size_t inTCharCountMax, 158 size_t * outTCharCount ); 159 #endif 160 161 #if 0 162 #pragma mark == Globals == 163 #endif 164 165 //=========================================================================================================================== 166 // Private Globals 167 //=========================================================================================================================== 168 169 // General 170 171 static bool gDebugInitialized = false; 172 static DebugOutputType gDebugOutputType = kDebugOutputTypeNone; 173 static DebugLevel gDebugPrintLevelMin = kDebugLevelInfo; 174 static DebugLevel gDebugPrintLevelMax = kDebugLevelMax; 175 static DebugLevel gDebugBreakLevel = kDebugLevelAssert; 176 #if ( DEBUG_CORE_SERVICE_ASSERTS_ENABLED ) 177 static DebugAssertOutputHandlerUPP gDebugAssertOutputHandlerUPP = NULL; 178 #endif 179 180 // Custom 181 182 static DebugOutputFunctionPtr gDebugCustomOutputFunction = NULL; 183 static void * gDebugCustomOutputContext = NULL; 184 185 // fprintf 186 187 #if ( DEBUG_FPRINTF_ENABLED ) 188 static FILE * gDebugFPrintFFile = NULL; 189 #endif 190 191 // MacOSXLog 192 193 #if ( TARGET_OS_MAC ) 194 typedef int ( *DebugMacOSXLogFunctionPtr )( const char *inFormat, ... ); 195 196 static DebugMacOSXLogFunctionPtr gDebugMacOSXLogFunction = NULL; 197 #endif 198 199 // WindowsEventLog 200 201 202 #if ( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE ) 203 static HANDLE gDebugWindowsEventLogEventSource = NULL; 204 #endif 205 206 #if 0 207 #pragma mark - 208 #pragma mark == General == 209 #endif 210 211 //=========================================================================================================================== 212 // DebugInitialize 213 //=========================================================================================================================== 214 215 DEBUG_EXPORT OSStatus DebugInitialize( DebugOutputType inType, ... ) 216 { 217 OSStatus err; 218 DebugOutputType type; 219 va_list args; 220 221 va_start( args, inType ); 222 223 // Set up DebugLib stuff (if building with Debugging.h). 224 225 #if ( DEBUG_CORE_SERVICE_ASSERTS_ENABLED ) 226 if( !gDebugAssertOutputHandlerUPP ) 227 { 228 gDebugAssertOutputHandlerUPP = NewDebugAssertOutputHandlerUPP( DebugAssertOutputHandler ); 229 check( gDebugAssertOutputHandlerUPP ); 230 if( gDebugAssertOutputHandlerUPP ) 231 { 232 InstallDebugAssertOutputHandler( gDebugAssertOutputHandlerUPP ); 233 } 234 } 235 #endif 236 237 // Pre-process meta-output kind to pick an appropriate output kind for the platform. 238 239 type = inType; 240 if( type == kDebugOutputTypeMetaConsole ) 241 { 242 #if ( TARGET_OS_MAC ) 243 type = kDebugOutputTypeMacOSXLog; 244 #elif ( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE ) 245 #if ( DEBUG_FPRINTF_ENABLED ) 246 type = kDebugOutputTypeFPrintF; 247 #else 248 type = kDebugOutputTypeWindowsDebugger; 249 #endif 250 #elif ( TARGET_API_MAC_OSX_KERNEL ) 251 #if ( DEBUG_MAC_OS_X_IOLOG_ENABLED ) 252 type = kDebugOutputTypeMacOSXIOLog; 253 #elif ( DEBUG_IDEBUG_ENABLED ) 254 type = kDebugOutputTypeiDebug; 255 #elif ( DEBUG_KPRINTF_ENABLED ) 256 type = kDebugOutputTypeKPrintF; 257 #endif 258 #else 259 #if ( DEBUG_FPRINTF_ENABLED ) 260 type = kDebugOutputTypeFPrintF; 261 #endif 262 #endif 263 } 264 265 // Process output kind. 266 267 gDebugOutputType = type; 268 switch( type ) 269 { 270 case kDebugOutputTypeNone: 271 err = kNoErr; 272 break; 273 274 case kDebugOutputTypeCustom: 275 gDebugCustomOutputFunction = va_arg( args, DebugOutputFunctionPtr ); 276 gDebugCustomOutputContext = va_arg( args, void * ); 277 err = kNoErr; 278 break; 279 280 #if ( DEBUG_FPRINTF_ENABLED ) 281 case kDebugOutputTypeFPrintF: 282 if( inType == kDebugOutputTypeMetaConsole ) 283 { 284 err = DebugFPrintFInit( kDebugOutputTypeFlagsStdErr, NULL ); 285 } 286 else 287 { 288 DebugOutputTypeFlags flags; 289 const char * filename; 290 291 flags = (DebugOutputTypeFlags) va_arg( args, unsigned int ); 292 if( ( flags & kDebugOutputTypeFlagsTypeMask ) == kDebugOutputTypeFlagsFile ) 293 { 294 filename = va_arg( args, const char * ); 295 } 296 else 297 { 298 filename = NULL; 299 } 300 err = DebugFPrintFInit( flags, filename ); 301 } 302 break; 303 #endif 304 305 #if ( DEBUG_IDEBUG_ENABLED ) 306 case kDebugOutputTypeiDebug: 307 err = DebugiDebugInit(); 308 break; 309 #endif 310 311 #if ( DEBUG_KPRINTF_ENABLED ) 312 case kDebugOutputTypeKPrintF: 313 err = kNoErr; 314 break; 315 #endif 316 317 #if ( DEBUG_MAC_OS_X_IOLOG_ENABLED ) 318 case kDebugOutputTypeMacOSXIOLog: 319 err = kNoErr; 320 break; 321 #endif 322 323 #if ( TARGET_OS_MAC ) 324 case kDebugOutputTypeMacOSXLog: 325 err = DebugMacOSXLogInit(); 326 break; 327 #endif 328 329 #if ( TARGET_OS_WIN32 ) 330 case kDebugOutputTypeWindowsDebugger: 331 err = kNoErr; 332 break; 333 #endif 334 335 #if ( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE ) 336 case kDebugOutputTypeWindowsEventLog: 337 { 338 const char * name; 339 HMODULE module; 340 341 name = va_arg( args, const char * ); 342 module = va_arg( args, HMODULE ); 343 err = DebugWindowsEventLogInit( name, module ); 344 } 345 break; 346 #endif 347 348 default: 349 err = kParamErr; 350 goto exit; 351 } 352 gDebugInitialized = true; 353 354 exit: 355 va_end( args ); 356 return( err ); 357 } 358 359 //=========================================================================================================================== 360 // DebugFinalize 361 //=========================================================================================================================== 362 363 DEBUG_EXPORT void DebugFinalize( void ) 364 { 365 #if ( DEBUG_CORE_SERVICE_ASSERTS_ENABLED ) 366 check( gDebugAssertOutputHandlerUPP ); 367 if( gDebugAssertOutputHandlerUPP ) 368 { 369 InstallDebugAssertOutputHandler( NULL ); 370 DisposeDebugAssertOutputHandlerUPP( gDebugAssertOutputHandlerUPP ); 371 gDebugAssertOutputHandlerUPP = NULL; 372 } 373 #endif 374 } 375 376 //=========================================================================================================================== 377 // DebugGetProperty 378 //=========================================================================================================================== 379 380 DEBUG_EXPORT OSStatus DebugGetProperty( DebugPropertyTag inTag, ... ) 381 { 382 OSStatus err; 383 va_list args; 384 DebugLevel * level; 385 386 va_start( args, inTag ); 387 switch( inTag ) 388 { 389 case kDebugPropertyTagPrintLevelMin: 390 level = va_arg( args, DebugLevel * ); 391 *level = gDebugPrintLevelMin; 392 err = kNoErr; 393 break; 394 395 case kDebugPropertyTagPrintLevelMax: 396 level = va_arg( args, DebugLevel * ); 397 *level = gDebugPrintLevelMax; 398 err = kNoErr; 399 break; 400 401 case kDebugPropertyTagBreakLevel: 402 level = va_arg( args, DebugLevel * ); 403 *level = gDebugBreakLevel; 404 err = kNoErr; 405 break; 406 407 default: 408 err = kUnsupportedErr; 409 break; 410 } 411 va_end( args ); 412 return( err ); 413 } 414 415 //=========================================================================================================================== 416 // DebugSetProperty 417 //=========================================================================================================================== 418 419 DEBUG_EXPORT OSStatus DebugSetProperty( DebugPropertyTag inTag, ... ) 420 { 421 OSStatus err; 422 va_list args; 423 DebugLevel level; 424 425 va_start( args, inTag ); 426 switch( inTag ) 427 { 428 case kDebugPropertyTagPrintLevelMin: 429 level = va_arg( args, DebugLevel ); 430 gDebugPrintLevelMin = level; 431 err = kNoErr; 432 break; 433 434 case kDebugPropertyTagPrintLevelMax: 435 level = va_arg( args, DebugLevel ); 436 gDebugPrintLevelMax = level; 437 err = kNoErr; 438 break; 439 440 case kDebugPropertyTagBreakLevel: 441 level = va_arg( args, DebugLevel ); 442 gDebugBreakLevel = level; 443 err = kNoErr; 444 break; 445 446 default: 447 err = kUnsupportedErr; 448 break; 449 } 450 va_end( args ); 451 return( err ); 452 } 453 454 #if 0 455 #pragma mark - 456 #pragma mark == Output == 457 #endif 458 459 //=========================================================================================================================== 460 // DebugPrintF 461 //=========================================================================================================================== 462 463 DEBUG_EXPORT size_t DebugPrintF( DebugLevel inLevel, const char *inFormat, ... ) 464 { 465 va_list args; 466 size_t n; 467 468 // Skip if the level is not in the enabled range.. 469 470 if( ( inLevel < gDebugPrintLevelMin ) || ( inLevel > gDebugPrintLevelMax ) ) 471 { 472 n = 0; 473 goto exit; 474 } 475 476 va_start( args, inFormat ); 477 n = DebugPrintFVAList( inLevel, inFormat, args ); 478 va_end( args ); 479 480 exit: 481 return( n ); 482 } 483 484 //=========================================================================================================================== 485 // DebugPrintFVAList 486 //=========================================================================================================================== 487 488 DEBUG_EXPORT size_t DebugPrintFVAList( DebugLevel inLevel, const char *inFormat, va_list inArgs ) 489 { 490 size_t n; 491 char buffer[ 512 ]; 492 493 // Skip if the level is not in the enabled range.. 494 495 if( ( inLevel < gDebugPrintLevelMin ) || ( inLevel > gDebugPrintLevelMax ) ) 496 { 497 n = 0; 498 goto exit; 499 } 500 501 n = DebugSNPrintFVAList( buffer, sizeof( buffer ), inFormat, inArgs ); 502 DebugPrint( inLevel, buffer, (size_t) n ); 503 504 exit: 505 return( n ); 506 } 507 508 //=========================================================================================================================== 509 // DebugPrint 510 //=========================================================================================================================== 511 512 static OSStatus DebugPrint( DebugLevel inLevel, char *inData, size_t inSize ) 513 { 514 OSStatus err; 515 516 // Skip if the level is not in the enabled range.. 517 518 if( ( inLevel < gDebugPrintLevelMin ) || ( inLevel > gDebugPrintLevelMax ) ) 519 { 520 err = kRangeErr; 521 goto exit; 522 } 523 524 // Printing is not safe at interrupt time so check for this and warn with an interrupt safe mechanism (if available). 525 526 if( DebugTaskLevel() & kDebugInterruptLevelMask ) 527 { 528 err = kExecutionStateErr; 529 goto exit; 530 } 531 532 // Initialize the debugging library if it hasn't already been initialized (allows for zero-config usage). 533 534 if( !gDebugInitialized ) 535 { 536 debug_initialize( kDebugOutputTypeMetaConsole ); 537 } 538 539 // Print based on the current output type. 540 541 switch( gDebugOutputType ) 542 { 543 case kDebugOutputTypeNone: 544 break; 545 546 case kDebugOutputTypeCustom: 547 if( gDebugCustomOutputFunction ) 548 { 549 gDebugCustomOutputFunction( inData, inSize, gDebugCustomOutputContext ); 550 } 551 break; 552 553 #if ( DEBUG_FPRINTF_ENABLED ) 554 case kDebugOutputTypeFPrintF: 555 DebugFPrintFPrint( inData, inSize ); 556 break; 557 #endif 558 559 #if ( DEBUG_IDEBUG_ENABLED ) 560 case kDebugOutputTypeiDebug: 561 DebugiDebugPrint( inData, inSize ); 562 break; 563 #endif 564 565 #if ( DEBUG_KPRINTF_ENABLED ) 566 case kDebugOutputTypeKPrintF: 567 DebugKPrintFPrint( inData, inSize ); 568 break; 569 #endif 570 571 #if ( DEBUG_MAC_OS_X_IOLOG_ENABLED ) 572 case kDebugOutputTypeMacOSXIOLog: 573 DebugMacOSXIOLogPrint( inData, inSize ); 574 break; 575 #endif 576 577 #if ( TARGET_OS_MAC ) 578 case kDebugOutputTypeMacOSXLog: 579 DebugMacOSXLogPrint( inData, inSize ); 580 break; 581 #endif 582 583 #if ( TARGET_OS_WIN32 ) 584 case kDebugOutputTypeWindowsDebugger: 585 DebugWindowsDebuggerPrint( inData, inSize ); 586 break; 587 #endif 588 589 #if ( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE ) 590 case kDebugOutputTypeWindowsEventLog: 591 DebugWindowsEventLogPrint( inLevel, inData, inSize ); 592 break; 593 #endif 594 595 default: 596 break; 597 } 598 err = kNoErr; 599 600 exit: 601 return( err ); 602 } 603 604 //=========================================================================================================================== 605 // DebugPrintAssert 606 // 607 // Warning: This routine relies on several of the strings being string constants that will exist forever because the 608 // underlying logMsg API that does the printing is asynchronous so it cannot use temporary/stack-based 609 // pointer variables (e.g. local strings). The debug macros that invoke this function only use constant 610 // constant strings, but if this function is invoked directly from other places, it must use constant strings. 611 //=========================================================================================================================== 612 613 DEBUG_EXPORT void 614 DebugPrintAssert( 615 int_least32_t inErrorCode, 616 const char * inAssertString, 617 const char * inMessage, 618 const char * inFilename, 619 int_least32_t inLineNumber, 620 const char * inFunction ) 621 { 622 // Skip if the level is not in the enabled range.. 623 624 if( ( kDebugLevelAssert < gDebugPrintLevelMin ) || ( kDebugLevelAssert > gDebugPrintLevelMax ) ) 625 { 626 return; 627 } 628 629 if( inErrorCode != 0 ) 630 { 631 DebugPrintF( 632 kDebugLevelAssert, 633 "\n" 634 "[ASSERT] error: %ld (%m)\n" 635 "[ASSERT] where: \"%s\", line %ld, \"%s\"\n" 636 "\n", 637 inErrorCode, inErrorCode, 638 inFilename ? inFilename : "", 639 inLineNumber, 640 inFunction ? inFunction : "" ); 641 } 642 else 643 { 644 DebugPrintF( 645 kDebugLevelAssert, 646 "\n" 647 "[ASSERT] assert: \"%s\" %s\n" 648 "[ASSERT] where: \"%s\", line %ld, \"%s\"\n" 649 "\n", 650 inAssertString ? inAssertString : "", 651 inMessage ? inMessage : "", 652 inFilename ? inFilename : "", 653 inLineNumber, 654 inFunction ? inFunction : "" ); 655 } 656 657 // Break into the debugger if enabled. 658 659 #if ( TARGET_OS_WIN32 ) 660 if( gDebugBreakLevel <= kDebugLevelAssert ) 661 { 662 if( IsDebuggerPresent() ) 663 { 664 DebugBreak(); 665 } 666 } 667 #endif 668 } 669 670 #if 0 671 #pragma mark - 672 #endif 673 674 #if ( DEBUG_FPRINTF_ENABLED ) 675 //=========================================================================================================================== 676 // DebugFPrintFInit 677 //=========================================================================================================================== 678 679 static OSStatus DebugFPrintFInit( DebugOutputTypeFlags inFlags, const char *inFilename ) 680 { 681 OSStatus err; 682 DebugOutputTypeFlags typeFlags; 683 684 typeFlags = inFlags & kDebugOutputTypeFlagsTypeMask; 685 if( typeFlags == kDebugOutputTypeFlagsStdOut ) 686 { 687 #if ( TARGET_OS_WIN32 ) 688 DebugWinEnableConsole(); 689 #endif 690 691 gDebugFPrintFFile = stdout; 692 } 693 else if( typeFlags == kDebugOutputTypeFlagsStdErr ) 694 { 695 #if ( TARGET_OS_WIN32 ) 696 DebugWinEnableConsole(); 697 #endif 698 699 gDebugFPrintFFile = stdout; 700 } 701 else if( typeFlags == kDebugOutputTypeFlagsFile ) 702 { 703 require_action_quiet( inFilename && ( *inFilename != '\0' ), exit, err = kOpenErr ); 704 705 gDebugFPrintFFile = fopen( inFilename, "a" ); 706 require_action_quiet( gDebugFPrintFFile, exit, err = kOpenErr ); 707 } 708 else 709 { 710 err = kParamErr; 711 goto exit; 712 } 713 err = kNoErr; 714 715 exit: 716 return( err ); 717 } 718 719 //=========================================================================================================================== 720 // DebugFPrintFPrint 721 //=========================================================================================================================== 722 723 static void DebugFPrintFPrint( char *inData, size_t inSize ) 724 { 725 char * p; 726 char * q; 727 728 // Convert \r to \n. fprintf will interpret \n and convert to whatever is appropriate for the platform. 729 730 p = inData; 731 q = p + inSize; 732 while( p < q ) 733 { 734 if( *p == '\r' ) 735 { 736 *p = '\n'; 737 } 738 ++p; 739 } 740 741 // Write the data and flush. 742 743 if( gDebugFPrintFFile ) 744 { 745 fprintf( gDebugFPrintFFile, "%.*s", (int) inSize, inData ); 746 fflush( gDebugFPrintFFile ); 747 } 748 } 749 #endif // DEBUG_FPRINTF_ENABLED 750 751 #if ( DEBUG_IDEBUG_ENABLED ) 752 //=========================================================================================================================== 753 // DebugiDebugInit 754 //=========================================================================================================================== 755 756 static OSStatus DebugiDebugInit( void ) 757 { 758 OSStatus err; 759 760 #if ( TARGET_API_MAC_OSX_KERNEL ) 761 762 extern uint32_t * _giDebugReserved1; 763 764 // Emulate the iDebugSetOutputType macro in iDebugServices.h. 765 // Note: This is not thread safe, but neither is iDebugServices.h nor iDebugKext. 766 767 if( !_giDebugReserved1 ) 768 { 769 _giDebugReserved1 = (uint32_t *) IOMalloc( sizeof( uint32_t ) ); 770 require_action_quiet( _giDebugReserved1, exit, err = kNoMemoryErr ); 771 } 772 *_giDebugReserved1 = 0x00010000U; 773 err = kNoErr; 774 exit: 775 #else 776 777 __private_extern__ void iDebugSetOutputTypeInternal( uint32_t inType ); 778 779 iDebugSetOutputTypeInternal( 0x00010000U ); 780 err = kNoErr; 781 782 #endif 783 784 return( err ); 785 } 786 787 //=========================================================================================================================== 788 // DebugiDebugPrint 789 //=========================================================================================================================== 790 791 static void DebugiDebugPrint( char *inData, size_t inSize ) 792 { 793 #if ( TARGET_API_MAC_OSX_KERNEL ) 794 795 // Locally declared here so we do not need to include iDebugKext.h. 796 // Note: IOKit uses a global namespace for all code and only a partial link occurs at build time. When the 797 // KEXT is loaded, the runtime linker will link in this extern'd symbol (assuming iDebug is present). 798 // _giDebugLogInternal is actually part of IOKit proper so this should link even if iDebug is not present. 799 800 typedef void ( *iDebugLogFunctionPtr )( uint32_t inLevel, uint32_t inTag, const char *inFormat, ... ); 801 802 extern iDebugLogFunctionPtr _giDebugLogInternal; 803 804 if( _giDebugLogInternal ) 805 { 806 _giDebugLogInternal( 0, 0, "%.*s", (int) inSize, inData ); 807 } 808 809 #else 810 811 __private_extern__ void iDebugLogInternal( uint32_t inLevel, uint32_t inTag, const char *inFormat, ... ); 812 813 iDebugLogInternal( 0, 0, "%.*s", (int) inSize, inData ); 814 815 #endif 816 } 817 #endif 818 819 #if ( DEBUG_KPRINTF_ENABLED ) 820 //=========================================================================================================================== 821 // DebugKPrintFPrint 822 //=========================================================================================================================== 823 824 static void DebugKPrintFPrint( char *inData, size_t inSize ) 825 { 826 extern void kprintf( const char *inFormat, ... ); 827 828 kprintf( "%.*s", (int) inSize, inData ); 829 } 830 #endif 831 832 #if ( DEBUG_MAC_OS_X_IOLOG_ENABLED ) 833 //=========================================================================================================================== 834 // DebugMacOSXIOLogPrint 835 //=========================================================================================================================== 836 837 static void DebugMacOSXIOLogPrint( char *inData, size_t inSize ) 838 { 839 extern void IOLog( const char *inFormat, ... ); 840 841 IOLog( "%.*s", (int) inSize, inData ); 842 } 843 #endif 844 845 #if ( TARGET_OS_MAC ) 846 //=========================================================================================================================== 847 // DebugMacOSXLogInit 848 //=========================================================================================================================== 849 850 static OSStatus DebugMacOSXLogInit( void ) 851 { 852 OSStatus err; 853 CFStringRef path; 854 CFURLRef url; 855 CFBundleRef bundle; 856 CFStringRef functionName; 857 void * functionPtr; 858 859 bundle = NULL; 860 861 // Create a bundle reference for System.framework. 862 863 path = CFSTR( "/System/Library/Frameworks/System.framework" ); 864 url = CFURLCreateWithFileSystemPath( NULL, path, kCFURLPOSIXPathStyle, true ); 865 require_action_quiet( url, exit, err = memFullErr ); 866 867 bundle = CFBundleCreate( NULL, url ); 868 CFRelease( url ); 869 require_action_quiet( bundle, exit, err = memFullErr ); 870 871 // Get a ptr to the system's "printf" function from System.framework. 872 873 functionName = CFSTR( "printf" ); 874 functionPtr = CFBundleGetFunctionPointerForName( bundle, functionName ); 875 require_action_quiet( functionPtr, exit, err = memFullErr ); 876 877 // Success! Note: The bundle cannot be released because it would invalidate the function ptr. 878 879 gDebugMacOSXLogFunction = (DebugMacOSXLogFunctionPtr) functionPtr; 880 bundle = NULL; 881 err = noErr; 882 883 exit: 884 if( bundle ) 885 { 886 CFRelease( bundle ); 887 } 888 return( err ); 889 } 890 891 //=========================================================================================================================== 892 // DebugMacOSXLogPrint 893 //=========================================================================================================================== 894 895 static void DebugMacOSXLogPrint( char *inData, size_t inSize ) 896 { 897 if( gDebugMacOSXLogFunction ) 898 { 899 gDebugMacOSXLogFunction( "%.*s", (int) inSize, inData ); 900 } 901 } 902 #endif 903 904 #if ( TARGET_OS_WIN32 ) 905 //=========================================================================================================================== 906 // DebugWindowsDebuggerPrint 907 //=========================================================================================================================== 908 909 void DebugWindowsDebuggerPrint( char *inData, size_t inSize ) 910 { 911 TCHAR buffer[ 512 ]; 912 const char * src; 913 const char * end; 914 TCHAR * dst; 915 char c; 916 917 // Copy locally and null terminate the string. This also converts from char to TCHAR in case we are 918 // building with UNICODE enabled since the input is always char. Also convert \r to \n in the process. 919 920 src = inData; 921 if( inSize >= sizeof_array( buffer ) ) 922 { 923 inSize = sizeof_array( buffer ) - 1; 924 } 925 end = src + inSize; 926 dst = buffer; 927 while( src < end ) 928 { 929 c = *src++; 930 if( c == '\r' ) 931 { 932 c = '\n'; 933 } 934 *dst++ = (TCHAR) c; 935 } 936 *dst = 0; 937 938 // Print out the string to the debugger. 939 940 OutputDebugString( buffer ); 941 } 942 #endif 943 944 #if ( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE ) 945 //=========================================================================================================================== 946 // DebugWindowsEventLogInit 947 //=========================================================================================================================== 948 949 static OSStatus DebugWindowsEventLogInit( const char *inName, HMODULE inModule ) 950 { 951 OSStatus err; 952 HKEY key; 953 TCHAR name[ 128 ]; 954 const char * src; 955 TCHAR path[ MAX_PATH ]; 956 size_t size; 957 DWORD typesSupported; 958 DWORD n; 959 960 key = NULL; 961 962 // Use a default name if needed then convert the name to TCHARs so it works on ANSI or Unicode builds. 963 964 if( !inName || ( *inName == '\0' ) ) 965 { 966 inName = "DefaultApp"; 967 } 968 DebugWinCharToTCharString( inName, kSizeCString, name, sizeof( name ), NULL ); 969 970 // Build the path string using the fixed registry path and app name. 971 972 src = "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\"; 973 DebugWinCharToTCharString( src, kSizeCString, path, sizeof_array( path ), &size ); 974 DebugWinCharToTCharString( inName, kSizeCString, path + size, sizeof_array( path ) - size, NULL ); 975 976 // Add/Open the source name as a sub-key under the Application key in the EventLog registry key. 977 978 err = RegCreateKeyEx( HKEY_LOCAL_MACHINE, path, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, NULL ); 979 require_noerr_quiet( err, exit ); 980 981 // Set the path in the EventMessageFile subkey. Add 1 to the TCHAR count to include the null terminator. 982 983 n = GetModuleFileName( inModule, path, sizeof_array( path ) ); 984 err = translate_errno( n > 0, (OSStatus) GetLastError(), kParamErr ); 985 require_noerr_quiet( err, exit ); 986 n += 1; 987 n *= sizeof( TCHAR ); 988 989 err = RegSetValueEx( key, TEXT( "EventMessageFile" ), 0, REG_EXPAND_SZ, (const LPBYTE) path, n ); 990 require_noerr_quiet( err, exit ); 991 992 // Set the supported event types in the TypesSupported subkey. 993 994 typesSupported = EVENTLOG_SUCCESS | EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE | 995 EVENTLOG_AUDIT_SUCCESS | EVENTLOG_AUDIT_FAILURE; 996 err = RegSetValueEx( key, TEXT( "TypesSupported" ), 0, REG_DWORD, (const LPBYTE) &typesSupported, sizeof( DWORD ) ); 997 require_noerr_quiet( err, exit ); 998 999 // Set up the event source. 1000 1001 gDebugWindowsEventLogEventSource = RegisterEventSource( NULL, name ); 1002 err = translate_errno( gDebugWindowsEventLogEventSource, (OSStatus) GetLastError(), kParamErr ); 1003 require_noerr_quiet( err, exit ); 1004 1005 exit: 1006 if( key ) 1007 { 1008 RegCloseKey( key ); 1009 } 1010 return( err ); 1011 } 1012 1013 //=========================================================================================================================== 1014 // DebugWindowsEventLogPrint 1015 //=========================================================================================================================== 1016 1017 static void DebugWindowsEventLogPrint( DebugLevel inLevel, char *inData, size_t inSize ) 1018 { 1019 WORD type; 1020 TCHAR buffer[ 512 ]; 1021 const char * src; 1022 const char * end; 1023 TCHAR * dst; 1024 char c; 1025 const TCHAR * array[ 1 ]; 1026 1027 // Map the debug level to a Windows EventLog type. 1028 1029 if( inLevel <= kDebugLevelNotice ) 1030 { 1031 type = EVENTLOG_INFORMATION_TYPE; 1032 } 1033 else if( inLevel <= kDebugLevelWarning ) 1034 { 1035 type = EVENTLOG_WARNING_TYPE; 1036 } 1037 else 1038 { 1039 type = EVENTLOG_ERROR_TYPE; 1040 } 1041 1042 // Copy locally and null terminate the string. This also converts from char to TCHAR in case we are 1043 // building with UNICODE enabled since the input is always char. Also convert \r to \n in the process. 1044 1045 src = inData; 1046 if( inSize >= sizeof_array( buffer ) ) 1047 { 1048 inSize = sizeof_array( buffer ) - 1; 1049 } 1050 end = src + inSize; 1051 dst = buffer; 1052 while( src < end ) 1053 { 1054 c = *src++; 1055 if( c == '\r' ) 1056 { 1057 c = '\n'; 1058 } 1059 *dst++ = (TCHAR) c; 1060 } 1061 *dst = 0; 1062 1063 // Add the the string to the event log. 1064 1065 array[ 0 ] = buffer; 1066 if( gDebugWindowsEventLogEventSource ) 1067 { 1068 ReportEvent( gDebugWindowsEventLogEventSource, type, 0, 0x20000001L, NULL, 1, 0, array, NULL ); 1069 } 1070 } 1071 #endif // TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE 1072 1073 #if ( DEBUG_CORE_SERVICE_ASSERTS_ENABLED ) 1074 //=========================================================================================================================== 1075 // DebugAssertOutputHandler 1076 //=========================================================================================================================== 1077 1078 static pascal void 1079 DebugAssertOutputHandler( 1080 OSType inComponentSignature, 1081 UInt32 inOptions, 1082 const char * inAssertString, 1083 const char * inExceptionString, 1084 const char * inErrorString, 1085 const char * inFileName, 1086 long inLineNumber, 1087 void * inValue, 1088 ConstStr255Param inOutputMsg ) 1089 { 1090 DEBUG_UNUSED( inComponentSignature ); 1091 DEBUG_UNUSED( inOptions ); 1092 DEBUG_UNUSED( inExceptionString ); 1093 DEBUG_UNUSED( inValue ); 1094 DEBUG_UNUSED( inOutputMsg ); 1095 1096 DebugPrintAssert( 0, inAssertString, inErrorString, inFileName, (int_least32_t) inLineNumber, "" ); 1097 } 1098 #endif 1099 1100 #if 0 1101 #pragma mark - 1102 #pragma mark == Utilities == 1103 #endif 1104 1105 //=========================================================================================================================== 1106 // DebugSNPrintF 1107 // 1108 // Stolen from mDNS.c's mDNS_snprintf/mDNS_vsnprintf with the following changes: 1109 // 1110 // Changed names to avoid name collisions with the mDNS versions. 1111 // Changed types to standard C types since mDNSEmbeddedAPI.h may not be available. 1112 // Conditionalized mDNS stuff so it can be used with or with mDNSEmbeddedAPI.h. 1113 // Added 64-bit support for %d (%lld), %i (%lli), %u (%llu), %o (%llo), %x (%llx), and %b (%llb). 1114 // Added %@ - Cocoa/CoreFoundation object. Param is the object. Strings are used directly. Others use CFCopyDescription. 1115 // Added %.8a - FIbre Channel address. Arg=ptr to address. 1116 // Added %##a - IPv4 (if AF_INET defined) or IPv6 (if AF_INET6 defined) sockaddr. Arg=ptr to sockaddr. 1117 // Added %b - Binary representation of integer (e.g. 01101011). Modifiers and arg=the same as %d, %x, etc. 1118 // Added %C - Mac-style FourCharCode (e.g. 'APPL'). Arg=32-bit value to print as a Mac-style FourCharCode. 1119 // Added %H - Hex Dump (e.g. "\x6b\xa7" -> "6B A7"). 1st arg=ptr, 2nd arg=size, 3rd arg=max size. 1120 // Added %#H - Hex Dump & ASCII (e.g. "\x41\x62" -> "6B A7 'Ab'"). 1st arg=ptr, 2nd arg=size, 3rd arg=max size. 1121 // Added %m - Error Message (e.g. 0 -> "kNoErr"). Modifiers and error code args are the same as %d, %x, etc. 1122 // Added %S - UTF-16 string. Host order if no BOM. Precision is UTF-16 char count. BOM counts in any precision. Arg=ptr. 1123 // Added %#S - Big Endian UTF-16 string (unless BOM overrides). Otherwise the same as %S. 1124 // Added %##S - Little Endian UTF-16 string (unless BOM overrides). Otherwise the same as %S. 1125 // Added %U - Universally Unique Identifier (UUID) (e.g. 6ba7b810-9dad-11d1-80b4-00c04fd430c8). Arg=ptr to 16-byte UUID. 1126 //=========================================================================================================================== 1127 1128 DEBUG_EXPORT size_t DebugSNPrintF(char *sbuffer, size_t buflen, const char *fmt, ...) 1129 { 1130 size_t length; 1131 1132 va_list ptr; 1133 va_start(ptr,fmt); 1134 length = DebugSNPrintFVAList(sbuffer, buflen, fmt, ptr); 1135 va_end(ptr); 1136 1137 return(length); 1138 } 1139 1140 //=========================================================================================================================== 1141 // DebugSNPrintFVAList - va_list version of DebugSNPrintF. See DebugSNPrintF for more info. 1142 //=========================================================================================================================== 1143 1144 DEBUG_EXPORT size_t DebugSNPrintFVAList(char *sbuffer, size_t buflen, const char *fmt, va_list arg) 1145 { 1146 static const struct DebugSNPrintF_format 1147 { 1148 unsigned leftJustify : 1; 1149 unsigned forceSign : 1; 1150 unsigned zeroPad : 1; 1151 unsigned havePrecision : 1; 1152 unsigned hSize : 1; 1153 char lSize; 1154 char altForm; 1155 char sign; // +, - or space 1156 unsigned int fieldWidth; 1157 unsigned int precision; 1158 } DebugSNPrintF_format_default = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 1159 1160 size_t nwritten = 0; 1161 int c; 1162 #if TYPE_LONGLONG_NATIVE 1163 unsigned_long_long_compat n; 1164 unsigned_long_long_compat base; 1165 #else 1166 unsigned long n; 1167 unsigned long base; 1168 #endif 1169 if (buflen == 0) return(0); 1170 buflen--; // Pre-reserve one space in the buffer for the terminating nul 1171 if (buflen == 0) goto exit; 1172 1173 for (c = *fmt; c != 0; c = *++fmt) 1174 { 1175 if (c != '%') 1176 { 1177 *sbuffer++ = (char)c; 1178 if (++nwritten >= buflen) goto exit; 1179 } 1180 else 1181 { 1182 size_t i=0, j; 1183 // The mDNS Vsprintf Argument Conversion Buffer is used as a temporary holding area for 1184 // generating decimal numbers, hexdecimal numbers, IP addresses, domain name strings, etc. 1185 // The size needs to be enough for a 256-byte domain name plus some error text. 1186 #define mDNS_VACB_Size 300 1187 char mDNS_VACB[mDNS_VACB_Size]; 1188 #define mDNS_VACB_Lim (&mDNS_VACB[mDNS_VACB_Size]) 1189 #define mDNS_VACB_Remain(s) ((size_t)(mDNS_VACB_Lim - s)) 1190 char *s = mDNS_VACB_Lim; 1191 const char *digits = "0123456789ABCDEF"; 1192 struct DebugSNPrintF_format F = DebugSNPrintF_format_default; 1193 1194 for(;;) // decode flags 1195 { 1196 c = *++fmt; 1197 if (c == '-') F.leftJustify = 1; 1198 else if (c == '+') F.forceSign = 1; 1199 else if (c == ' ') F.sign = ' '; 1200 else if (c == '#') F.altForm++; 1201 else if (c == '0') F.zeroPad = 1; 1202 else break; 1203 } 1204 1205 if (c == '*') // decode field width 1206 { 1207 int f = va_arg(arg, int); 1208 if (f < 0) { f = -f; F.leftJustify = 1; } 1209 F.fieldWidth = (unsigned int)f; 1210 c = *++fmt; 1211 } 1212 else 1213 { 1214 for (; c >= '0' && c <= '9'; c = *++fmt) 1215 F.fieldWidth = (10 * F.fieldWidth) + (c - '0'); 1216 } 1217 1218 if (c == '.') // decode precision 1219 { 1220 if ((c = *++fmt) == '*') 1221 { F.precision = va_arg(arg, unsigned int); c = *++fmt; } 1222 else for (; c >= '0' && c <= '9'; c = *++fmt) 1223 F.precision = (10 * F.precision) + (c - '0'); 1224 F.havePrecision = 1; 1225 } 1226 1227 if (F.leftJustify) F.zeroPad = 0; 1228 1229 conv: 1230 switch (c) // perform appropriate conversion 1231 { 1232 case 'h': F.hSize = 1; c = *++fmt; goto conv; 1233 case 'l': // fall through 1234 case 'L': F.lSize++; c = *++fmt; goto conv; 1235 case 'd': 1236 case 'i': base = 10; 1237 goto canBeSigned; 1238 case 'u': base = 10; 1239 goto notSigned; 1240 case 'o': base = 8; 1241 goto notSigned; 1242 case 'b': base = 2; 1243 goto notSigned; 1244 case 'p': n = va_arg(arg, uintptr_t); 1245 F.havePrecision = 1; 1246 F.precision = (sizeof(uintptr_t) == 4) ? 8 : 16; 1247 F.sign = 0; 1248 base = 16; 1249 c = 'x'; 1250 goto number; 1251 case 'x': digits = "0123456789abcdef"; 1252 case 'X': base = 16; 1253 goto notSigned; 1254 canBeSigned: 1255 #if TYPE_LONGLONG_NATIVE 1256 if (F.lSize == 1) n = (unsigned_long_long_compat)va_arg(arg, long); 1257 else if (F.lSize == 2) n = (unsigned_long_long_compat)va_arg(arg, long_long_compat); 1258 else n = (unsigned_long_long_compat)va_arg(arg, int); 1259 #else 1260 if (F.lSize == 1) n = (unsigned long)va_arg(arg, long); 1261 else if (F.lSize == 2) goto exit; 1262 else n = (unsigned long)va_arg(arg, int); 1263 #endif 1264 if (F.hSize) n = (short) n; 1265 #if TYPE_LONGLONG_NATIVE 1266 if ((long_long_compat) n < 0) { n = (unsigned_long_long_compat)-(long_long_compat)n; F.sign = '-'; } 1267 #else 1268 if ((long) n < 0) { n = (unsigned long)-(long)n; F.sign = '-'; } 1269 #endif 1270 else if (F.forceSign) F.sign = '+'; 1271 goto number; 1272 1273 notSigned: if (F.lSize == 1) n = va_arg(arg, unsigned long); 1274 else if (F.lSize == 2) 1275 { 1276 #if TYPE_LONGLONG_NATIVE 1277 n = va_arg(arg, unsigned_long_long_compat); 1278 #else 1279 goto exit; 1280 #endif 1281 } 1282 else n = va_arg(arg, unsigned int); 1283 if (F.hSize) n = (unsigned short) n; 1284 F.sign = 0; 1285 goto number; 1286 1287 number: if (!F.havePrecision) 1288 { 1289 if (F.zeroPad) 1290 { 1291 F.precision = F.fieldWidth; 1292 if (F.altForm) F.precision -= 2; 1293 if (F.sign) --F.precision; 1294 } 1295 if (F.precision < 1) F.precision = 1; 1296 } 1297 if (F.precision > mDNS_VACB_Size - 1) 1298 F.precision = mDNS_VACB_Size - 1; 1299 for (i = 0; n; n /= base, i++) *--s = (char)(digits[n % base]); 1300 for (; i < F.precision; i++) *--s = '0'; 1301 if (F.altForm) { *--s = (char)c; *--s = '0'; i += 2; } 1302 if (F.sign) { *--s = F.sign; i++; } 1303 break; 1304 1305 case 'a': { 1306 unsigned char *a = va_arg(arg, unsigned char *); 1307 char pre[4] = ""; 1308 char post[32] = ""; 1309 if (!a) { static char emsg[] = "<<NULL>>"; s = emsg; i = sizeof(emsg)-1; } 1310 else 1311 { 1312 s = mDNS_VACB; // Adjust s to point to the start of the buffer, not the end 1313 if (F.altForm == 1) 1314 { 1315 #if (defined(MDNS_DEBUGMSGS)) 1316 mDNSAddr *ip = (mDNSAddr*)a; 1317 switch (ip->type) 1318 { 1319 case mDNSAddrType_IPv4: F.precision = 4; a = (unsigned char *)&ip->ip.v4; break; 1320 case mDNSAddrType_IPv6: F.precision = 16; a = (unsigned char *)&ip->ip.v6; break; 1321 default: F.precision = 0; break; 1322 } 1323 #else 1324 F.precision = 0; // mDNSEmbeddedAPI.h not included so no mDNSAddr support 1325 #endif 1326 } 1327 else if (F.altForm == 2) 1328 { 1329 #ifdef AF_INET 1330 const struct sockaddr *sa; 1331 unsigned char *port; 1332 sa = (const struct sockaddr*)a; 1333 switch (sa->sa_family) 1334 { 1335 case AF_INET: F.precision = 4; a = (unsigned char*)&((const struct sockaddr_in *)a)->sin_addr; 1336 port = (unsigned char*)&((const struct sockaddr_in *)sa)->sin_port; 1337 DebugSNPrintF(post, sizeof(post), ":%d", (port[0] << 8) | port[1]); break; 1338 #ifdef AF_INET6 1339 case AF_INET6: F.precision = 16; a = (unsigned char*)&((const struct sockaddr_in6 *)a)->sin6_addr; 1340 pre[0] = '['; pre[1] = '\0'; 1341 port = (unsigned char*)&((const struct sockaddr_in6 *)sa)->sin6_port; 1342 DebugSNPrintF(post, sizeof(post), "%%%d]:%d", 1343 (int)((const struct sockaddr_in6 *)sa)->sin6_scope_id, 1344 (port[0] << 8) | port[1]); break; 1345 #endif 1346 default: F.precision = 0; break; 1347 } 1348 #else 1349 F.precision = 0; // socket interfaces not included so no sockaddr support 1350 #endif 1351 } 1352 switch (F.precision) 1353 { 1354 case 4: i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), "%d.%d.%d.%d%s", 1355 a[0], a[1], a[2], a[3], post); break; 1356 case 6: i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), "%02X:%02X:%02X:%02X:%02X:%02X", 1357 a[0], a[1], a[2], a[3], a[4], a[5]); break; 1358 case 8: i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", 1359 a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]); break; 1360 case 16: i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), 1361 "%s%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X%s", 1362 pre, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], 1363 a[9], a[10], a[11], a[12], a[13], a[14], a[15], post); break; 1364 default: i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), "%s", "<< ERROR: Must specify address size " 1365 "(i.e. %.4a=IPv4, %.6a=Ethernet, %.8a=Fibre Channel %.16a=IPv6) >>"); break; 1366 } 1367 } 1368 } 1369 break; 1370 1371 case 'U': { 1372 unsigned char *a = va_arg(arg, unsigned char *); 1373 if (!a) { static char emsg[] = "<<NULL>>"; s = emsg; i = sizeof(emsg)-1; } 1374 else 1375 { 1376 s = mDNS_VACB; // Adjust s to point to the start of the buffer, not the end 1377 i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", 1378 *((uint32_t*) &a[0]), *((uint16_t*) &a[4]), *((uint16_t*) &a[6]), 1379 a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]); break; 1380 } 1381 } 1382 break; 1383 1384 case 'c': *--s = (char)va_arg(arg, int); i = 1; break; 1385 1386 case 'C': if (F.lSize) n = va_arg(arg, unsigned long); 1387 else n = va_arg(arg, unsigned int); 1388 if (F.hSize) n = (unsigned short) n; 1389 c = (int)( n & 0xFF); *--s = (char)(DebugIsPrint(c) ? c : '^'); 1390 c = (int)((n >> 8) & 0xFF); *--s = (char)(DebugIsPrint(c) ? c : '^'); 1391 c = (int)((n >> 16) & 0xFF); *--s = (char)(DebugIsPrint(c) ? c : '^'); 1392 c = (int)((n >> 24) & 0xFF); *--s = (char)(DebugIsPrint(c) ? c : '^'); 1393 i = 4; 1394 break; 1395 1396 case 's': s = va_arg(arg, char *); 1397 if (!s) { static char emsg[] = "<<NULL>>"; s = emsg; i = sizeof(emsg)-1; } 1398 else switch (F.altForm) 1399 { 1400 case 0: i=0; 1401 if (F.havePrecision) // C string 1402 { 1403 while((i < F.precision) && s[i]) i++; 1404 // Make sure we don't truncate in the middle of a UTF-8 character. 1405 // If the last character is part of a multi-byte UTF-8 character, back up to the start of it. 1406 j=0; 1407 while((i > 0) && ((c = s[i-1]) & 0x80)) { j++; i--; if((c & 0xC0) != 0x80) break;} 1408 // If the actual count of UTF-8 characters matches the encoded UTF-8 count, add it back. 1409 if((j > 1) && (j <= 6)) 1410 { 1411 int test = (0xFF << (8-j)) & 0xFF; 1412 int mask = test | (1 << ((8-j)-1)); 1413 if((c & mask) == test) i += j; 1414 } 1415 } 1416 else 1417 while(s[i]) i++; 1418 break; 1419 case 1: i = (unsigned char) *s++; break; // Pascal string 1420 case 2: { // DNS label-sequence name 1421 unsigned char *a = (unsigned char *)s; 1422 s = mDNS_VACB; // Adjust s to point to the start of the buffer, not the end 1423 if (*a == 0) *s++ = '.'; // Special case for root DNS name 1424 while (*a) 1425 { 1426 if (*a > 63) { s += DebugSNPrintF(s, mDNS_VACB_Remain(s), "<<INVALID LABEL LENGTH %u>>", *a); break; } 1427 if (s + *a >= &mDNS_VACB[254]) { s += DebugSNPrintF(s, mDNS_VACB_Remain(s), "<<NAME TOO LONG>>"); break; } 1428 s += DebugSNPrintF(s, mDNS_VACB_Remain(s), "%#s.", a); 1429 a += 1 + *a; 1430 } 1431 i = (size_t)(s - mDNS_VACB); 1432 s = mDNS_VACB; // Reset s back to the start of the buffer 1433 break; 1434 } 1435 } 1436 if (F.havePrecision && i > F.precision) // Make sure we don't truncate in the middle of a UTF-8 character 1437 { i = F.precision; while (i>0 && (s[i] & 0xC0) == 0x80) i--;} 1438 break; 1439 1440 case 'S': { // UTF-16 string 1441 unsigned char *a = va_arg(arg, unsigned char *); 1442 uint16_t *u = (uint16_t*)a; 1443 if (!u) { static char emsg[] = "<<NULL>>"; s = emsg; i = sizeof(emsg)-1; } 1444 if ((!F.havePrecision || F.precision)) 1445 { 1446 if ((a[0] == 0xFE) && (a[1] == 0xFF)) { F.altForm = 1; u += 1; a += 2; F.precision--; } // Big Endian 1447 else if ((a[0] == 0xFF) && (a[1] == 0xFE)) { F.altForm = 2; u += 1; a += 2; F.precision--; } // Little Endian 1448 } 1449 s = mDNS_VACB; // Adjust s to point to the start of the buffer, not the end 1450 switch (F.altForm) 1451 { 1452 case 0: while ((!F.havePrecision || (i < F.precision)) && u[i] && mDNS_VACB_Remain(s)) // Host Endian 1453 { c = u[i]; *s++ = (char)(DebugIsPrint(c) ? c : '^'); i++; } 1454 break; 1455 case 1: while ((!F.havePrecision || (i < F.precision)) && u[i] && mDNS_VACB_Remain(s)) // Big Endian 1456 { c = ((a[0] << 8) | a[1]) & 0xFF; *s++ = (char)(DebugIsPrint(c) ? c : '^'); i++; a += 2; } 1457 break; 1458 case 2: while ((!F.havePrecision || (i < F.precision)) && u[i] && mDNS_VACB_Remain(s)) // Little Endian 1459 { c = ((a[1] << 8) | a[0]) & 0xFF; *s++ = (char)(DebugIsPrint(c) ? c : '^'); i++; a += 2; } 1460 break; 1461 } 1462 } 1463 s = mDNS_VACB; // Reset s back to the start of the buffer 1464 break; 1465 1466 #if TARGET_OS_MAC 1467 case '@': { // Cocoa/CoreFoundation object 1468 CFTypeRef cfObj; 1469 CFStringRef cfStr; 1470 cfObj = (CFTypeRef) va_arg(arg, void *); 1471 cfStr = (CFGetTypeID(cfObj) == CFStringGetTypeID()) ? (CFStringRef)CFRetain(cfObj) : CFCopyDescription(cfObj); 1472 s = mDNS_VACB; // Adjust s to point to the start of the buffer, not the end 1473 if (cfStr) 1474 { 1475 CFRange range; 1476 CFIndex m; 1477 range = CFRangeMake(0, CFStringGetLength(cfStr)); 1478 m = 0; 1479 CFStringGetBytes(cfStr, range, kCFStringEncodingUTF8, '^', false, (UInt8*)mDNS_VACB, (CFIndex)sizeof(mDNS_VACB), &m); 1480 CFRelease(cfStr); 1481 i = (size_t) m; 1482 } 1483 else 1484 { 1485 i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), "%s", "ERROR: <invalid CF object>" ); 1486 } 1487 } 1488 if (F.havePrecision && i > F.precision) // Make sure we don't truncate in the middle of a UTF-8 character 1489 { i = F.precision; while (i>0 && (s[i] & 0xC0) == 0x80) i--;} 1490 break; 1491 #endif 1492 1493 case 'm': { // Error Message 1494 long err; 1495 if (F.lSize) err = va_arg(arg, long); 1496 else err = va_arg(arg, int); 1497 if (F.hSize) err = (short)err; 1498 DebugGetErrorString(err, mDNS_VACB, sizeof(mDNS_VACB)); 1499 s = mDNS_VACB; // Adjust s to point to the start of the buffer, not the end 1500 for(i=0; s[i]; i++) {} 1501 } 1502 break; 1503 1504 case 'H': { // Hex Dump 1505 void *a = va_arg(arg, void *); 1506 size_t size = (size_t)va_arg(arg, int); 1507 size_t max = (size_t)va_arg(arg, int); 1508 DebugFlags flags = 1509 kDebugFlagsNoAddress | kDebugFlagsNoOffset | kDebugFlagsNoNewLine | 1510 kDebugFlags8BitSeparator | kDebugFlagsNo32BitSeparator | 1511 kDebugFlagsNo16ByteHexPad | kDebugFlagsNoByteCount; 1512 if (F.altForm == 0) flags |= kDebugFlagsNoASCII; 1513 size = (max < size) ? max : size; 1514 s = mDNS_VACB; // Adjust s to point to the start of the buffer, not the end 1515 i = DebugHexDump(kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, a, a, size, flags, mDNS_VACB, sizeof(mDNS_VACB)); 1516 } 1517 break; 1518 1519 case 'v': { // Version 1520 uint32_t version; 1521 version = va_arg(arg, unsigned int); 1522 DebugNumVersionToString(version, mDNS_VACB); 1523 s = mDNS_VACB; // Adjust s to point to the start of the buffer, not the end 1524 for(i=0; s[i]; i++) {} 1525 } 1526 break; 1527 1528 case 'n': s = va_arg(arg, char *); 1529 if (F.hSize) *(short *) s = (short)nwritten; 1530 else if (F.lSize) *(long *) s = (long)nwritten; 1531 else *(int *) s = (int)nwritten; 1532 continue; 1533 1534 default: s = mDNS_VACB; 1535 i = DebugSNPrintF(mDNS_VACB, sizeof(mDNS_VACB), "<<UNKNOWN FORMAT CONVERSION CODE %%%c>>", c); 1536 1537 case '%': *sbuffer++ = (char)c; 1538 if (++nwritten >= buflen) goto exit; 1539 break; 1540 } 1541 1542 if (i < F.fieldWidth && !F.leftJustify) // Pad on the left 1543 do { 1544 *sbuffer++ = ' '; 1545 if (++nwritten >= buflen) goto exit; 1546 } while (i < --F.fieldWidth); 1547 1548 if (i > buflen - nwritten) // Make sure we don't truncate in the middle of a UTF-8 character 1549 { i = buflen - nwritten; while (i>0 && (s[i] & 0xC0) == 0x80) i--;} 1550 for (j=0; j<i; j++) *sbuffer++ = *s++; // Write the converted result 1551 nwritten += i; 1552 if (nwritten >= buflen) goto exit; 1553 1554 for (; i < F.fieldWidth; i++) // Pad on the right 1555 { 1556 *sbuffer++ = ' '; 1557 if (++nwritten >= buflen) goto exit; 1558 } 1559 } 1560 } 1561 exit: 1562 *sbuffer++ = 0; 1563 return(nwritten); 1564 } 1565 1566 //=========================================================================================================================== 1567 // DebugGetErrorString 1568 //=========================================================================================================================== 1569 1570 DEBUG_EXPORT const char * DebugGetErrorString( long inErrorCode, char *inBuffer, size_t inBufferSize ) 1571 { 1572 const char * s; 1573 char * dst; 1574 char * end; 1575 #if ( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE ) 1576 char buffer[ 256 ]; 1577 #endif 1578 1579 switch( inErrorCode ) 1580 { 1581 #define CaseErrorString( X, STR ) case X: s = STR; break 1582 #define CaseErrorStringify( X ) case X: s = # X; break 1583 #define CaseErrorStringifyHardCode( VALUE, X ) case VALUE: s = # X; break 1584 1585 // General Errors 1586 1587 CaseErrorString( 0, "no error" ); 1588 CaseErrorString( 1, "in-progress/waiting" ); 1589 CaseErrorString( -1, "catch-all unknown error" ); 1590 1591 // ACP Errors 1592 1593 CaseErrorStringifyHardCode( -2, kACPBadRequestErr ); 1594 CaseErrorStringifyHardCode( -3, kACPNoMemoryErr ); 1595 CaseErrorStringifyHardCode( -4, kACPBadParamErr ); 1596 CaseErrorStringifyHardCode( -5, kACPNotFoundErr ); 1597 CaseErrorStringifyHardCode( -6, kACPBadChecksumErr ); 1598 CaseErrorStringifyHardCode( -7, kACPCommandNotHandledErr ); 1599 CaseErrorStringifyHardCode( -8, kACPNetworkErr ); 1600 CaseErrorStringifyHardCode( -9, kACPDuplicateCommandHandlerErr ); 1601 CaseErrorStringifyHardCode( -10, kACPUnknownPropertyErr ); 1602 CaseErrorStringifyHardCode( -11, kACPImmutablePropertyErr ); 1603 CaseErrorStringifyHardCode( -12, kACPBadPropertyValueErr ); 1604 CaseErrorStringifyHardCode( -13, kACPNoResourcesErr ); 1605 CaseErrorStringifyHardCode( -14, kACPBadOptionErr ); 1606 CaseErrorStringifyHardCode( -15, kACPBadSizeErr ); 1607 CaseErrorStringifyHardCode( -16, kACPBadPasswordErr ); 1608 CaseErrorStringifyHardCode( -17, kACPNotInitializedErr ); 1609 CaseErrorStringifyHardCode( -18, kACPNonReadablePropertyErr ); 1610 CaseErrorStringifyHardCode( -19, kACPBadVersionErr ); 1611 CaseErrorStringifyHardCode( -20, kACPBadSignatureErr ); 1612 CaseErrorStringifyHardCode( -21, kACPBadIndexErr ); 1613 CaseErrorStringifyHardCode( -22, kACPUnsupportedErr ); 1614 CaseErrorStringifyHardCode( -23, kACPInUseErr ); 1615 CaseErrorStringifyHardCode( -24, kACPParamCountErr ); 1616 CaseErrorStringifyHardCode( -25, kACPIDErr ); 1617 CaseErrorStringifyHardCode( -26, kACPFormatErr ); 1618 CaseErrorStringifyHardCode( -27, kACPUnknownUserErr ); 1619 CaseErrorStringifyHardCode( -28, kACPAccessDeniedErr ); 1620 CaseErrorStringifyHardCode( -29, kACPIncorrectFWErr ); 1621 1622 // Common Services Errors 1623 1624 CaseErrorStringify( kUnknownErr ); 1625 CaseErrorStringify( kOptionErr ); 1626 CaseErrorStringify( kSelectorErr ); 1627 CaseErrorStringify( kExecutionStateErr ); 1628 CaseErrorStringify( kPathErr ); 1629 CaseErrorStringify( kParamErr ); 1630 CaseErrorStringify( kParamCountErr ); 1631 CaseErrorStringify( kCommandErr ); 1632 CaseErrorStringify( kIDErr ); 1633 CaseErrorStringify( kStateErr ); 1634 CaseErrorStringify( kRangeErr ); 1635 CaseErrorStringify( kRequestErr ); 1636 CaseErrorStringify( kResponseErr ); 1637 CaseErrorStringify( kChecksumErr ); 1638 CaseErrorStringify( kNotHandledErr ); 1639 CaseErrorStringify( kVersionErr ); 1640 CaseErrorStringify( kSignatureErr ); 1641 CaseErrorStringify( kFormatErr ); 1642 CaseErrorStringify( kNotInitializedErr ); 1643 CaseErrorStringify( kAlreadyInitializedErr ); 1644 CaseErrorStringify( kNotInUseErr ); 1645 CaseErrorStringify( kInUseErr ); 1646 CaseErrorStringify( kTimeoutErr ); 1647 CaseErrorStringify( kCanceledErr ); 1648 CaseErrorStringify( kAlreadyCanceledErr ); 1649 CaseErrorStringify( kCannotCancelErr ); 1650 CaseErrorStringify( kDeletedErr ); 1651 CaseErrorStringify( kNotFoundErr ); 1652 CaseErrorStringify( kNoMemoryErr ); 1653 CaseErrorStringify( kNoResourcesErr ); 1654 CaseErrorStringify( kDuplicateErr ); 1655 CaseErrorStringify( kImmutableErr ); 1656 CaseErrorStringify( kUnsupportedDataErr ); 1657 CaseErrorStringify( kIntegrityErr ); 1658 CaseErrorStringify( kIncompatibleErr ); 1659 CaseErrorStringify( kUnsupportedErr ); 1660 CaseErrorStringify( kUnexpectedErr ); 1661 CaseErrorStringify( kValueErr ); 1662 CaseErrorStringify( kNotReadableErr ); 1663 CaseErrorStringify( kNotWritableErr ); 1664 CaseErrorStringify( kBadReferenceErr ); 1665 CaseErrorStringify( kFlagErr ); 1666 CaseErrorStringify( kMalformedErr ); 1667 CaseErrorStringify( kSizeErr ); 1668 CaseErrorStringify( kNameErr ); 1669 CaseErrorStringify( kNotReadyErr ); 1670 CaseErrorStringify( kReadErr ); 1671 CaseErrorStringify( kWriteErr ); 1672 CaseErrorStringify( kMismatchErr ); 1673 CaseErrorStringify( kDateErr ); 1674 CaseErrorStringify( kUnderrunErr ); 1675 CaseErrorStringify( kOverrunErr ); 1676 CaseErrorStringify( kEndingErr ); 1677 CaseErrorStringify( kConnectionErr ); 1678 CaseErrorStringify( kAuthenticationErr ); 1679 CaseErrorStringify( kOpenErr ); 1680 CaseErrorStringify( kTypeErr ); 1681 CaseErrorStringify( kSkipErr ); 1682 CaseErrorStringify( kNoAckErr ); 1683 CaseErrorStringify( kCollisionErr ); 1684 CaseErrorStringify( kBackoffErr ); 1685 CaseErrorStringify( kNoAddressAckErr ); 1686 CaseErrorStringify( kBusyErr ); 1687 CaseErrorStringify( kNoSpaceErr ); 1688 1689 // mDNS/DNS-SD Errors 1690 1691 CaseErrorStringifyHardCode( -65537, mStatus_UnknownErr ); 1692 CaseErrorStringifyHardCode( -65538, mStatus_NoSuchNameErr ); 1693 CaseErrorStringifyHardCode( -65539, mStatus_NoMemoryErr ); 1694 CaseErrorStringifyHardCode( -65540, mStatus_BadParamErr ); 1695 CaseErrorStringifyHardCode( -65541, mStatus_BadReferenceErr ); 1696 CaseErrorStringifyHardCode( -65542, mStatus_BadStateErr ); 1697 CaseErrorStringifyHardCode( -65543, mStatus_BadFlagsErr ); 1698 CaseErrorStringifyHardCode( -65544, mStatus_UnsupportedErr ); 1699 CaseErrorStringifyHardCode( -65545, mStatus_NotInitializedErr ); 1700 CaseErrorStringifyHardCode( -65546, mStatus_NoCache ); 1701 CaseErrorStringifyHardCode( -65547, mStatus_AlreadyRegistered ); 1702 CaseErrorStringifyHardCode( -65548, mStatus_NameConflict ); 1703 CaseErrorStringifyHardCode( -65549, mStatus_Invalid ); 1704 CaseErrorStringifyHardCode( -65550, mStatus_GrowCache ); 1705 CaseErrorStringifyHardCode( -65551, mStatus_Incompatible ); 1706 CaseErrorStringifyHardCode( -65552, mStatus_BadInterfaceErr ); 1707 CaseErrorStringifyHardCode( -65791, mStatus_ConfigChanged ); 1708 CaseErrorStringifyHardCode( -65792, mStatus_MemFree ); 1709 1710 // RSP Errors 1711 1712 CaseErrorStringifyHardCode( -400000, kRSPUnknownErr ); 1713 CaseErrorStringifyHardCode( -400050, kRSPParamErr ); 1714 CaseErrorStringifyHardCode( -400108, kRSPNoMemoryErr ); 1715 CaseErrorStringifyHardCode( -405246, kRSPRangeErr ); 1716 CaseErrorStringifyHardCode( -409057, kRSPSizeErr ); 1717 CaseErrorStringifyHardCode( -400200, kRSPHardwareErr ); 1718 CaseErrorStringifyHardCode( -401712, kRSPTimeoutErr ); 1719 CaseErrorStringifyHardCode( -402053, kRSPUnsupportedErr ); 1720 CaseErrorStringifyHardCode( -402419, kRSPIDErr ); 1721 CaseErrorStringifyHardCode( -403165, kRSPFlagErr ); 1722 CaseErrorString( -200000, "kRSPControllerStatusBase - 0x50" ); 1723 CaseErrorString( -200080, "kRSPCommandSucceededErr - 0x50" ); 1724 CaseErrorString( -200001, "kRSPCommandFailedErr - 0x01" ); 1725 CaseErrorString( -200051, "kRSPChecksumErr - 0x33" ); 1726 CaseErrorString( -200132, "kRSPCommandTimeoutErr - 0x84" ); 1727 CaseErrorString( -200034, "kRSPPasswordRequiredErr - 0x22 OBSOLETE" ); 1728 CaseErrorString( -200128, "kRSPCanceledErr - 0x02 Async" ); 1729 1730 // XML Errors 1731 1732 CaseErrorStringifyHardCode( -100043, kXMLNotFoundErr ); 1733 CaseErrorStringifyHardCode( -100050, kXMLParamErr ); 1734 CaseErrorStringifyHardCode( -100108, kXMLNoMemoryErr ); 1735 CaseErrorStringifyHardCode( -100206, kXMLFormatErr ); 1736 CaseErrorStringifyHardCode( -100586, kXMLNoRootElementErr ); 1737 CaseErrorStringifyHardCode( -101703, kXMLWrongDataTypeErr ); 1738 CaseErrorStringifyHardCode( -101726, kXMLKeyErr ); 1739 CaseErrorStringifyHardCode( -102053, kXMLUnsupportedErr ); 1740 CaseErrorStringifyHardCode( -102063, kXMLMissingElementErr ); 1741 CaseErrorStringifyHardCode( -103026, kXMLParseErr ); 1742 CaseErrorStringifyHardCode( -103159, kXMLBadDataErr ); 1743 CaseErrorStringifyHardCode( -103170, kXMLBadNameErr ); 1744 CaseErrorStringifyHardCode( -105246, kXMLRangeErr ); 1745 CaseErrorStringifyHardCode( -105251, kXMLUnknownElementErr ); 1746 CaseErrorStringifyHardCode( -108739, kXMLMalformedInputErr ); 1747 CaseErrorStringifyHardCode( -109057, kXMLBadSizeErr ); 1748 CaseErrorStringifyHardCode( -101730, kXMLMissingChildElementErr ); 1749 CaseErrorStringifyHardCode( -102107, kXMLMissingParentElementErr ); 1750 CaseErrorStringifyHardCode( -130587, kXMLNonRootElementErr ); 1751 CaseErrorStringifyHardCode( -102015, kXMLDateErr ); 1752 1753 #if ( __MACH__ ) 1754 1755 // Mach Errors 1756 1757 CaseErrorStringifyHardCode( 0x00002000, MACH_MSG_IPC_SPACE ); 1758 CaseErrorStringifyHardCode( 0x00001000, MACH_MSG_VM_SPACE ); 1759 CaseErrorStringifyHardCode( 0x00000800, MACH_MSG_IPC_KERNEL ); 1760 CaseErrorStringifyHardCode( 0x00000400, MACH_MSG_VM_KERNEL ); 1761 CaseErrorStringifyHardCode( 0x10000001, MACH_SEND_IN_PROGRESS ); 1762 CaseErrorStringifyHardCode( 0x10000002, MACH_SEND_INVALID_DATA ); 1763 CaseErrorStringifyHardCode( 0x10000003, MACH_SEND_INVALID_DEST ); 1764 CaseErrorStringifyHardCode( 0x10000004, MACH_SEND_TIMED_OUT ); 1765 CaseErrorStringifyHardCode( 0x10000007, MACH_SEND_INTERRUPTED ); 1766 CaseErrorStringifyHardCode( 0x10000008, MACH_SEND_MSG_TOO_SMALL ); 1767 CaseErrorStringifyHardCode( 0x10000009, MACH_SEND_INVALID_REPLY ); 1768 CaseErrorStringifyHardCode( 0x1000000A, MACH_SEND_INVALID_RIGHT ); 1769 CaseErrorStringifyHardCode( 0x1000000B, MACH_SEND_INVALID_NOTIFY ); 1770 CaseErrorStringifyHardCode( 0x1000000C, MACH_SEND_INVALID_MEMORY ); 1771 CaseErrorStringifyHardCode( 0x1000000D, MACH_SEND_NO_BUFFER ); 1772 CaseErrorStringifyHardCode( 0x1000000E, MACH_SEND_TOO_LARGE ); 1773 CaseErrorStringifyHardCode( 0x1000000F, MACH_SEND_INVALID_TYPE ); 1774 CaseErrorStringifyHardCode( 0x10000010, MACH_SEND_INVALID_HEADER ); 1775 CaseErrorStringifyHardCode( 0x10000011, MACH_SEND_INVALID_TRAILER ); 1776 CaseErrorStringifyHardCode( 0x10000015, MACH_SEND_INVALID_RT_OOL_SIZE ); 1777 CaseErrorStringifyHardCode( 0x10004001, MACH_RCV_IN_PROGRESS ); 1778 CaseErrorStringifyHardCode( 0x10004002, MACH_RCV_INVALID_NAME ); 1779 CaseErrorStringifyHardCode( 0x10004003, MACH_RCV_TIMED_OUT ); 1780 CaseErrorStringifyHardCode( 0x10004004, MACH_RCV_TOO_LARGE ); 1781 CaseErrorStringifyHardCode( 0x10004005, MACH_RCV_INTERRUPTED ); 1782 CaseErrorStringifyHardCode( 0x10004006, MACH_RCV_PORT_CHANGED ); 1783 CaseErrorStringifyHardCode( 0x10004007, MACH_RCV_INVALID_NOTIFY ); 1784 CaseErrorStringifyHardCode( 0x10004008, MACH_RCV_INVALID_DATA ); 1785 CaseErrorStringifyHardCode( 0x10004009, MACH_RCV_PORT_DIED ); 1786 CaseErrorStringifyHardCode( 0x1000400A, MACH_RCV_IN_SET ); 1787 CaseErrorStringifyHardCode( 0x1000400B, MACH_RCV_HEADER_ERROR ); 1788 CaseErrorStringifyHardCode( 0x1000400C, MACH_RCV_BODY_ERROR ); 1789 CaseErrorStringifyHardCode( 0x1000400D, MACH_RCV_INVALID_TYPE ); 1790 CaseErrorStringifyHardCode( 0x1000400E, MACH_RCV_SCATTER_SMALL ); 1791 CaseErrorStringifyHardCode( 0x1000400F, MACH_RCV_INVALID_TRAILER ); 1792 CaseErrorStringifyHardCode( 0x10004011, MACH_RCV_IN_PROGRESS_TIMED ); 1793 1794 // Mach OSReturn Errors 1795 1796 CaseErrorStringifyHardCode( 0xDC000001, kOSReturnError ); 1797 CaseErrorStringifyHardCode( 0xDC004001, kOSMetaClassInternal ); 1798 CaseErrorStringifyHardCode( 0xDC004002, kOSMetaClassHasInstances ); 1799 CaseErrorStringifyHardCode( 0xDC004003, kOSMetaClassNoInit ); 1800 CaseErrorStringifyHardCode( 0xDC004004, kOSMetaClassNoTempData ); 1801 CaseErrorStringifyHardCode( 0xDC004005, kOSMetaClassNoDicts ); 1802 CaseErrorStringifyHardCode( 0xDC004006, kOSMetaClassNoKModSet ); 1803 CaseErrorStringifyHardCode( 0xDC004007, kOSMetaClassNoInsKModSet ); 1804 CaseErrorStringifyHardCode( 0xDC004008, kOSMetaClassNoSuper ); 1805 CaseErrorStringifyHardCode( 0xDC004009, kOSMetaClassInstNoSuper ); 1806 CaseErrorStringifyHardCode( 0xDC00400A, kOSMetaClassDuplicateClass ); 1807 1808 // IOKit Errors 1809 1810 CaseErrorStringifyHardCode( 0xE00002BC, kIOReturnError ); 1811 CaseErrorStringifyHardCode( 0xE00002BD, kIOReturnNoMemory ); 1812 CaseErrorStringifyHardCode( 0xE00002BE, kIOReturnNoResources ); 1813 CaseErrorStringifyHardCode( 0xE00002BF, kIOReturnIPCError ); 1814 CaseErrorStringifyHardCode( 0xE00002C0, kIOReturnNoDevice ); 1815 CaseErrorStringifyHardCode( 0xE00002C1, kIOReturnNotPrivileged ); 1816 CaseErrorStringifyHardCode( 0xE00002C2, kIOReturnBadArgument ); 1817 CaseErrorStringifyHardCode( 0xE00002C3, kIOReturnLockedRead ); 1818 CaseErrorStringifyHardCode( 0xE00002C4, kIOReturnLockedWrite ); 1819 CaseErrorStringifyHardCode( 0xE00002C5, kIOReturnExclusiveAccess ); 1820 CaseErrorStringifyHardCode( 0xE00002C6, kIOReturnBadMessageID ); 1821 CaseErrorStringifyHardCode( 0xE00002C7, kIOReturnUnsupported ); 1822 CaseErrorStringifyHardCode( 0xE00002C8, kIOReturnVMError ); 1823 CaseErrorStringifyHardCode( 0xE00002C9, kIOReturnInternalError ); 1824 CaseErrorStringifyHardCode( 0xE00002CA, kIOReturnIOError ); 1825 CaseErrorStringifyHardCode( 0xE00002CC, kIOReturnCannotLock ); 1826 CaseErrorStringifyHardCode( 0xE00002CD, kIOReturnNotOpen ); 1827 CaseErrorStringifyHardCode( 0xE00002CE, kIOReturnNotReadable ); 1828 CaseErrorStringifyHardCode( 0xE00002CF, kIOReturnNotWritable ); 1829 CaseErrorStringifyHardCode( 0xE00002D0, kIOReturnNotAligned ); 1830 CaseErrorStringifyHardCode( 0xE00002D1, kIOReturnBadMedia ); 1831 CaseErrorStringifyHardCode( 0xE00002D2, kIOReturnStillOpen ); 1832 CaseErrorStringifyHardCode( 0xE00002D3, kIOReturnRLDError ); 1833 CaseErrorStringifyHardCode( 0xE00002D4, kIOReturnDMAError ); 1834 CaseErrorStringifyHardCode( 0xE00002D5, kIOReturnBusy ); 1835 CaseErrorStringifyHardCode( 0xE00002D6, kIOReturnTimeout ); 1836 CaseErrorStringifyHardCode( 0xE00002D7, kIOReturnOffline ); 1837 CaseErrorStringifyHardCode( 0xE00002D8, kIOReturnNotReady ); 1838 CaseErrorStringifyHardCode( 0xE00002D9, kIOReturnNotAttached ); 1839 CaseErrorStringifyHardCode( 0xE00002DA, kIOReturnNoChannels ); 1840 CaseErrorStringifyHardCode( 0xE00002DB, kIOReturnNoSpace ); 1841 CaseErrorStringifyHardCode( 0xE00002DD, kIOReturnPortExists ); 1842 CaseErrorStringifyHardCode( 0xE00002DE, kIOReturnCannotWire ); 1843 CaseErrorStringifyHardCode( 0xE00002DF, kIOReturnNoInterrupt ); 1844 CaseErrorStringifyHardCode( 0xE00002E0, kIOReturnNoFrames ); 1845 CaseErrorStringifyHardCode( 0xE00002E1, kIOReturnMessageTooLarge ); 1846 CaseErrorStringifyHardCode( 0xE00002E2, kIOReturnNotPermitted ); 1847 CaseErrorStringifyHardCode( 0xE00002E3, kIOReturnNoPower ); 1848 CaseErrorStringifyHardCode( 0xE00002E4, kIOReturnNoMedia ); 1849 CaseErrorStringifyHardCode( 0xE00002E5, kIOReturnUnformattedMedia ); 1850 CaseErrorStringifyHardCode( 0xE00002E6, kIOReturnUnsupportedMode ); 1851 CaseErrorStringifyHardCode( 0xE00002E7, kIOReturnUnderrun ); 1852 CaseErrorStringifyHardCode( 0xE00002E8, kIOReturnOverrun ); 1853 CaseErrorStringifyHardCode( 0xE00002E9, kIOReturnDeviceError ); 1854 CaseErrorStringifyHardCode( 0xE00002EA, kIOReturnNoCompletion ); 1855 CaseErrorStringifyHardCode( 0xE00002EB, kIOReturnAborted ); 1856 CaseErrorStringifyHardCode( 0xE00002EC, kIOReturnNoBandwidth ); 1857 CaseErrorStringifyHardCode( 0xE00002ED, kIOReturnNotResponding ); 1858 CaseErrorStringifyHardCode( 0xE00002EE, kIOReturnIsoTooOld ); 1859 CaseErrorStringifyHardCode( 0xE00002EF, kIOReturnIsoTooNew ); 1860 CaseErrorStringifyHardCode( 0xE00002F0, kIOReturnNotFound ); 1861 CaseErrorStringifyHardCode( 0xE0000001, kIOReturnInvalid ); 1862 1863 // IOKit FireWire Errors 1864 1865 CaseErrorStringifyHardCode( 0xE0008010, kIOFireWireResponseBase ); 1866 CaseErrorStringifyHardCode( 0xE0008020, kIOFireWireBusReset ); 1867 CaseErrorStringifyHardCode( 0xE0008001, kIOConfigNoEntry ); 1868 CaseErrorStringifyHardCode( 0xE0008002, kIOFireWirePending ); 1869 CaseErrorStringifyHardCode( 0xE0008003, kIOFireWireLastDCLToken ); 1870 CaseErrorStringifyHardCode( 0xE0008004, kIOFireWireConfigROMInvalid ); 1871 CaseErrorStringifyHardCode( 0xE0008005, kIOFireWireAlreadyRegistered ); 1872 CaseErrorStringifyHardCode( 0xE0008006, kIOFireWireMultipleTalkers ); 1873 CaseErrorStringifyHardCode( 0xE0008007, kIOFireWireChannelActive ); 1874 CaseErrorStringifyHardCode( 0xE0008008, kIOFireWireNoListenerOrTalker ); 1875 CaseErrorStringifyHardCode( 0xE0008009, kIOFireWireNoChannels ); 1876 CaseErrorStringifyHardCode( 0xE000800A, kIOFireWireChannelNotAvailable ); 1877 CaseErrorStringifyHardCode( 0xE000800B, kIOFireWireSeparateBus ); 1878 CaseErrorStringifyHardCode( 0xE000800C, kIOFireWireBadSelfIDs ); 1879 CaseErrorStringifyHardCode( 0xE000800D, kIOFireWireLowCableVoltage ); 1880 CaseErrorStringifyHardCode( 0xE000800E, kIOFireWireInsufficientPower ); 1881 CaseErrorStringifyHardCode( 0xE000800F, kIOFireWireOutOfTLabels ); 1882 CaseErrorStringifyHardCode( 0xE0008101, kIOFireWireBogusDCLProgram ); 1883 CaseErrorStringifyHardCode( 0xE0008102, kIOFireWireTalkingAndListening ); 1884 CaseErrorStringifyHardCode( 0xE0008103, kIOFireWireHardwareSlept ); 1885 CaseErrorStringifyHardCode( 0xE00087D0, kIOFWMessageServiceIsRequestingClose ); 1886 CaseErrorStringifyHardCode( 0xE00087D1, kIOFWMessagePowerStateChanged ); 1887 CaseErrorStringifyHardCode( 0xE00087D2, kIOFWMessageTopologyChanged ); 1888 1889 // IOKit USB Errors 1890 1891 CaseErrorStringifyHardCode( 0xE0004061, kIOUSBUnknownPipeErr ); 1892 CaseErrorStringifyHardCode( 0xE0004060, kIOUSBTooManyPipesErr ); 1893 CaseErrorStringifyHardCode( 0xE000405F, kIOUSBNoAsyncPortErr ); 1894 CaseErrorStringifyHardCode( 0xE000405E, kIOUSBNotEnoughPipesErr ); 1895 CaseErrorStringifyHardCode( 0xE000405D, kIOUSBNotEnoughPowerErr ); 1896 CaseErrorStringifyHardCode( 0xE0004057, kIOUSBEndpointNotFound ); 1897 CaseErrorStringifyHardCode( 0xE0004056, kIOUSBConfigNotFound ); 1898 CaseErrorStringifyHardCode( 0xE0004051, kIOUSBTransactionTimeout ); 1899 CaseErrorStringifyHardCode( 0xE0004050, kIOUSBTransactionReturned ); 1900 CaseErrorStringifyHardCode( 0xE000404F, kIOUSBPipeStalled ); 1901 CaseErrorStringifyHardCode( 0xE000404E, kIOUSBInterfaceNotFound ); 1902 CaseErrorStringifyHardCode( 0xE000404D, kIOUSBLowLatencyBufferNotPreviouslyAllocated ); 1903 CaseErrorStringifyHardCode( 0xE000404C, kIOUSBLowLatencyFrameListNotPreviouslyAllocated ); 1904 CaseErrorStringifyHardCode( 0xE000404B, kIOUSBHighSpeedSplitError ); 1905 CaseErrorStringifyHardCode( 0xE0004010, kIOUSBLinkErr ); 1906 CaseErrorStringifyHardCode( 0xE000400F, kIOUSBNotSent2Err ); 1907 CaseErrorStringifyHardCode( 0xE000400E, kIOUSBNotSent1Err ); 1908 CaseErrorStringifyHardCode( 0xE000400D, kIOUSBBufferUnderrunErr ); 1909 CaseErrorStringifyHardCode( 0xE000400C, kIOUSBBufferOverrunErr ); 1910 CaseErrorStringifyHardCode( 0xE000400B, kIOUSBReserved2Err ); 1911 CaseErrorStringifyHardCode( 0xE000400A, kIOUSBReserved1Err ); 1912 CaseErrorStringifyHardCode( 0xE0004007, kIOUSBWrongPIDErr ); 1913 CaseErrorStringifyHardCode( 0xE0004006, kIOUSBPIDCheckErr ); 1914 CaseErrorStringifyHardCode( 0xE0004003, kIOUSBDataToggleErr ); 1915 CaseErrorStringifyHardCode( 0xE0004002, kIOUSBBitstufErr ); 1916 CaseErrorStringifyHardCode( 0xE0004001, kIOUSBCRCErr ); 1917 1918 #endif // __MACH__ 1919 1920 // Other Errors 1921 1922 default: 1923 s = NULL; 1924 #if ( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE ) 1925 if( inBuffer && ( inBufferSize > 0 ) ) 1926 { 1927 DWORD n; 1928 1929 n = FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, (DWORD) inErrorCode, 1930 MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), buffer, sizeof( buffer ), NULL ); 1931 if( n > 0 ) 1932 { 1933 // Remove any trailing CR's or LF's since some messages have them. 1934 1935 while( ( n > 0 ) && isspace( ( (unsigned char *) buffer )[ n - 1 ] ) ) 1936 { 1937 buffer[ --n ] = '\0'; 1938 } 1939 s = buffer; 1940 } 1941 } 1942 #endif 1943 1944 if( !s ) 1945 { 1946 #if ( !TARGET_API_MAC_OSX_KERNEL && !TARGET_OS_WINDOWS_CE ) 1947 if( ( inErrorCode >= INT_MIN ) && ( inErrorCode <= INT_MAX ) ) 1948 { 1949 s = strerror( (int) inErrorCode ); 1950 } 1951 #endif 1952 if( !s ) 1953 { 1954 s = "<unknown error code>"; 1955 } 1956 } 1957 break; 1958 } 1959 1960 // Copy the string to the output buffer. If no buffer is supplied or it is empty, return an empty string. 1961 1962 if( inBuffer && ( inBufferSize > 0 ) ) 1963 { 1964 dst = inBuffer; 1965 end = dst + ( inBufferSize - 1 ); 1966 while( ( ( end - dst ) > 0 ) && ( *s != '\0' ) ) 1967 { 1968 *dst++ = *s++; 1969 } 1970 *dst = '\0'; 1971 s = inBuffer; 1972 } 1973 return( s ); 1974 } 1975 1976 //=========================================================================================================================== 1977 // DebugHexDump 1978 //=========================================================================================================================== 1979 1980 DEBUG_EXPORT size_t 1981 DebugHexDump( 1982 DebugLevel inLevel, 1983 int inIndent, 1984 const char * inLabel, 1985 size_t inLabelSize, 1986 int inLabelMinWidth, 1987 const char * inType, 1988 size_t inTypeSize, 1989 const void * inDataStart, 1990 const void * inData, 1991 size_t inDataSize, 1992 DebugFlags inFlags, 1993 char * outBuffer, 1994 size_t inBufferSize ) 1995 { 1996 static const char kHexChars[] = "0123456789ABCDEF"; 1997 const uint8_t * start; 1998 const uint8_t * src; 1999 char * dst; 2000 char * end; 2001 size_t n; 2002 int offset; 2003 int width; 2004 const char * newline; 2005 char separator[ 8 ]; 2006 char * s; 2007 2008 DEBUG_UNUSED( inType ); 2009 DEBUG_UNUSED( inTypeSize ); 2010 2011 // Set up the function-wide variables. 2012 2013 if( inLabelSize == kSizeCString ) 2014 { 2015 inLabelSize = strlen( inLabel ); 2016 } 2017 start = (const uint8_t *) inData; 2018 src = start; 2019 dst = outBuffer; 2020 end = dst + inBufferSize; 2021 offset = (int)( (intptr_t) inData - (intptr_t) inDataStart ); 2022 width = ( (int) inLabelSize > inLabelMinWidth ) ? (int) inLabelSize : inLabelMinWidth; 2023 newline = ( inFlags & kDebugFlagsNoNewLine ) ? "" : "\n"; 2024 2025 // Set up the separator string. This is used to insert spaces on subsequent "lines" when not using newlines. 2026 2027 s = separator; 2028 if( inFlags & kDebugFlagsNoNewLine ) 2029 { 2030 if( inFlags & kDebugFlags8BitSeparator ) 2031 { 2032 *s++ = ' '; 2033 } 2034 if( inFlags & kDebugFlags16BitSeparator ) 2035 { 2036 *s++ = ' '; 2037 } 2038 if( !( inFlags & kDebugFlagsNo32BitSeparator ) ) 2039 { 2040 *s++ = ' '; 2041 } 2042 check( ( (size_t)( s - separator ) ) < sizeof( separator ) ); 2043 } 2044 *s = '\0'; 2045 2046 for( ;; ) 2047 { 2048 char prefixString[ 32 ]; 2049 char hexString[ 64 ]; 2050 char asciiString[ 32 ]; 2051 char byteCountString[ 32 ]; 2052 int c; 2053 size_t chunkSize; 2054 size_t i; 2055 2056 // If this is a label-only item (i.e. no data), print the label (accounting for prefix string spacing) and exit. 2057 2058 if( inDataSize == 0 ) 2059 { 2060 if( inLabel && ( inLabelSize > 0 ) ) 2061 { 2062 width = 0; 2063 if( !( inFlags & kDebugFlagsNoAddress ) ) 2064 { 2065 width += 8; // "00000000" 2066 if( !( inFlags & kDebugFlagsNoOffset ) ) 2067 { 2068 width += 1; // "+" 2069 } 2070 } 2071 if( inFlags & kDebugFlags32BitOffset ) 2072 { 2073 width += 8; // "00000000" 2074 } 2075 else if( !( inFlags & kDebugFlagsNoOffset ) ) 2076 { 2077 width += 4; // "0000" 2078 } 2079 2080 if( outBuffer ) 2081 { 2082 dst += DebugSNPrintF( dst, (size_t)( end - dst ), "%*s" "%-*.*s" "%.*s" "%s", 2083 width, "", 2084 ( width > 0 ) ? ": " : "", 2085 width, (int) inLabelSize, inLabel, 2086 newline ); 2087 } 2088 else 2089 { 2090 dst += DebugPrintF( inLevel, "%*s" "%-*.*s" "%.*s" "%s", 2091 width, "", 2092 ( width > 0 ) ? ": " : "", 2093 width, (int) inLabelSize, inLabel, 2094 newline ); 2095 } 2096 } 2097 break; 2098 } 2099 2100 // Build the prefix string. It will be in one of the following formats: 2101 // 2102 // 1) "00000000+0000[0000]" (address and offset) 2103 // 2) "00000000" (address only) 2104 // 3) "0000[0000]" (offset only) 2105 // 4) "" (no address or offset) 2106 // 2107 // Note: If we're printing multiple "lines", but not printing newlines, a space is used to separate. 2108 2109 s = prefixString; 2110 if( !( inFlags & kDebugFlagsNoAddress ) ) 2111 { 2112 *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 28 ) & 0xF ]; 2113 *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 24 ) & 0xF ]; 2114 *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 20 ) & 0xF ]; 2115 *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 16 ) & 0xF ]; 2116 *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 12 ) & 0xF ]; 2117 *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 8 ) & 0xF ]; 2118 *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 4 ) & 0xF ]; 2119 *s++ = kHexChars[ ( (uintptr_t) src ) & 0xF ]; 2120 2121 if( !( inFlags & kDebugFlagsNoOffset ) ) 2122 { 2123 *s++ = '+'; 2124 } 2125 } 2126 if( !( inFlags & kDebugFlagsNoOffset ) ) 2127 { 2128 if( inFlags & kDebugFlags32BitOffset ) 2129 { 2130 *s++ = kHexChars[ ( offset >> 28 ) & 0xF ]; 2131 *s++ = kHexChars[ ( offset >> 24 ) & 0xF ]; 2132 *s++ = kHexChars[ ( offset >> 20 ) & 0xF ]; 2133 *s++ = kHexChars[ ( offset >> 16 ) & 0xF ]; 2134 } 2135 *s++ = kHexChars[ ( offset >> 12 ) & 0xF ]; 2136 *s++ = kHexChars[ ( offset >> 8 ) & 0xF ]; 2137 *s++ = kHexChars[ ( offset >> 4 ) & 0xF ]; 2138 *s++ = kHexChars[ offset & 0xF ]; 2139 } 2140 if( s != prefixString ) 2141 { 2142 *s++ = ':'; 2143 *s++ = ' '; 2144 } 2145 check( ( (size_t)( s - prefixString ) ) < sizeof( prefixString ) ); 2146 *s = '\0'; 2147 2148 // Build a hex string with a optional spaces after every 1, 2, and/or 4 bytes to make it easier to read. 2149 // Optionally pads the hex string with space to fill the full 16 byte range (so it lines up). 2150 2151 s = hexString; 2152 chunkSize = ( inDataSize < 16 ) ? inDataSize : 16; 2153 n = ( inFlags & kDebugFlagsNo16ByteHexPad ) ? chunkSize : 16; 2154 for( i = 0; i < n; ++i ) 2155 { 2156 if( ( inFlags & kDebugFlags8BitSeparator ) && ( i > 0 ) ) 2157 { 2158 *s++ = ' '; 2159 } 2160 if( ( inFlags & kDebugFlags16BitSeparator ) && ( i > 0 ) && ( ( i % 2 ) == 0 ) ) 2161 { 2162 *s++ = ' '; 2163 } 2164 if( !( inFlags & kDebugFlagsNo32BitSeparator ) && ( i > 0 ) && ( ( i % 4 ) == 0 ) ) 2165 { 2166 *s++ = ' '; 2167 } 2168 if( i < chunkSize ) 2169 { 2170 *s++ = kHexChars[ src[ i ] >> 4 ]; 2171 *s++ = kHexChars[ src[ i ] & 0xF ]; 2172 } 2173 else 2174 { 2175 *s++ = ' '; 2176 *s++ = ' '; 2177 } 2178 } 2179 check( ( (size_t)( s - hexString ) ) < sizeof( hexString ) ); 2180 *s = '\0'; 2181 2182 // Build a string with the ASCII version of the data (replaces non-printable characters with '^'). 2183 // Optionally pads the string with '`' to fill the full 16 byte range (so it lines up). 2184 2185 s = asciiString; 2186 if( !( inFlags & kDebugFlagsNoASCII ) ) 2187 { 2188 *s++ = ' '; 2189 *s++ = '|'; 2190 for( i = 0; i < n; ++i ) 2191 { 2192 if( i < chunkSize ) 2193 { 2194 c = src[ i ]; 2195 if( !DebugIsPrint( c ) ) 2196 { 2197 c = '^'; 2198 } 2199 } 2200 else 2201 { 2202 c = '`'; 2203 } 2204 *s++ = (char) c; 2205 } 2206 *s++ = '|'; 2207 check( ( (size_t)( s - asciiString ) ) < sizeof( asciiString ) ); 2208 } 2209 *s = '\0'; 2210 2211 // Build a string indicating how bytes are in the hex dump. Only printed on the first line. 2212 2213 s = byteCountString; 2214 if( !( inFlags & kDebugFlagsNoByteCount ) ) 2215 { 2216 if( src == start ) 2217 { 2218 s += DebugSNPrintF( s, sizeof( byteCountString ), " (%d bytes)", (int) inDataSize ); 2219 } 2220 } 2221 check( ( (size_t)( s - byteCountString ) ) < sizeof( byteCountString ) ); 2222 *s = '\0'; 2223 2224 // Build the entire line from all the pieces we've previously built. 2225 2226 if( outBuffer ) 2227 { 2228 if( src == start ) 2229 { 2230 dst += DebugSNPrintF( dst, (size_t)( end - dst ), 2231 "%*s" // Indention 2232 "%s" // Separator (only if needed) 2233 "%s" // Prefix 2234 "%-*.*s" // Label 2235 "%s" // Separator 2236 "%s" // Hex 2237 "%s" // ASCII 2238 "%s" // Byte Count 2239 "%s", // Newline 2240 inIndent, "", 2241 ( src != start ) ? separator : "", 2242 prefixString, 2243 width, (int) inLabelSize, inLabel ? inLabel : "", 2244 ( width > 0 ) ? " " : "", 2245 hexString, 2246 asciiString, 2247 byteCountString, 2248 newline ); 2249 } 2250 else 2251 { 2252 dst += DebugSNPrintF( dst, (size_t)( end - dst ), 2253 "%*s" // Indention 2254 "%s" // Separator (only if needed) 2255 "%s" // Prefix 2256 "%*s" // Label Spacing 2257 "%s" // Separator 2258 "%s" // Hex 2259 "%s" // ASCII 2260 "%s" // Byte Count 2261 "%s", // Newline 2262 inIndent, "", 2263 ( src != start ) ? separator : "", 2264 prefixString, 2265 width, "", 2266 ( width > 0 ) ? " " : "", 2267 hexString, 2268 asciiString, 2269 byteCountString, 2270 newline ); 2271 } 2272 } 2273 else 2274 { 2275 if( src == start ) 2276 { 2277 dst += DebugPrintF( inLevel, 2278 "%*s" // Indention 2279 "%s" // Separator (only if needed) 2280 "%s" // Prefix 2281 "%-*.*s" // Label 2282 "%s" // Separator 2283 "%s" // Hex 2284 "%s" // ASCII 2285 "%s" // Byte Count 2286 "%s", // Newline 2287 inIndent, "", 2288 ( src != start ) ? separator : "", 2289 prefixString, 2290 width, (int) inLabelSize, inLabel, 2291 ( width > 0 ) ? " " : "", 2292 hexString, 2293 asciiString, 2294 byteCountString, 2295 newline ); 2296 } 2297 else 2298 { 2299 dst += DebugPrintF( inLevel, 2300 "%*s" // Indention 2301 "%s" // Separator (only if needed) 2302 "%s" // Prefix 2303 "%*s" // Label Spacing 2304 "%s" // Separator 2305 "%s" // Hex 2306 "%s" // ASCII 2307 "%s" // Byte Count 2308 "%s", // Newline 2309 inIndent, "", 2310 ( src != start ) ? separator : "", 2311 prefixString, 2312 width, "", 2313 ( width > 0 ) ? " " : "", 2314 hexString, 2315 asciiString, 2316 byteCountString, 2317 newline ); 2318 } 2319 } 2320 2321 // Move to the next chunk. Exit if there is no more data. 2322 2323 offset += (int) chunkSize; 2324 src += chunkSize; 2325 inDataSize -= chunkSize; 2326 if( inDataSize == 0 ) 2327 { 2328 break; 2329 } 2330 } 2331 2332 // Note: The "dst - outBuffer" size calculation works even if "outBuffer" is NULL because it's all relative. 2333 2334 return( (size_t)( dst - outBuffer ) ); 2335 } 2336 2337 //=========================================================================================================================== 2338 // DebugNumVersionToString 2339 //=========================================================================================================================== 2340 2341 static char * DebugNumVersionToString( uint32_t inVersion, char *inString ) 2342 { 2343 char * s; 2344 uint8_t majorRev; 2345 uint8_t minor; 2346 uint8_t bugFix; 2347 uint8_t stage; 2348 uint8_t revision; 2349 2350 check( inString ); 2351 2352 majorRev = (uint8_t)( ( inVersion >> 24 ) & 0xFF ); 2353 minor = (uint8_t)( ( inVersion >> 20 ) & 0x0F ); 2354 bugFix = (uint8_t)( ( inVersion >> 16 ) & 0x0F ); 2355 stage = (uint8_t)( ( inVersion >> 8 ) & 0xFF ); 2356 revision = (uint8_t)( inVersion & 0xFF ); 2357 2358 // Convert the major, minor, and bugfix numbers. 2359 2360 s = inString; 2361 s += sprintf( s, "%u", majorRev ); 2362 s += sprintf( s, ".%u", minor ); 2363 if( bugFix != 0 ) 2364 { 2365 s += sprintf( s, ".%u", bugFix ); 2366 } 2367 2368 // Convert the version stage and non-release revision number. 2369 2370 switch( stage ) 2371 { 2372 case kVersionStageDevelopment: 2373 s += sprintf( s, "d%u", revision ); 2374 break; 2375 2376 case kVersionStageAlpha: 2377 s += sprintf( s, "a%u", revision ); 2378 break; 2379 2380 case kVersionStageBeta: 2381 s += sprintf( s, "b%u", revision ); 2382 break; 2383 2384 case kVersionStageFinal: 2385 2386 // A non-release revision of zero is a special case indicating the software is GM (at the golden master 2387 // stage) and therefore, the non-release revision should not be added to the string. 2388 2389 if( revision != 0 ) 2390 { 2391 s += sprintf( s, "f%u", revision ); 2392 } 2393 break; 2394 2395 default: 2396 dlog( kDebugLevelError, "invalid NumVersion stage (0x%02X)\n", stage ); 2397 break; 2398 } 2399 return( inString ); 2400 } 2401 2402 //=========================================================================================================================== 2403 // DebugTaskLevel 2404 //=========================================================================================================================== 2405 2406 DEBUG_EXPORT uint32_t DebugTaskLevel( void ) 2407 { 2408 uint32_t level; 2409 2410 level = 0; 2411 2412 return( level ); 2413 } 2414 2415 #if ( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE ) 2416 //=========================================================================================================================== 2417 // DebugWinEnableConsole 2418 //=========================================================================================================================== 2419 2420 #pragma warning( disable:4311 ) 2421 2422 static void DebugWinEnableConsole( void ) 2423 { 2424 static bool sConsoleEnabled = false; 2425 BOOL result; 2426 int fileHandle; 2427 FILE * file; 2428 int err; 2429 2430 if( sConsoleEnabled ) 2431 { 2432 goto exit; 2433 } 2434 2435 // Create console window. 2436 2437 result = AllocConsole(); 2438 require_quiet( result, exit ); 2439 2440 // Redirect stdin to the console stdin. 2441 2442 fileHandle = _open_osfhandle( (long) GetStdHandle( STD_INPUT_HANDLE ), _O_TEXT ); 2443 2444 #if ( defined( __MWERKS__ ) ) 2445 file = __handle_reopen( (unsigned long) fileHandle, "r", stdin ); 2446 require_quiet( file, exit ); 2447 #else 2448 file = _fdopen( fileHandle, "r" ); 2449 require_quiet( file, exit ); 2450 2451 *stdin = *file; 2452 #endif 2453 2454 err = setvbuf( stdin, NULL, _IONBF, 0 ); 2455 require_noerr_quiet( err, exit ); 2456 2457 // Redirect stdout to the console stdout. 2458 2459 fileHandle = _open_osfhandle( (long) GetStdHandle( STD_OUTPUT_HANDLE ), _O_TEXT ); 2460 2461 #if ( defined( __MWERKS__ ) ) 2462 file = __handle_reopen( (unsigned long) fileHandle, "w", stdout ); 2463 require_quiet( file, exit ); 2464 #else 2465 file = _fdopen( fileHandle, "w" ); 2466 require_quiet( file, exit ); 2467 2468 *stdout = *file; 2469 #endif 2470 2471 err = setvbuf( stdout, NULL, _IONBF, 0 ); 2472 require_noerr_quiet( err, exit ); 2473 2474 // Redirect stderr to the console stdout. 2475 2476 fileHandle = _open_osfhandle( (long) GetStdHandle( STD_OUTPUT_HANDLE ), _O_TEXT ); 2477 2478 #if ( defined( __MWERKS__ ) ) 2479 file = __handle_reopen( (unsigned long) fileHandle, "w", stderr ); 2480 require_quiet( file, exit ); 2481 #else 2482 file = _fdopen( fileHandle, "w" ); 2483 require_quiet( file, exit ); 2484 2485 *stderr = *file; 2486 #endif 2487 2488 err = setvbuf( stderr, NULL, _IONBF, 0 ); 2489 require_noerr_quiet( err, exit ); 2490 2491 sConsoleEnabled = true; 2492 2493 exit: 2494 return; 2495 } 2496 2497 #pragma warning( default:4311 ) 2498 2499 #endif // TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE 2500 2501 #if ( TARGET_OS_WIN32 ) 2502 //=========================================================================================================================== 2503 // DebugWinCharToTCharString 2504 //=========================================================================================================================== 2505 2506 static TCHAR * 2507 DebugWinCharToTCharString( 2508 const char * inCharString, 2509 size_t inCharCount, 2510 TCHAR * outTCharString, 2511 size_t inTCharCountMax, 2512 size_t * outTCharCount ) 2513 { 2514 const char * src; 2515 TCHAR * dst; 2516 TCHAR * end; 2517 2518 if( inCharCount == kSizeCString ) 2519 { 2520 inCharCount = strlen( inCharString ); 2521 } 2522 src = inCharString; 2523 dst = outTCharString; 2524 if( inTCharCountMax > 0 ) 2525 { 2526 inTCharCountMax -= 1; 2527 if( inTCharCountMax > inCharCount ) 2528 { 2529 inTCharCountMax = inCharCount; 2530 } 2531 2532 end = dst + inTCharCountMax; 2533 while( dst < end ) 2534 { 2535 *dst++ = (TCHAR) *src++; 2536 } 2537 *dst = 0; 2538 } 2539 if( outTCharCount ) 2540 { 2541 *outTCharCount = (size_t)( dst - outTCharString ); 2542 } 2543 return( outTCharString ); 2544 } 2545 #endif 2546 2547 #if 0 2548 #pragma mark - 2549 #pragma mark == Debugging == 2550 #endif 2551 2552 //=========================================================================================================================== 2553 // DebugServicesTest 2554 //=========================================================================================================================== 2555 2556 DEBUG_EXPORT OSStatus DebugServicesTest( void ) 2557 { 2558 OSStatus err; 2559 char s[ 512 ]; 2560 uint8_t * p; 2561 uint8_t data[] = 2562 { 2563 0x11, 0x22, 0x33, 0x44, 2564 0x55, 0x66, 2565 0x77, 0x88, 0x99, 0xAA, 2566 0xBB, 0xCC, 0xDD, 2567 0xEE, 2568 0xFF, 2569 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 2570 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xA0, 2571 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, 0x81, 0x91, 0xA1 2572 }; 2573 2574 debug_initialize( kDebugOutputTypeMetaConsole ); 2575 2576 // check's 2577 2578 check( 0 && "SHOULD SEE: check" ); 2579 check( 1 && "SHOULD *NOT* SEE: check (valid)" ); 2580 check_string( 0, "SHOULD SEE: check_string" ); 2581 check_string( 1, "SHOULD *NOT* SEE: check_string (valid)" ); 2582 check_noerr( -123 ); 2583 check_noerr( 10038 ); 2584 check_noerr( 22 ); 2585 check_noerr( 0 ); 2586 check_noerr_string( -6712, "SHOULD SEE: check_noerr_string" ); 2587 check_noerr_string( 0, "SHOULD *NOT* SEE: check_noerr_string (valid)" ); 2588 check_translated_errno( 0 >= 0 && "SHOULD *NOT* SEE", -384, -999 ); 2589 check_translated_errno( -1 >= 0 && "SHOULD SEE", -384, -999 ); 2590 check_translated_errno( -1 >= 0 && "SHOULD SEE", 0, -999 ); 2591 check_ptr_overlap( "SHOULD *NOT* SEE" ? 10 : 0, 10, 22, 10 ); 2592 check_ptr_overlap( "SHOULD SEE" ? 10 : 0, 10, 5, 10 ); 2593 check_ptr_overlap( "SHOULD SEE" ? 10 : 0, 10, 12, 6 ); 2594 check_ptr_overlap( "SHOULD SEE" ? 12 : 0, 6, 10, 10 ); 2595 check_ptr_overlap( "SHOULD SEE" ? 12 : 0, 10, 10, 10 ); 2596 check_ptr_overlap( "SHOULD *NOT* SEE" ? 22 : 0, 10, 10, 10 ); 2597 check_ptr_overlap( "SHOULD *NOT* SEE" ? 10 : 0, 10, 20, 10 ); 2598 check_ptr_overlap( "SHOULD *NOT* SEE" ? 20 : 0, 10, 10, 10 ); 2599 2600 // require's 2601 2602 require( 0 && "SHOULD SEE", require1 ); 2603 { err = kResponseErr; goto exit; } 2604 require1: 2605 require( 1 && "SHOULD *NOT* SEE", require2 ); 2606 goto require2Good; 2607 require2: 2608 { err = kResponseErr; goto exit; } 2609 require2Good: 2610 require_string( 0 && "SHOULD SEE", require3, "SHOULD SEE: require_string" ); 2611 { err = kResponseErr; goto exit; } 2612 require3: 2613 require_string( 1 && "SHOULD *NOT* SEE", require4, "SHOULD *NOT* SEE: require_string (valid)" ); 2614 goto require4Good; 2615 require4: 2616 { err = kResponseErr; goto exit; } 2617 require4Good: 2618 require_quiet( 0 && "SHOULD SEE", require5 ); 2619 { err = kResponseErr; goto exit; } 2620 require5: 2621 require_quiet( 1 && "SHOULD *NOT* SEE", require6 ); 2622 goto require6Good; 2623 require6: 2624 { err = kResponseErr; goto exit; } 2625 require6Good: 2626 require_noerr( -1, require7 ); 2627 { err = kResponseErr; goto exit; } 2628 require7: 2629 require_noerr( 0, require8 ); 2630 goto require8Good; 2631 require8: 2632 { err = kResponseErr; goto exit; } 2633 require8Good: 2634 require_noerr_string( -2, require9, "SHOULD SEE: require_noerr_string"); 2635 { err = kResponseErr; goto exit; } 2636 require9: 2637 require_noerr_string( 0, require10, "SHOULD *NOT* SEE: require_noerr_string (valid)" ); 2638 goto require10Good; 2639 require10: 2640 { err = kResponseErr; goto exit; } 2641 require10Good: 2642 require_noerr_action_string( -3, require11, dlog( kDebugLevelMax, "action 1 (expected)\n" ), "require_noerr_action_string" ); 2643 { err = kResponseErr; goto exit; } 2644 require11: 2645 require_noerr_action_string( 0, require12, dlog( kDebugLevelMax, "action 2\n" ), "require_noerr_action_string (valid)" ); 2646 goto require12Good; 2647 require12: 2648 { err = kResponseErr; goto exit; } 2649 require12Good: 2650 require_noerr_quiet( -4, require13 ); 2651 { err = kResponseErr; goto exit; } 2652 require13: 2653 require_noerr_quiet( 0, require14 ); 2654 goto require14Good; 2655 require14: 2656 { err = kResponseErr; goto exit; } 2657 require14Good: 2658 require_noerr_action( -5, require15, dlog( kDebugLevelMax, "SHOULD SEE: action 3 (expected)\n" ) ); 2659 { err = kResponseErr; goto exit; } 2660 require15: 2661 require_noerr_action( 0, require16, dlog( kDebugLevelMax, "SHOULD *NOT* SEE: action 4\n" ) ); 2662 goto require16Good; 2663 require16: 2664 { err = kResponseErr; goto exit; } 2665 require16Good: 2666 require_noerr_action_quiet( -4, require17, dlog( kDebugLevelMax, "SHOULD SEE: action 5 (expected)\n" ) ); 2667 { err = kResponseErr; goto exit; } 2668 require17: 2669 require_noerr_action_quiet( 0, require18, dlog( kDebugLevelMax, "SHOULD *NOT* SEE: action 6\n" ) ); 2670 goto require18Good; 2671 require18: 2672 { err = kResponseErr; goto exit; } 2673 require18Good: 2674 require_action( 0 && "SHOULD SEE", require19, dlog( kDebugLevelMax, "SHOULD SEE: action 7 (expected)\n" ) ); 2675 { err = kResponseErr; goto exit; } 2676 require19: 2677 require_action( 1 && "SHOULD *NOT* SEE", require20, dlog( kDebugLevelMax, "SHOULD *NOT* SEE: action 8\n" ) ); 2678 goto require20Good; 2679 require20: 2680 { err = kResponseErr; goto exit; } 2681 require20Good: 2682 require_action_quiet( 0, require21, dlog( kDebugLevelMax, "SHOULD SEE: action 9 (expected)\n" ) ); 2683 { err = kResponseErr; goto exit; } 2684 require21: 2685 require_action_quiet( 1, require22, dlog( kDebugLevelMax, "SHOULD *NOT* SEE: action 10\n" ) ); 2686 goto require22Good; 2687 require22: 2688 { err = kResponseErr; goto exit; } 2689 require22Good: 2690 require_action_string( 0, require23, dlog( kDebugLevelMax, "SHOULD SEE: action 11 (expected)\n" ), "SHOULD SEE: require_action_string" ); 2691 { err = kResponseErr; goto exit; } 2692 require23: 2693 require_action_string( 1, require24, dlog( kDebugLevelMax, "SHOULD *NOT* SEE: action 12\n" ), "SHOULD *NOT* SEE: require_action_string" ); 2694 goto require24Good; 2695 require24: 2696 { err = kResponseErr; goto exit; } 2697 require24Good: 2698 2699 #if ( defined( __MWERKS__ ) ) 2700 #if ( defined( __cplusplus ) && __option( exceptions ) ) 2701 #define COMPILER_HAS_EXCEPTIONS 1 2702 #else 2703 #define COMPILER_HAS_EXCEPTIONS 0 2704 #endif 2705 #else 2706 #if ( defined( __cplusplus ) ) 2707 #define COMPILER_HAS_EXCEPTIONS 1 2708 #else 2709 #define COMPILER_HAS_EXCEPTIONS 0 2710 #endif 2711 #endif 2712 2713 #if ( COMPILER_HAS_EXCEPTIONS ) 2714 try 2715 { 2716 require_throw( 1 && "SHOULD *NOT* SEE" ); 2717 require_throw( 0 && "SHOULD SEE" ); 2718 } 2719 catch(... ) 2720 { 2721 goto require26Good; 2722 } 2723 { err = kResponseErr; goto exit; } 2724 require26Good: 2725 #endif 2726 2727 // translate_errno 2728 2729 err = translate_errno( 1 != -1, -123, -567 ); 2730 require( ( err == 0 ) && "SHOULD *NOT* SEE", exit ); 2731 2732 err = translate_errno( -1 != -1, -123, -567 ); 2733 require( ( err == -123 ) && "SHOULD *NOT* SEE", exit ); 2734 2735 err = translate_errno( -1 != -1, 0, -567 ); 2736 require( ( err == -567 ) && "SHOULD *NOT* SEE", exit ); 2737 2738 // debug_string 2739 2740 debug_string( "debug_string" ); 2741 2742 // DebugSNPrintF 2743 2744 DebugSNPrintF( s, sizeof( s ), "%d", 1234 ); 2745 require_action( strcmp( s, "1234" ) == 0, exit, err = -1 ); 2746 2747 DebugSNPrintF( s, sizeof( s ), "%X", 0x2345 ); 2748 require_action( strcmp( s, "2345" ) == 0, exit, err = -1 ); 2749 2750 DebugSNPrintF( s, sizeof( s ), "%#s", "\05test" ); 2751 require_action( strcmp( s, "test" ) == 0, exit, err = -1 ); 2752 2753 DebugSNPrintF( s, sizeof( s ), "%##s", "\03www\05apple\03com" ); 2754 require_action( strcmp( s, "www.apple.com." ) == 0, exit, err = -1 ); 2755 2756 DebugSNPrintF( s, sizeof( s ), "%ld", (long) INT32_C( 2147483647 ) ); 2757 require_action( strcmp( s, "2147483647" ) == 0, exit, err = -1 ); 2758 2759 DebugSNPrintF( s, sizeof( s ), "%lu", (unsigned long) UINT32_C( 4294967295 ) ); 2760 require_action( strcmp( s, "4294967295" ) == 0, exit, err = -1 ); 2761 2762 #if ( TYPE_LONGLONG_NATIVE ) 2763 DebugSNPrintF( s, sizeof( s ), "%lld", (long_long_compat) INT64_C( 9223372036854775807 ) ); 2764 require_action( strcmp( s, "9223372036854775807" ) == 0, exit, err = -1 ); 2765 2766 DebugSNPrintF( s, sizeof( s ), "%lld", (long_long_compat) INT64_C( -9223372036854775807 ) ); 2767 require_action( strcmp( s, "-9223372036854775807" ) == 0, exit, err = -1 ); 2768 2769 DebugSNPrintF( s, sizeof( s ), "%llu", (unsigned_long_long_compat) UINT64_C( 18446744073709551615 ) ); 2770 require_action( strcmp( s, "18446744073709551615" ) == 0, exit, err = -1 ); 2771 #endif 2772 2773 DebugSNPrintF( s, sizeof( s ), "%lb", (unsigned long) binary_32( 01111011, 01111011, 01111011, 01111011 ) ); 2774 require_action( strcmp( s, "1111011011110110111101101111011" ) == 0, exit, err = -1 ); 2775 2776 DebugSNPrintF( s, sizeof( s ), "%C", 0x41624364 ); // 'AbCd' 2777 require_action( strcmp( s, "AbCd" ) == 0, exit, err = -1 ); 2778 2779 #if ( defined( MDNS_DEBUGMSGS ) ) 2780 { 2781 mDNSAddr maddr; 2782 2783 memset( &maddr, 0, sizeof( maddr ) ); 2784 maddr.type = mDNSAddrType_IPv4; 2785 maddr.ip.v4.b[ 0 ] = 127; 2786 maddr.ip.v4.b[ 1 ] = 0; 2787 maddr.ip.v4.b[ 2 ] = 0; 2788 maddr.ip.v4.b[ 3 ] = 1; 2789 DebugSNPrintF( s, sizeof( s ), "%#a", &maddr ); 2790 require_action( strcmp( s, "127.0.0.1" ) == 0, exit, err = -1 ); 2791 2792 memset( &maddr, 0, sizeof( maddr ) ); 2793 maddr.type = mDNSAddrType_IPv6; 2794 maddr.ip.v6.b[ 0 ] = 0xFE; 2795 maddr.ip.v6.b[ 1 ] = 0x80; 2796 maddr.ip.v6.b[ 15 ] = 0x01; 2797 DebugSNPrintF( s, sizeof( s ), "%#a", &maddr ); 2798 require_action( strcmp( s, "FE80:0000:0000:0000:0000:0000:0000:0001" ) == 0, exit, err = -1 ); 2799 } 2800 #endif 2801 2802 #if ( AF_INET ) 2803 { 2804 struct sockaddr_in sa4; 2805 2806 memset( &sa4, 0, sizeof( sa4 ) ); 2807 sa4.sin_family = AF_INET; 2808 p = (uint8_t *) &sa4.sin_port; 2809 p[ 0 ] = (uint8_t)( ( 80 >> 8 ) & 0xFF ); 2810 p[ 1 ] = (uint8_t)( 80 & 0xFF ); 2811 p = (uint8_t *) &sa4.sin_addr.s_addr; 2812 p[ 0 ] = (uint8_t)( ( INADDR_LOOPBACK >> 24 ) & 0xFF ); 2813 p[ 1 ] = (uint8_t)( ( INADDR_LOOPBACK >> 16 ) & 0xFF ); 2814 p[ 2 ] = (uint8_t)( ( INADDR_LOOPBACK >> 8 ) & 0xFF ); 2815 p[ 3 ] = (uint8_t)( INADDR_LOOPBACK & 0xFF ); 2816 DebugSNPrintF( s, sizeof( s ), "%##a", &sa4 ); 2817 require_action( strcmp( s, "127.0.0.1:80" ) == 0, exit, err = -1 ); 2818 } 2819 #endif 2820 2821 #if ( AF_INET6 ) 2822 { 2823 struct sockaddr_in6 sa6; 2824 2825 memset( &sa6, 0, sizeof( sa6 ) ); 2826 sa6.sin6_family = AF_INET6; 2827 p = (uint8_t *) &sa6.sin6_port; 2828 p[ 0 ] = (uint8_t)( ( 80 >> 8 ) & 0xFF ); 2829 p[ 1 ] = (uint8_t)( 80 & 0xFF ); 2830 sa6.sin6_addr.s6_addr[ 0 ] = 0xFE; 2831 sa6.sin6_addr.s6_addr[ 1 ] = 0x80; 2832 sa6.sin6_addr.s6_addr[ 15 ] = 0x01; 2833 sa6.sin6_scope_id = 2; 2834 DebugSNPrintF( s, sizeof( s ), "%##a", &sa6 ); 2835 require_action( strcmp( s, "[FE80:0000:0000:0000:0000:0000:0000:0001%2]:80" ) == 0, exit, err = -1 ); 2836 } 2837 #endif 2838 2839 // Unicode 2840 2841 DebugSNPrintF(s, sizeof(s), "%.*s", 4, "tes" ); 2842 require_action( strcmp( s, "tes" ) == 0, exit, err = kResponseErr ); 2843 2844 DebugSNPrintF(s, sizeof(s), "%.*s", 4, "test" ); 2845 require_action( strcmp( s, "test" ) == 0, exit, err = kResponseErr ); 2846 2847 DebugSNPrintF(s, sizeof(s), "%.*s", 4, "testing" ); 2848 require_action( strcmp( s, "test" ) == 0, exit, err = kResponseErr ); 2849 2850 DebugSNPrintF(s, sizeof(s), "%.*s", 4, "te\xC3\xA9" ); 2851 require_action( strcmp( s, "te\xC3\xA9" ) == 0, exit, err = kResponseErr ); 2852 2853 DebugSNPrintF(s, sizeof(s), "%.*s", 4, "te\xC3\xA9ing" ); 2854 require_action( strcmp( s, "te\xC3\xA9" ) == 0, exit, err = kResponseErr ); 2855 2856 DebugSNPrintF(s, sizeof(s), "%.*s", 4, "tes\xC3\xA9ing" ); 2857 require_action( strcmp( s, "tes" ) == 0, exit, err = kResponseErr ); 2858 2859 DebugSNPrintF(s, sizeof(s), "%.*s", 4, "t\xed\x9f\xbf" ); 2860 require_action( strcmp( s, "t\xed\x9f\xbf" ) == 0, exit, err = kResponseErr ); 2861 2862 DebugSNPrintF(s, sizeof(s), "%.*s", 4, "t\xed\x9f\xbfing" ); 2863 require_action( strcmp( s, "t\xed\x9f\xbf" ) == 0, exit, err = kResponseErr ); 2864 2865 DebugSNPrintF(s, sizeof(s), "%.*s", 4, "te\xed\x9f\xbf" ); 2866 require_action( strcmp( s, "te" ) == 0, exit, err = kResponseErr ); 2867 2868 DebugSNPrintF(s, sizeof(s), "%.*s", 4, "te\xed\x9f\xbfing" ); 2869 require_action( strcmp( s, "te" ) == 0, exit, err = kResponseErr ); 2870 2871 DebugSNPrintF(s, sizeof(s), "%.*s", 7, "te\xC3\xA9\xed\x9f\xbfing" ); 2872 require_action( strcmp( s, "te\xC3\xA9\xed\x9f\xbf" ) == 0, exit, err = kResponseErr ); 2873 2874 DebugSNPrintF(s, sizeof(s), "%.*s", 6, "te\xC3\xA9\xed\x9f\xbfing" ); 2875 require_action( strcmp( s, "te\xC3\xA9" ) == 0, exit, err = kResponseErr ); 2876 2877 DebugSNPrintF(s, sizeof(s), "%.*s", 5, "te\xC3\xA9\xed\x9f\xbfing" ); 2878 require_action( strcmp( s, "te\xC3\xA9" ) == 0, exit, err = kResponseErr ); 2879 2880 #if ( TARGET_RT_BIG_ENDIAN ) 2881 DebugSNPrintF( s, sizeof( s ), "%S", "\x00" "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" "\x00" ); 2882 require_action( strcmp( s, "abcd" ) == 0, exit, err = -1 ); 2883 #else 2884 DebugSNPrintF( s, sizeof( s ), "%S", "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" "\x00" "\x00" ); 2885 require_action( strcmp( s, "abcd" ) == 0, exit, err = -1 ); 2886 #endif 2887 2888 DebugSNPrintF( s, sizeof( s ), "%S", 2889 "\xFE\xFF" "\x00" "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" "\x00" ); // Big Endian BOM 2890 require_action( strcmp( s, "abcd" ) == 0, exit, err = -1 ); 2891 2892 DebugSNPrintF( s, sizeof( s ), "%S", 2893 "\xFF\xFE" "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" "\x00" "\x00" ); // Little Endian BOM 2894 require_action( strcmp( s, "abcd" ) == 0, exit, err = -1 ); 2895 2896 DebugSNPrintF( s, sizeof( s ), "%#S", "\x00" "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" "\x00" ); // Big Endian 2897 require_action( strcmp( s, "abcd" ) == 0, exit, err = -1 ); 2898 2899 DebugSNPrintF( s, sizeof( s ), "%##S", "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" "\x00" "\x00" ); // Little Endian 2900 require_action( strcmp( s, "abcd" ) == 0, exit, err = -1 ); 2901 2902 DebugSNPrintF( s, sizeof( s ), "%.*S", 2903 4, "\xFE\xFF" "\x00" "a" "\x00" "b" "\x00" "c" "\x00" "d" ); // Big Endian BOM 2904 require_action( strcmp( s, "abc" ) == 0, exit, err = -1 ); 2905 2906 DebugSNPrintF( s, sizeof( s ), "%.*S", 2907 4, "\xFF\xFE" "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" ); // Little Endian BOM 2908 require_action( strcmp( s, "abc" ) == 0, exit, err = -1 ); 2909 2910 #if ( TARGET_RT_BIG_ENDIAN ) 2911 DebugSNPrintF( s, sizeof( s ), "%.*S", 3, "\x00" "a" "\x00" "b" "\x00" "c" "\x00" "d" ); 2912 require_action( strcmp( s, "abc" ) == 0, exit, err = -1 ); 2913 #else 2914 DebugSNPrintF( s, sizeof( s ), "%.*S", 3, "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" ); 2915 require_action( strcmp( s, "abc" ) == 0, exit, err = -1 ); 2916 #endif 2917 2918 DebugSNPrintF( s, sizeof( s ), "%#.*S", 3, "\x00" "a" "\x00" "b" "\x00" "c" "\x00" "d" ); // Big Endian 2919 require_action( strcmp( s, "abc" ) == 0, exit, err = -1 ); 2920 2921 DebugSNPrintF( s, sizeof( s ), "%##.*S", 3, "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" ); // Little Endian 2922 require_action( strcmp( s, "abc" ) == 0, exit, err = -1 ); 2923 2924 // Misc 2925 2926 DebugSNPrintF( s, sizeof( s ), "%U", "\x10\xb8\xa7\x6b" "\xad\x9d" "\xd1\x11" "\x80\xb4" "\x00\xc0\x4f\xd4\x30\xc8" ); 2927 require_action( strcmp( s, "6ba7b810-9dad-11d1-80b4-00c04fd430c8" ) == 0, exit, err = -1 ); 2928 2929 DebugSNPrintF( s, sizeof( s ), "%m", 0 ); 2930 require_action( strcmp( s, "no error" ) == 0, exit, err = -1 ); 2931 2932 DebugSNPrintF( s, sizeof( s ), "%lm", (long) 0 ); 2933 require_action( strcmp( s, "no error" ) == 0, exit, err = -1 ); 2934 2935 DebugSNPrintF( s, sizeof( s ), "\"%H\"", "\x6b\xa7\xb8\x10\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8", 16, 16 ); 2936 DebugPrintF( kDebugLevelMax, "%s\n\n", s ); 2937 2938 DebugSNPrintF( s, sizeof( s ), "\"%H\"", 2939 "\x6b\xa7\xb8\x10\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8" 2940 "\x6b\xa7\xb8\x10\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8", 2941 32, 32 ); 2942 DebugPrintF( kDebugLevelMax, "%s\n\n", s ); 2943 2944 DebugSNPrintF( s, sizeof( s ), "\"%H\"", "\x6b\xa7", 2, 2 ); 2945 DebugPrintF( kDebugLevelMax, "%s\n\n", s ); 2946 2947 // Hex Dumps 2948 2949 s[ 0 ] = '\0'; 2950 DebugHexDump( kDebugLevelMax, 0, "My Label", kSizeCString, 0, NULL, 0, data, data, sizeof( data ), 2951 kDebugFlagsNone, s, sizeof( s ) ); 2952 DebugPrintF( kDebugLevelMax, "%s\n", s ); 2953 2954 s[ 0 ] = '\0'; 2955 DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, data, data, sizeof( data ), 2956 kDebugFlagsNoAddress | kDebugFlagsNoOffset, s, sizeof( s ) ); 2957 DebugPrintF( kDebugLevelMax, "%s\n", s ); 2958 2959 s[ 0 ] = '\0'; 2960 DebugHexDump( kDebugLevelMax, 0, "My Label", kSizeCString, 0, NULL, 0, data, data, sizeof( data ), 2961 kDebugFlagsNoAddress | kDebugFlagsNoOffset, s, sizeof( s ) ); 2962 DebugPrintF( kDebugLevelMax, "%s\n", s ); 2963 2964 s[ 0 ] = '\0'; 2965 DebugHexDump( kDebugLevelMax, 0, "My Label", kSizeCString, 0, NULL, 0, data, data, sizeof( data ), 2966 kDebugFlagsNoAddress, s, sizeof( s ) ); 2967 DebugPrintF( kDebugLevelMax, "%s\n", s ); 2968 2969 s[ 0 ] = '\0'; 2970 DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, data, data, sizeof( data ), 2971 kDebugFlagsNoOffset, s, sizeof( s ) ); 2972 DebugPrintF( kDebugLevelMax, "%s\n", s ); 2973 2974 s[ 0 ] = '\0'; 2975 DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, data, data, sizeof( data ), 2976 kDebugFlagsNoAddress, s, sizeof( s ) ); 2977 DebugPrintF( kDebugLevelMax, "%s\n", s ); 2978 2979 s[ 0 ] = '\0'; 2980 DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, data, data, sizeof( data ), 2981 kDebugFlagsNoOffset, s, sizeof( s ) ); 2982 DebugPrintF( kDebugLevelMax, "%s\n", s ); 2983 2984 s[ 0 ] = '\0'; 2985 DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, data, data, sizeof( data ), 2986 kDebugFlagsNoByteCount, s, sizeof( s ) ); 2987 DebugPrintF( kDebugLevelMax, "%s\n", s ); 2988 2989 s[ 0 ] = '\0'; 2990 DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, "\x41\x62\x43\x64", "\x41\x62\x43\x64", 4, // 'AbCd' 2991 kDebugFlagsNoAddress | kDebugFlagsNoOffset | kDebugFlagsNoNewLine | 2992 kDebugFlagsNo32BitSeparator | kDebugFlagsNo16ByteHexPad | kDebugFlagsNoByteCount, 2993 s, sizeof( s ) ); 2994 DebugPrintF( kDebugLevelMax, "%s\n", s ); 2995 2996 s[ 0 ] = '\0'; 2997 DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, data, data, sizeof( data ), 2998 kDebugFlagsNoAddress | kDebugFlagsNoOffset | kDebugFlagsNoASCII | kDebugFlagsNoNewLine | 2999 kDebugFlags16BitSeparator | kDebugFlagsNo32BitSeparator | 3000 kDebugFlagsNo16ByteHexPad | kDebugFlagsNoByteCount, s, sizeof( s ) ); 3001 DebugPrintF( kDebugLevelMax, "%s\n", s ); 3002 3003 s[ 0 ] = '\0'; 3004 DebugHexDump( kDebugLevelMax, 8, NULL, 0, 0, NULL, 0, data, data, sizeof( data ), kDebugFlagsNone, s, sizeof( s ) ); 3005 DebugPrintF( kDebugLevelMax, "%s\n", s ); 3006 3007 // dlog's 3008 3009 dlog( kDebugLevelNotice, "dlog\n" ); 3010 dlog( kDebugLevelNotice, "dlog integer: %d\n", 123 ); 3011 dlog( kDebugLevelNotice, "dlog string: \"%s\"\n", "test string" ); 3012 dlogmem( kDebugLevelNotice, data, sizeof( data ) ); 3013 3014 // Done 3015 3016 DebugPrintF( kDebugLevelMax, "\n\nALL TESTS DONE\n\n" ); 3017 err = kNoErr; 3018 3019 exit: 3020 if( err ) 3021 { 3022 DebugPrintF( kDebugLevelMax, "\n\n### TEST FAILED ###\n\n" ); 3023 } 3024 return( err ); 3025 } 3026 3027 #endif // DEBUG 3028