]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/BasePrintLib/PrintLibInternal.c
Fix the prototype inconsitency issue.
[mirror_edk2.git] / MdePkg / Library / BasePrintLib / PrintLibInternal.c
CommitLineData
e1f414b6 1/** @file\r
eceb3a4c 2 Print Library internal worker functions.\r
e1f414b6 3\r
eceb3a4c 4 Copyright (c) 2006 - 2008, Intel Corporation<BR>\r
e1f414b6 5 All rights reserved. This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
e1f414b6 13**/\r
14\r
e1f414b6 15#include "PrintLibInternal.h"\r
16\r
e389c39b 17#define WARNING_STATUS_NUMBER 4\r
18#define ERROR_STATUS_NUMBER 24\r
19\r
e1f414b6 20GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mHexStr[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};\r
21\r
e389c39b 22GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mStatusString[] = {\r
23 "Success", // RETURN_SUCCESS = 0\r
24 "Warning Unknown Glyph", // RETURN_WARN_UNKNOWN_GLYPH = 1\r
25 "Warning Delete Failure", // RETURN_WARN_DELETE_FAILURE = 2\r
26 "Warning Write Failure", // RETURN_WARN_WRITE_FAILURE = 3\r
27 "Warning Buffer Too Small", // RETURN_WARN_BUFFER_TOO_SMALL = 4\r
28 "Load Error", // RETURN_LOAD_ERROR = 1 | MAX_BIT\r
29 "Invalid Parameter", // RETURN_INVALID_PARAMETER = 2 | MAX_BIT\r
30 "Unsupported", // RETURN_UNSUPPORTED = 3 | MAX_BIT\r
31 "Bad Buffer Size", // RETURN_BAD_BUFFER_SIZE = 4 | MAX_BIT\r
32 "Buffer Too Small", // RETURN_BUFFER_TOO_SMALL, = 5 | MAX_BIT\r
33 "Not Ready", // RETURN_NOT_READY = 6 | MAX_BIT\r
34 "Device Error", // RETURN_DEVICE_ERROR = 7 | MAX_BIT\r
35 "Write Protected", // RETURN_WRITE_PROTECTED = 8 | MAX_BIT\r
36 "Out of Resources", // RETURN_OUT_OF_RESOURCES = 9 | MAX_BIT\r
37 "Volume Corrupt", // RETURN_VOLUME_CORRUPTED = 10 | MAX_BIT\r
38 "Volume Full", // RETURN_VOLUME_FULL = 11 | MAX_BIT\r
39 "No Media", // RETURN_NO_MEDIA = 12 | MAX_BIT\r
40 "Media changed", // RETURN_MEDIA_CHANGED = 13 | MAX_BIT\r
41 "Not Found", // RETURN_NOT_FOUND = 14 | MAX_BIT\r
42 "Access Denied", // RETURN_ACCESS_DENIED = 15 | MAX_BIT\r
43 "No Response", // RETURN_NO_RESPONSE = 16 | MAX_BIT\r
44 "No mapping", // RETURN_NO_MAPPING = 17 | MAX_BIT\r
45 "Time out", // RETURN_TIMEOUT = 18 | MAX_BIT\r
46 "Not started", // RETURN_NOT_STARTED = 19 | MAX_BIT\r
47 "Already started", // RETURN_ALREADY_STARTED = 20 | MAX_BIT\r
48 "Aborted", // RETURN_ABORTED = 21 | MAX_BIT\r
49 "ICMP Error", // RETURN_ICMP_ERROR = 22 | MAX_BIT\r
50 "TFTP Error", // RETURN_TFTP_ERROR = 23 | MAX_BIT\r
51 "Protocol Error" // RETURN_PROTOCOL_ERROR = 24 | MAX_BIT\r
52};\r
53\r
e1f414b6 54\r
55/**\r
56 Internal function that places the character into the Buffer.\r
57\r
58 Internal function that places ASCII or Unicode character into the Buffer.\r
59\r
60 @param Buffer Buffer to place the Unicode or ASCII string.\r
61 @param EndBuffer The end of the input Buffer. No characters will be\r
62 placed after that. \r
63 @param Length Count of character to be placed into Buffer.\r
64 @param Character Character to be placed into Buffer.\r
65 @param Increment Character increment in Buffer.\r
66\r
eceb3a4c 67 @return Buffer Buffer filled with the input Character.\r
e1f414b6 68\r
69**/\r
70CHAR8 *\r
71BasePrintLibFillBuffer (\r
eceb3a4c
LG
72 OUT CHAR8 *Buffer,\r
73 IN CHAR8 *EndBuffer,\r
74 IN INTN Length,\r
75 IN UINTN Character,\r
76 IN INTN Increment\r
e1f414b6 77 )\r
78{\r
79 INTN Index;\r
d6039b1d 80 if(Increment != 1) {\r
81 for (Index = 0; Index < Length && Buffer < EndBuffer; Index++) {\r
82 *Buffer = (CHAR8) Character;\r
83 *(Buffer + 1) = (CHAR8) (Character >> 8);\r
340ffb09 84 Buffer += Increment;\r
d6039b1d 85 }\r
d6039b1d 86 } else {\r
87 for (Index = 0; Index < Length && Buffer < EndBuffer; Index++) {\r
88 *Buffer = (CHAR8) Character;\r
340ffb09 89 Buffer += Increment;\r
d6039b1d 90 }\r
e1f414b6 91 }\r
92 return Buffer;\r
93}\r
94\r
95/**\r
96 Internal function that convert a decimal number to a string in Buffer.\r
97\r
98 Print worker function that convert a decimal number to a string in Buffer.\r
99\r
100 @param Buffer Location to place the Unicode or ASCII string of Value.\r
101 @param Value Value to convert to a Decimal or Hexidecimal string in Buffer.\r
102 @param Radix Radix of the value\r
103\r
104 @return Number of characters printed.\r
105\r
106**/\r
107UINTN\r
e1f414b6 108BasePrintLibValueToString (\r
efb23117 109 IN OUT CHAR8 *Buffer, \r
110 IN INT64 Value, \r
e1f414b6 111 IN UINTN Radix\r
112 )\r
113{\r
114 UINTN Digits;\r
115 UINT32 Remainder;\r
116\r
117 //\r
118 // Loop to convert one digit at a time in reverse order\r
119 //\r
120 *(Buffer++) = 0;\r
121 Digits = 0;\r
122 do {\r
123 Value = (INT64)DivU64x32Remainder ((UINT64)Value, (UINT32)Radix, &Remainder);\r
124 *(Buffer++) = mHexStr[Remainder];\r
125 Digits++;\r
126 } while (Value != 0);\r
eceb3a4c
LG
127\r
128 //\r
129 // the length of Buffer string converted from Value\r
130 //\r
e1f414b6 131 return Digits;\r
132}\r
133\r
134/**\r
135 Internal function that converts a decimal value to a Null-terminated string.\r
136 \r
137 Converts the decimal number specified by Value to a Null-terminated \r
138 string specified by Buffer containing at most Width characters.\r
139 If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed.\r
efb23117 140 The total number of characters placed in Buffer is returned.\r
e1f414b6 141 If the conversion contains more than Width characters, then only the first\r
142 Width characters are returned, and the total number of characters \r
143 required to perform the conversion is returned.\r
144 Additional conversion parameters are specified in Flags. \r
145 The Flags bit LEFT_JUSTIFY is always ignored.\r
146 All conversions are left justified in Buffer.\r
147 If Width is 0, PREFIX_ZERO is ignored in Flags.\r
148 If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and commas\r
149 are inserted every 3rd digit starting from the right.\r
efb23117 150 If Value is < 0, then the fist character in Buffer is a '-'.\r
e1f414b6 151 If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored, \r
152 then Buffer is padded with '0' characters so the combination of the optional '-' \r
153 sign character, '0' characters, digit characters for Value, and the Null-terminator\r
154 add up to Width characters.\r
e1f414b6 155\r
156 If Buffer is NULL, then ASSERT().\r
157 If unsupported bits are set in Flags, then ASSERT().\r
158 If Width >= MAXIMUM_VALUE_CHARACTERS, then ASSERT()\r
159\r
160 @param Buffer Pointer to the output buffer for the produced Null-terminated\r
161 string.\r
162 @param Flags The bitmask of flags that specify left justification, zero pad,\r
163 and commas.\r
164 @param Value The 64-bit signed value to convert to a string.\r
165 @param Width The maximum number of characters to place in Buffer, not including\r
166 the Null-terminator.\r
167 @param Increment Character increment in Buffer.\r
168 \r
efb23117 169 @return Total number of characters required to perform the conversion.\r
e1f414b6 170\r
171**/\r
172UINTN\r
173BasePrintLibConvertValueToString (\r
174 IN OUT CHAR8 *Buffer,\r
175 IN UINTN Flags,\r
176 IN INT64 Value,\r
177 IN UINTN Width,\r
178 IN UINTN Increment\r
179 )\r
180{\r
181 CHAR8 *OriginalBuffer;\r
182 CHAR8 *EndBuffer;\r
183 CHAR8 ValueBuffer[MAXIMUM_VALUE_CHARACTERS];\r
184 UINTN Count;\r
185 UINTN Digits;\r
186 UINTN Index;\r
187 UINTN Radix;\r
188\r
eceb3a4c
LG
189 //\r
190 // Make sure Buffer is not NULL and Width < MAXIMUM\r
191 //\r
e1f414b6 192 ASSERT (Buffer != NULL);\r
193 ASSERT (Width < MAXIMUM_VALUE_CHARACTERS);\r
194 //\r
195 // Make sure Flags can only contain supported bits.\r
196 //\r
197 ASSERT ((Flags & ~(LEFT_JUSTIFY | COMMA_TYPE | PREFIX_ZERO | RADIX_HEX)) == 0);\r
198\r
199 //\r
200 // If both COMMA_TYPE and HEX_RADIX are set, then ASSERT ()\r
201 //\r
202 ASSERT (((Flags & COMMA_TYPE) != 0 && (Flags & RADIX_HEX) != 0) == FALSE);\r
203\r
204 OriginalBuffer = Buffer;\r
eceb3a4c
LG
205 \r
206 //\r
207 // Width is 0 or COMMA_TYPE is set, PREFIX_ZERO is ignored.\r
208 //\r
e1f414b6 209 if (Width == 0 || (Flags & COMMA_TYPE) != 0) {\r
210 Flags &= (~PREFIX_ZERO);\r
211 }\r
eceb3a4c
LG
212 //\r
213 // If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed.\r
214 //\r
e1f414b6 215 if (Width == 0) {\r
216 Width = MAXIMUM_VALUE_CHARACTERS - 1;\r
217 }\r
218 //\r
219 // Set the tag for the end of the input Buffer.\r
220 //\r
221 EndBuffer = Buffer + Width * Increment;\r
eceb3a4c
LG
222 \r
223 //\r
224 // Convert decimal negative\r
225 //\r
e1f414b6 226 if ((Value < 0) && ((Flags & RADIX_HEX) == 0)) {\r
227 Value = -Value;\r
228 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, '-', Increment);\r
229 Width--;\r
230 }\r
eceb3a4c
LG
231 \r
232 //\r
233 // Count the length of the value string.\r
234 //\r
e1f414b6 235 Radix = ((Flags & RADIX_HEX) == 0)? 10 : 16;\r
236 Count = BasePrintLibValueToString (ValueBuffer, Value, Radix);\r
eceb3a4c
LG
237 \r
238 //\r
239 // Append Zero\r
240 //\r
e1f414b6 241 if ((Flags & PREFIX_ZERO) != 0) {\r
242 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Width - Count, '0', Increment);\r
243 }\r
eceb3a4c
LG
244 \r
245 //\r
246 // Print Comma type for every 3 characters\r
247 //\r
e1f414b6 248 Digits = Count % 3;\r
249 if (Digits != 0) {\r
250 Digits = 3 - Digits;\r
251 }\r
252 for (Index = 0; Index < Count; Index++) {\r
253 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ValueBuffer[Count - Index], Increment);\r
254 if ((Flags & COMMA_TYPE) != 0) {\r
255 Digits++;\r
256 if (Digits == 3) {\r
257 Digits = 0;\r
258 if ((Index + 1) < Count) {\r
259 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ',', Increment);\r
260 }\r
261 }\r
262 }\r
263 }\r
eceb3a4c
LG
264 \r
265 //\r
266 // Print Null-terminator\r
267 //\r
e1f414b6 268 BasePrintLibFillBuffer (Buffer, EndBuffer + Increment, 1, 0, Increment);\r
269\r
270 return ((Buffer - OriginalBuffer) / Increment);\r
271}\r
272\r
e389c39b 273/**\r
274 Worker function that produces a Null-terminated string in an output buffer \r
275 based on a Null-terminated format string and a VA_LIST argument list.\r
276\r
277 VSPrint function to process format and place the results in Buffer. Since a \r
278 VA_LIST is used this rountine allows the nesting of Vararg routines. Thus \r
279 this is the main print working routine.\r
280\r
281 @param Buffer Character buffer to print the results of the parsing\r
282 of Format into.\r
283 @param BufferSize Maximum number of characters to put into buffer.\r
284 @param Flags Intial flags value.\r
285 Can only have FORMAT_UNICODE and OUTPUT_UNICODE set.\r
286 @param Format Null-terminated format string.\r
287 @param Marker Vararg list consumed by processing Format.\r
288\r
289 @return Number of characters printed not including the Null-terminator.\r
290\r
291**/\r
292UINTN\r
293BasePrintLibVSPrint (\r
294 OUT CHAR8 *Buffer,\r
295 IN UINTN BufferSize,\r
296 IN UINTN Flags,\r
297 IN CONST CHAR8 *Format,\r
298 IN VA_LIST Marker\r
299 )\r
300{\r
301 CHAR8 *OriginalBuffer;\r
302 CHAR8 *EndBuffer;\r
303 CHAR8 ValueBuffer[MAXIMUM_VALUE_CHARACTERS];\r
304 UINTN BytesPerOutputCharacter;\r
305 UINTN BytesPerFormatCharacter;\r
306 UINTN FormatMask;\r
307 UINTN FormatCharacter;\r
308 UINTN Width;\r
309 UINTN Precision;\r
310 INT64 Value;\r
311 CONST CHAR8 *ArgumentString;\r
312 UINTN Character;\r
313 GUID *TmpGuid;\r
314 TIME *TmpTime;\r
315 UINTN Count;\r
316 UINTN ArgumentMask;\r
317 INTN BytesPerArgumentCharacter;\r
318 UINTN ArgumentCharacter;\r
319 BOOLEAN Done;\r
320 UINTN Index;\r
321 CHAR8 Prefix;\r
322 BOOLEAN ZeroPad;\r
323 BOOLEAN Comma;\r
324 UINTN Digits;\r
325 UINTN Radix;\r
326 RETURN_STATUS Status;\r
327\r
328 if (BufferSize == 0) {\r
329 return 0;\r
330 }\r
331 ASSERT (Buffer != NULL);\r
332\r
333 if ((Flags & OUTPUT_UNICODE) != 0) {\r
334 BytesPerOutputCharacter = 2;\r
335 } else {\r
336 BytesPerOutputCharacter = 1;\r
337 }\r
338\r
339 //\r
340 // Reserve space for the Null terminator.\r
341 //\r
342 BufferSize--;\r
343 OriginalBuffer = Buffer;\r
344 //\r
345 // Set the tag for the end of the input Buffer.\r
346 //\r
347 EndBuffer = Buffer + BufferSize * BytesPerOutputCharacter;\r
348\r
349 if ((Flags & FORMAT_UNICODE) != 0) {\r
350 //\r
351 // Make sure format string cannot contain more than PcdMaximumUnicodeStringLength\r
352 // Unicode characters if PcdMaximumUnicodeStringLength is not zero. \r
353 //\r
354 ASSERT (StrSize ((CHAR16 *) Format) != 0);\r
355 BytesPerFormatCharacter = 2;\r
356 FormatMask = 0xffff;\r
357 } else {\r
358 //\r
359 // Make sure format string cannot contain more than PcdMaximumAsciiStringLength\r
360 // Ascii characters if PcdMaximumAsciiStringLength is not zero. \r
361 //\r
362 ASSERT (AsciiStrSize (Format) != 0);\r
363 BytesPerFormatCharacter = 1;\r
364 FormatMask = 0xff;\r
365 }\r
366\r
367\r
368\r
369 //\r
370 // Get the first character from the format string\r
371 //\r
372 FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;\r
373\r
374 //\r
375 // Loop until the end of the format string is reached or the output buffer is full\r
376 //\r
377 while (FormatCharacter != 0 && Buffer < EndBuffer) {\r
378 //\r
379 // Clear all the flag bits except those that may have been passed in\r
380 //\r
381 Flags &= (OUTPUT_UNICODE | FORMAT_UNICODE);\r
382\r
383 //\r
384 // Set the default width to zero, and the default precision to 1\r
385 //\r
386 Width = 0;\r
387 Precision = 1;\r
388 Prefix = 0;\r
389 Comma = FALSE;\r
390 ZeroPad = FALSE;\r
391 Count = 0;\r
392 Digits = 0;\r
393\r
394 switch (FormatCharacter) {\r
395 case '%':\r
396 //\r
397 // Parse Flags and Width\r
398 //\r
399 for (Done = FALSE; !Done; ) {\r
400 Format += BytesPerFormatCharacter;\r
401 FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;\r
402 switch (FormatCharacter) {\r
403 case '.': \r
404 Flags |= PRECISION; \r
405 break;\r
406 case '-': \r
407 Flags |= LEFT_JUSTIFY; \r
408 break;\r
409 case '+': \r
410 Flags |= PREFIX_SIGN; \r
411 break;\r
412 case ' ': \r
413 Flags |= PREFIX_BLANK; \r
414 break;\r
415 case ',': \r
416 Flags |= COMMA_TYPE; \r
417 break;\r
418 case 'L':\r
419 case 'l': \r
420 Flags |= LONG_TYPE; \r
421 break;\r
422 case '*':\r
423 if ((Flags & PRECISION) == 0) {\r
424 Flags |= PAD_TO_WIDTH;\r
425 Width = VA_ARG (Marker, UINTN);\r
426 } else {\r
427 Precision = VA_ARG (Marker, UINTN);\r
428 }\r
429 break;\r
430 case '0':\r
431 if ((Flags & PRECISION) == 0) {\r
432 Flags |= PREFIX_ZERO;\r
433 }\r
434 case '1':\r
435 case '2':\r
436 case '3':\r
437 case '4':\r
438 case '5':\r
439 case '6':\r
440 case '7':\r
441 case '8':\r
442 case '9':\r
443 for (Count = 0; ((FormatCharacter >= '0') && (FormatCharacter <= '9')); ){\r
444 Count = (Count * 10) + FormatCharacter - '0';\r
445 Format += BytesPerFormatCharacter;\r
446 FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;\r
447 }\r
448 Format -= BytesPerFormatCharacter;\r
449 if ((Flags & PRECISION) == 0) {\r
450 Flags |= PAD_TO_WIDTH;\r
451 Width = Count;\r
452 } else {\r
453 Precision = Count;\r
454 }\r
455 break;\r
456 \r
457 case '\0':\r
458 //\r
459 // Make no output if Format string terminates unexpectedly when\r
460 // looking up for flag, width, precision and type. \r
461 //\r
462 Format -= BytesPerFormatCharacter;\r
463 Precision = 0;\r
464 //\r
465 // break skipped on purpose.\r
466 //\r
467 default:\r
468 Done = TRUE;\r
469 break;\r
470 }\r
471 } \r
472\r
473 //\r
474 // Handle each argument type\r
475 //\r
476 switch (FormatCharacter) {\r
477 case 'p':\r
478 //\r
479 // Flag space, +, 0, L & l are invalid for type p.\r
480 //\r
481 Flags &= ~(PREFIX_BLANK | PREFIX_SIGN | PREFIX_ZERO | LONG_TYPE);\r
482 if (sizeof (VOID *) > 4) {\r
483 Flags |= LONG_TYPE;\r
484 }\r
485 case 'X':\r
486 Flags |= PREFIX_ZERO;\r
487 //\r
488 // break skipped on purpose\r
489 //\r
490 case 'x':\r
491 Flags |= RADIX_HEX;\r
492 //\r
493 // break skipped on purpose\r
494 //\r
495 case 'd':\r
496 if ((Flags & LONG_TYPE) == 0) {\r
497 Value = (VA_ARG (Marker, int));\r
498 } else {\r
499 Value = VA_ARG (Marker, INT64);\r
500 }\r
501 if ((Flags & PREFIX_BLANK) != 0) {\r
502 Prefix = ' ';\r
503 }\r
504 if ((Flags & PREFIX_SIGN) != 0) {\r
505 Prefix = '+';\r
506 }\r
507 if ((Flags & COMMA_TYPE) != 0) {\r
508 Comma = TRUE;\r
509 }\r
510 if ((Flags & RADIX_HEX) == 0) {\r
511 Radix = 10;\r
512 if (Comma) {\r
513 Flags &= (~PREFIX_ZERO);\r
514 Precision = 1;\r
515 }\r
516 if (Value < 0) {\r
517 Flags |= PREFIX_SIGN;\r
518 Prefix = '-';\r
519 Value = -Value;\r
520 }\r
521 } else {\r
522 Radix = 16;\r
523 Comma = FALSE;\r
524 if ((Flags & LONG_TYPE) == 0 && Value < 0) {\r
525 Value = (unsigned int)Value;\r
526 }\r
527 }\r
528 //\r
529 // Convert Value to a reversed string\r
530 //\r
531 Count = BasePrintLibValueToString (ValueBuffer, Value, Radix);\r
532 if (Value == 0 && Precision == 0) {\r
533 Count = 0;\r
534 }\r
535 ArgumentString = (CHAR8 *)ValueBuffer + Count;\r
536 \r
537 Digits = Count % 3;\r
538 if (Digits != 0) {\r
539 Digits = 3 - Digits;\r
540 }\r
541 if (Comma && Count != 0) {\r
542 Count += ((Count - 1) / 3);\r
543 }\r
544 if (Prefix != 0) {\r
545 Count++;\r
546 Precision++;\r
547 }\r
548 Flags |= ARGUMENT_REVERSED;\r
549 ZeroPad = TRUE;\r
550 if ((Flags & PREFIX_ZERO) != 0) {\r
551 if ((Flags & LEFT_JUSTIFY) == 0) {\r
552 if ((Flags & PAD_TO_WIDTH) != 0) {\r
553 if ((Flags & PRECISION) == 0) {\r
554 Precision = Width;\r
555 }\r
556 }\r
557 }\r
558 }\r
559 break;\r
560\r
561 case 's':\r
562 case 'S':\r
563 Flags |= ARGUMENT_UNICODE;\r
564 //\r
565 // break skipped on purpose\r
566 //\r
567 case 'a':\r
568 ArgumentString = (CHAR8 *)VA_ARG (Marker, CHAR8 *);\r
569 if (ArgumentString == NULL) {\r
570 Flags &= (~ARGUMENT_UNICODE);\r
571 ArgumentString = "<null string>";\r
572 }\r
573 //\r
574 // Set the default precision for string to be zero if not specified.\r
575 //\r
576 if ((Flags & PRECISION) == 0) {\r
577 Precision = 0;\r
578 }\r
579 break;\r
580\r
581 case 'c':\r
582 Character = VA_ARG (Marker, UINTN) & 0xffff;\r
583 ArgumentString = (CHAR8 *)&Character;\r
584 Flags |= ARGUMENT_UNICODE;\r
585 break;\r
586\r
587 case 'g':\r
588 TmpGuid = VA_ARG (Marker, GUID *);\r
589 if (TmpGuid == NULL) {\r
590 ArgumentString = "<null guid>";\r
591 } else {\r
592 BasePrintLibSPrint (\r
593 ValueBuffer,\r
594 MAXIMUM_VALUE_CHARACTERS, \r
595 0,\r
596 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",\r
597 TmpGuid->Data1,\r
598 TmpGuid->Data2,\r
599 TmpGuid->Data3,\r
600 TmpGuid->Data4[0],\r
601 TmpGuid->Data4[1],\r
602 TmpGuid->Data4[2],\r
603 TmpGuid->Data4[3],\r
604 TmpGuid->Data4[4],\r
605 TmpGuid->Data4[5],\r
606 TmpGuid->Data4[6],\r
607 TmpGuid->Data4[7]\r
608 );\r
609 ArgumentString = ValueBuffer;\r
610 }\r
611 break;\r
612\r
613 case 't':\r
614 TmpTime = VA_ARG (Marker, TIME *); \r
615 if (TmpTime == NULL) {\r
616 ArgumentString = "<null time>";\r
617 } else {\r
618 BasePrintLibSPrint (\r
619 ValueBuffer,\r
620 MAXIMUM_VALUE_CHARACTERS,\r
621 0,\r
622 "%02d/%02d/%04d %02d:%02d",\r
623 TmpTime->Month,\r
624 TmpTime->Day,\r
625 TmpTime->Year,\r
626 TmpTime->Hour,\r
627 TmpTime->Minute\r
628 );\r
629 ArgumentString = ValueBuffer;\r
630 }\r
631 break;\r
632\r
633 case 'r':\r
634 Status = VA_ARG (Marker, RETURN_STATUS);\r
635 ArgumentString = ValueBuffer;\r
636 if (RETURN_ERROR (Status)) {\r
637 //\r
638 // Clear error bit\r
639 //\r
640 Index = Status & ~MAX_BIT;\r
641 if (Index > 0 && Index <= ERROR_STATUS_NUMBER) {\r
642 ArgumentString = mStatusString [Index + WARNING_STATUS_NUMBER];\r
643 }\r
644 } else {\r
645 Index = Status;\r
646 if (Index <= WARNING_STATUS_NUMBER) {\r
647 ArgumentString = mStatusString [Index];\r
648 }\r
649 }\r
650 if (ArgumentString == ValueBuffer) {\r
651 BasePrintLibSPrint ((CHAR8 *) ValueBuffer, MAXIMUM_VALUE_CHARACTERS, 0, "%08X", Status);\r
652 }\r
653 break;\r
654\r
655 case '\n':\r
656 ArgumentString = "\n\r";\r
657 break;\r
658\r
659 case '%':\r
660 default:\r
661 //\r
662 // if the type is '%' or unknown, then print it to the screen\r
663 //\r
664 ArgumentString = (CHAR8 *)&FormatCharacter;\r
665 Flags |= ARGUMENT_UNICODE;\r
666 break;\r
667 }\r
668 break;\r
669 \r
670 case '\n':\r
671 ArgumentString = "\n\r";\r
672 break;\r
673\r
674 default:\r
675 ArgumentString = (CHAR8 *)&FormatCharacter;\r
676 Flags |= ARGUMENT_UNICODE;\r
677 break;\r
678 }\r
679\r
680 //\r
681 // Retrieve the ArgumentString attriubutes\r
682 //\r
683 if ((Flags & ARGUMENT_UNICODE) != 0) {\r
684 ArgumentMask = 0xffff;\r
685 BytesPerArgumentCharacter = 2;\r
686 } else {\r
687 ArgumentMask = 0xff;\r
688 BytesPerArgumentCharacter = 1;\r
689 }\r
690 if ((Flags & ARGUMENT_REVERSED) != 0) {\r
691 BytesPerArgumentCharacter = -BytesPerArgumentCharacter;\r
692 } else {\r
693 //\r
694 // Compute the number of characters in ArgumentString and store it in Count\r
695 // ArgumentString is either null-terminated, or it contains Precision characters\r
696 //\r
697 for (Count = 0; Count < Precision || ((Flags & PRECISION) == 0); Count++) {\r
698 ArgumentCharacter = ((ArgumentString[Count * BytesPerArgumentCharacter] & 0xff) | ((ArgumentString[Count * BytesPerArgumentCharacter + 1]) << 8)) & ArgumentMask;\r
699 if (ArgumentCharacter == 0) {\r
700 break;\r
701 }\r
702 }\r
703 }\r
704\r
705 if (Precision < Count) {\r
706 Precision = Count;\r
707 }\r
708\r
709 //\r
710 // Pad before the string\r
711 //\r
712 if ((Flags & (PAD_TO_WIDTH | LEFT_JUSTIFY)) == (PAD_TO_WIDTH)) {\r
713 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Width - Precision, ' ', BytesPerOutputCharacter);\r
714 }\r
715\r
716 if (ZeroPad) {\r
717 if (Prefix != 0) {\r
718 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, Prefix, BytesPerOutputCharacter);\r
719 }\r
720 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Precision - Count, '0', BytesPerOutputCharacter);\r
721 } else {\r
722 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Precision - Count, ' ', BytesPerOutputCharacter);\r
723 if (Prefix != 0) {\r
724 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, Prefix, BytesPerOutputCharacter);\r
725 }\r
726 }\r
727\r
728 //\r
729 // Output the Prefix character if it is present\r
730 //\r
731 Index = 0;\r
732 if (Prefix != 0) {\r
733 Index++;\r
734 }\r
735\r
736 //\r
737 // Copy the string into the output buffer performing the required type conversions\r
738 //\r
739 while (Index < Count) {\r
740 ArgumentCharacter = ((*ArgumentString & 0xff) | (*(ArgumentString + 1) << 8)) & ArgumentMask;\r
741\r
742 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ArgumentCharacter, BytesPerOutputCharacter);\r
743 ArgumentString += BytesPerArgumentCharacter;\r
744 Index++;\r
745 if (Comma) {\r
746 Digits++;\r
747 if (Digits == 3) {\r
748 Digits = 0;\r
749 Index++;\r
750 if (Index < Count) {\r
751 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ',', BytesPerOutputCharacter);\r
752 }\r
753 }\r
754 }\r
755 }\r
756\r
757 //\r
758 // Pad after the string\r
759 //\r
760 if ((Flags & (PAD_TO_WIDTH | LEFT_JUSTIFY)) == (PAD_TO_WIDTH | LEFT_JUSTIFY)) {\r
761 Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Width - Precision, ' ', BytesPerOutputCharacter);\r
762 }\r
763\r
764 //\r
765 // Get the next character from the format string\r
766 //\r
767 Format += BytesPerFormatCharacter;\r
768\r
769 //\r
770 // Get the next character from the format string\r
771 //\r
772 FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;\r
773 }\r
774\r
775 //\r
776 // Null terminate the Unicode or ASCII string\r
777 //\r
778 BasePrintLibFillBuffer (Buffer, EndBuffer + BytesPerOutputCharacter, 1, 0, BytesPerOutputCharacter);\r
779 //\r
780 // Make sure output buffer cannot contain more than PcdMaximumUnicodeStringLength\r
781 // Unicode characters if PcdMaximumUnicodeStringLength is not zero. \r
782 //\r
783 ASSERT ((((Flags & OUTPUT_UNICODE) == 0)) || (StrSize ((CHAR16 *) OriginalBuffer) != 0));\r
784 //\r
785 // Make sure output buffer cannot contain more than PcdMaximumAsciiStringLength\r
786 // ASCII characters if PcdMaximumAsciiStringLength is not zero. \r
787 //\r
788 ASSERT ((((Flags & OUTPUT_UNICODE) != 0)) || (AsciiStrSize (OriginalBuffer) != 0));\r
789\r
790 return ((Buffer - OriginalBuffer) / BytesPerOutputCharacter);\r
791}\r
792\r
793/**\r
794 Worker function that produces a Null-terminated string in an output buffer \r
795 based on a Null-terminated format string and variable argument list.\r
796\r
797 VSPrint function to process format and place the results in Buffer. Since a \r
798 VA_LIST is used this rountine allows the nesting of Vararg routines. Thus \r
efb23117 799 this is the main print working routine\r
e389c39b 800\r
801 @param StartOfBuffer Character buffer to print the results of the parsing\r
802 of Format into.\r
803 @param BufferSize Maximum number of characters to put into buffer.\r
804 Zero means no limit.\r
805 @param Flags Intial flags value.\r
806 Can only have FORMAT_UNICODE and OUTPUT_UNICODE set\r
807 @param FormatString Null-terminated format string.\r
808 @param ... The variable argument list.\r
809\r
efb23117 810 @return Number of characters printed.\r
e389c39b 811\r
812**/\r
813UINTN\r
814BasePrintLibSPrint (\r
815 OUT CHAR8 *StartOfBuffer,\r
816 IN UINTN BufferSize,\r
817 IN UINTN Flags,\r
818 IN CONST CHAR8 *FormatString,\r
819 ...\r
820 )\r
821{\r
822 VA_LIST Marker;\r
823\r
824 VA_START (Marker, FormatString);\r
825 return BasePrintLibVSPrint (StartOfBuffer, BufferSize, Flags, FormatString, Marker);\r
826}\r