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