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 
DebugInitialize(DebugOutputType inType,...)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 
DebugFinalize(void)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 
DebugGetProperty(DebugPropertyTag inTag,...)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 
DebugSetProperty(DebugPropertyTag inTag,...)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 
DebugPrintF(DebugLevel inLevel,const char * inFormat,...)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 
DebugPrintFVAList(DebugLevel inLevel,const char * inFormat,va_list inArgs)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 
DebugPrint(DebugLevel inLevel,char * inData,size_t inSize)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
DebugPrintAssert(int_least32_t inErrorCode,const char * inAssertString,const char * inMessage,const char * inFilename,int_least32_t inLineNumber,const char * inFunction)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 
DebugFPrintFInit(DebugOutputTypeFlags inFlags,const char * inFilename)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 
DebugFPrintFPrint(char * inData,size_t inSize)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 
DebugiDebugInit(void)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 
DebugiDebugPrint(char * inData,size_t inSize)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 
DebugKPrintFPrint(char * inData,size_t inSize)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 
DebugMacOSXIOLogPrint(char * inData,size_t inSize)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 
DebugMacOSXLogInit(void)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 
DebugMacOSXLogPrint(char * inData,size_t inSize)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 
DebugWindowsDebuggerPrint(char * inData,size_t inSize)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 
DebugWindowsEventLogInit(const char * inName,HMODULE inModule)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 
DebugWindowsEventLogPrint(DebugLevel inLevel,char * inData,size_t inSize)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
DebugAssertOutputHandler(OSType inComponentSignature,UInt32 inOptions,const char * inAssertString,const char * inExceptionString,const char * inErrorString,const char * inFileName,long inLineNumber,void * inValue,ConstStr255Param inOutputMsg)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 
DebugSNPrintF(char * sbuffer,size_t buflen,const char * fmt,...)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 
DebugSNPrintFVAList(char * sbuffer,size_t buflen,const char * fmt,va_list arg)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 
DebugGetErrorString(long inErrorCode,char * inBuffer,size_t inBufferSize)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
DebugHexDump(DebugLevel inLevel,int inIndent,const char * inLabel,size_t inLabelSize,int inLabelMinWidth,const char * inType,size_t inTypeSize,const void * inDataStart,const void * inData,size_t inDataSize,DebugFlags inFlags,char * outBuffer,size_t inBufferSize)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 
DebugNumVersionToString(uint32_t inVersion,char * inString)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 
DebugTaskLevel(void)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 
DebugWinEnableConsole(void)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 *
DebugWinCharToTCharString(const char * inCharString,size_t inCharCount,TCHAR * outTCharString,size_t inTCharCountMax,size_t * outTCharCount)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 
DebugServicesTest(void)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