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