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