xref: /netbsd-src/sys/external/bsd/acpica/dist/utilities/utprint.c (revision d90047b5d07facf36e6c01dcc0bded8997ce9cc2)
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