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