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
82 Internal function that places the character into the Buffer.
84 Internal function that places ASCII or Unicode character into the Buffer.
86 @param Buffer The buffer to place the Unicode or ASCII string.
87 @param EndBuffer The end of the input Buffer. No characters will be
89 @param Length The count of character to be placed into Buffer.
90 (Negative value indicates no buffer fill.)
91 @param Character The character to be placed into Buffer.
92 @param Increment The character increment in Buffer.
98 BasePrintLibFillBuffer (
108 for (Index
= 0; Index
< Length
&& Buffer
< EndBuffer
; Index
++) {
109 *Buffer
= (CHAR8
)Character
;
110 if (Increment
!= 1) {
111 *(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
);
237 // If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed.
240 Width
= MAXIMUM_VALUE_CHARACTERS
- 1;
244 // Set the tag for the end of the input Buffer.
246 EndBuffer
= Buffer
+ Width
* Increment
;
249 // Convert decimal negative
251 if ((Value
< 0) && ((Flags
& RADIX_HEX
) == 0)) {
253 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, 1, '-', Increment
);
258 // Count the length of the value string.
260 Radix
= ((Flags
& RADIX_HEX
) == 0) ? 10 : 16;
261 ValueBufferPtr
= BasePrintLibValueToString (ValueBuffer
, Value
, Radix
);
262 Count
= ValueBufferPtr
- ValueBuffer
;
267 if ((Flags
& PREFIX_ZERO
) != 0) {
268 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, Width
- Count
, '0', Increment
);
272 // Print Comma type for every 3 characters
279 for (Index
= 0; Index
< Count
; Index
++) {
280 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, 1, *ValueBufferPtr
--, Increment
);
281 if ((Flags
& COMMA_TYPE
) != 0) {
285 if ((Index
+ 1) < Count
) {
286 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, 1, ',', Increment
);
293 // Print Null-terminator
295 BasePrintLibFillBuffer (Buffer
, EndBuffer
+ Increment
, 1, 0, Increment
);
297 return ((Buffer
- OriginalBuffer
) / Increment
);
301 Internal function that converts a decimal value to a Null-terminated string.
303 Converts the decimal number specified by Value to a Null-terminated string
304 specified by Buffer containing at most Width characters. If Width is 0 then a
305 width of MAXIMUM_VALUE_CHARACTERS is assumed. If the conversion contains more
306 than Width characters, then only the first Width characters are placed in
307 Buffer. Additional conversion parameters are specified in Flags.
308 The Flags bit LEFT_JUSTIFY is always ignored.
309 All conversions are left justified in Buffer.
310 If Width is 0, PREFIX_ZERO is ignored in Flags.
311 If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and
312 commas are inserted every 3rd digit starting from the right.
313 If Value is < 0, then the fist character in Buffer is a '-'.
314 If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored,
315 then Buffer is padded with '0' characters so the combination of the optional
316 '-' sign character, '0' characters, digit characters for Value, and the
317 Null-terminator add up to Width characters.
319 If an error would be returned, the function will ASSERT().
321 @param Buffer The pointer to the output buffer for the produced
322 Null-terminated string.
323 @param BufferSize The size of Buffer in bytes, including the
325 @param Flags The bitmask of flags that specify left justification,
326 zero pad, and commas.
327 @param Value The 64-bit signed value to convert to a string.
328 @param Width The maximum number of characters to place in Buffer,
329 not including the Null-terminator.
330 @param Increment The character increment in Buffer.
332 @retval RETURN_SUCCESS The decimal value is converted.
333 @retval RETURN_BUFFER_TOO_SMALL If BufferSize cannot hold the converted
335 @retval RETURN_INVALID_PARAMETER If Buffer is NULL.
336 If Increment is 1 and
337 PcdMaximumAsciiStringLength is not zero,
338 BufferSize is greater than
339 PcdMaximumAsciiStringLength.
340 If Increment is not 1 and
341 PcdMaximumUnicodeStringLength is not zero,
342 BufferSize is greater than
343 (PcdMaximumUnicodeStringLength *
344 sizeof (CHAR16) + 1).
345 If unsupported bits are set in Flags.
346 If both COMMA_TYPE and RADIX_HEX are set in
348 If Width >= MAXIMUM_VALUE_CHARACTERS.
352 BasePrintLibConvertValueToStringS (
353 IN OUT CHAR8
*Buffer
,
362 CHAR8 ValueBuffer
[MAXIMUM_VALUE_CHARACTERS
];
363 CHAR8
*ValueBufferPtr
;
370 // 1. Buffer shall not be a null pointer.
372 SAFE_PRINT_CONSTRAINT_CHECK ((Buffer
!= NULL
), RETURN_INVALID_PARAMETER
);
375 // 2. BufferSize shall not be greater than (RSIZE_MAX * sizeof (CHAR16)) for
376 // Unicode output string or shall not be greater than ASCII_RSIZE_MAX for
377 // Ascii output string.
379 if (Increment
== 1) {
381 // Ascii output string
383 if (ASCII_RSIZE_MAX
!= 0) {
384 SAFE_PRINT_CONSTRAINT_CHECK ((BufferSize
<= ASCII_RSIZE_MAX
), RETURN_INVALID_PARAMETER
);
388 // Unicode output string
390 if (RSIZE_MAX
!= 0) {
391 SAFE_PRINT_CONSTRAINT_CHECK ((BufferSize
<= RSIZE_MAX
* sizeof (CHAR16
) + 1), RETURN_INVALID_PARAMETER
);
396 // 3. Flags shall be set properly.
398 SAFE_PRINT_CONSTRAINT_CHECK (((Flags
& ~(LEFT_JUSTIFY
| COMMA_TYPE
| PREFIX_ZERO
| RADIX_HEX
)) == 0), RETURN_INVALID_PARAMETER
);
399 SAFE_PRINT_CONSTRAINT_CHECK ((((Flags
& COMMA_TYPE
) == 0) || ((Flags
& RADIX_HEX
) == 0)), RETURN_INVALID_PARAMETER
);
402 // 4. Width shall be smaller than MAXIMUM_VALUE_CHARACTERS.
404 SAFE_PRINT_CONSTRAINT_CHECK ((Width
< MAXIMUM_VALUE_CHARACTERS
), RETURN_INVALID_PARAMETER
);
407 // Width is 0 or COMMA_TYPE is set, PREFIX_ZERO is ignored.
409 if ((Width
== 0) || ((Flags
& COMMA_TYPE
) != 0)) {
410 Flags
&= ~((UINTN
)PREFIX_ZERO
);
414 // If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed.
417 Width
= MAXIMUM_VALUE_CHARACTERS
- 1;
421 // Count the characters of the output string.
424 Radix
= ((Flags
& RADIX_HEX
) == 0) ? 10 : 16;
426 if ((Flags
& PREFIX_ZERO
) != 0) {
429 if ((Value
< 0) && ((Flags
& RADIX_HEX
) == 0)) {
430 Count
++; // minus sign
431 ValueBufferPtr
= BasePrintLibValueToString (ValueBuffer
, -Value
, Radix
);
433 ValueBufferPtr
= BasePrintLibValueToString (ValueBuffer
, Value
, Radix
);
436 Digits
= ValueBufferPtr
- ValueBuffer
;
439 if ((Flags
& COMMA_TYPE
) != 0) {
440 Count
+= (Digits
- 1) / 3; // commas
444 Width
= MIN (Count
, Width
);
447 // 5. BufferSize shall be large enough to hold the converted string.
449 SAFE_PRINT_CONSTRAINT_CHECK ((BufferSize
>= (Width
+ 1) * Increment
), RETURN_BUFFER_TOO_SMALL
);
452 // Set the tag for the end of the input Buffer.
454 EndBuffer
= Buffer
+ Width
* Increment
;
457 // Convert decimal negative
459 if ((Value
< 0) && ((Flags
& RADIX_HEX
) == 0)) {
461 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, 1, '-', Increment
);
466 // Count the length of the value string.
468 ValueBufferPtr
= BasePrintLibValueToString (ValueBuffer
, Value
, Radix
);
469 Count
= ValueBufferPtr
- ValueBuffer
;
474 if ((Flags
& PREFIX_ZERO
) != 0) {
475 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, Width
- Count
, '0', Increment
);
479 // Print Comma type for every 3 characters
486 for (Index
= 0; Index
< Count
; Index
++) {
487 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, 1, *ValueBufferPtr
--, Increment
);
488 if ((Flags
& COMMA_TYPE
) != 0) {
492 if ((Index
+ 1) < Count
) {
493 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, 1, ',', Increment
);
500 // Print Null-terminator
502 BasePrintLibFillBuffer (Buffer
, EndBuffer
+ Increment
, 1, 0, Increment
);
504 return RETURN_SUCCESS
;
508 Worker function that produces a Null-terminated string in an output buffer
509 based on a Null-terminated format string and a VA_LIST argument list.
511 VSPrint function to process format and place the results in Buffer. Since a
512 VA_LIST is used this routine allows the nesting of Vararg routines. Thus
513 this is the main print working routine.
515 If COUNT_ONLY_NO_PRINT is set in Flags, Buffer will not be modified at all.
517 @param[out] Buffer The character buffer to print the results of the
518 parsing of Format into.
519 @param[in] BufferSize The maximum number of characters to put into
521 @param[in] Flags Initial flags value.
522 Can only have FORMAT_UNICODE, OUTPUT_UNICODE,
523 and COUNT_ONLY_NO_PRINT set.
524 @param[in] Format A Null-terminated format string.
525 @param[in] VaListMarker VA_LIST style variable argument list consumed by
527 @param[in] BaseListMarker BASE_LIST style variable argument list consumed
528 by processing Format.
530 @return The number of characters printed not including the Null-terminator.
531 If COUNT_ONLY_NO_PRINT was set returns the same, but without any
532 modification to Buffer.
536 BasePrintLibSPrintMarker (
540 IN CONST CHAR8
*Format
,
541 IN VA_LIST VaListMarker OPTIONAL
,
542 IN BASE_LIST BaseListMarker OPTIONAL
545 CHAR8
*OriginalBuffer
;
547 CHAR8 ValueBuffer
[MAXIMUM_VALUE_CHARACTERS
];
548 UINT32 BytesPerOutputCharacter
;
549 UINTN BytesPerFormatCharacter
;
551 UINTN FormatCharacter
;
555 CONST CHAR8
*ArgumentString
;
561 INTN BytesPerArgumentCharacter
;
562 UINTN ArgumentCharacter
;
570 RETURN_STATUS Status
;
574 UINTN LengthToReturn
;
577 // If you change this code be sure to match the 2 versions of this function.
578 // Nearly identical logic is found in the BasePrintLib and
579 // DxePrintLibPrint2Protocol (both PrintLib instances).
583 // 1. Buffer shall not be a null pointer when both BufferSize > 0 and
584 // COUNT_ONLY_NO_PRINT is not set in Flags.
586 if ((BufferSize
> 0) && ((Flags
& COUNT_ONLY_NO_PRINT
) == 0)) {
587 SAFE_PRINT_CONSTRAINT_CHECK ((Buffer
!= NULL
), 0);
591 // 2. Format shall not be a null pointer when BufferSize > 0 or when
592 // COUNT_ONLY_NO_PRINT is set in Flags.
594 if ((BufferSize
> 0) || ((Flags
& COUNT_ONLY_NO_PRINT
) != 0)) {
595 SAFE_PRINT_CONSTRAINT_CHECK ((Format
!= NULL
), 0);
599 // 3. BufferSize shall not be greater than RSIZE_MAX for Unicode output or
600 // ASCII_RSIZE_MAX for Ascii output.
602 if ((Flags
& OUTPUT_UNICODE
) != 0) {
603 if (RSIZE_MAX
!= 0) {
604 SAFE_PRINT_CONSTRAINT_CHECK ((BufferSize
<= RSIZE_MAX
), 0);
607 BytesPerOutputCharacter
= 2;
609 if (ASCII_RSIZE_MAX
!= 0) {
610 SAFE_PRINT_CONSTRAINT_CHECK ((BufferSize
<= ASCII_RSIZE_MAX
), 0);
613 BytesPerOutputCharacter
= 1;
617 // 4. Format shall not contain more than RSIZE_MAX Unicode characters or
618 // ASCII_RSIZE_MAX Ascii characters.
620 if ((Flags
& FORMAT_UNICODE
) != 0) {
621 if (RSIZE_MAX
!= 0) {
622 SAFE_PRINT_CONSTRAINT_CHECK ((StrnLenS ((CHAR16
*)Format
, RSIZE_MAX
+ 1) <= RSIZE_MAX
), 0);
625 BytesPerFormatCharacter
= 2;
628 if (ASCII_RSIZE_MAX
!= 0) {
629 SAFE_PRINT_CONSTRAINT_CHECK ((AsciiStrnLenS (Format
, ASCII_RSIZE_MAX
+ 1) <= ASCII_RSIZE_MAX
), 0);
632 BytesPerFormatCharacter
= 1;
636 if ((Flags
& COUNT_ONLY_NO_PRINT
) != 0) {
637 if (BufferSize
== 0) {
642 // We can run without a Buffer for counting only.
644 if (BufferSize
== 0) {
651 OriginalBuffer
= NULL
;
654 // Reserve space for the Null terminator.
656 if (Buffer
!= NULL
) {
658 OriginalBuffer
= Buffer
;
661 // Set the tag for the end of the input Buffer.
663 EndBuffer
= Buffer
+ BufferSize
* BytesPerOutputCharacter
;
667 // Get the first character from the format string
669 FormatCharacter
= ((*Format
& 0xff) | ((BytesPerFormatCharacter
== 1) ? 0 : (*(Format
+ 1) << 8))) & FormatMask
;
672 // Loop until the end of the format string is reached or the output buffer is full
674 while (FormatCharacter
!= 0) {
675 if ((Buffer
!= NULL
) && (Buffer
>= EndBuffer
)) {
680 // Clear all the flag bits except those that may have been passed in
682 Flags
&= (UINTN
)(OUTPUT_UNICODE
| FORMAT_UNICODE
| COUNT_ONLY_NO_PRINT
);
685 // Set the default width to zero, and the default precision to 1
695 switch (FormatCharacter
) {
698 // Parse Flags and Width
700 for (Done
= FALSE
; !Done
; ) {
701 Format
+= BytesPerFormatCharacter
;
702 FormatCharacter
= ((*Format
& 0xff) | ((BytesPerFormatCharacter
== 1) ? 0 : (*(Format
+ 1) << 8))) & FormatMask
;
703 switch (FormatCharacter
) {
708 Flags
|= LEFT_JUSTIFY
;
711 Flags
|= PREFIX_SIGN
;
714 Flags
|= PREFIX_BLANK
;
724 if ((Flags
& PRECISION
) == 0) {
725 Flags
|= PAD_TO_WIDTH
;
726 if (BaseListMarker
== NULL
) {
727 Width
= VA_ARG (VaListMarker
, UINTN
);
729 Width
= BASE_ARG (BaseListMarker
, UINTN
);
732 if (BaseListMarker
== NULL
) {
733 Precision
= VA_ARG (VaListMarker
, UINTN
);
735 Precision
= BASE_ARG (BaseListMarker
, UINTN
);
741 if ((Flags
& PRECISION
) == 0) {
742 Flags
|= PREFIX_ZERO
;
754 for (Count
= 0; ((FormatCharacter
>= '0') && (FormatCharacter
<= '9')); ) {
755 Count
= (Count
* 10) + FormatCharacter
- '0';
756 Format
+= BytesPerFormatCharacter
;
757 FormatCharacter
= ((*Format
& 0xff) | ((BytesPerFormatCharacter
== 1) ? 0 : (*(Format
+ 1) << 8))) & FormatMask
;
760 Format
-= BytesPerFormatCharacter
;
761 if ((Flags
& PRECISION
) == 0) {
762 Flags
|= PAD_TO_WIDTH
;
772 // Make no output if Format string terminates unexpectedly when
773 // looking up for flag, width, precision and type.
775 Format
-= BytesPerFormatCharacter
;
778 // break skipped on purpose.
787 // Handle each argument type
789 switch (FormatCharacter
) {
792 // Flag space, +, 0, L & l are invalid for type p.
794 Flags
&= ~((UINTN
)(PREFIX_BLANK
| PREFIX_SIGN
| PREFIX_ZERO
| LONG_TYPE
));
795 if (sizeof (VOID
*) > 4) {
800 // break skipped on purpose
803 Flags
|= PREFIX_ZERO
;
805 // break skipped on purpose
810 // break skipped on purpose
813 if ((Flags
& RADIX_HEX
) == 0) {
814 Flags
&= ~((UINTN
)(PREFIX_SIGN
));
815 Flags
|= UNSIGNED_TYPE
;
819 // break skipped on purpose
822 if ((Flags
& LONG_TYPE
) == 0) {
824 // 'd', 'u', 'x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".
825 // This assumption is made so the format string definition is compatible with the ANSI C
826 // Specification for formatted strings. It is recommended that the Base Types be used
827 // everywhere, but in this one case, compliance with ANSI C is more important, and
828 // provides an implementation that is compatible with that largest possible set of CPU
829 // architectures. This is why the type "int" is used in this one case.
831 if (BaseListMarker
== NULL
) {
832 Value
= VA_ARG (VaListMarker
, int);
834 Value
= BASE_ARG (BaseListMarker
, int);
837 if (BaseListMarker
== NULL
) {
838 Value
= VA_ARG (VaListMarker
, INT64
);
840 Value
= BASE_ARG (BaseListMarker
, INT64
);
844 if ((Flags
& PREFIX_BLANK
) != 0) {
848 if ((Flags
& PREFIX_SIGN
) != 0) {
852 if ((Flags
& COMMA_TYPE
) != 0) {
856 if ((Flags
& RADIX_HEX
) == 0) {
859 Flags
&= ~((UINTN
)PREFIX_ZERO
);
863 if ((Value
< 0) && ((Flags
& UNSIGNED_TYPE
) == 0)) {
864 Flags
|= PREFIX_SIGN
;
867 } else if (((Flags
& UNSIGNED_TYPE
) != 0) && ((Flags
& LONG_TYPE
) == 0)) {
869 // 'd', 'u', 'x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".
870 // This assumption is made so the format string definition is compatible with the ANSI C
871 // Specification for formatted strings. It is recommended that the Base Types be used
872 // everywhere, but in this one case, compliance with ANSI C is more important, and
873 // provides an implementation that is compatible with that largest possible set of CPU
874 // architectures. This is why the type "unsigned int" is used in this one case.
876 Value
= (unsigned int)Value
;
881 if (((Flags
& LONG_TYPE
) == 0) && (Value
< 0)) {
883 // 'd', 'u', 'x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".
884 // This assumption is made so the format string definition is compatible with the ANSI C
885 // Specification for formatted strings. It is recommended that the Base Types be used
886 // everywhere, but in this one case, compliance with ANSI C is more important, and
887 // provides an implementation that is compatible with that largest possible set of CPU
888 // architectures. This is why the type "unsigned int" is used in this one case.
890 Value
= (unsigned int)Value
;
895 // Convert Value to a reversed string
897 Count
= BasePrintLibValueToString (ValueBuffer
, Value
, Radix
) - ValueBuffer
;
898 if ((Value
== 0) && (Precision
== 0)) {
902 ArgumentString
= (CHAR8
*)ValueBuffer
+ Count
;
909 if (Comma
&& (Count
!= 0)) {
910 Count
+= ((Count
- 1) / 3);
918 Flags
|= ARGUMENT_REVERSED
;
920 if ((Flags
& PREFIX_ZERO
) != 0) {
921 if ((Flags
& LEFT_JUSTIFY
) == 0) {
922 if ((Flags
& PAD_TO_WIDTH
) != 0) {
923 if ((Flags
& PRECISION
) == 0) {
934 Flags
|= ARGUMENT_UNICODE
;
936 // break skipped on purpose
939 if (BaseListMarker
== NULL
) {
940 ArgumentString
= VA_ARG (VaListMarker
, CHAR8
*);
942 ArgumentString
= BASE_ARG (BaseListMarker
, CHAR8
*);
945 if (ArgumentString
== NULL
) {
946 Flags
&= ~((UINTN
)ARGUMENT_UNICODE
);
947 ArgumentString
= "<null string>";
951 // Set the default precision for string to be zero if not specified.
953 if ((Flags
& PRECISION
) == 0) {
960 if (BaseListMarker
== NULL
) {
961 Character
= VA_ARG (VaListMarker
, UINTN
) & 0xffff;
963 Character
= BASE_ARG (BaseListMarker
, UINTN
) & 0xffff;
966 ArgumentString
= (CHAR8
*)&Character
;
967 Flags
|= ARGUMENT_UNICODE
;
971 if (BaseListMarker
== NULL
) {
972 TmpGuid
= VA_ARG (VaListMarker
, GUID
*);
974 TmpGuid
= BASE_ARG (BaseListMarker
, GUID
*);
977 if (TmpGuid
== NULL
) {
978 ArgumentString
= "<null guid>";
980 GuidData1
= ReadUnaligned32 (&(TmpGuid
->Data1
));
981 GuidData2
= ReadUnaligned16 (&(TmpGuid
->Data2
));
982 GuidData3
= ReadUnaligned16 (&(TmpGuid
->Data3
));
985 MAXIMUM_VALUE_CHARACTERS
,
987 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1000 ArgumentString
= ValueBuffer
;
1006 if (BaseListMarker
== NULL
) {
1007 TmpTime
= VA_ARG (VaListMarker
, TIME
*);
1009 TmpTime
= BASE_ARG (BaseListMarker
, TIME
*);
1012 if (TmpTime
== NULL
) {
1013 ArgumentString
= "<null time>";
1015 BasePrintLibSPrint (
1017 MAXIMUM_VALUE_CHARACTERS
,
1019 "%02d/%02d/%04d %02d:%02d",
1026 ArgumentString
= ValueBuffer
;
1032 if (BaseListMarker
== NULL
) {
1033 Status
= VA_ARG (VaListMarker
, RETURN_STATUS
);
1035 Status
= BASE_ARG (BaseListMarker
, RETURN_STATUS
);
1038 ArgumentString
= ValueBuffer
;
1039 if (RETURN_ERROR (Status
)) {
1043 Index
= Status
& ~MAX_BIT
;
1044 if ((Index
> 0) && (Index
<= ERROR_STATUS_NUMBER
)) {
1045 ArgumentString
= mErrorString
[Index
- 1];
1049 if (Index
<= WARNING_STATUS_NUMBER
) {
1050 ArgumentString
= mWarningString
[Index
];
1054 if (ArgumentString
== ValueBuffer
) {
1055 BasePrintLibSPrint ((CHAR8
*)ValueBuffer
, MAXIMUM_VALUE_CHARACTERS
, 0, "%08X", Status
);
1061 Format
+= BytesPerFormatCharacter
;
1062 FormatCharacter
= ((*Format
& 0xff) | ((BytesPerFormatCharacter
== 1) ? 0 : (*(Format
+ 1) << 8))) & FormatMask
;
1063 if (FormatCharacter
== '\n') {
1065 // Translate '\r\n' to '\r\n'
1067 ArgumentString
= "\r\n";
1070 // Translate '\r' to '\r'
1072 ArgumentString
= "\r";
1073 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
;
1094 // if the type is '%' or unknown, then print it to the screen
1096 ArgumentString
= (CHAR8
*)&FormatCharacter
;
1097 Flags
|= ARGUMENT_UNICODE
;
1104 Format
+= BytesPerFormatCharacter
;
1105 FormatCharacter
= ((*Format
& 0xff) | ((BytesPerFormatCharacter
== 1) ? 0 : (*(Format
+ 1) << 8))) & FormatMask
;
1106 if (FormatCharacter
== '\n') {
1108 // Translate '\r\n' to '\r\n'
1110 ArgumentString
= "\r\n";
1113 // Translate '\r' to '\r'
1115 ArgumentString
= "\r";
1116 Format
-= BytesPerFormatCharacter
;
1123 // Translate '\n' to '\r\n' and '\n\r' to '\r\n'
1125 ArgumentString
= "\r\n";
1126 Format
+= BytesPerFormatCharacter
;
1127 FormatCharacter
= ((*Format
& 0xff) | ((BytesPerFormatCharacter
== 1) ? 0 : (*(Format
+ 1) << 8))) & FormatMask
;
1128 if (FormatCharacter
!= '\r') {
1129 Format
-= BytesPerFormatCharacter
;
1135 ArgumentString
= (CHAR8
*)&FormatCharacter
;
1136 Flags
|= ARGUMENT_UNICODE
;
1141 // Retrieve the ArgumentString attriubutes
1143 if ((Flags
& ARGUMENT_UNICODE
) != 0) {
1144 ArgumentMask
= 0xffff;
1145 BytesPerArgumentCharacter
= 2;
1147 ArgumentMask
= 0xff;
1148 BytesPerArgumentCharacter
= 1;
1151 if ((Flags
& ARGUMENT_REVERSED
) != 0) {
1152 BytesPerArgumentCharacter
= -BytesPerArgumentCharacter
;
1155 // Compute the number of characters in ArgumentString and store it in Count
1156 // ArgumentString is either null-terminated, or it contains Precision characters
1159 (ArgumentString
[Count
* BytesPerArgumentCharacter
] != '\0' ||
1160 (BytesPerArgumentCharacter
> 1 &&
1161 ArgumentString
[Count
* BytesPerArgumentCharacter
+ 1] != '\0')) &&
1162 (Count
< Precision
|| ((Flags
& PRECISION
) == 0));
1165 ArgumentCharacter
= ((ArgumentString
[Count
* BytesPerArgumentCharacter
] & 0xff) | ((ArgumentString
[Count
* BytesPerArgumentCharacter
+ 1]) << 8)) & ArgumentMask
;
1166 if (ArgumentCharacter
== 0) {
1172 if (Precision
< Count
) {
1177 // Pad before the string
1179 if ((Flags
& (PAD_TO_WIDTH
| LEFT_JUSTIFY
)) == (PAD_TO_WIDTH
)) {
1180 LengthToReturn
+= ((Width
- Precision
) * BytesPerOutputCharacter
);
1181 if (((Flags
& COUNT_ONLY_NO_PRINT
) == 0) && (Buffer
!= NULL
)) {
1182 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, Width
- Precision
, ' ', BytesPerOutputCharacter
);
1188 LengthToReturn
+= (1 * BytesPerOutputCharacter
);
1189 if (((Flags
& COUNT_ONLY_NO_PRINT
) == 0) && (Buffer
!= NULL
)) {
1190 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, 1, Prefix
, BytesPerOutputCharacter
);
1194 LengthToReturn
+= ((Precision
- Count
) * BytesPerOutputCharacter
);
1195 if (((Flags
& COUNT_ONLY_NO_PRINT
) == 0) && (Buffer
!= NULL
)) {
1196 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, Precision
- Count
, '0', BytesPerOutputCharacter
);
1199 LengthToReturn
+= ((Precision
- Count
) * BytesPerOutputCharacter
);
1200 if (((Flags
& COUNT_ONLY_NO_PRINT
) == 0) && (Buffer
!= NULL
)) {
1201 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, Precision
- Count
, ' ', BytesPerOutputCharacter
);
1205 LengthToReturn
+= (1 * BytesPerOutputCharacter
);
1206 if (((Flags
& COUNT_ONLY_NO_PRINT
) == 0) && (Buffer
!= NULL
)) {
1207 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, 1, Prefix
, BytesPerOutputCharacter
);
1213 // Output the Prefix character if it is present
1221 // Copy the string into the output buffer performing the required type conversions
1223 while (Index
< Count
&&
1224 (ArgumentString
[0] != '\0' ||
1225 (BytesPerArgumentCharacter
> 1 && ArgumentString
[1] != '\0')))
1227 ArgumentCharacter
= ((*ArgumentString
& 0xff) | (((UINT8
)*(ArgumentString
+ 1)) << 8)) & ArgumentMask
;
1229 LengthToReturn
+= (1 * BytesPerOutputCharacter
);
1230 if (((Flags
& COUNT_ONLY_NO_PRINT
) == 0) && (Buffer
!= NULL
)) {
1231 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, 1, ArgumentCharacter
, BytesPerOutputCharacter
);
1234 ArgumentString
+= BytesPerArgumentCharacter
;
1241 if (Index
< Count
) {
1242 LengthToReturn
+= (1 * BytesPerOutputCharacter
);
1243 if (((Flags
& COUNT_ONLY_NO_PRINT
) == 0) && (Buffer
!= NULL
)) {
1244 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, 1, ',', BytesPerOutputCharacter
);
1252 // Pad after the string
1254 if ((Flags
& (PAD_TO_WIDTH
| LEFT_JUSTIFY
)) == (PAD_TO_WIDTH
| LEFT_JUSTIFY
)) {
1255 LengthToReturn
+= ((Width
- Precision
) * BytesPerOutputCharacter
);
1256 if (((Flags
& COUNT_ONLY_NO_PRINT
) == 0) && (Buffer
!= NULL
)) {
1257 Buffer
= BasePrintLibFillBuffer (Buffer
, EndBuffer
, Width
- Precision
, ' ', BytesPerOutputCharacter
);
1262 // Get the next character from the format string
1264 Format
+= BytesPerFormatCharacter
;
1267 // Get the next character from the format string
1269 FormatCharacter
= ((*Format
& 0xff) | ((BytesPerFormatCharacter
== 1) ? 0 : (*(Format
+ 1) << 8))) & FormatMask
;
1272 if ((Flags
& COUNT_ONLY_NO_PRINT
) != 0) {
1273 return (LengthToReturn
/ BytesPerOutputCharacter
);
1276 ASSERT (Buffer
!= NULL
);
1278 // Null terminate the Unicode or ASCII string
1280 BasePrintLibFillBuffer (Buffer
, EndBuffer
+ BytesPerOutputCharacter
, 1, 0, BytesPerOutputCharacter
);
1282 return ((Buffer
- OriginalBuffer
) / BytesPerOutputCharacter
);
1286 Worker function that produces a Null-terminated string in an output buffer
1287 based on a Null-terminated format string and variable argument list.
1289 VSPrint function to process format and place the results in Buffer. Since a
1290 VA_LIST is used this routine allows the nesting of Vararg routines. Thus
1291 this is the main print working routine
1293 @param StartOfBuffer The character buffer to print the results of the parsing
1295 @param BufferSize The maximum number of characters to put into buffer.
1296 Zero means no limit.
1297 @param Flags Initial flags value.
1298 Can only have FORMAT_UNICODE and OUTPUT_UNICODE set
1299 @param FormatString A Null-terminated format string.
1300 @param ... The variable argument list.
1302 @return The number of characters printed.
1307 BasePrintLibSPrint (
1308 OUT CHAR8
*StartOfBuffer
,
1309 IN UINTN BufferSize
,
1311 IN CONST CHAR8
*FormatString
,
1316 UINTN NumberOfPrinted
;
1318 VA_START (Marker
, FormatString
);
1319 NumberOfPrinted
= BasePrintLibSPrintMarker (StartOfBuffer
, BufferSize
, Flags
, FormatString
, Marker
, NULL
);
1321 return NumberOfPrinted
;