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 
83 static 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 
149 static 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 
196 static bool									gDebugInitialized				= false;
197 static DebugOutputType						gDebugOutputType 				= kDebugOutputTypeNone;
198 static DebugLevel							gDebugPrintLevelMin				= kDebugLevelInfo;
199 static DebugLevel							gDebugPrintLevelMax				= kDebugLevelMax;
200 static DebugLevel							gDebugBreakLevel				= kDebugLevelAssert;
201 #if( DEBUG_CORE_SERVICE_ASSERTS_ENABLED )
202 	static DebugAssertOutputHandlerUPP		gDebugAssertOutputHandlerUPP	= NULL;
203 #endif
204 
205 // Custom
206 
207 static DebugOutputFunctionPtr				gDebugCustomOutputFunction 		= NULL;
208 static 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 
DebugInitialize(DebugOutputType inType,...)240 DEBUG_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 
394 exit:
395 	va_end( args );
396 	return( err );
397 }
398 
399 //===========================================================================================================================
400 //	DebugFinalize
401 //===========================================================================================================================
402 
DebugFinalize(void)403 DEBUG_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 
DebugGetProperty(DebugPropertyTag inTag,...)420 DEBUG_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 
DebugSetProperty(DebugPropertyTag inTag,...)459 DEBUG_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 
DebugPrintF(DebugLevel inLevel,const char * inFormat,...)503 DEBUG_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 
520 exit:
521 	return( n );
522 }
523 
524 //===========================================================================================================================
525 //	DebugPrintFVAList
526 //===========================================================================================================================
527 
DebugPrintFVAList(DebugLevel inLevel,const char * inFormat,va_list inArgs)528 DEBUG_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 
544 exit:
545 	return( n );
546 }
547 
548 //===========================================================================================================================
549 //	DebugPrint
550 //===========================================================================================================================
551 
DebugPrint(DebugLevel inLevel,char * inData,size_t inSize)552 static 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 
644 exit:
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 
657 DEBUG_EXPORT void
DebugPrintAssert(int_least32_t inErrorCode,const char * inAssertString,const char * inMessage,const char * inFilename,int_least32_t inLineNumber,const char * inFunction)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 
DebugFPrintFInit(DebugOutputTypeFlags inFlags,const char * inFilename)723 static 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 
759 exit:
760 	return( err );
761 }
762 
763 //===========================================================================================================================
764 //	DebugFPrintFPrint
765 //===========================================================================================================================
766 
DebugFPrintFPrint(char * inData,size_t inSize)767 static 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 
DebugiDebugInit(void)800 static 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;
818 exit:
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 
DebugiDebugPrint(char * inData,size_t inSize)835 static 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 
DebugKPrintFPrint(char * inData,size_t inSize)868 static 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 
DebugMacOSXIOLogPrint(char * inData,size_t inSize)881 static 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 
DebugMacOSXLogInit(void)894 static 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 
927 exit:
928 	if( bundle )
929 	{
930 		CFRelease( bundle );
931 	}
932 	return( err );
933 }
934 
935 //===========================================================================================================================
936 //	DebugMacOSXLogPrint
937 //===========================================================================================================================
938 
DebugMacOSXLogPrint(char * inData,size_t inSize)939 static 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 
DebugWindowsDebuggerPrint(char * inData,size_t inSize)953 void	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 
DebugWindowsEventLogInit(const char * inName,HMODULE inModule)993 static 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 
1049 exit:
1050 	if( key )
1051 	{
1052 		RegCloseKey( key );
1053 	}
1054 	return( err );
1055 }
1056 
1057 //===========================================================================================================================
1058 //	DebugWindowsEventLogPrint
1059 //===========================================================================================================================
1060 
DebugWindowsEventLogPrint(DebugLevel inLevel,char * inData,size_t inSize)1061 static 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 
1122 static pascal void
DebugAssertOutputHandler(OSType inComponentSignature,UInt32 inOptions,const char * inAssertString,const char * inExceptionString,const char * inErrorString,const char * inFileName,long inLineNumber,void * inValue,ConstStr255Param inOutputMsg)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 
DebugSNPrintF(char * sbuffer,size_t buflen,const char * fmt,...)1172 DEBUG_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 
DebugSNPrintFVAList(char * sbuffer,size_t buflen,const char * fmt,va_list arg)1188 DEBUG_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 
DebugGetErrorString(int_least32_t inErrorCode,char * inBuffer,size_t inBufferSize)1614 DEBUG_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 
2021 DEBUG_EXPORT size_t
DebugHexDump(DebugLevel inLevel,int inIndent,const char * inLabel,size_t inLabelSize,int inLabelMinWidth,const char * inType,size_t inTypeSize,const void * inDataStart,const void * inData,size_t inDataSize,DebugFlags inFlags,char * outBuffer,size_t inBufferSize)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 
DebugNumVersionToString(uint32_t inVersion,char * inString)2382 static 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 
DebugTaskLevel(void)2447 DEBUG_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 
DebugWinEnableConsole(void)2470 static 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 
2541 exit:
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 
2554 static TCHAR *
DebugWinCharToTCharString(const char * inCharString,size_t inCharCount,TCHAR * outTCharString,size_t inTCharCountMax,size_t * outTCharCount)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 
DebugServicesTest(void)2604 DEBUG_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; }
2652 require1:
2653 	require( 1 && "SHOULD *NOT* SEE", require2 );
2654 	goto require2Good;
2655 require2:
2656 	{ err = kResponseErr; goto exit; }
2657 require2Good:
2658 	require_string( 0 && "SHOULD SEE", require3, "SHOULD SEE: require_string" );
2659 	{ err = kResponseErr; goto exit; }
2660 require3:
2661 	require_string( 1 && "SHOULD *NOT* SEE", require4, "SHOULD *NOT* SEE: require_string (valid)" );
2662 	goto require4Good;
2663 require4:
2664 	{ err = kResponseErr; goto exit; }
2665 require4Good:
2666 	require_quiet( 0 && "SHOULD SEE", require5 );
2667 	{ err = kResponseErr; goto exit; }
2668 require5:
2669 	require_quiet( 1 && "SHOULD *NOT* SEE", require6 );
2670 	goto require6Good;
2671 require6:
2672 	{ err = kResponseErr; goto exit; }
2673 require6Good:
2674 	require_noerr( -1, require7 );
2675 	{ err = kResponseErr; goto exit; }
2676 require7:
2677 	require_noerr( 0, require8 );
2678 	goto require8Good;
2679 require8:
2680 	{ err = kResponseErr; goto exit; }
2681 require8Good:
2682 	require_noerr_string( -2, require9, "SHOULD SEE: require_noerr_string");
2683 	{ err = kResponseErr; goto exit; }
2684 require9:
2685 	require_noerr_string( 0, require10, "SHOULD *NOT* SEE: require_noerr_string (valid)" );
2686 	goto require10Good;
2687 require10:
2688 	{ err = kResponseErr; goto exit; }
2689 require10Good:
2690 	require_noerr_action_string( -3, require11, dlog( kDebugLevelMax, "action 1 (expected)\n" ), "require_noerr_action_string" );
2691 	{ err = kResponseErr; goto exit; }
2692 require11:
2693 	require_noerr_action_string( 0, require12, dlog( kDebugLevelMax, "action 2\n" ), "require_noerr_action_string (valid)" );
2694 	goto require12Good;
2695 require12:
2696 	{ err = kResponseErr; goto exit; }
2697 require12Good:
2698 	require_noerr_quiet( -4, require13 );
2699 	{ err = kResponseErr; goto exit; }
2700 require13:
2701 	require_noerr_quiet( 0, require14 );
2702 	goto require14Good;
2703 require14:
2704 	{ err = kResponseErr; goto exit; }
2705 require14Good:
2706 	require_noerr_action( -5, require15, dlog( kDebugLevelMax, "SHOULD SEE: action 3 (expected)\n" ) );
2707 	{ err = kResponseErr; goto exit; }
2708 require15:
2709 	require_noerr_action( 0, require16, dlog( kDebugLevelMax, "SHOULD *NOT* SEE: action 4\n" ) );
2710 	goto require16Good;
2711 require16:
2712 	{ err = kResponseErr; goto exit; }
2713 require16Good:
2714 	require_noerr_action_quiet( -4, require17, dlog( kDebugLevelMax, "SHOULD SEE: action 5 (expected)\n" ) );
2715 	{ err = kResponseErr; goto exit; }
2716 require17:
2717 	require_noerr_action_quiet( 0, require18, dlog( kDebugLevelMax, "SHOULD *NOT* SEE: action 6\n" ) );
2718 	goto require18Good;
2719 require18:
2720 	{ err = kResponseErr; goto exit; }
2721 require18Good:
2722 	require_action( 0 && "SHOULD SEE", require19, dlog( kDebugLevelMax, "SHOULD SEE: action 7 (expected)\n" ) );
2723 	{ err = kResponseErr; goto exit; }
2724 require19:
2725 	require_action( 1 && "SHOULD *NOT* SEE", require20, dlog( kDebugLevelMax, "SHOULD *NOT* SEE: action 8\n" ) );
2726 	goto require20Good;
2727 require20:
2728 	{ err = kResponseErr; goto exit; }
2729 require20Good:
2730 	require_action_quiet( 0, require21, dlog( kDebugLevelMax, "SHOULD SEE: action 9 (expected)\n" ) );
2731 	{ err = kResponseErr; goto exit; }
2732 require21:
2733 	require_action_quiet( 1, require22, dlog( kDebugLevelMax, "SHOULD *NOT* SEE: action 10\n" ) );
2734 	goto require22Good;
2735 require22:
2736 	{ err = kResponseErr; goto exit; }
2737 require22Good:
2738 	require_action_string( 0, require23, dlog( kDebugLevelMax, "SHOULD SEE: action 11 (expected)\n" ), "SHOULD SEE: require_action_string" );
2739 	{ err = kResponseErr; goto exit; }
2740 require23:
2741 	require_action_string( 1, require24, dlog( kDebugLevelMax, "SHOULD *NOT* SEE: action 12\n" ), "SHOULD *NOT* SEE: require_action_string" );
2742 	goto require24Good;
2743 require24:
2744 	{ err = kResponseErr; goto exit; }
2745 require24Good:
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; }
2772 require26Good:
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 
3067 exit:
3068 	if( err )
3069 	{
3070 		DebugPrintF( kDebugLevelMax, "\n\n### TEST FAILED ###\n\n" );
3071 	}
3072 	return( err );
3073 }
3074 
3075 #endif	// DEBUG
3076