utprint.c revision 281075
1/******************************************************************************
2 *
3 * Module Name: utprint - Formatted printing routines
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2015, 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/* Module globals */
92
93static const char           AcpiGbl_LowerHexDigits[] = "0123456789abcdef";
94static 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
110static ACPI_SIZE
111AcpiUtBoundStringLength (
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
143static char *
144AcpiUtBoundStringOutput (
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
176static char *
177AcpiUtPutNumber (
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
222const char *
223AcpiUtScanNumber (
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
254const char *
255AcpiUtPrintNumber (
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
295static char *
296AcpiUtFormatNumber (
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
438int
439AcpiUtVsnprintf (
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
727int
728AcpiUtSnprintf (
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
761int
762AcpiUtFileVprintf (
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
795int
796AcpiUtFilePrintf (
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