utprint.c revision 1.8 1 /******************************************************************************
2 *
3 * Module Name: utprint - Formatted printing routines
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2020, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43 #include "acpi.h"
44 #include "accommon.h"
45
46 #define _COMPONENT ACPI_UTILITIES
47 ACPI_MODULE_NAME ("utprint")
48
49
50 #define ACPI_FORMAT_SIGN 0x01
51 #define ACPI_FORMAT_SIGN_PLUS 0x02
52 #define ACPI_FORMAT_SIGN_PLUS_SPACE 0x04
53 #define ACPI_FORMAT_ZERO 0x08
54 #define ACPI_FORMAT_LEFT 0x10
55 #define ACPI_FORMAT_UPPER 0x20
56 #define ACPI_FORMAT_PREFIX 0x40
57
58
59 /* Local prototypes */
60
61 static ACPI_SIZE
62 AcpiUtBoundStringLength (
63 const char *String,
64 ACPI_SIZE Count);
65
66 static char *
67 AcpiUtBoundStringOutput (
68 char *String,
69 const char *End,
70 char c);
71
72 static char *
73 AcpiUtFormatNumber (
74 char *String,
75 char *End,
76 UINT64 Number,
77 UINT8 Base,
78 INT32 Width,
79 INT32 Precision,
80 UINT8 Type);
81
82 static char *
83 AcpiUtPutNumber (
84 char *String,
85 UINT64 Number,
86 UINT8 Base,
87 BOOLEAN Upper);
88
89
90 /*******************************************************************************
91 *
92 * FUNCTION: AcpiUtBoundStringLength
93 *
94 * PARAMETERS: String - String with boundary
95 * Count - Boundary of the string
96 *
97 * RETURN: Length of the string. Less than or equal to Count.
98 *
99 * DESCRIPTION: Calculate the length of a string with boundary.
100 *
101 ******************************************************************************/
102
103 static ACPI_SIZE
104 AcpiUtBoundStringLength (
105 const char *String,
106 ACPI_SIZE Count)
107 {
108 UINT32 Length = 0;
109
110
111 while (*String && Count)
112 {
113 Length++;
114 String++;
115 Count--;
116 }
117
118 return (Length);
119 }
120
121
122 /*******************************************************************************
123 *
124 * FUNCTION: AcpiUtBoundStringOutput
125 *
126 * PARAMETERS: String - String with boundary
127 * End - Boundary of the string
128 * c - Character to be output to the string
129 *
130 * RETURN: Updated position for next valid character
131 *
132 * DESCRIPTION: Output a character into a string with boundary check.
133 *
134 ******************************************************************************/
135
136 static char *
137 AcpiUtBoundStringOutput (
138 char *String,
139 const char *End,
140 char c)
141 {
142
143 if (String < End)
144 {
145 *String = c;
146 }
147
148 ++String;
149 return (String);
150 }
151
152
153 /*******************************************************************************
154 *
155 * FUNCTION: AcpiUtPutNumber
156 *
157 * PARAMETERS: String - Buffer to hold reverse-ordered string
158 * Number - Integer to be converted
159 * Base - Base of the integer
160 * Upper - Whether or not using upper cased digits
161 *
162 * RETURN: Updated position for next valid character
163 *
164 * DESCRIPTION: Convert an integer into a string, note that, the string holds a
165 * reversed ordered number without the trailing zero.
166 *
167 ******************************************************************************/
168
169 static char *
170 AcpiUtPutNumber (
171 char *String,
172 UINT64 Number,
173 UINT8 Base,
174 BOOLEAN Upper)
175 {
176 const char *Digits;
177 UINT64 DigitIndex;
178 char *Pos;
179
180
181 Pos = String;
182 Digits = Upper ? AcpiGbl_UpperHexDigits : AcpiGbl_LowerHexDigits;
183
184 if (Number == 0)
185 {
186 *(Pos++) = '0';
187 }
188 else
189 {
190 while (Number)
191 {
192 (void) AcpiUtDivide (Number, Base, &Number, &DigitIndex);
193 *(Pos++) = Digits[DigitIndex];
194 }
195 }
196
197 /* *(Pos++) = '0'; */
198 return (Pos);
199 }
200
201
202 /*******************************************************************************
203 *
204 * FUNCTION: AcpiUtScanNumber
205 *
206 * PARAMETERS: String - String buffer
207 * NumberPtr - Where the number is returned
208 *
209 * RETURN: Updated position for next valid character
210 *
211 * DESCRIPTION: Scan a string for a decimal integer.
212 *
213 ******************************************************************************/
214
215 const char *
216 AcpiUtScanNumber (
217 const char *String,
218 UINT64 *NumberPtr)
219 {
220 UINT64 Number = 0;
221
222
223 while (isdigit ((int) *String))
224 {
225 AcpiUtShortMultiply (Number, 10, &Number);
226 Number += *(String++) - '0';
227 }
228
229 *NumberPtr = Number;
230 return (String);
231 }
232
233
234 /*******************************************************************************
235 *
236 * FUNCTION: AcpiUtPrintNumber
237 *
238 * PARAMETERS: String - String buffer
239 * Number - The number to be converted
240 *
241 * RETURN: Updated position for next valid character
242 *
243 * DESCRIPTION: Print a decimal integer into a string.
244 *
245 ******************************************************************************/
246
247 const char *
248 AcpiUtPrintNumber (
249 char *String,
250 UINT64 Number)
251 {
252 char AsciiString[20];
253 const char *Pos1;
254 char *Pos2;
255
256
257 Pos1 = AcpiUtPutNumber (AsciiString, Number, 10, FALSE);
258 Pos2 = String;
259
260 while (Pos1 != AsciiString)
261 {
262 *(Pos2++) = *(--Pos1);
263 }
264
265 *Pos2 = 0;
266 return (String);
267 }
268
269
270 /*******************************************************************************
271 *
272 * FUNCTION: AcpiUtFormatNumber
273 *
274 * PARAMETERS: String - String buffer with boundary
275 * End - Boundary of the string
276 * Number - The number to be converted
277 * Base - Base of the integer
278 * Width - Field width
279 * Precision - Precision of the integer
280 * Type - Special printing flags
281 *
282 * RETURN: Updated position for next valid character
283 *
284 * DESCRIPTION: Print an integer into a string with any base and any precision.
285 *
286 ******************************************************************************/
287
288 static char *
289 AcpiUtFormatNumber (
290 char *String,
291 char *End,
292 UINT64 Number,
293 UINT8 Base,
294 INT32 Width,
295 INT32 Precision,
296 UINT8 Type)
297 {
298 char *Pos;
299 char Sign;
300 char Zero;
301 BOOLEAN NeedPrefix;
302 BOOLEAN Upper;
303 INT32 i;
304 char ReversedString[66];
305
306
307 /* Parameter validation */
308
309 if (Base < 2 || Base > 16)
310 {
311 return (NULL);
312 }
313
314 if (Type & ACPI_FORMAT_LEFT)
315 {
316 Type &= ~ACPI_FORMAT_ZERO;
317 }
318
319 NeedPrefix = ((Type & ACPI_FORMAT_PREFIX) && Base != 10) ? TRUE : FALSE;
320 Upper = (Type & ACPI_FORMAT_UPPER) ? TRUE : FALSE;
321 Zero = (Type & ACPI_FORMAT_ZERO) ? '0' : ' ';
322
323 /* Calculate size according to sign and prefix */
324
325 Sign = '\0';
326 if (Type & ACPI_FORMAT_SIGN)
327 {
328 if ((INT64) Number < 0)
329 {
330 Sign = '-';
331 Number = - (INT64) Number;
332 Width--;
333 }
334 else if (Type & ACPI_FORMAT_SIGN_PLUS)
335 {
336 Sign = '+';
337 Width--;
338 }
339 else if (Type & ACPI_FORMAT_SIGN_PLUS_SPACE)
340 {
341 Sign = ' ';
342 Width--;
343 }
344 }
345 if (NeedPrefix)
346 {
347 Width--;
348 if (Base == 16)
349 {
350 Width--;
351 }
352 }
353
354 /* Generate full string in reverse order */
355
356 Pos = AcpiUtPutNumber (ReversedString, Number, Base, Upper);
357 i = (INT32) ACPI_PTR_DIFF (Pos, ReversedString);
358
359 /* Printing 100 using %2d gives "100", not "00" */
360
361 if (i > Precision)
362 {
363 Precision = i;
364 }
365
366 Width -= Precision;
367
368 /* Output the string */
369
370 if (!(Type & (ACPI_FORMAT_ZERO | ACPI_FORMAT_LEFT)))
371 {
372 while (--Width >= 0)
373 {
374 String = AcpiUtBoundStringOutput (String, End, ' ');
375 }
376 }
377 if (Sign)
378 {
379 String = AcpiUtBoundStringOutput (String, End, Sign);
380 }
381 if (NeedPrefix)
382 {
383 String = AcpiUtBoundStringOutput (String, End, '0');
384 if (Base == 16)
385 {
386 String = AcpiUtBoundStringOutput (
387 String, End, Upper ? 'X' : 'x');
388 }
389 }
390 if (!(Type & ACPI_FORMAT_LEFT))
391 {
392 while (--Width >= 0)
393 {
394 String = AcpiUtBoundStringOutput (String, End, Zero);
395 }
396 }
397
398 while (i <= --Precision)
399 {
400 String = AcpiUtBoundStringOutput (String, End, '0');
401 }
402 while (--i >= 0)
403 {
404 String = AcpiUtBoundStringOutput (String, End,
405 ReversedString[i]);
406 }
407 while (--Width >= 0)
408 {
409 String = AcpiUtBoundStringOutput (String, End, ' ');
410 }
411
412 return (String);
413 }
414
415 #undef sprintf
416 #undef snprintf
417 #undef vsnprintf
418 /*******************************************************************************
419 *
420 * FUNCTION: vsnprintf
421 *
422 * PARAMETERS: String - String with boundary
423 * Size - Boundary of the string
424 * Format - Standard printf format
425 * Args - Argument list
426 *
427 * RETURN: Number of bytes actually written.
428 *
429 * DESCRIPTION: Formatted output to a string using argument list pointer.
430 *
431 ******************************************************************************/
432
433 int
434 vsnprintf (
435 char *String,
436 ACPI_SIZE Size,
437 const char *Format,
438 va_list Args)
439 {
440 UINT8 Base;
441 UINT8 Type;
442 INT32 Width;
443 INT32 Precision;
444 char Qualifier;
445 UINT64 Number;
446 char *Pos;
447 char *End;
448 char c;
449 const char *s;
450 const void *p;
451 INT32 Length;
452 int i;
453
454
455 Pos = String;
456
457
458 if (Size != ACPI_UINT32_MAX) {
459 End = String + Size;
460 } else {
461 End = ACPI_CAST_PTR(char, ACPI_UINT32_MAX);
462 }
463
464 for (; *Format; ++Format)
465 {
466 if (*Format != '%')
467 {
468 Pos = AcpiUtBoundStringOutput (Pos, End, *Format);
469 continue;
470 }
471
472 Type = 0;
473 Base = 10;
474
475 /* Process sign */
476
477 do
478 {
479 ++Format;
480 if (*Format == '#')
481 {
482 Type |= ACPI_FORMAT_PREFIX;
483 }
484 else if (*Format == '0')
485 {
486 Type |= ACPI_FORMAT_ZERO;
487 }
488 else if (*Format == '+')
489 {
490 Type |= ACPI_FORMAT_SIGN_PLUS;
491 }
492 else if (*Format == ' ')
493 {
494 Type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
495 }
496 else if (*Format == '-')
497 {
498 Type |= ACPI_FORMAT_LEFT;
499 }
500 else
501 {
502 break;
503 }
504
505 } while (1);
506
507 /* Process width */
508
509 Width = -1;
510 if (isdigit ((int) *Format))
511 {
512 Format = AcpiUtScanNumber (Format, &Number);
513 Width = (INT32) Number;
514 }
515 else if (*Format == '*')
516 {
517 ++Format;
518 Width = va_arg (Args, int);
519 if (Width < 0)
520 {
521 Width = -Width;
522 Type |= ACPI_FORMAT_LEFT;
523 }
524 }
525
526 /* Process precision */
527
528 Precision = -1;
529 if (*Format == '.')
530 {
531 ++Format;
532 if (isdigit ((int) *Format))
533 {
534 Format = AcpiUtScanNumber (Format, &Number);
535 Precision = (INT32) Number;
536 }
537 else if (*Format == '*')
538 {
539 ++Format;
540 Precision = va_arg (Args, int);
541 }
542
543 if (Precision < 0)
544 {
545 Precision = 0;
546 }
547 }
548
549 /* Process qualifier */
550
551 Qualifier = -1;
552 if (*Format == 'h' || *Format == 'l' || *Format == 'L')
553 {
554 Qualifier = *Format;
555 ++Format;
556
557 if (Qualifier == 'l' && *Format == 'l')
558 {
559 Qualifier = 'L';
560 ++Format;
561 }
562 }
563
564 switch (*Format)
565 {
566 case '%':
567
568 Pos = AcpiUtBoundStringOutput (Pos, End, '%');
569 continue;
570
571 case 'c':
572
573 if (!(Type & ACPI_FORMAT_LEFT))
574 {
575 while (--Width > 0)
576 {
577 Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
578 }
579 }
580
581 c = (char) va_arg (Args, int);
582 Pos = AcpiUtBoundStringOutput (Pos, End, c);
583
584 while (--Width > 0)
585 {
586 Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
587 }
588 continue;
589
590 case 's':
591
592 s = va_arg (Args, char *);
593 if (!s)
594 {
595 s = "<NULL>";
596 }
597 Length = (INT32) AcpiUtBoundStringLength (s, Precision);
598 if (!(Type & ACPI_FORMAT_LEFT))
599 {
600 while (Length < Width--)
601 {
602 Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
603 }
604 }
605
606 for (i = 0; i < Length; ++i)
607 {
608 Pos = AcpiUtBoundStringOutput (Pos, End, *s);
609 ++s;
610 }
611
612 while (Length < Width--)
613 {
614 Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
615 }
616 continue;
617
618 case 'o':
619
620 Base = 8;
621 break;
622
623 case 'X':
624
625 Type |= ACPI_FORMAT_UPPER;
626 /* FALLTHROUGH */
627
628 case 'x':
629
630 Base = 16;
631 break;
632
633 case 'd':
634 case 'i':
635
636 Type |= ACPI_FORMAT_SIGN;
637
638 case 'u':
639
640 break;
641
642 case 'p':
643
644 if (Width == -1)
645 {
646 Width = 2 * sizeof (void *);
647 Type |= ACPI_FORMAT_ZERO;
648 }
649
650 p = va_arg (Args, void *);
651 Pos = AcpiUtFormatNumber (
652 Pos, End, ACPI_TO_INTEGER (p), 16, Width, Precision, Type);
653 continue;
654
655 default:
656
657 Pos = AcpiUtBoundStringOutput (Pos, End, '%');
658 if (*Format)
659 {
660 Pos = AcpiUtBoundStringOutput (Pos, End, *Format);
661 }
662 else
663 {
664 --Format;
665 }
666 continue;
667 }
668
669 if (Qualifier == 'L')
670 {
671 Number = va_arg (Args, UINT64);
672 if (Type & ACPI_FORMAT_SIGN)
673 {
674 Number = (INT64) Number;
675 }
676 }
677 else if (Qualifier == 'l')
678 {
679 Number = va_arg (Args, unsigned long);
680 if (Type & ACPI_FORMAT_SIGN)
681 {
682 Number = (INT32) Number;
683 }
684 }
685 else if (Qualifier == 'h')
686 {
687 Number = (UINT16) va_arg (Args, int);
688 if (Type & ACPI_FORMAT_SIGN)
689 {
690 Number = (INT16) Number;
691 }
692 }
693 else
694 {
695 Number = va_arg (Args, unsigned int);
696 if (Type & ACPI_FORMAT_SIGN)
697 {
698 Number = (signed int) Number;
699 }
700 }
701
702 Pos = AcpiUtFormatNumber (Pos, End, Number, Base,
703 Width, Precision, Type);
704 }
705
706 if (Size > 0)
707 {
708 if (Pos < End)
709 {
710 *Pos = '\0';
711 }
712 else
713 {
714 End[-1] = '\0';
715 }
716 }
717
718 return ((int) ACPI_PTR_DIFF (Pos, String));
719 }
720
721
722 /*******************************************************************************
723 *
724 * FUNCTION: snprintf
725 *
726 * PARAMETERS: String - String with boundary
727 * Size - Boundary of the string
728 * Format, ... - Standard printf format
729 *
730 * RETURN: Number of bytes actually written.
731 *
732 * DESCRIPTION: Formatted output to a string.
733 *
734 ******************************************************************************/
735
736 int
737 snprintf (
738 char *String,
739 ACPI_SIZE Size,
740 const char *Format,
741 ...)
742 {
743 va_list Args;
744 int Length;
745
746
747 va_start (Args, Format);
748 Length = vsnprintf (String, Size, Format, Args);
749 va_end (Args);
750
751 return (Length);
752 }
753
754
755 /*******************************************************************************
756 *
757 * FUNCTION: sprintf
758 *
759 * PARAMETERS: String - String with boundary
760 * Format, ... - Standard printf format
761 *
762 * RETURN: Number of bytes actually written.
763 *
764 * DESCRIPTION: Formatted output to a string.
765 *
766 ******************************************************************************/
767
768 int
769 sprintf (
770 char *String,
771 const char *Format,
772 ...)
773 {
774 va_list Args;
775 int Length;
776
777
778 va_start (Args, Format);
779 Length = vsnprintf (String, ACPI_UINT32_MAX, Format, Args);
780 va_end (Args);
781
782 return (Length);
783 }
784
785
786 #ifdef ACPI_APPLICATION
787 /*******************************************************************************
788 *
789 * FUNCTION: vprintf
790 *
791 * PARAMETERS: Format - Standard printf format
792 * Args - Argument list
793 *
794 * RETURN: Number of bytes actually written.
795 *
796 * DESCRIPTION: Formatted output to stdout using argument list pointer.
797 *
798 ******************************************************************************/
799
800 int
801 vprintf (
802 const char *Format,
803 va_list Args)
804 {
805 ACPI_CPU_FLAGS Flags;
806 int Length;
807
808
809 Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock);
810 Length = vsnprintf (AcpiGbl_PrintBuffer,
811 sizeof (AcpiGbl_PrintBuffer), Format, Args);
812
813 (void) fwrite (AcpiGbl_PrintBuffer, Length, 1, ACPI_FILE_OUT);
814 AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags);
815
816 return (Length);
817 }
818
819
820 /*******************************************************************************
821 *
822 * FUNCTION: printf
823 *
824 * PARAMETERS: Format, ... - Standard printf format
825 *
826 * RETURN: Number of bytes actually written.
827 *
828 * DESCRIPTION: Formatted output to stdout.
829 *
830 ******************************************************************************/
831
832 int
833 printf (
834 const char *Format,
835 ...)
836 {
837 va_list Args;
838 int Length;
839
840
841 va_start (Args, Format);
842 Length = vprintf (Format, Args);
843 va_end (Args);
844
845 return (Length);
846 }
847
848
849 /*******************************************************************************
850 *
851 * FUNCTION: vfprintf
852 *
853 * PARAMETERS: File - File descriptor
854 * Format - Standard printf format
855 * Args - Argument list
856 *
857 * RETURN: Number of bytes actually written.
858 *
859 * DESCRIPTION: Formatted output to a file using argument list pointer.
860 *
861 ******************************************************************************/
862
863 int
864 vfprintf (
865 FILE *File,
866 const char *Format,
867 va_list Args)
868 {
869 ACPI_CPU_FLAGS Flags;
870 int Length;
871
872
873 Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock);
874 Length = vsnprintf (AcpiGbl_PrintBuffer,
875 sizeof (AcpiGbl_PrintBuffer), Format, Args);
876
877 (void) fwrite (AcpiGbl_PrintBuffer, Length, 1, File);
878 AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags);
879
880 return (Length);
881 }
882
883
884 /*******************************************************************************
885 *
886 * FUNCTION: fprintf
887 *
888 * PARAMETERS: File - File descriptor
889 * Format, ... - Standard printf format
890 *
891 * RETURN: Number of bytes actually written.
892 *
893 * DESCRIPTION: Formatted output to a file.
894 *
895 ******************************************************************************/
896
897 int
898 fprintf (
899 FILE *File,
900 const char *Format,
901 ...)
902 {
903 va_list Args;
904 int Length;
905
906
907 va_start (Args, Format);
908 Length = vfprintf (File, Format, Args);
909 va_end (Args);
910
911 return (Length);
912 }
913 #endif
914