1 /****************************************************************************** 2 * 3 * Module Name: utprint - Formatted printing routines 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2015, 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 (String, End, 394 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 } while (1); 504 505 /* Process width */ 506 507 Width = -1; 508 if (isdigit ((int) *Format)) 509 { 510 Format = AcpiUtScanNumber (Format, &Number); 511 Width = (INT32) Number; 512 } 513 else if (*Format == '*') 514 { 515 ++Format; 516 Width = va_arg (Args, int); 517 if (Width < 0) 518 { 519 Width = -Width; 520 Type |= ACPI_FORMAT_LEFT; 521 } 522 } 523 524 /* Process precision */ 525 526 Precision = -1; 527 if (*Format == '.') 528 { 529 ++Format; 530 if (isdigit ((int) *Format)) 531 { 532 Format = AcpiUtScanNumber (Format, &Number); 533 Precision = (INT32) Number; 534 } 535 else if (*Format == '*') 536 { 537 ++Format; 538 Precision = va_arg (Args, int); 539 } 540 if (Precision < 0) 541 { 542 Precision = 0; 543 } 544 } 545 546 /* Process qualifier */ 547 548 Qualifier = -1; 549 if (*Format == 'h' || *Format == 'l' || *Format == 'L') 550 { 551 Qualifier = *Format; 552 ++Format; 553 554 if (Qualifier == 'l' && *Format == 'l') 555 { 556 Qualifier = 'L'; 557 ++Format; 558 } 559 } 560 561 switch (*Format) 562 { 563 case '%': 564 565 Pos = AcpiUtBoundStringOutput (Pos, End, '%'); 566 continue; 567 568 case 'c': 569 570 if (!(Type & ACPI_FORMAT_LEFT)) 571 { 572 while (--Width > 0) 573 { 574 Pos = AcpiUtBoundStringOutput (Pos, End, ' '); 575 } 576 } 577 578 c = (char) va_arg (Args, int); 579 Pos = AcpiUtBoundStringOutput (Pos, End, c); 580 581 while (--Width > 0) 582 { 583 Pos = AcpiUtBoundStringOutput (Pos, End, ' '); 584 } 585 continue; 586 587 case 's': 588 589 s = va_arg (Args, char *); 590 if (!s) 591 { 592 s = "<NULL>"; 593 } 594 Length = AcpiUtBoundStringLength (s, Precision); 595 if (!(Type & ACPI_FORMAT_LEFT)) 596 { 597 while (Length < Width--) 598 { 599 Pos = AcpiUtBoundStringOutput (Pos, End, ' '); 600 } 601 } 602 for (i = 0; i < Length; ++i) 603 { 604 Pos = AcpiUtBoundStringOutput (Pos, End, *s); 605 ++s; 606 } 607 while (Length < Width--) 608 { 609 Pos = AcpiUtBoundStringOutput (Pos, End, ' '); 610 } 611 continue; 612 613 case 'o': 614 615 Base = 8; 616 break; 617 618 case 'X': 619 620 Type |= ACPI_FORMAT_UPPER; 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 (Pos, End, 646 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 (ACPI_PTR_DIFF (Pos, String)); 713 } 714 715 716 /******************************************************************************* 717 * 718 * FUNCTION: AcpiUtSnprintf 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 AcpiUtSnprintf ( 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 = AcpiUtVsnprintf (String, Size, Format, Args); 743 va_end (Args); 744 745 return (Length); 746 } 747 748 749 #ifdef ACPI_APPLICATION 750 /******************************************************************************* 751 * 752 * FUNCTION: AcpiUtFileVprintf 753 * 754 * PARAMETERS: File - File descriptor 755 * Format - Standard printf format 756 * Args - Argument list 757 * 758 * RETURN: Number of bytes actually written. 759 * 760 * DESCRIPTION: Formatted output to a file using argument list pointer. 761 * 762 ******************************************************************************/ 763 764 int 765 AcpiUtFileVprintf ( 766 ACPI_FILE File, 767 const char *Format, 768 va_list Args) 769 { 770 ACPI_CPU_FLAGS Flags; 771 int Length; 772 773 774 Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock); 775 Length = AcpiUtVsnprintf (AcpiGbl_PrintBuffer, 776 sizeof (AcpiGbl_PrintBuffer), Format, Args); 777 778 (void) AcpiOsWriteFile (File, AcpiGbl_PrintBuffer, Length, 1); 779 AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags); 780 781 return (Length); 782 } 783 784 785 /******************************************************************************* 786 * 787 * FUNCTION: AcpiUtFilePrintf 788 * 789 * PARAMETERS: File - File descriptor 790 * Format, ... - Standard printf format 791 * 792 * RETURN: Number of bytes actually written. 793 * 794 * DESCRIPTION: Formatted output to a file. 795 * 796 ******************************************************************************/ 797 798 int 799 AcpiUtFilePrintf ( 800 ACPI_FILE File, 801 const char *Format, 802 ...) 803 { 804 va_list Args; 805 int Length; 806 807 808 va_start (Args, Format); 809 Length = AcpiUtFileVprintf (File, Format, Args); 810 va_end (Args); 811 812 return (Length); 813 } 814 #endif 815