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