ffb5e6ad24d1edf424a8cdcfc0e58430e747e2ed
[dragonfly.git] / sys / contrib / dev / acpica / source / components / utilities / utprint.c
1 /******************************************************************************
2  *
3  * Module Name: utprint - Formatted printing routines
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2015, 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 /* Module globals */
92
93 static const char           AcpiGbl_LowerHexDigits[] = "0123456789abcdef";
94 static const char           AcpiGbl_UpperHexDigits[] = "0123456789ABCDEF";
95
96
97 /*******************************************************************************
98  *
99  * FUNCTION:    AcpiUtBoundStringLength
100  *
101  * PARAMETERS:  String              - String with boundary
102  *              Count               - Boundary of the string
103  *
104  * RETURN:      Length of the string. Less than or equal to Count.
105  *
106  * DESCRIPTION: Calculate the length of a string with boundary.
107  *
108  ******************************************************************************/
109
110 static ACPI_SIZE
111 AcpiUtBoundStringLength (
112     const char              *String,
113     ACPI_SIZE               Count)
114 {
115     UINT32                  Length = 0;
116
117
118     while (*String && Count)
119     {
120         Length++;
121         String++;
122         Count--;
123     }
124
125     return (Length);
126 }
127
128
129 /*******************************************************************************
130  *
131  * FUNCTION:    AcpiUtBoundStringOutput
132  *
133  * PARAMETERS:  String              - String with boundary
134  *              End                 - Boundary of the string
135  *              c                   - Character to be output to the string
136  *
137  * RETURN:      Updated position for next valid character
138  *
139  * DESCRIPTION: Output a character into a string with boundary check.
140  *
141  ******************************************************************************/
142
143 static char *
144 AcpiUtBoundStringOutput (
145     char                    *String,
146     const char              *End,
147     char                    c)
148 {
149
150     if (String < End)
151     {
152         *String = c;
153     }
154
155     ++String;
156     return (String);
157 }
158
159
160 /*******************************************************************************
161  *
162  * FUNCTION:    AcpiUtPutNumber
163  *
164  * PARAMETERS:  String              - Buffer to hold reverse-ordered string
165  *              Number              - Integer to be converted
166  *              Base                - Base of the integer
167  *              Upper               - Whether or not using upper cased digits
168  *
169  * RETURN:      Updated position for next valid character
170  *
171  * DESCRIPTION: Convert an integer into a string, note that, the string holds a
172  *              reversed ordered number without the trailing zero.
173  *
174  ******************************************************************************/
175
176 static char *
177 AcpiUtPutNumber (
178     char                    *String,
179     UINT64                  Number,
180     UINT8                   Base,
181     BOOLEAN                 Upper)
182 {
183     const char              *Digits;
184     UINT64                  DigitIndex;
185     char                    *Pos;
186
187
188     Pos = String;
189     Digits = Upper ? AcpiGbl_UpperHexDigits : AcpiGbl_LowerHexDigits;
190
191     if (Number == 0)
192     {
193         *(Pos++) = '0';
194     }
195     else
196     {
197         while (Number)
198         {
199             (void) AcpiUtDivide (Number, Base, &Number, &DigitIndex);
200             *(Pos++) = Digits[DigitIndex];
201         }
202     }
203
204     /* *(Pos++) = '0'; */
205     return (Pos);
206 }
207
208
209 /*******************************************************************************
210  *
211  * FUNCTION:    AcpiUtScanNumber
212  *
213  * PARAMETERS:  String              - String buffer
214  *              NumberPtr           - Where the number is returned
215  *
216  * RETURN:      Updated position for next valid character
217  *
218  * DESCRIPTION: Scan a string for a decimal integer.
219  *
220  ******************************************************************************/
221
222 const char *
223 AcpiUtScanNumber (
224     const char              *String,
225     UINT64                  *NumberPtr)
226 {
227     UINT64                  Number = 0;
228
229
230     while (ACPI_IS_DIGIT (*String))
231     {
232         Number *= 10;
233         Number += *(String++) - '0';
234     }
235
236     *NumberPtr = Number;
237     return (String);
238 }
239
240
241 /*******************************************************************************
242  *
243  * FUNCTION:    AcpiUtPrintNumber
244  *
245  * PARAMETERS:  String              - String buffer
246  *              Number              - The number to be converted
247  *
248  * RETURN:      Updated position for next valid character
249  *
250  * DESCRIPTION: Print a decimal integer into a string.
251  *
252  ******************************************************************************/
253
254 const char *
255 AcpiUtPrintNumber (
256     char                    *String,
257     UINT64                  Number)
258 {
259     char                    AsciiString[20];
260     const char              *Pos1;
261     char                    *Pos2;
262
263
264     Pos1 = AcpiUtPutNumber (AsciiString, Number, 10, FALSE);
265     Pos2 = String;
266
267     while (Pos1 != AsciiString)
268     {
269         *(Pos2++) = *(--Pos1);
270     }
271
272     *Pos2 = 0;
273     return (String);
274 }
275
276
277 /*******************************************************************************
278  *
279  * FUNCTION:    AcpiUtFormatNumber
280  *
281  * PARAMETERS:  String              - String buffer with boundary
282  *              End                 - Boundary of the string
283  *              Number              - The number to be converted
284  *              Base                - Base of the integer
285  *              Width               - Field width
286  *              Precision           - Precision of the integer
287  *              Type                - Special printing flags
288  *
289  * RETURN:      Updated position for next valid character
290  *
291  * DESCRIPTION: Print an integer into a string with any base and any precision.
292  *
293  ******************************************************************************/
294
295 static char *
296 AcpiUtFormatNumber (
297     char                    *String,
298     char                    *End,
299     UINT64                  Number,
300     UINT8                   Base,
301     INT32                   Width,
302     INT32                   Precision,
303     UINT8                   Type)
304 {
305     char                    *Pos;
306     char                    Sign;
307     char                    Zero;
308     BOOLEAN                 NeedPrefix;
309     BOOLEAN                 Upper;
310     INT32                   i;
311     char                    ReversedString[66];
312
313
314     /* Parameter validation */
315
316     if (Base < 2 || Base > 16)
317     {
318         return (NULL);
319     }
320
321     if (Type & ACPI_FORMAT_LEFT)
322     {
323         Type &= ~ACPI_FORMAT_ZERO;
324     }
325
326     NeedPrefix = ((Type & ACPI_FORMAT_PREFIX) && Base != 10) ? TRUE : FALSE;
327     Upper = (Type & ACPI_FORMAT_UPPER) ? TRUE : FALSE;
328     Zero = (Type & ACPI_FORMAT_ZERO) ? '0' : ' ';
329
330     /* Calculate size according to sign and prefix */
331
332     Sign = '\0';
333     if (Type & ACPI_FORMAT_SIGN)
334     {
335         if ((INT64) Number < 0)
336         {
337             Sign = '-';
338             Number = - (INT64) Number;
339             Width--;
340         }
341         else if (Type & ACPI_FORMAT_SIGN_PLUS)
342         {
343             Sign = '+';
344             Width--;
345         }
346         else if (Type & ACPI_FORMAT_SIGN_PLUS_SPACE)
347         {
348             Sign = ' ';
349             Width--;
350         }
351     }
352     if (NeedPrefix)
353     {
354         Width--;
355         if (Base == 16)
356         {
357             Width--;
358         }
359     }
360
361     /* Generate full string in reverse order */
362
363     Pos = AcpiUtPutNumber (ReversedString, Number, Base, Upper);
364     i = ACPI_PTR_DIFF (Pos, ReversedString);
365
366     /* Printing 100 using %2d gives "100", not "00" */
367
368     if (i > Precision)
369     {
370         Precision = i;
371     }
372
373     Width -= Precision;
374
375     /* Output the string */
376
377     if (!(Type & (ACPI_FORMAT_ZERO | ACPI_FORMAT_LEFT)))
378     {
379         while (--Width >= 0)
380         {
381             String = AcpiUtBoundStringOutput (String, End, ' ');
382         }
383     }
384     if (Sign)
385     {
386         String = AcpiUtBoundStringOutput (String, End, Sign);
387     }
388     if (NeedPrefix)
389     {
390         String = AcpiUtBoundStringOutput (String, End, '0');
391         if (Base == 16)
392         {
393             String = AcpiUtBoundStringOutput (String, End,
394                         Upper ? 'X' : 'x');
395         }
396     }
397     if (!(Type & ACPI_FORMAT_LEFT))
398     {
399         while (--Width >= 0)
400         {
401             String = AcpiUtBoundStringOutput (String, End, Zero);
402         }
403     }
404
405     while (i <= --Precision)
406     {
407         String = AcpiUtBoundStringOutput (String, End, '0');
408     }
409     while (--i >= 0)
410     {
411         String = AcpiUtBoundStringOutput (String, End,
412                     ReversedString[i]);
413     }
414     while (--Width >= 0)
415     {
416         String = AcpiUtBoundStringOutput (String, End, ' ');
417     }
418
419     return (String);
420 }
421
422
423 /*******************************************************************************
424  *
425  * FUNCTION:    AcpiUtVsnprintf
426  *
427  * PARAMETERS:  String              - String with boundary
428  *              Size                - Boundary of the string
429  *              Format              - Standard printf format
430  *              Args                - Argument list
431  *
432  * RETURN:      Number of bytes actually written.
433  *
434  * DESCRIPTION: Formatted output to a string using argument list pointer.
435  *
436  ******************************************************************************/
437
438 int
439 AcpiUtVsnprintf (
440     char                    *String,
441     ACPI_SIZE               Size,
442     const char              *Format,
443     va_list                 Args)
444 {
445     UINT8                   Base;
446     UINT8                   Type;
447     INT32                   Width;
448     INT32                   Precision;
449     char                    Qualifier;
450     UINT64                  Number;
451     char                    *Pos;
452     char                    *End;
453     char                    c;
454     const char              *s;
455     const void              *p;
456     INT32                   Length;
457     int                     i;
458
459
460     Pos = String;
461     End = String + Size;
462
463     for (; *Format; ++Format)
464     {
465         if (*Format != '%')
466         {
467             Pos = AcpiUtBoundStringOutput (Pos, End, *Format);
468             continue;
469         }
470
471         Type = 0;
472         Base = 10;
473
474         /* Process sign */
475
476         do
477         {
478             ++Format;
479             if (*Format == '#')
480             {
481                 Type |= ACPI_FORMAT_PREFIX;
482             }
483             else if (*Format == '0')
484             {
485                 Type |= ACPI_FORMAT_ZERO;
486             }
487             else if (*Format == '+')
488             {
489                 Type |= ACPI_FORMAT_SIGN_PLUS;
490             }
491             else if (*Format == ' ')
492             {
493                 Type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
494             }
495             else if (*Format == '-')
496             {
497                 Type |= ACPI_FORMAT_LEFT;
498             }
499             else
500             {
501                 break;
502             }
503         } while (1);
504
505         /* Process width */
506
507         Width = -1;
508         if (ACPI_IS_DIGIT (*Format))
509         {
510             Format = AcpiUtScanNumber (Format, &Number);
511             Width = (INT32) Number;
512         }
513         else if (*Format == '*')
514         {
515             ++Format;
516             Width = va_arg (Args, int);
517             if (Width < 0)
518             {
519                 Width = -Width;
520                 Type |= ACPI_FORMAT_LEFT;
521             }
522         }
523
524         /* Process precision */
525
526         Precision = -1;
527         if (*Format == '.')
528         {
529             ++Format;
530             if (ACPI_IS_DIGIT(*Format))
531             {
532                 Format = AcpiUtScanNumber (Format, &Number);
533                 Precision = (INT32) Number;
534             }
535             else if (*Format == '*')
536             {
537                 ++Format;
538                 Precision = va_arg (Args, int);
539             }
540             if (Precision < 0)
541             {
542                 Precision = 0;
543             }
544         }
545
546         /* Process qualifier */
547
548         Qualifier = -1;
549         if (*Format == 'h' || *Format == 'l' || *Format == 'L')
550         {
551             Qualifier = *Format;
552             ++Format;
553
554             if (Qualifier == 'l' && *Format == 'l')
555             {
556                 Qualifier = 'L';
557                 ++Format;
558             }
559         }
560
561         switch (*Format)
562         {
563         case '%':
564
565             Pos = AcpiUtBoundStringOutput (Pos, End, '%');
566             continue;
567
568         case 'c':
569
570             if (!(Type & ACPI_FORMAT_LEFT))
571             {
572                 while (--Width > 0)
573                 {
574                     Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
575                 }
576             }
577
578             c = (char) va_arg (Args, int);
579             Pos = AcpiUtBoundStringOutput (Pos, End, c);
580
581             while (--Width > 0)
582             {
583                 Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
584             }
585             continue;
586
587         case 's':
588
589             s = va_arg (Args, char *);
590             if (!s)
591             {
592                 s = "<NULL>";
593             }
594             Length = AcpiUtBoundStringLength (s, Precision);
595             if (!(Type & ACPI_FORMAT_LEFT))
596             {
597                 while (Length < Width--)
598                 {
599                     Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
600                 }
601             }
602             for (i = 0; i < Length; ++i)
603             {
604                 Pos = AcpiUtBoundStringOutput (Pos, End, *s);
605                 ++s;
606             }
607             while (Length < Width--)
608             {
609                 Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
610             }
611             continue;
612
613         case 'o':
614
615             Base = 8;
616             break;
617
618         case 'X':
619
620             Type |= ACPI_FORMAT_UPPER;
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 (Pos, End,
646                     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 (ACPI_PTR_DIFF (Pos, String));
713 }
714
715
716 /*******************************************************************************
717  *
718  * FUNCTION:    AcpiUtSnprintf
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 AcpiUtSnprintf (
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 = AcpiUtVsnprintf (String, Size, Format, Args);
743     va_end (Args);
744
745     return (Length);
746 }
747
748
749 #ifdef ACPI_APPLICATION
750 /*******************************************************************************
751  *
752  * FUNCTION:    AcpiUtFileVprintf
753  *
754  * PARAMETERS:  File                - File descriptor
755  *              Format              - Standard printf format
756  *              Args                - Argument list
757  *
758  * RETURN:      Number of bytes actually written.
759  *
760  * DESCRIPTION: Formatted output to a file using argument list pointer.
761  *
762  ******************************************************************************/
763
764 int
765 AcpiUtFileVprintf (
766     ACPI_FILE               File,
767     const char              *Format,
768     va_list                 Args)
769 {
770     ACPI_CPU_FLAGS          Flags;
771     int                     Length;
772
773
774     Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock);
775     Length = AcpiUtVsnprintf (AcpiGbl_PrintBuffer,
776                 sizeof (AcpiGbl_PrintBuffer), Format, Args);
777
778     (void) AcpiOsWriteFile (File, AcpiGbl_PrintBuffer, Length, 1);
779     AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags);
780
781     return (Length);
782 }
783
784
785 /*******************************************************************************
786  *
787  * FUNCTION:    AcpiUtFilePrintf
788  *
789  * PARAMETERS:  File                - File descriptor
790  *              Format, ...         - Standard printf format
791  *
792  * RETURN:      Number of bytes actually written.
793  *
794  * DESCRIPTION: Formatted output to a file.
795  *
796  ******************************************************************************/
797
798 int
799 AcpiUtFilePrintf (
800     ACPI_FILE               File,
801     const char              *Format,
802     ...)
803 {
804     va_list                 Args;
805     int                     Length;
806
807
808     va_start (Args, Format);
809     Length = AcpiUtFileVprintf (File, Format, Args);
810     va_end (Args);
811
812     return (Length);
813 }
814 #endif