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