1 /****************************************************************************** 2 * 3 * Module Name: utprint - Formatted printing routines 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2025, 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 MERCHANTABILITY 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.h" 45 #include "accommon.h" 46 47 #define _COMPONENT ACPI_UTILITIES 48 ACPI_MODULE_NAME ("utprint") 49 50 51 #define ACPI_FORMAT_SIGN 0x01 52 #define ACPI_FORMAT_SIGN_PLUS 0x02 53 #define ACPI_FORMAT_SIGN_PLUS_SPACE 0x04 54 #define ACPI_FORMAT_ZERO 0x08 55 #define ACPI_FORMAT_LEFT 0x10 56 #define ACPI_FORMAT_UPPER 0x20 57 #define ACPI_FORMAT_PREFIX 0x40 58 59 60 /* Local prototypes */ 61 62 static ACPI_SIZE 63 AcpiUtBoundStringLength ( 64 const char *String, 65 ACPI_SIZE Count); 66 67 static char * 68 AcpiUtBoundStringOutput ( 69 char *String, 70 const char *End, 71 char c); 72 73 static char * 74 AcpiUtFormatNumber ( 75 char *String, 76 char *End, 77 UINT64 Number, 78 UINT8 Base, 79 INT32 Width, 80 INT32 Precision, 81 UINT8 Type); 82 83 static char * 84 AcpiUtPutNumber ( 85 char *String, 86 UINT64 Number, 87 UINT8 Base, 88 BOOLEAN Upper); 89 90 91 /******************************************************************************* 92 * 93 * FUNCTION: AcpiUtBoundStringLength 94 * 95 * PARAMETERS: String - String with boundary 96 * Count - Boundary of the string 97 * 98 * RETURN: Length of the string. Less than or equal to Count. 99 * 100 * DESCRIPTION: Calculate the length of a string with boundary. 101 * 102 ******************************************************************************/ 103 104 static ACPI_SIZE 105 AcpiUtBoundStringLength ( 106 const char *String, 107 ACPI_SIZE Count) 108 { 109 UINT32 Length = 0; 110 111 112 while (*String && Count) 113 { 114 Length++; 115 String++; 116 Count--; 117 } 118 119 return (Length); 120 } 121 122 123 /******************************************************************************* 124 * 125 * FUNCTION: AcpiUtBoundStringOutput 126 * 127 * PARAMETERS: String - String with boundary 128 * End - Boundary of the string 129 * c - Character to be output to the string 130 * 131 * RETURN: Updated position for next valid character 132 * 133 * DESCRIPTION: Output a character into a string with boundary check. 134 * 135 ******************************************************************************/ 136 137 static char * 138 AcpiUtBoundStringOutput ( 139 char *String, 140 const char *End, 141 char c) 142 { 143 144 if (String < End) 145 { 146 *String = c; 147 } 148 149 ++String; 150 return (String); 151 } 152 153 154 /******************************************************************************* 155 * 156 * FUNCTION: AcpiUtPutNumber 157 * 158 * PARAMETERS: String - Buffer to hold reverse-ordered string 159 * Number - Integer to be converted 160 * Base - Base of the integer 161 * Upper - Whether or not using upper cased digits 162 * 163 * RETURN: Updated position for next valid character 164 * 165 * DESCRIPTION: Convert an integer into a string, note that, the string holds a 166 * reversed ordered number without the trailing zero. 167 * 168 ******************************************************************************/ 169 170 static char * 171 AcpiUtPutNumber ( 172 char *String, 173 UINT64 Number, 174 UINT8 Base, 175 BOOLEAN Upper) 176 { 177 const char *Digits; 178 UINT64 DigitIndex; 179 char *Pos; 180 181 182 Pos = String; 183 Digits = Upper ? AcpiGbl_UpperHexDigits : AcpiGbl_LowerHexDigits; 184 185 if (Number == 0) 186 { 187 *(Pos++) = '0'; 188 } 189 else 190 { 191 while (Number) 192 { 193 (void) AcpiUtDivide (Number, Base, &Number, &DigitIndex); 194 *(Pos++) = Digits[DigitIndex]; 195 } 196 } 197 198 /* *(Pos++) = '0'; */ 199 return (Pos); 200 } 201 202 203 /******************************************************************************* 204 * 205 * FUNCTION: AcpiUtScanNumber 206 * 207 * PARAMETERS: String - String buffer 208 * NumberPtr - Where the number is returned 209 * 210 * RETURN: Updated position for next valid character 211 * 212 * DESCRIPTION: Scan a string for a decimal integer. 213 * 214 ******************************************************************************/ 215 216 const char * 217 AcpiUtScanNumber ( 218 const char *String, 219 UINT64 *NumberPtr) 220 { 221 UINT64 Number = 0; 222 223 224 while (isdigit ((int) *String)) 225 { 226 AcpiUtShortMultiply (Number, 10, &Number); 227 Number += *(String++) - '0'; 228 } 229 230 *NumberPtr = Number; 231 return (String); 232 } 233 234 235 /******************************************************************************* 236 * 237 * FUNCTION: AcpiUtPrintNumber 238 * 239 * PARAMETERS: String - String buffer 240 * Number - The number to be converted 241 * 242 * RETURN: Updated position for next valid character 243 * 244 * DESCRIPTION: Print a decimal integer into a string. 245 * 246 ******************************************************************************/ 247 248 const char * 249 AcpiUtPrintNumber ( 250 char *String, 251 UINT64 Number) 252 { 253 char AsciiString[20]; 254 const char *Pos1; 255 char *Pos2; 256 257 258 Pos1 = AcpiUtPutNumber (AsciiString, Number, 10, FALSE); 259 Pos2 = String; 260 261 while (Pos1 != AsciiString) 262 { 263 *(Pos2++) = *(--Pos1); 264 } 265 266 *Pos2 = 0; 267 return (String); 268 } 269 270 271 /******************************************************************************* 272 * 273 * FUNCTION: AcpiUtFormatNumber 274 * 275 * PARAMETERS: String - String buffer with boundary 276 * End - Boundary of the string 277 * Number - The number to be converted 278 * Base - Base of the integer 279 * Width - Field width 280 * Precision - Precision of the integer 281 * Type - Special printing flags 282 * 283 * RETURN: Updated position for next valid character 284 * 285 * DESCRIPTION: Print an integer into a string with any base and any precision. 286 * 287 ******************************************************************************/ 288 289 static char * 290 AcpiUtFormatNumber ( 291 char *String, 292 char *End, 293 UINT64 Number, 294 UINT8 Base, 295 INT32 Width, 296 INT32 Precision, 297 UINT8 Type) 298 { 299 char *Pos; 300 char Sign; 301 char Zero; 302 BOOLEAN NeedPrefix; 303 BOOLEAN Upper; 304 INT32 i; 305 char ReversedString[66]; 306 307 308 /* Parameter validation */ 309 310 if (Base < 2 || Base > 16) 311 { 312 return (NULL); 313 } 314 315 if (Type & ACPI_FORMAT_LEFT) 316 { 317 Type &= ~ACPI_FORMAT_ZERO; 318 } 319 320 NeedPrefix = ((Type & ACPI_FORMAT_PREFIX) && Base != 10) ? TRUE : FALSE; 321 Upper = (Type & ACPI_FORMAT_UPPER) ? TRUE : FALSE; 322 Zero = (Type & ACPI_FORMAT_ZERO) ? '0' : ' '; 323 324 /* Calculate size according to sign and prefix */ 325 326 Sign = '\0'; 327 if (Type & ACPI_FORMAT_SIGN) 328 { 329 if ((INT64) Number < 0) 330 { 331 Sign = '-'; 332 Number = - (INT64) Number; 333 Width--; 334 } 335 else if (Type & ACPI_FORMAT_SIGN_PLUS) 336 { 337 Sign = '+'; 338 Width--; 339 } 340 else if (Type & ACPI_FORMAT_SIGN_PLUS_SPACE) 341 { 342 Sign = ' '; 343 Width--; 344 } 345 } 346 if (NeedPrefix) 347 { 348 Width--; 349 if (Base == 16) 350 { 351 Width--; 352 } 353 } 354 355 /* Generate full string in reverse order */ 356 357 Pos = AcpiUtPutNumber (ReversedString, Number, Base, Upper); 358 i = (INT32) ACPI_PTR_DIFF (Pos, ReversedString); 359 360 /* Printing 100 using %2d gives "100", not "00" */ 361 362 if (i > Precision) 363 { 364 Precision = i; 365 } 366 367 Width -= Precision; 368 369 /* Output the string */ 370 371 if (!(Type & (ACPI_FORMAT_ZERO | ACPI_FORMAT_LEFT))) 372 { 373 while (--Width >= 0) 374 { 375 String = AcpiUtBoundStringOutput (String, End, ' '); 376 } 377 } 378 if (Sign) 379 { 380 String = AcpiUtBoundStringOutput (String, End, Sign); 381 } 382 if (NeedPrefix) 383 { 384 String = AcpiUtBoundStringOutput (String, End, '0'); 385 if (Base == 16) 386 { 387 String = AcpiUtBoundStringOutput ( 388 String, End, Upper ? 'X' : 'x'); 389 } 390 } 391 if (!(Type & ACPI_FORMAT_LEFT)) 392 { 393 while (--Width >= 0) 394 { 395 String = AcpiUtBoundStringOutput (String, End, Zero); 396 } 397 } 398 399 while (i <= --Precision) 400 { 401 String = AcpiUtBoundStringOutput (String, End, '0'); 402 } 403 while (--i >= 0) 404 { 405 String = AcpiUtBoundStringOutput (String, End, 406 ReversedString[i]); 407 } 408 while (--Width >= 0) 409 { 410 String = AcpiUtBoundStringOutput (String, End, ' '); 411 } 412 413 return (String); 414 } 415 416 #undef sprintf 417 #undef snprintf 418 #undef vsnprintf 419 /******************************************************************************* 420 * 421 * FUNCTION: vsnprintf 422 * 423 * PARAMETERS: String - String with boundary 424 * Size - Boundary of the string 425 * Format - Standard printf format 426 * Args - Argument list 427 * 428 * RETURN: Number of bytes actually written. 429 * 430 * DESCRIPTION: Formatted output to a string using argument list pointer. 431 * 432 ******************************************************************************/ 433 434 int 435 vsnprintf ( 436 char *String, 437 ACPI_SIZE Size, 438 const char *Format, 439 va_list Args) 440 { 441 UINT8 Base; 442 UINT8 Type; 443 INT32 Width; 444 INT32 Precision; 445 char Qualifier; 446 UINT64 Number; 447 char *Pos; 448 char *End; 449 char c; 450 const char *s; 451 const void *p; 452 INT32 Length; 453 int i; 454 455 456 Pos = String; 457 458 Size = ACPI_MIN(Size, ACPI_PTR_DIFF(ACPI_MAX_PTR, String)); 459 End = String + Size; 460 461 for (; *Format; ++Format) 462 { 463 if (*Format != '%') 464 { 465 Pos = AcpiUtBoundStringOutput (Pos, End, *Format); 466 continue; 467 } 468 469 Type = 0; 470 Base = 10; 471 472 /* Process sign */ 473 474 do 475 { 476 ++Format; 477 if (*Format == '#') 478 { 479 Type |= ACPI_FORMAT_PREFIX; 480 } 481 else if (*Format == '0') 482 { 483 Type |= ACPI_FORMAT_ZERO; 484 } 485 else if (*Format == '+') 486 { 487 Type |= ACPI_FORMAT_SIGN_PLUS; 488 } 489 else if (*Format == ' ') 490 { 491 Type |= ACPI_FORMAT_SIGN_PLUS_SPACE; 492 } 493 else if (*Format == '-') 494 { 495 Type |= ACPI_FORMAT_LEFT; 496 } 497 else 498 { 499 break; 500 } 501 502 } while (1); 503 504 /* Process width */ 505 506 Width = -1; 507 if (isdigit ((int) *Format)) 508 { 509 Format = AcpiUtScanNumber (Format, &Number); 510 Width = (INT32) Number; 511 } 512 else if (*Format == '*') 513 { 514 ++Format; 515 Width = va_arg (Args, int); 516 if (Width < 0) 517 { 518 Width = -Width; 519 Type |= ACPI_FORMAT_LEFT; 520 } 521 } 522 523 /* Process precision */ 524 525 Precision = -1; 526 if (*Format == '.') 527 { 528 ++Format; 529 if (isdigit ((int) *Format)) 530 { 531 Format = AcpiUtScanNumber (Format, &Number); 532 Precision = (INT32) Number; 533 } 534 else if (*Format == '*') 535 { 536 ++Format; 537 Precision = va_arg (Args, int); 538 } 539 540 if (Precision < 0) 541 { 542 Precision = 0; 543 } 544 } 545 546 /* Process qualifier */ 547 548 Qualifier = -1; 549 if (*Format == 'h' || *Format == 'l' || *Format == 'L') 550 { 551 Qualifier = *Format; 552 ++Format; 553 554 if (Qualifier == 'l' && *Format == 'l') 555 { 556 Qualifier = 'L'; 557 ++Format; 558 } 559 } 560 561 switch (*Format) 562 { 563 case '%': 564 565 Pos = AcpiUtBoundStringOutput (Pos, End, '%'); 566 continue; 567 568 case 'c': 569 570 if (!(Type & ACPI_FORMAT_LEFT)) 571 { 572 while (--Width > 0) 573 { 574 Pos = AcpiUtBoundStringOutput (Pos, End, ' '); 575 } 576 } 577 578 c = (char) va_arg (Args, int); 579 Pos = AcpiUtBoundStringOutput (Pos, End, c); 580 581 while (--Width > 0) 582 { 583 Pos = AcpiUtBoundStringOutput (Pos, End, ' '); 584 } 585 continue; 586 587 case 's': 588 589 s = va_arg (Args, char *); 590 if (!s) 591 { 592 s = "<NULL>"; 593 } 594 Length = (INT32) AcpiUtBoundStringLength (s, Precision); 595 if (!(Type & ACPI_FORMAT_LEFT)) 596 { 597 while (Length < Width--) 598 { 599 Pos = AcpiUtBoundStringOutput (Pos, End, ' '); 600 } 601 } 602 603 for (i = 0; i < Length; ++i) 604 { 605 Pos = AcpiUtBoundStringOutput (Pos, End, *s); 606 ++s; 607 } 608 609 while (Length < Width--) 610 { 611 Pos = AcpiUtBoundStringOutput (Pos, End, ' '); 612 } 613 continue; 614 615 case 'o': 616 617 Base = 8; 618 break; 619 620 case 'X': 621 622 Type |= ACPI_FORMAT_UPPER; 623 ACPI_FALLTHROUGH; 624 625 case 'x': 626 627 Base = 16; 628 break; 629 630 case 'd': 631 case 'i': 632 633 Type |= ACPI_FORMAT_SIGN; 634 635 case 'u': 636 637 break; 638 639 case 'p': 640 641 if (Width == -1) 642 { 643 Width = 2 * sizeof (void *); 644 Type |= ACPI_FORMAT_ZERO; 645 } 646 647 p = va_arg (Args, void *); 648 Pos = AcpiUtFormatNumber ( 649 Pos, End, ACPI_TO_INTEGER (p), 16, Width, Precision, Type); 650 continue; 651 652 default: 653 654 Pos = AcpiUtBoundStringOutput (Pos, End, '%'); 655 if (*Format) 656 { 657 Pos = AcpiUtBoundStringOutput (Pos, End, *Format); 658 } 659 else 660 { 661 --Format; 662 } 663 continue; 664 } 665 666 if (Qualifier == 'L') 667 { 668 Number = va_arg (Args, UINT64); 669 if (Type & ACPI_FORMAT_SIGN) 670 { 671 Number = (INT64) Number; 672 } 673 } 674 else if (Qualifier == 'l') 675 { 676 Number = va_arg (Args, unsigned long); 677 if (Type & ACPI_FORMAT_SIGN) 678 { 679 Number = (INT32) Number; 680 } 681 } 682 else if (Qualifier == 'h') 683 { 684 Number = (UINT16) va_arg (Args, int); 685 if (Type & ACPI_FORMAT_SIGN) 686 { 687 Number = (INT16) Number; 688 } 689 } 690 else 691 { 692 Number = va_arg (Args, unsigned int); 693 if (Type & ACPI_FORMAT_SIGN) 694 { 695 Number = (signed int) Number; 696 } 697 } 698 699 Pos = AcpiUtFormatNumber (Pos, End, Number, Base, 700 Width, Precision, Type); 701 } 702 703 if (Size > 0) 704 { 705 if (Pos < End) 706 { 707 *Pos = '\0'; 708 } 709 else 710 { 711 End[-1] = '\0'; 712 } 713 } 714 715 return ((int) ACPI_PTR_DIFF (Pos, String)); 716 } 717 718 719 /******************************************************************************* 720 * 721 * FUNCTION: snprintf 722 * 723 * PARAMETERS: String - String with boundary 724 * Size - Boundary of the string 725 * Format, ... - Standard printf format 726 * 727 * RETURN: Number of bytes actually written. 728 * 729 * DESCRIPTION: Formatted output to a string. 730 * 731 ******************************************************************************/ 732 733 int 734 snprintf ( 735 char *String, 736 ACPI_SIZE Size, 737 const char *Format, 738 ...) 739 { 740 va_list Args; 741 int Length; 742 743 744 va_start (Args, Format); 745 Length = vsnprintf (String, Size, Format, Args); 746 va_end (Args); 747 748 return (Length); 749 } 750 751 752 /******************************************************************************* 753 * 754 * FUNCTION: sprintf 755 * 756 * PARAMETERS: String - String with boundary 757 * Format, ... - Standard printf format 758 * 759 * RETURN: Number of bytes actually written. 760 * 761 * DESCRIPTION: Formatted output to a string. 762 * 763 ******************************************************************************/ 764 765 int 766 sprintf ( 767 char *String, 768 const char *Format, 769 ...) 770 { 771 va_list Args; 772 int Length; 773 774 775 va_start (Args, Format); 776 Length = vsnprintf (String, ACPI_UINT32_MAX, Format, Args); 777 va_end (Args); 778 779 return (Length); 780 } 781 782 783 #ifdef ACPI_APPLICATION 784 /******************************************************************************* 785 * 786 * FUNCTION: vprintf 787 * 788 * PARAMETERS: Format - Standard printf format 789 * Args - Argument list 790 * 791 * RETURN: Number of bytes actually written. 792 * 793 * DESCRIPTION: Formatted output to stdout using argument list pointer. 794 * 795 ******************************************************************************/ 796 797 int 798 vprintf ( 799 const char *Format, 800 va_list Args) 801 { 802 ACPI_CPU_FLAGS Flags; 803 int Length; 804 805 806 Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock); 807 Length = vsnprintf (AcpiGbl_PrintBuffer, 808 sizeof (AcpiGbl_PrintBuffer), Format, Args); 809 810 (void) fwrite (AcpiGbl_PrintBuffer, Length, 1, ACPI_FILE_OUT); 811 AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags); 812 813 return (Length); 814 } 815 816 817 /******************************************************************************* 818 * 819 * FUNCTION: printf 820 * 821 * PARAMETERS: Format, ... - Standard printf format 822 * 823 * RETURN: Number of bytes actually written. 824 * 825 * DESCRIPTION: Formatted output to stdout. 826 * 827 ******************************************************************************/ 828 829 int 830 printf ( 831 const char *Format, 832 ...) 833 { 834 va_list Args; 835 int Length; 836 837 838 va_start (Args, Format); 839 Length = vprintf (Format, Args); 840 va_end (Args); 841 842 return (Length); 843 } 844 845 846 /******************************************************************************* 847 * 848 * FUNCTION: vfprintf 849 * 850 * PARAMETERS: File - File descriptor 851 * Format - Standard printf format 852 * Args - Argument list 853 * 854 * RETURN: Number of bytes actually written. 855 * 856 * DESCRIPTION: Formatted output to a file using argument list pointer. 857 * 858 ******************************************************************************/ 859 860 int 861 vfprintf ( 862 FILE *File, 863 const char *Format, 864 va_list Args) 865 { 866 ACPI_CPU_FLAGS Flags; 867 int Length; 868 869 870 Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock); 871 Length = vsnprintf (AcpiGbl_PrintBuffer, 872 sizeof (AcpiGbl_PrintBuffer), Format, Args); 873 874 (void) fwrite (AcpiGbl_PrintBuffer, Length, 1, File); 875 AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags); 876 877 return (Length); 878 } 879 880 881 /******************************************************************************* 882 * 883 * FUNCTION: fprintf 884 * 885 * PARAMETERS: File - File descriptor 886 * Format, ... - Standard printf format 887 * 888 * RETURN: Number of bytes actually written. 889 * 890 * DESCRIPTION: Formatted output to a file. 891 * 892 ******************************************************************************/ 893 894 int 895 fprintf ( 896 FILE *File, 897 const char *Format, 898 ...) 899 { 900 va_list Args; 901 int Length; 902 903 904 va_start (Args, Format); 905 Length = vfprintf (File, Format, Args); 906 va_end (Args); 907 908 return (Length); 909 } 910 #endif 911