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