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