]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/BasePrintLib/PrintLibInternal.c
MdePkg: Change OPTIONAL keyword usage style
[mirror_edk2.git] / MdePkg / Library / BasePrintLib / PrintLibInternal.c
CommitLineData
e1f414b6 1/** @file\r
eceb3a4c 2 Print Library internal worker functions.\r
e1f414b6 3\r
9095d37b 4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
9344f092 5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
e1f414b6 6\r
e1f414b6 7**/\r
8\r
e1f414b6 9#include "PrintLibInternal.h"\r
10\r
0df625fa
LG
11#define WARNING_STATUS_NUMBER 5\r
12#define ERROR_STATUS_NUMBER 33\r
e389c39b 13\r
9b002aa4
HW
14//\r
15// Safe print checks\r
16//\r
17#define RSIZE_MAX (PcdGet32 (PcdMaximumUnicodeStringLength))\r
18#define ASCII_RSIZE_MAX (PcdGet32 (PcdMaximumAsciiStringLength))\r
19\r
20#define SAFE_PRINT_CONSTRAINT_CHECK(Expression, RetVal) \\r
21 do { \\r
22 ASSERT (Expression); \\r
23 if (!(Expression)) { \\r
24 return RetVal; \\r
25 } \\r
26 } while (FALSE)\r
27\r
e1f414b6 28GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mHexStr[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};\r
29\r
a2433243
AB
30//\r
31// Longest string: RETURN_WARN_BUFFER_TOO_SMALL => 24 characters plus NUL byte\r
32//\r
33GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mWarningString[][24+1] = {\r
e389c39b 34 "Success", // RETURN_SUCCESS = 0\r
35 "Warning Unknown Glyph", // RETURN_WARN_UNKNOWN_GLYPH = 1\r
36 "Warning Delete Failure", // RETURN_WARN_DELETE_FAILURE = 2\r
37 "Warning Write Failure", // RETURN_WARN_WRITE_FAILURE = 3\r
38 "Warning Buffer Too Small", // RETURN_WARN_BUFFER_TOO_SMALL = 4\r
0df625fa 39 "Warning Stale Data", // RETURN_WARN_STALE_DATA = 5\r
a2433243
AB
40};\r
41\r
42//\r
43// Longest string: RETURN_INCOMPATIBLE_VERSION => 20 characters plus NUL byte\r
44//\r
45GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mErrorString[][20+1] = {\r
e389c39b 46 "Load Error", // RETURN_LOAD_ERROR = 1 | MAX_BIT\r
47 "Invalid Parameter", // RETURN_INVALID_PARAMETER = 2 | MAX_BIT\r
48 "Unsupported", // RETURN_UNSUPPORTED = 3 | MAX_BIT\r
49 "Bad Buffer Size", // RETURN_BAD_BUFFER_SIZE = 4 | MAX_BIT\r
50 "Buffer Too Small", // RETURN_BUFFER_TOO_SMALL, = 5 | MAX_BIT\r
51 "Not Ready", // RETURN_NOT_READY = 6 | MAX_BIT\r
52 "Device Error", // RETURN_DEVICE_ERROR = 7 | MAX_BIT\r
53 "Write Protected", // RETURN_WRITE_PROTECTED = 8 | MAX_BIT\r
54 "Out of Resources", // RETURN_OUT_OF_RESOURCES = 9 | MAX_BIT\r
55 "Volume Corrupt", // RETURN_VOLUME_CORRUPTED = 10 | MAX_BIT\r
56 "Volume Full", // RETURN_VOLUME_FULL = 11 | MAX_BIT\r
57 "No Media", // RETURN_NO_MEDIA = 12 | MAX_BIT\r
58 "Media changed", // RETURN_MEDIA_CHANGED = 13 | MAX_BIT\r
59 "Not Found", // RETURN_NOT_FOUND = 14 | MAX_BIT\r
60 "Access Denied", // RETURN_ACCESS_DENIED = 15 | MAX_BIT\r
61 "No Response", // RETURN_NO_RESPONSE = 16 | MAX_BIT\r
62 "No mapping", // RETURN_NO_MAPPING = 17 | MAX_BIT\r
63 "Time out", // RETURN_TIMEOUT = 18 | MAX_BIT\r
64 "Not started", // RETURN_NOT_STARTED = 19 | MAX_BIT\r
65 "Already started", // RETURN_ALREADY_STARTED = 20 | MAX_BIT\r
66 "Aborted", // RETURN_ABORTED = 21 | MAX_BIT\r
67 "ICMP Error", // RETURN_ICMP_ERROR = 22 | MAX_BIT\r
68 "TFTP Error", // RETURN_TFTP_ERROR = 23 | MAX_BIT\r
5e2fd937 69 "Protocol Error", // RETURN_PROTOCOL_ERROR = 24 | MAX_BIT\r
0df625fa
LG
70 "Incompatible Version", // RETURN_INCOMPATIBLE_VERSION = 25 | MAX_BIT\r
71 "Security Violation", // RETURN_SECURITY_VIOLATION = 26 | MAX_BIT\r
72 "CRC Error", // RETURN_CRC_ERROR = 27 | MAX_BIT\r
73 "End of Media", // RETURN_END_OF_MEDIA = 28 | MAX_BIT\r
74 "Reserved (29)", // RESERVED = 29 | MAX_BIT\r
75 "Reserved (30)", // RESERVED = 30 | MAX_BIT\r
76 "End of File", // RETURN_END_OF_FILE = 31 | MAX_BIT\r
77 "Invalid Language", // RETURN_INVALID_LANGUAGE = 32 | MAX_BIT\r
78 "Compromised Data" // RETURN_COMPROMISED_DATA = 33 | MAX_BIT\r
e389c39b 79};\r
80\r
e1f414b6 81\r
82/**\r
83 Internal function that places the character into the Buffer.\r
84\r
85 Internal function that places ASCII or Unicode character into the Buffer.\r
86\r
2fc59a00 87 @param Buffer The buffer to place the Unicode or ASCII string.\r
e1f414b6 88 @param EndBuffer The end of the input Buffer. No characters will be\r
9095d37b 89 placed after that.\r
2fc59a00 90 @param Length The count of character to be placed into Buffer.\r
a2bc29c4 91 (Negative value indicates no buffer fill.)\r
2fc59a00 92 @param Character The character to be placed into Buffer.\r
93 @param Increment The character increment in Buffer.\r
e1f414b6 94\r
2fc59a00 95 @return Buffer.\r
e1f414b6 96\r
97**/\r
98CHAR8 *\r
99BasePrintLibFillBuffer (\r
eceb3a4c
LG
100 OUT CHAR8 *Buffer,\r
101 IN CHAR8 *EndBuffer,\r
102 IN INTN Length,\r
103 IN UINTN Character,\r
104 IN INTN Increment\r
e1f414b6 105 )\r
106{\r
a2bc29c4 107 INTN Index;\r
9095d37b 108\r
a2bc29c4 109 for (Index = 0; Index < Length && Buffer < EndBuffer; Index++) {\r
110 *Buffer = (CHAR8) Character;\r
111 if (Increment != 1) {\r
112 *(Buffer + 1) = (CHAR8)(Character >> 8);\r
113 }\r
114 Buffer += Increment;\r
115 }\r
116\r
117 return Buffer;\r
e1f414b6 118}\r
119\r
120/**\r
7c905091 121 Internal function that convert a number to a string in Buffer.\r
e1f414b6 122\r
7c905091 123 Print worker function that converts a decimal or hexadecimal number to an ASCII string in Buffer.\r
e1f414b6 124\r
7c905091 125 @param Buffer Location to place the ASCII string of Value.\r
2fc59a00 126 @param Value The value to convert to a Decimal or Hexadecimal string in Buffer.\r
e1f414b6 127 @param Radix Radix of the value\r
128\r
7c905091 129 @return A pointer to the end of buffer filled with ASCII string.\r
e1f414b6 130\r
131**/\r
7c905091 132CHAR8 *\r
e1f414b6 133BasePrintLibValueToString (\r
9095d37b
LG
134 IN OUT CHAR8 *Buffer,\r
135 IN INT64 Value,\r
e1f414b6 136 IN UINTN Radix\r
137 )\r
138{\r
e1f414b6 139 UINT32 Remainder;\r
140\r
141 //\r
142 // Loop to convert one digit at a time in reverse order\r
143 //\r
7c905091 144 *Buffer = 0;\r
e1f414b6 145 do {\r
146 Value = (INT64)DivU64x32Remainder ((UINT64)Value, (UINT32)Radix, &Remainder);\r
7c905091 147 *(++Buffer) = mHexStr[Remainder];\r
e1f414b6 148 } while (Value != 0);\r
eceb3a4c
LG
149\r
150 //\r
7c905091 151 // Return pointer of the end of filled buffer.\r
eceb3a4c 152 //\r
7c905091 153 return Buffer;\r
e1f414b6 154}\r
155\r
156/**\r
157 Internal function that converts a decimal value to a Null-terminated string.\r
9095d37b
LG
158\r
159 Converts the decimal number specified by Value to a Null-terminated\r
e1f414b6 160 string specified by Buffer containing at most Width characters.\r
161 If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed.\r
efb23117 162 The total number of characters placed in Buffer is returned.\r
e1f414b6 163 If the conversion contains more than Width characters, then only the first\r
9095d37b 164 Width characters are returned, and the total number of characters\r
e1f414b6 165 required to perform the conversion is returned.\r
9095d37b 166 Additional conversion parameters are specified in Flags.\r
e1f414b6 167 The Flags bit LEFT_JUSTIFY is always ignored.\r
168 All conversions are left justified in Buffer.\r
169 If Width is 0, PREFIX_ZERO is ignored in Flags.\r
170 If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and commas\r
171 are inserted every 3rd digit starting from the right.\r
efb23117 172 If Value is < 0, then the fist character in Buffer is a '-'.\r
9095d37b
LG
173 If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored,\r
174 then Buffer is padded with '0' characters so the combination of the optional '-'\r
e1f414b6 175 sign character, '0' characters, digit characters for Value, and the Null-terminator\r
176 add up to Width characters.\r
e1f414b6 177\r
178 If Buffer is NULL, then ASSERT().\r
179 If unsupported bits are set in Flags, then ASSERT().\r
180 If Width >= MAXIMUM_VALUE_CHARACTERS, then ASSERT()\r
181\r
2fc59a00 182 @param Buffer The pointer to the output buffer for the produced Null-terminated\r
e1f414b6 183 string.\r
184 @param Flags The bitmask of flags that specify left justification, zero pad,\r
185 and commas.\r
186 @param Value The 64-bit signed value to convert to a string.\r
187 @param Width The maximum number of characters to place in Buffer, not including\r
188 the Null-terminator.\r
2fc59a00 189 @param Increment The character increment in Buffer.\r
9095d37b 190\r
efb23117 191 @return Total number of characters required to perform the conversion.\r
e1f414b6 192\r
193**/\r
194UINTN\r
195BasePrintLibConvertValueToString (\r
196 IN OUT CHAR8 *Buffer,\r
197 IN UINTN Flags,\r
198 IN INT64 Value,\r
199 IN UINTN Width,\r
200 IN UINTN Increment\r
201 )\r
202{\r
203 CHAR8 *OriginalBuffer;\r
204 CHAR8 *EndBuffer;\r
205 CHAR8 ValueBuffer[MAXIMUM_VALUE_CHARACTERS];\r
7c905091 206 CHAR8 *ValueBufferPtr;\r
e1f414b6 207 UINTN Count;\r
208 UINTN Digits;\r
209 UINTN Index;\r
210 UINTN Radix;\r
211\r
eceb3a4c
LG
212 //\r
213 // Make sure Buffer is not NULL and Width < MAXIMUM\r
214 //\r
e1f414b6 215 ASSERT (Buffer != NULL);\r
216 ASSERT (Width < MAXIMUM_VALUE_CHARACTERS);\r
217 //\r
218 // Make sure Flags can only contain supported bits.\r
219 //\r
220 ASSERT ((Flags & ~(LEFT_JUSTIFY | COMMA_TYPE | PREFIX_ZERO | RADIX_HEX)) == 0);\r
221\r
222 //\r
df8d0595 223 // If both COMMA_TYPE and RADIX_HEX are set, then ASSERT ()\r
e1f414b6 224 //\r
841c0770 225 ASSERT (((Flags & COMMA_TYPE) == 0) || ((Flags & RADIX_HEX) == 0));\r
e1f414b6 226\r
227 OriginalBuffer = Buffer;\r
9095d37b 228\r
eceb3a4c
LG
229 //\r
230 // Width is 0 or COMMA_TYPE is set, PREFIX_ZERO is ignored.\r
231 //\r
e1f414b6 232 if (Width == 0 || (Flags & COMMA_TYPE) != 0) {\r
e935092f 233 Flags &= ~((UINTN) PREFIX_ZERO);\r
e1f414b6 234 }\r
eceb3a4c
LG
235 //\r
236 // If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed.\r
237 //\r
e1f414b6 238 if (Width == 0) {\r
239 Width = MAXIMUM_VALUE_CHARACTERS - 1;\r
240 }\r
241 //\r
242 // Set the tag for the end of the input Buffer.\r
243 //\r
244 EndBuffer = Buffer + Width * Increment;\r
9095d37b 245\r
eceb3a4c
LG
246 //\r
247 // Convert decimal negative\r
248 //\r
e1f414b6 249 if ((Value < 0) && ((Flags & RADIX_HEX) == 0)) {\r
250 Value = -Value;\r
251 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, '-', Increment);\r
252 Width--;\r
253 }\r
9095d37b 254\r
eceb3a4c
LG
255 //\r
256 // Count the length of the value string.\r
257 //\r
e1f414b6 258 Radix = ((Flags & RADIX_HEX) == 0)? 10 : 16;\r
7c905091 259 ValueBufferPtr = BasePrintLibValueToString (ValueBuffer, Value, Radix);\r
260 Count = ValueBufferPtr - ValueBuffer;\r
9095d37b 261\r
eceb3a4c
LG
262 //\r
263 // Append Zero\r
264 //\r
e1f414b6 265 if ((Flags & PREFIX_ZERO) != 0) {\r
266 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Width - Count, '0', Increment);\r
267 }\r
9095d37b 268\r
eceb3a4c
LG
269 //\r
270 // Print Comma type for every 3 characters\r
271 //\r
e1f414b6 272 Digits = Count % 3;\r
273 if (Digits != 0) {\r
274 Digits = 3 - Digits;\r
275 }\r
276 for (Index = 0; Index < Count; Index++) {\r
7c905091 277 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, *ValueBufferPtr--, Increment);\r
e1f414b6 278 if ((Flags & COMMA_TYPE) != 0) {\r
279 Digits++;\r
280 if (Digits == 3) {\r
281 Digits = 0;\r
282 if ((Index + 1) < Count) {\r
283 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ',', Increment);\r
284 }\r
285 }\r
286 }\r
287 }\r
9095d37b 288\r
eceb3a4c
LG
289 //\r
290 // Print Null-terminator\r
291 //\r
e1f414b6 292 BasePrintLibFillBuffer (Buffer, EndBuffer + Increment, 1, 0, Increment);\r
293\r
294 return ((Buffer - OriginalBuffer) / Increment);\r
295}\r
296\r
51f0ceb4
HW
297/**\r
298 Internal function that converts a decimal value to a Null-terminated string.\r
299\r
300 Converts the decimal number specified by Value to a Null-terminated string\r
301 specified by Buffer containing at most Width characters. If Width is 0 then a\r
302 width of MAXIMUM_VALUE_CHARACTERS is assumed. If the conversion contains more\r
303 than Width characters, then only the first Width characters are placed in\r
304 Buffer. Additional conversion parameters are specified in Flags.\r
305 The Flags bit LEFT_JUSTIFY is always ignored.\r
306 All conversions are left justified in Buffer.\r
307 If Width is 0, PREFIX_ZERO is ignored in Flags.\r
308 If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and\r
309 commas are inserted every 3rd digit starting from the right.\r
310 If Value is < 0, then the fist character in Buffer is a '-'.\r
311 If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored,\r
312 then Buffer is padded with '0' characters so the combination of the optional\r
313 '-' sign character, '0' characters, digit characters for Value, and the\r
314 Null-terminator add up to Width characters.\r
315\r
316 If an error would be returned, the function will ASSERT().\r
317\r
318 @param Buffer The pointer to the output buffer for the produced\r
319 Null-terminated string.\r
320 @param BufferSize The size of Buffer in bytes, including the\r
321 Null-terminator.\r
322 @param Flags The bitmask of flags that specify left justification,\r
323 zero pad, and commas.\r
324 @param Value The 64-bit signed value to convert to a string.\r
325 @param Width The maximum number of characters to place in Buffer,\r
326 not including the Null-terminator.\r
327 @param Increment The character increment in Buffer.\r
328\r
329 @retval RETURN_SUCCESS The decimal value is converted.\r
330 @retval RETURN_BUFFER_TOO_SMALL If BufferSize cannot hold the converted\r
331 value.\r
332 @retval RETURN_INVALID_PARAMETER If Buffer is NULL.\r
333 If Increment is 1 and\r
334 PcdMaximumAsciiStringLength is not zero,\r
335 BufferSize is greater than\r
336 PcdMaximumAsciiStringLength.\r
337 If Increment is not 1 and\r
338 PcdMaximumUnicodeStringLength is not zero,\r
339 BufferSize is greater than\r
340 (PcdMaximumUnicodeStringLength *\r
341 sizeof (CHAR16) + 1).\r
342 If unsupported bits are set in Flags.\r
343 If both COMMA_TYPE and RADIX_HEX are set in\r
344 Flags.\r
345 If Width >= MAXIMUM_VALUE_CHARACTERS.\r
346\r
347**/\r
348RETURN_STATUS\r
349BasePrintLibConvertValueToStringS (\r
350 IN OUT CHAR8 *Buffer,\r
351 IN UINTN BufferSize,\r
352 IN UINTN Flags,\r
353 IN INT64 Value,\r
354 IN UINTN Width,\r
355 IN UINTN Increment\r
356 )\r
357{\r
358 CHAR8 *EndBuffer;\r
359 CHAR8 ValueBuffer[MAXIMUM_VALUE_CHARACTERS];\r
360 CHAR8 *ValueBufferPtr;\r
361 UINTN Count;\r
362 UINTN Digits;\r
363 UINTN Index;\r
364 UINTN Radix;\r
365\r
366 //\r
367 // 1. Buffer shall not be a null pointer.\r
368 //\r
369 SAFE_PRINT_CONSTRAINT_CHECK ((Buffer != NULL), RETURN_INVALID_PARAMETER);\r
370\r
371 //\r
372 // 2. BufferSize shall not be greater than (RSIZE_MAX * sizeof (CHAR16)) for\r
373 // Unicode output string or shall not be greater than ASCII_RSIZE_MAX for\r
374 // Ascii output string.\r
375 //\r
376 if (Increment == 1) {\r
377 //\r
378 // Ascii output string\r
379 //\r
380 if (ASCII_RSIZE_MAX != 0) {\r
381 SAFE_PRINT_CONSTRAINT_CHECK ((BufferSize <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);\r
382 }\r
383 } else {\r
384 //\r
385 // Unicode output string\r
386 //\r
387 if (RSIZE_MAX != 0) {\r
388 SAFE_PRINT_CONSTRAINT_CHECK ((BufferSize <= RSIZE_MAX * sizeof (CHAR16) + 1), RETURN_INVALID_PARAMETER);\r
389 }\r
390 }\r
391\r
392 //\r
393 // 3. Flags shall be set properly.\r
394 //\r
395 SAFE_PRINT_CONSTRAINT_CHECK (((Flags & ~(LEFT_JUSTIFY | COMMA_TYPE | PREFIX_ZERO | RADIX_HEX)) == 0), RETURN_INVALID_PARAMETER);\r
396 SAFE_PRINT_CONSTRAINT_CHECK ((((Flags & COMMA_TYPE) == 0) || ((Flags & RADIX_HEX) == 0)), RETURN_INVALID_PARAMETER);\r
397\r
398 //\r
399 // 4. Width shall be smaller than MAXIMUM_VALUE_CHARACTERS.\r
400 //\r
401 SAFE_PRINT_CONSTRAINT_CHECK ((Width < MAXIMUM_VALUE_CHARACTERS), RETURN_INVALID_PARAMETER);\r
402\r
403 //\r
404 // Width is 0 or COMMA_TYPE is set, PREFIX_ZERO is ignored.\r
405 //\r
406 if (Width == 0 || (Flags & COMMA_TYPE) != 0) {\r
407 Flags &= ~((UINTN) PREFIX_ZERO);\r
408 }\r
409 //\r
410 // If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed.\r
411 //\r
412 if (Width == 0) {\r
413 Width = MAXIMUM_VALUE_CHARACTERS - 1;\r
414 }\r
415\r
416 //\r
417 // Count the characters of the output string.\r
418 //\r
419 Count = 0;\r
420 Radix = ((Flags & RADIX_HEX) == 0)? 10 : 16;\r
421\r
422 if ((Flags & PREFIX_ZERO) != 0) {\r
423 Count = Width;\r
424 } else {\r
425 if ((Value < 0) && ((Flags & RADIX_HEX) == 0)) {\r
426 Count++; // minus sign\r
427 ValueBufferPtr = BasePrintLibValueToString (ValueBuffer, -Value, Radix);\r
428 } else {\r
429 ValueBufferPtr = BasePrintLibValueToString (ValueBuffer, Value, Radix);\r
430 }\r
431 Digits = ValueBufferPtr - ValueBuffer;\r
432 Count += Digits;\r
433\r
434 if ((Flags & COMMA_TYPE) != 0) {\r
435 Count += (Digits - 1) / 3; // commas\r
436 }\r
437 }\r
438\r
439 Width = MIN (Count, Width);\r
440\r
441 //\r
442 // 5. BufferSize shall be large enough to hold the converted string.\r
443 //\r
444 SAFE_PRINT_CONSTRAINT_CHECK ((BufferSize >= (Width + 1) * Increment), RETURN_BUFFER_TOO_SMALL);\r
445\r
446 //\r
447 // Set the tag for the end of the input Buffer.\r
448 //\r
449 EndBuffer = Buffer + Width * Increment;\r
450\r
451 //\r
452 // Convert decimal negative\r
453 //\r
454 if ((Value < 0) && ((Flags & RADIX_HEX) == 0)) {\r
455 Value = -Value;\r
456 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, '-', Increment);\r
457 Width--;\r
458 }\r
459\r
460 //\r
461 // Count the length of the value string.\r
462 //\r
463 ValueBufferPtr = BasePrintLibValueToString (ValueBuffer, Value, Radix);\r
464 Count = ValueBufferPtr - ValueBuffer;\r
465\r
466 //\r
467 // Append Zero\r
468 //\r
469 if ((Flags & PREFIX_ZERO) != 0) {\r
470 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Width - Count, '0', Increment);\r
471 }\r
472\r
473 //\r
474 // Print Comma type for every 3 characters\r
475 //\r
476 Digits = Count % 3;\r
477 if (Digits != 0) {\r
478 Digits = 3 - Digits;\r
479 }\r
480 for (Index = 0; Index < Count; Index++) {\r
481 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, *ValueBufferPtr--, Increment);\r
482 if ((Flags & COMMA_TYPE) != 0) {\r
483 Digits++;\r
484 if (Digits == 3) {\r
485 Digits = 0;\r
486 if ((Index + 1) < Count) {\r
487 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ',', Increment);\r
488 }\r
489 }\r
490 }\r
491 }\r
492\r
493 //\r
494 // Print Null-terminator\r
495 //\r
496 BasePrintLibFillBuffer (Buffer, EndBuffer + Increment, 1, 0, Increment);\r
497\r
498 return RETURN_SUCCESS;\r
499}\r
500\r
e389c39b 501/**\r
9095d37b 502 Worker function that produces a Null-terminated string in an output buffer\r
e389c39b 503 based on a Null-terminated format string and a VA_LIST argument list.\r
504\r
9095d37b
LG
505 VSPrint function to process format and place the results in Buffer. Since a\r
506 VA_LIST is used this routine allows the nesting of Vararg routines. Thus\r
e389c39b 507 this is the main print working routine.\r
508\r
f405c067 509 If COUNT_ONLY_NO_PRINT is set in Flags, Buffer will not be modified at all.\r
510\r
9095d37b 511 @param[out] Buffer The character buffer to print the results of the\r
f405c067 512 parsing of Format into.\r
9095d37b 513 @param[in] BufferSize The maximum number of characters to put into\r
f405c067 514 buffer.\r
515 @param[in] Flags Initial flags value.\r
9095d37b 516 Can only have FORMAT_UNICODE, OUTPUT_UNICODE,\r
f405c067 517 and COUNT_ONLY_NO_PRINT set.\r
518 @param[in] Format A Null-terminated format string.\r
519 @param[in] VaListMarker VA_LIST style variable argument list consumed by\r
520 processing Format.\r
521 @param[in] BaseListMarker BASE_LIST style variable argument list consumed\r
522 by processing Format.\r
e389c39b 523\r
2fc59a00 524 @return The number of characters printed not including the Null-terminator.\r
f405c067 525 If COUNT_ONLY_NO_PRINT was set returns the same, but without any\r
526 modification to Buffer.\r
e389c39b 527\r
528**/\r
529UINTN\r
2075236e 530BasePrintLibSPrintMarker (\r
e389c39b 531 OUT CHAR8 *Buffer,\r
532 IN UINTN BufferSize,\r
533 IN UINTN Flags,\r
534 IN CONST CHAR8 *Format,\r
d0e2f823 535 IN VA_LIST VaListMarker OPTIONAL,\r
2075236e 536 IN BASE_LIST BaseListMarker OPTIONAL\r
e389c39b 537 )\r
538{\r
2075236e 539 CHAR8 *OriginalBuffer;\r
540 CHAR8 *EndBuffer;\r
541 CHAR8 ValueBuffer[MAXIMUM_VALUE_CHARACTERS];\r
f405c067 542 UINT32 BytesPerOutputCharacter;\r
2075236e 543 UINTN BytesPerFormatCharacter;\r
544 UINTN FormatMask;\r
545 UINTN FormatCharacter;\r
546 UINTN Width;\r
547 UINTN Precision;\r
548 INT64 Value;\r
549 CONST CHAR8 *ArgumentString;\r
550 UINTN Character;\r
551 GUID *TmpGuid;\r
552 TIME *TmpTime;\r
553 UINTN Count;\r
554 UINTN ArgumentMask;\r
555 INTN BytesPerArgumentCharacter;\r
556 UINTN ArgumentCharacter;\r
557 BOOLEAN Done;\r
558 UINTN Index;\r
559 CHAR8 Prefix;\r
560 BOOLEAN ZeroPad;\r
561 BOOLEAN Comma;\r
562 UINTN Digits;\r
563 UINTN Radix;\r
564 RETURN_STATUS Status;\r
4b0f378c
LG
565 UINT32 GuidData1;\r
566 UINT16 GuidData2;\r
567 UINT16 GuidData3;\r
41342801 568 UINTN LengthToReturn;\r
e389c39b 569\r
f405c067 570 //\r
571 // If you change this code be sure to match the 2 versions of this function.\r
9095d37b 572 // Nearly identical logic is found in the BasePrintLib and\r
f405c067 573 // DxePrintLibPrint2Protocol (both PrintLib instances).\r
574 //\r
575\r
9b002aa4
HW
576 //\r
577 // 1. Buffer shall not be a null pointer when both BufferSize > 0 and\r
578 // COUNT_ONLY_NO_PRINT is not set in Flags.\r
579 //\r
580 if ((BufferSize > 0) && ((Flags & COUNT_ONLY_NO_PRINT) == 0)) {\r
581 SAFE_PRINT_CONSTRAINT_CHECK ((Buffer != NULL), 0);\r
582 }\r
583\r
584 //\r
585 // 2. Format shall not be a null pointer when BufferSize > 0 or when\r
586 // COUNT_ONLY_NO_PRINT is set in Flags.\r
587 //\r
588 if ((BufferSize > 0) || ((Flags & COUNT_ONLY_NO_PRINT) != 0)) {\r
589 SAFE_PRINT_CONSTRAINT_CHECK ((Format != NULL), 0);\r
590 }\r
591\r
592 //\r
593 // 3. BufferSize shall not be greater than RSIZE_MAX for Unicode output or\r
594 // ASCII_RSIZE_MAX for Ascii output.\r
595 //\r
596 if ((Flags & OUTPUT_UNICODE) != 0) {\r
597 if (RSIZE_MAX != 0) {\r
598 SAFE_PRINT_CONSTRAINT_CHECK ((BufferSize <= RSIZE_MAX), 0);\r
599 }\r
600 BytesPerOutputCharacter = 2;\r
601 } else {\r
602 if (ASCII_RSIZE_MAX != 0) {\r
603 SAFE_PRINT_CONSTRAINT_CHECK ((BufferSize <= ASCII_RSIZE_MAX), 0);\r
604 }\r
605 BytesPerOutputCharacter = 1;\r
606 }\r
607\r
608 //\r
609 // 4. Format shall not contain more than RSIZE_MAX Unicode characters or\r
610 // ASCII_RSIZE_MAX Ascii characters.\r
611 //\r
612 if ((Flags & FORMAT_UNICODE) != 0) {\r
613 if (RSIZE_MAX != 0) {\r
614 SAFE_PRINT_CONSTRAINT_CHECK ((StrnLenS ((CHAR16 *)Format, RSIZE_MAX + 1) <= RSIZE_MAX), 0);\r
615 }\r
616 BytesPerFormatCharacter = 2;\r
617 FormatMask = 0xffff;\r
618 } else {\r
619 if (ASCII_RSIZE_MAX != 0) {\r
620 SAFE_PRINT_CONSTRAINT_CHECK ((AsciiStrnLenS (Format, ASCII_RSIZE_MAX + 1) <= ASCII_RSIZE_MAX), 0);\r
621 }\r
622 BytesPerFormatCharacter = 1;\r
623 FormatMask = 0xff;\r
624 }\r
625\r
83f1f16a 626 if ((Flags & COUNT_ONLY_NO_PRINT) != 0) {\r
f405c067 627 if (BufferSize == 0) {\r
628 Buffer = NULL;\r
629 }\r
630 } else {\r
631 //\r
632 // We can run without a Buffer for counting only.\r
633 //\r
634 if (BufferSize == 0) {\r
635 return 0;\r
636 }\r
e389c39b 637 }\r
638\r
f405c067 639 LengthToReturn = 0;\r
28087ef0
HL
640 EndBuffer = NULL;\r
641 OriginalBuffer = NULL;\r
f405c067 642\r
e389c39b 643 //\r
644 // Reserve space for the Null terminator.\r
645 //\r
28087ef0
HL
646 if (Buffer != NULL) {\r
647 BufferSize--;\r
648 OriginalBuffer = Buffer;\r
2075236e 649\r
28087ef0
HL
650 //\r
651 // Set the tag for the end of the input Buffer.\r
652 //\r
653 EndBuffer = Buffer + BufferSize * BytesPerOutputCharacter;\r
654 }\r
e389c39b 655\r
e389c39b 656 //\r
657 // Get the first character from the format string\r
658 //\r
b1d4b965 659 FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask;\r
e389c39b 660\r
661 //\r
662 // Loop until the end of the format string is reached or the output buffer is full\r
663 //\r
28087ef0
HL
664 while (FormatCharacter != 0) {\r
665 if ((Buffer != NULL) && (Buffer >= EndBuffer)) {\r
666 break;\r
667 }\r
e389c39b 668 //\r
669 // Clear all the flag bits except those that may have been passed in\r
670 //\r
e935092f 671 Flags &= (UINTN) (OUTPUT_UNICODE | FORMAT_UNICODE | COUNT_ONLY_NO_PRINT);\r
e389c39b 672\r
673 //\r
674 // Set the default width to zero, and the default precision to 1\r
675 //\r
676 Width = 0;\r
677 Precision = 1;\r
678 Prefix = 0;\r
679 Comma = FALSE;\r
680 ZeroPad = FALSE;\r
681 Count = 0;\r
682 Digits = 0;\r
683\r
684 switch (FormatCharacter) {\r
685 case '%':\r
686 //\r
687 // Parse Flags and Width\r
688 //\r
689 for (Done = FALSE; !Done; ) {\r
690 Format += BytesPerFormatCharacter;\r
b1d4b965 691 FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask;\r
e389c39b 692 switch (FormatCharacter) {\r
9095d37b
LG
693 case '.':\r
694 Flags |= PRECISION;\r
e389c39b 695 break;\r
9095d37b
LG
696 case '-':\r
697 Flags |= LEFT_JUSTIFY;\r
e389c39b 698 break;\r
9095d37b
LG
699 case '+':\r
700 Flags |= PREFIX_SIGN;\r
e389c39b 701 break;\r
9095d37b
LG
702 case ' ':\r
703 Flags |= PREFIX_BLANK;\r
e389c39b 704 break;\r
9095d37b
LG
705 case ',':\r
706 Flags |= COMMA_TYPE;\r
e389c39b 707 break;\r
708 case 'L':\r
9095d37b
LG
709 case 'l':\r
710 Flags |= LONG_TYPE;\r
e389c39b 711 break;\r
712 case '*':\r
713 if ((Flags & PRECISION) == 0) {\r
714 Flags |= PAD_TO_WIDTH;\r
2075236e 715 if (BaseListMarker == NULL) {\r
716 Width = VA_ARG (VaListMarker, UINTN);\r
717 } else {\r
718 Width = BASE_ARG (BaseListMarker, UINTN);\r
719 }\r
e389c39b 720 } else {\r
2075236e 721 if (BaseListMarker == NULL) {\r
722 Precision = VA_ARG (VaListMarker, UINTN);\r
723 } else {\r
724 Precision = BASE_ARG (BaseListMarker, UINTN);\r
725 }\r
e389c39b 726 }\r
727 break;\r
728 case '0':\r
729 if ((Flags & PRECISION) == 0) {\r
730 Flags |= PREFIX_ZERO;\r
731 }\r
732 case '1':\r
733 case '2':\r
734 case '3':\r
735 case '4':\r
736 case '5':\r
737 case '6':\r
738 case '7':\r
739 case '8':\r
740 case '9':\r
741 for (Count = 0; ((FormatCharacter >= '0') && (FormatCharacter <= '9')); ){\r
742 Count = (Count * 10) + FormatCharacter - '0';\r
743 Format += BytesPerFormatCharacter;\r
b1d4b965 744 FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask;\r
e389c39b 745 }\r
746 Format -= BytesPerFormatCharacter;\r
747 if ((Flags & PRECISION) == 0) {\r
748 Flags |= PAD_TO_WIDTH;\r
749 Width = Count;\r
750 } else {\r
751 Precision = Count;\r
752 }\r
753 break;\r
9095d37b 754\r
e389c39b 755 case '\0':\r
756 //\r
757 // Make no output if Format string terminates unexpectedly when\r
9095d37b 758 // looking up for flag, width, precision and type.\r
e389c39b 759 //\r
760 Format -= BytesPerFormatCharacter;\r
761 Precision = 0;\r
762 //\r
763 // break skipped on purpose.\r
764 //\r
765 default:\r
766 Done = TRUE;\r
767 break;\r
768 }\r
9095d37b 769 }\r
e389c39b 770\r
771 //\r
772 // Handle each argument type\r
773 //\r
774 switch (FormatCharacter) {\r
775 case 'p':\r
776 //\r
777 // Flag space, +, 0, L & l are invalid for type p.\r
778 //\r
e935092f 779 Flags &= ~((UINTN) (PREFIX_BLANK | PREFIX_SIGN | PREFIX_ZERO | LONG_TYPE));\r
e389c39b 780 if (sizeof (VOID *) > 4) {\r
781 Flags |= LONG_TYPE;\r
782 }\r
d6bee311
ED
783 //\r
784 // break skipped on purpose\r
785 //\r
e389c39b 786 case 'X':\r
787 Flags |= PREFIX_ZERO;\r
788 //\r
789 // break skipped on purpose\r
790 //\r
791 case 'x':\r
792 Flags |= RADIX_HEX;\r
793 //\r
794 // break skipped on purpose\r
795 //\r
9ade4339
QS
796 case 'u':\r
797 if ((Flags & RADIX_HEX) == 0) {\r
798 Flags &= ~((UINTN) (PREFIX_SIGN));\r
799 Flags |= UNSIGNED_TYPE;\r
800 }\r
801 //\r
802 // break skipped on purpose\r
803 //\r
e389c39b 804 case 'd':\r
805 if ((Flags & LONG_TYPE) == 0) {\r
57dd2382 806 //\r
9ade4339 807 // 'd', 'u', 'x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".\r
18e81d77 808 // This assumption is made so the format string definition is compatible with the ANSI C\r
9095d37b
LG
809 // Specification for formatted strings. It is recommended that the Base Types be used\r
810 // everywhere, but in this one case, compliance with ANSI C is more important, and\r
811 // provides an implementation that is compatible with that largest possible set of CPU\r
57dd2382 812 // architectures. This is why the type "int" is used in this one case.\r
813 //\r
2075236e 814 if (BaseListMarker == NULL) {\r
815 Value = VA_ARG (VaListMarker, int);\r
816 } else {\r
817 Value = BASE_ARG (BaseListMarker, int);\r
818 }\r
e389c39b 819 } else {\r
2075236e 820 if (BaseListMarker == NULL) {\r
821 Value = VA_ARG (VaListMarker, INT64);\r
822 } else {\r
823 Value = BASE_ARG (BaseListMarker, INT64);\r
824 }\r
e389c39b 825 }\r
826 if ((Flags & PREFIX_BLANK) != 0) {\r
827 Prefix = ' ';\r
828 }\r
829 if ((Flags & PREFIX_SIGN) != 0) {\r
830 Prefix = '+';\r
831 }\r
832 if ((Flags & COMMA_TYPE) != 0) {\r
833 Comma = TRUE;\r
834 }\r
835 if ((Flags & RADIX_HEX) == 0) {\r
836 Radix = 10;\r
837 if (Comma) {\r
e935092f 838 Flags &= ~((UINTN) PREFIX_ZERO);\r
e389c39b 839 Precision = 1;\r
840 }\r
9ade4339 841 if (Value < 0 && (Flags & UNSIGNED_TYPE) == 0) {\r
e389c39b 842 Flags |= PREFIX_SIGN;\r
843 Prefix = '-';\r
844 Value = -Value;\r
9ade4339
QS
845 } else if ((Flags & UNSIGNED_TYPE) != 0 && (Flags & LONG_TYPE) == 0) {\r
846 //\r
847 // 'd', 'u', 'x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".\r
848 // This assumption is made so the format string definition is compatible with the ANSI C\r
9095d37b
LG
849 // Specification for formatted strings. It is recommended that the Base Types be used\r
850 // everywhere, but in this one case, compliance with ANSI C is more important, and\r
851 // provides an implementation that is compatible with that largest possible set of CPU\r
9ade4339
QS
852 // architectures. This is why the type "unsigned int" is used in this one case.\r
853 //\r
854 Value = (unsigned int)Value;\r
e389c39b 855 }\r
856 } else {\r
857 Radix = 16;\r
858 Comma = FALSE;\r
859 if ((Flags & LONG_TYPE) == 0 && Value < 0) {\r
57dd2382 860 //\r
9ade4339 861 // 'd', 'u', 'x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".\r
18e81d77 862 // This assumption is made so the format string definition is compatible with the ANSI C\r
9095d37b
LG
863 // Specification for formatted strings. It is recommended that the Base Types be used\r
864 // everywhere, but in this one case, compliance with ANSI C is more important, and\r
865 // provides an implementation that is compatible with that largest possible set of CPU\r
57dd2382 866 // architectures. This is why the type "unsigned int" is used in this one case.\r
867 //\r
e389c39b 868 Value = (unsigned int)Value;\r
869 }\r
870 }\r
871 //\r
872 // Convert Value to a reversed string\r
873 //\r
7c905091 874 Count = BasePrintLibValueToString (ValueBuffer, Value, Radix) - ValueBuffer;\r
e389c39b 875 if (Value == 0 && Precision == 0) {\r
876 Count = 0;\r
877 }\r
878 ArgumentString = (CHAR8 *)ValueBuffer + Count;\r
9095d37b 879\r
e389c39b 880 Digits = Count % 3;\r
881 if (Digits != 0) {\r
882 Digits = 3 - Digits;\r
883 }\r
884 if (Comma && Count != 0) {\r
885 Count += ((Count - 1) / 3);\r
886 }\r
887 if (Prefix != 0) {\r
888 Count++;\r
889 Precision++;\r
890 }\r
891 Flags |= ARGUMENT_REVERSED;\r
892 ZeroPad = TRUE;\r
893 if ((Flags & PREFIX_ZERO) != 0) {\r
894 if ((Flags & LEFT_JUSTIFY) == 0) {\r
895 if ((Flags & PAD_TO_WIDTH) != 0) {\r
896 if ((Flags & PRECISION) == 0) {\r
897 Precision = Width;\r
898 }\r
899 }\r
900 }\r
901 }\r
902 break;\r
903\r
904 case 's':\r
905 case 'S':\r
906 Flags |= ARGUMENT_UNICODE;\r
907 //\r
908 // break skipped on purpose\r
909 //\r
910 case 'a':\r
2075236e 911 if (BaseListMarker == NULL) {\r
912 ArgumentString = VA_ARG (VaListMarker, CHAR8 *);\r
913 } else {\r
914 ArgumentString = BASE_ARG (BaseListMarker, CHAR8 *);\r
915 }\r
e389c39b 916 if (ArgumentString == NULL) {\r
e935092f 917 Flags &= ~((UINTN) ARGUMENT_UNICODE);\r
e389c39b 918 ArgumentString = "<null string>";\r
919 }\r
920 //\r
921 // Set the default precision for string to be zero if not specified.\r
922 //\r
923 if ((Flags & PRECISION) == 0) {\r
924 Precision = 0;\r
925 }\r
926 break;\r
927\r
928 case 'c':\r
2075236e 929 if (BaseListMarker == NULL) {\r
930 Character = VA_ARG (VaListMarker, UINTN) & 0xffff;\r
931 } else {\r
932 Character = BASE_ARG (BaseListMarker, UINTN) & 0xffff;\r
933 }\r
e389c39b 934 ArgumentString = (CHAR8 *)&Character;\r
935 Flags |= ARGUMENT_UNICODE;\r
936 break;\r
937\r
938 case 'g':\r
2075236e 939 if (BaseListMarker == NULL) {\r
940 TmpGuid = VA_ARG (VaListMarker, GUID *);\r
941 } else {\r
942 TmpGuid = BASE_ARG (BaseListMarker, GUID *);\r
943 }\r
e389c39b 944 if (TmpGuid == NULL) {\r
945 ArgumentString = "<null guid>";\r
946 } else {\r
4b0f378c
LG
947 GuidData1 = ReadUnaligned32 (&(TmpGuid->Data1));\r
948 GuidData2 = ReadUnaligned16 (&(TmpGuid->Data2));\r
949 GuidData3 = ReadUnaligned16 (&(TmpGuid->Data3));\r
e389c39b 950 BasePrintLibSPrint (\r
951 ValueBuffer,\r
9095d37b 952 MAXIMUM_VALUE_CHARACTERS,\r
e389c39b 953 0,\r
954 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",\r
4b0f378c
LG
955 GuidData1,\r
956 GuidData2,\r
957 GuidData3,\r
e389c39b 958 TmpGuid->Data4[0],\r
959 TmpGuid->Data4[1],\r
960 TmpGuid->Data4[2],\r
961 TmpGuid->Data4[3],\r
962 TmpGuid->Data4[4],\r
963 TmpGuid->Data4[5],\r
964 TmpGuid->Data4[6],\r
965 TmpGuid->Data4[7]\r
966 );\r
967 ArgumentString = ValueBuffer;\r
968 }\r
969 break;\r
970\r
971 case 't':\r
2075236e 972 if (BaseListMarker == NULL) {\r
9095d37b 973 TmpTime = VA_ARG (VaListMarker, TIME *);\r
2075236e 974 } else {\r
9095d37b 975 TmpTime = BASE_ARG (BaseListMarker, TIME *);\r
2075236e 976 }\r
e389c39b 977 if (TmpTime == NULL) {\r
978 ArgumentString = "<null time>";\r
979 } else {\r
980 BasePrintLibSPrint (\r
981 ValueBuffer,\r
982 MAXIMUM_VALUE_CHARACTERS,\r
983 0,\r
984 "%02d/%02d/%04d %02d:%02d",\r
985 TmpTime->Month,\r
986 TmpTime->Day,\r
987 TmpTime->Year,\r
988 TmpTime->Hour,\r
989 TmpTime->Minute\r
990 );\r
991 ArgumentString = ValueBuffer;\r
992 }\r
993 break;\r
994\r
995 case 'r':\r
2075236e 996 if (BaseListMarker == NULL) {\r
997 Status = VA_ARG (VaListMarker, RETURN_STATUS);\r
998 } else {\r
999 Status = BASE_ARG (BaseListMarker, RETURN_STATUS);\r
1000 }\r
e389c39b 1001 ArgumentString = ValueBuffer;\r
1002 if (RETURN_ERROR (Status)) {\r
1003 //\r
1004 // Clear error bit\r
1005 //\r
1006 Index = Status & ~MAX_BIT;\r
1007 if (Index > 0 && Index <= ERROR_STATUS_NUMBER) {\r
a2433243 1008 ArgumentString = mErrorString [Index - 1];\r
e389c39b 1009 }\r
1010 } else {\r
1011 Index = Status;\r
1012 if (Index <= WARNING_STATUS_NUMBER) {\r
a2433243 1013 ArgumentString = mWarningString [Index];\r
e389c39b 1014 }\r
1015 }\r
1016 if (ArgumentString == ValueBuffer) {\r
1017 BasePrintLibSPrint ((CHAR8 *) ValueBuffer, MAXIMUM_VALUE_CHARACTERS, 0, "%08X", Status);\r
1018 }\r
1019 break;\r
1020\r
c553db4b 1021 case '\r':\r
1022 Format += BytesPerFormatCharacter;\r
b1d4b965 1023 FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask;\r
c553db4b 1024 if (FormatCharacter == '\n') {\r
1025 //\r
1026 // Translate '\r\n' to '\r\n'\r
1027 //\r
1028 ArgumentString = "\r\n";\r
1029 } else {\r
1030 //\r
1031 // Translate '\r' to '\r'\r
1032 //\r
1033 ArgumentString = "\r";\r
1034 Format -= BytesPerFormatCharacter;\r
1035 }\r
1036 break;\r
1037\r
e389c39b 1038 case '\n':\r
c553db4b 1039 //\r
1040 // Translate '\n' to '\r\n' and '\n\r' to '\r\n'\r
1041 //\r
1042 ArgumentString = "\r\n";\r
1043 Format += BytesPerFormatCharacter;\r
b1d4b965 1044 FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask;\r
c553db4b 1045 if (FormatCharacter != '\r') {\r
1046 Format -= BytesPerFormatCharacter;\r
1047 }\r
e389c39b 1048 break;\r
1049\r
1050 case '%':\r
1051 default:\r
1052 //\r
1053 // if the type is '%' or unknown, then print it to the screen\r
1054 //\r
1055 ArgumentString = (CHAR8 *)&FormatCharacter;\r
1056 Flags |= ARGUMENT_UNICODE;\r
1057 break;\r
1058 }\r
1059 break;\r
9095d37b 1060\r
c553db4b 1061 case '\r':\r
1062 Format += BytesPerFormatCharacter;\r
b1d4b965 1063 FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask;\r
c553db4b 1064 if (FormatCharacter == '\n') {\r
1065 //\r
1066 // Translate '\r\n' to '\r\n'\r
1067 //\r
1068 ArgumentString = "\r\n";\r
1069 } else {\r
1070 //\r
1071 // Translate '\r' to '\r'\r
1072 //\r
1073 ArgumentString = "\r";\r
1074 Format -= BytesPerFormatCharacter;\r
1075 }\r
1076 break;\r
1077\r
e389c39b 1078 case '\n':\r
c553db4b 1079 //\r
1080 // Translate '\n' to '\r\n' and '\n\r' to '\r\n'\r
1081 //\r
1082 ArgumentString = "\r\n";\r
1083 Format += BytesPerFormatCharacter;\r
b1d4b965 1084 FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask;\r
c553db4b 1085 if (FormatCharacter != '\r') {\r
1086 Format -= BytesPerFormatCharacter;\r
1087 }\r
e389c39b 1088 break;\r
1089\r
1090 default:\r
1091 ArgumentString = (CHAR8 *)&FormatCharacter;\r
1092 Flags |= ARGUMENT_UNICODE;\r
1093 break;\r
1094 }\r
1095\r
1096 //\r
1097 // Retrieve the ArgumentString attriubutes\r
1098 //\r
1099 if ((Flags & ARGUMENT_UNICODE) != 0) {\r
1100 ArgumentMask = 0xffff;\r
1101 BytesPerArgumentCharacter = 2;\r
1102 } else {\r
1103 ArgumentMask = 0xff;\r
1104 BytesPerArgumentCharacter = 1;\r
1105 }\r
1106 if ((Flags & ARGUMENT_REVERSED) != 0) {\r
1107 BytesPerArgumentCharacter = -BytesPerArgumentCharacter;\r
1108 } else {\r
1109 //\r
1110 // Compute the number of characters in ArgumentString and store it in Count\r
1111 // ArgumentString is either null-terminated, or it contains Precision characters\r
1112 //\r
6805854a 1113 for (Count = 0;\r
701e8cc2
WJ
1114 (ArgumentString[Count * BytesPerArgumentCharacter] != '\0' ||\r
1115 (BytesPerArgumentCharacter > 1 &&\r
1116 ArgumentString[Count * BytesPerArgumentCharacter + 1]!= '\0')) &&\r
6805854a
JW
1117 (Count < Precision || ((Flags & PRECISION) == 0));\r
1118 Count++) {\r
e389c39b 1119 ArgumentCharacter = ((ArgumentString[Count * BytesPerArgumentCharacter] & 0xff) | ((ArgumentString[Count * BytesPerArgumentCharacter + 1]) << 8)) & ArgumentMask;\r
1120 if (ArgumentCharacter == 0) {\r
1121 break;\r
1122 }\r
1123 }\r
1124 }\r
1125\r
1126 if (Precision < Count) {\r
1127 Precision = Count;\r
1128 }\r
1129\r
1130 //\r
1131 // Pad before the string\r
1132 //\r
1133 if ((Flags & (PAD_TO_WIDTH | LEFT_JUSTIFY)) == (PAD_TO_WIDTH)) {\r
6bae492f 1134 LengthToReturn += ((Width - Precision) * BytesPerOutputCharacter);\r
6709bbd1 1135 if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {\r
f405c067 1136 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Width - Precision, ' ', BytesPerOutputCharacter);\r
1137 }\r
e389c39b 1138 }\r
1139\r
1140 if (ZeroPad) {\r
1141 if (Prefix != 0) {\r
6bae492f 1142 LengthToReturn += (1 * BytesPerOutputCharacter);\r
6709bbd1 1143 if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {\r
f405c067 1144 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, Prefix, BytesPerOutputCharacter);\r
1145 }\r
1146 }\r
6bae492f 1147 LengthToReturn += ((Precision - Count) * BytesPerOutputCharacter);\r
6709bbd1 1148 if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {\r
f405c067 1149 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Precision - Count, '0', BytesPerOutputCharacter);\r
e389c39b 1150 }\r
e389c39b 1151 } else {\r
6bae492f 1152 LengthToReturn += ((Precision - Count) * BytesPerOutputCharacter);\r
6709bbd1 1153 if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {\r
f405c067 1154 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Precision - Count, ' ', BytesPerOutputCharacter);\r
1155 }\r
e389c39b 1156 if (Prefix != 0) {\r
6bae492f 1157 LengthToReturn += (1 * BytesPerOutputCharacter);\r
6709bbd1 1158 if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {\r
f405c067 1159 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, Prefix, BytesPerOutputCharacter);\r
1160 }\r
e389c39b 1161 }\r
1162 }\r
1163\r
1164 //\r
1165 // Output the Prefix character if it is present\r
1166 //\r
1167 Index = 0;\r
1168 if (Prefix != 0) {\r
1169 Index++;\r
1170 }\r
1171\r
1172 //\r
1173 // Copy the string into the output buffer performing the required type conversions\r
1174 //\r
701e8cc2
WJ
1175 while (Index < Count &&\r
1176 (ArgumentString[0] != '\0' ||\r
1177 (BytesPerArgumentCharacter > 1 && ArgumentString[1] != '\0'))) {\r
ea0b1506 1178 ArgumentCharacter = ((*ArgumentString & 0xff) | (((UINT8)*(ArgumentString + 1)) << 8)) & ArgumentMask;\r
e389c39b 1179\r
6bae492f 1180 LengthToReturn += (1 * BytesPerOutputCharacter);\r
6709bbd1 1181 if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {\r
f405c067 1182 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ArgumentCharacter, BytesPerOutputCharacter);\r
1183 }\r
e389c39b 1184 ArgumentString += BytesPerArgumentCharacter;\r
1185 Index++;\r
1186 if (Comma) {\r
1187 Digits++;\r
1188 if (Digits == 3) {\r
1189 Digits = 0;\r
1190 Index++;\r
1191 if (Index < Count) {\r
6bae492f 1192 LengthToReturn += (1 * BytesPerOutputCharacter);\r
6709bbd1 1193 if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {\r
f405c067 1194 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ',', BytesPerOutputCharacter);\r
1195 }\r
e389c39b 1196 }\r
1197 }\r
1198 }\r
1199 }\r
1200\r
1201 //\r
1202 // Pad after the string\r
1203 //\r
1204 if ((Flags & (PAD_TO_WIDTH | LEFT_JUSTIFY)) == (PAD_TO_WIDTH | LEFT_JUSTIFY)) {\r
6bae492f 1205 LengthToReturn += ((Width - Precision) * BytesPerOutputCharacter);\r
6709bbd1 1206 if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {\r
f405c067 1207 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Width - Precision, ' ', BytesPerOutputCharacter);\r
1208 }\r
e389c39b 1209 }\r
1210\r
1211 //\r
1212 // Get the next character from the format string\r
1213 //\r
1214 Format += BytesPerFormatCharacter;\r
1215\r
1216 //\r
1217 // Get the next character from the format string\r
1218 //\r
b1d4b965 1219 FormatCharacter = ((*Format & 0xff) | ((BytesPerFormatCharacter == 1) ? 0 : (*(Format + 1) << 8))) & FormatMask;\r
e389c39b 1220 }\r
1221\r
4ae2e63c 1222 if ((Flags & COUNT_ONLY_NO_PRINT) != 0) {\r
f405c067 1223 return (LengthToReturn / BytesPerOutputCharacter);\r
1224 }\r
1225\r
6709bbd1 1226 ASSERT (Buffer != NULL);\r
e389c39b 1227 //\r
1228 // Null terminate the Unicode or ASCII string\r
1229 //\r
1230 BasePrintLibFillBuffer (Buffer, EndBuffer + BytesPerOutputCharacter, 1, 0, BytesPerOutputCharacter);\r
e389c39b 1231\r
1232 return ((Buffer - OriginalBuffer) / BytesPerOutputCharacter);\r
1233}\r
1234\r
1235/**\r
9095d37b 1236 Worker function that produces a Null-terminated string in an output buffer\r
e389c39b 1237 based on a Null-terminated format string and variable argument list.\r
1238\r
9095d37b
LG
1239 VSPrint function to process format and place the results in Buffer. Since a\r
1240 VA_LIST is used this routine allows the nesting of Vararg routines. Thus\r
efb23117 1241 this is the main print working routine\r
e389c39b 1242\r
2fc59a00 1243 @param StartOfBuffer The character buffer to print the results of the parsing\r
e389c39b 1244 of Format into.\r
2fc59a00 1245 @param BufferSize The maximum number of characters to put into buffer.\r
e389c39b 1246 Zero means no limit.\r
7c905091 1247 @param Flags Initial flags value.\r
e389c39b 1248 Can only have FORMAT_UNICODE and OUTPUT_UNICODE set\r
2fc59a00 1249 @param FormatString A Null-terminated format string.\r
e389c39b 1250 @param ... The variable argument list.\r
1251\r
2fc59a00 1252 @return The number of characters printed.\r
e389c39b 1253\r
1254**/\r
1255UINTN\r
932d66a9 1256EFIAPI\r
e389c39b 1257BasePrintLibSPrint (\r
1258 OUT CHAR8 *StartOfBuffer,\r
1259 IN UINTN BufferSize,\r
1260 IN UINTN Flags,\r
1261 IN CONST CHAR8 *FormatString,\r
1262 ...\r
1263 )\r
1264{\r
1265 VA_LIST Marker;\r
3bbe68a3 1266 UINTN NumberOfPrinted;\r
e389c39b 1267\r
1268 VA_START (Marker, FormatString);\r
3bbe68a3 1269 NumberOfPrinted = BasePrintLibSPrintMarker (StartOfBuffer, BufferSize, Flags, FormatString, Marker, NULL);\r
1270 VA_END (Marker);\r
1271 return NumberOfPrinted;\r
e389c39b 1272}\r