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 /******************************************************************************* 92 * 93 * FUNCTION: AcpiUtBoundStringLength 94 * 95 * PARAMETERS: String - String with boundary 96 * Count - Boundary of the string 97 * 98 * RETURN: Length of the string. 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 ++String; 149 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 LowerDigits[] = "0123456789abcdef"; 178 const char UpperDigits[] = "0123456789ABCDEF"; 179 const char *Digits; 180 UINT64 DigitIndex; 181 char *Pos; 182 183 184 Pos = String; 185 Digits = Upper ? UpperDigits : LowerDigits; 186 187 if (Number == 0) 188 { 189 *(Pos++) = '0'; 190 } 191 else 192 { 193 while (Number) 194 { 195 (void) AcpiUtDivide (Number, Base, &Number, &DigitIndex); 196 *(Pos++) = Digits[DigitIndex]; 197 } 198 } 199 /* *(Pos++) = '0'; */ 200 201 return (Pos); 202 } 203 204 205 /******************************************************************************* 206 * 207 * FUNCTION: AcpiUtScanNumber 208 * 209 * PARAMETERS: String - String buffer 210 * NumberPtr - Where the number is returned 211 * 212 * RETURN: Updated position for next valid character 213 * 214 * DESCRIPTION: Scan a string for a decimal integer. 215 * 216 ******************************************************************************/ 217 218 const char * 219 AcpiUtScanNumber ( 220 const char *String, 221 UINT64 *NumberPtr) 222 { 223 UINT64 Number = 0; 224 225 226 while (ACPI_IS_DIGIT (*String)) 227 { 228 Number *= 10; 229 Number += *(String++) - '0'; 230 } 231 *NumberPtr = Number; 232 233 return (String); 234 } 235 236 237 /******************************************************************************* 238 * 239 * FUNCTION: AcpiUtPrintNumber 240 * 241 * PARAMETERS: String - String buffer 242 * Number - The number to be converted 243 * 244 * RETURN: Updated position for next valid character 245 * 246 * DESCRIPTION: Print a decimal integer into a string. 247 * 248 ******************************************************************************/ 249 250 const char * 251 AcpiUtPrintNumber ( 252 char *String, 253 UINT64 Number) 254 { 255 char AsciiString[20]; 256 const char *Pos1; 257 char *Pos2; 258 259 260 Pos1 = AcpiUtPutNumber (AsciiString, Number, 10, FALSE); 261 Pos2 = String; 262 263 while (Pos1 != AsciiString) 264 { 265 *(Pos2++) = *(--Pos1); 266 } 267 *Pos2 = 0; 268 269 return (String); 270 } 271 272 273 /******************************************************************************* 274 * 275 * FUNCTION: AcpiUtFormatNumber 276 * 277 * PARAMETERS: String - String buffer with boundary 278 * End - Boundary of the string 279 * Number - The number to be converted 280 * Base - Base of the integer 281 * Width - Field width 282 * Precision - Precision of the integer 283 * Type - Special printing flags 284 * 285 * RETURN: Updated position for next valid character 286 * 287 * DESCRIPTION: Print an integer into a string with any base and any precision. 288 * 289 ******************************************************************************/ 290 291 static char * 292 AcpiUtFormatNumber ( 293 char *String, 294 char *End, 295 UINT64 Number, 296 UINT8 Base, 297 INT32 Width, 298 INT32 Precision, 299 UINT8 Type) 300 { 301 char Sign; 302 char Zero; 303 BOOLEAN NeedPrefix; 304 BOOLEAN Upper; 305 INT32 i; 306 char ReversedString[66]; 307 308 309 /* Perform sanity checks */ 310 311 if (Base < 2 || Base > 16) 312 { 313 return NULL; 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 i = ACPI_PTR_DIFF ( 358 AcpiUtPutNumber (ReversedString, Number, Base, Upper), 359 ReversedString); 360 361 /* Printing 100 using %2d gives "100", not "00" */ 362 363 if (i > Precision) 364 { 365 Precision = i; 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 (String, End, 388 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 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 416 /******************************************************************************* 417 * 418 * FUNCTION: AcpiUtVsnprintf 419 * 420 * PARAMETERS: String - String with boundary 421 * Size - Boundary of the string 422 * Format - Standard printf format 423 * Args - Argument list 424 * 425 * RETURN: Size of successfully output bytes 426 * 427 * DESCRIPTION: Formatted output to a string using argument list pointer. 428 * 429 ******************************************************************************/ 430 431 int 432 AcpiUtVsnprintf ( 433 char *String, 434 ACPI_SIZE Size, 435 const char *Format, 436 va_list Args) 437 { 438 UINT8 Base = 10; 439 UINT8 Type = 0; 440 INT32 Width = -1; 441 INT32 Precision = -1; 442 char Qualifier = 0; 443 UINT64 Number; 444 char *Pos; 445 char *End; 446 char c; 447 const char *s; 448 const void *p; 449 INT32 Length; 450 int i; 451 452 453 Pos = String; 454 End = String + Size; 455 456 for (; *Format ; ++Format) 457 { 458 if (*Format != '%') 459 { 460 Pos = AcpiUtBoundStringOutput (Pos, End, *Format); 461 continue; 462 } 463 464 /* Process sign */ 465 466 do 467 { 468 ++Format; 469 if (*Format == '#') 470 { 471 Type |= ACPI_FORMAT_PREFIX; 472 } 473 else if (*Format == '0') 474 { 475 Type |= ACPI_FORMAT_ZERO; 476 } 477 else if (*Format == '+') 478 { 479 Type |= ACPI_FORMAT_SIGN_PLUS; 480 } 481 else if (*Format == ' ') 482 { 483 Type |= ACPI_FORMAT_SIGN_PLUS_SPACE; 484 } 485 else if (*Format == '-') 486 { 487 Type |= ACPI_FORMAT_LEFT; 488 } 489 else 490 { 491 break; 492 } 493 } while (1); 494 495 /* Process width */ 496 497 if (ACPI_IS_DIGIT (*Format)) 498 { 499 Format = AcpiUtScanNumber (Format, &Number); 500 Width = (INT32) Number; 501 } 502 else if (*Format == '*') 503 { 504 ++Format; 505 Width = va_arg(Args, int); 506 if (Width < 0) 507 { 508 Width = -Width; 509 Type |= ACPI_FORMAT_LEFT; 510 } 511 } 512 513 /* Process precision */ 514 515 if (*Format == '.') 516 { 517 ++Format; 518 if (ACPI_IS_DIGIT(*Format)) 519 { 520 Format = AcpiUtScanNumber (Format, &Number); 521 Precision = (INT32) Number; 522 } 523 else if (*Format == '*') 524 { 525 ++Format; 526 Precision = va_arg(Args, int); 527 } 528 if (Precision < 0) 529 { 530 Precision = 0; 531 } 532 } 533 534 /* Process qualifier */ 535 536 if (*Format == 'h' || *Format == 'l' || *Format == 'L') 537 { 538 Qualifier = *Format; 539 ++Format; 540 if (Qualifier == 'l' && *Format == 'l') 541 { 542 Qualifier = 'L'; 543 ++Format; 544 } 545 } 546 547 switch (*Format) 548 { 549 case '%': 550 551 Pos = AcpiUtBoundStringOutput (Pos, End, '%'); 552 continue; 553 554 case 'c': 555 556 if (!(Type & ACPI_FORMAT_LEFT)) 557 { 558 while (--Width > 0) 559 { 560 Pos = AcpiUtBoundStringOutput (Pos, End, ' '); 561 } 562 } 563 c = (char) va_arg (Args, int); 564 Pos = AcpiUtBoundStringOutput (Pos, End, c); 565 while (--Width > 0) 566 { 567 Pos = AcpiUtBoundStringOutput (Pos, End, ' '); 568 } 569 continue; 570 571 case 's': 572 573 s = va_arg (Args, char *); 574 if (!s) 575 { 576 s = "<NULL>"; 577 } 578 Length = AcpiUtBoundStringLength (s, Precision); 579 if (!(Type & ACPI_FORMAT_LEFT)) 580 { 581 while (Length < Width--) 582 { 583 Pos = AcpiUtBoundStringOutput (Pos, End, ' '); 584 } 585 } 586 for (i = 0; i < Length; ++i) 587 { 588 Pos = AcpiUtBoundStringOutput (Pos, End, *s); 589 ++s; 590 } 591 while (Length < Width--) 592 { 593 Pos = AcpiUtBoundStringOutput (Pos, End, ' '); 594 } 595 continue; 596 597 case 'o': 598 599 Base = 8; 600 break; 601 602 case 'X': 603 604 Type |= ACPI_FORMAT_UPPER; 605 606 case 'x': 607 608 Base = 16; 609 break; 610 611 case 'd': 612 case 'i': 613 614 Type |= ACPI_FORMAT_SIGN; 615 616 case 'u': 617 618 break; 619 620 case 'p': 621 622 if (Width == -1) 623 { 624 Width = 2 * sizeof (void *); 625 Type |= ACPI_FORMAT_ZERO; 626 } 627 p = va_arg (Args, void *); 628 Pos = AcpiUtFormatNumber (Pos, End, 629 ACPI_TO_INTEGER (p), 630 16, Width, Precision, Type); 631 continue; 632 633 default: 634 635 Pos = AcpiUtBoundStringOutput (Pos, End, '%'); 636 if (*Format) 637 { 638 Pos = AcpiUtBoundStringOutput (Pos, End, *Format); 639 } 640 else 641 { 642 --Format; 643 } 644 continue; 645 } 646 647 if (Qualifier == 'L') 648 { 649 Number = va_arg (Args, UINT64); 650 if (Type & ACPI_FORMAT_SIGN) 651 { 652 Number = (INT64) Number; 653 } 654 } 655 else if (Qualifier == 'l') 656 { 657 Number = va_arg (Args, unsigned long); 658 if (Type & ACPI_FORMAT_SIGN) 659 { 660 Number = (INT32) Number; 661 } 662 } 663 else if (Qualifier == 'h') 664 { 665 Number = (UINT16) va_arg (Args, int); 666 if (Type & ACPI_FORMAT_SIGN) 667 { 668 Number = (INT16) Number; 669 } 670 } 671 else 672 { 673 Number = va_arg (Args, unsigned int); 674 if (Type & ACPI_FORMAT_SIGN) 675 { 676 Number = (signed int) Number; 677 } 678 } 679 Pos = AcpiUtFormatNumber(Pos, End, Number, Base, 680 Width, Precision, Type); 681 } 682 683 if (Size > 0) 684 { 685 if (Pos < End) 686 { 687 *Pos = '\0'; 688 } 689 else 690 { 691 End[-1] = '\0'; 692 } 693 } 694 695 return (ACPI_PTR_DIFF (Pos, String)); 696 } 697 698 699 /******************************************************************************* 700 * 701 * FUNCTION: AcpiUtSnprintf 702 * 703 * PARAMETERS: String - String with boundary 704 * Size - Boundary of the string 705 * Format, ... - Standard printf format 706 * 707 * RETURN: Size of successfully output bytes 708 * 709 * DESCRIPTION: Formatted output to a string. 710 * 711 ******************************************************************************/ 712 713 int 714 AcpiUtSnprintf ( 715 char *String, 716 ACPI_SIZE Size, 717 const char *Format, 718 ...) 719 { 720 va_list Args; 721 int Length; 722 723 724 va_start (Args, Format); 725 Length = AcpiUtVsnprintf (String, Size, Format, Args); 726 va_end (Args); 727 728 return (Length); 729 } 730 731 732 #ifdef ACPI_APPLICATION 733 /******************************************************************************* 734 * 735 * FUNCTION: AcpiUtFileVprintf 736 * 737 * PARAMETERS: File - File descriptor 738 * Format - Standard printf format 739 * Args - Argument list 740 * 741 * RETURN: Size of successfully output bytes 742 * 743 * DESCRIPTION: Formatted output to a file using argument list pointer. 744 * 745 ******************************************************************************/ 746 747 int 748 AcpiUtFileVprintf ( 749 ACPI_FILE File, 750 const char *Format, 751 va_list Args) 752 { 753 ACPI_CPU_FLAGS Flags; 754 int Length; 755 756 757 Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock); 758 Length = AcpiUtVsnprintf(AcpiGbl_PrintBuffer, 759 sizeof (AcpiGbl_PrintBuffer), Format, Args); 760 (void) AcpiOsWriteFile (File, AcpiGbl_PrintBuffer, Length, 1); 761 AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags); 762 763 return (Length); 764 } 765 766 767 /******************************************************************************* 768 * 769 * FUNCTION: AcpiUtFilePrintf 770 * 771 * PARAMETERS: File - File descriptor 772 * Format, ... - Standard printf format 773 * 774 * RETURN: Size of successfully output bytes 775 * 776 * DESCRIPTION: Formatted output to a file. 777 * 778 ******************************************************************************/ 779 780 int 781 AcpiUtFilePrintf ( 782 ACPI_FILE File, 783 const char *Format, 784 ...) 785 { 786 va_list Args; 787 int Length; 788 789 790 va_start (Args, Format); 791 Length = AcpiUtFileVprintf (File, Format, Args); 792 va_end (Args); 793 794 return (Length); 795 } 796 #endif 797