xref: /netbsd-src/sys/external/bsd/acpica/dist/utilities/utprint.c (revision 2e2322c9c07009df921d11b1268f8506affbb8ba)
1 /******************************************************************************
2  *
3  * Module Name: utprint - Formatted printing routines
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2016, 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         Number *= 10;
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 = 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 = 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 
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 (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