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