VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-StrFormatV.c@ 84794

Last change on this file since 84794 was 83022, checked in by vboxsync, 5 years ago

bs3kit: Fixed bug in string formatter where %s output was counteded twice. Adjusted Bs3TestSub[V].

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 24.3 KB
Line 
1/* $Id: bs3-cmn-StrFormatV.c 83022 2020-02-07 13:49:18Z vboxsync $ */
2/** @file
3 * BS3Kit - Bs3StrFormatV
4 */
5
6/*
7 * Copyright (C) 2007-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include "bs3kit-template-header.h"
32#include <iprt/ctype.h>
33
34
35/*********************************************************************************************************************************
36* Defined Constants And Macros *
37*********************************************************************************************************************************/
38#define STR_F_CAPITAL 0x0001
39#define STR_F_LEFT 0x0002
40#define STR_F_ZEROPAD 0x0004
41#define STR_F_SPECIAL 0x0008
42#define STR_F_VALSIGNED 0x0010
43#define STR_F_PLUS 0x0020
44#define STR_F_BLANK 0x0040
45#define STR_F_WIDTH 0x0080
46#define STR_F_PRECISION 0x0100
47#define STR_F_THOUSAND_SEP 0x0200
48#define STR_F_NEGATIVE 0x0400 /**< Used to indicated '-' must be printed. */
49
50
51/*********************************************************************************************************************************
52* Structures and Typedefs *
53*********************************************************************************************************************************/
54/** Size of the temporary buffer. */
55#define BS3FMT_TMP_SIZE 64
56
57/**
58 * BS3kit string format state.
59 */
60typedef struct BS3FMTSTATE
61{
62 /** The output function. */
63 PFNBS3STRFORMATOUTPUT pfnOutput;
64 /** User argument for pfnOutput. */
65 void BS3_FAR *pvUser;
66
67 /** STR_F_XXX flags. */
68 unsigned fFlags;
69 /** The width when STR_F_WIDTH is specific. */
70 int cchWidth;
71 /** The width when STR_F_PRECISION is specific. */
72 int cchPrecision;
73 /** The number format base. */
74 unsigned uBase;
75 /** Temporary buffer. */
76 char szTmp[BS3FMT_TMP_SIZE];
77} BS3FMTSTATE;
78/** Pointer to a BS3Kit string formatter state. */
79typedef BS3FMTSTATE BS3_FAR *PBS3FMTSTATE;
80
81
82
83/*********************************************************************************************************************************
84* Internal Functions *
85*********************************************************************************************************************************/
86#if ARCH_BITS != 64
87static size_t bs3StrFormatU32(PBS3FMTSTATE pState, uint32_t uValue);
88#endif
89
90
91
92/**
93 * Formats a number string.
94 *
95 * @returns Number of chars printed.
96 * @param pState The string formatter state.
97 * @param pszNumber The formatted number string.
98 * @param cchNumber The length of the number.
99 */
100static size_t bs3StrFormatNumberString(PBS3FMTSTATE pState, char const BS3_FAR *pszNumber, size_t cchNumber)
101{
102 /*
103 * Calc the length of the core number with prefixes.
104 */
105 size_t cchActual = 0;
106 size_t cchRet = cchNumber;
107
108 /* Accunt for sign char. */
109 cchRet += !!(pState->fFlags & (STR_F_NEGATIVE | STR_F_PLUS | STR_F_BLANK));
110
111 /* Account for the hex prefix: '0x' or '0X' */
112 if (pState->fFlags & STR_F_SPECIAL)
113 {
114 cchRet += 2;
115 BS3_ASSERT(pState->uBase == 16);
116 }
117
118 /* Account for thousand separators (applied while printing). */
119 if (pState->fFlags & STR_F_THOUSAND_SEP)
120 cchRet += (cchNumber - 1) / (pState->uBase == 10 ? 3 : 8);
121
122 /*
123 * Do left blank padding.
124 */
125 if ((pState->fFlags & (STR_F_ZEROPAD | STR_F_LEFT | STR_F_WIDTH)) == STR_F_WIDTH)
126 while (cchRet < pState->cchWidth)
127 {
128 cchActual += pState->pfnOutput(' ', pState->pvUser);
129 cchRet++;
130 }
131
132 /*
133 * Sign indicator / space.
134 */
135 if (pState->fFlags & (STR_F_NEGATIVE | STR_F_PLUS | STR_F_BLANK))
136 {
137 char ch;
138 if (pState->fFlags & STR_F_NEGATIVE)
139 ch = '-';
140 else if (pState->fFlags & STR_F_PLUS)
141 ch = '+';
142 else
143 ch = ' ';
144 cchActual += pState->pfnOutput(ch, pState->pvUser);
145 }
146
147 /*
148 * Hex prefix.
149 */
150 if (pState->fFlags & STR_F_SPECIAL)
151 {
152 cchActual += pState->pfnOutput('0', pState->pvUser);
153 cchActual += pState->pfnOutput(!(pState->fFlags & STR_F_CAPITAL) ? 'x' : 'X', pState->pvUser);
154 }
155
156 /*
157 * Zero padding.
158 */
159 if (pState->fFlags & STR_F_ZEROPAD)
160 while (cchRet < pState->cchWidth)
161 {
162 cchActual += pState->pfnOutput('0', pState->pvUser);
163 cchRet++;
164 }
165
166 /*
167 * Output the number.
168 */
169 if ( !(pState->fFlags & STR_F_THOUSAND_SEP)
170 || cchNumber < 4)
171 while (cchNumber-- > 0)
172 cchActual += pState->pfnOutput(*pszNumber++, pState->pvUser);
173 else
174 {
175 char const chSep = pState->uBase == 10 ? ' ' : '\'';
176 unsigned const cchEvery = pState->uBase == 10 ? 3 : 8;
177 unsigned cchLeft = --cchNumber % cchEvery;
178
179 cchActual += pState->pfnOutput(*pszNumber++, pState->pvUser);
180 while (cchNumber-- > 0)
181 {
182 if (cchLeft == 0)
183 {
184 cchActual += pState->pfnOutput(chSep, pState->pvUser);
185 cchLeft = cchEvery;
186 }
187 cchLeft--;
188 cchActual += pState->pfnOutput(*pszNumber++, pState->pvUser);
189 }
190 }
191
192 /*
193 * Do right blank padding.
194 */
195 if ((pState->fFlags & (STR_F_ZEROPAD | STR_F_LEFT | STR_F_WIDTH)) == (STR_F_WIDTH | STR_F_LEFT))
196 while (cchRet < pState->cchWidth)
197 {
198 cchActual += pState->pfnOutput(' ', pState->pvUser);
199 cchRet++;
200 }
201
202 return cchActual;
203}
204
205
206/**
207 * Format a 64-bit number.
208 *
209 * @returns Number of characters.
210 * @param pState The string formatter state.
211 * @param uValue The value.
212 */
213static size_t bs3StrFormatU64(PBS3FMTSTATE pState, uint64_t uValue)
214{
215#if ARCH_BITS != 64
216 /* Avoid 64-bit division by formatting 64-bit numbers as hex if they're higher than _4G. */
217 if (pState->uBase == 10)
218 {
219 if (!(uValue >> 32)) /* uValue <= UINT32_MAX does not work, trouble with 64-bit compile time math! */
220 return bs3StrFormatU32(pState, uValue);
221 pState->fFlags |= STR_F_SPECIAL;
222 pState->uBase = 16;
223 }
224#endif
225
226 {
227 const char BS3_FAR *pachDigits = !(pState->fFlags & STR_F_CAPITAL) ? g_achBs3HexDigits : g_achBs3HexDigitsUpper;
228 char BS3_FAR *psz = &pState->szTmp[BS3FMT_TMP_SIZE];
229
230 *--psz = '\0';
231#if ARCH_BITS == 64
232 if (pState->uBase == 10)
233 {
234 do
235 {
236 *--psz = pachDigits[uValue % 10];
237 uValue /= 10;
238 } while (uValue > 0);
239 }
240 else
241#endif
242 {
243 BS3_ASSERT(pState->uBase == 16);
244 do
245 {
246 *--psz = pachDigits[uValue & 0xf];
247 uValue >>= 4;
248 } while (uValue > 0);
249 }
250 return bs3StrFormatNumberString(pState, psz, &pState->szTmp[BS3FMT_TMP_SIZE - 1] - psz);
251 }
252}
253
254
255/**
256 * Format a 32-bit number.
257 *
258 * @returns Number of characters.
259 * @param pState The string formatter state.
260 * @param uValue The value.
261 */
262static size_t bs3StrFormatU32(PBS3FMTSTATE pState, uint32_t uValue)
263{
264#if ARCH_BITS < 64
265 const char BS3_FAR *pachDigits = !(pState->fFlags & STR_F_CAPITAL) ? g_achBs3HexDigits : g_achBs3HexDigitsUpper;
266 char BS3_FAR *psz = &pState->szTmp[BS3FMT_TMP_SIZE];
267
268 *--psz = '\0';
269 if (pState->uBase == 10)
270 {
271 do
272 {
273 *--psz = pachDigits[uValue % 10];
274 uValue /= 10;
275 } while (uValue > 0);
276 }
277 else
278 {
279 BS3_ASSERT(pState->uBase == 16);
280 do
281 {
282 *--psz = pachDigits[uValue & 0xf];
283 uValue >>= 4;
284 } while (uValue > 0);
285 }
286 return bs3StrFormatNumberString(pState, psz, &pState->szTmp[BS3FMT_TMP_SIZE - 1] - psz);
287
288#else
289 /* We've got native 64-bit division, save space. */
290 return bs3StrFormatU64(pState, uValue);
291#endif
292}
293
294
295#if ARCH_BITS == 16
296/**
297 * Format a 16-bit number.
298 *
299 * @returns Number of characters.
300 * @param pState The string formatter state.
301 * @param uValue The value.
302 */
303static size_t bs3StrFormatU16(PBS3FMTSTATE pState, uint16_t uValue)
304{
305 if (pState->uBase == 10)
306 {
307 const char BS3_FAR *pachDigits = !(pState->fFlags & STR_F_CAPITAL)
308 ? g_achBs3HexDigits : g_achBs3HexDigitsUpper;
309 char BS3_FAR *psz = &pState->szTmp[BS3FMT_TMP_SIZE];
310
311 *--psz = '\0';
312 do
313 {
314 *--psz = pachDigits[uValue % 10];
315 uValue /= 10;
316 } while (uValue > 0);
317 return bs3StrFormatNumberString(pState, psz, &pState->szTmp[BS3FMT_TMP_SIZE - 1] - psz);
318 }
319
320 /*
321 * 32-bit shifting is reasonably cheap and inlined, so combine with 32-bit.
322 */
323 return bs3StrFormatU32(pState, uValue);
324}
325#endif
326
327
328static size_t bs3StrFormatS64(PBS3FMTSTATE pState, int32_t iValue)
329{
330 if (iValue < 0)
331 {
332 iValue = -iValue;
333 pState->fFlags |= STR_F_NEGATIVE;
334 }
335 return bs3StrFormatU64(pState, iValue);
336}
337
338
339static size_t bs3StrFormatS32(PBS3FMTSTATE pState, int32_t iValue)
340{
341 if (iValue < 0)
342 {
343 iValue = -iValue;
344 pState->fFlags |= STR_F_NEGATIVE;
345 }
346 return bs3StrFormatU32(pState, iValue);
347}
348
349
350#if ARCH_BITS == 16
351static size_t bs3StrFormatS16(PBS3FMTSTATE pState, int16_t iValue)
352{
353 if (iValue < 0)
354 {
355 iValue = -iValue;
356 pState->fFlags |= STR_F_NEGATIVE;
357 }
358 return bs3StrFormatU16(pState, iValue);
359}
360#endif
361
362
363#undef Bs3StrFormatV
364BS3_CMN_DEF(size_t, Bs3StrFormatV,(const char BS3_FAR *pszFormat, va_list BS3_FAR va,
365 PFNBS3STRFORMATOUTPUT pfnOutput, void BS3_FAR *pvUser))
366{
367 BS3FMTSTATE State;
368 size_t cchRet = 0;
369 char ch;
370#if ARCH_BITS == 16
371 typedef int SIZE_CHECK_TYPE1[sizeof(va) == 4 && sizeof(va[0]) == 4];
372#endif
373
374 State.pfnOutput = pfnOutput;
375 State.pvUser = pvUser;
376
377 while ((ch = *pszFormat++) != '\0')
378 {
379 char chArgSize;
380
381 /*
382 * Deal with plain chars.
383 */
384 if (ch != '%')
385 {
386 cchRet += State.pfnOutput(ch, State.pvUser);
387 continue;
388 }
389
390 ch = *pszFormat++;
391 if (ch == '%')
392 {
393 cchRet += State.pfnOutput(ch, State.pvUser);
394 continue;
395 }
396
397 /*
398 * Flags.
399 */
400 State.fFlags = 0;
401 for (;;)
402 {
403 unsigned int fThis;
404 switch (ch)
405 {
406 default: fThis = 0; break;
407 case '#': fThis = STR_F_SPECIAL; break;
408 case '-': fThis = STR_F_LEFT; break;
409 case '+': fThis = STR_F_PLUS; break;
410 case ' ': fThis = STR_F_BLANK; break;
411 case '0': fThis = STR_F_ZEROPAD; break;
412 case '\'': fThis = STR_F_THOUSAND_SEP; break;
413 }
414 if (!fThis)
415 break;
416 State.fFlags |= fThis;
417 ch = *pszFormat++;
418 }
419
420 /*
421 * Width.
422 */
423 State.cchWidth = 0;
424 if (RT_C_IS_DIGIT(ch))
425 {
426 do
427 {
428 State.cchWidth *= 10;
429 State.cchWidth += ch - '0';
430 ch = *pszFormat++;
431 } while (RT_C_IS_DIGIT(ch));
432 State.fFlags |= STR_F_WIDTH;
433 }
434 else if (ch == '*')
435 {
436 State.cchWidth = va_arg(va, int);
437 if (State.cchWidth < 0)
438 {
439 State.cchWidth = -State.cchWidth;
440 State.fFlags |= STR_F_LEFT;
441 }
442 State.fFlags |= STR_F_WIDTH;
443 ch = *pszFormat++;
444 }
445
446 /*
447 * Precision
448 */
449 State.cchPrecision = 0;
450 if (ch == '.')
451 {
452 ch = *pszFormat++;
453 if (RT_C_IS_DIGIT(ch))
454 {
455 do
456 {
457 State.cchPrecision *= 10;
458 State.cchPrecision += ch - '0';
459 ch = *pszFormat++;
460 } while (RT_C_IS_DIGIT(ch));
461 State.fFlags |= STR_F_PRECISION;
462 }
463 else if (ch == '*')
464 {
465 State.cchPrecision = va_arg(va, int);
466 if (State.cchPrecision < 0)
467 State.cchPrecision = 0;
468 State.fFlags |= STR_F_PRECISION;
469 ch = *pszFormat++;
470 }
471 }
472
473 /*
474 * Argument size.
475 */
476 chArgSize = ch;
477 switch (ch)
478 {
479 default:
480 chArgSize = 0;
481 break;
482
483 case 'z':
484 case 'L':
485 case 'j':
486 case 't':
487 ch = *pszFormat++;
488 break;
489
490 case 'l':
491 ch = *pszFormat++;
492 if (ch == 'l')
493 {
494 chArgSize = 'L';
495 ch = *pszFormat++;
496 }
497 break;
498
499 case 'h':
500 ch = *pszFormat++;
501 if (ch == 'h')
502 {
503 chArgSize = 'H';
504 ch = *pszFormat++;
505 }
506 break;
507 }
508
509 /*
510 * The type.
511 */
512 switch (ch)
513 {
514 /*
515 * Char
516 */
517 case 'c':
518 {
519 char ch = va_arg(va, int /*char*/);
520 cchRet += State.pfnOutput(ch, State.pvUser);
521 break;
522 }
523
524 /*
525 * String.
526 */
527 case 's':
528 {
529 const char BS3_FAR *psz = va_arg(va, const char BS3_FAR *);
530 size_t cch;
531 if (psz != NULL)
532 cch = Bs3StrNLen(psz, State.fFlags & STR_F_PRECISION ? RT_ABS(State.cchPrecision) : ~(size_t)0);
533 else
534 {
535 psz = "<NULL>";
536 cch = 6;
537 }
538
539 if ((State.fFlags & (STR_F_LEFT | STR_F_WIDTH)) == STR_F_WIDTH)
540 while (--State.cchWidth >= cch)
541 cchRet += State.pfnOutput(' ', State.pvUser);
542
543 while (cch-- > 0)
544 cchRet += State.pfnOutput(*psz++, State.pvUser);
545
546 if ((State.fFlags & (STR_F_LEFT | STR_F_WIDTH)) == (STR_F_LEFT | STR_F_WIDTH))
547 while (--State.cchWidth >= cch)
548 cchRet += State.pfnOutput(' ', State.pvUser);
549 break;
550 }
551
552 /*
553 * Signed integers.
554 */
555 case 'i':
556 case 'd':
557 State.fFlags &= ~STR_F_SPECIAL;
558 State.fFlags |= STR_F_VALSIGNED;
559 State.uBase = 10;
560 switch (chArgSize)
561 {
562 case 0:
563 case 'h': /* signed short should be promoted to int or be the same as int */
564 case 'H': /* signed char should be promoted to int. */
565 {
566 signed int iValue = va_arg(va, signed int);
567#if ARCH_BITS == 16
568 cchRet += bs3StrFormatS16(&State, iValue);
569#else
570 cchRet += bs3StrFormatS32(&State, iValue);
571#endif
572 break;
573 }
574 case 'l':
575 {
576 signed long lValue = va_arg(va, signed long);
577 if (sizeof(lValue) == 4)
578 cchRet += bs3StrFormatS32(&State, lValue);
579 else
580 cchRet += bs3StrFormatS64(&State, lValue);
581 break;
582 }
583 case 'L':
584 {
585 unsigned long long ullValue = va_arg(va, unsigned long long);
586 cchRet += bs3StrFormatS64(&State, ullValue);
587 break;
588 }
589 }
590 break;
591
592 /*
593 * Unsigned integers.
594 */
595 case 'X':
596 State.fFlags |= STR_F_CAPITAL;
597 case 'x':
598 case 'u':
599 {
600 if (ch == 'u')
601 {
602 State.uBase = 10;
603 State.fFlags &= ~(STR_F_PLUS | STR_F_BLANK | STR_F_SPECIAL);
604 }
605 else
606 {
607 State.uBase = 16;
608 State.fFlags &= ~(STR_F_PLUS | STR_F_BLANK);
609 }
610 switch (chArgSize)
611 {
612 case 0:
613 case 'h': /* unsigned short should be promoted to int or be the same as int */
614 case 'H': /* unsigned char should be promoted to int. */
615 {
616 unsigned int uValue = va_arg(va, unsigned int);
617#if ARCH_BITS == 16
618 cchRet += bs3StrFormatU16(&State, uValue);
619#else
620 cchRet += bs3StrFormatU32(&State, uValue);
621#endif
622 break;
623 }
624 case 'l':
625 {
626 unsigned long ulValue = va_arg(va, unsigned long);
627 if (sizeof(ulValue) == 4)
628 cchRet += bs3StrFormatU32(&State, ulValue);
629 else
630 cchRet += bs3StrFormatU64(&State, ulValue);
631 break;
632 }
633 case 'L':
634 {
635 unsigned long long ullValue = va_arg(va, unsigned long long);
636 cchRet += bs3StrFormatU64(&State, ullValue);
637 break;
638 }
639 }
640 break;
641 }
642
643 /*
644 * Our stuff.
645 */
646 case 'R':
647 {
648 ch = *pszFormat++;
649 switch (ch)
650 {
651 case 'I':
652 State.fFlags |= STR_F_VALSIGNED;
653 State.uBase &= ~STR_F_SPECIAL;
654 State.uBase = 10;
655 break;
656 case 'U':
657 State.fFlags &= ~(STR_F_PLUS | STR_F_BLANK | STR_F_SPECIAL);
658 State.uBase = 10;
659 break;
660 case 'X':
661 State.fFlags &= ~(STR_F_PLUS | STR_F_BLANK);
662 State.uBase = 16;
663 break;
664 case 'h':
665 ch = *pszFormat++;
666 if (ch == 'x')
667 {
668 /* Hex dumping. */
669 uint8_t const BS3_FAR *pbHex = va_arg(va, uint8_t const BS3_FAR *);
670 if (State.cchPrecision < 0)
671 State.cchPrecision = 16;
672 ch = *pszFormat++;
673 if (ch == 's' || ch == 'd')
674 {
675 /* %Rhxd is currently implemented as %Rhxs. */
676 while (State.cchPrecision-- > 0)
677 {
678 uint8_t b = *pbHex++;
679 State.pfnOutput(g_achBs3HexDigits[b >> 4], State.pvUser);
680 State.pfnOutput(g_achBs3HexDigits[b & 0x0f], State.pvUser);
681 if (State.cchPrecision)
682 State.pfnOutput(' ', State.pvUser);
683 }
684 }
685 }
686 State.uBase = 0;
687 break;
688 default:
689 State.uBase = 0;
690 break;
691 }
692 if (State.uBase)
693 {
694 ch = *pszFormat++;
695 switch (ch)
696 {
697#if ARCH_BITS != 16
698 case '3':
699 case '1': /* Will an unsigned 16-bit value always be promoted
700 to a 16-bit unsigned int. It certainly will be promoted to a 32-bit int. */
701 pszFormat++; /* Assumes (1)'6' or (3)'2' */
702#else
703 case '1':
704 pszFormat++; /* Assumes (1)'6' */
705#endif
706 case '8': /* An unsigned 8-bit value should be promoted to int, which is at least 16-bit. */
707 {
708 unsigned int uValue = va_arg(va, unsigned int);
709#if ARCH_BITS == 16
710 cchRet += bs3StrFormatU16(&State, uValue);
711#else
712 cchRet += bs3StrFormatU32(&State, uValue);
713#endif
714 break;
715 }
716#if ARCH_BITS == 16
717 case '3':
718 {
719 uint32_t uValue = va_arg(va, uint32_t);
720 pszFormat++;
721 cchRet += bs3StrFormatU32(&State, uValue);
722 break;
723 }
724#endif
725 case '6':
726 {
727 uint64_t uValue = va_arg(va, uint64_t);
728 pszFormat++;
729 cchRet += bs3StrFormatU64(&State, uValue);
730 break;
731 }
732 }
733 }
734 break;
735 }
736
737 /*
738 * Pointers.
739 */
740 case 'P':
741 State.fFlags |= STR_F_CAPITAL;
742 RT_FALL_THRU();
743 case 'p':
744 {
745 void BS3_FAR *pv = va_arg(va, void BS3_FAR *);
746 State.uBase = 16;
747 State.fFlags &= ~(STR_F_PLUS | STR_F_BLANK);
748#if ARCH_BITS == 16
749 State.fFlags |= STR_F_ZEROPAD;
750 State.cchWidth = State.fFlags & STR_F_SPECIAL ? 6: 4;
751 cchRet += bs3StrFormatU16(&State, BS3_FP_SEG(pv));
752 cchRet += State.pfnOutput(':', State.pvUser);
753 cchRet += bs3StrFormatU16(&State, BS3_FP_OFF(pv));
754#elif ARCH_BITS == 32
755 State.fFlags |= STR_F_SPECIAL | STR_F_ZEROPAD;
756 State.cchWidth = 10;
757 cchRet += bs3StrFormatU32(&State, (uintptr_t)pv);
758#elif ARCH_BITS == 64
759 State.fFlags |= STR_F_SPECIAL | STR_F_ZEROPAD | STR_F_THOUSAND_SEP;
760 State.cchWidth = 19;
761 cchRet += bs3StrFormatU64(&State, (uintptr_t)pv);
762#else
763# error "Undefined or invalid ARCH_BITS."
764#endif
765 break;
766 }
767
768 }
769 }
770
771 /*
772 * Termination call.
773 */
774 cchRet += State.pfnOutput(0, State.pvUser);
775
776 return cchRet;
777}
778
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette