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 /* 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 (isdigit ((int) *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 (
394                 String, End, 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 
504         } while (1);
505 
506         /* Process width */
507 
508         Width = -1;
509         if (isdigit ((int) *Format))
510         {
511             Format = AcpiUtScanNumber (Format, &Number);
512             Width = (INT32) Number;
513         }
514         else if (*Format == '*')
515         {
516             ++Format;
517             Width = va_arg (Args, int);
518             if (Width < 0)
519             {
520                 Width = -Width;
521                 Type |= ACPI_FORMAT_LEFT;
522             }
523         }
524 
525         /* Process precision */
526 
527         Precision = -1;
528         if (*Format == '.')
529         {
530             ++Format;
531             if (isdigit ((int) *Format))
532             {
533                 Format = AcpiUtScanNumber (Format, &Number);
534                 Precision = (INT32) Number;
535             }
536             else if (*Format == '*')
537             {
538                 ++Format;
539                 Precision = va_arg (Args, int);
540             }
541 
542             if (Precision < 0)
543             {
544                 Precision = 0;
545             }
546         }
547 
548         /* Process qualifier */
549 
550         Qualifier = -1;
551         if (*Format == 'h' || *Format == 'l' || *Format == 'L')
552         {
553             Qualifier = *Format;
554             ++Format;
555 
556             if (Qualifier == 'l' && *Format == 'l')
557             {
558                 Qualifier = 'L';
559                 ++Format;
560             }
561         }
562 
563         switch (*Format)
564         {
565         case '%':
566 
567             Pos = AcpiUtBoundStringOutput (Pos, End, '%');
568             continue;
569 
570         case 'c':
571 
572             if (!(Type & ACPI_FORMAT_LEFT))
573             {
574                 while (--Width > 0)
575                 {
576                     Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
577                 }
578             }
579 
580             c = (char) va_arg (Args, int);
581             Pos = AcpiUtBoundStringOutput (Pos, End, c);
582 
583             while (--Width > 0)
584             {
585                 Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
586             }
587             continue;
588 
589         case 's':
590 
591             s = va_arg (Args, char *);
592             if (!s)
593             {
594                 s = "<NULL>";
595             }
596             Length = AcpiUtBoundStringLength (s, Precision);
597             if (!(Type & ACPI_FORMAT_LEFT))
598             {
599                 while (Length < Width--)
600                 {
601                     Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
602                 }
603             }
604 
605             for (i = 0; i < Length; ++i)
606             {
607                 Pos = AcpiUtBoundStringOutput (Pos, End, *s);
608                 ++s;
609             }
610 
611             while (Length < Width--)
612             {
613                 Pos = AcpiUtBoundStringOutput (Pos, End, ' ');
614             }
615             continue;
616 
617         case 'o':
618 
619             Base = 8;
620             break;
621 
622         case 'X':
623 
624             Type |= ACPI_FORMAT_UPPER;
625 
626         case 'x':
627 
628             Base = 16;
629             break;
630 
631         case 'd':
632         case 'i':
633 
634             Type |= ACPI_FORMAT_SIGN;
635 
636         case 'u':
637 
638             break;
639 
640         case 'p':
641 
642             if (Width == -1)
643             {
644                 Width = 2 * sizeof (void *);
645                 Type |= ACPI_FORMAT_ZERO;
646             }
647 
648             p = va_arg (Args, void *);
649             Pos = AcpiUtFormatNumber (
650                 Pos, End, ACPI_TO_INTEGER (p), 16, Width, Precision, Type);
651             continue;
652 
653         default:
654 
655             Pos = AcpiUtBoundStringOutput (Pos, End, '%');
656             if (*Format)
657             {
658                 Pos = AcpiUtBoundStringOutput (Pos, End, *Format);
659             }
660             else
661             {
662                 --Format;
663             }
664             continue;
665         }
666 
667         if (Qualifier == 'L')
668         {
669             Number = va_arg (Args, UINT64);
670             if (Type & ACPI_FORMAT_SIGN)
671             {
672                 Number = (INT64) Number;
673             }
674         }
675         else if (Qualifier == 'l')
676         {
677             Number = va_arg (Args, unsigned long);
678             if (Type & ACPI_FORMAT_SIGN)
679             {
680                 Number = (INT32) Number;
681             }
682         }
683         else if (Qualifier == 'h')
684         {
685             Number = (UINT16) va_arg (Args, int);
686             if (Type & ACPI_FORMAT_SIGN)
687             {
688                 Number = (INT16) Number;
689             }
690         }
691         else
692         {
693             Number = va_arg (Args, unsigned int);
694             if (Type & ACPI_FORMAT_SIGN)
695             {
696                 Number = (signed int) Number;
697             }
698         }
699 
700         Pos = AcpiUtFormatNumber (Pos, End, Number, Base,
701             Width, Precision, Type);
702     }
703 
704     if (Size > 0)
705     {
706         if (Pos < End)
707         {
708             *Pos = '\0';
709         }
710         else
711         {
712             End[-1] = '\0';
713         }
714     }
715 
716     return (ACPI_PTR_DIFF (Pos, String));
717 }
718 
719 
720 /*******************************************************************************
721  *
722  * FUNCTION:    AcpiUtSnprintf
723  *
724  * PARAMETERS:  String              - String with boundary
725  *              Size                - Boundary of the string
726  *              Format, ...         - Standard printf format
727  *
728  * RETURN:      Number of bytes actually written.
729  *
730  * DESCRIPTION: Formatted output to a string.
731  *
732  ******************************************************************************/
733 
734 int
735 AcpiUtSnprintf (
736     char                    *String,
737     ACPI_SIZE               Size,
738     const char              *Format,
739     ...)
740 {
741     va_list                 Args;
742     int                     Length;
743 
744 
745     va_start (Args, Format);
746     Length = AcpiUtVsnprintf (String, Size, Format, Args);
747     va_end (Args);
748 
749     return (Length);
750 }
751 
752 
753 #ifdef ACPI_APPLICATION
754 /*******************************************************************************
755  *
756  * FUNCTION:    AcpiUtFileVprintf
757  *
758  * PARAMETERS:  File                - File descriptor
759  *              Format              - Standard printf format
760  *              Args                - Argument list
761  *
762  * RETURN:      Number of bytes actually written.
763  *
764  * DESCRIPTION: Formatted output to a file using argument list pointer.
765  *
766  ******************************************************************************/
767 
768 int
769 AcpiUtFileVprintf (
770     ACPI_FILE               File,
771     const char              *Format,
772     va_list                 Args)
773 {
774     ACPI_CPU_FLAGS          Flags;
775     int                     Length;
776 
777 
778     Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock);
779     Length = AcpiUtVsnprintf (AcpiGbl_PrintBuffer,
780         sizeof (AcpiGbl_PrintBuffer), Format, Args);
781 
782     (void) AcpiOsWriteFile (File, AcpiGbl_PrintBuffer, Length, 1);
783     AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags);
784 
785     return (Length);
786 }
787 
788 
789 /*******************************************************************************
790  *
791  * FUNCTION:    AcpiUtFilePrintf
792  *
793  * PARAMETERS:  File                - File descriptor
794  *              Format, ...         - Standard printf format
795  *
796  * RETURN:      Number of bytes actually written.
797  *
798  * DESCRIPTION: Formatted output to a file.
799  *
800  ******************************************************************************/
801 
802 int
803 AcpiUtFilePrintf (
804     ACPI_FILE               File,
805     const char              *Format,
806     ...)
807 {
808     va_list                 Args;
809     int                     Length;
810 
811 
812     va_start (Args, Format);
813     Length = AcpiUtFileVprintf (File, Format, Args);
814     va_end (Args);
815 
816     return (Length);
817 }
818 #endif
819