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