Home | History | Annotate | Line # | Download | only in mDNSShared
      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