4 Copyright (c) 2006, Intel Corporation<BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 Module Name: PrintLib.c
17 #include <Common/UefiBaseTypes.h>
18 #include <Library/PrintLib.h>
20 #include "CommonLib.h"
21 #include "PrintLibInternal.h"
26 } STATUS_LOOKUP_TABLE_ENTRY
;
28 static CONST STATUS_LOOKUP_TABLE_ENTRY StatusString
[] = {
29 { RETURN_SUCCESS
, "Success" },
30 { RETURN_LOAD_ERROR
, "Load Error" },
31 { RETURN_INVALID_PARAMETER
, "Invalid Parameter" },
32 { RETURN_UNSUPPORTED
, "Unsupported" },
33 { RETURN_BAD_BUFFER_SIZE
, "Bad Buffer Size" },
34 { RETURN_BUFFER_TOO_SMALL
, "Buffer Too Small" },
35 { RETURN_NOT_READY
, "Not Ready" },
36 { RETURN_DEVICE_ERROR
, "Device Error" },
37 { RETURN_WRITE_PROTECTED
, "Write Protected" },
38 { RETURN_OUT_OF_RESOURCES
, "Out of Resources" },
39 { RETURN_VOLUME_CORRUPTED
, "Volume Corrupt" },
40 { RETURN_VOLUME_FULL
, "Volume Full" },
41 { RETURN_NO_MEDIA
, "No Media" },
42 { RETURN_MEDIA_CHANGED
, "Media changed" },
43 { RETURN_NOT_FOUND
, "Not Found" },
44 { RETURN_ACCESS_DENIED
, "Access Denied" },
45 { RETURN_NO_RESPONSE
, "No Response" },
46 { RETURN_NO_MAPPING
, "No mapping" },
47 { RETURN_TIMEOUT
, "Time out" },
48 { RETURN_NOT_STARTED
, "Not started" },
49 { RETURN_ALREADY_STARTED
, "Already started" },
50 { RETURN_ABORTED
, "Aborted" },
51 { RETURN_ICMP_ERROR
, "ICMP Error" },
52 { RETURN_TFTP_ERROR
, "TFTP Error" },
53 { RETURN_PROTOCOL_ERROR
, "Protocol Error" },
54 { RETURN_WARN_UNKNOWN_GLYPH
, "Warning Unknown Glyph" },
55 { RETURN_WARN_DELETE_FAILURE
, "Warning Delete Failure" },
56 { RETURN_WARN_WRITE_FAILURE
, "Warning Write Failure" },
57 { RETURN_WARN_BUFFER_TOO_SMALL
, "Warning Buffer Too Small" },
63 VSPrint function to process format and place the results in Buffer. Since a
64 VA_LIST is used this rountine allows the nesting of Vararg routines. Thus
65 this is the main print working routine
67 @param StartOfBuffer Unicode buffer to print the results of the parsing of Format into.
69 @param BufferSize Maximum number of characters to put into buffer. Zero means
72 @param Flags Intial flags value. Can only have FORMAT_UNICODE and OUTPUT_UNICODE set
74 @param FormatString Unicode format string see file header for more details.
76 @param Marker Vararg list consumed by processing Format.
78 @return Number of characters printed.
86 IN CONST CHAR8
*Format
,
90 CHAR8
*OriginalBuffer
;
91 CHAR8 ValueBuffer
[MAXIMUM_VALUE_CHARACTERS
];
92 UINTN BytesPerOutputCharacter
;
93 UINTN BytesPerFormatCharacter
;
95 UINTN FormatCharacter
;
99 CHAR8
*ArgumentString
;
105 INTN BytesPerArgumentCharacter
;
106 UINTN ArgumentCharacter
;
114 RETURN_STATUS Status
;
116 OriginalBuffer
= Buffer
;
118 if ((Flags
& OUTPUT_UNICODE
) != 0) {
119 BytesPerOutputCharacter
= 2;
121 BytesPerOutputCharacter
= 1;
123 if ((Flags
& FORMAT_UNICODE
) != 0) {
124 BytesPerFormatCharacter
= 2;
127 BytesPerFormatCharacter
= 1;
132 // Reserve space for the Null terminator.
133 // If BufferSize is 0, this will set BufferSize to the max unsigned value
138 // Get the first character from the format string
140 FormatCharacter
= (*Format
| (*(Format
+ 1) << 8)) & FormatMask
;
143 // Loop until the end of the format string is reached or the output buffer is full
145 while (FormatCharacter
!= 0 && BufferSize
> 0) {
147 // Clear all the flag bits except those that may have been passed in
149 Flags
&= (OUTPUT_UNICODE
| FORMAT_UNICODE
);
152 // Set the default width to zero, and the default precision to 1
162 switch (FormatCharacter
) {
165 // Parse Flags and Width
167 for (Done
= FALSE
; !Done
; ) {
168 Format
+= BytesPerFormatCharacter
;
169 FormatCharacter
= (*Format
| (*(Format
+ 1) << 8)) & FormatMask
;
170 switch (FormatCharacter
) {
175 Flags
|= LEFT_JUSTIFY
;
178 Flags
|= PREFIX_SIGN
;
181 Flags
|= PREFIX_BLANK
;
191 if ((Flags
& PRECISION
) == 0) {
192 Flags
|= PAD_TO_WIDTH
;
193 Width
= VA_ARG (Marker
, UINTN
);
195 Precision
= VA_ARG (Marker
, UINTN
);
199 if ((Flags
& PRECISION
) == 0) {
200 Flags
|= PREFIX_ZERO
;
211 for (Count
= 0; ((FormatCharacter
>= '0') && (FormatCharacter
<= '9')); ){
212 Count
= (Count
* 10) + FormatCharacter
- '0';
213 Format
+= BytesPerFormatCharacter
;
214 FormatCharacter
= (*Format
| (*(Format
+ 1) << 8)) & FormatMask
;
216 Format
-= BytesPerFormatCharacter
;
217 if ((Flags
& PRECISION
) == 0) {
218 Flags
|= PAD_TO_WIDTH
;
231 // Limit the maximum field width to the remaining characters in the output buffer
233 if (Width
> BufferSize
) {
238 // Handle each argument type
240 switch (FormatCharacter
) {
242 Flags
|= PREFIX_ZERO
;
244 // break skiped on purpose
249 // break skiped on purpose
252 if ((Flags
& LONG_TYPE
) == 0) {
253 Value
= (VA_ARG (Marker
, INTN
));
255 Value
= VA_ARG (Marker
, INT64
);
257 if ((Flags
& PREFIX_BLANK
) != 0) {
260 if ((Flags
& PREFIX_SIGN
) != 0) {
263 if ((Flags
& COMMA_TYPE
) != 0) {
266 if ((Flags
& RADIX_HEX
) == 0) {
269 Flags
&= (~PREFIX_ZERO
);
273 Flags
|= PREFIX_SIGN
;
280 if ((Flags
& LONG_TYPE
) == 0 && Value
< 0) {
281 Value
= (UINTN
)Value
;
285 // Convert Value to a reversed string
287 Count
= BasePrintLibValueToString (ValueBuffer
, Value
, Radix
);
288 if (Value
== 0 && Precision
== 0) {
291 ArgumentString
= (CHAR8
*)ValueBuffer
+ Count
;
292 Digits
= 3 - (Count
% 3);
293 if (Comma
&& Count
!= 0) {
294 Count
+= ((Count
- 1) / 3);
299 Flags
|= ARGUMENT_REVERSED
;
301 if ((Flags
& PREFIX_ZERO
) != 0) {
302 if ((Flags
& PAD_TO_WIDTH
) != 0) {
303 if ((Flags
& PRECISION
) == 0) {
312 Flags
|= ARGUMENT_UNICODE
;
314 // break skipped on purpose
317 ArgumentString
= (CHAR8
*)VA_ARG (Marker
, CHAR8
*);
318 if (ArgumentString
== NULL
) {
319 Flags
&= (~ARGUMENT_UNICODE
);
320 ArgumentString
= "<null string>";
325 Character
= VA_ARG (Marker
, UINTN
) & 0xffff;
326 ArgumentString
= (CHAR8
*)&Character
;
327 Flags
|= ARGUMENT_UNICODE
;
331 TmpGuid
= VA_ARG (Marker
, GUID
*);
332 if (TmpGuid
== NULL
) {
333 ArgumentString
= "<null guid>";
339 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
352 ArgumentString
= ValueBuffer
;
357 TmpTime
= VA_ARG (Marker
, TIME
*);
358 if (TmpTime
== NULL
) {
359 ArgumentString
= "<null time>";
365 "%02d/%02d/%04d %02d:%02d",
372 ArgumentString
= ValueBuffer
;
377 Status
= VA_ARG (Marker
, RETURN_STATUS
);
378 ArgumentString
= ValueBuffer
;
379 for (Index
= 0; StatusString
[Index
].String
!= NULL
; Index
++) {
380 if (Status
== StatusString
[Index
].Status
) {
381 ArgumentString
= StatusString
[Index
].String
;
384 if (ArgumentString
== ValueBuffer
) {
385 BasePrintLibSPrint ((CHAR8
*) ValueBuffer
, 0, 0, "%08X", Status
);
392 // if the type is '%' or unknown, then print it to the screen
394 ArgumentString
= (CHAR8
*)&FormatCharacter
;
395 Flags
|= ARGUMENT_UNICODE
;
400 ArgumentString
= "\r\n";
403 ArgumentString
= (CHAR8
*)&FormatCharacter
;
404 Flags
|= ARGUMENT_UNICODE
;
409 // Retrieve the ArgumentString attriubutes
411 if ((Flags
& ARGUMENT_UNICODE
) != 0) {
412 ArgumentMask
= 0xffff;
413 BytesPerArgumentCharacter
= 2;
416 BytesPerArgumentCharacter
= 1;
418 if ((Flags
& ARGUMENT_REVERSED
) != 0) {
419 BytesPerArgumentCharacter
= -BytesPerArgumentCharacter
;
422 // Compute the number of characters in ArgumentString and store it in Count
423 // ArgumentString is either null-terminated, or it contains Precision characters
425 for (Count
= 0; Count
< Precision
|| ((Flags
& PRECISION
) == 0); Count
++) {
426 ArgumentCharacter
= ((ArgumentString
[Count
* BytesPerArgumentCharacter
] & 0xff) | ((ArgumentString
[Count
* BytesPerArgumentCharacter
+ 1]) << 8)) & ArgumentMask
;
427 if (ArgumentCharacter
== 0) {
434 // Limit the length of the string to append to the remaining characters in the output buffer
436 if (Count
> BufferSize
) {
439 if (Precision
< Count
) {
444 // Pad before the string
446 if ((Flags
& (PAD_TO_WIDTH
| LEFT_JUSTIFY
)) == (PAD_TO_WIDTH
)) {
447 Buffer
= BasePrintLibFillBuffer (Buffer
, Width
- Precision
, ' ', BytesPerOutputCharacter
);
452 Buffer
= BasePrintLibFillBuffer (Buffer
, 1, Prefix
, BytesPerOutputCharacter
);
454 Buffer
= BasePrintLibFillBuffer (Buffer
, Precision
- Count
, '0', BytesPerOutputCharacter
);
456 Buffer
= BasePrintLibFillBuffer (Buffer
, Precision
- Count
, ' ', BytesPerOutputCharacter
);
458 Buffer
= BasePrintLibFillBuffer (Buffer
, 1, Prefix
, BytesPerOutputCharacter
);
463 // Output the Prefix character if it is present
471 // Copy the string into the output buffer performing the required type conversions
473 while (Index
< Count
) {
474 ArgumentCharacter
= ((*ArgumentString
& 0xff) | (*(ArgumentString
+ 1) << 8)) & ArgumentMask
;
476 Buffer
= BasePrintLibFillBuffer (Buffer
, 1, ArgumentCharacter
, BytesPerOutputCharacter
);
477 ArgumentString
+= BytesPerArgumentCharacter
;
485 Buffer
= BasePrintLibFillBuffer (Buffer
, 1, ',', BytesPerOutputCharacter
);
492 // Pad after the string
494 if ((Flags
& (PAD_TO_WIDTH
| LEFT_JUSTIFY
)) == (PAD_TO_WIDTH
| LEFT_JUSTIFY
)) {
495 Buffer
= BasePrintLibFillBuffer (Buffer
, Width
- Precision
, ' ', BytesPerOutputCharacter
);
499 // Reduce the number of characters
504 // Get the next character from the format string
506 Format
+= BytesPerFormatCharacter
;
509 // Get the next character from the format string
511 FormatCharacter
= (*Format
| (*(Format
+ 1) << 8)) & FormatMask
;
515 // Null terminate the Unicode or ASCII string
517 Buffer
= BasePrintLibFillBuffer (Buffer
, 1, 0, BytesPerOutputCharacter
);
519 return ((Buffer
- OriginalBuffer
) / BytesPerOutputCharacter
);
524 OUT CHAR8
*StartOfBuffer
,
527 IN CONST CHAR8
*FormatString
,
533 VA_START (Marker
, FormatString
);
534 return BasePrintLibVSPrint (StartOfBuffer
, BufferSize
, Flags
, FormatString
, Marker
);
540 OUT CHAR16
*StartOfBuffer
,
542 IN CONST CHAR16
*FormatString
,
546 return BasePrintLibVSPrint ((CHAR8
*)StartOfBuffer
, BufferSize
>> 1, FORMAT_UNICODE
| OUTPUT_UNICODE
, (CHAR8
*)FormatString
, Marker
);
552 OUT CHAR16
*StartOfBuffer
,
554 IN CONST CHAR16
*FormatString
,
560 VA_START (Marker
, FormatString
);
561 return UnicodeVSPrint (StartOfBuffer
, BufferSize
, FormatString
, Marker
);
566 UnicodeVSPrintAsciiFormat (
567 OUT CHAR16
*StartOfBuffer
,
569 IN CONST CHAR8
*FormatString
,
573 return BasePrintLibVSPrint ((CHAR8
*)StartOfBuffer
, BufferSize
>> 1, OUTPUT_UNICODE
,FormatString
, Marker
);
578 UnicodeSPrintAsciiFormat (
579 OUT CHAR16
*StartOfBuffer
,
581 IN CONST CHAR8
*FormatString
,
587 VA_START (Marker
, FormatString
);
588 return UnicodeVSPrintAsciiFormat (StartOfBuffer
, BufferSize
>> 1, FormatString
, Marker
);
594 OUT CHAR8
*StartOfBuffer
,
596 IN CONST CHAR8
*FormatString
,
600 return BasePrintLibVSPrint (StartOfBuffer
, BufferSize
, 0, FormatString
, Marker
);
606 OUT CHAR8
*StartOfBuffer
,
608 IN CONST CHAR8
*FormatString
,
614 VA_START (Marker
, FormatString
);
615 return AsciiVSPrint (StartOfBuffer
, BufferSize
, FormatString
, Marker
);
620 AsciiVSPrintUnicodeFormat (
621 OUT CHAR8
*StartOfBuffer
,
623 IN CONST CHAR16
*FormatString
,
627 return BasePrintLibVSPrint (StartOfBuffer
, BufferSize
, FORMAT_UNICODE
, (CHAR8
*)FormatString
, Marker
);
632 AsciiSPrintUnicodeFormat (
633 OUT CHAR8
*StartOfBuffer
,
635 IN CONST CHAR16
*FormatString
,
641 VA_START (Marker
, FormatString
);
642 return AsciiVSPrintUnicodeFormat (StartOfBuffer
, BufferSize
, FormatString
, Marker
);
647 UnicodeValueToString (
648 IN OUT CHAR16
*Buffer
,
654 return BasePrintLibConvertValueToString ((CHAR8
*)Buffer
, Flags
, Value
, Width
, 2);
660 IN OUT CHAR8
*Buffer
,
666 return BasePrintLibConvertValueToString ((CHAR8
*)Buffer
, Flags
, Value
, Width
, 1);