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