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 - 2019, 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                        /* FALLTHROUGH */
 474
 475                case 'x':
 476
 477                        base = 16;
 478                        break;
 479
 480                case 'd':
 481                case 'i':
 482
 483                        type |= ACPI_FORMAT_SIGN;
 484
 485                case 'u':
 486
 487                        break;
 488
 489                case 'p':
 490
 491                        if (width == -1) {
 492                                width = 2 * sizeof(void *);
 493                                type |= ACPI_FORMAT_ZERO;
 494                        }
 495
 496                        p = va_arg(args, void *);
 497                        pos =
 498                            acpi_ut_format_number(pos, end, ACPI_TO_INTEGER(p),
 499                                                  16, width, precision, type);
 500                        continue;
 501
 502                default:
 503
 504                        pos = acpi_ut_bound_string_output(pos, end, '%');
 505                        if (*format) {
 506                                pos =
 507                                    acpi_ut_bound_string_output(pos, end,
 508                                                                *format);
 509                        } else {
 510                                --format;
 511                        }
 512                        continue;
 513                }
 514
 515                if (qualifier == 'L') {
 516                        number = va_arg(args, u64);
 517                        if (type & ACPI_FORMAT_SIGN) {
 518                                number = (s64)number;
 519                        }
 520                } else if (qualifier == 'l') {
 521                        number = va_arg(args, unsigned long);
 522                        if (type & ACPI_FORMAT_SIGN) {
 523                                number = (s32)number;
 524                        }
 525                } else if (qualifier == 'h') {
 526                        number = (u16)va_arg(args, int);
 527                        if (type & ACPI_FORMAT_SIGN) {
 528                                number = (s16)number;
 529                        }
 530                } else {
 531                        number = va_arg(args, unsigned int);
 532                        if (type & ACPI_FORMAT_SIGN) {
 533                                number = (signed int)number;
 534                        }
 535                }
 536
 537                pos = acpi_ut_format_number(pos, end, number, base,
 538                                            width, precision, type);
 539        }
 540
 541        if (size > 0) {
 542                if (pos < end) {
 543                        *pos = '\0';
 544                } else {
 545                        end[-1] = '\0';
 546                }
 547        }
 548
 549        return ((int)ACPI_PTR_DIFF(pos, string));
 550}
 551
 552/*******************************************************************************
 553 *
 554 * FUNCTION:    snprintf
 555 *
 556 * PARAMETERS:  string              - String with boundary
 557 *              size                - Boundary of the string
 558 *              Format, ...         - Standard printf format
 559 *
 560 * RETURN:      Number of bytes actually written.
 561 *
 562 * DESCRIPTION: Formatted output to a string.
 563 *
 564 ******************************************************************************/
 565
 566int snprintf(char *string, acpi_size size, const char *format, ...)
 567{
 568        va_list args;
 569        int length;
 570
 571        va_start(args, format);
 572        length = vsnprintf(string, size, format, args);
 573        va_end(args);
 574
 575        return (length);
 576}
 577
 578/*******************************************************************************
 579 *
 580 * FUNCTION:    sprintf
 581 *
 582 * PARAMETERS:  string              - String with boundary
 583 *              Format, ...         - Standard printf format
 584 *
 585 * RETURN:      Number of bytes actually written.
 586 *
 587 * DESCRIPTION: Formatted output to a string.
 588 *
 589 ******************************************************************************/
 590
 591int sprintf(char *string, const char *format, ...)
 592{
 593        va_list args;
 594        int length;
 595
 596        va_start(args, format);
 597        length = vsnprintf(string, ACPI_UINT32_MAX, format, args);
 598        va_end(args);
 599
 600        return (length);
 601}
 602
 603#ifdef ACPI_APPLICATION
 604/*******************************************************************************
 605 *
 606 * FUNCTION:    vprintf
 607 *
 608 * PARAMETERS:  format              - Standard printf format
 609 *              args                - Argument list
 610 *
 611 * RETURN:      Number of bytes actually written.
 612 *
 613 * DESCRIPTION: Formatted output to stdout using argument list pointer.
 614 *
 615 ******************************************************************************/
 616
 617int vprintf(const char *format, va_list args)
 618{
 619        acpi_cpu_flags flags;
 620        int length;
 621
 622        flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
 623        length = vsnprintf(acpi_gbl_print_buffer,
 624                           sizeof(acpi_gbl_print_buffer), format, args);
 625
 626        (void)fwrite(acpi_gbl_print_buffer, length, 1, ACPI_FILE_OUT);
 627        acpi_os_release_lock(acpi_gbl_print_lock, flags);
 628
 629        return (length);
 630}
 631
 632/*******************************************************************************
 633 *
 634 * FUNCTION:    printf
 635 *
 636 * PARAMETERS:  Format, ...         - Standard printf format
 637 *
 638 * RETURN:      Number of bytes actually written.
 639 *
 640 * DESCRIPTION: Formatted output to stdout.
 641 *
 642 ******************************************************************************/
 643
 644int printf(const char *format, ...)
 645{
 646        va_list args;
 647        int length;
 648
 649        va_start(args, format);
 650        length = vprintf(format, args);
 651        va_end(args);
 652
 653        return (length);
 654}
 655
 656/*******************************************************************************
 657 *
 658 * FUNCTION:    vfprintf
 659 *
 660 * PARAMETERS:  file                - File descriptor
 661 *              format              - Standard printf format
 662 *              args                - Argument list
 663 *
 664 * RETURN:      Number of bytes actually written.
 665 *
 666 * DESCRIPTION: Formatted output to a file using argument list pointer.
 667 *
 668 ******************************************************************************/
 669
 670int vfprintf(FILE * file, const char *format, va_list args)
 671{
 672        acpi_cpu_flags flags;
 673        int length;
 674
 675        flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
 676        length = vsnprintf(acpi_gbl_print_buffer,
 677                           sizeof(acpi_gbl_print_buffer), format, args);
 678
 679        (void)fwrite(acpi_gbl_print_buffer, length, 1, file);
 680        acpi_os_release_lock(acpi_gbl_print_lock, flags);
 681
 682        return (length);
 683}
 684
 685/*******************************************************************************
 686 *
 687 * FUNCTION:    fprintf
 688 *
 689 * PARAMETERS:  file                - File descriptor
 690 *              Format, ...         - Standard printf format
 691 *
 692 * RETURN:      Number of bytes actually written.
 693 *
 694 * DESCRIPTION: Formatted output to a file.
 695 *
 696 ******************************************************************************/
 697
 698int fprintf(FILE * file, const char *format, ...)
 699{
 700        va_list args;
 701        int length;
 702
 703        va_start(args, format);
 704        length = vfprintf(file, format, args);
 705        va_end(args);
 706
 707        return (length);
 708}
 709#endif
 710