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