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