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