Add new OSS License
[mirror_edk2.git] / Tools / Source / TianoTools / String / PrintLib.c
1 /** @file
2 Print Library.
3
4
5 Copyright (c) 2004-2006 Intel Corporation. All rights reserved
6 This software and associated documentation (if any) is furnished
7 under a license and may only be used or copied in accordance
8 with the terms of the license. Except as permitted by such
9 license, no part of this software or documentation may be
10 reproduced, stored in a retrieval system, or transmitted in any
11 form or by any means without the express written consent of
12 Intel Corporation.
13
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16
17 Module Name: PrintLib.c
18
19 **/
20
21 #include <Common/UefiBaseTypes.h>
22 #include <Library/PrintLib.h>
23
24 #include "CommonLib.h"
25 #include "PrintLibInternal.h"
26
27 typedef struct {
28 RETURN_STATUS Status;
29 CHAR8 *String;
30 } STATUS_LOOKUP_TABLE_ENTRY;
31
32 static CONST STATUS_LOOKUP_TABLE_ENTRY StatusString[] = {
33 { RETURN_SUCCESS, "Success" },
34 { RETURN_LOAD_ERROR, "Load Error" },
35 { RETURN_INVALID_PARAMETER, "Invalid Parameter" },
36 { RETURN_UNSUPPORTED, "Unsupported" },
37 { RETURN_BAD_BUFFER_SIZE, "Bad Buffer Size" },
38 { RETURN_BUFFER_TOO_SMALL, "Buffer Too Small" },
39 { RETURN_NOT_READY, "Not Ready" },
40 { RETURN_DEVICE_ERROR, "Device Error" },
41 { RETURN_WRITE_PROTECTED, "Write Protected" },
42 { RETURN_OUT_OF_RESOURCES, "Out of Resources" },
43 { RETURN_VOLUME_CORRUPTED, "Volume Corrupt" },
44 { RETURN_VOLUME_FULL, "Volume Full" },
45 { RETURN_NO_MEDIA, "No Media" },
46 { RETURN_MEDIA_CHANGED, "Media changed" },
47 { RETURN_NOT_FOUND, "Not Found" },
48 { RETURN_ACCESS_DENIED, "Access Denied" },
49 { RETURN_NO_RESPONSE, "No Response" },
50 { RETURN_NO_MAPPING, "No mapping" },
51 { RETURN_TIMEOUT, "Time out" },
52 { RETURN_NOT_STARTED, "Not started" },
53 { RETURN_ALREADY_STARTED, "Already started" },
54 { RETURN_ABORTED, "Aborted" },
55 { RETURN_ICMP_ERROR, "ICMP Error" },
56 { RETURN_TFTP_ERROR, "TFTP Error" },
57 { RETURN_PROTOCOL_ERROR, "Protocol Error" },
58 { RETURN_WARN_UNKNOWN_GLYPH, "Warning Unknown Glyph" },
59 { RETURN_WARN_DELETE_FAILURE, "Warning Delete Failure" },
60 { RETURN_WARN_WRITE_FAILURE, "Warning Write Failure" },
61 { RETURN_WARN_BUFFER_TOO_SMALL, "Warning Buffer Too Small" },
62 { 0, NULL }
63 };
64
65
66 /**
67 VSPrint function to process format and place the results in Buffer. Since a
68 VA_LIST is used this rountine allows the nesting of Vararg routines. Thus
69 this is the main print working routine
70
71 @param StartOfBuffer Unicode buffer to print the results of the parsing of Format into.
72
73 @param BufferSize Maximum number of characters to put into buffer. Zero means
74 no limit.
75
76 @param Flags Intial flags value. Can only have FORMAT_UNICODE and OUTPUT_UNICODE set
77
78 @param FormatString Unicode format string see file header for more details.
79
80 @param Marker Vararg list consumed by processing Format.
81
82 @return Number of characters printed.
83
84 **/
85 UINTN
86 BasePrintLibVSPrint (
87 OUT CHAR8 *Buffer,
88 IN UINTN BufferSize,
89 IN UINTN Flags,
90 IN CONST CHAR8 *Format,
91 IN VA_LIST Marker
92 )
93 {
94 CHAR8 *OriginalBuffer;
95 CHAR8 ValueBuffer[MAXIMUM_VALUE_CHARACTERS];
96 UINTN BytesPerOutputCharacter;
97 UINTN BytesPerFormatCharacter;
98 UINTN FormatMask;
99 UINTN FormatCharacter;
100 UINTN Width;
101 UINTN Precision;
102 INT64 Value;
103 CHAR8 *ArgumentString;
104 UINTN Character;
105 GUID *TmpGuid;
106 TIME *TmpTime;
107 UINTN Count;
108 UINTN ArgumentMask;
109 INTN BytesPerArgumentCharacter;
110 UINTN ArgumentCharacter;
111 BOOLEAN Done;
112 UINTN Index;
113 CHAR8 Prefix;
114 BOOLEAN ZeroPad;
115 BOOLEAN Comma;
116 UINTN Digits;
117 UINTN Radix;
118 RETURN_STATUS Status;
119
120 OriginalBuffer = Buffer;
121
122 if ((Flags & OUTPUT_UNICODE) != 0) {
123 BytesPerOutputCharacter = 2;
124 } else {
125 BytesPerOutputCharacter = 1;
126 }
127 if ((Flags & FORMAT_UNICODE) != 0) {
128 BytesPerFormatCharacter = 2;
129 FormatMask = 0xffff;
130 } else {
131 BytesPerFormatCharacter = 1;
132 FormatMask = 0xff;
133 }
134
135 //
136 // Reserve space for the Null terminator.
137 // If BufferSize is 0, this will set BufferSize to the max unsigned value
138 //
139 BufferSize--;
140
141 //
142 // Get the first character from the format string
143 //
144 FormatCharacter = (*Format | (*(Format + 1) << 8)) & FormatMask;
145
146 //
147 // Loop until the end of the format string is reached or the output buffer is full
148 //
149 while (FormatCharacter != 0 && BufferSize > 0) {
150 //
151 // Clear all the flag bits except those that may have been passed in
152 //
153 Flags &= (OUTPUT_UNICODE | FORMAT_UNICODE);
154
155 //
156 // Set the default width to zero, and the default precision to 1
157 //
158 Width = 0;
159 Precision = 1;
160 Prefix = 0;
161 Comma = FALSE;
162 ZeroPad = FALSE;
163 Count = 0;
164 Digits = 0;
165
166 switch (FormatCharacter) {
167 case '%':
168 //
169 // Parse Flags and Width
170 //
171 for (Done = FALSE; !Done; ) {
172 Format += BytesPerFormatCharacter;
173 FormatCharacter = (*Format | (*(Format + 1) << 8)) & FormatMask;
174 switch (FormatCharacter) {
175 case '.':
176 Flags |= PRECISION;
177 break;
178 case '-':
179 Flags |= LEFT_JUSTIFY;
180 break;
181 case '+':
182 Flags |= PREFIX_SIGN;
183 break;
184 case ' ':
185 Flags |= PREFIX_BLANK;
186 break;
187 case ',':
188 Flags |= COMMA_TYPE;
189 break;
190 case 'L':
191 case 'l':
192 Flags |= LONG_TYPE;
193 break;
194 case '*':
195 if ((Flags & PRECISION) == 0) {
196 Flags |= PAD_TO_WIDTH;
197 Width = VA_ARG (Marker, UINTN);
198 } else {
199 Precision = VA_ARG (Marker, UINTN);
200 }
201 break;
202 case '0':
203 if ((Flags & PRECISION) == 0) {
204 Flags |= PREFIX_ZERO;
205 }
206 case '1':
207 case '2':
208 case '3':
209 case '4':
210 case '5':
211 case '6':
212 case '7':
213 case '8':
214 case '9':
215 for (Count = 0; ((FormatCharacter >= '0') && (FormatCharacter <= '9')); ){
216 Count = (Count * 10) + FormatCharacter - '0';
217 Format += BytesPerFormatCharacter;
218 FormatCharacter = (*Format | (*(Format + 1) << 8)) & FormatMask;
219 }
220 Format -= BytesPerFormatCharacter;
221 if ((Flags & PRECISION) == 0) {
222 Flags |= PAD_TO_WIDTH;
223 Width = Count;
224 } else {
225 Precision = Count;
226 }
227 break;
228 default:
229 Done = TRUE;
230 break;
231 }
232 }
233
234 //
235 // Limit the maximum field width to the remaining characters in the output buffer
236 //
237 if (Width > BufferSize) {
238 Width = BufferSize;
239 }
240
241 //
242 // Handle each argument type
243 //
244 switch (FormatCharacter) {
245 case 'X':
246 Flags |= PREFIX_ZERO;
247 //
248 // break skiped on purpose
249 //
250 case 'x':
251 Flags |= RADIX_HEX;
252 //
253 // break skiped on purpose
254 //
255 case 'd':
256 if ((Flags & LONG_TYPE) == 0) {
257 Value = (VA_ARG (Marker, INTN));
258 } else {
259 Value = VA_ARG (Marker, INT64);
260 }
261 if ((Flags & PREFIX_BLANK) != 0) {
262 Prefix = ' ';
263 }
264 if ((Flags & PREFIX_SIGN) != 0) {
265 Prefix = '+';
266 }
267 if ((Flags & COMMA_TYPE) != 0) {
268 Comma = TRUE;
269 }
270 if ((Flags & RADIX_HEX) == 0) {
271 Radix = 10;
272 if (Comma) {
273 Flags &= (~PREFIX_ZERO);
274 Precision = 1;
275 }
276 if (Value < 0) {
277 Flags |= PREFIX_SIGN;
278 Prefix = '-';
279 Value = -Value;
280 }
281 } else {
282 Radix = 16;
283 Comma = FALSE;
284 if ((Flags & LONG_TYPE) == 0 && Value < 0) {
285 Value = (UINTN)Value;
286 }
287 }
288 //
289 // Convert Value to a reversed string
290 //
291 Count = BasePrintLibValueToString (ValueBuffer, Value, Radix);
292 if (Value == 0 && Precision == 0) {
293 Count = 0;
294 }
295 ArgumentString = (CHAR8 *)ValueBuffer + Count;
296 Digits = 3 - (Count % 3);
297 if (Comma && Count != 0) {
298 Count += ((Count - 1) / 3);
299 }
300 if (Prefix != 0) {
301 Count++;
302 }
303 Flags |= ARGUMENT_REVERSED;
304 ZeroPad = TRUE;
305 if ((Flags & PREFIX_ZERO) != 0) {
306 if ((Flags & PAD_TO_WIDTH) != 0) {
307 if ((Flags & PRECISION) == 0) {
308 Precision = Width;
309 }
310 }
311 }
312 break;
313
314 case 's':
315 case 'S':
316 Flags |= ARGUMENT_UNICODE;
317 //
318 // break skipped on purpose
319 //
320 case 'a':
321 ArgumentString = (CHAR8 *)VA_ARG (Marker, CHAR8 *);
322 if (ArgumentString == NULL) {
323 Flags &= (~ARGUMENT_UNICODE);
324 ArgumentString = "<null string>";
325 }
326 break;
327
328 case 'c':
329 Character = VA_ARG (Marker, UINTN) & 0xffff;
330 ArgumentString = (CHAR8 *)&Character;
331 Flags |= ARGUMENT_UNICODE;
332 break;
333
334 case 'g':
335 TmpGuid = VA_ARG (Marker, GUID *);
336 if (TmpGuid == NULL) {
337 ArgumentString = "<null guid>";
338 } else {
339 BasePrintLibSPrint (
340 ValueBuffer,
341 0,
342 0,
343 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
344 TmpGuid->Data1,
345 TmpGuid->Data2,
346 TmpGuid->Data3,
347 TmpGuid->Data4[0],
348 TmpGuid->Data4[1],
349 TmpGuid->Data4[2],
350 TmpGuid->Data4[3],
351 TmpGuid->Data4[4],
352 TmpGuid->Data4[5],
353 TmpGuid->Data4[6],
354 TmpGuid->Data4[7]
355 );
356 ArgumentString = ValueBuffer;
357 }
358 break;
359
360 case 't':
361 TmpTime = VA_ARG (Marker, TIME *);
362 if (TmpTime == NULL) {
363 ArgumentString = "<null time>";
364 } else {
365 BasePrintLibSPrint (
366 ValueBuffer,
367 0,
368 0,
369 "%02d/%02d/%04d %02d:%02d",
370 TmpTime->Month,
371 TmpTime->Day,
372 TmpTime->Year,
373 TmpTime->Hour,
374 TmpTime->Minute
375 );
376 ArgumentString = ValueBuffer;
377 }
378 break;
379
380 case 'r':
381 Status = VA_ARG (Marker, RETURN_STATUS);
382 ArgumentString = ValueBuffer;
383 for (Index = 0; StatusString[Index].String != NULL; Index++) {
384 if (Status == StatusString[Index].Status) {
385 ArgumentString = StatusString[Index].String;
386 }
387 }
388 if (ArgumentString == ValueBuffer) {
389 BasePrintLibSPrint ((CHAR8 *) ValueBuffer, 0, 0, "%08X", Status);
390 }
391 break;
392
393 case '%':
394 default:
395 //
396 // if the type is '%' or unknown, then print it to the screen
397 //
398 ArgumentString = (CHAR8 *)&FormatCharacter;
399 Flags |= ARGUMENT_UNICODE;
400 break;
401 }
402 break;
403 case '\n':
404 ArgumentString = "\r\n";
405 break;
406 default:
407 ArgumentString = (CHAR8 *)&FormatCharacter;
408 Flags |= ARGUMENT_UNICODE;
409 break;
410 }
411
412 //
413 // Retrieve the ArgumentString attriubutes
414 //
415 if ((Flags & ARGUMENT_UNICODE) != 0) {
416 ArgumentMask = 0xffff;
417 BytesPerArgumentCharacter = 2;
418 } else {
419 ArgumentMask = 0xff;
420 BytesPerArgumentCharacter = 1;
421 }
422 if ((Flags & ARGUMENT_REVERSED) != 0) {
423 BytesPerArgumentCharacter = -BytesPerArgumentCharacter;
424 } else {
425 //
426 // Compute the number of characters in ArgumentString and store it in Count
427 // ArgumentString is either null-terminated, or it contains Precision characters
428 //
429 for (Count = 0; Count < Precision || ((Flags & PRECISION) == 0); Count++) {
430 ArgumentCharacter = ((ArgumentString[Count * BytesPerArgumentCharacter] & 0xff) | ((ArgumentString[Count * BytesPerArgumentCharacter + 1]) << 8)) & ArgumentMask;
431 if (ArgumentCharacter == 0) {
432 break;
433 }
434 }
435 }
436
437 //
438 // Limit the length of the string to append to the remaining characters in the output buffer
439 //
440 if (Count > BufferSize) {
441 Count = BufferSize;
442 }
443 if (Precision < Count) {
444 Precision = Count;
445 }
446
447 //
448 // Pad before the string
449 //
450 if ((Flags & (PAD_TO_WIDTH | LEFT_JUSTIFY)) == (PAD_TO_WIDTH)) {
451 Buffer = BasePrintLibFillBuffer (Buffer, Width - Precision, ' ', BytesPerOutputCharacter);
452 }
453
454 if (ZeroPad) {
455 if (Prefix != 0) {
456 Buffer = BasePrintLibFillBuffer (Buffer, 1, Prefix, BytesPerOutputCharacter);
457 }
458 Buffer = BasePrintLibFillBuffer (Buffer, Precision - Count, '0', BytesPerOutputCharacter);
459 } else {
460 Buffer = BasePrintLibFillBuffer (Buffer, Precision - Count, ' ', BytesPerOutputCharacter);
461 if (Prefix != 0) {
462 Buffer = BasePrintLibFillBuffer (Buffer, 1, Prefix, BytesPerOutputCharacter);
463 }
464 }
465
466 //
467 // Output the Prefix character if it is present
468 //
469 Index = 0;
470 if (Prefix) {
471 Index++;
472 }
473
474 //
475 // Copy the string into the output buffer performing the required type conversions
476 //
477 while (Index < Count) {
478 ArgumentCharacter = ((*ArgumentString & 0xff) | (*(ArgumentString + 1) << 8)) & ArgumentMask;
479
480 Buffer = BasePrintLibFillBuffer (Buffer, 1, ArgumentCharacter, BytesPerOutputCharacter);
481 ArgumentString += BytesPerArgumentCharacter;
482 Index++;
483 if (Comma) {
484 Digits++;
485 if (Digits == 3) {
486 Digits = 0;
487 Index++;
488 if (Index < Count) {
489 Buffer = BasePrintLibFillBuffer (Buffer, 1, ',', BytesPerOutputCharacter);
490 }
491 }
492 }
493 }
494
495 //
496 // Pad after the string
497 //
498 if ((Flags & (PAD_TO_WIDTH | LEFT_JUSTIFY)) == (PAD_TO_WIDTH | LEFT_JUSTIFY)) {
499 Buffer = BasePrintLibFillBuffer (Buffer, Width - Precision, ' ', BytesPerOutputCharacter);
500 }
501
502 //
503 // Reduce the number of characters
504 //
505 BufferSize -= Count;
506
507 //
508 // Get the next character from the format string
509 //
510 Format += BytesPerFormatCharacter;
511
512 //
513 // Get the next character from the format string
514 //
515 FormatCharacter = (*Format | (*(Format + 1) << 8)) & FormatMask;
516 }
517
518 //
519 // Null terminate the Unicode or ASCII string
520 //
521 Buffer = BasePrintLibFillBuffer (Buffer, 1, 0, BytesPerOutputCharacter);
522
523 return ((Buffer - OriginalBuffer) / BytesPerOutputCharacter);
524 }
525
526 UINTN
527 BasePrintLibSPrint (
528 OUT CHAR8 *StartOfBuffer,
529 IN UINTN BufferSize,
530 IN UINTN Flags,
531 IN CONST CHAR8 *FormatString,
532 ...
533 )
534 {
535 VA_LIST Marker;
536
537 VA_START (Marker, FormatString);
538 return BasePrintLibVSPrint (StartOfBuffer, BufferSize, Flags, FormatString, Marker);
539 }
540
541 UINTN
542 EFIAPI
543 UnicodeVSPrint (
544 OUT CHAR16 *StartOfBuffer,
545 IN UINTN BufferSize,
546 IN CONST CHAR16 *FormatString,
547 IN VA_LIST Marker
548 )
549 {
550 return BasePrintLibVSPrint ((CHAR8 *)StartOfBuffer, BufferSize >> 1, FORMAT_UNICODE | OUTPUT_UNICODE, (CHAR8 *)FormatString, Marker);
551 }
552
553 UINTN
554 EFIAPI
555 UnicodeSPrint (
556 OUT CHAR16 *StartOfBuffer,
557 IN UINTN BufferSize,
558 IN CONST CHAR16 *FormatString,
559 ...
560 )
561 {
562 VA_LIST Marker;
563
564 VA_START (Marker, FormatString);
565 return UnicodeVSPrint (StartOfBuffer, BufferSize, FormatString, Marker);
566 }
567
568 UINTN
569 EFIAPI
570 UnicodeVSPrintAsciiFormat (
571 OUT CHAR16 *StartOfBuffer,
572 IN UINTN BufferSize,
573 IN CONST CHAR8 *FormatString,
574 IN VA_LIST Marker
575 )
576 {
577 return BasePrintLibVSPrint ((CHAR8 *)StartOfBuffer, BufferSize >> 1, OUTPUT_UNICODE,FormatString, Marker);
578 }
579
580 UINTN
581 EFIAPI
582 UnicodeSPrintAsciiFormat (
583 OUT CHAR16 *StartOfBuffer,
584 IN UINTN BufferSize,
585 IN CONST CHAR8 *FormatString,
586 ...
587 )
588 {
589 VA_LIST Marker;
590
591 VA_START (Marker, FormatString);
592 return UnicodeVSPrintAsciiFormat (StartOfBuffer, BufferSize >> 1, FormatString, Marker);
593 }
594
595 UINTN
596 EFIAPI
597 AsciiVSPrint (
598 OUT CHAR8 *StartOfBuffer,
599 IN UINTN BufferSize,
600 IN CONST CHAR8 *FormatString,
601 IN VA_LIST Marker
602 )
603 {
604 return BasePrintLibVSPrint (StartOfBuffer, BufferSize, 0, FormatString, Marker);
605 }
606
607 UINTN
608 EFIAPI
609 AsciiSPrint (
610 OUT CHAR8 *StartOfBuffer,
611 IN UINTN BufferSize,
612 IN CONST CHAR8 *FormatString,
613 ...
614 )
615 {
616 VA_LIST Marker;
617
618 VA_START (Marker, FormatString);
619 return AsciiVSPrint (StartOfBuffer, BufferSize, FormatString, Marker);
620 }
621
622 UINTN
623 EFIAPI
624 AsciiVSPrintUnicodeFormat (
625 OUT CHAR8 *StartOfBuffer,
626 IN UINTN BufferSize,
627 IN CONST CHAR16 *FormatString,
628 IN VA_LIST Marker
629 )
630 {
631 return BasePrintLibVSPrint (StartOfBuffer, BufferSize, FORMAT_UNICODE, (CHAR8 *)FormatString, Marker);
632 }
633
634 UINTN
635 EFIAPI
636 AsciiSPrintUnicodeFormat (
637 OUT CHAR8 *StartOfBuffer,
638 IN UINTN BufferSize,
639 IN CONST CHAR16 *FormatString,
640 ...
641 )
642 {
643 VA_LIST Marker;
644
645 VA_START (Marker, FormatString);
646 return AsciiVSPrintUnicodeFormat (StartOfBuffer, BufferSize, FormatString, Marker);
647 }
648
649 UINTN
650 EFIAPI
651 UnicodeValueToString (
652 IN OUT CHAR16 *Buffer,
653 IN UINTN Flags,
654 IN INT64 Value,
655 IN UINTN Width
656 )
657 {
658 return BasePrintLibConvertValueToString ((CHAR8 *)Buffer, Flags, Value, Width, 2);
659 }
660
661 UINTN
662 EFIAPI
663 AsciiValueToString (
664 IN OUT CHAR8 *Buffer,
665 IN UINTN Flags,
666 IN INT64 Value,
667 IN UINTN Width
668 )
669 {
670 return BasePrintLibConvertValueToString ((CHAR8 *)Buffer, Flags, Value, Width, 1);
671 }