1 /******************************************************************************
2  *
3  * Module Name: utprint - Formatted printing routines
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2021, 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
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 *
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 *
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 *
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 *
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 *
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 
417 /*******************************************************************************
418  *
419  * FUNCTION:    vsnprintf
420  *
421  * PARAMETERS:  String              - String with boundary
422  *              Size                - Boundary of the string
423  *              Format              - Standard printf format
424  *              Args                - Argument list
425  *
426  * RETURN:      Number of bytes actually written.
427  *
428  * DESCRIPTION: Formatted output to a string using argument list pointer.
429  *
430  ******************************************************************************/
431 
432 int
433 vsnprintf (
434     char                    *String,
435     ACPI_SIZE               Size,
436     const char              *Format,
437     va_list                 Args)
438 {
439     UINT8                   Base;
440     UINT8                   Type;
441     INT32                   Width;
442     INT32                   Precision;
443     char                    Qualifier;
444     UINT64                  Number;
445     char                    *Pos;
446     char                    *End;
447     char                    c;
448     const char              *s;
449     const void              *p;
450     INT32                   Length;
451     int                     i;
452 
453 
454     Pos = String;
455 
456 
457     if (Size != ACPI_UINT32_MAX) {
458         End = String + Size;
459     } else {
460         End = ACPI_CAST_PTR(char, ACPI_UINT32_MAX);
461     }
462 
463     for (; *Format; ++Format)
464     {
465         if (*Format != '%')
466         {
467             Pos = AcpiUtBoundStringOutput (Pos, End, *Format);
468             continue;
469         }
470 
471         Type = 0;
472         Base = 10;
473 
474         /* Process sign */
475 
476         do
477         {
478             ++Format;
479             if (*Format == '#')
480             {
481                 Type |= ACPI_FORMAT_PREFIX;
482             }
483             else if (*Format == '0')
484             {
485                 Type |= ACPI_FORMAT_ZERO;
486             }
487             else if (*Format == '+')
488             {
489                 Type |= ACPI_FORMAT_SIGN_PLUS;
490             }
491             else if (*Format == ' ')
492             {
493                 Type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
494             }
495             else if (*Format == '-')
496             {
497                 Type |= ACPI_FORMAT_LEFT;
498             }
499             else
500             {
501                 break;
502             }
503 
504         } while (1);
505 
506         /* Process width */
507 
508         Width = -1;
509         if (isdigit ((int) *Format))
510         {
511             Format = AcpiUtScanNumber (Format, &Number);
512             Width = (INT32) Number;
513         }
514         else if (*Format == '*')
515         {
516             ++Format;
517             Width = va_arg (Args, int);
518             if (Width < 0)
519             {
520                 Width = -Width;
521                 Type |= ACPI_FORMAT_LEFT;
522             }
523         }
524 
525         /* Process precision */
526 
527         Precision = -1;
528         if (*Format == '.')
529         {
530             ++Format;
531             if (isdigit ((int) *Format))
532             {
533                 Format = AcpiUtScanNumber (Format, &Number);
534                 Precision = (INT32) Number;
535             }
536             else if (*Format == '*')
537             {
538                 ++Format;
539                 Precision = va_arg (Args, int);
540             }
541 
542             if (Precision < 0)
543             {
544                 Precision = 0;
545             }
546         }
547 
548         /* Process qualifier */
549 
550         Qualifier = -1;
551         if (*Format == 'h' || *Format == 'l' || *Format == 'L')
552         {
553             Qualifier = *Format;
554             ++Format;
555 
556             if (Qualifier == 'l' && *Format == 'l')
557             {
558                 Qualifier = 'L';
559                 ++Format;
560             }
561         }
562 
563         switch (*Format)
564         {
565         case '%':
566 
567             Pos = AcpiUtBoundStringOutput (Pos, End, '%');
568             continue;
569 
570         case 'c':
571 
572             if (!(Type & ACPI_FORMAT_LEFT))
573             {
574                 while (--Width > 0)
575                 {
576                     Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
577                 }
578             }
579 
580             c = (char) va_arg (Args, int);
581             Pos = AcpiUtBoundStringOutput (Pos, End, c);
582 
583             while (--Width > 0)
584             {
585                 Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
586             }
587             continue;
588 
589         case 's':
590 
591             s = va_arg (Args, char *);
592             if (!s)
593             {
594                 s = "<NULL>";
595             }
596             Length = (INT32) AcpiUtBoundStringLength (s, Precision);
597             if (!(Type & ACPI_FORMAT_LEFT))
598             {
599                 while (Length < Width--)
600                 {
601                     Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
602                 }
603             }
604 
605             for (i = 0; i < Length; ++i)
606             {
607                 Pos = AcpiUtBoundStringOutput (Pos, End, *s);
608                 ++s;
609             }
610 
611             while (Length < Width--)
612             {
613                 Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
614             }
615             continue;
616 
617         case 'o':
618 
619             Base = 8;
620             break;
621 
622         case 'X':
623 
624             Type |= ACPI_FORMAT_UPPER;
625             ACPI_FALLTHROUGH;
626 
627         case 'x':
628 
629             Base = 16;
630             break;
631 
632         case 'd':
633         case 'i':
634 
635             Type |= ACPI_FORMAT_SIGN;
636 
637         case 'u':
638 
639             break;
640 
641         case 'p':
642 
643             if (Width == -1)
644             {
645                 Width = 2 * sizeof (void *);
646                 Type |= ACPI_FORMAT_ZERO;
647             }
648 
649             p = va_arg (Args, void *);
650             Pos = AcpiUtFormatNumber (
651                 Pos, End, ACPI_TO_INTEGER (p), 16, Width, Precision, Type);
652             continue;
653 
654         default:
655 
656             Pos = AcpiUtBoundStringOutput (Pos, End, '%');
657             if (*Format)
658             {
659                 Pos = AcpiUtBoundStringOutput (Pos, End, *Format);
660             }
661             else
662             {
663                 --Format;
664             }
665             continue;
666         }
667 
668         if (Qualifier == 'L')
669         {
670             Number = va_arg (Args, UINT64);
671             if (Type & ACPI_FORMAT_SIGN)
672             {
673                 Number = (INT64) Number;
674             }
675         }
676         else if (Qualifier == 'l')
677         {
678             Number = va_arg (Args, unsigned long);
679             if (Type & ACPI_FORMAT_SIGN)
680             {
681                 Number = (INT32) Number;
682             }
683         }
684         else if (Qualifier == 'h')
685         {
686             Number = (UINT16) va_arg (Args, int);
687             if (Type & ACPI_FORMAT_SIGN)
688             {
689                 Number = (INT16) Number;
690             }
691         }
692         else
693         {
694             Number = va_arg (Args, unsigned int);
695             if (Type & ACPI_FORMAT_SIGN)
696             {
697                 Number = (signed int) Number;
698             }
699         }
700 
701         Pos = AcpiUtFormatNumber (Pos, End, Number, Base,
702             Width, Precision, Type);
703     }
704 
705     if (Size > 0)
706     {
707         if (Pos < End)
708         {
709             *Pos = '\0';
710         }
711         else
712         {
713             End[-1] = '\0';
714         }
715     }
716 
717     return ((int) ACPI_PTR_DIFF (Pos, String));
718 }
719 
720 
721 /*******************************************************************************
722  *
723  * FUNCTION:    snprintf
724  *
725  * PARAMETERS:  String              - String with boundary
726  *              Size                - Boundary of the string
727  *              Format, ...         - Standard printf format
728  *
729  * RETURN:      Number of bytes actually written.
730  *
731  * DESCRIPTION: Formatted output to a string.
732  *
733  ******************************************************************************/
734 
735 int
736 snprintf (
737     char                    *String,
738     ACPI_SIZE               Size,
739     const char              *Format,
740     ...)
741 {
742     va_list                 Args;
743     int                     Length;
744 
745 
746     va_start (Args, Format);
747     Length = vsnprintf (String, Size, Format, Args);
748     va_end (Args);
749 
750     return (Length);
751 }
752 
753 
754 /*******************************************************************************
755  *
756  * FUNCTION:    sprintf
757  *
758  * PARAMETERS:  String              - String with boundary
759  *              Format, ...         - Standard printf format
760  *
761  * RETURN:      Number of bytes actually written.
762  *
763  * DESCRIPTION: Formatted output to a string.
764  *
765  ******************************************************************************/
766 
767 int
768 sprintf (
769     char                    *String,
770     const char              *Format,
771     ...)
772 {
773     va_list                 Args;
774     int                     Length;
775 
776 
777     va_start (Args, Format);
778     Length = vsnprintf (String, ACPI_UINT32_MAX, Format, Args);
779     va_end (Args);
780 
781     return (Length);
782 }
783 
784 
785 #ifdef ACPI_APPLICATION
786 /*******************************************************************************
787  *
788  * FUNCTION:    vprintf
789  *
790  * PARAMETERS:  Format              - Standard printf format
791  *              Args                - Argument list
792  *
793  * RETURN:      Number of bytes actually written.
794  *
795  * DESCRIPTION: Formatted output to stdout using argument list pointer.
796  *
797  ******************************************************************************/
798 
799 int
800 vprintf (
801     const char              *Format,
802     va_list                 Args)
803 {
804     ACPI_CPU_FLAGS          Flags;
805     int                     Length;
806 
807 
808     Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock);
809     Length = vsnprintf (AcpiGbl_PrintBuffer,
810                 sizeof (AcpiGbl_PrintBuffer), Format, Args);
811 
812     (void) fwrite (AcpiGbl_PrintBuffer, Length, 1, ACPI_FILE_OUT);
813     AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags);
814 
815     return (Length);
816 }
817 
818 
819 /*******************************************************************************
820  *
821  * FUNCTION:    printf
822  *
823  * PARAMETERS:  Format, ...         - Standard printf format
824  *
825  * RETURN:      Number of bytes actually written.
826  *
827  * DESCRIPTION: Formatted output to stdout.
828  *
829  ******************************************************************************/
830 
831 int
832 printf (
833     const char              *Format,
834     ...)
835 {
836     va_list                 Args;
837     int                     Length;
838 
839 
840     va_start (Args, Format);
841     Length = vprintf (Format, Args);
842     va_end (Args);
843 
844     return (Length);
845 }
846 
847 
848 /*******************************************************************************
849  *
850  * FUNCTION:    vfprintf
851  *
852  * PARAMETERS:  File                - File descriptor
853  *              Format              - Standard printf format
854  *              Args                - Argument list
855  *
856  * RETURN:      Number of bytes actually written.
857  *
858  * DESCRIPTION: Formatted output to a file using argument list pointer.
859  *
860  ******************************************************************************/
861 
862 int
863 vfprintf (
864     FILE                    *File,
865     const char              *Format,
866     va_list                 Args)
867 {
868     ACPI_CPU_FLAGS          Flags;
869     int                     Length;
870 
871 
872     Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock);
873     Length = vsnprintf (AcpiGbl_PrintBuffer,
874         sizeof (AcpiGbl_PrintBuffer), Format, Args);
875 
876     (void) fwrite (AcpiGbl_PrintBuffer, Length, 1, File);
877     AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags);
878 
879     return (Length);
880 }
881 
882 
883 /*******************************************************************************
884  *
885  * FUNCTION:    fprintf
886  *
887  * PARAMETERS:  File                - File descriptor
888  *              Format, ...         - Standard printf format
889  *
890  * RETURN:      Number of bytes actually written.
891  *
892  * DESCRIPTION: Formatted output to a file.
893  *
894  ******************************************************************************/
895 
896 int
897 fprintf (
898     FILE                    *File,
899     const char              *Format,
900     ...)
901 {
902     va_list                 Args;
903     int                     Length;
904 
905 
906     va_start (Args, Format);
907     Length = vfprintf (File, Format, Args);
908     va_end (Args);
909 
910     return (Length);
911 }
912 #endif
913