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