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 - 2018, 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        end = string + size;
 336
 337        for (; *format; ++format) {
 338                if (*format != '%') {
 339                        pos = acpi_ut_bound_string_output(pos, end, *format);
 340                        continue;
 341                }
 342
 343                type = 0;
 344                base = 10;
 345
 346                /* Process sign */
 347
 348                do {
 349                        ++format;
 350                        if (*format == '#') {
 351                                type |= ACPI_FORMAT_PREFIX;
 352                        } else if (*format == '0') {
 353                                type |= ACPI_FORMAT_ZERO;
 354                        } else if (*format == '+') {
 355                                type |= ACPI_FORMAT_SIGN_PLUS;
 356                        } else if (*format == ' ') {
 357                                type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
 358                        } else if (*format == '-') {
 359                                type |= ACPI_FORMAT_LEFT;
 360                        } else {
 361                                break;
 362                        }
 363
 364                } while (1);
 365
 366                /* Process width */
 367
 368                width = -1;
 369                if (isdigit((int)*format)) {
 370                        format = acpi_ut_scan_number(format, &number);
 371                        width = (s32)number;
 372                } else if (*format == '*') {
 373                        ++format;
 374                        width = va_arg(args, int);
 375                        if (width < 0) {
 376                                width = -width;
 377                                type |= ACPI_FORMAT_LEFT;
 378                        }
 379                }
 380
 381                /* Process precision */
 382
 383                precision = -1;
 384                if (*format == '.') {
 385                        ++format;
 386                        if (isdigit((int)*format)) {
 387                                format = acpi_ut_scan_number(format, &number);
 388                                precision = (s32)number;
 389                        } else if (*format == '*') {
 390                                ++format;
 391                                precision = va_arg(args, int);
 392                        }
 393
 394                        if (precision < 0) {
 395                                precision = 0;
 396                        }
 397                }
 398
 399                /* Process qualifier */
 400
 401                qualifier = -1;
 402                if (*format == 'h' || *format == 'l' || *format == 'L') {
 403                        qualifier = *format;
 404                        ++format;
 405
 406                        if (qualifier == 'l' && *format == 'l') {
 407                                qualifier = 'L';
 408                                ++format;
 409                        }
 410                }
 411
 412                switch (*format) {
 413                case '%':
 414
 415                        pos = acpi_ut_bound_string_output(pos, end, '%');
 416                        continue;
 417
 418                case 'c':
 419
 420                        if (!(type & ACPI_FORMAT_LEFT)) {
 421                                while (--width > 0) {
 422                                        pos =
 423                                            acpi_ut_bound_string_output(pos,
 424                                                                        end,
 425                                                                        ' ');
 426                                }
 427                        }
 428
 429                        c = (char)va_arg(args, int);
 430                        pos = acpi_ut_bound_string_output(pos, end, c);
 431
 432                        while (--width > 0) {
 433                                pos =
 434                                    acpi_ut_bound_string_output(pos, end, ' ');
 435                        }
 436                        continue;
 437
 438                case 's':
 439
 440                        s = va_arg(args, char *);
 441                        if (!s) {
 442                                s = "<NULL>";
 443                        }
 444                        length = (s32)acpi_ut_bound_string_length(s, precision);
 445                        if (!(type & ACPI_FORMAT_LEFT)) {
 446                                while (length < width--) {
 447                                        pos =
 448                                            acpi_ut_bound_string_output(pos,
 449                                                                        end,
 450                                                                        ' ');
 451                                }
 452                        }
 453
 454                        for (i = 0; i < length; ++i) {
 455                                pos = acpi_ut_bound_string_output(pos, end, *s);
 456                                ++s;
 457                        }
 458
 459                        while (length < width--) {
 460                                pos =
 461                                    acpi_ut_bound_string_output(pos, end, ' ');
 462                        }
 463                        continue;
 464
 465                case 'o':
 466
 467                        base = 8;
 468                        break;
 469
 470                case 'X':
 471
 472                        type |= ACPI_FORMAT_UPPER;
 473
 474                case 'x':
 475
 476                        base = 16;
 477                        break;
 478
 479                case 'd':
 480                case 'i':
 481
 482                        type |= ACPI_FORMAT_SIGN;
 483
 484                case 'u':
 485
 486                        break;
 487
 488                case 'p':
 489
 490                        if (width == -1) {
 491                                width = 2 * sizeof(void *);
 492                                type |= ACPI_FORMAT_ZERO;
 493                        }
 494
 495                        p = va_arg(args, void *);
 496                        pos =
 497                            acpi_ut_format_number(pos, end, ACPI_TO_INTEGER(p),
 498                                                  16, width, precision, type);
 499                        continue;
 500
 501                default:
 502
 503                        pos = acpi_ut_bound_string_output(pos, end, '%');
 504                        if (*format) {
 505                                pos =
 506                                    acpi_ut_bound_string_output(pos, end,
 507                                                                *format);
 508                        } else {
 509                                --format;
 510                        }
 511                        continue;
 512                }
 513
 514                if (qualifier == 'L') {
 515                        number = va_arg(args, u64);
 516                        if (type & ACPI_FORMAT_SIGN) {
 517                                number = (s64)number;
 518                        }
 519                } else if (qualifier == 'l') {
 520                        number = va_arg(args, unsigned long);
 521                        if (type & ACPI_FORMAT_SIGN) {
 522                                number = (s32)number;
 523                        }
 524                } else if (qualifier == 'h') {
 525                        number = (u16)va_arg(args, int);
 526                        if (type & ACPI_FORMAT_SIGN) {
 527                                number = (s16)number;
 528                        }
 529                } else {
 530                        number = va_arg(args, unsigned int);
 531                        if (type & ACPI_FORMAT_SIGN) {
 532                                number = (signed int)number;
 533                        }
 534                }
 535
 536                pos = acpi_ut_format_number(pos, end, number, base,
 537                                            width, precision, type);
 538        }
 539
 540        if (size > 0) {
 541                if (pos < end) {
 542                        *pos = '\0';
 543                } else {
 544                        end[-1] = '\0';
 545                }
 546        }
 547
 548        return ((int)ACPI_PTR_DIFF(pos, string));
 549}
 550
 551/*******************************************************************************
 552 *
 553 * FUNCTION:    snprintf
 554 *
 555 * PARAMETERS:  string              - String with boundary
 556 *              size                - Boundary of the string
 557 *              Format, ...         - Standard printf format
 558 *
 559 * RETURN:      Number of bytes actually written.
 560 *
 561 * DESCRIPTION: Formatted output to a string.
 562 *
 563 ******************************************************************************/
 564
 565int snprintf(char *string, acpi_size size, const char *format, ...)
 566{
 567        va_list args;
 568        int length;
 569
 570        va_start(args, format);
 571        length = vsnprintf(string, size, format, args);
 572        va_end(args);
 573
 574        return (length);
 575}
 576
 577/*******************************************************************************
 578 *
 579 * FUNCTION:    sprintf
 580 *
 581 * PARAMETERS:  string              - String with boundary
 582 *              Format, ...         - Standard printf format
 583 *
 584 * RETURN:      Number of bytes actually written.
 585 *
 586 * DESCRIPTION: Formatted output to a string.
 587 *
 588 ******************************************************************************/
 589
 590int sprintf(char *string, const char *format, ...)
 591{
 592        va_list args;
 593        int length;
 594
 595        va_start(args, format);
 596        length = vsnprintf(string, ACPI_UINT32_MAX, format, args);
 597        va_end(args);
 598
 599        return (length);
 600}
 601
 602#ifdef ACPI_APPLICATION
 603/*******************************************************************************
 604 *
 605 * FUNCTION:    vprintf
 606 *
 607 * PARAMETERS:  format              - Standard printf format
 608 *              args                - Argument list
 609 *
 610 * RETURN:      Number of bytes actually written.
 611 *
 612 * DESCRIPTION: Formatted output to stdout using argument list pointer.
 613 *
 614 ******************************************************************************/
 615
 616int vprintf(const char *format, va_list args)
 617{
 618        acpi_cpu_flags flags;
 619        int length;
 620
 621        flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
 622        length = vsnprintf(acpi_gbl_print_buffer,
 623                           sizeof(acpi_gbl_print_buffer), format, args);
 624
 625        (void)fwrite(acpi_gbl_print_buffer, length, 1, ACPI_FILE_OUT);
 626        acpi_os_release_lock(acpi_gbl_print_lock, flags);
 627
 628        return (length);
 629}
 630
 631/*******************************************************************************
 632 *
 633 * FUNCTION:    printf
 634 *
 635 * PARAMETERS:  Format, ...         - Standard printf format
 636 *
 637 * RETURN:      Number of bytes actually written.
 638 *
 639 * DESCRIPTION: Formatted output to stdout.
 640 *
 641 ******************************************************************************/
 642
 643int printf(const char *format, ...)
 644{
 645        va_list args;
 646        int length;
 647
 648        va_start(args, format);
 649        length = vprintf(format, args);
 650        va_end(args);
 651
 652        return (length);
 653}
 654
 655/*******************************************************************************
 656 *
 657 * FUNCTION:    vfprintf
 658 *
 659 * PARAMETERS:  file                - File descriptor
 660 *              format              - Standard printf format
 661 *              args                - Argument list
 662 *
 663 * RETURN:      Number of bytes actually written.
 664 *
 665 * DESCRIPTION: Formatted output to a file using argument list pointer.
 666 *
 667 ******************************************************************************/
 668
 669int vfprintf(FILE * file, const char *format, va_list args)
 670{
 671        acpi_cpu_flags flags;
 672        int length;
 673
 674        flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
 675        length = vsnprintf(acpi_gbl_print_buffer,
 676                           sizeof(acpi_gbl_print_buffer), format, args);
 677
 678        (void)fwrite(acpi_gbl_print_buffer, length, 1, file);
 679        acpi_os_release_lock(acpi_gbl_print_lock, flags);
 680
 681        return (length);
 682}
 683
 684/*******************************************************************************
 685 *
 686 * FUNCTION:    fprintf
 687 *
 688 * PARAMETERS:  file                - File descriptor
 689 *              Format, ...         - Standard printf format
 690 *
 691 * RETURN:      Number of bytes actually written.
 692 *
 693 * DESCRIPTION: Formatted output to a file.
 694 *
 695 ******************************************************************************/
 696
 697int fprintf(FILE * file, const char *format, ...)
 698{
 699        va_list args;
 700        int length;
 701
 702        va_start(args, format);
 703        length = vfprintf(file, format, args);
 704        va_end(args);
 705
 706        return (length);
 707}
 708#endif
 709