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