linux/drivers/acpi/acpica/utprint.c
<<
>>
Prefs
   1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
   2/******************************************************************************
   3 *
   4 * Module Name: utprint - Formatted printing routines
   5 *
   6 * Copyright (C) 2000 - 2021, Intel Corp.
   7 *
   8 *****************************************************************************/
   9
  10#include <acpi/acpi.h>
  11#include "accommon.h"
  12
  13#define _COMPONENT          ACPI_UTILITIES
  14ACPI_MODULE_NAME("utprint")
  15
  16#define ACPI_FORMAT_SIGN            0x01
  17#define ACPI_FORMAT_SIGN_PLUS       0x02
  18#define ACPI_FORMAT_SIGN_PLUS_SPACE 0x04
  19#define ACPI_FORMAT_ZERO            0x08
  20#define ACPI_FORMAT_LEFT            0x10
  21#define ACPI_FORMAT_UPPER           0x20
  22#define ACPI_FORMAT_PREFIX          0x40
  23/* Local prototypes */
  24static acpi_size
  25acpi_ut_bound_string_length(const char *string, acpi_size count);
  26
  27static char *acpi_ut_bound_string_output(char *string, const char *end, char c);
  28
  29static char *acpi_ut_format_number(char *string,
  30                                   char *end,
  31                                   u64 number,
  32                                   u8 base, s32 width, s32 precision, u8 type);
  33
  34static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper);
  35
  36/*******************************************************************************
  37 *
  38 * FUNCTION:    acpi_ut_bound_string_length
  39 *
  40 * PARAMETERS:  string              - String with boundary
  41 *              count               - Boundary of the string
  42 *
  43 * RETURN:      Length of the string. Less than or equal to Count.
  44 *
  45 * DESCRIPTION: Calculate the length of a string with boundary.
  46 *
  47 ******************************************************************************/
  48
  49static acpi_size
  50acpi_ut_bound_string_length(const char *string, acpi_size count)
  51{
  52        u32 length = 0;
  53
  54        while (*string && count) {
  55                length++;
  56                string++;
  57                count--;
  58        }
  59
  60        return (length);
  61}
  62
  63/*******************************************************************************
  64 *
  65 * FUNCTION:    acpi_ut_bound_string_output
  66 *
  67 * PARAMETERS:  string              - String with boundary
  68 *              end                 - Boundary of the string
  69 *              c                   - Character to be output to the string
  70 *
  71 * RETURN:      Updated position for next valid character
  72 *
  73 * DESCRIPTION: Output a character into a string with boundary check.
  74 *
  75 ******************************************************************************/
  76
  77static char *acpi_ut_bound_string_output(char *string, const char *end, char c)
  78{
  79
  80        if (string < end) {
  81                *string = c;
  82        }
  83
  84        ++string;
  85        return (string);
  86}
  87
  88/*******************************************************************************
  89 *
  90 * FUNCTION:    acpi_ut_put_number
  91 *
  92 * PARAMETERS:  string              - Buffer to hold reverse-ordered string
  93 *              number              - Integer to be converted
  94 *              base                - Base of the integer
  95 *              upper               - Whether or not using upper cased digits
  96 *
  97 * RETURN:      Updated position for next valid character
  98 *
  99 * DESCRIPTION: Convert an integer into a string, note that, the string holds a
 100 *              reversed ordered number without the trailing zero.
 101 *
 102 ******************************************************************************/
 103
 104static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper)
 105{
 106        const char *digits;
 107        u64 digit_index;
 108        char *pos;
 109
 110        pos = string;
 111        digits = upper ? acpi_gbl_upper_hex_digits : acpi_gbl_lower_hex_digits;
 112
 113        if (number == 0) {
 114                *(pos++) = '0';
 115        } else {
 116                while (number) {
 117                        (void)acpi_ut_divide(number, base, &number,
 118                                             &digit_index);
 119                        *(pos++) = digits[digit_index];
 120                }
 121        }
 122
 123        /* *(Pos++) = '0'; */
 124        return (pos);
 125}
 126
 127/*******************************************************************************
 128 *
 129 * FUNCTION:    acpi_ut_scan_number
 130 *
 131 * PARAMETERS:  string              - String buffer
 132 *              number_ptr          - Where the number is returned
 133 *
 134 * RETURN:      Updated position for next valid character
 135 *
 136 * DESCRIPTION: Scan a string for a decimal integer.
 137 *
 138 ******************************************************************************/
 139
 140const char *acpi_ut_scan_number(const char *string, u64 *number_ptr)
 141{
 142        u64 number = 0;
 143
 144        while (isdigit((int)*string)) {
 145                acpi_ut_short_multiply(number, 10, &number);
 146                number += *(string++) - '0';
 147        }
 148
 149        *number_ptr = number;
 150        return (string);
 151}
 152
 153/*******************************************************************************
 154 *
 155 * FUNCTION:    acpi_ut_print_number
 156 *
 157 * PARAMETERS:  string              - String buffer
 158 *              number              - The number to be converted
 159 *
 160 * RETURN:      Updated position for next valid character
 161 *
 162 * DESCRIPTION: Print a decimal integer into a string.
 163 *
 164 ******************************************************************************/
 165
 166const char *acpi_ut_print_number(char *string, u64 number)
 167{
 168        char ascii_string[20];
 169        const char *pos1;
 170        char *pos2;
 171
 172        pos1 = acpi_ut_put_number(ascii_string, number, 10, FALSE);
 173        pos2 = string;
 174
 175        while (pos1 != ascii_string) {
 176                *(pos2++) = *(--pos1);
 177        }
 178
 179        *pos2 = 0;
 180        return (string);
 181}
 182
 183/*******************************************************************************
 184 *
 185 * FUNCTION:    acpi_ut_format_number
 186 *
 187 * PARAMETERS:  string              - String buffer with boundary
 188 *              end                 - Boundary of the string
 189 *              number              - The number to be converted
 190 *              base                - Base of the integer
 191 *              width               - Field width
 192 *              precision           - Precision of the integer
 193 *              type                - Special printing flags
 194 *
 195 * RETURN:      Updated position for next valid character
 196 *
 197 * DESCRIPTION: Print an integer into a string with any base and any precision.
 198 *
 199 ******************************************************************************/
 200
 201static char *acpi_ut_format_number(char *string,
 202                                   char *end,
 203                                   u64 number,
 204                                   u8 base, s32 width, s32 precision, u8 type)
 205{
 206        char *pos;
 207        char sign;
 208        char zero;
 209        u8 need_prefix;
 210        u8 upper;
 211        s32 i;
 212        char reversed_string[66];
 213
 214        /* Parameter validation */
 215
 216        if (base < 2 || base > 16) {
 217                return (NULL);
 218        }
 219
 220        if (type & ACPI_FORMAT_LEFT) {
 221                type &= ~ACPI_FORMAT_ZERO;
 222        }
 223
 224        need_prefix = ((type & ACPI_FORMAT_PREFIX)
 225                       && base != 10) ? TRUE : FALSE;
 226        upper = (type & ACPI_FORMAT_UPPER) ? TRUE : FALSE;
 227        zero = (type & ACPI_FORMAT_ZERO) ? '0' : ' ';
 228
 229        /* Calculate size according to sign and prefix */
 230
 231        sign = '\0';
 232        if (type & ACPI_FORMAT_SIGN) {
 233                if ((s64)number < 0) {
 234                        sign = '-';
 235                        number = -(s64)number;
 236                        width--;
 237                } else if (type & ACPI_FORMAT_SIGN_PLUS) {
 238                        sign = '+';
 239                        width--;
 240                } else if (type & ACPI_FORMAT_SIGN_PLUS_SPACE) {
 241                        sign = ' ';
 242                        width--;
 243                }
 244        }
 245        if (need_prefix) {
 246                width--;
 247                if (base == 16) {
 248                        width--;
 249                }
 250        }
 251
 252        /* Generate full string in reverse order */
 253
 254        pos = acpi_ut_put_number(reversed_string, number, base, upper);
 255        i = (s32)ACPI_PTR_DIFF(pos, reversed_string);
 256
 257        /* Printing 100 using %2d gives "100", not "00" */
 258
 259        if (i > precision) {
 260                precision = i;
 261        }
 262
 263        width -= precision;
 264
 265        /* Output the string */
 266
 267        if (!(type & (ACPI_FORMAT_ZERO | ACPI_FORMAT_LEFT))) {
 268                while (--width >= 0) {
 269                        string = acpi_ut_bound_string_output(string, end, ' ');
 270                }
 271        }
 272        if (sign) {
 273                string = acpi_ut_bound_string_output(string, end, sign);
 274        }
 275        if (need_prefix) {
 276                string = acpi_ut_bound_string_output(string, end, '0');
 277                if (base == 16) {
 278                        string =
 279                            acpi_ut_bound_string_output(string, end,
 280                                                        upper ? 'X' : 'x');
 281                }
 282        }
 283        if (!(type & ACPI_FORMAT_LEFT)) {
 284                while (--width >= 0) {
 285                        string = acpi_ut_bound_string_output(string, end, zero);
 286                }
 287        }
 288
 289        while (i <= --precision) {
 290                string = acpi_ut_bound_string_output(string, end, '0');
 291        }
 292        while (--i >= 0) {
 293                string = acpi_ut_bound_string_output(string, end,
 294                                                     reversed_string[i]);
 295        }
 296        while (--width >= 0) {
 297                string = acpi_ut_bound_string_output(string, end, ' ');
 298        }
 299
 300        return (string);
 301}
 302
 303/*******************************************************************************
 304 *
 305 * FUNCTION:    vsnprintf
 306 *
 307 * PARAMETERS:  string              - String with boundary
 308 *              size                - Boundary of the string
 309 *              format              - Standard printf format
 310 *              args                - Argument list
 311 *
 312 * RETURN:      Number of bytes actually written.
 313 *
 314 * DESCRIPTION: Formatted output to a string using argument list pointer.
 315 *
 316 ******************************************************************************/
 317
 318int vsnprintf(char *string, acpi_size size, const char *format, va_list args)
 319{
 320        u8 base;
 321        u8 type;
 322        s32 width;
 323        s32 precision;
 324        char qualifier;
 325        u64 number;
 326        char *pos;
 327        char *end;
 328        char c;
 329        const char *s;
 330        const void *p;
 331        s32 length;
 332        int i;
 333
 334        pos = string;
 335
 336        if (size != ACPI_UINT32_MAX) {
 337                end = string + size;
 338        } else {
 339                end = ACPI_CAST_PTR(char, ACPI_UINT32_MAX);
 340        }
 341
 342        for (; *format; ++format) {
 343                if (*format != '%') {
 344                        pos = acpi_ut_bound_string_output(pos, end, *format);
 345                        continue;
 346                }
 347
 348                type = 0;
 349                base = 10;
 350
 351                /* Process sign */
 352
 353                do {
 354                        ++format;
 355                        if (*format == '#') {
 356                                type |= ACPI_FORMAT_PREFIX;
 357                        } else if (*format == '0') {
 358                                type |= ACPI_FORMAT_ZERO;
 359                        } else if (*format == '+') {
 360                                type |= ACPI_FORMAT_SIGN_PLUS;
 361                        } else if (*format == ' ') {
 362                                type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
 363                        } else if (*format == '-') {
 364                                type |= ACPI_FORMAT_LEFT;
 365                        } else {
 366                                break;
 367                        }
 368
 369                } while (1);
 370
 371                /* Process width */
 372
 373                width = -1;
 374                if (isdigit((int)*format)) {
 375                        format = acpi_ut_scan_number(format, &number);
 376                        width = (s32)number;
 377                } else if (*format == '*') {
 378                        ++format;
 379                        width = va_arg(args, int);
 380                        if (width < 0) {
 381                                width = -width;
 382                                type |= ACPI_FORMAT_LEFT;
 383                        }
 384                }
 385
 386                /* Process precision */
 387
 388                precision = -1;
 389                if (*format == '.') {
 390                        ++format;
 391                        if (isdigit((int)*format)) {
 392                                format = acpi_ut_scan_number(format, &number);
 393                                precision = (s32)number;
 394                        } else if (*format == '*') {
 395                                ++format;
 396                                precision = va_arg(args, int);
 397                        }
 398
 399                        if (precision < 0) {
 400                                precision = 0;
 401                        }
 402                }
 403
 404                /* Process qualifier */
 405
 406                qualifier = -1;
 407                if (*format == 'h' || *format == 'l' || *format == 'L') {
 408                        qualifier = *format;
 409                        ++format;
 410
 411                        if (qualifier == 'l' && *format == 'l') {
 412                                qualifier = 'L';
 413                                ++format;
 414                        }
 415                }
 416
 417                switch (*format) {
 418                case '%':
 419
 420                        pos = acpi_ut_bound_string_output(pos, end, '%');
 421                        continue;
 422
 423                case 'c':
 424
 425                        if (!(type & ACPI_FORMAT_LEFT)) {
 426                                while (--width > 0) {
 427                                        pos =
 428                                            acpi_ut_bound_string_output(pos,
 429                                                                        end,
 430                                                                        ' ');
 431                                }
 432                        }
 433
 434                        c = (char)va_arg(args, int);
 435                        pos = acpi_ut_bound_string_output(pos, end, c);
 436
 437                        while (--width > 0) {
 438                                pos =
 439                                    acpi_ut_bound_string_output(pos, end, ' ');
 440                        }
 441                        continue;
 442
 443                case 's':
 444
 445                        s = va_arg(args, char *);
 446                        if (!s) {
 447                                s = "<NULL>";
 448                        }
 449                        length = (s32)acpi_ut_bound_string_length(s, precision);
 450                        if (!(type & ACPI_FORMAT_LEFT)) {
 451                                while (length < width--) {
 452                                        pos =
 453                                            acpi_ut_bound_string_output(pos,
 454                                                                        end,
 455                                                                        ' ');
 456                                }
 457                        }
 458
 459                        for (i = 0; i < length; ++i) {
 460                                pos = acpi_ut_bound_string_output(pos, end, *s);
 461                                ++s;
 462                        }
 463
 464                        while (length < width--) {
 465                                pos =
 466                                    acpi_ut_bound_string_output(pos, end, ' ');
 467                        }
 468                        continue;
 469
 470                case 'o':
 471
 472                        base = 8;
 473                        break;
 474
 475                case 'X':
 476
 477                        type |= ACPI_FORMAT_UPPER;
 478                        ACPI_FALLTHROUGH;
 479
 480                case 'x':
 481
 482                        base = 16;
 483                        break;
 484
 485                case 'd':
 486                case 'i':
 487
 488                        type |= ACPI_FORMAT_SIGN;
 489
 490                case 'u':
 491
 492                        break;
 493
 494                case 'p':
 495
 496                        if (width == -1) {
 497                                width = 2 * sizeof(void *);
 498                                type |= ACPI_FORMAT_ZERO;
 499                        }
 500
 501                        p = va_arg(args, void *);
 502                        pos =
 503                            acpi_ut_format_number(pos, end, ACPI_TO_INTEGER(p),
 504                                                  16, width, precision, type);
 505                        continue;
 506
 507                default:
 508
 509                        pos = acpi_ut_bound_string_output(pos, end, '%');
 510                        if (*format) {
 511                                pos =
 512                                    acpi_ut_bound_string_output(pos, end,
 513                                                                *format);
 514                        } else {
 515                                --format;
 516                        }
 517                        continue;
 518                }
 519
 520                if (qualifier == 'L') {
 521                        number = va_arg(args, u64);
 522                        if (type & ACPI_FORMAT_SIGN) {
 523                                number = (s64)number;
 524                        }
 525                } else if (qualifier == 'l') {
 526                        number = va_arg(args, unsigned long);
 527                        if (type & ACPI_FORMAT_SIGN) {
 528                                number = (s32)number;
 529                        }
 530                } else if (qualifier == 'h') {
 531                        number = (u16)va_arg(args, int);
 532                        if (type & ACPI_FORMAT_SIGN) {
 533                                number = (s16)number;
 534                        }
 535                } else {
 536                        number = va_arg(args, unsigned int);
 537                        if (type & ACPI_FORMAT_SIGN) {
 538                                number = (signed int)number;
 539                        }
 540                }
 541
 542                pos = acpi_ut_format_number(pos, end, number, base,
 543                                            width, precision, type);
 544        }
 545
 546        if (size > 0) {
 547                if (pos < end) {
 548                        *pos = '\0';
 549                } else {
 550                        end[-1] = '\0';
 551                }
 552        }
 553
 554        return ((int)ACPI_PTR_DIFF(pos, string));
 555}
 556
 557/*******************************************************************************
 558 *
 559 * FUNCTION:    snprintf
 560 *
 561 * PARAMETERS:  string              - String with boundary
 562 *              size                - Boundary of the string
 563 *              Format, ...         - Standard printf format
 564 *
 565 * RETURN:      Number of bytes actually written.
 566 *
 567 * DESCRIPTION: Formatted output to a string.
 568 *
 569 ******************************************************************************/
 570
 571int snprintf(char *string, acpi_size size, const char *format, ...)
 572{
 573        va_list args;
 574        int length;
 575
 576        va_start(args, format);
 577        length = vsnprintf(string, size, format, args);
 578        va_end(args);
 579
 580        return (length);
 581}
 582
 583/*******************************************************************************
 584 *
 585 * FUNCTION:    sprintf
 586 *
 587 * PARAMETERS:  string              - String with boundary
 588 *              Format, ...         - Standard printf format
 589 *
 590 * RETURN:      Number of bytes actually written.
 591 *
 592 * DESCRIPTION: Formatted output to a string.
 593 *
 594 ******************************************************************************/
 595
 596int sprintf(char *string, const char *format, ...)
 597{
 598        va_list args;
 599        int length;
 600
 601        va_start(args, format);
 602        length = vsnprintf(string, ACPI_UINT32_MAX, format, args);
 603        va_end(args);
 604
 605        return (length);
 606}
 607
 608#ifdef ACPI_APPLICATION
 609/*******************************************************************************
 610 *
 611 * FUNCTION:    vprintf
 612 *
 613 * PARAMETERS:  format              - Standard printf format
 614 *              args                - Argument list
 615 *
 616 * RETURN:      Number of bytes actually written.
 617 *
 618 * DESCRIPTION: Formatted output to stdout using argument list pointer.
 619 *
 620 ******************************************************************************/
 621
 622int vprintf(const char *format, va_list args)
 623{
 624        acpi_cpu_flags flags;
 625        int length;
 626
 627        flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
 628        length = vsnprintf(acpi_gbl_print_buffer,
 629                           sizeof(acpi_gbl_print_buffer), format, args);
 630
 631        (void)fwrite(acpi_gbl_print_buffer, length, 1, ACPI_FILE_OUT);
 632        acpi_os_release_lock(acpi_gbl_print_lock, flags);
 633
 634        return (length);
 635}
 636
 637/*******************************************************************************
 638 *
 639 * FUNCTION:    printf
 640 *
 641 * PARAMETERS:  Format, ...         - Standard printf format
 642 *
 643 * RETURN:      Number of bytes actually written.
 644 *
 645 * DESCRIPTION: Formatted output to stdout.
 646 *
 647 ******************************************************************************/
 648
 649int printf(const char *format, ...)
 650{
 651        va_list args;
 652        int length;
 653
 654        va_start(args, format);
 655        length = vprintf(format, args);
 656        va_end(args);
 657
 658        return (length);
 659}
 660
 661/*******************************************************************************
 662 *
 663 * FUNCTION:    vfprintf
 664 *
 665 * PARAMETERS:  file                - File descriptor
 666 *              format              - Standard printf format
 667 *              args                - Argument list
 668 *
 669 * RETURN:      Number of bytes actually written.
 670 *
 671 * DESCRIPTION: Formatted output to a file using argument list pointer.
 672 *
 673 ******************************************************************************/
 674
 675int vfprintf(FILE * file, const char *format, va_list args)
 676{
 677        acpi_cpu_flags flags;
 678        int length;
 679
 680        flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
 681        length = vsnprintf(acpi_gbl_print_buffer,
 682                           sizeof(acpi_gbl_print_buffer), format, args);
 683
 684        (void)fwrite(acpi_gbl_print_buffer, length, 1, file);
 685        acpi_os_release_lock(acpi_gbl_print_lock, flags);
 686
 687        return (length);
 688}
 689
 690/*******************************************************************************
 691 *
 692 * FUNCTION:    fprintf
 693 *
 694 * PARAMETERS:  file                - File descriptor
 695 *              Format, ...         - Standard printf format
 696 *
 697 * RETURN:      Number of bytes actually written.
 698 *
 699 * DESCRIPTION: Formatted output to a file.
 700 *
 701 ******************************************************************************/
 702
 703int fprintf(FILE * file, const char *format, ...)
 704{
 705        va_list args;
 706        int length;
 707
 708        va_start(args, format);
 709        length = vfprintf(file, format, args);
 710        va_end(args);
 711
 712        return (length);
 713}
 714#endif
 715