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