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