xref: /titanic_50/usr/src/cmd/acpi/common/utprint.c (revision 8a790dc67da1bad097488e7ad4a58af32d7ab24d)
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 
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. Less than or equal to Count.
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 
149     ++String;
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              *Digits;
178     UINT64                  DigitIndex;
179     char                    *Pos;
180 
181 
182     Pos = String;
183     Digits = Upper ? AcpiGbl_UpperHexDigits : AcpiGbl_LowerHexDigits;
184 
185     if (Number == 0)
186     {
187         *(Pos++) = '0';
188     }
189     else
190     {
191         while (Number)
192         {
193             (void) AcpiUtDivide (Number, Base, &Number, &DigitIndex);
194             *(Pos++) = Digits[DigitIndex];
195         }
196     }
197 
198     /* *(Pos++) = '0'; */
199     return (Pos);
200 }
201 
202 
203 /*******************************************************************************
204  *
205  * FUNCTION:    AcpiUtScanNumber
206  *
207  * PARAMETERS:  String              - String buffer
208  *              NumberPtr           - Where the number is returned
209  *
210  * RETURN:      Updated position for next valid character
211  *
212  * DESCRIPTION: Scan a string for a decimal integer.
213  *
214  ******************************************************************************/
215 
216 const char *
217 AcpiUtScanNumber (
218     const char              *String,
219     UINT64                  *NumberPtr)
220 {
221     UINT64                  Number = 0;
222 
223 
224     while (isdigit ((int) *String))
225     {
226         Number *= 10;
227         Number += *(String++) - '0';
228     }
229 
230     *NumberPtr = Number;
231     return (String);
232 }
233 
234 
235 /*******************************************************************************
236  *
237  * FUNCTION:    AcpiUtPrintNumber
238  *
239  * PARAMETERS:  String              - String buffer
240  *              Number              - The number to be converted
241  *
242  * RETURN:      Updated position for next valid character
243  *
244  * DESCRIPTION: Print a decimal integer into a string.
245  *
246  ******************************************************************************/
247 
248 const char *
249 AcpiUtPrintNumber (
250     char                    *String,
251     UINT64                  Number)
252 {
253     char                    AsciiString[20];
254     const char              *Pos1;
255     char                    *Pos2;
256 
257 
258     Pos1 = AcpiUtPutNumber (AsciiString, Number, 10, FALSE);
259     Pos2 = String;
260 
261     while (Pos1 != AsciiString)
262     {
263         *(Pos2++) = *(--Pos1);
264     }
265 
266     *Pos2 = 0;
267     return (String);
268 }
269 
270 
271 /*******************************************************************************
272  *
273  * FUNCTION:    AcpiUtFormatNumber
274  *
275  * PARAMETERS:  String              - String buffer with boundary
276  *              End                 - Boundary of the string
277  *              Number              - The number to be converted
278  *              Base                - Base of the integer
279  *              Width               - Field width
280  *              Precision           - Precision of the integer
281  *              Type                - Special printing flags
282  *
283  * RETURN:      Updated position for next valid character
284  *
285  * DESCRIPTION: Print an integer into a string with any base and any precision.
286  *
287  ******************************************************************************/
288 
289 static char *
290 AcpiUtFormatNumber (
291     char                    *String,
292     char                    *End,
293     UINT64                  Number,
294     UINT8                   Base,
295     INT32                   Width,
296     INT32                   Precision,
297     UINT8                   Type)
298 {
299     char                    *Pos;
300     char                    Sign;
301     char                    Zero;
302     BOOLEAN                 NeedPrefix;
303     BOOLEAN                 Upper;
304     INT32                   i;
305     char                    ReversedString[66];
306 
307 
308     /* Parameter validation */
309 
310     if (Base < 2 || Base > 16)
311     {
312         return (NULL);
313     }
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     Pos = AcpiUtPutNumber (ReversedString, Number, Base, Upper);
358     i = ACPI_PTR_DIFF (Pos, ReversedString);
359 
360     /* Printing 100 using %2d gives "100", not "00" */
361 
362     if (i > Precision)
363     {
364         Precision = i;
365     }
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 (
388                 String, End, 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 
399     while (i <= --Precision)
400     {
401         String = AcpiUtBoundStringOutput (String, End, '0');
402     }
403     while (--i >= 0)
404     {
405         String = AcpiUtBoundStringOutput (String, End,
406                     ReversedString[i]);
407     }
408     while (--Width >= 0)
409     {
410         String = AcpiUtBoundStringOutput (String, End, ' ');
411     }
412 
413     return (String);
414 }
415 
416 
417 /*******************************************************************************
418  *
419  * FUNCTION:    AcpiUtVsnprintf
420  *
421  * PARAMETERS:  String              - String with boundary
422  *              Size                - Boundary of the string
423  *              Format              - Standard printf format
424  *              Args                - Argument list
425  *
426  * RETURN:      Number of bytes actually written.
427  *
428  * DESCRIPTION: Formatted output to a string using argument list pointer.
429  *
430  ******************************************************************************/
431 
432 int
433 AcpiUtVsnprintf (
434     char                    *String,
435     ACPI_SIZE               Size,
436     const char              *Format,
437     va_list                 Args)
438 {
439     UINT8                   Base;
440     UINT8                   Type;
441     INT32                   Width;
442     INT32                   Precision;
443     char                    Qualifier;
444     UINT64                  Number;
445     char                    *Pos;
446     char                    *End;
447     char                    c;
448     const char              *s;
449     const void              *p;
450     INT32                   Length;
451     int                     i;
452 
453 
454     Pos = String;
455     End = String + Size;
456 
457     for (; *Format; ++Format)
458     {
459         if (*Format != '%')
460         {
461             Pos = AcpiUtBoundStringOutput (Pos, End, *Format);
462             continue;
463         }
464 
465         Type = 0;
466         Base = 10;
467 
468         /* Process sign */
469 
470         do
471         {
472             ++Format;
473             if (*Format == '#')
474             {
475                 Type |= ACPI_FORMAT_PREFIX;
476             }
477             else if (*Format == '0')
478             {
479                 Type |= ACPI_FORMAT_ZERO;
480             }
481             else if (*Format == '+')
482             {
483                 Type |= ACPI_FORMAT_SIGN_PLUS;
484             }
485             else if (*Format == ' ')
486             {
487                 Type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
488             }
489             else if (*Format == '-')
490             {
491                 Type |= ACPI_FORMAT_LEFT;
492             }
493             else
494             {
495                 break;
496             }
497 
498         } while (1);
499 
500         /* Process width */
501 
502         Width = -1;
503         if (isdigit ((int) *Format))
504         {
505             Format = AcpiUtScanNumber (Format, &Number);
506             Width = (INT32) Number;
507         }
508         else if (*Format == '*')
509         {
510             ++Format;
511             Width = va_arg (Args, int);
512             if (Width < 0)
513             {
514                 Width = -Width;
515                 Type |= ACPI_FORMAT_LEFT;
516             }
517         }
518 
519         /* Process precision */
520 
521         Precision = -1;
522         if (*Format == '.')
523         {
524             ++Format;
525             if (isdigit ((int) *Format))
526             {
527                 Format = AcpiUtScanNumber (Format, &Number);
528                 Precision = (INT32) Number;
529             }
530             else if (*Format == '*')
531             {
532                 ++Format;
533                 Precision = va_arg (Args, int);
534             }
535 
536             if (Precision < 0)
537             {
538                 Precision = 0;
539             }
540         }
541 
542         /* Process qualifier */
543 
544         Qualifier = -1;
545         if (*Format == 'h' || *Format == 'l' || *Format == 'L')
546         {
547             Qualifier = *Format;
548             ++Format;
549 
550             if (Qualifier == 'l' && *Format == 'l')
551             {
552                 Qualifier = 'L';
553                 ++Format;
554             }
555         }
556 
557         switch (*Format)
558         {
559         case '%':
560 
561             Pos = AcpiUtBoundStringOutput (Pos, End, '%');
562             continue;
563 
564         case 'c':
565 
566             if (!(Type & ACPI_FORMAT_LEFT))
567             {
568                 while (--Width > 0)
569                 {
570                     Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
571                 }
572             }
573 
574             c = (char) va_arg (Args, int);
575             Pos = AcpiUtBoundStringOutput (Pos, End, c);
576 
577             while (--Width > 0)
578             {
579                 Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
580             }
581             continue;
582 
583         case 's':
584 
585             s = va_arg (Args, char *);
586             if (!s)
587             {
588                 s = "<NULL>";
589             }
590             Length = AcpiUtBoundStringLength (s, Precision);
591             if (!(Type & ACPI_FORMAT_LEFT))
592             {
593                 while (Length < Width--)
594                 {
595                     Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
596                 }
597             }
598 
599             for (i = 0; i < Length; ++i)
600             {
601                 Pos = AcpiUtBoundStringOutput (Pos, End, *s);
602                 ++s;
603             }
604 
605             while (Length < Width--)
606             {
607                 Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
608             }
609             continue;
610 
611         case 'o':
612 
613             Base = 8;
614             break;
615 
616         case 'X':
617 
618             Type |= ACPI_FORMAT_UPPER;
619 
620         case 'x':
621 
622             Base = 16;
623             break;
624 
625         case 'd':
626         case 'i':
627 
628             Type |= ACPI_FORMAT_SIGN;
629 
630         case 'u':
631 
632             break;
633 
634         case 'p':
635 
636             if (Width == -1)
637             {
638                 Width = 2 * sizeof (void *);
639                 Type |= ACPI_FORMAT_ZERO;
640             }
641 
642             p = va_arg (Args, void *);
643             Pos = AcpiUtFormatNumber (
644                 Pos, End, ACPI_TO_INTEGER (p), 16, Width, Precision, Type);
645             continue;
646 
647         default:
648 
649             Pos = AcpiUtBoundStringOutput (Pos, End, '%');
650             if (*Format)
651             {
652                 Pos = AcpiUtBoundStringOutput (Pos, End, *Format);
653             }
654             else
655             {
656                 --Format;
657             }
658             continue;
659         }
660 
661         if (Qualifier == 'L')
662         {
663             Number = va_arg (Args, UINT64);
664             if (Type & ACPI_FORMAT_SIGN)
665             {
666                 Number = (INT64) Number;
667             }
668         }
669         else if (Qualifier == 'l')
670         {
671             Number = va_arg (Args, unsigned long);
672             if (Type & ACPI_FORMAT_SIGN)
673             {
674                 Number = (INT32) Number;
675             }
676         }
677         else if (Qualifier == 'h')
678         {
679             Number = (UINT16) va_arg (Args, int);
680             if (Type & ACPI_FORMAT_SIGN)
681             {
682                 Number = (INT16) Number;
683             }
684         }
685         else
686         {
687             Number = va_arg (Args, unsigned int);
688             if (Type & ACPI_FORMAT_SIGN)
689             {
690                 Number = (signed int) Number;
691             }
692         }
693 
694         Pos = AcpiUtFormatNumber (Pos, End, Number, Base,
695             Width, Precision, Type);
696     }
697 
698     if (Size > 0)
699     {
700         if (Pos < End)
701         {
702             *Pos = '\0';
703         }
704         else
705         {
706             End[-1] = '\0';
707         }
708     }
709 
710     return (ACPI_PTR_DIFF (Pos, String));
711 }
712 
713 
714 /*******************************************************************************
715  *
716  * FUNCTION:    AcpiUtSnprintf
717  *
718  * PARAMETERS:  String              - String with boundary
719  *              Size                - Boundary of the string
720  *              Format, ...         - Standard printf format
721  *
722  * RETURN:      Number of bytes actually written.
723  *
724  * DESCRIPTION: Formatted output to a string.
725  *
726  ******************************************************************************/
727 
728 int
729 AcpiUtSnprintf (
730     char                    *String,
731     ACPI_SIZE               Size,
732     const char              *Format,
733     ...)
734 {
735     va_list                 Args;
736     int                     Length;
737 
738 
739     va_start (Args, Format);
740     Length = AcpiUtVsnprintf (String, Size, Format, Args);
741     va_end (Args);
742 
743     return (Length);
744 }
745 
746 
747 #ifdef ACPI_APPLICATION
748 /*******************************************************************************
749  *
750  * FUNCTION:    AcpiUtFileVprintf
751  *
752  * PARAMETERS:  File                - File descriptor
753  *              Format              - Standard printf format
754  *              Args                - Argument list
755  *
756  * RETURN:      Number of bytes actually written.
757  *
758  * DESCRIPTION: Formatted output to a file using argument list pointer.
759  *
760  ******************************************************************************/
761 
762 int
763 AcpiUtFileVprintf (
764     ACPI_FILE               File,
765     const char              *Format,
766     va_list                 Args)
767 {
768     ACPI_CPU_FLAGS          Flags;
769     int                     Length;
770 
771 
772     Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock);
773     Length = AcpiUtVsnprintf (AcpiGbl_PrintBuffer,
774         sizeof (AcpiGbl_PrintBuffer), Format, Args);
775 
776     (void) AcpiOsWriteFile (File, AcpiGbl_PrintBuffer, Length, 1);
777     AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags);
778 
779     return (Length);
780 }
781 
782 
783 /*******************************************************************************
784  *
785  * FUNCTION:    AcpiUtFilePrintf
786  *
787  * PARAMETERS:  File                - File descriptor
788  *              Format, ...         - Standard printf format
789  *
790  * RETURN:      Number of bytes actually written.
791  *
792  * DESCRIPTION: Formatted output to a file.
793  *
794  ******************************************************************************/
795 
796 int
797 AcpiUtFilePrintf (
798     ACPI_FILE               File,
799     const char              *Format,
800     ...)
801 {
802     va_list                 Args;
803     int                     Length;
804 
805 
806     va_start (Args, Format);
807     Length = AcpiUtFileVprintf (File, Format, Args);
808     va_end (Args);
809 
810     return (Length);
811 }
812 #endif
813