1 /****************************************************************************** 2 * 3 * Module Name: utprint - Formatted printing routines 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2021, 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 459 if (Size != ACPI_UINT32_MAX) { 460 End = String + Size; 461 } else { 462 End = ACPI_CAST_PTR(char, ACPI_UINT32_MAX); 463 } 464 465 for (; *Format; ++Format) 466 { 467 if (*Format != '%') 468 { 469 Pos = AcpiUtBoundStringOutput (Pos, End, *Format); 470 continue; 471 } 472 473 Type = 0; 474 Base = 10; 475 476 /* Process sign */ 477 478 do 479 { 480 ++Format; 481 if (*Format == '#') 482 { 483 Type |= ACPI_FORMAT_PREFIX; 484 } 485 else if (*Format == '0') 486 { 487 Type |= ACPI_FORMAT_ZERO; 488 } 489 else if (*Format == '+') 490 { 491 Type |= ACPI_FORMAT_SIGN_PLUS; 492 } 493 else if (*Format == ' ') 494 { 495 Type |= ACPI_FORMAT_SIGN_PLUS_SPACE; 496 } 497 else if (*Format == '-') 498 { 499 Type |= ACPI_FORMAT_LEFT; 500 } 501 else 502 { 503 break; 504 } 505 506 } while (1); 507 508 /* Process width */ 509 510 Width = -1; 511 if (isdigit ((int) *Format)) 512 { 513 Format = AcpiUtScanNumber (Format, &Number); 514 Width = (INT32) Number; 515 } 516 else if (*Format == '*') 517 { 518 ++Format; 519 Width = va_arg (Args, int); 520 if (Width < 0) 521 { 522 Width = -Width; 523 Type |= ACPI_FORMAT_LEFT; 524 } 525 } 526 527 /* Process precision */ 528 529 Precision = -1; 530 if (*Format == '.') 531 { 532 ++Format; 533 if (isdigit ((int) *Format)) 534 { 535 Format = AcpiUtScanNumber (Format, &Number); 536 Precision = (INT32) Number; 537 } 538 else if (*Format == '*') 539 { 540 ++Format; 541 Precision = va_arg (Args, int); 542 } 543 544 if (Precision < 0) 545 { 546 Precision = 0; 547 } 548 } 549 550 /* Process qualifier */ 551 552 Qualifier = -1; 553 if (*Format == 'h' || *Format == 'l' || *Format == 'L') 554 { 555 Qualifier = *Format; 556 ++Format; 557 558 if (Qualifier == 'l' && *Format == 'l') 559 { 560 Qualifier = 'L'; 561 ++Format; 562 } 563 } 564 565 switch (*Format) 566 { 567 case '%': 568 569 Pos = AcpiUtBoundStringOutput (Pos, End, '%'); 570 continue; 571 572 case 'c': 573 574 if (!(Type & ACPI_FORMAT_LEFT)) 575 { 576 while (--Width > 0) 577 { 578 Pos = AcpiUtBoundStringOutput (Pos, End, ' '); 579 } 580 } 581 582 c = (char) va_arg (Args, int); 583 Pos = AcpiUtBoundStringOutput (Pos, End, c); 584 585 while (--Width > 0) 586 { 587 Pos = AcpiUtBoundStringOutput (Pos, End, ' '); 588 } 589 continue; 590 591 case 's': 592 593 s = va_arg (Args, char *); 594 if (!s) 595 { 596 s = "<NULL>"; 597 } 598 Length = (INT32) AcpiUtBoundStringLength (s, Precision); 599 if (!(Type & ACPI_FORMAT_LEFT)) 600 { 601 while (Length < Width--) 602 { 603 Pos = AcpiUtBoundStringOutput (Pos, End, ' '); 604 } 605 } 606 607 for (i = 0; i < Length; ++i) 608 { 609 Pos = AcpiUtBoundStringOutput (Pos, End, *s); 610 ++s; 611 } 612 613 while (Length < Width--) 614 { 615 Pos = AcpiUtBoundStringOutput (Pos, End, ' '); 616 } 617 continue; 618 619 case 'o': 620 621 Base = 8; 622 break; 623 624 case 'X': 625 626 Type |= ACPI_FORMAT_UPPER; 627 /* FALLTHROUGH */ 628 629 case 'x': 630 631 Base = 16; 632 break; 633 634 case 'd': 635 case 'i': 636 637 Type |= ACPI_FORMAT_SIGN; 638 639 case 'u': 640 641 break; 642 643 case 'p': 644 645 if (Width == -1) 646 { 647 Width = 2 * sizeof (void *); 648 Type |= ACPI_FORMAT_ZERO; 649 } 650 651 p = va_arg (Args, void *); 652 Pos = AcpiUtFormatNumber ( 653 Pos, End, ACPI_TO_INTEGER (p), 16, Width, Precision, Type); 654 continue; 655 656 default: 657 658 Pos = AcpiUtBoundStringOutput (Pos, End, '%'); 659 if (*Format) 660 { 661 Pos = AcpiUtBoundStringOutput (Pos, End, *Format); 662 } 663 else 664 { 665 --Format; 666 } 667 continue; 668 } 669 670 if (Qualifier == 'L') 671 { 672 Number = va_arg (Args, UINT64); 673 if (Type & ACPI_FORMAT_SIGN) 674 { 675 Number = (INT64) Number; 676 } 677 } 678 else if (Qualifier == 'l') 679 { 680 Number = va_arg (Args, unsigned long); 681 if (Type & ACPI_FORMAT_SIGN) 682 { 683 Number = (INT32) Number; 684 } 685 } 686 else if (Qualifier == 'h') 687 { 688 Number = (UINT16) va_arg (Args, int); 689 if (Type & ACPI_FORMAT_SIGN) 690 { 691 Number = (INT16) Number; 692 } 693 } 694 else 695 { 696 Number = va_arg (Args, unsigned int); 697 if (Type & ACPI_FORMAT_SIGN) 698 { 699 Number = (signed int) Number; 700 } 701 } 702 703 Pos = AcpiUtFormatNumber (Pos, End, Number, Base, 704 Width, Precision, Type); 705 } 706 707 if (Size > 0) 708 { 709 if (Pos < End) 710 { 711 *Pos = '\0'; 712 } 713 else 714 { 715 End[-1] = '\0'; 716 } 717 } 718 719 return ((int) ACPI_PTR_DIFF (Pos, String)); 720 } 721 722 723 /******************************************************************************* 724 * 725 * FUNCTION: snprintf 726 * 727 * PARAMETERS: String - String with boundary 728 * Size - Boundary of the string 729 * Format, ... - Standard printf format 730 * 731 * RETURN: Number of bytes actually written. 732 * 733 * DESCRIPTION: Formatted output to a string. 734 * 735 ******************************************************************************/ 736 737 int 738 snprintf ( 739 char *String, 740 ACPI_SIZE Size, 741 const char *Format, 742 ...) 743 { 744 va_list Args; 745 int Length; 746 747 748 va_start (Args, Format); 749 Length = vsnprintf (String, Size, Format, Args); 750 va_end (Args); 751 752 return (Length); 753 } 754 755 756 /******************************************************************************* 757 * 758 * FUNCTION: sprintf 759 * 760 * PARAMETERS: String - String with boundary 761 * Format, ... - Standard printf format 762 * 763 * RETURN: Number of bytes actually written. 764 * 765 * DESCRIPTION: Formatted output to a string. 766 * 767 ******************************************************************************/ 768 769 int 770 sprintf ( 771 char *String, 772 const char *Format, 773 ...) 774 { 775 va_list Args; 776 int Length; 777 778 779 va_start (Args, Format); 780 Length = vsnprintf (String, ACPI_UINT32_MAX, Format, Args); 781 va_end (Args); 782 783 return (Length); 784 } 785 786 787 #ifdef ACPI_APPLICATION 788 /******************************************************************************* 789 * 790 * FUNCTION: vprintf 791 * 792 * PARAMETERS: Format - Standard printf format 793 * Args - Argument list 794 * 795 * RETURN: Number of bytes actually written. 796 * 797 * DESCRIPTION: Formatted output to stdout using argument list pointer. 798 * 799 ******************************************************************************/ 800 801 int 802 vprintf ( 803 const char *Format, 804 va_list Args) 805 { 806 ACPI_CPU_FLAGS Flags; 807 int Length; 808 809 810 Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock); 811 Length = vsnprintf (AcpiGbl_PrintBuffer, 812 sizeof (AcpiGbl_PrintBuffer), Format, Args); 813 814 (void) fwrite (AcpiGbl_PrintBuffer, Length, 1, ACPI_FILE_OUT); 815 AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags); 816 817 return (Length); 818 } 819 820 821 /******************************************************************************* 822 * 823 * FUNCTION: printf 824 * 825 * PARAMETERS: Format, ... - Standard printf format 826 * 827 * RETURN: Number of bytes actually written. 828 * 829 * DESCRIPTION: Formatted output to stdout. 830 * 831 ******************************************************************************/ 832 833 int 834 printf ( 835 const char *Format, 836 ...) 837 { 838 va_list Args; 839 int Length; 840 841 842 va_start (Args, Format); 843 Length = vprintf (Format, Args); 844 va_end (Args); 845 846 return (Length); 847 } 848 849 850 /******************************************************************************* 851 * 852 * FUNCTION: vfprintf 853 * 854 * PARAMETERS: File - File descriptor 855 * Format - Standard printf format 856 * Args - Argument list 857 * 858 * RETURN: Number of bytes actually written. 859 * 860 * DESCRIPTION: Formatted output to a file using argument list pointer. 861 * 862 ******************************************************************************/ 863 864 int 865 vfprintf ( 866 FILE *File, 867 const char *Format, 868 va_list Args) 869 { 870 ACPI_CPU_FLAGS Flags; 871 int Length; 872 873 874 Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock); 875 Length = vsnprintf (AcpiGbl_PrintBuffer, 876 sizeof (AcpiGbl_PrintBuffer), Format, Args); 877 878 (void) fwrite (AcpiGbl_PrintBuffer, Length, 1, File); 879 AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags); 880 881 return (Length); 882 } 883 884 885 /******************************************************************************* 886 * 887 * FUNCTION: fprintf 888 * 889 * PARAMETERS: File - File descriptor 890 * Format, ... - Standard printf format 891 * 892 * RETURN: Number of bytes actually written. 893 * 894 * DESCRIPTION: Formatted output to a file. 895 * 896 ******************************************************************************/ 897 898 int 899 fprintf ( 900 FILE *File, 901 const char *Format, 902 ...) 903 { 904 va_list Args; 905 int Length; 906 907 908 va_start (Args, Format); 909 Length = vfprintf (File, Format, Args); 910 va_end (Args); 911 912 return (Length); 913 } 914 #endif 915