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