utprint.c revision 306536
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 <contrib/dev/acpica/include/acpi.h>
45#include <contrib/dev/acpica/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
62static ACPI_SIZE
63AcpiUtBoundStringLength (
64    const char              *String,
65    ACPI_SIZE               Count);
66
67static char *
68AcpiUtBoundStringOutput (
69    char                    *String,
70    const char              *End,
71    char                    c);
72
73static char *
74AcpiUtFormatNumber (
75    char                    *String,
76    char                    *End,
77    UINT64                  Number,
78    UINT8                   Base,
79    INT32                   Width,
80    INT32                   Precision,
81    UINT8                   Type);
82
83static char *
84AcpiUtPutNumber (
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
104static ACPI_SIZE
105AcpiUtBoundStringLength (
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
137static char *
138AcpiUtBoundStringOutput (
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
170static char *
171AcpiUtPutNumber (
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
216const char *
217AcpiUtScanNumber (
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
248const char *
249AcpiUtPrintNumber (
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
289static char *
290AcpiUtFormatNumber (
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
432int
433AcpiUtVsnprintf (
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
728int
729AcpiUtSnprintf (
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
762int
763AcpiUtFileVprintf (
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
796int
797AcpiUtFilePrintf (
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