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 /******************************************************************************* 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 Number *= 10; 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 = 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: AcpiUtVsnprintf 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 AcpiUtVsnprintf ( 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 = 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 620 case 'x': 621 622 Base = 16; 623 break; 624 625 case 'd': 626 case 'i': 627 628 Type |= ACPI_FORMAT_SIGN; 629 630 case 'u': 631 632 break; 633 634 case 'p': 635 636 if (Width == -1) 637 { 638 Width = 2 * sizeof (void *); 639 Type |= ACPI_FORMAT_ZERO; 640 } 641 642 p = va_arg (Args, void *); 643 Pos = AcpiUtFormatNumber ( 644 Pos, End, ACPI_TO_INTEGER (p), 16, Width, Precision, Type); 645 continue; 646 647 default: 648 649 Pos = AcpiUtBoundStringOutput (Pos, End, '%'); 650 if (*Format) 651 { 652 Pos = AcpiUtBoundStringOutput (Pos, End, *Format); 653 } 654 else 655 { 656 --Format; 657 } 658 continue; 659 } 660 661 if (Qualifier == 'L') 662 { 663 Number = va_arg (Args, UINT64); 664 if (Type & ACPI_FORMAT_SIGN) 665 { 666 Number = (INT64) Number; 667 } 668 } 669 else if (Qualifier == 'l') 670 { 671 Number = va_arg (Args, unsigned long); 672 if (Type & ACPI_FORMAT_SIGN) 673 { 674 Number = (INT32) Number; 675 } 676 } 677 else if (Qualifier == 'h') 678 { 679 Number = (UINT16) va_arg (Args, int); 680 if (Type & ACPI_FORMAT_SIGN) 681 { 682 Number = (INT16) Number; 683 } 684 } 685 else 686 { 687 Number = va_arg (Args, unsigned int); 688 if (Type & ACPI_FORMAT_SIGN) 689 { 690 Number = (signed int) Number; 691 } 692 } 693 694 Pos = AcpiUtFormatNumber (Pos, End, Number, Base, 695 Width, Precision, Type); 696 } 697 698 if (Size > 0) 699 { 700 if (Pos < End) 701 { 702 *Pos = '\0'; 703 } 704 else 705 { 706 End[-1] = '\0'; 707 } 708 } 709 710 return (ACPI_PTR_DIFF (Pos, String)); 711 } 712 713 714 /******************************************************************************* 715 * 716 * FUNCTION: AcpiUtSnprintf 717 * 718 * PARAMETERS: String - String with boundary 719 * Size - Boundary of the string 720 * Format, ... - Standard printf format 721 * 722 * RETURN: Number of bytes actually written. 723 * 724 * DESCRIPTION: Formatted output to a string. 725 * 726 ******************************************************************************/ 727 728 int 729 AcpiUtSnprintf ( 730 char *String, 731 ACPI_SIZE Size, 732 const char *Format, 733 ...) 734 { 735 va_list Args; 736 int Length; 737 738 739 va_start (Args, Format); 740 Length = AcpiUtVsnprintf (String, Size, Format, Args); 741 va_end (Args); 742 743 return (Length); 744 } 745 746 747 #ifdef ACPI_APPLICATION 748 /******************************************************************************* 749 * 750 * FUNCTION: AcpiUtFileVprintf 751 * 752 * PARAMETERS: File - File descriptor 753 * Format - Standard printf format 754 * Args - Argument list 755 * 756 * RETURN: Number of bytes actually written. 757 * 758 * DESCRIPTION: Formatted output to a file using argument list pointer. 759 * 760 ******************************************************************************/ 761 762 int 763 AcpiUtFileVprintf ( 764 ACPI_FILE File, 765 const char *Format, 766 va_list Args) 767 { 768 ACPI_CPU_FLAGS Flags; 769 int Length; 770 771 772 Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock); 773 Length = AcpiUtVsnprintf (AcpiGbl_PrintBuffer, 774 sizeof (AcpiGbl_PrintBuffer), Format, Args); 775 776 (void) AcpiOsWriteFile (File, AcpiGbl_PrintBuffer, Length, 1); 777 AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags); 778 779 return (Length); 780 } 781 782 783 /******************************************************************************* 784 * 785 * FUNCTION: AcpiUtFilePrintf 786 * 787 * PARAMETERS: File - File descriptor 788 * Format, ... - Standard printf format 789 * 790 * RETURN: Number of bytes actually written. 791 * 792 * DESCRIPTION: Formatted output to a file. 793 * 794 ******************************************************************************/ 795 796 int 797 AcpiUtFilePrintf ( 798 ACPI_FILE File, 799 const char *Format, 800 ...) 801 { 802 va_list Args; 803 int Length; 804 805 806 va_start (Args, Format); 807 Length = AcpiUtFileVprintf (File, Format, Args); 808 va_end (Args); 809 810 return (Length); 811 } 812 #endif 813