2 Print Library internal worker functions.
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "PrintLibInternal.h"
11 #define WARNING_STATUS_NUMBER 5
12 #define ERROR_STATUS_NUMBER 33
17 #define RSIZE_MAX (PcdGet32 (PcdMaximumUnicodeStringLength))
18 #define ASCII_RSIZE_MAX (PcdGet32 (PcdMaximumAsciiStringLength))
20 #define SAFE_PRINT_CONSTRAINT_CHECK(Expression, RetVal) \
22 ASSERT (Expression); \
23 if (!(Expression)) { \
28 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mHexStr
[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
31 // Longest string: RETURN_WARN_BUFFER_TOO_SMALL => 24 characters plus NUL byte
33 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mWarningString
[][24+1] = {
34 "Success", // RETURN_SUCCESS = 0
35 "Warning Unknown Glyph", // RETURN_WARN_UNKNOWN_GLYPH = 1
36 "Warning Delete Failure", // RETURN_WARN_DELETE_FAILURE = 2
37 "Warning Write Failure", // RETURN_WARN_WRITE_FAILURE = 3
38 "Warning Buffer Too Small", // RETURN_WARN_BUFFER_TOO_SMALL = 4
39 "Warning Stale Data", // RETURN_WARN_STALE_DATA = 5
43 // Longest string: RETURN_INCOMPATIBLE_VERSION => 20 characters plus NUL byte
45 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mErrorString
[][20+1] = {
46 "Load Error", // RETURN_LOAD_ERROR = 1 | MAX_BIT
47 "Invalid Parameter", // RETURN_INVALID_PARAMETER = 2 | MAX_BIT
48 "Unsupported", // RETURN_UNSUPPORTED = 3 | MAX_BIT
49 "Bad Buffer Size", // RETURN_BAD_BUFFER_SIZE = 4 | MAX_BIT
50 "Buffer Too Small", // RETURN_BUFFER_TOO_SMALL, = 5 | MAX_BIT
51 "Not Ready", // RETURN_NOT_READY = 6 | MAX_BIT
52 "Device Error", // RETURN_DEVICE_ERROR = 7 | MAX_BIT
53 "Write Protected", // RETURN_WRITE_PROTECTED = 8 | MAX_BIT
54 "Out of Resources", // RETURN_OUT_OF_RESOURCES = 9 | MAX_BIT
55 "Volume Corrupt", // RETURN_VOLUME_CORRUPTED = 10 | MAX_BIT
56 "Volume Full", // RETURN_VOLUME_FULL = 11 | MAX_BIT
57 "No Media", // RETURN_NO_MEDIA = 12 | MAX_BIT
58 "Media changed", // RETURN_MEDIA_CHANGED = 13 | MAX_BIT
59 "Not Found", // RETURN_NOT_FOUND = 14 | MAX_BIT
60 "Access Denied", // RETURN_ACCESS_DENIED = 15 | MAX_BIT
61 "No Response", // RETURN_NO_RESPONSE = 16 | MAX_BIT
62 "No mapping", // RETURN_NO_MAPPING = 17 | MAX_BIT
63 "Time out", // RETURN_TIMEOUT = 18 | MAX_BIT
64 "Not started", // RETURN_NOT_STARTED = 19 | MAX_BIT
65 "Already started", // RETURN_ALREADY_STARTED = 20 | MAX_BIT
66 "Aborted", // RETURN_ABORTED = 21 | MAX_BIT
67 "ICMP Error", // RETURN_ICMP_ERROR = 22 | MAX_BIT
68 "TFTP Error", // RETURN_TFTP_ERROR = 23 | MAX_BIT
69 "Protocol Error", // RETURN_PROTOCOL_ERROR = 24 | MAX_BIT
70 "Incompatible Version", // RETURN_INCOMPATIBLE_VERSION = 25 | MAX_BIT
71 "Security Violation", // RETURN_SECURITY_VIOLATION = 26 | MAX_BIT
72 "CRC Error", // RETURN_CRC_ERROR = 27 | MAX_BIT
73 "End of Media", // RETURN_END_OF_MEDIA = 28 | MAX_BIT
74 "Reserved (29)", // RESERVED = 29 | MAX_BIT
75 "Reserved (30)", // RESERVED = 30 | MAX_BIT
76 "End of File", // RETURN_END_OF_FILE = 31 | MAX_BIT
77 "Invalid Language", // RETURN_INVALID_LANGUAGE = 32 | MAX_BIT
78 "Compromised Data" // RETURN_COMPROMISED_DATA = 33 | MAX_BIT
83 Internal function that places the character into the Buffer.
85 Internal function that places ASCII or Unicode character into the Buffer.
87 @param Buffer The buffer to place the Unicode or ASCII string.
88 @param EndBuffer The end of the input Buffer. No characters will be
90 @param Length The count of character to be placed into Buffer.
91 (Negative value indicates no buffer fill.)
92 @param Character The character to be placed into Buffer.
93 @param Increment The character increment in Buffer.
99 BasePrintLibFillBuffer (
109 for (Index
= 0; Index
< Length
&& Buffer
< EndBuffer
; Index
++) {
110 *Buffer
= (CHAR8
) Character
;
111 if (Increment
!= 1) {
112 *(Buffer
+ 1) = (CHAR8
)(Character
>> 8);
121 Internal function that convert a number to a string in Buffer.
123 Print worker function that converts a decimal or hexadecimal number to an ASCII string in Buffer.
125 @param Buffer Location to place the ASCII string of Value.
126 @param Value The value to convert to a Decimal or Hexadecimal string in Buffer.
127 @param Radix Radix of the value
129 @return A pointer to the end of buffer filled with ASCII string.
133 BasePrintLibValueToString (
134 IN OUT CHAR8
*Buffer
,
142 // Loop to convert one digit at a time in reverse order
146 Value
= (INT64
)DivU64x32Remainder ((UINT64
)Value
, (UINT32
)Radix
, &Remainder
);
147 *(++Buffer
) = mHexStr
[Remainder
];
148 } while (Value
!= 0);
151 // Return pointer of the end of filled buffer.
157 Internal function that converts a decimal value to a Null-terminated string.
159 Converts the decimal number specified by Value to a Null-terminated
160 string specified by Buffer containing at most Width characters.
161 If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed.
162 The total number of characters placed in Buffer is returned.
163 If the conversion contains more than Width characters, then only the first
164 Width characters are returned, and the total number of characters
165 required to perform the conversion is returned.
166 Additional conversion parameters are specified in Flags.
167 The Flags bit LEFT_JUSTIFY is always ignored.
168 All conversions are left justified in Buffer.
169 If Width is 0, PREFIX_ZERO is ignored in Flags.
170 If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and commas
171 are inserted every 3rd digit starting from the right.
172 If Value is < 0, then the fist character in Buffer is a '-'.
173 If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored,
174 then Buffer is padded with '0' characters so the combination of the optional '-'
175 sign character, '0' characters, digit characters for Value, and the Null-terminator
176 add up to Width characters.
178 If Buffer is NULL, then ASSERT().
179 If unsupported bits are set in Flags, then ASSERT().
180 If Width >= MAXIMUM_VALUE_CHARACTERS, then ASSERT()
182 @param Buffer The pointer to the output buffer for the produced Null-terminated
184 @param Flags The bitmask of flags that specify left justification, zero pad,
186 @param Value The 64-bit signed value to convert to a string.
187 @param Width The maximum number of characters to place in Buffer, not including
189 @param Increment The character increment in Buffer.
191 @return Total number of characters required to perform the conversion.
195 BasePrintLibConvertValueToString (
196 IN OUT CHAR8
*Buffer
,
203 CHAR8
*OriginalBuffer
;
205 CHAR8 ValueBuffer
[MAXIMUM_VALUE_CHARACTERS
];
206 CHAR8
*ValueBufferPtr
;
213 // Make sure Buffer is not NULL and Width < MAXIMUM
215 ASSERT (Buffer
!= NULL
);
216 ASSERT (Width
< MAXIMUM_VALUE_CHARACTERS
);
218 // Make sure Flags can only contain supported bits.
220 ASSERT ((Flags
& ~(LEFT_JUSTIFY
| COMMA_TYPE
| PREFIX_ZERO
| RADIX_HEX
)) == 0);
223 // If both COMMA_TYPE and RADIX_HEX are set, then ASSERT ()
225 ASSERT (((Flags
& COMMA_TYPE
) == 0) || ((Flags
& RADIX_HEX
) == 0));
227 OriginalBuffer
= Buffer
;
230 // Width is 0 or COMMA_TYPE is set, PREFIX_ZERO is ignored.
232 if (Width
== 0 || (Flags
& COMMA_TYPE
) != 0) {
233 Flags
&= ~((UINTN
) PREFIX_ZERO
);
236 // If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed.
239 Width
= MAXIMUM_VALUE_CHARACTERS
- 1;
242 // Set the tag for the end of the input Buffer.
244 EndBuffer
= Buffer
+ Width
* Increment
;
247 // Convert decimal negative
249 if ((Value
< 0) && ((Flags
& RADIX_HEX
) == 0)) {
251 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, 1, '-', Increment
);
256 // Count the length of the value string.
258 Radix
= ((Flags
& RADIX_HEX
) == 0)? 10 : 16;
259 ValueBufferPtr
= BasePrintLibValueToString (ValueBuffer
, Value
, Radix
);
260 Count
= ValueBufferPtr
- ValueBuffer
;
265 if ((Flags
& PREFIX_ZERO
) != 0) {
266 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, Width
- Count
, '0', Increment
);
270 // Print Comma type for every 3 characters
276 for (Index
= 0; Index
< Count
; Index
++) {
277 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, 1, *ValueBufferPtr
--, Increment
);
278 if ((Flags
& COMMA_TYPE
) != 0) {
282 if ((Index
+ 1) < Count
) {
283 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, 1, ',', Increment
);
290 // Print Null-terminator
292 BasePrintLibFillBuffer (Buffer
, EndBuffer
+ Increment
, 1, 0, Increment
);
294 return ((Buffer
- OriginalBuffer
) / Increment
);
298 Internal function that converts a decimal value to a Null-terminated string.
300 Converts the decimal number specified by Value to a Null-terminated string
301 specified by Buffer containing at most Width characters. If Width is 0 then a
302 width of MAXIMUM_VALUE_CHARACTERS is assumed. If the conversion contains more
303 than Width characters, then only the first Width characters are placed in
304 Buffer. Additional conversion parameters are specified in Flags.
305 The Flags bit LEFT_JUSTIFY is always ignored.
306 All conversions are left justified in Buffer.
307 If Width is 0, PREFIX_ZERO is ignored in Flags.
308 If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and
309 commas are inserted every 3rd digit starting from the right.
310 If Value is < 0, then the fist character in Buffer is a '-'.
311 If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored,
312 then Buffer is padded with '0' characters so the combination of the optional
313 '-' sign character, '0' characters, digit characters for Value, and the
314 Null-terminator add up to Width characters.
316 If an error would be returned, the function will ASSERT().
318 @param Buffer The pointer to the output buffer for the produced
319 Null-terminated string.
320 @param BufferSize The size of Buffer in bytes, including the
322 @param Flags The bitmask of flags that specify left justification,
323 zero pad, and commas.
324 @param Value The 64-bit signed value to convert to a string.
325 @param Width The maximum number of characters to place in Buffer,
326 not including the Null-terminator.
327 @param Increment The character increment in Buffer.
329 @retval RETURN_SUCCESS The decimal value is converted.
330 @retval RETURN_BUFFER_TOO_SMALL If BufferSize cannot hold the converted
332 @retval RETURN_INVALID_PARAMETER If Buffer is NULL.
333 If Increment is 1 and
334 PcdMaximumAsciiStringLength is not zero,
335 BufferSize is greater than
336 PcdMaximumAsciiStringLength.
337 If Increment is not 1 and
338 PcdMaximumUnicodeStringLength is not zero,
339 BufferSize is greater than
340 (PcdMaximumUnicodeStringLength *
341 sizeof (CHAR16) + 1).
342 If unsupported bits are set in Flags.
343 If both COMMA_TYPE and RADIX_HEX are set in
345 If Width >= MAXIMUM_VALUE_CHARACTERS.
349 BasePrintLibConvertValueToStringS (
350 IN OUT CHAR8
*Buffer
,
359 CHAR8 ValueBuffer
[MAXIMUM_VALUE_CHARACTERS
];
360 CHAR8
*ValueBufferPtr
;
367 // 1. Buffer shall not be a null pointer.
369 SAFE_PRINT_CONSTRAINT_CHECK ((Buffer
!= NULL
), RETURN_INVALID_PARAMETER
);
372 // 2. BufferSize shall not be greater than (RSIZE_MAX * sizeof (CHAR16)) for
373 // Unicode output string or shall not be greater than ASCII_RSIZE_MAX for
374 // Ascii output string.
376 if (Increment
== 1) {
378 // Ascii output string
380 if (ASCII_RSIZE_MAX
!= 0) {
381 SAFE_PRINT_CONSTRAINT_CHECK ((BufferSize
<= ASCII_RSIZE_MAX
), RETURN_INVALID_PARAMETER
);
385 // Unicode output string
387 if (RSIZE_MAX
!= 0) {
388 SAFE_PRINT_CONSTRAINT_CHECK ((BufferSize
<= RSIZE_MAX
* sizeof (CHAR16
) + 1), RETURN_INVALID_PARAMETER
);
393 // 3. Flags shall be set properly.
395 SAFE_PRINT_CONSTRAINT_CHECK (((Flags
& ~(LEFT_JUSTIFY
| COMMA_TYPE
| PREFIX_ZERO
| RADIX_HEX
)) == 0), RETURN_INVALID_PARAMETER
);
396 SAFE_PRINT_CONSTRAINT_CHECK ((((Flags
& COMMA_TYPE
) == 0) || ((Flags
& RADIX_HEX
) == 0)), RETURN_INVALID_PARAMETER
);
399 // 4. Width shall be smaller than MAXIMUM_VALUE_CHARACTERS.
401 SAFE_PRINT_CONSTRAINT_CHECK ((Width
< MAXIMUM_VALUE_CHARACTERS
), RETURN_INVALID_PARAMETER
);
404 // Width is 0 or COMMA_TYPE is set, PREFIX_ZERO is ignored.
406 if (Width
== 0 || (Flags
& COMMA_TYPE
) != 0) {
407 Flags
&= ~((UINTN
) PREFIX_ZERO
);
410 // If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed.
413 Width
= MAXIMUM_VALUE_CHARACTERS
- 1;
417 // Count the characters of the output string.
420 Radix
= ((Flags
& RADIX_HEX
) == 0)? 10 : 16;
422 if ((Flags
& PREFIX_ZERO
) != 0) {
425 if ((Value
< 0) && ((Flags
& RADIX_HEX
) == 0)) {
426 Count
++; // minus sign
427 ValueBufferPtr
= BasePrintLibValueToString (ValueBuffer
, -Value
, Radix
);
429 ValueBufferPtr
= BasePrintLibValueToString (ValueBuffer
, Value
, Radix
);
431 Digits
= ValueBufferPtr
- ValueBuffer
;
434 if ((Flags
& COMMA_TYPE
) != 0) {
435 Count
+= (Digits
- 1) / 3; // commas
439 Width
= MIN (Count
, Width
);
442 // 5. BufferSize shall be large enough to hold the converted string.
444 SAFE_PRINT_CONSTRAINT_CHECK ((BufferSize
>= (Width
+ 1) * Increment
), RETURN_BUFFER_TOO_SMALL
);
447 // Set the tag for the end of the input Buffer.
449 EndBuffer
= Buffer
+ Width
* Increment
;
452 // Convert decimal negative
454 if ((Value
< 0) && ((Flags
& RADIX_HEX
) == 0)) {
456 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, 1, '-', Increment
);
461 // Count the length of the value string.
463 ValueBufferPtr
= BasePrintLibValueToString (ValueBuffer
, Value
, Radix
);
464 Count
= ValueBufferPtr
- ValueBuffer
;
469 if ((Flags
& PREFIX_ZERO
) != 0) {
470 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, Width
- Count
, '0', Increment
);
474 // Print Comma type for every 3 characters
480 for (Index
= 0; Index
< Count
; Index
++) {
481 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, 1, *ValueBufferPtr
--, Increment
);
482 if ((Flags
& COMMA_TYPE
) != 0) {
486 if ((Index
+ 1) < Count
) {
487 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, 1, ',', Increment
);
494 // Print Null-terminator
496 BasePrintLibFillBuffer (Buffer
, EndBuffer
+ Increment
, 1, 0, Increment
);
498 return RETURN_SUCCESS
;
502 Worker function that produces a Null-terminated string in an output buffer
503 based on a Null-terminated format string and a VA_LIST argument list.
505 VSPrint function to process format and place the results in Buffer. Since a
506 VA_LIST is used this routine allows the nesting of Vararg routines. Thus
507 this is the main print working routine.
509 If COUNT_ONLY_NO_PRINT is set in Flags, Buffer will not be modified at all.
511 @param[out] Buffer The character buffer to print the results of the
512 parsing of Format into.
513 @param[in] BufferSize The maximum number of characters to put into
515 @param[in] Flags Initial flags value.
516 Can only have FORMAT_UNICODE, OUTPUT_UNICODE,
517 and COUNT_ONLY_NO_PRINT set.
518 @param[in] Format A Null-terminated format string.
519 @param[in] VaListMarker VA_LIST style variable argument list consumed by
521 @param[in] BaseListMarker BASE_LIST style variable argument list consumed
522 by processing Format.
524 @return The number of characters printed not including the Null-terminator.
525 If COUNT_ONLY_NO_PRINT was set returns the same, but without any
526 modification to Buffer.
530 BasePrintLibSPrintMarker (
534 IN CONST CHAR8
*Format
,
535 IN VA_LIST VaListMarker OPTIONAL
,
536 IN BASE_LIST BaseListMarker OPTIONAL
539 CHAR8
*OriginalBuffer
;
541 CHAR8 ValueBuffer
[MAXIMUM_VALUE_CHARACTERS
];
542 UINT32 BytesPerOutputCharacter
;
543 UINTN BytesPerFormatCharacter
;
545 UINTN FormatCharacter
;
549 CONST CHAR8
*ArgumentString
;
555 INTN BytesPerArgumentCharacter
;
556 UINTN ArgumentCharacter
;
564 RETURN_STATUS Status
;
568 UINTN LengthToReturn
;
571 // If you change this code be sure to match the 2 versions of this function.
572 // Nearly identical logic is found in the BasePrintLib and
573 // DxePrintLibPrint2Protocol (both PrintLib instances).
577 // 1. Buffer shall not be a null pointer when both BufferSize > 0 and
578 // COUNT_ONLY_NO_PRINT is not set in Flags.
580 if ((BufferSize
> 0) && ((Flags
& COUNT_ONLY_NO_PRINT
) == 0)) {
581 SAFE_PRINT_CONSTRAINT_CHECK ((Buffer
!= NULL
), 0);
585 // 2. Format shall not be a null pointer when BufferSize > 0 or when
586 // COUNT_ONLY_NO_PRINT is set in Flags.
588 if ((BufferSize
> 0) || ((Flags
& COUNT_ONLY_NO_PRINT
) != 0)) {
589 SAFE_PRINT_CONSTRAINT_CHECK ((Format
!= NULL
), 0);
593 // 3. BufferSize shall not be greater than RSIZE_MAX for Unicode output or
594 // ASCII_RSIZE_MAX for Ascii output.
596 if ((Flags
& OUTPUT_UNICODE
) != 0) {
597 if (RSIZE_MAX
!= 0) {
598 SAFE_PRINT_CONSTRAINT_CHECK ((BufferSize
<= RSIZE_MAX
), 0);
600 BytesPerOutputCharacter
= 2;
602 if (ASCII_RSIZE_MAX
!= 0) {
603 SAFE_PRINT_CONSTRAINT_CHECK ((BufferSize
<= ASCII_RSIZE_MAX
), 0);
605 BytesPerOutputCharacter
= 1;
609 // 4. Format shall not contain more than RSIZE_MAX Unicode characters or
610 // ASCII_RSIZE_MAX Ascii characters.
612 if ((Flags
& FORMAT_UNICODE
) != 0) {
613 if (RSIZE_MAX
!= 0) {
614 SAFE_PRINT_CONSTRAINT_CHECK ((StrnLenS ((CHAR16
*)Format
, RSIZE_MAX
+ 1) <= RSIZE_MAX
), 0);
616 BytesPerFormatCharacter
= 2;
619 if (ASCII_RSIZE_MAX
!= 0) {
620 SAFE_PRINT_CONSTRAINT_CHECK ((AsciiStrnLenS (Format
, ASCII_RSIZE_MAX
+ 1) <= ASCII_RSIZE_MAX
), 0);
622 BytesPerFormatCharacter
= 1;
626 if ((Flags
& COUNT_ONLY_NO_PRINT
) != 0) {
627 if (BufferSize
== 0) {
632 // We can run without a Buffer for counting only.
634 if (BufferSize
== 0) {
641 OriginalBuffer
= NULL
;
644 // Reserve space for the Null terminator.
646 if (Buffer
!= NULL
) {
648 OriginalBuffer
= Buffer
;
651 // Set the tag for the end of the input Buffer.
653 EndBuffer
= Buffer
+ BufferSize
* BytesPerOutputCharacter
;
657 // Get the first character from the format string
659 FormatCharacter
= ((*Format
& 0xff) | ((BytesPerFormatCharacter
== 1) ? 0 : (*(Format
+ 1) << 8))) & FormatMask
;
662 // Loop until the end of the format string is reached or the output buffer is full
664 while (FormatCharacter
!= 0) {
665 if ((Buffer
!= NULL
) && (Buffer
>= EndBuffer
)) {
669 // Clear all the flag bits except those that may have been passed in
671 Flags
&= (UINTN
) (OUTPUT_UNICODE
| FORMAT_UNICODE
| COUNT_ONLY_NO_PRINT
);
674 // Set the default width to zero, and the default precision to 1
684 switch (FormatCharacter
) {
687 // Parse Flags and Width
689 for (Done
= FALSE
; !Done
; ) {
690 Format
+= BytesPerFormatCharacter
;
691 FormatCharacter
= ((*Format
& 0xff) | ((BytesPerFormatCharacter
== 1) ? 0 : (*(Format
+ 1) << 8))) & FormatMask
;
692 switch (FormatCharacter
) {
697 Flags
|= LEFT_JUSTIFY
;
700 Flags
|= PREFIX_SIGN
;
703 Flags
|= PREFIX_BLANK
;
713 if ((Flags
& PRECISION
) == 0) {
714 Flags
|= PAD_TO_WIDTH
;
715 if (BaseListMarker
== NULL
) {
716 Width
= VA_ARG (VaListMarker
, UINTN
);
718 Width
= BASE_ARG (BaseListMarker
, UINTN
);
721 if (BaseListMarker
== NULL
) {
722 Precision
= VA_ARG (VaListMarker
, UINTN
);
724 Precision
= BASE_ARG (BaseListMarker
, UINTN
);
729 if ((Flags
& PRECISION
) == 0) {
730 Flags
|= PREFIX_ZERO
;
741 for (Count
= 0; ((FormatCharacter
>= '0') && (FormatCharacter
<= '9')); ){
742 Count
= (Count
* 10) + FormatCharacter
- '0';
743 Format
+= BytesPerFormatCharacter
;
744 FormatCharacter
= ((*Format
& 0xff) | ((BytesPerFormatCharacter
== 1) ? 0 : (*(Format
+ 1) << 8))) & FormatMask
;
746 Format
-= BytesPerFormatCharacter
;
747 if ((Flags
& PRECISION
) == 0) {
748 Flags
|= PAD_TO_WIDTH
;
757 // Make no output if Format string terminates unexpectedly when
758 // looking up for flag, width, precision and type.
760 Format
-= BytesPerFormatCharacter
;
763 // break skipped on purpose.
772 // Handle each argument type
774 switch (FormatCharacter
) {
777 // Flag space, +, 0, L & l are invalid for type p.
779 Flags
&= ~((UINTN
) (PREFIX_BLANK
| PREFIX_SIGN
| PREFIX_ZERO
| LONG_TYPE
));
780 if (sizeof (VOID
*) > 4) {
784 // break skipped on purpose
787 Flags
|= PREFIX_ZERO
;
789 // break skipped on purpose
794 // break skipped on purpose
797 if ((Flags
& RADIX_HEX
) == 0) {
798 Flags
&= ~((UINTN
) (PREFIX_SIGN
));
799 Flags
|= UNSIGNED_TYPE
;
802 // break skipped on purpose
805 if ((Flags
& LONG_TYPE
) == 0) {
807 // 'd', 'u', 'x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".
808 // This assumption is made so the format string definition is compatible with the ANSI C
809 // Specification for formatted strings. It is recommended that the Base Types be used
810 // everywhere, but in this one case, compliance with ANSI C is more important, and
811 // provides an implementation that is compatible with that largest possible set of CPU
812 // architectures. This is why the type "int" is used in this one case.
814 if (BaseListMarker
== NULL
) {
815 Value
= VA_ARG (VaListMarker
, int);
817 Value
= BASE_ARG (BaseListMarker
, int);
820 if (BaseListMarker
== NULL
) {
821 Value
= VA_ARG (VaListMarker
, INT64
);
823 Value
= BASE_ARG (BaseListMarker
, INT64
);
826 if ((Flags
& PREFIX_BLANK
) != 0) {
829 if ((Flags
& PREFIX_SIGN
) != 0) {
832 if ((Flags
& COMMA_TYPE
) != 0) {
835 if ((Flags
& RADIX_HEX
) == 0) {
838 Flags
&= ~((UINTN
) PREFIX_ZERO
);
841 if (Value
< 0 && (Flags
& UNSIGNED_TYPE
) == 0) {
842 Flags
|= PREFIX_SIGN
;
845 } else if ((Flags
& UNSIGNED_TYPE
) != 0 && (Flags
& LONG_TYPE
) == 0) {
847 // 'd', 'u', 'x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".
848 // This assumption is made so the format string definition is compatible with the ANSI C
849 // Specification for formatted strings. It is recommended that the Base Types be used
850 // everywhere, but in this one case, compliance with ANSI C is more important, and
851 // provides an implementation that is compatible with that largest possible set of CPU
852 // architectures. This is why the type "unsigned int" is used in this one case.
854 Value
= (unsigned int)Value
;
859 if ((Flags
& LONG_TYPE
) == 0 && Value
< 0) {
861 // 'd', 'u', 'x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".
862 // This assumption is made so the format string definition is compatible with the ANSI C
863 // Specification for formatted strings. It is recommended that the Base Types be used
864 // everywhere, but in this one case, compliance with ANSI C is more important, and
865 // provides an implementation that is compatible with that largest possible set of CPU
866 // architectures. This is why the type "unsigned int" is used in this one case.
868 Value
= (unsigned int)Value
;
872 // Convert Value to a reversed string
874 Count
= BasePrintLibValueToString (ValueBuffer
, Value
, Radix
) - ValueBuffer
;
875 if (Value
== 0 && Precision
== 0) {
878 ArgumentString
= (CHAR8
*)ValueBuffer
+ Count
;
884 if (Comma
&& Count
!= 0) {
885 Count
+= ((Count
- 1) / 3);
891 Flags
|= ARGUMENT_REVERSED
;
893 if ((Flags
& PREFIX_ZERO
) != 0) {
894 if ((Flags
& LEFT_JUSTIFY
) == 0) {
895 if ((Flags
& PAD_TO_WIDTH
) != 0) {
896 if ((Flags
& PRECISION
) == 0) {
906 Flags
|= ARGUMENT_UNICODE
;
908 // break skipped on purpose
911 if (BaseListMarker
== NULL
) {
912 ArgumentString
= VA_ARG (VaListMarker
, CHAR8
*);
914 ArgumentString
= BASE_ARG (BaseListMarker
, CHAR8
*);
916 if (ArgumentString
== NULL
) {
917 Flags
&= ~((UINTN
) ARGUMENT_UNICODE
);
918 ArgumentString
= "<null string>";
921 // Set the default precision for string to be zero if not specified.
923 if ((Flags
& PRECISION
) == 0) {
929 if (BaseListMarker
== NULL
) {
930 Character
= VA_ARG (VaListMarker
, UINTN
) & 0xffff;
932 Character
= BASE_ARG (BaseListMarker
, UINTN
) & 0xffff;
934 ArgumentString
= (CHAR8
*)&Character
;
935 Flags
|= ARGUMENT_UNICODE
;
939 if (BaseListMarker
== NULL
) {
940 TmpGuid
= VA_ARG (VaListMarker
, GUID
*);
942 TmpGuid
= BASE_ARG (BaseListMarker
, GUID
*);
944 if (TmpGuid
== NULL
) {
945 ArgumentString
= "<null guid>";
947 GuidData1
= ReadUnaligned32 (&(TmpGuid
->Data1
));
948 GuidData2
= ReadUnaligned16 (&(TmpGuid
->Data2
));
949 GuidData3
= ReadUnaligned16 (&(TmpGuid
->Data3
));
952 MAXIMUM_VALUE_CHARACTERS
,
954 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
967 ArgumentString
= ValueBuffer
;
972 if (BaseListMarker
== NULL
) {
973 TmpTime
= VA_ARG (VaListMarker
, TIME
*);
975 TmpTime
= BASE_ARG (BaseListMarker
, TIME
*);
977 if (TmpTime
== NULL
) {
978 ArgumentString
= "<null time>";
982 MAXIMUM_VALUE_CHARACTERS
,
984 "%02d/%02d/%04d %02d:%02d",
991 ArgumentString
= ValueBuffer
;
996 if (BaseListMarker
== NULL
) {
997 Status
= VA_ARG (VaListMarker
, RETURN_STATUS
);
999 Status
= BASE_ARG (BaseListMarker
, RETURN_STATUS
);
1001 ArgumentString
= ValueBuffer
;
1002 if (RETURN_ERROR (Status
)) {
1006 Index
= Status
& ~MAX_BIT
;
1007 if (Index
> 0 && Index
<= ERROR_STATUS_NUMBER
) {
1008 ArgumentString
= mErrorString
[Index
- 1];
1012 if (Index
<= WARNING_STATUS_NUMBER
) {
1013 ArgumentString
= mWarningString
[Index
];
1016 if (ArgumentString
== ValueBuffer
) {
1017 BasePrintLibSPrint ((CHAR8
*) ValueBuffer
, MAXIMUM_VALUE_CHARACTERS
, 0, "%08X", Status
);
1022 Format
+= BytesPerFormatCharacter
;
1023 FormatCharacter
= ((*Format
& 0xff) | ((BytesPerFormatCharacter
== 1) ? 0 : (*(Format
+ 1) << 8))) & FormatMask
;
1024 if (FormatCharacter
== '\n') {
1026 // Translate '\r\n' to '\r\n'
1028 ArgumentString
= "\r\n";
1031 // Translate '\r' to '\r'
1033 ArgumentString
= "\r";
1034 Format
-= BytesPerFormatCharacter
;
1040 // Translate '\n' to '\r\n' and '\n\r' to '\r\n'
1042 ArgumentString
= "\r\n";
1043 Format
+= BytesPerFormatCharacter
;
1044 FormatCharacter
= ((*Format
& 0xff) | ((BytesPerFormatCharacter
== 1) ? 0 : (*(Format
+ 1) << 8))) & FormatMask
;
1045 if (FormatCharacter
!= '\r') {
1046 Format
-= BytesPerFormatCharacter
;
1053 // if the type is '%' or unknown, then print it to the screen
1055 ArgumentString
= (CHAR8
*)&FormatCharacter
;
1056 Flags
|= ARGUMENT_UNICODE
;
1062 Format
+= BytesPerFormatCharacter
;
1063 FormatCharacter
= ((*Format
& 0xff) | ((BytesPerFormatCharacter
== 1) ? 0 : (*(Format
+ 1) << 8))) & FormatMask
;
1064 if (FormatCharacter
== '\n') {
1066 // Translate '\r\n' to '\r\n'
1068 ArgumentString
= "\r\n";
1071 // Translate '\r' to '\r'
1073 ArgumentString
= "\r";
1074 Format
-= BytesPerFormatCharacter
;
1080 // Translate '\n' to '\r\n' and '\n\r' to '\r\n'
1082 ArgumentString
= "\r\n";
1083 Format
+= BytesPerFormatCharacter
;
1084 FormatCharacter
= ((*Format
& 0xff) | ((BytesPerFormatCharacter
== 1) ? 0 : (*(Format
+ 1) << 8))) & FormatMask
;
1085 if (FormatCharacter
!= '\r') {
1086 Format
-= BytesPerFormatCharacter
;
1091 ArgumentString
= (CHAR8
*)&FormatCharacter
;
1092 Flags
|= ARGUMENT_UNICODE
;
1097 // Retrieve the ArgumentString attriubutes
1099 if ((Flags
& ARGUMENT_UNICODE
) != 0) {
1100 ArgumentMask
= 0xffff;
1101 BytesPerArgumentCharacter
= 2;
1103 ArgumentMask
= 0xff;
1104 BytesPerArgumentCharacter
= 1;
1106 if ((Flags
& ARGUMENT_REVERSED
) != 0) {
1107 BytesPerArgumentCharacter
= -BytesPerArgumentCharacter
;
1110 // Compute the number of characters in ArgumentString and store it in Count
1111 // ArgumentString is either null-terminated, or it contains Precision characters
1114 (ArgumentString
[Count
* BytesPerArgumentCharacter
] != '\0' ||
1115 (BytesPerArgumentCharacter
> 1 &&
1116 ArgumentString
[Count
* BytesPerArgumentCharacter
+ 1]!= '\0')) &&
1117 (Count
< Precision
|| ((Flags
& PRECISION
) == 0));
1119 ArgumentCharacter
= ((ArgumentString
[Count
* BytesPerArgumentCharacter
] & 0xff) | ((ArgumentString
[Count
* BytesPerArgumentCharacter
+ 1]) << 8)) & ArgumentMask
;
1120 if (ArgumentCharacter
== 0) {
1126 if (Precision
< Count
) {
1131 // Pad before the string
1133 if ((Flags
& (PAD_TO_WIDTH
| LEFT_JUSTIFY
)) == (PAD_TO_WIDTH
)) {
1134 LengthToReturn
+= ((Width
- Precision
) * BytesPerOutputCharacter
);
1135 if ((Flags
& COUNT_ONLY_NO_PRINT
) == 0 && Buffer
!= NULL
) {
1136 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, Width
- Precision
, ' ', BytesPerOutputCharacter
);
1142 LengthToReturn
+= (1 * BytesPerOutputCharacter
);
1143 if ((Flags
& COUNT_ONLY_NO_PRINT
) == 0 && Buffer
!= NULL
) {
1144 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, 1, Prefix
, BytesPerOutputCharacter
);
1147 LengthToReturn
+= ((Precision
- Count
) * BytesPerOutputCharacter
);
1148 if ((Flags
& COUNT_ONLY_NO_PRINT
) == 0 && Buffer
!= NULL
) {
1149 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, Precision
- Count
, '0', BytesPerOutputCharacter
);
1152 LengthToReturn
+= ((Precision
- Count
) * BytesPerOutputCharacter
);
1153 if ((Flags
& COUNT_ONLY_NO_PRINT
) == 0 && Buffer
!= NULL
) {
1154 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, Precision
- Count
, ' ', BytesPerOutputCharacter
);
1157 LengthToReturn
+= (1 * BytesPerOutputCharacter
);
1158 if ((Flags
& COUNT_ONLY_NO_PRINT
) == 0 && Buffer
!= NULL
) {
1159 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, 1, Prefix
, BytesPerOutputCharacter
);
1165 // Output the Prefix character if it is present
1173 // Copy the string into the output buffer performing the required type conversions
1175 while (Index
< Count
&&
1176 (ArgumentString
[0] != '\0' ||
1177 (BytesPerArgumentCharacter
> 1 && ArgumentString
[1] != '\0'))) {
1178 ArgumentCharacter
= ((*ArgumentString
& 0xff) | (((UINT8
)*(ArgumentString
+ 1)) << 8)) & ArgumentMask
;
1180 LengthToReturn
+= (1 * BytesPerOutputCharacter
);
1181 if ((Flags
& COUNT_ONLY_NO_PRINT
) == 0 && Buffer
!= NULL
) {
1182 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, 1, ArgumentCharacter
, BytesPerOutputCharacter
);
1184 ArgumentString
+= BytesPerArgumentCharacter
;
1191 if (Index
< Count
) {
1192 LengthToReturn
+= (1 * BytesPerOutputCharacter
);
1193 if ((Flags
& COUNT_ONLY_NO_PRINT
) == 0 && Buffer
!= NULL
) {
1194 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, 1, ',', BytesPerOutputCharacter
);
1202 // Pad after the string
1204 if ((Flags
& (PAD_TO_WIDTH
| LEFT_JUSTIFY
)) == (PAD_TO_WIDTH
| LEFT_JUSTIFY
)) {
1205 LengthToReturn
+= ((Width
- Precision
) * BytesPerOutputCharacter
);
1206 if ((Flags
& COUNT_ONLY_NO_PRINT
) == 0 && Buffer
!= NULL
) {
1207 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, Width
- Precision
, ' ', BytesPerOutputCharacter
);
1212 // Get the next character from the format string
1214 Format
+= BytesPerFormatCharacter
;
1217 // Get the next character from the format string
1219 FormatCharacter
= ((*Format
& 0xff) | ((BytesPerFormatCharacter
== 1) ? 0 : (*(Format
+ 1) << 8))) & FormatMask
;
1222 if ((Flags
& COUNT_ONLY_NO_PRINT
) != 0) {
1223 return (LengthToReturn
/ BytesPerOutputCharacter
);
1226 ASSERT (Buffer
!= NULL
);
1228 // Null terminate the Unicode or ASCII string
1230 BasePrintLibFillBuffer (Buffer
, EndBuffer
+ BytesPerOutputCharacter
, 1, 0, BytesPerOutputCharacter
);
1232 return ((Buffer
- OriginalBuffer
) / BytesPerOutputCharacter
);
1236 Worker function that produces a Null-terminated string in an output buffer
1237 based on a Null-terminated format string and variable argument list.
1239 VSPrint function to process format and place the results in Buffer. Since a
1240 VA_LIST is used this routine allows the nesting of Vararg routines. Thus
1241 this is the main print working routine
1243 @param StartOfBuffer The character buffer to print the results of the parsing
1245 @param BufferSize The maximum number of characters to put into buffer.
1246 Zero means no limit.
1247 @param Flags Initial flags value.
1248 Can only have FORMAT_UNICODE and OUTPUT_UNICODE set
1249 @param FormatString A Null-terminated format string.
1250 @param ... The variable argument list.
1252 @return The number of characters printed.
1257 BasePrintLibSPrint (
1258 OUT CHAR8
*StartOfBuffer
,
1259 IN UINTN BufferSize
,
1261 IN CONST CHAR8
*FormatString
,
1266 UINTN NumberOfPrinted
;
1268 VA_START (Marker
, FormatString
);
1269 NumberOfPrinted
= BasePrintLibSPrintMarker (StartOfBuffer
, BufferSize
, Flags
, FormatString
, Marker
, NULL
);
1271 return NumberOfPrinted
;