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