1 /****************************************************************************** 2 * 3 * Module Name: utprint - Formatted printing routines 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2016, 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 /* Module globals */ 92 93 static const char AcpiGbl_LowerHexDigits[] = "0123456789abcdef"; 94 static const char AcpiGbl_UpperHexDigits[] = "0123456789ABCDEF"; 95 96 97 /******************************************************************************* 98 * 99 * FUNCTION: AcpiUtBoundStringLength 100 * 101 * PARAMETERS: String - String with boundary 102 * Count - Boundary of the string 103 * 104 * RETURN: Length of the string. Less than or equal to Count. 105 * 106 * DESCRIPTION: Calculate the length of a string with boundary. 107 * 108 ******************************************************************************/ 109 110 static ACPI_SIZE 111 AcpiUtBoundStringLength ( 112 const char *String, 113 ACPI_SIZE Count) 114 { 115 UINT32 Length = 0; 116 117 118 while (*String && Count) 119 { 120 Length++; 121 String++; 122 Count--; 123 } 124 125 return (Length); 126 } 127 128 129 /******************************************************************************* 130 * 131 * FUNCTION: AcpiUtBoundStringOutput 132 * 133 * PARAMETERS: String - String with boundary 134 * End - Boundary of the string 135 * c - Character to be output to the string 136 * 137 * RETURN: Updated position for next valid character 138 * 139 * DESCRIPTION: Output a character into a string with boundary check. 140 * 141 ******************************************************************************/ 142 143 static char * 144 AcpiUtBoundStringOutput ( 145 char *String, 146 const char *End, 147 char c) 148 { 149 150 if (String < End) 151 { 152 *String = c; 153 } 154 155 ++String; 156 return (String); 157 } 158 159 160 /******************************************************************************* 161 * 162 * FUNCTION: AcpiUtPutNumber 163 * 164 * PARAMETERS: String - Buffer to hold reverse-ordered string 165 * Number - Integer to be converted 166 * Base - Base of the integer 167 * Upper - Whether or not using upper cased digits 168 * 169 * RETURN: Updated position for next valid character 170 * 171 * DESCRIPTION: Convert an integer into a string, note that, the string holds a 172 * reversed ordered number without the trailing zero. 173 * 174 ******************************************************************************/ 175 176 static char * 177 AcpiUtPutNumber ( 178 char *String, 179 UINT64 Number, 180 UINT8 Base, 181 BOOLEAN Upper) 182 { 183 const char *Digits; 184 UINT64 DigitIndex; 185 char *Pos; 186 187 188 Pos = String; 189 Digits = Upper ? AcpiGbl_UpperHexDigits : AcpiGbl_LowerHexDigits; 190 191 if (Number == 0) 192 { 193 *(Pos++) = '0'; 194 } 195 else 196 { 197 while (Number) 198 { 199 (void) AcpiUtDivide (Number, Base, &Number, &DigitIndex); 200 *(Pos++) = Digits[DigitIndex]; 201 } 202 } 203 204 /* *(Pos++) = '0'; */ 205 return (Pos); 206 } 207 208 209 /******************************************************************************* 210 * 211 * FUNCTION: AcpiUtScanNumber 212 * 213 * PARAMETERS: String - String buffer 214 * NumberPtr - Where the number is returned 215 * 216 * RETURN: Updated position for next valid character 217 * 218 * DESCRIPTION: Scan a string for a decimal integer. 219 * 220 ******************************************************************************/ 221 222 const char * 223 AcpiUtScanNumber ( 224 const char *String, 225 UINT64 *NumberPtr) 226 { 227 UINT64 Number = 0; 228 229 230 while (isdigit ((int) *String)) 231 { 232 Number *= 10; 233 Number += *(String++) - '0'; 234 } 235 236 *NumberPtr = Number; 237 return (String); 238 } 239 240 241 /******************************************************************************* 242 * 243 * FUNCTION: AcpiUtPrintNumber 244 * 245 * PARAMETERS: String - String buffer 246 * Number - The number to be converted 247 * 248 * RETURN: Updated position for next valid character 249 * 250 * DESCRIPTION: Print a decimal integer into a string. 251 * 252 ******************************************************************************/ 253 254 const char * 255 AcpiUtPrintNumber ( 256 char *String, 257 UINT64 Number) 258 { 259 char AsciiString[20]; 260 const char *Pos1; 261 char *Pos2; 262 263 264 Pos1 = AcpiUtPutNumber (AsciiString, Number, 10, FALSE); 265 Pos2 = String; 266 267 while (Pos1 != AsciiString) 268 { 269 *(Pos2++) = *(--Pos1); 270 } 271 272 *Pos2 = 0; 273 return (String); 274 } 275 276 277 /******************************************************************************* 278 * 279 * FUNCTION: AcpiUtFormatNumber 280 * 281 * PARAMETERS: String - String buffer with boundary 282 * End - Boundary of the string 283 * Number - The number to be converted 284 * Base - Base of the integer 285 * Width - Field width 286 * Precision - Precision of the integer 287 * Type - Special printing flags 288 * 289 * RETURN: Updated position for next valid character 290 * 291 * DESCRIPTION: Print an integer into a string with any base and any precision. 292 * 293 ******************************************************************************/ 294 295 static char * 296 AcpiUtFormatNumber ( 297 char *String, 298 char *End, 299 UINT64 Number, 300 UINT8 Base, 301 INT32 Width, 302 INT32 Precision, 303 UINT8 Type) 304 { 305 char *Pos; 306 char Sign; 307 char Zero; 308 BOOLEAN NeedPrefix; 309 BOOLEAN Upper; 310 INT32 i; 311 char ReversedString[66]; 312 313 314 /* Parameter validation */ 315 316 if (Base < 2 || Base > 16) 317 { 318 return (NULL); 319 } 320 321 if (Type & ACPI_FORMAT_LEFT) 322 { 323 Type &= ~ACPI_FORMAT_ZERO; 324 } 325 326 NeedPrefix = ((Type & ACPI_FORMAT_PREFIX) && Base != 10) ? TRUE : FALSE; 327 Upper = (Type & ACPI_FORMAT_UPPER) ? TRUE : FALSE; 328 Zero = (Type & ACPI_FORMAT_ZERO) ? '0' : ' '; 329 330 /* Calculate size according to sign and prefix */ 331 332 Sign = '\0'; 333 if (Type & ACPI_FORMAT_SIGN) 334 { 335 if ((INT64) Number < 0) 336 { 337 Sign = '-'; 338 Number = - (INT64) Number; 339 Width--; 340 } 341 else if (Type & ACPI_FORMAT_SIGN_PLUS) 342 { 343 Sign = '+'; 344 Width--; 345 } 346 else if (Type & ACPI_FORMAT_SIGN_PLUS_SPACE) 347 { 348 Sign = ' '; 349 Width--; 350 } 351 } 352 if (NeedPrefix) 353 { 354 Width--; 355 if (Base == 16) 356 { 357 Width--; 358 } 359 } 360 361 /* Generate full string in reverse order */ 362 363 Pos = AcpiUtPutNumber (ReversedString, Number, Base, Upper); 364 i = ACPI_PTR_DIFF (Pos, ReversedString); 365 366 /* Printing 100 using %2d gives "100", not "00" */ 367 368 if (i > Precision) 369 { 370 Precision = i; 371 } 372 373 Width -= Precision; 374 375 /* Output the string */ 376 377 if (!(Type & (ACPI_FORMAT_ZERO | ACPI_FORMAT_LEFT))) 378 { 379 while (--Width >= 0) 380 { 381 String = AcpiUtBoundStringOutput (String, End, ' '); 382 } 383 } 384 if (Sign) 385 { 386 String = AcpiUtBoundStringOutput (String, End, Sign); 387 } 388 if (NeedPrefix) 389 { 390 String = AcpiUtBoundStringOutput (String, End, '0'); 391 if (Base == 16) 392 { 393 String = AcpiUtBoundStringOutput ( 394 String, End, Upper ? 'X' : 'x'); 395 } 396 } 397 if (!(Type & ACPI_FORMAT_LEFT)) 398 { 399 while (--Width >= 0) 400 { 401 String = AcpiUtBoundStringOutput (String, End, Zero); 402 } 403 } 404 405 while (i <= --Precision) 406 { 407 String = AcpiUtBoundStringOutput (String, End, '0'); 408 } 409 while (--i >= 0) 410 { 411 String = AcpiUtBoundStringOutput (String, End, 412 ReversedString[i]); 413 } 414 while (--Width >= 0) 415 { 416 String = AcpiUtBoundStringOutput (String, End, ' '); 417 } 418 419 return (String); 420 } 421 422 423 /******************************************************************************* 424 * 425 * FUNCTION: AcpiUtVsnprintf 426 * 427 * PARAMETERS: String - String with boundary 428 * Size - Boundary of the string 429 * Format - Standard printf format 430 * Args - Argument list 431 * 432 * RETURN: Number of bytes actually written. 433 * 434 * DESCRIPTION: Formatted output to a string using argument list pointer. 435 * 436 ******************************************************************************/ 437 438 int 439 AcpiUtVsnprintf ( 440 char *String, 441 ACPI_SIZE Size, 442 const char *Format, 443 va_list Args) 444 { 445 UINT8 Base; 446 UINT8 Type; 447 INT32 Width; 448 INT32 Precision; 449 char Qualifier; 450 UINT64 Number; 451 char *Pos; 452 char *End; 453 char c; 454 const char *s; 455 const void *p; 456 INT32 Length; 457 int i; 458 459 460 Pos = String; 461 End = String + Size; 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 = 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 626 case 'x': 627 628 Base = 16; 629 break; 630 631 case 'd': 632 case 'i': 633 634 Type |= ACPI_FORMAT_SIGN; 635 636 case 'u': 637 638 break; 639 640 case 'p': 641 642 if (Width == -1) 643 { 644 Width = 2 * sizeof (void *); 645 Type |= ACPI_FORMAT_ZERO; 646 } 647 648 p = va_arg (Args, void *); 649 Pos = AcpiUtFormatNumber ( 650 Pos, End, ACPI_TO_INTEGER (p), 16, Width, Precision, Type); 651 continue; 652 653 default: 654 655 Pos = AcpiUtBoundStringOutput (Pos, End, '%'); 656 if (*Format) 657 { 658 Pos = AcpiUtBoundStringOutput (Pos, End, *Format); 659 } 660 else 661 { 662 --Format; 663 } 664 continue; 665 } 666 667 if (Qualifier == 'L') 668 { 669 Number = va_arg (Args, UINT64); 670 if (Type & ACPI_FORMAT_SIGN) 671 { 672 Number = (INT64) Number; 673 } 674 } 675 else if (Qualifier == 'l') 676 { 677 Number = va_arg (Args, unsigned long); 678 if (Type & ACPI_FORMAT_SIGN) 679 { 680 Number = (INT32) Number; 681 } 682 } 683 else if (Qualifier == 'h') 684 { 685 Number = (UINT16) va_arg (Args, int); 686 if (Type & ACPI_FORMAT_SIGN) 687 { 688 Number = (INT16) Number; 689 } 690 } 691 else 692 { 693 Number = va_arg (Args, unsigned int); 694 if (Type & ACPI_FORMAT_SIGN) 695 { 696 Number = (signed int) Number; 697 } 698 } 699 700 Pos = AcpiUtFormatNumber (Pos, End, Number, Base, 701 Width, Precision, Type); 702 } 703 704 if (Size > 0) 705 { 706 if (Pos < End) 707 { 708 *Pos = '\0'; 709 } 710 else 711 { 712 End[-1] = '\0'; 713 } 714 } 715 716 return (ACPI_PTR_DIFF (Pos, String)); 717 } 718 719 720 /******************************************************************************* 721 * 722 * FUNCTION: AcpiUtSnprintf 723 * 724 * PARAMETERS: String - String with boundary 725 * Size - Boundary of the string 726 * Format, ... - Standard printf format 727 * 728 * RETURN: Number of bytes actually written. 729 * 730 * DESCRIPTION: Formatted output to a string. 731 * 732 ******************************************************************************/ 733 734 int 735 AcpiUtSnprintf ( 736 char *String, 737 ACPI_SIZE Size, 738 const char *Format, 739 ...) 740 { 741 va_list Args; 742 int Length; 743 744 745 va_start (Args, Format); 746 Length = AcpiUtVsnprintf (String, Size, Format, Args); 747 va_end (Args); 748 749 return (Length); 750 } 751 752 753 #ifdef ACPI_APPLICATION 754 /******************************************************************************* 755 * 756 * FUNCTION: AcpiUtFileVprintf 757 * 758 * PARAMETERS: File - File descriptor 759 * Format - Standard printf format 760 * Args - Argument list 761 * 762 * RETURN: Number of bytes actually written. 763 * 764 * DESCRIPTION: Formatted output to a file using argument list pointer. 765 * 766 ******************************************************************************/ 767 768 int 769 AcpiUtFileVprintf ( 770 ACPI_FILE File, 771 const char *Format, 772 va_list Args) 773 { 774 ACPI_CPU_FLAGS Flags; 775 int Length; 776 777 778 Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock); 779 Length = AcpiUtVsnprintf (AcpiGbl_PrintBuffer, 780 sizeof (AcpiGbl_PrintBuffer), Format, Args); 781 782 (void) AcpiOsWriteFile (File, AcpiGbl_PrintBuffer, Length, 1); 783 AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags); 784 785 return (Length); 786 } 787 788 789 /******************************************************************************* 790 * 791 * FUNCTION: AcpiUtFilePrintf 792 * 793 * PARAMETERS: File - File descriptor 794 * Format, ... - Standard printf format 795 * 796 * RETURN: Number of bytes actually written. 797 * 798 * DESCRIPTION: Formatted output to a file. 799 * 800 ******************************************************************************/ 801 802 int 803 AcpiUtFilePrintf ( 804 ACPI_FILE File, 805 const char *Format, 806 ...) 807 { 808 va_list Args; 809 int Length; 810 811 812 va_start (Args, Format); 813 Length = AcpiUtFileVprintf (File, Format, Args); 814 va_end (Args); 815 816 return (Length); 817 } 818 #endif 819