1 /****************************************************************************** 2 * 3 * Module Name: utprint - Formatted printing routines 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2014, 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 (ACPI_IS_DIGIT (*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 = 10; 446 UINT8 Type = 0; 447 INT32 Width = -1; 448 INT32 Precision = -1; 449 char Qualifier = 0; 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 /* Process sign */ 472 473 do 474 { 475 ++Format; 476 if (*Format == '#') 477 { 478 Type |= ACPI_FORMAT_PREFIX; 479 } 480 else if (*Format == '0') 481 { 482 Type |= ACPI_FORMAT_ZERO; 483 } 484 else if (*Format == '+') 485 { 486 Type |= ACPI_FORMAT_SIGN_PLUS; 487 } 488 else if (*Format == ' ') 489 { 490 Type |= ACPI_FORMAT_SIGN_PLUS_SPACE; 491 } 492 else if (*Format == '-') 493 { 494 Type |= ACPI_FORMAT_LEFT; 495 } 496 else 497 { 498 break; 499 } 500 } while (1); 501 502 /* Process width */ 503 504 Width = -1; 505 if (ACPI_IS_DIGIT (*Format)) 506 { 507 Format = AcpiUtScanNumber (Format, &Number); 508 Width = (INT32) Number; 509 } 510 else if (*Format == '*') 511 { 512 ++Format; 513 Width = va_arg (Args, int); 514 if (Width < 0) 515 { 516 Width = -Width; 517 Type |= ACPI_FORMAT_LEFT; 518 } 519 } 520 521 /* Process precision */ 522 523 Precision = -1; 524 if (*Format == '.') 525 { 526 ++Format; 527 if (ACPI_IS_DIGIT(*Format)) 528 { 529 Format = AcpiUtScanNumber (Format, &Number); 530 Precision = (INT32) Number; 531 } 532 else if (*Format == '*') 533 { 534 ++Format; 535 Precision = va_arg (Args, int); 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 = AcpiUtBoundStringLength (s, Precision); 592 if (!(Type & ACPI_FORMAT_LEFT)) 593 { 594 while (Length < Width--) 595 { 596 Pos = AcpiUtBoundStringOutput (Pos, End, ' '); 597 } 598 } 599 for (i = 0; i < Length; ++i) 600 { 601 Pos = AcpiUtBoundStringOutput (Pos, End, *s); 602 ++s; 603 } 604 while (Length < Width--) 605 { 606 Pos = AcpiUtBoundStringOutput (Pos, End, ' '); 607 } 608 continue; 609 610 case 'o': 611 612 Base = 8; 613 break; 614 615 case 'X': 616 617 Type |= ACPI_FORMAT_UPPER; 618 619 case 'x': 620 621 Base = 16; 622 break; 623 624 case 'd': 625 case 'i': 626 627 Type |= ACPI_FORMAT_SIGN; 628 629 case 'u': 630 631 break; 632 633 case 'p': 634 635 if (Width == -1) 636 { 637 Width = 2 * sizeof (void *); 638 Type |= ACPI_FORMAT_ZERO; 639 } 640 641 p = va_arg (Args, void *); 642 Pos = AcpiUtFormatNumber (Pos, End, 643 ACPI_TO_INTEGER (p), 16, Width, Precision, Type); 644 continue; 645 646 default: 647 648 Pos = AcpiUtBoundStringOutput (Pos, End, '%'); 649 if (*Format) 650 { 651 Pos = AcpiUtBoundStringOutput (Pos, End, *Format); 652 } 653 else 654 { 655 --Format; 656 } 657 continue; 658 } 659 660 if (Qualifier == 'L') 661 { 662 Number = va_arg (Args, UINT64); 663 if (Type & ACPI_FORMAT_SIGN) 664 { 665 Number = (INT64) Number; 666 } 667 } 668 else if (Qualifier == 'l') 669 { 670 Number = va_arg (Args, unsigned long); 671 if (Type & ACPI_FORMAT_SIGN) 672 { 673 Number = (INT32) Number; 674 } 675 } 676 else if (Qualifier == 'h') 677 { 678 Number = (UINT16) va_arg (Args, int); 679 if (Type & ACPI_FORMAT_SIGN) 680 { 681 Number = (INT16) Number; 682 } 683 } 684 else 685 { 686 Number = va_arg (Args, unsigned int); 687 if (Type & ACPI_FORMAT_SIGN) 688 { 689 Number = (signed int) Number; 690 } 691 } 692 693 Pos = AcpiUtFormatNumber (Pos, End, Number, Base, 694 Width, Precision, Type); 695 } 696 697 if (Size > 0) 698 { 699 if (Pos < End) 700 { 701 *Pos = '\0'; 702 } 703 else 704 { 705 End[-1] = '\0'; 706 } 707 } 708 709 return (ACPI_PTR_DIFF (Pos, String)); 710 } 711 712 713 /******************************************************************************* 714 * 715 * FUNCTION: AcpiUtSnprintf 716 * 717 * PARAMETERS: String - String with boundary 718 * Size - Boundary of the string 719 * Format, ... - Standard printf format 720 * 721 * RETURN: Number of bytes actually written. 722 * 723 * DESCRIPTION: Formatted output to a string. 724 * 725 ******************************************************************************/ 726 727 int 728 AcpiUtSnprintf ( 729 char *String, 730 ACPI_SIZE Size, 731 const char *Format, 732 ...) 733 { 734 va_list Args; 735 int Length; 736 737 738 va_start (Args, Format); 739 Length = AcpiUtVsnprintf (String, Size, Format, Args); 740 va_end (Args); 741 742 return (Length); 743 } 744 745 746 #ifdef ACPI_APPLICATION 747 /******************************************************************************* 748 * 749 * FUNCTION: AcpiUtFileVprintf 750 * 751 * PARAMETERS: File - File descriptor 752 * Format - Standard printf format 753 * Args - Argument list 754 * 755 * RETURN: Number of bytes actually written. 756 * 757 * DESCRIPTION: Formatted output to a file using argument list pointer. 758 * 759 ******************************************************************************/ 760 761 int 762 AcpiUtFileVprintf ( 763 ACPI_FILE File, 764 const char *Format, 765 va_list Args) 766 { 767 ACPI_CPU_FLAGS Flags; 768 int Length; 769 770 771 Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock); 772 Length = AcpiUtVsnprintf (AcpiGbl_PrintBuffer, 773 sizeof (AcpiGbl_PrintBuffer), Format, Args); 774 775 (void) AcpiOsWriteFile (File, AcpiGbl_PrintBuffer, Length, 1); 776 AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags); 777 778 return (Length); 779 } 780 781 782 /******************************************************************************* 783 * 784 * FUNCTION: AcpiUtFilePrintf 785 * 786 * PARAMETERS: File - File descriptor 787 * Format, ... - Standard printf format 788 * 789 * RETURN: Number of bytes actually written. 790 * 791 * DESCRIPTION: Formatted output to a file. 792 * 793 ******************************************************************************/ 794 795 int 796 AcpiUtFilePrintf ( 797 ACPI_FILE File, 798 const char *Format, 799 ...) 800 { 801 va_list Args; 802 int Length; 803 804 805 va_start (Args, Format); 806 Length = AcpiUtFileVprintf (File, Format, Args); 807 va_end (Args); 808 809 return (Length); 810 } 811 #endif 812