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 - 2018, 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 474 case 'x': 475 476 base = 16; 477 break; 478 479 case 'd': 480 case 'i': 481 482 type |= ACPI_FORMAT_SIGN; 483 484 case 'u': 485 486 break; 487 488 case 'p': 489 490 if (width == -1) { 491 width = 2 * sizeof(void *); 492 type |= ACPI_FORMAT_ZERO; 493 } 494 495 p = va_arg(args, void *); 496 pos = 497 acpi_ut_format_number(pos, end, ACPI_TO_INTEGER(p), 498 16, width, precision, type); 499 continue; 500 501 default: 502 503 pos = acpi_ut_bound_string_output(pos, end, '%'); 504 if (*format) { 505 pos = 506 acpi_ut_bound_string_output(pos, end, 507 *format); 508 } else { 509 --format; 510 } 511 continue; 512 } 513 514 if (qualifier == 'L') { 515 number = va_arg(args, u64); 516 if (type & ACPI_FORMAT_SIGN) { 517 number = (s64)number; 518 } 519 } else if (qualifier == 'l') { 520 number = va_arg(args, unsigned long); 521 if (type & ACPI_FORMAT_SIGN) { 522 number = (s32)number; 523 } 524 } else if (qualifier == 'h') { 525 number = (u16)va_arg(args, int); 526 if (type & ACPI_FORMAT_SIGN) { 527 number = (s16)number; 528 } 529 } else { 530 number = va_arg(args, unsigned int); 531 if (type & ACPI_FORMAT_SIGN) { 532 number = (signed int)number; 533 } 534 } 535 536 pos = acpi_ut_format_number(pos, end, number, base, 537 width, precision, type); 538 } 539 540 if (size > 0) { 541 if (pos < end) { 542 *pos = '\0'; 543 } else { 544 end[-1] = '\0'; 545 } 546 } 547 548 return ((int)ACPI_PTR_DIFF(pos, string)); 549 } 550 551 /******************************************************************************* 552 * 553 * FUNCTION: snprintf 554 * 555 * PARAMETERS: string - String with boundary 556 * size - Boundary of the string 557 * Format, ... - Standard printf format 558 * 559 * RETURN: Number of bytes actually written. 560 * 561 * DESCRIPTION: Formatted output to a string. 562 * 563 ******************************************************************************/ 564 565 int snprintf(char *string, acpi_size size, const char *format, ...) 566 { 567 va_list args; 568 int length; 569 570 va_start(args, format); 571 length = vsnprintf(string, size, format, args); 572 va_end(args); 573 574 return (length); 575 } 576 577 /******************************************************************************* 578 * 579 * FUNCTION: sprintf 580 * 581 * PARAMETERS: string - String with boundary 582 * Format, ... - Standard printf format 583 * 584 * RETURN: Number of bytes actually written. 585 * 586 * DESCRIPTION: Formatted output to a string. 587 * 588 ******************************************************************************/ 589 590 int sprintf(char *string, const char *format, ...) 591 { 592 va_list args; 593 int length; 594 595 va_start(args, format); 596 length = vsnprintf(string, ACPI_UINT32_MAX, format, args); 597 va_end(args); 598 599 return (length); 600 } 601 602 #ifdef ACPI_APPLICATION 603 /******************************************************************************* 604 * 605 * FUNCTION: vprintf 606 * 607 * PARAMETERS: format - Standard printf format 608 * args - Argument list 609 * 610 * RETURN: Number of bytes actually written. 611 * 612 * DESCRIPTION: Formatted output to stdout using argument list pointer. 613 * 614 ******************************************************************************/ 615 616 int vprintf(const char *format, va_list args) 617 { 618 acpi_cpu_flags flags; 619 int length; 620 621 flags = acpi_os_acquire_lock(acpi_gbl_print_lock); 622 length = vsnprintf(acpi_gbl_print_buffer, 623 sizeof(acpi_gbl_print_buffer), format, args); 624 625 (void)fwrite(acpi_gbl_print_buffer, length, 1, ACPI_FILE_OUT); 626 acpi_os_release_lock(acpi_gbl_print_lock, flags); 627 628 return (length); 629 } 630 631 /******************************************************************************* 632 * 633 * FUNCTION: printf 634 * 635 * PARAMETERS: Format, ... - Standard printf format 636 * 637 * RETURN: Number of bytes actually written. 638 * 639 * DESCRIPTION: Formatted output to stdout. 640 * 641 ******************************************************************************/ 642 643 int printf(const char *format, ...) 644 { 645 va_list args; 646 int length; 647 648 va_start(args, format); 649 length = vprintf(format, args); 650 va_end(args); 651 652 return (length); 653 } 654 655 /******************************************************************************* 656 * 657 * FUNCTION: vfprintf 658 * 659 * PARAMETERS: file - File descriptor 660 * format - Standard printf format 661 * args - Argument list 662 * 663 * RETURN: Number of bytes actually written. 664 * 665 * DESCRIPTION: Formatted output to a file using argument list pointer. 666 * 667 ******************************************************************************/ 668 669 int vfprintf(FILE * file, const char *format, va_list args) 670 { 671 acpi_cpu_flags flags; 672 int length; 673 674 flags = acpi_os_acquire_lock(acpi_gbl_print_lock); 675 length = vsnprintf(acpi_gbl_print_buffer, 676 sizeof(acpi_gbl_print_buffer), format, args); 677 678 (void)fwrite(acpi_gbl_print_buffer, length, 1, file); 679 acpi_os_release_lock(acpi_gbl_print_lock, flags); 680 681 return (length); 682 } 683 684 /******************************************************************************* 685 * 686 * FUNCTION: fprintf 687 * 688 * PARAMETERS: file - File descriptor 689 * Format, ... - Standard printf format 690 * 691 * RETURN: Number of bytes actually written. 692 * 693 * DESCRIPTION: Formatted output to a file. 694 * 695 ******************************************************************************/ 696 697 int fprintf(FILE * file, const char *format, ...) 698 { 699 va_list args; 700 int length; 701 702 va_start(args, format); 703 length = vfprintf(file, format, args); 704 va_end(args); 705 706 return (length); 707 } 708 #endif 709