Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Module Name: utprint - Formatted printing routines
0005  *
0006  * Copyright (C) 2000 - 2022, Intel Corp.
0007  *
0008  *****************************************************************************/
0009 
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 
0013 #define _COMPONENT          ACPI_UTILITIES
0014 ACPI_MODULE_NAME("utprint")
0015 
0016 #define ACPI_FORMAT_SIGN            0x01
0017 #define ACPI_FORMAT_SIGN_PLUS       0x02
0018 #define ACPI_FORMAT_SIGN_PLUS_SPACE 0x04
0019 #define ACPI_FORMAT_ZERO            0x08
0020 #define ACPI_FORMAT_LEFT            0x10
0021 #define ACPI_FORMAT_UPPER           0x20
0022 #define ACPI_FORMAT_PREFIX          0x40
0023 /* Local prototypes */
0024 static acpi_size
0025 acpi_ut_bound_string_length(const char *string, acpi_size count);
0026 
0027 static char *acpi_ut_bound_string_output(char *string, const char *end, char c);
0028 
0029 static char *acpi_ut_format_number(char *string,
0030                    char *end,
0031                    u64 number,
0032                    u8 base, s32 width, s32 precision, u8 type);
0033 
0034 static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper);
0035 
0036 /*******************************************************************************
0037  *
0038  * FUNCTION:    acpi_ut_bound_string_length
0039  *
0040  * PARAMETERS:  string              - String with boundary
0041  *              count               - Boundary of the string
0042  *
0043  * RETURN:      Length of the string. Less than or equal to Count.
0044  *
0045  * DESCRIPTION: Calculate the length of a string with boundary.
0046  *
0047  ******************************************************************************/
0048 
0049 static acpi_size
0050 acpi_ut_bound_string_length(const char *string, acpi_size count)
0051 {
0052     u32 length = 0;
0053 
0054     while (*string && count) {
0055         length++;
0056         string++;
0057         count--;
0058     }
0059 
0060     return (length);
0061 }
0062 
0063 /*******************************************************************************
0064  *
0065  * FUNCTION:    acpi_ut_bound_string_output
0066  *
0067  * PARAMETERS:  string              - String with boundary
0068  *              end                 - Boundary of the string
0069  *              c                   - Character to be output to the string
0070  *
0071  * RETURN:      Updated position for next valid character
0072  *
0073  * DESCRIPTION: Output a character into a string with boundary check.
0074  *
0075  ******************************************************************************/
0076 
0077 static char *acpi_ut_bound_string_output(char *string, const char *end, char c)
0078 {
0079 
0080     if (string < end) {
0081         *string = c;
0082     }
0083 
0084     ++string;
0085     return (string);
0086 }
0087 
0088 /*******************************************************************************
0089  *
0090  * FUNCTION:    acpi_ut_put_number
0091  *
0092  * PARAMETERS:  string              - Buffer to hold reverse-ordered string
0093  *              number              - Integer to be converted
0094  *              base                - Base of the integer
0095  *              upper               - Whether or not using upper cased digits
0096  *
0097  * RETURN:      Updated position for next valid character
0098  *
0099  * DESCRIPTION: Convert an integer into a string, note that, the string holds a
0100  *              reversed ordered number without the trailing zero.
0101  *
0102  ******************************************************************************/
0103 
0104 static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper)
0105 {
0106     const char *digits;
0107     u64 digit_index;
0108     char *pos;
0109 
0110     pos = string;
0111     digits = upper ? acpi_gbl_upper_hex_digits : acpi_gbl_lower_hex_digits;
0112 
0113     if (number == 0) {
0114         *(pos++) = '0';
0115     } else {
0116         while (number) {
0117             (void)acpi_ut_divide(number, base, &number,
0118                          &digit_index);
0119             *(pos++) = digits[digit_index];
0120         }
0121     }
0122 
0123     /* *(Pos++) = '0'; */
0124     return (pos);
0125 }
0126 
0127 /*******************************************************************************
0128  *
0129  * FUNCTION:    acpi_ut_scan_number
0130  *
0131  * PARAMETERS:  string              - String buffer
0132  *              number_ptr          - Where the number is returned
0133  *
0134  * RETURN:      Updated position for next valid character
0135  *
0136  * DESCRIPTION: Scan a string for a decimal integer.
0137  *
0138  ******************************************************************************/
0139 
0140 const char *acpi_ut_scan_number(const char *string, u64 *number_ptr)
0141 {
0142     u64 number = 0;
0143 
0144     while (isdigit((int)*string)) {
0145         acpi_ut_short_multiply(number, 10, &number);
0146         number += *(string++) - '0';
0147     }
0148 
0149     *number_ptr = number;
0150     return (string);
0151 }
0152 
0153 /*******************************************************************************
0154  *
0155  * FUNCTION:    acpi_ut_print_number
0156  *
0157  * PARAMETERS:  string              - String buffer
0158  *              number              - The number to be converted
0159  *
0160  * RETURN:      Updated position for next valid character
0161  *
0162  * DESCRIPTION: Print a decimal integer into a string.
0163  *
0164  ******************************************************************************/
0165 
0166 const char *acpi_ut_print_number(char *string, u64 number)
0167 {
0168     char ascii_string[20];
0169     const char *pos1;
0170     char *pos2;
0171 
0172     pos1 = acpi_ut_put_number(ascii_string, number, 10, FALSE);
0173     pos2 = string;
0174 
0175     while (pos1 != ascii_string) {
0176         *(pos2++) = *(--pos1);
0177     }
0178 
0179     *pos2 = 0;
0180     return (string);
0181 }
0182 
0183 /*******************************************************************************
0184  *
0185  * FUNCTION:    acpi_ut_format_number
0186  *
0187  * PARAMETERS:  string              - String buffer with boundary
0188  *              end                 - Boundary of the string
0189  *              number              - The number to be converted
0190  *              base                - Base of the integer
0191  *              width               - Field width
0192  *              precision           - Precision of the integer
0193  *              type                - Special printing flags
0194  *
0195  * RETURN:      Updated position for next valid character
0196  *
0197  * DESCRIPTION: Print an integer into a string with any base and any precision.
0198  *
0199  ******************************************************************************/
0200 
0201 static char *acpi_ut_format_number(char *string,
0202                    char *end,
0203                    u64 number,
0204                    u8 base, s32 width, s32 precision, u8 type)
0205 {
0206     char *pos;
0207     char sign;
0208     char zero;
0209     u8 need_prefix;
0210     u8 upper;
0211     s32 i;
0212     char reversed_string[66];
0213 
0214     /* Parameter validation */
0215 
0216     if (base < 2 || base > 16) {
0217         return (NULL);
0218     }
0219 
0220     if (type & ACPI_FORMAT_LEFT) {
0221         type &= ~ACPI_FORMAT_ZERO;
0222     }
0223 
0224     need_prefix = ((type & ACPI_FORMAT_PREFIX)
0225                && base != 10) ? TRUE : FALSE;
0226     upper = (type & ACPI_FORMAT_UPPER) ? TRUE : FALSE;
0227     zero = (type & ACPI_FORMAT_ZERO) ? '0' : ' ';
0228 
0229     /* Calculate size according to sign and prefix */
0230 
0231     sign = '\0';
0232     if (type & ACPI_FORMAT_SIGN) {
0233         if ((s64)number < 0) {
0234             sign = '-';
0235             number = -(s64)number;
0236             width--;
0237         } else if (type & ACPI_FORMAT_SIGN_PLUS) {
0238             sign = '+';
0239             width--;
0240         } else if (type & ACPI_FORMAT_SIGN_PLUS_SPACE) {
0241             sign = ' ';
0242             width--;
0243         }
0244     }
0245     if (need_prefix) {
0246         width--;
0247         if (base == 16) {
0248             width--;
0249         }
0250     }
0251 
0252     /* Generate full string in reverse order */
0253 
0254     pos = acpi_ut_put_number(reversed_string, number, base, upper);
0255     i = (s32)ACPI_PTR_DIFF(pos, reversed_string);
0256 
0257     /* Printing 100 using %2d gives "100", not "00" */
0258 
0259     if (i > precision) {
0260         precision = i;
0261     }
0262 
0263     width -= precision;
0264 
0265     /* Output the string */
0266 
0267     if (!(type & (ACPI_FORMAT_ZERO | ACPI_FORMAT_LEFT))) {
0268         while (--width >= 0) {
0269             string = acpi_ut_bound_string_output(string, end, ' ');
0270         }
0271     }
0272     if (sign) {
0273         string = acpi_ut_bound_string_output(string, end, sign);
0274     }
0275     if (need_prefix) {
0276         string = acpi_ut_bound_string_output(string, end, '0');
0277         if (base == 16) {
0278             string =
0279                 acpi_ut_bound_string_output(string, end,
0280                             upper ? 'X' : 'x');
0281         }
0282     }
0283     if (!(type & ACPI_FORMAT_LEFT)) {
0284         while (--width >= 0) {
0285             string = acpi_ut_bound_string_output(string, end, zero);
0286         }
0287     }
0288 
0289     while (i <= --precision) {
0290         string = acpi_ut_bound_string_output(string, end, '0');
0291     }
0292     while (--i >= 0) {
0293         string = acpi_ut_bound_string_output(string, end,
0294                              reversed_string[i]);
0295     }
0296     while (--width >= 0) {
0297         string = acpi_ut_bound_string_output(string, end, ' ');
0298     }
0299 
0300     return (string);
0301 }
0302 
0303 /*******************************************************************************
0304  *
0305  * FUNCTION:    vsnprintf
0306  *
0307  * PARAMETERS:  string              - String with boundary
0308  *              size                - Boundary of the string
0309  *              format              - Standard printf format
0310  *              args                - Argument list
0311  *
0312  * RETURN:      Number of bytes actually written.
0313  *
0314  * DESCRIPTION: Formatted output to a string using argument list pointer.
0315  *
0316  ******************************************************************************/
0317 
0318 int vsnprintf(char *string, acpi_size size, const char *format, va_list args)
0319 {
0320     u8 base;
0321     u8 type;
0322     s32 width;
0323     s32 precision;
0324     char qualifier;
0325     u64 number;
0326     char *pos;
0327     char *end;
0328     char c;
0329     const char *s;
0330     const void *p;
0331     s32 length;
0332     int i;
0333 
0334     pos = string;
0335 
0336     if (size != ACPI_UINT32_MAX) {
0337         end = string + size;
0338     } else {
0339         end = ACPI_CAST_PTR(char, ACPI_UINT32_MAX);
0340     }
0341 
0342     for (; *format; ++format) {
0343         if (*format != '%') {
0344             pos = acpi_ut_bound_string_output(pos, end, *format);
0345             continue;
0346         }
0347 
0348         type = 0;
0349         base = 10;
0350 
0351         /* Process sign */
0352 
0353         do {
0354             ++format;
0355             if (*format == '#') {
0356                 type |= ACPI_FORMAT_PREFIX;
0357             } else if (*format == '0') {
0358                 type |= ACPI_FORMAT_ZERO;
0359             } else if (*format == '+') {
0360                 type |= ACPI_FORMAT_SIGN_PLUS;
0361             } else if (*format == ' ') {
0362                 type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
0363             } else if (*format == '-') {
0364                 type |= ACPI_FORMAT_LEFT;
0365             } else {
0366                 break;
0367             }
0368 
0369         } while (1);
0370 
0371         /* Process width */
0372 
0373         width = -1;
0374         if (isdigit((int)*format)) {
0375             format = acpi_ut_scan_number(format, &number);
0376             width = (s32)number;
0377         } else if (*format == '*') {
0378             ++format;
0379             width = va_arg(args, int);
0380             if (width < 0) {
0381                 width = -width;
0382                 type |= ACPI_FORMAT_LEFT;
0383             }
0384         }
0385 
0386         /* Process precision */
0387 
0388         precision = -1;
0389         if (*format == '.') {
0390             ++format;
0391             if (isdigit((int)*format)) {
0392                 format = acpi_ut_scan_number(format, &number);
0393                 precision = (s32)number;
0394             } else if (*format == '*') {
0395                 ++format;
0396                 precision = va_arg(args, int);
0397             }
0398 
0399             if (precision < 0) {
0400                 precision = 0;
0401             }
0402         }
0403 
0404         /* Process qualifier */
0405 
0406         qualifier = -1;
0407         if (*format == 'h' || *format == 'l' || *format == 'L') {
0408             qualifier = *format;
0409             ++format;
0410 
0411             if (qualifier == 'l' && *format == 'l') {
0412                 qualifier = 'L';
0413                 ++format;
0414             }
0415         }
0416 
0417         switch (*format) {
0418         case '%':
0419 
0420             pos = acpi_ut_bound_string_output(pos, end, '%');
0421             continue;
0422 
0423         case 'c':
0424 
0425             if (!(type & ACPI_FORMAT_LEFT)) {
0426                 while (--width > 0) {
0427                     pos =
0428                         acpi_ut_bound_string_output(pos,
0429                                     end,
0430                                     ' ');
0431                 }
0432             }
0433 
0434             c = (char)va_arg(args, int);
0435             pos = acpi_ut_bound_string_output(pos, end, c);
0436 
0437             while (--width > 0) {
0438                 pos =
0439                     acpi_ut_bound_string_output(pos, end, ' ');
0440             }
0441             continue;
0442 
0443         case 's':
0444 
0445             s = va_arg(args, char *);
0446             if (!s) {
0447                 s = "<NULL>";
0448             }
0449             length = (s32)acpi_ut_bound_string_length(s, precision);
0450             if (!(type & ACPI_FORMAT_LEFT)) {
0451                 while (length < width--) {
0452                     pos =
0453                         acpi_ut_bound_string_output(pos,
0454                                     end,
0455                                     ' ');
0456                 }
0457             }
0458 
0459             for (i = 0; i < length; ++i) {
0460                 pos = acpi_ut_bound_string_output(pos, end, *s);
0461                 ++s;
0462             }
0463 
0464             while (length < width--) {
0465                 pos =
0466                     acpi_ut_bound_string_output(pos, end, ' ');
0467             }
0468             continue;
0469 
0470         case 'o':
0471 
0472             base = 8;
0473             break;
0474 
0475         case 'X':
0476 
0477             type |= ACPI_FORMAT_UPPER;
0478             ACPI_FALLTHROUGH;
0479 
0480         case 'x':
0481 
0482             base = 16;
0483             break;
0484 
0485         case 'd':
0486         case 'i':
0487 
0488             type |= ACPI_FORMAT_SIGN;
0489 
0490         case 'u':
0491 
0492             break;
0493 
0494         case 'p':
0495 
0496             if (width == -1) {
0497                 width = 2 * sizeof(void *);
0498                 type |= ACPI_FORMAT_ZERO;
0499             }
0500 
0501             p = va_arg(args, void *);
0502             pos =
0503                 acpi_ut_format_number(pos, end, ACPI_TO_INTEGER(p),
0504                           16, width, precision, type);
0505             continue;
0506 
0507         default:
0508 
0509             pos = acpi_ut_bound_string_output(pos, end, '%');
0510             if (*format) {
0511                 pos =
0512                     acpi_ut_bound_string_output(pos, end,
0513                                 *format);
0514             } else {
0515                 --format;
0516             }
0517             continue;
0518         }
0519 
0520         if (qualifier == 'L') {
0521             number = va_arg(args, u64);
0522             if (type & ACPI_FORMAT_SIGN) {
0523                 number = (s64)number;
0524             }
0525         } else if (qualifier == 'l') {
0526             number = va_arg(args, unsigned long);
0527             if (type & ACPI_FORMAT_SIGN) {
0528                 number = (s32)number;
0529             }
0530         } else if (qualifier == 'h') {
0531             number = (u16)va_arg(args, int);
0532             if (type & ACPI_FORMAT_SIGN) {
0533                 number = (s16)number;
0534             }
0535         } else {
0536             number = va_arg(args, unsigned int);
0537             if (type & ACPI_FORMAT_SIGN) {
0538                 number = (signed int)number;
0539             }
0540         }
0541 
0542         pos = acpi_ut_format_number(pos, end, number, base,
0543                         width, precision, type);
0544     }
0545 
0546     if (size > 0) {
0547         if (pos < end) {
0548             *pos = '\0';
0549         } else {
0550             end[-1] = '\0';
0551         }
0552     }
0553 
0554     return ((int)ACPI_PTR_DIFF(pos, string));
0555 }
0556 
0557 /*******************************************************************************
0558  *
0559  * FUNCTION:    snprintf
0560  *
0561  * PARAMETERS:  string              - String with boundary
0562  *              size                - Boundary of the string
0563  *              Format, ...         - Standard printf format
0564  *
0565  * RETURN:      Number of bytes actually written.
0566  *
0567  * DESCRIPTION: Formatted output to a string.
0568  *
0569  ******************************************************************************/
0570 
0571 int snprintf(char *string, acpi_size size, const char *format, ...)
0572 {
0573     va_list args;
0574     int length;
0575 
0576     va_start(args, format);
0577     length = vsnprintf(string, size, format, args);
0578     va_end(args);
0579 
0580     return (length);
0581 }
0582 
0583 /*******************************************************************************
0584  *
0585  * FUNCTION:    sprintf
0586  *
0587  * PARAMETERS:  string              - String with boundary
0588  *              Format, ...         - Standard printf format
0589  *
0590  * RETURN:      Number of bytes actually written.
0591  *
0592  * DESCRIPTION: Formatted output to a string.
0593  *
0594  ******************************************************************************/
0595 
0596 int sprintf(char *string, const char *format, ...)
0597 {
0598     va_list args;
0599     int length;
0600 
0601     va_start(args, format);
0602     length = vsnprintf(string, ACPI_UINT32_MAX, format, args);
0603     va_end(args);
0604 
0605     return (length);
0606 }
0607 
0608 #ifdef ACPI_APPLICATION
0609 /*******************************************************************************
0610  *
0611  * FUNCTION:    vprintf
0612  *
0613  * PARAMETERS:  format              - Standard printf format
0614  *              args                - Argument list
0615  *
0616  * RETURN:      Number of bytes actually written.
0617  *
0618  * DESCRIPTION: Formatted output to stdout using argument list pointer.
0619  *
0620  ******************************************************************************/
0621 
0622 int vprintf(const char *format, va_list args)
0623 {
0624     acpi_cpu_flags flags;
0625     int length;
0626 
0627     flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
0628     length = vsnprintf(acpi_gbl_print_buffer,
0629                sizeof(acpi_gbl_print_buffer), format, args);
0630 
0631     (void)fwrite(acpi_gbl_print_buffer, length, 1, ACPI_FILE_OUT);
0632     acpi_os_release_lock(acpi_gbl_print_lock, flags);
0633 
0634     return (length);
0635 }
0636 
0637 /*******************************************************************************
0638  *
0639  * FUNCTION:    printf
0640  *
0641  * PARAMETERS:  Format, ...         - Standard printf format
0642  *
0643  * RETURN:      Number of bytes actually written.
0644  *
0645  * DESCRIPTION: Formatted output to stdout.
0646  *
0647  ******************************************************************************/
0648 
0649 int printf(const char *format, ...)
0650 {
0651     va_list args;
0652     int length;
0653 
0654     va_start(args, format);
0655     length = vprintf(format, args);
0656     va_end(args);
0657 
0658     return (length);
0659 }
0660 
0661 /*******************************************************************************
0662  *
0663  * FUNCTION:    vfprintf
0664  *
0665  * PARAMETERS:  file                - File descriptor
0666  *              format              - Standard printf format
0667  *              args                - Argument list
0668  *
0669  * RETURN:      Number of bytes actually written.
0670  *
0671  * DESCRIPTION: Formatted output to a file using argument list pointer.
0672  *
0673  ******************************************************************************/
0674 
0675 int vfprintf(FILE * file, const char *format, va_list args)
0676 {
0677     acpi_cpu_flags flags;
0678     int length;
0679 
0680     flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
0681     length = vsnprintf(acpi_gbl_print_buffer,
0682                sizeof(acpi_gbl_print_buffer), format, args);
0683 
0684     (void)fwrite(acpi_gbl_print_buffer, length, 1, file);
0685     acpi_os_release_lock(acpi_gbl_print_lock, flags);
0686 
0687     return (length);
0688 }
0689 
0690 /*******************************************************************************
0691  *
0692  * FUNCTION:    fprintf
0693  *
0694  * PARAMETERS:  file                - File descriptor
0695  *              Format, ...         - Standard printf format
0696  *
0697  * RETURN:      Number of bytes actually written.
0698  *
0699  * DESCRIPTION: Formatted output to a file.
0700  *
0701  ******************************************************************************/
0702 
0703 int fprintf(FILE * file, const char *format, ...)
0704 {
0705     va_list args;
0706     int length;
0707 
0708     va_start(args, format);
0709     length = vfprintf(file, format, args);
0710     va_end(args);
0711 
0712     return (length);
0713 }
0714 #endif