xref: /dflybsd-src/sys/contrib/dev/acpica/source/components/utilities/utprint.c (revision 73029d086fecb97607aec6269511b65ab8a3131d)
1 /******************************************************************************
2  *
3  * Module Name: utprint - Formatted printing routines
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2014, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #include "acpi.h"
45 #include "accommon.h"
46 
47 #define _COMPONENT          ACPI_UTILITIES
48         ACPI_MODULE_NAME    ("utprint")
49 
50 
51 #define ACPI_FORMAT_SIGN            0x01
52 #define ACPI_FORMAT_SIGN_PLUS       0x02
53 #define ACPI_FORMAT_SIGN_PLUS_SPACE 0x04
54 #define ACPI_FORMAT_ZERO            0x08
55 #define ACPI_FORMAT_LEFT            0x10
56 #define ACPI_FORMAT_UPPER           0x20
57 #define ACPI_FORMAT_PREFIX          0x40
58 
59 
60 /* Local prototypes */
61 
62 static ACPI_SIZE
63 AcpiUtBoundStringLength (
64     const char              *String,
65     ACPI_SIZE               Count);
66 
67 static char *
68 AcpiUtBoundStringOutput (
69     char                    *String,
70     const char              *End,
71     char                    c);
72 
73 static char *
74 AcpiUtFormatNumber (
75     char                    *String,
76     char                    *End,
77     UINT64                  Number,
78     UINT8                   Base,
79     INT32                   Width,
80     INT32                   Precision,
81     UINT8                   Type);
82 
83 static char *
84 AcpiUtPutNumber (
85     char                    *String,
86     UINT64                  Number,
87     UINT8                   Base,
88     BOOLEAN                 Upper);
89 
90 
91 /*******************************************************************************
92  *
93  * FUNCTION:    AcpiUtBoundStringLength
94  *
95  * PARAMETERS:  String              - String with boundary
96  *              Count               - Boundary of the string
97  *
98  * RETURN:      Length of the string.
99  *
100  * DESCRIPTION: Calculate the length of a string with boundary.
101  *
102  ******************************************************************************/
103 
104 static ACPI_SIZE
105 AcpiUtBoundStringLength (
106     const char              *String,
107     ACPI_SIZE               Count)
108 {
109     UINT32                  Length = 0;
110 
111 
112     while (*String && Count)
113     {
114         Length++;
115         String++;
116         Count--;
117     }
118 
119     return (Length);
120 }
121 
122 
123 /*******************************************************************************
124  *
125  * FUNCTION:    AcpiUtBoundStringOutput
126  *
127  * PARAMETERS:  String              - String with boundary
128  *              End                 - Boundary of the string
129  *              c                   - Character to be output to the string
130  *
131  * RETURN:      Updated position for next valid character
132  *
133  * DESCRIPTION: Output a character into a string with boundary check.
134  *
135  ******************************************************************************/
136 
137 static char *
138 AcpiUtBoundStringOutput (
139     char                    *String,
140     const char              *End,
141     char                    c)
142 {
143 
144     if (String < End)
145     {
146         *String = c;
147     }
148     ++String;
149 
150     return (String);
151 }
152 
153 
154 /*******************************************************************************
155  *
156  * FUNCTION:    AcpiUtPutNumber
157  *
158  * PARAMETERS:  String              - Buffer to hold reverse-ordered string
159  *              Number              - Integer to be converted
160  *              Base                - Base of the integer
161  *              Upper               - Whether or not using upper cased digits
162  *
163  * RETURN:      Updated position for next valid character
164  *
165  * DESCRIPTION: Convert an integer into a string, note that, the string holds a
166  *              reversed ordered number without the trailing zero.
167  *
168  ******************************************************************************/
169 
170 static char *
171 AcpiUtPutNumber (
172     char                    *String,
173     UINT64                  Number,
174     UINT8                   Base,
175     BOOLEAN                 Upper)
176 {
177     const char              LowerDigits[] = "0123456789abcdef";
178     const char              UpperDigits[] = "0123456789ABCDEF";
179     const char              *Digits;
180     UINT64                  DigitIndex;
181     char                    *Pos;
182 
183 
184     Pos = String;
185     Digits = Upper ? UpperDigits : LowerDigits;
186 
187     if (Number == 0)
188     {
189         *(Pos++) = '0';
190     }
191     else
192     {
193         while (Number)
194         {
195             (void) AcpiUtDivide (Number, Base, &Number, &DigitIndex);
196             *(Pos++) = Digits[DigitIndex];
197         }
198     }
199     /* *(Pos++) = '0'; */
200 
201     return (Pos);
202 }
203 
204 
205 /*******************************************************************************
206  *
207  * FUNCTION:    AcpiUtScanNumber
208  *
209  * PARAMETERS:  String              - String buffer
210  *              NumberPtr           - Where the number is returned
211  *
212  * RETURN:      Updated position for next valid character
213  *
214  * DESCRIPTION: Scan a string for a decimal integer.
215  *
216  ******************************************************************************/
217 
218 const char *
219 AcpiUtScanNumber (
220     const char              *String,
221     UINT64                  *NumberPtr)
222 {
223     UINT64                  Number = 0;
224 
225 
226     while (ACPI_IS_DIGIT (*String))
227     {
228         Number *= 10;
229         Number += *(String++) - '0';
230     }
231     *NumberPtr = Number;
232 
233     return (String);
234 }
235 
236 
237 /*******************************************************************************
238  *
239  * FUNCTION:    AcpiUtPrintNumber
240  *
241  * PARAMETERS:  String              - String buffer
242  *              Number              - The number to be converted
243  *
244  * RETURN:      Updated position for next valid character
245  *
246  * DESCRIPTION: Print a decimal integer into a string.
247  *
248  ******************************************************************************/
249 
250 const char *
251 AcpiUtPrintNumber (
252     char                    *String,
253     UINT64                  Number)
254 {
255     char                    AsciiString[20];
256     const char              *Pos1;
257     char                    *Pos2;
258 
259 
260     Pos1 = AcpiUtPutNumber (AsciiString, Number, 10, FALSE);
261     Pos2 = String;
262 
263     while (Pos1 != AsciiString)
264     {
265         *(Pos2++) = *(--Pos1);
266     }
267     *Pos2 = 0;
268 
269     return (String);
270 }
271 
272 
273 /*******************************************************************************
274  *
275  * FUNCTION:    AcpiUtFormatNumber
276  *
277  * PARAMETERS:  String              - String buffer with boundary
278  *              End                 - Boundary of the string
279  *              Number              - The number to be converted
280  *              Base                - Base of the integer
281  *              Width               - Field width
282  *              Precision           - Precision of the integer
283  *              Type                - Special printing flags
284  *
285  * RETURN:      Updated position for next valid character
286  *
287  * DESCRIPTION: Print an integer into a string with any base and any precision.
288  *
289  ******************************************************************************/
290 
291 static char *
292 AcpiUtFormatNumber (
293     char                    *String,
294     char                    *End,
295     UINT64                  Number,
296     UINT8                   Base,
297     INT32                   Width,
298     INT32                   Precision,
299     UINT8                   Type)
300 {
301     char                    Sign;
302     char                    Zero;
303     BOOLEAN                 NeedPrefix;
304     BOOLEAN                 Upper;
305     INT32                   i;
306     char                    ReversedString[66];
307 
308 
309     /* Perform sanity checks */
310 
311     if (Base < 2 || Base > 16)
312     {
313         return NULL;
314     }
315     if (Type & ACPI_FORMAT_LEFT)
316     {
317         Type &= ~ACPI_FORMAT_ZERO;
318     }
319 
320     NeedPrefix = ((Type & ACPI_FORMAT_PREFIX) && Base != 10) ? TRUE : FALSE;
321     Upper = (Type & ACPI_FORMAT_UPPER) ? TRUE : FALSE;
322     Zero = (Type & ACPI_FORMAT_ZERO) ? '0' : ' ';
323 
324     /* Calculate size according to sign and prefix */
325 
326     Sign = '\0';
327     if (Type & ACPI_FORMAT_SIGN)
328     {
329         if ((INT64) Number < 0)
330         {
331             Sign = '-';
332             Number = - (INT64) Number;
333             Width--;
334         }
335         else if (Type & ACPI_FORMAT_SIGN_PLUS)
336         {
337             Sign = '+';
338             Width--;
339         }
340         else if (Type & ACPI_FORMAT_SIGN_PLUS_SPACE)
341         {
342             Sign = ' ';
343             Width--;
344         }
345     }
346     if (NeedPrefix)
347     {
348         Width--;
349         if (Base == 16)
350         {
351             Width--;
352         }
353     }
354 
355     /* Generate full string in reverse order */
356 
357     i = ACPI_PTR_DIFF (
358             AcpiUtPutNumber (ReversedString, Number, Base, Upper),
359 	    ReversedString);
360 
361     /* Printing 100 using %2d gives "100", not "00" */
362 
363     if (i > Precision)
364     {
365         Precision = i;
366     }
367     Width -= Precision;
368 
369     /* Output the string */
370 
371     if (!(Type & (ACPI_FORMAT_ZERO | ACPI_FORMAT_LEFT)))
372     {
373         while (--Width >= 0)
374         {
375             String = AcpiUtBoundStringOutput (String, End, ' ');
376         }
377     }
378     if (Sign)
379     {
380         String = AcpiUtBoundStringOutput (String, End, Sign);
381     }
382     if (NeedPrefix)
383     {
384         String = AcpiUtBoundStringOutput (String, End, '0');
385         if (Base == 16)
386         {
387             String = AcpiUtBoundStringOutput (String, End,
388                         Upper ? 'X' : 'x');
389 	}
390     }
391     if (!(Type & ACPI_FORMAT_LEFT))
392     {
393         while (--Width >= 0)
394         {
395             String = AcpiUtBoundStringOutput (String, End, Zero);
396         }
397     }
398     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 
416 /*******************************************************************************
417  *
418  * FUNCTION:    AcpiUtVsnprintf
419  *
420  * PARAMETERS:  String              - String with boundary
421  *              Size                - Boundary of the string
422  *              Format              - Standard printf format
423  *              Args                - Argument list
424  *
425  * RETURN:      Size of successfully output bytes
426  *
427  * DESCRIPTION: Formatted output to a string using argument list pointer.
428  *
429  ******************************************************************************/
430 
431 int
432 AcpiUtVsnprintf (
433     char                    *String,
434     ACPI_SIZE               Size,
435     const char              *Format,
436     va_list                 Args)
437 {
438     UINT8                   Base = 10;
439     UINT8                   Type = 0;
440     INT32                   Width = -1;
441     INT32                   Precision = -1;
442     char                    Qualifier = 0;
443     UINT64                  Number;
444     char                    *Pos;
445     char                    *End;
446     char                    c;
447     const char              *s;
448     const void              *p;
449     INT32                   Length;
450     int                     i;
451 
452 
453     Pos = String;
454     End = String + Size;
455 
456     for (; *Format ; ++Format)
457     {
458         if (*Format != '%')
459         {
460             Pos = AcpiUtBoundStringOutput (Pos, End, *Format);
461             continue;
462         }
463 
464         /* Process sign */
465 
466         do
467         {
468             ++Format;
469             if (*Format == '#')
470             {
471                 Type |= ACPI_FORMAT_PREFIX;
472             }
473             else if (*Format == '0')
474             {
475                 Type |= ACPI_FORMAT_ZERO;
476             }
477             else if (*Format == '+')
478             {
479                 Type |= ACPI_FORMAT_SIGN_PLUS;
480             }
481             else if (*Format == ' ')
482             {
483                 Type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
484             }
485             else if (*Format == '-')
486             {
487                 Type |= ACPI_FORMAT_LEFT;
488             }
489             else
490             {
491                 break;
492             }
493         } while (1);
494 
495         /* Process width */
496 
497         if (ACPI_IS_DIGIT (*Format))
498         {
499             Format = AcpiUtScanNumber (Format, &Number);
500             Width = (INT32) Number;
501         }
502         else if (*Format == '*')
503         {
504             ++Format;
505             Width = va_arg(Args, int);
506             if (Width < 0)
507             {
508                 Width = -Width;
509                 Type |= ACPI_FORMAT_LEFT;
510             }
511         }
512 
513         /* Process precision */
514 
515         if (*Format == '.')
516         {
517             ++Format;
518             if (ACPI_IS_DIGIT(*Format))
519             {
520                 Format = AcpiUtScanNumber (Format, &Number);
521                 Precision = (INT32) Number;
522             }
523             else if (*Format == '*')
524             {
525                 ++Format;
526                 Precision = va_arg(Args, int);
527             }
528             if (Precision < 0)
529             {
530                 Precision = 0;
531             }
532         }
533 
534         /* Process qualifier */
535 
536         if (*Format == 'h' || *Format == 'l' || *Format == 'L')
537         {
538             Qualifier = *Format;
539             ++Format;
540             if (Qualifier == 'l' && *Format == 'l')
541             {
542                 Qualifier = 'L';
543                 ++Format;
544             }
545         }
546 
547         switch (*Format)
548         {
549         case '%':
550 
551             Pos = AcpiUtBoundStringOutput (Pos, End, '%');
552             continue;
553 
554         case 'c':
555 
556             if (!(Type & ACPI_FORMAT_LEFT))
557             {
558                 while (--Width > 0)
559                 {
560                     Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
561                 }
562             }
563             c = (char) va_arg (Args, int);
564             Pos = AcpiUtBoundStringOutput (Pos, End, c);
565             while (--Width > 0)
566             {
567                 Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
568             }
569             continue;
570 
571         case 's':
572 
573             s = va_arg (Args, char *);
574             if (!s)
575             {
576                 s = "<NULL>";
577             }
578             Length = AcpiUtBoundStringLength (s, Precision);
579             if (!(Type & ACPI_FORMAT_LEFT))
580             {
581                 while (Length < Width--)
582                 {
583                     Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
584                 }
585             }
586             for (i = 0; i < Length; ++i)
587             {
588                 Pos = AcpiUtBoundStringOutput (Pos, End, *s);
589                 ++s;
590             }
591             while (Length < Width--)
592             {
593                 Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
594             }
595             continue;
596 
597         case 'o':
598 
599             Base = 8;
600             break;
601 
602         case 'X':
603 
604             Type |= ACPI_FORMAT_UPPER;
605 
606         case 'x':
607 
608             Base = 16;
609             break;
610 
611         case 'd':
612         case 'i':
613 
614             Type |= ACPI_FORMAT_SIGN;
615 
616         case 'u':
617 
618             break;
619 
620         case 'p':
621 
622             if (Width == -1)
623             {
624                 Width = 2 * sizeof (void *);
625                 Type |= ACPI_FORMAT_ZERO;
626             }
627             p = va_arg (Args, void *);
628             Pos = AcpiUtFormatNumber (Pos, End,
629                     ACPI_TO_INTEGER (p),
630                     16, Width, Precision, Type);
631             continue;
632 
633         default:
634 
635             Pos = AcpiUtBoundStringOutput (Pos, End, '%');
636             if (*Format)
637             {
638                 Pos = AcpiUtBoundStringOutput (Pos, End, *Format);
639             }
640             else
641             {
642                 --Format;
643             }
644             continue;
645         }
646 
647         if (Qualifier == 'L')
648         {
649             Number = va_arg (Args, UINT64);
650             if (Type & ACPI_FORMAT_SIGN)
651             {
652                 Number = (INT64) Number;
653             }
654         }
655         else if (Qualifier == 'l')
656         {
657             Number = va_arg (Args, unsigned long);
658             if (Type & ACPI_FORMAT_SIGN)
659             {
660                 Number = (INT32) Number;
661             }
662         }
663         else if (Qualifier == 'h')
664         {
665             Number = (UINT16) va_arg (Args, int);
666             if (Type & ACPI_FORMAT_SIGN)
667             {
668                 Number = (INT16) Number;
669             }
670         }
671         else
672         {
673             Number = va_arg (Args, unsigned int);
674             if (Type & ACPI_FORMAT_SIGN)
675             {
676                 Number = (signed int) Number;
677             }
678         }
679         Pos = AcpiUtFormatNumber(Pos, End, Number, Base,
680                 Width, Precision, Type);
681     }
682 
683     if (Size > 0)
684     {
685         if (Pos < End)
686         {
687             *Pos = '\0';
688         }
689         else
690         {
691             End[-1] = '\0';
692         }
693     }
694 
695     return (ACPI_PTR_DIFF (Pos, String));
696 }
697 
698 
699 /*******************************************************************************
700  *
701  * FUNCTION:    AcpiUtSnprintf
702  *
703  * PARAMETERS:  String              - String with boundary
704  *              Size                - Boundary of the string
705  *              Format, ...         - Standard printf format
706  *
707  * RETURN:      Size of successfully output bytes
708  *
709  * DESCRIPTION: Formatted output to a string.
710  *
711  ******************************************************************************/
712 
713 int
714 AcpiUtSnprintf (
715     char                    *String,
716     ACPI_SIZE               Size,
717     const char              *Format,
718     ...)
719 {
720     va_list                 Args;
721     int                     Length;
722 
723 
724     va_start (Args, Format);
725     Length = AcpiUtVsnprintf (String, Size, Format, Args);
726     va_end (Args);
727 
728     return (Length);
729 }
730 
731 
732 #ifdef ACPI_APPLICATION
733 /*******************************************************************************
734  *
735  * FUNCTION:    AcpiUtFileVprintf
736  *
737  * PARAMETERS:  File                - File descriptor
738  *              Format              - Standard printf format
739  *              Args                - Argument list
740  *
741  * RETURN:      Size of successfully output bytes
742  *
743  * DESCRIPTION: Formatted output to a file using argument list pointer.
744  *
745  ******************************************************************************/
746 
747 int
748 AcpiUtFileVprintf (
749     ACPI_FILE               File,
750     const char              *Format,
751     va_list                 Args)
752 {
753     ACPI_CPU_FLAGS          Flags;
754     int                     Length;
755 
756 
757     Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock);
758     Length = AcpiUtVsnprintf(AcpiGbl_PrintBuffer,
759                 sizeof (AcpiGbl_PrintBuffer), Format, Args);
760     (void) AcpiOsWriteFile (File, AcpiGbl_PrintBuffer, Length, 1);
761     AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags);
762 
763     return (Length);
764 }
765 
766 
767 /*******************************************************************************
768  *
769  * FUNCTION:    AcpiUtFilePrintf
770  *
771  * PARAMETERS:  File                - File descriptor
772  *              Format, ...         - Standard printf format
773  *
774  * RETURN:      Size of successfully output bytes
775  *
776  * DESCRIPTION: Formatted output to a file.
777  *
778  ******************************************************************************/
779 
780 int
781 AcpiUtFilePrintf (
782     ACPI_FILE               File,
783     const char              *Format,
784     ...)
785 {
786     va_list                 Args;
787     int                     Length;
788 
789 
790     va_start (Args, Format);
791     Length = AcpiUtFileVprintf (File, Format, Args);
792     va_end (Args);
793 
794     return (Length);
795 }
796 #endif
797