1 /* -*- Mode: C; tab-width: 4 -*-
2  *
3  * Copyright (c) 1997-2004 Apple Computer, Inc. All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16 
17     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 (buflen == 0) return(0);
1163     buflen--;       // Pre-reserve one space in the buffer for the terminating nul
1164     if (buflen == 0) goto exit;
1165 
1166     for (c = *fmt; c != 0; c = *++fmt)
1167     {
1168         if (c != '%')
1169         {
1170             *sbuffer++ = (char)c;
1171             if (++nwritten >= buflen) goto exit;
1172         }
1173         else
1174         {
1175             size_t i=0, j;
1176             // The mDNS Vsprintf Argument Conversion Buffer is used as a temporary holding area for
1177             // generating decimal numbers, hexdecimal numbers, IP addresses, domain name strings, etc.
1178             // The size needs to be enough for a 256-byte domain name plus some error text.
1179             #define mDNS_VACB_Size 300
1180             char mDNS_VACB[mDNS_VACB_Size];
1181             #define mDNS_VACB_Lim (&mDNS_VACB[mDNS_VACB_Size])
1182             #define mDNS_VACB_Remain(s) ((size_t)(mDNS_VACB_Lim - s))
1183             char *s = mDNS_VACB_Lim;
1184             const char *digits = "0123456789ABCDEF";
1185             struct DebugSNPrintF_format F = DebugSNPrintF_format_default;
1186 
1187             for(;;) //  decode flags
1188             {
1189                 c = *++fmt;
1190                 if      (c == '-') F.leftJustify = 1;
1191                 else if (c == '+') F.forceSign = 1;
1192                 else if (c == ' ') F.sign = ' ';
1193                 else if (c == '#') F.altForm++;
1194                 else if (c == '0') F.zeroPad = 1;
1195                 else break;
1196             }
1197 
1198             if (c == '*')   //  decode field width
1199             {
1200                 int f = va_arg(arg, int);
1201                 if (f < 0) { f = -f; F.leftJustify = 1; }
1202                 F.fieldWidth = (unsigned int)f;
1203                 c = *++fmt;
1204             }
1205             else
1206             {
1207                 for (; c >= '0' && c <= '9'; c = *++fmt)
1208                     F.fieldWidth = (10 * F.fieldWidth) + (c - '0');
1209             }
1210 
1211             if (c == '.')   //  decode precision
1212             {
1213                 if ((c = *++fmt) == '*')
1214                 { F.precision = va_arg(arg, unsigned int); c = *++fmt; }
1215                 else for (; c >= '0' && c <= '9'; c = *++fmt)
1216                         F.precision = (10 * F.precision) + (c - '0');
1217                 F.havePrecision = 1;
1218             }
1219 
1220             if (F.leftJustify) F.zeroPad = 0;
1221 
1222 conv:
1223             switch (c)  //  perform appropriate conversion
1224             {
1225                 #if TYPE_LONGLONG_NATIVE
1226                 unsigned_long_long_compat n;
1227                 unsigned_long_long_compat base;
1228                 #else
1229                 unsigned long n;
1230                 unsigned long base;
1231                 #endif
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(int_least32_t inErrorCode,char * inBuffer,size_t inBufferSize)1570 DEBUG_EXPORT const char *   DebugGetErrorString( int_least32_t 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             s = strerror( inErrorCode );
1948                 #endif
1949             if( !s )
1950             {
1951                 s = "<unknown error code>";
1952             }
1953         }
1954         break;
1955     }
1956 
1957     // Copy the string to the output buffer. If no buffer is supplied or it is empty, return an empty string.
1958 
1959     if( inBuffer && ( inBufferSize > 0 ) )
1960     {
1961         dst = inBuffer;
1962         end = dst + ( inBufferSize - 1 );
1963         while( ( ( end - dst ) > 0 ) && ( *s != '\0' ) )
1964         {
1965             *dst++ = *s++;
1966         }
1967         *dst = '\0';
1968         s = inBuffer;
1969     }
1970     return( s );
1971 }
1972 
1973 //===========================================================================================================================
1974 //	DebugHexDump
1975 //===========================================================================================================================
1976 
1977 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)1978 DebugHexDump(
1979     DebugLevel inLevel,
1980     int inIndent,
1981     const char *    inLabel,
1982     size_t inLabelSize,
1983     int inLabelMinWidth,
1984     const char *    inType,
1985     size_t inTypeSize,
1986     const void *    inDataStart,
1987     const void *    inData,
1988     size_t inDataSize,
1989     DebugFlags inFlags,
1990     char *          outBuffer,
1991     size_t inBufferSize )
1992 {
1993     static const char kHexChars[] = "0123456789ABCDEF";
1994     const uint8_t *         start;
1995     const uint8_t *         src;
1996     char *                  dst;
1997     char *                  end;
1998     size_t n;
1999     int offset;
2000     int width;
2001     const char *            newline;
2002     char separator[ 8 ];
2003     char *                  s;
2004 
2005     DEBUG_UNUSED( inType );
2006     DEBUG_UNUSED( inTypeSize );
2007 
2008     // Set up the function-wide variables.
2009 
2010     if( inLabelSize == kSizeCString )
2011     {
2012         inLabelSize = strlen( inLabel );
2013     }
2014     start   = (const uint8_t *) inData;
2015     src     = start;
2016     dst     = outBuffer;
2017     end     = dst + inBufferSize;
2018     offset  = (int)( (intptr_t) inData - (intptr_t) inDataStart );
2019     width   = ( (int) inLabelSize > inLabelMinWidth ) ? (int) inLabelSize : inLabelMinWidth;
2020     newline = ( inFlags & kDebugFlagsNoNewLine ) ? "" : "\n";
2021 
2022     // Set up the separator string. This is used to insert spaces on subsequent "lines" when not using newlines.
2023 
2024     s = separator;
2025     if( inFlags & kDebugFlagsNoNewLine )
2026     {
2027         if( inFlags & kDebugFlags8BitSeparator )
2028         {
2029             *s++ = ' ';
2030         }
2031         if( inFlags & kDebugFlags16BitSeparator )
2032         {
2033             *s++ = ' ';
2034         }
2035         if( !( inFlags & kDebugFlagsNo32BitSeparator ) )
2036         {
2037             *s++ = ' ';
2038         }
2039         check( ( (size_t)( s - separator ) ) < sizeof( separator ) );
2040     }
2041     *s = '\0';
2042 
2043     for( ;; )
2044     {
2045         char prefixString[ 32 ];
2046         char hexString[ 64 ];
2047         char asciiString[ 32 ];
2048         char byteCountString[ 32 ];
2049         int c;
2050         size_t chunkSize;
2051         size_t i;
2052 
2053         // If this is a label-only item (i.e. no data), print the label (accounting for prefix string spacing) and exit.
2054 
2055         if( inDataSize == 0 )
2056         {
2057             if( inLabel && ( inLabelSize > 0 ) )
2058             {
2059                 width = 0;
2060                 if( !( inFlags & kDebugFlagsNoAddress ) )
2061                 {
2062                     width += 8;         // "00000000"
2063                     if( !( inFlags & kDebugFlagsNoOffset ) )
2064                     {
2065                         width += 1;     // "+"
2066                     }
2067                 }
2068                 if( inFlags & kDebugFlags32BitOffset )
2069                 {
2070                     width += 8;         // "00000000"
2071                 }
2072                 else if( !( inFlags & kDebugFlagsNoOffset ) )
2073                 {
2074                     width += 4;         // "0000"
2075                 }
2076 
2077                 if( outBuffer )
2078                 {
2079                     dst += DebugSNPrintF( dst, (size_t)( end - dst ), "%*s" "%-*.*s" "%.*s" "%s",
2080                                           width, "",
2081                                           ( width > 0 ) ? ": " : "",
2082                                           width, (int) inLabelSize, inLabel,
2083                                           newline );
2084                 }
2085                 else
2086                 {
2087                     dst += DebugPrintF( inLevel, "%*s" "%-*.*s" "%.*s" "%s",
2088                                         width, "",
2089                                         ( width > 0 ) ? ": " : "",
2090                                         width, (int) inLabelSize, inLabel,
2091                                         newline );
2092                 }
2093             }
2094             break;
2095         }
2096 
2097         // Build the prefix string. It will be in one of the following formats:
2098         //
2099         // 1) "00000000+0000[0000]"	(address and offset)
2100         // 2) "00000000"			(address only)
2101         // 3) "0000[0000]"			(offset only)
2102         // 4) ""					(no address or offset)
2103         //
2104         // Note: If we're printing multiple "lines", but not printing newlines, a space is used to separate.
2105 
2106         s = prefixString;
2107         if( !( inFlags & kDebugFlagsNoAddress ) )
2108         {
2109             *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 28 ) & 0xF ];
2110             *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 24 ) & 0xF ];
2111             *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 20 ) & 0xF ];
2112             *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 16 ) & 0xF ];
2113             *s++ = kHexChars[ ( ( (uintptr_t) src ) >> 12 ) & 0xF ];
2114             *s++ = kHexChars[ ( ( (uintptr_t) src ) >>  8 ) & 0xF ];
2115             *s++ = kHexChars[ ( ( (uintptr_t) src ) >>  4 ) & 0xF ];
2116             *s++ = kHexChars[   ( (uintptr_t) src )         & 0xF ];
2117 
2118             if( !( inFlags & kDebugFlagsNoOffset ) )
2119             {
2120                 *s++ = '+';
2121             }
2122         }
2123         if( !( inFlags & kDebugFlagsNoOffset ) )
2124         {
2125             if( inFlags & kDebugFlags32BitOffset )
2126             {
2127                 *s++ = kHexChars[ ( offset >> 28 ) & 0xF ];
2128                 *s++ = kHexChars[ ( offset >> 24 ) & 0xF ];
2129                 *s++ = kHexChars[ ( offset >> 20 ) & 0xF ];
2130                 *s++ = kHexChars[ ( offset >> 16 ) & 0xF ];
2131             }
2132             *s++ = kHexChars[ ( offset >> 12 ) & 0xF ];
2133             *s++ = kHexChars[ ( offset >>  8 ) & 0xF ];
2134             *s++ = kHexChars[ ( offset >>  4 ) & 0xF ];
2135             *s++ = kHexChars[   offset         & 0xF ];
2136         }
2137         if( s != prefixString )
2138         {
2139             *s++ = ':';
2140             *s++ = ' ';
2141         }
2142         check( ( (size_t)( s - prefixString ) ) < sizeof( prefixString ) );
2143         *s = '\0';
2144 
2145         // Build a hex string with a optional spaces after every 1, 2, and/or 4 bytes to make it easier to read.
2146         // Optionally pads the hex string with space to fill the full 16 byte range (so it lines up).
2147 
2148         s = hexString;
2149         chunkSize = ( inDataSize < 16 ) ? inDataSize : 16;
2150         n = ( inFlags & kDebugFlagsNo16ByteHexPad ) ? chunkSize : 16;
2151         for( i = 0; i < n; ++i )
2152         {
2153             if( ( inFlags & kDebugFlags8BitSeparator ) && ( i > 0 ) )
2154             {
2155                 *s++ = ' ';
2156             }
2157             if( ( inFlags & kDebugFlags16BitSeparator ) && ( i > 0 ) && ( ( i % 2 ) == 0 ) )
2158             {
2159                 *s++ = ' ';
2160             }
2161             if( !( inFlags & kDebugFlagsNo32BitSeparator ) && ( i > 0 ) && ( ( i % 4 ) == 0 ) )
2162             {
2163                 *s++ = ' ';
2164             }
2165             if( i < chunkSize )
2166             {
2167                 *s++ = kHexChars[ src[ i ] >> 4   ];
2168                 *s++ = kHexChars[ src[ i ] &  0xF ];
2169             }
2170             else
2171             {
2172                 *s++ = ' ';
2173                 *s++ = ' ';
2174             }
2175         }
2176         check( ( (size_t)( s - hexString ) ) < sizeof( hexString ) );
2177         *s = '\0';
2178 
2179         // Build a string with the ASCII version of the data (replaces non-printable characters with '^').
2180         // Optionally pads the string with '`' to fill the full 16 byte range (so it lines up).
2181 
2182         s = asciiString;
2183         if( !( inFlags & kDebugFlagsNoASCII ) )
2184         {
2185             *s++ = ' ';
2186             *s++ = '|';
2187             for( i = 0; i < n; ++i )
2188             {
2189                 if( i < chunkSize )
2190                 {
2191                     c = src[ i ];
2192                     if( !DebugIsPrint( c ) )
2193                     {
2194                         c = '^';
2195                     }
2196                 }
2197                 else
2198                 {
2199                     c = '`';
2200                 }
2201                 *s++ = (char) c;
2202             }
2203             *s++ = '|';
2204             check( ( (size_t)( s - asciiString ) ) < sizeof( asciiString ) );
2205         }
2206         *s = '\0';
2207 
2208         // Build a string indicating how bytes are in the hex dump. Only printed on the first line.
2209 
2210         s = byteCountString;
2211         if( !( inFlags & kDebugFlagsNoByteCount ) )
2212         {
2213             if( src == start )
2214             {
2215                 s += DebugSNPrintF( s, sizeof( byteCountString ), " (%d bytes)", (int) inDataSize );
2216             }
2217         }
2218         check( ( (size_t)( s - byteCountString ) ) < sizeof( byteCountString ) );
2219         *s = '\0';
2220 
2221         // Build the entire line from all the pieces we've previously built.
2222 
2223         if( outBuffer )
2224         {
2225             if( src == start )
2226             {
2227                 dst += DebugSNPrintF( dst, (size_t)( end - dst ),
2228                                       "%*s" // Indention
2229                                       "%s" // Separator (only if needed)
2230                                       "%s" // Prefix
2231                                       "%-*.*s" // Label
2232                                       "%s" // Separator
2233                                       "%s" // Hex
2234                                       "%s" // ASCII
2235                                       "%s" // Byte Count
2236                                       "%s", // Newline
2237                                       inIndent, "",
2238                                       ( src != start ) ? separator : "",
2239                                       prefixString,
2240                                       width, (int) inLabelSize, inLabel ? inLabel : "",
2241                                       ( width > 0 ) ? " " : "",
2242                                       hexString,
2243                                       asciiString,
2244                                       byteCountString,
2245                                       newline );
2246             }
2247             else
2248             {
2249                 dst += DebugSNPrintF( dst, (size_t)( end - dst ),
2250                                       "%*s" // Indention
2251                                       "%s" // Separator (only if needed)
2252                                       "%s" // Prefix
2253                                       "%*s" // Label Spacing
2254                                       "%s" // Separator
2255                                       "%s" // Hex
2256                                       "%s" // ASCII
2257                                       "%s" // Byte Count
2258                                       "%s", // Newline
2259                                       inIndent, "",
2260                                       ( src != start ) ? separator : "",
2261                                       prefixString,
2262                                       width, "",
2263                                       ( width > 0 ) ? " " : "",
2264                                       hexString,
2265                                       asciiString,
2266                                       byteCountString,
2267                                       newline );
2268             }
2269         }
2270         else
2271         {
2272             if( src == start )
2273             {
2274                 dst += DebugPrintF( inLevel,
2275                                     "%*s" // Indention
2276                                     "%s" // Separator (only if needed)
2277                                     "%s" // Prefix
2278                                     "%-*.*s" // Label
2279                                     "%s" // Separator
2280                                     "%s" // Hex
2281                                     "%s" // ASCII
2282                                     "%s" // Byte Count
2283                                     "%s", // Newline
2284                                     inIndent, "",
2285                                     ( src != start ) ? separator : "",
2286                                     prefixString,
2287                                     width, (int) inLabelSize, inLabel,
2288                                     ( width > 0 ) ? " " : "",
2289                                     hexString,
2290                                     asciiString,
2291                                     byteCountString,
2292                                     newline );
2293             }
2294             else
2295             {
2296                 dst += DebugPrintF( inLevel,
2297                                     "%*s" // Indention
2298                                     "%s" // Separator (only if needed)
2299                                     "%s" // Prefix
2300                                     "%*s" // Label Spacing
2301                                     "%s" // Separator
2302                                     "%s" // Hex
2303                                     "%s" // ASCII
2304                                     "%s" // Byte Count
2305                                     "%s", // Newline
2306                                     inIndent, "",
2307                                     ( src != start ) ? separator : "",
2308                                     prefixString,
2309                                     width, "",
2310                                     ( width > 0 ) ? " " : "",
2311                                     hexString,
2312                                     asciiString,
2313                                     byteCountString,
2314                                     newline );
2315             }
2316         }
2317 
2318         // Move to the next chunk. Exit if there is no more data.
2319 
2320         offset      += (int) chunkSize;
2321         src         += chunkSize;
2322         inDataSize  -= chunkSize;
2323         if( inDataSize == 0 )
2324         {
2325             break;
2326         }
2327     }
2328 
2329     // Note: The "dst - outBuffer" size calculation works even if "outBuffer" is NULL because it's all relative.
2330 
2331     return( (size_t)( dst - outBuffer ) );
2332 }
2333 
2334 //===========================================================================================================================
2335 //	DebugNumVersionToString
2336 //===========================================================================================================================
2337 
DebugNumVersionToString(uint32_t inVersion,char * inString)2338 static char *   DebugNumVersionToString( uint32_t inVersion, char *inString )
2339 {
2340     char *      s;
2341     uint8_t majorRev;
2342     uint8_t minor;
2343     uint8_t bugFix;
2344     uint8_t stage;
2345     uint8_t revision;
2346 
2347     check( inString );
2348 
2349     majorRev    = (uint8_t)( ( inVersion >> 24 ) & 0xFF );
2350     minor       = (uint8_t)( ( inVersion >> 20 ) & 0x0F );
2351     bugFix      = (uint8_t)( ( inVersion >> 16 ) & 0x0F );
2352     stage       = (uint8_t)( ( inVersion >>  8 ) & 0xFF );
2353     revision    = (uint8_t)(   inVersion         & 0xFF );
2354 
2355     // Convert the major, minor, and bugfix numbers.
2356 
2357     s  = inString;
2358     s += sprintf( s, "%u", majorRev );
2359     s += sprintf( s, ".%u", minor );
2360     if( bugFix != 0 )
2361     {
2362         s += sprintf( s, ".%u", bugFix );
2363     }
2364 
2365     // Convert the version stage and non-release revision number.
2366 
2367     switch( stage )
2368     {
2369     case kVersionStageDevelopment:
2370         s += sprintf( s, "d%u", revision );
2371         break;
2372 
2373     case kVersionStageAlpha:
2374         s += sprintf( s, "a%u", revision );
2375         break;
2376 
2377     case kVersionStageBeta:
2378         s += sprintf( s, "b%u", revision );
2379         break;
2380 
2381     case kVersionStageFinal:
2382 
2383         // A non-release revision of zero is a special case indicating the software is GM (at the golden master
2384         // stage) and therefore, the non-release revision should not be added to the string.
2385 
2386         if( revision != 0 )
2387         {
2388             s += sprintf( s, "f%u", revision );
2389         }
2390         break;
2391 
2392     default:
2393         dlog( kDebugLevelError, "invalid NumVersion stage (0x%02X)\n", stage );
2394         break;
2395     }
2396     return( inString );
2397 }
2398 
2399 //===========================================================================================================================
2400 //	DebugTaskLevel
2401 //===========================================================================================================================
2402 
DebugTaskLevel(void)2403 DEBUG_EXPORT uint32_t   DebugTaskLevel( void )
2404 {
2405     uint32_t level;
2406 
2407     level = 0;
2408 
2409     return( level );
2410 }
2411 
2412 #if ( TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE )
2413 //===========================================================================================================================
2414 //	DebugWinEnableConsole
2415 //===========================================================================================================================
2416 
2417 #pragma warning( disable:4311 )
2418 
DebugWinEnableConsole(void)2419 static void DebugWinEnableConsole( void )
2420 {
2421     static bool sConsoleEnabled = false;
2422     BOOL result;
2423     int fileHandle;
2424     FILE *          file;
2425     int err;
2426 
2427     if( sConsoleEnabled )
2428     {
2429         goto exit;
2430     }
2431 
2432     // Create console window.
2433 
2434     result = AllocConsole();
2435     require_quiet( result, exit );
2436 
2437     // Redirect stdin to the console stdin.
2438 
2439     fileHandle = _open_osfhandle( (long) GetStdHandle( STD_INPUT_HANDLE ), _O_TEXT );
2440 
2441     #if ( defined( __MWERKS__ ) )
2442     file = __handle_reopen( (unsigned long) fileHandle, "r", stdin );
2443     require_quiet( file, exit );
2444     #else
2445     file = _fdopen( fileHandle, "r" );
2446     require_quiet( file, exit );
2447 
2448     *stdin = *file;
2449     #endif
2450 
2451     err = setvbuf( stdin, NULL, _IONBF, 0 );
2452     require_noerr_quiet( err, exit );
2453 
2454     // Redirect stdout to the console stdout.
2455 
2456     fileHandle = _open_osfhandle( (long) GetStdHandle( STD_OUTPUT_HANDLE ), _O_TEXT );
2457 
2458     #if ( defined( __MWERKS__ ) )
2459     file = __handle_reopen( (unsigned long) fileHandle, "w", stdout );
2460     require_quiet( file, exit );
2461     #else
2462     file = _fdopen( fileHandle, "w" );
2463     require_quiet( file, exit );
2464 
2465     *stdout = *file;
2466     #endif
2467 
2468     err = setvbuf( stdout, NULL, _IONBF, 0 );
2469     require_noerr_quiet( err, exit );
2470 
2471     // Redirect stderr to the console stdout.
2472 
2473     fileHandle = _open_osfhandle( (long) GetStdHandle( STD_OUTPUT_HANDLE ), _O_TEXT );
2474 
2475     #if ( defined( __MWERKS__ ) )
2476     file = __handle_reopen( (unsigned long) fileHandle, "w", stderr );
2477     require_quiet( file, exit );
2478     #else
2479     file = _fdopen( fileHandle, "w" );
2480     require_quiet( file, exit );
2481 
2482     *stderr = *file;
2483     #endif
2484 
2485     err = setvbuf( stderr, NULL, _IONBF, 0 );
2486     require_noerr_quiet( err, exit );
2487 
2488     sConsoleEnabled = true;
2489 
2490 exit:
2491     return;
2492 }
2493 
2494 #pragma warning( default:4311 )
2495 
2496 #endif  // TARGET_OS_WIN32 && !TARGET_OS_WINDOWS_CE
2497 
2498 #if ( TARGET_OS_WIN32 )
2499 //===========================================================================================================================
2500 //	DebugWinCharToTCharString
2501 //===========================================================================================================================
2502 
2503 static TCHAR *
DebugWinCharToTCharString(const char * inCharString,size_t inCharCount,TCHAR * outTCharString,size_t inTCharCountMax,size_t * outTCharCount)2504 DebugWinCharToTCharString(
2505     const char *    inCharString,
2506     size_t inCharCount,
2507     TCHAR *         outTCharString,
2508     size_t inTCharCountMax,
2509     size_t *        outTCharCount )
2510 {
2511     const char *        src;
2512     TCHAR *             dst;
2513     TCHAR *             end;
2514 
2515     if( inCharCount == kSizeCString )
2516     {
2517         inCharCount = strlen( inCharString );
2518     }
2519     src = inCharString;
2520     dst = outTCharString;
2521     if( inTCharCountMax > 0 )
2522     {
2523         inTCharCountMax -= 1;
2524         if( inTCharCountMax > inCharCount )
2525         {
2526             inTCharCountMax = inCharCount;
2527         }
2528 
2529         end = dst + inTCharCountMax;
2530         while( dst < end )
2531         {
2532             *dst++ = (TCHAR) *src++;
2533         }
2534         *dst = 0;
2535     }
2536     if( outTCharCount )
2537     {
2538         *outTCharCount = (size_t)( dst - outTCharString );
2539     }
2540     return( outTCharString );
2541 }
2542 #endif
2543 
2544 #if 0
2545 #pragma mark -
2546 #pragma mark == Debugging ==
2547 #endif
2548 
2549 //===========================================================================================================================
2550 //	DebugServicesTest
2551 //===========================================================================================================================
2552 
DebugServicesTest(void)2553 DEBUG_EXPORT OSStatus   DebugServicesTest( void )
2554 {
2555     OSStatus err;
2556     char s[ 512 ];
2557     uint8_t *       p;
2558     uint8_t data[] =
2559     {
2560         0x11, 0x22, 0x33, 0x44,
2561         0x55, 0x66,
2562         0x77, 0x88, 0x99, 0xAA,
2563         0xBB, 0xCC, 0xDD,
2564         0xEE,
2565         0xFF,
2566         0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
2567         0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xA0,
2568         0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, 0x81, 0x91, 0xA1
2569     };
2570 
2571     debug_initialize( kDebugOutputTypeMetaConsole );
2572 
2573     // check's
2574 
2575     check( 0 && "SHOULD SEE: check" );
2576     check( 1 && "SHOULD *NOT* SEE: check (valid)" );
2577     check_string( 0, "SHOULD SEE: check_string" );
2578     check_string( 1, "SHOULD *NOT* SEE: check_string (valid)" );
2579     check_noerr( -123 );
2580     check_noerr( 10038 );
2581     check_noerr( 22 );
2582     check_noerr( 0 );
2583     check_noerr_string( -6712, "SHOULD SEE: check_noerr_string" );
2584     check_noerr_string( 0, "SHOULD *NOT* SEE: check_noerr_string (valid)" );
2585     check_translated_errno( 0 >= 0 && "SHOULD *NOT* SEE", -384, -999 );
2586     check_translated_errno( -1 >= 0 && "SHOULD SEE", -384, -999 );
2587     check_translated_errno( -1 >= 0 && "SHOULD SEE", 0, -999 );
2588     check_ptr_overlap( "SHOULD *NOT* SEE" ? 10 : 0, 10, 22, 10 );
2589     check_ptr_overlap( "SHOULD SEE" ? 10 : 0, 10,  5, 10 );
2590     check_ptr_overlap( "SHOULD SEE" ? 10 : 0, 10, 12,  6 );
2591     check_ptr_overlap( "SHOULD SEE" ? 12 : 0,  6, 10, 10 );
2592     check_ptr_overlap( "SHOULD SEE" ? 12 : 0, 10, 10, 10 );
2593     check_ptr_overlap( "SHOULD *NOT* SEE" ? 22 : 0, 10, 10, 10 );
2594     check_ptr_overlap( "SHOULD *NOT* SEE" ? 10 : 0, 10, 20, 10 );
2595     check_ptr_overlap( "SHOULD *NOT* SEE" ? 20 : 0, 10, 10, 10 );
2596 
2597     // require's
2598 
2599     require( 0 && "SHOULD SEE", require1 );
2600     { err = kResponseErr; goto exit; }
2601 require1:
2602     require( 1 && "SHOULD *NOT* SEE", require2 );
2603     goto require2Good;
2604 require2:
2605     { err = kResponseErr; goto exit; }
2606 require2Good:
2607     require_string( 0 && "SHOULD SEE", require3, "SHOULD SEE: require_string" );
2608     { err = kResponseErr; goto exit; }
2609 require3:
2610     require_string( 1 && "SHOULD *NOT* SEE", require4, "SHOULD *NOT* SEE: require_string (valid)" );
2611     goto require4Good;
2612 require4:
2613     { err = kResponseErr; goto exit; }
2614 require4Good:
2615     require_quiet( 0 && "SHOULD SEE", require5 );
2616     { err = kResponseErr; goto exit; }
2617 require5:
2618     require_quiet( 1 && "SHOULD *NOT* SEE", require6 );
2619     goto require6Good;
2620 require6:
2621     { err = kResponseErr; goto exit; }
2622 require6Good:
2623     require_noerr( -1, require7 );
2624     { err = kResponseErr; goto exit; }
2625 require7:
2626     require_noerr( 0, require8 );
2627     goto require8Good;
2628 require8:
2629     { err = kResponseErr; goto exit; }
2630 require8Good:
2631     require_noerr_string( -2, require9, "SHOULD SEE: require_noerr_string");
2632     { err = kResponseErr; goto exit; }
2633 require9:
2634     require_noerr_string( 0, require10, "SHOULD *NOT* SEE: require_noerr_string (valid)" );
2635     goto require10Good;
2636 require10:
2637     { err = kResponseErr; goto exit; }
2638 require10Good:
2639     require_noerr_action_string( -3, require11, dlog( kDebugLevelMax, "action 1 (expected)\n" ), "require_noerr_action_string" );
2640     { err = kResponseErr; goto exit; }
2641 require11:
2642     require_noerr_action_string( 0, require12, dlog( kDebugLevelMax, "action 2\n" ), "require_noerr_action_string (valid)" );
2643     goto require12Good;
2644 require12:
2645     { err = kResponseErr; goto exit; }
2646 require12Good:
2647     require_noerr_quiet( -4, require13 );
2648     { err = kResponseErr; goto exit; }
2649 require13:
2650     require_noerr_quiet( 0, require14 );
2651     goto require14Good;
2652 require14:
2653     { err = kResponseErr; goto exit; }
2654 require14Good:
2655     require_noerr_action( -5, require15, dlog( kDebugLevelMax, "SHOULD SEE: action 3 (expected)\n" ) );
2656     { err = kResponseErr; goto exit; }
2657 require15:
2658     require_noerr_action( 0, require16, dlog( kDebugLevelMax, "SHOULD *NOT* SEE: action 4\n" ) );
2659     goto require16Good;
2660 require16:
2661     { err = kResponseErr; goto exit; }
2662 require16Good:
2663     require_noerr_action_quiet( -4, require17, dlog( kDebugLevelMax, "SHOULD SEE: action 5 (expected)\n" ) );
2664     { err = kResponseErr; goto exit; }
2665 require17:
2666     require_noerr_action_quiet( 0, require18, dlog( kDebugLevelMax, "SHOULD *NOT* SEE: action 6\n" ) );
2667     goto require18Good;
2668 require18:
2669     { err = kResponseErr; goto exit; }
2670 require18Good:
2671     require_action( 0 && "SHOULD SEE", require19, dlog( kDebugLevelMax, "SHOULD SEE: action 7 (expected)\n" ) );
2672     { err = kResponseErr; goto exit; }
2673 require19:
2674     require_action( 1 && "SHOULD *NOT* SEE", require20, dlog( kDebugLevelMax, "SHOULD *NOT* SEE: action 8\n" ) );
2675     goto require20Good;
2676 require20:
2677     { err = kResponseErr; goto exit; }
2678 require20Good:
2679     require_action_quiet( 0, require21, dlog( kDebugLevelMax, "SHOULD SEE: action 9 (expected)\n" ) );
2680     { err = kResponseErr; goto exit; }
2681 require21:
2682     require_action_quiet( 1, require22, dlog( kDebugLevelMax, "SHOULD *NOT* SEE: action 10\n" ) );
2683     goto require22Good;
2684 require22:
2685     { err = kResponseErr; goto exit; }
2686 require22Good:
2687     require_action_string( 0, require23, dlog( kDebugLevelMax, "SHOULD SEE: action 11 (expected)\n" ), "SHOULD SEE: require_action_string" );
2688     { err = kResponseErr; goto exit; }
2689 require23:
2690     require_action_string( 1, require24, dlog( kDebugLevelMax, "SHOULD *NOT* SEE: action 12\n" ), "SHOULD *NOT* SEE: require_action_string" );
2691     goto require24Good;
2692 require24:
2693     { err = kResponseErr; goto exit; }
2694 require24Good:
2695 
2696 #if ( defined( __MWERKS__ )  )
2697     #if ( defined( __cplusplus ) && __option( exceptions ) )
2698         #define COMPILER_HAS_EXCEPTIONS     1
2699     #else
2700         #define COMPILER_HAS_EXCEPTIONS     0
2701     #endif
2702 #else
2703     #if ( defined( __cplusplus ) )
2704         #define COMPILER_HAS_EXCEPTIONS     1
2705     #else
2706         #define COMPILER_HAS_EXCEPTIONS     0
2707     #endif
2708 #endif
2709 
2710 #if ( COMPILER_HAS_EXCEPTIONS )
2711     try
2712     {
2713         require_throw( 1 && "SHOULD *NOT* SEE" );
2714         require_throw( 0 && "SHOULD SEE" );
2715     }
2716     catch(... )
2717     {
2718         goto require26Good;
2719     }
2720     { err = kResponseErr; goto exit; }
2721 require26Good:
2722 #endif
2723 
2724     // translate_errno
2725 
2726     err = translate_errno( 1 != -1, -123, -567 );
2727     require( ( err == 0 ) && "SHOULD *NOT* SEE", exit );
2728 
2729     err = translate_errno( -1 != -1, -123, -567 );
2730     require( ( err == -123 ) && "SHOULD *NOT* SEE", exit );
2731 
2732     err = translate_errno( -1 != -1, 0, -567 );
2733     require( ( err == -567 ) && "SHOULD *NOT* SEE", exit );
2734 
2735     // debug_string
2736 
2737     debug_string( "debug_string" );
2738 
2739     // DebugSNPrintF
2740 
2741     DebugSNPrintF( s, sizeof( s ), "%d", 1234 );
2742     require_action( strcmp( s, "1234" ) == 0, exit, err = -1 );
2743 
2744     DebugSNPrintF( s, sizeof( s ), "%X", 0x2345 );
2745     require_action( strcmp( s, "2345" ) == 0, exit, err = -1 );
2746 
2747     DebugSNPrintF( s, sizeof( s ), "%#s", "\05test" );
2748     require_action( strcmp( s, "test" ) == 0, exit, err = -1 );
2749 
2750     DebugSNPrintF( s, sizeof( s ), "%##s", "\03www\05apple\03com" );
2751     require_action( strcmp( s, "www.apple.com." ) == 0, exit, err = -1 );
2752 
2753     DebugSNPrintF( s, sizeof( s ), "%ld", (long) INT32_C( 2147483647 ) );
2754     require_action( strcmp( s, "2147483647" ) == 0, exit, err = -1 );
2755 
2756     DebugSNPrintF( s, sizeof( s ), "%lu", (unsigned long) UINT32_C( 4294967295 ) );
2757     require_action( strcmp( s, "4294967295" ) == 0, exit, err = -1 );
2758 
2759     #if ( TYPE_LONGLONG_NATIVE )
2760     DebugSNPrintF( s, sizeof( s ), "%lld", (long_long_compat) INT64_C( 9223372036854775807 ) );
2761     require_action( strcmp( s, "9223372036854775807" ) == 0, exit, err = -1 );
2762 
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 ), "%llu", (unsigned_long_long_compat) UINT64_C( 18446744073709551615 ) );
2767     require_action( strcmp( s, "18446744073709551615" ) == 0, exit, err = -1 );
2768     #endif
2769 
2770     DebugSNPrintF( s, sizeof( s ), "%lb", (unsigned long) binary_32( 01111011, 01111011, 01111011, 01111011 ) );
2771     require_action( strcmp( s, "1111011011110110111101101111011" ) == 0, exit, err = -1 );
2772 
2773     DebugSNPrintF( s, sizeof( s ), "%C", 0x41624364 );  // 'AbCd'
2774     require_action( strcmp( s, "AbCd" ) == 0, exit, err = -1 );
2775 
2776     #if ( defined( MDNS_DEBUGMSGS ) )
2777     {
2778         mDNSAddr maddr;
2779 
2780         memset( &maddr, 0, sizeof( maddr ) );
2781         maddr.type = mDNSAddrType_IPv4;
2782         maddr.ip.v4.b[ 0 ] = 127;
2783         maddr.ip.v4.b[ 1 ] = 0;
2784         maddr.ip.v4.b[ 2 ] = 0;
2785         maddr.ip.v4.b[ 3 ] = 1;
2786         DebugSNPrintF( s, sizeof( s ), "%#a", &maddr );
2787         require_action( strcmp( s, "127.0.0.1" ) == 0, exit, err = -1 );
2788 
2789         memset( &maddr, 0, sizeof( maddr ) );
2790         maddr.type = mDNSAddrType_IPv6;
2791         maddr.ip.v6.b[  0 ] = 0xFE;
2792         maddr.ip.v6.b[  1 ] = 0x80;
2793         maddr.ip.v6.b[ 15 ] = 0x01;
2794         DebugSNPrintF( s, sizeof( s ), "%#a", &maddr );
2795         require_action( strcmp( s, "FE80:0000:0000:0000:0000:0000:0000:0001" ) == 0, exit, err = -1 );
2796     }
2797     #endif
2798 
2799     #if ( AF_INET )
2800     {
2801         struct sockaddr_in sa4;
2802 
2803         memset( &sa4, 0, sizeof( sa4 ) );
2804         sa4.sin_family      = AF_INET;
2805         p                   = (uint8_t *) &sa4.sin_port;
2806         p[ 0 ]              = (uint8_t)( ( 80 >> 8 ) & 0xFF );
2807         p[ 1 ]              = (uint8_t)(   80        & 0xFF );
2808         p                   = (uint8_t *) &sa4.sin_addr.s_addr;
2809         p[ 0 ]              = (uint8_t)( ( INADDR_LOOPBACK >> 24 ) & 0xFF );
2810         p[ 1 ]              = (uint8_t)( ( INADDR_LOOPBACK >> 16 ) & 0xFF );
2811         p[ 2 ]              = (uint8_t)( ( INADDR_LOOPBACK >>  8 ) & 0xFF );
2812         p[ 3 ]              = (uint8_t)(   INADDR_LOOPBACK         & 0xFF );
2813         DebugSNPrintF( s, sizeof( s ), "%##a", &sa4 );
2814         require_action( strcmp( s, "127.0.0.1:80" ) == 0, exit, err = -1 );
2815     }
2816     #endif
2817 
2818     #if ( AF_INET6 )
2819     {
2820         struct sockaddr_in6 sa6;
2821 
2822         memset( &sa6, 0, sizeof( sa6 ) );
2823         sa6.sin6_family             = AF_INET6;
2824         p                           = (uint8_t *) &sa6.sin6_port;
2825         p[ 0 ]                      = (uint8_t)( ( 80 >> 8 ) & 0xFF );
2826         p[ 1 ]                      = (uint8_t)(   80        & 0xFF );
2827         sa6.sin6_addr.s6_addr[  0 ] = 0xFE;
2828         sa6.sin6_addr.s6_addr[  1 ] = 0x80;
2829         sa6.sin6_addr.s6_addr[ 15 ] = 0x01;
2830         sa6.sin6_scope_id           = 2;
2831         DebugSNPrintF( s, sizeof( s ), "%##a", &sa6 );
2832         require_action( strcmp( s, "[FE80:0000:0000:0000:0000:0000:0000:0001%2]:80" ) == 0, exit, err = -1 );
2833     }
2834     #endif
2835 
2836     // Unicode
2837 
2838     DebugSNPrintF(s, sizeof(s), "%.*s", 4, "tes" );
2839     require_action( strcmp( s, "tes" ) == 0, exit, err = kResponseErr );
2840 
2841     DebugSNPrintF(s, sizeof(s), "%.*s", 4, "test" );
2842     require_action( strcmp( s, "test" ) == 0, exit, err = kResponseErr );
2843 
2844     DebugSNPrintF(s, sizeof(s), "%.*s", 4, "testing" );
2845     require_action( strcmp( s, "test" ) == 0, exit, err = kResponseErr );
2846 
2847     DebugSNPrintF(s, sizeof(s), "%.*s", 4, "te\xC3\xA9" );
2848     require_action( strcmp( s, "te\xC3\xA9" ) == 0, exit, err = kResponseErr );
2849 
2850     DebugSNPrintF(s, sizeof(s), "%.*s", 4, "te\xC3\xA9ing" );
2851     require_action( strcmp( s, "te\xC3\xA9" ) == 0, exit, err = kResponseErr );
2852 
2853     DebugSNPrintF(s, sizeof(s), "%.*s", 4, "tes\xC3\xA9ing" );
2854     require_action( strcmp( s, "tes" ) == 0, exit, err = kResponseErr );
2855 
2856     DebugSNPrintF(s, sizeof(s), "%.*s", 4, "t\xed\x9f\xbf" );
2857     require_action( strcmp( s, "t\xed\x9f\xbf" ) == 0, exit, err = kResponseErr );
2858 
2859     DebugSNPrintF(s, sizeof(s), "%.*s", 4, "t\xed\x9f\xbfing" );
2860     require_action( strcmp( s, "t\xed\x9f\xbf" ) == 0, exit, err = kResponseErr );
2861 
2862     DebugSNPrintF(s, sizeof(s), "%.*s", 4, "te\xed\x9f\xbf" );
2863     require_action( strcmp( s, "te" ) == 0, exit, err = kResponseErr );
2864 
2865     DebugSNPrintF(s, sizeof(s), "%.*s", 4, "te\xed\x9f\xbfing" );
2866     require_action( strcmp( s, "te" ) == 0, exit, err = kResponseErr );
2867 
2868     DebugSNPrintF(s, sizeof(s), "%.*s", 7, "te\xC3\xA9\xed\x9f\xbfing" );
2869     require_action( strcmp( s, "te\xC3\xA9\xed\x9f\xbf" ) == 0, exit, err = kResponseErr );
2870 
2871     DebugSNPrintF(s, sizeof(s), "%.*s", 6, "te\xC3\xA9\xed\x9f\xbfing" );
2872     require_action( strcmp( s, "te\xC3\xA9" ) == 0, exit, err = kResponseErr );
2873 
2874     DebugSNPrintF(s, sizeof(s), "%.*s", 5, "te\xC3\xA9\xed\x9f\xbfing" );
2875     require_action( strcmp( s, "te\xC3\xA9" ) == 0, exit, err = kResponseErr );
2876 
2877     #if ( TARGET_RT_BIG_ENDIAN )
2878     DebugSNPrintF( s, sizeof( s ), "%S", "\x00" "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" "\x00" );
2879     require_action( strcmp( s, "abcd" ) == 0, exit, err = -1 );
2880     #else
2881     DebugSNPrintF( s, sizeof( s ), "%S", "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" "\x00" "\x00" );
2882     require_action( strcmp( s, "abcd" ) == 0, exit, err = -1 );
2883     #endif
2884 
2885     DebugSNPrintF( s, sizeof( s ), "%S",
2886                    "\xFE\xFF" "\x00" "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" "\x00" ); // Big Endian BOM
2887     require_action( strcmp( s, "abcd" ) == 0, exit, err = -1 );
2888 
2889     DebugSNPrintF( s, sizeof( s ), "%S",
2890                    "\xFF\xFE" "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" "\x00" "\x00" ); // Little Endian BOM
2891     require_action( strcmp( s, "abcd" ) == 0, exit, err = -1 );
2892 
2893     DebugSNPrintF( s, sizeof( s ), "%#S", "\x00" "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" "\x00" );  // Big Endian
2894     require_action( strcmp( s, "abcd" ) == 0, exit, err = -1 );
2895 
2896     DebugSNPrintF( s, sizeof( s ), "%##S", "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" "\x00" "\x00" ); // Little Endian
2897     require_action( strcmp( s, "abcd" ) == 0, exit, err = -1 );
2898 
2899     DebugSNPrintF( s, sizeof( s ), "%.*S",
2900                    4, "\xFE\xFF" "\x00" "a" "\x00" "b" "\x00" "c" "\x00" "d" ); // Big Endian BOM
2901     require_action( strcmp( s, "abc" ) == 0, exit, err = -1 );
2902 
2903     DebugSNPrintF( s, sizeof( s ), "%.*S",
2904                    4, "\xFF\xFE" "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" ); // Little Endian BOM
2905     require_action( strcmp( s, "abc" ) == 0, exit, err = -1 );
2906 
2907     #if ( TARGET_RT_BIG_ENDIAN )
2908     DebugSNPrintF( s, sizeof( s ), "%.*S", 3, "\x00" "a" "\x00" "b" "\x00" "c" "\x00" "d" );
2909     require_action( strcmp( s, "abc" ) == 0, exit, err = -1 );
2910     #else
2911     DebugSNPrintF( s, sizeof( s ), "%.*S", 3, "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" );
2912     require_action( strcmp( s, "abc" ) == 0, exit, err = -1 );
2913     #endif
2914 
2915     DebugSNPrintF( s, sizeof( s ), "%#.*S", 3, "\x00" "a" "\x00" "b" "\x00" "c" "\x00" "d" );   // Big Endian
2916     require_action( strcmp( s, "abc" ) == 0, exit, err = -1 );
2917 
2918     DebugSNPrintF( s, sizeof( s ), "%##.*S", 3, "a" "\x00" "b" "\x00" "c" "\x00" "d" "\x00" );  // Little Endian
2919     require_action( strcmp( s, "abc" ) == 0, exit, err = -1 );
2920 
2921     // Misc
2922 
2923     DebugSNPrintF( s, sizeof( s ), "%U", "\x10\xb8\xa7\x6b" "\xad\x9d" "\xd1\x11" "\x80\xb4" "\x00\xc0\x4f\xd4\x30\xc8" );
2924     require_action( strcmp( s, "6ba7b810-9dad-11d1-80b4-00c04fd430c8" ) == 0, exit, err = -1 );
2925 
2926     DebugSNPrintF( s, sizeof( s ), "%m", 0 );
2927     require_action( strcmp( s, "no error" ) == 0, exit, err = -1 );
2928 
2929     DebugSNPrintF( s, sizeof( s ), "%lm", (long) 0 );
2930     require_action( strcmp( s, "no error" ) == 0, exit, err = -1 );
2931 
2932     DebugSNPrintF( s, sizeof( s ), "\"%H\"", "\x6b\xa7\xb8\x10\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8", 16, 16 );
2933     DebugPrintF( kDebugLevelMax, "%s\n\n", s );
2934 
2935     DebugSNPrintF( s, sizeof( s ), "\"%H\"",
2936                    "\x6b\xa7\xb8\x10\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8"
2937                    "\x6b\xa7\xb8\x10\x9d\xad\x11\xd1\x80\xb4\x00\xc0\x4f\xd4\x30\xc8",
2938                    32, 32 );
2939     DebugPrintF( kDebugLevelMax, "%s\n\n", s );
2940 
2941     DebugSNPrintF( s, sizeof( s ), "\"%H\"", "\x6b\xa7", 2, 2 );
2942     DebugPrintF( kDebugLevelMax, "%s\n\n", s );
2943 
2944     // Hex Dumps
2945 
2946     s[ 0 ] = '\0';
2947     DebugHexDump( kDebugLevelMax, 0, "My Label", kSizeCString, 0, NULL, 0, data, data, sizeof( data ),
2948                   kDebugFlagsNone, s, sizeof( s ) );
2949     DebugPrintF( kDebugLevelMax, "%s\n", s );
2950 
2951     s[ 0 ] = '\0';
2952     DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, data, data, sizeof( data ),
2953                   kDebugFlagsNoAddress | kDebugFlagsNoOffset, s, sizeof( s ) );
2954     DebugPrintF( kDebugLevelMax, "%s\n", s );
2955 
2956     s[ 0 ] = '\0';
2957     DebugHexDump( kDebugLevelMax, 0, "My Label", kSizeCString, 0, NULL, 0, data, data, sizeof( data ),
2958                   kDebugFlagsNoAddress | kDebugFlagsNoOffset, s, sizeof( s ) );
2959     DebugPrintF( kDebugLevelMax, "%s\n", s );
2960 
2961     s[ 0 ] = '\0';
2962     DebugHexDump( kDebugLevelMax, 0, "My Label", kSizeCString, 0, NULL, 0, data, data, sizeof( data ),
2963                   kDebugFlagsNoAddress, s, sizeof( s ) );
2964     DebugPrintF( kDebugLevelMax, "%s\n", s );
2965 
2966     s[ 0 ] = '\0';
2967     DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, data, data, sizeof( data ),
2968                   kDebugFlagsNoOffset, s, sizeof( s ) );
2969     DebugPrintF( kDebugLevelMax, "%s\n", s );
2970 
2971     s[ 0 ] = '\0';
2972     DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, data, data, sizeof( data ),
2973                   kDebugFlagsNoAddress, s, sizeof( s ) );
2974     DebugPrintF( kDebugLevelMax, "%s\n", s );
2975 
2976     s[ 0 ] = '\0';
2977     DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, data, data, sizeof( data ),
2978                   kDebugFlagsNoOffset, s, sizeof( s ) );
2979     DebugPrintF( kDebugLevelMax, "%s\n", s );
2980 
2981     s[ 0 ] = '\0';
2982     DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, data, data, sizeof( data ),
2983                   kDebugFlagsNoByteCount, s, sizeof( s ) );
2984     DebugPrintF( kDebugLevelMax, "%s\n", s );
2985 
2986     s[ 0 ] = '\0';
2987     DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, "\x41\x62\x43\x64", "\x41\x62\x43\x64", 4,    // 'AbCd'
2988                   kDebugFlagsNoAddress | kDebugFlagsNoOffset | kDebugFlagsNoNewLine |
2989                   kDebugFlagsNo32BitSeparator | kDebugFlagsNo16ByteHexPad | kDebugFlagsNoByteCount,
2990                   s, sizeof( s ) );
2991     DebugPrintF( kDebugLevelMax, "%s\n", s );
2992 
2993     s[ 0 ] = '\0';
2994     DebugHexDump( kDebugLevelMax, 0, NULL, 0, 0, NULL, 0, data, data, sizeof( data ),
2995                   kDebugFlagsNoAddress | kDebugFlagsNoOffset | kDebugFlagsNoASCII | kDebugFlagsNoNewLine |
2996                   kDebugFlags16BitSeparator | kDebugFlagsNo32BitSeparator |
2997                   kDebugFlagsNo16ByteHexPad | kDebugFlagsNoByteCount, s, sizeof( s ) );
2998     DebugPrintF( kDebugLevelMax, "%s\n", s );
2999 
3000     s[ 0 ] = '\0';
3001     DebugHexDump( kDebugLevelMax, 8, NULL, 0, 0, NULL, 0, data, data, sizeof( data ), kDebugFlagsNone, s, sizeof( s ) );
3002     DebugPrintF( kDebugLevelMax, "%s\n", s );
3003 
3004     // dlog's
3005 
3006     dlog( kDebugLevelNotice, "dlog\n" );
3007     dlog( kDebugLevelNotice, "dlog integer: %d\n", 123 );
3008     dlog( kDebugLevelNotice, "dlog string:  \"%s\"\n", "test string" );
3009     dlogmem( kDebugLevelNotice, data, sizeof( data ) );
3010 
3011     // Done
3012 
3013     DebugPrintF( kDebugLevelMax, "\n\nALL TESTS DONE\n\n" );
3014     err = kNoErr;
3015 
3016 exit:
3017     if( err )
3018     {
3019         DebugPrintF( kDebugLevelMax, "\n\n### TEST FAILED ###\n\n" );
3020     }
3021     return( err );
3022 }
3023 
3024 #endif  // DEBUG
3025