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