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