1 /****************************************************************************** 2 * 3 * Module Name: utprint - Formatted printing routines 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2018, 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 48 ACPI_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 */ 58 static acpi_size 59 acpi_ut_bound_string_length(const char *string, acpi_size count); 60 61 static char *acpi_ut_bound_string_output(char *string, const char *end, char c); 62 63 static char *acpi_ut_format_number(char *string, 64 char *end, 65 u64 number, 66 u8 base, s32 width, s32 precision, u8 type); 67 68 static 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 83 static acpi_size 84 acpi_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 111 static 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 138 static 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 174 const char *acpi_ut_scan_number(const char *string, u64 *number_ptr) 175 { 176 u64 number = 0; 177 178 while (isdigit((int)*string)) { 179 acpi_ut_short_multiply(number, 10, &number); 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 200 const 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 235 static 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 = (s32)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 352 int 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 = (s32)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 ((int)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 599 int 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 624 int 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 650 int 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 677 int 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 703 int 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 731 int 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