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/acpi.h> 45 #include "accommon.h" 46 47 #define _COMPONENT ACPI_UTILITIES 48 ACPI_MODULE_NAME("utprint") 49 50 #define ACPI_FORMAT_SIGN 0x01 51 #define ACPI_FORMAT_SIGN_PLUS 0x02 52 #define ACPI_FORMAT_SIGN_PLUS_SPACE 0x04 53 #define ACPI_FORMAT_ZERO 0x08 54 #define ACPI_FORMAT_LEFT 0x10 55 #define ACPI_FORMAT_UPPER 0x20 56 #define ACPI_FORMAT_PREFIX 0x40 57 /* Local prototypes */ 58 static acpi_size 59 acpi_ut_bound_string_length(const char *string, acpi_size count); 60 61 static char *acpi_ut_bound_string_output(char *string, const char *end, char c); 62 63 static char *acpi_ut_format_number(char *string, 64 char *end, 65 u64 number, 66 u8 base, s32 width, s32 precision, u8 type); 67 68 static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper); 69 70 /* Module globals */ 71 72 static const char acpi_gbl_lower_hex_digits[] = "0123456789abcdef"; 73 static const char acpi_gbl_upper_hex_digits[] = "0123456789ABCDEF"; 74 75 /******************************************************************************* 76 * 77 * FUNCTION: acpi_ut_bound_string_length 78 * 79 * PARAMETERS: string - String with boundary 80 * count - Boundary of the string 81 * 82 * RETURN: Length of the string. Less than or equal to Count. 83 * 84 * DESCRIPTION: Calculate the length of a string with boundary. 85 * 86 ******************************************************************************/ 87 88 static acpi_size 89 acpi_ut_bound_string_length(const char *string, acpi_size count) 90 { 91 u32 length = 0; 92 93 while (*string && count) { 94 length++; 95 string++; 96 count--; 97 } 98 99 return (length); 100 } 101 102 /******************************************************************************* 103 * 104 * FUNCTION: acpi_ut_bound_string_output 105 * 106 * PARAMETERS: string - String with boundary 107 * end - Boundary of the string 108 * c - Character to be output to the string 109 * 110 * RETURN: Updated position for next valid character 111 * 112 * DESCRIPTION: Output a character into a string with boundary check. 113 * 114 ******************************************************************************/ 115 116 static char *acpi_ut_bound_string_output(char *string, const char *end, char c) 117 { 118 119 if (string < end) { 120 *string = c; 121 } 122 123 ++string; 124 return (string); 125 } 126 127 /******************************************************************************* 128 * 129 * FUNCTION: acpi_ut_put_number 130 * 131 * PARAMETERS: string - Buffer to hold reverse-ordered string 132 * number - Integer to be converted 133 * base - Base of the integer 134 * upper - Whether or not using upper cased digits 135 * 136 * RETURN: Updated position for next valid character 137 * 138 * DESCRIPTION: Convert an integer into a string, note that, the string holds a 139 * reversed ordered number without the trailing zero. 140 * 141 ******************************************************************************/ 142 143 static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper) 144 { 145 const char *digits; 146 u64 digit_index; 147 char *pos; 148 149 pos = string; 150 digits = upper ? acpi_gbl_upper_hex_digits : acpi_gbl_lower_hex_digits; 151 152 if (number == 0) { 153 *(pos++) = '0'; 154 } else { 155 while (number) { 156 (void)acpi_ut_divide(number, base, &number, 157 &digit_index); 158 *(pos++) = digits[digit_index]; 159 } 160 } 161 162 /* *(Pos++) = '0'; */ 163 return (pos); 164 } 165 166 /******************************************************************************* 167 * 168 * FUNCTION: acpi_ut_scan_number 169 * 170 * PARAMETERS: string - String buffer 171 * number_ptr - Where the number is returned 172 * 173 * RETURN: Updated position for next valid character 174 * 175 * DESCRIPTION: Scan a string for a decimal integer. 176 * 177 ******************************************************************************/ 178 179 const char *acpi_ut_scan_number(const char *string, u64 *number_ptr) 180 { 181 u64 number = 0; 182 183 while (isdigit((int)*string)) { 184 number *= 10; 185 number += *(string++) - '0'; 186 } 187 188 *number_ptr = number; 189 return (string); 190 } 191 192 /******************************************************************************* 193 * 194 * FUNCTION: acpi_ut_print_number 195 * 196 * PARAMETERS: string - String buffer 197 * number - The number to be converted 198 * 199 * RETURN: Updated position for next valid character 200 * 201 * DESCRIPTION: Print a decimal integer into a string. 202 * 203 ******************************************************************************/ 204 205 const char *acpi_ut_print_number(char *string, u64 number) 206 { 207 char ascii_string[20]; 208 const char *pos1; 209 char *pos2; 210 211 pos1 = acpi_ut_put_number(ascii_string, number, 10, FALSE); 212 pos2 = string; 213 214 while (pos1 != ascii_string) { 215 *(pos2++) = *(--pos1); 216 } 217 218 *pos2 = 0; 219 return (string); 220 } 221 222 /******************************************************************************* 223 * 224 * FUNCTION: acpi_ut_format_number 225 * 226 * PARAMETERS: string - String buffer with boundary 227 * end - Boundary of the string 228 * number - The number to be converted 229 * base - Base of the integer 230 * width - Field width 231 * precision - Precision of the integer 232 * type - Special printing flags 233 * 234 * RETURN: Updated position for next valid character 235 * 236 * DESCRIPTION: Print an integer into a string with any base and any precision. 237 * 238 ******************************************************************************/ 239 240 static char *acpi_ut_format_number(char *string, 241 char *end, 242 u64 number, 243 u8 base, s32 width, s32 precision, u8 type) 244 { 245 char *pos; 246 char sign; 247 char zero; 248 u8 need_prefix; 249 u8 upper; 250 s32 i; 251 char reversed_string[66]; 252 253 /* Parameter validation */ 254 255 if (base < 2 || base > 16) { 256 return (NULL); 257 } 258 259 if (type & ACPI_FORMAT_LEFT) { 260 type &= ~ACPI_FORMAT_ZERO; 261 } 262 263 need_prefix = ((type & ACPI_FORMAT_PREFIX) 264 && base != 10) ? TRUE : FALSE; 265 upper = (type & ACPI_FORMAT_UPPER) ? TRUE : FALSE; 266 zero = (type & ACPI_FORMAT_ZERO) ? '0' : ' '; 267 268 /* Calculate size according to sign and prefix */ 269 270 sign = '\0'; 271 if (type & ACPI_FORMAT_SIGN) { 272 if ((s64) number < 0) { 273 sign = '-'; 274 number = -(s64) number; 275 width--; 276 } else if (type & ACPI_FORMAT_SIGN_PLUS) { 277 sign = '+'; 278 width--; 279 } else if (type & ACPI_FORMAT_SIGN_PLUS_SPACE) { 280 sign = ' '; 281 width--; 282 } 283 } 284 if (need_prefix) { 285 width--; 286 if (base == 16) { 287 width--; 288 } 289 } 290 291 /* Generate full string in reverse order */ 292 293 pos = acpi_ut_put_number(reversed_string, number, base, upper); 294 i = ACPI_PTR_DIFF(pos, reversed_string); 295 296 /* Printing 100 using %2d gives "100", not "00" */ 297 298 if (i > precision) { 299 precision = i; 300 } 301 302 width -= precision; 303 304 /* Output the string */ 305 306 if (!(type & (ACPI_FORMAT_ZERO | ACPI_FORMAT_LEFT))) { 307 while (--width >= 0) { 308 string = acpi_ut_bound_string_output(string, end, ' '); 309 } 310 } 311 if (sign) { 312 string = acpi_ut_bound_string_output(string, end, sign); 313 } 314 if (need_prefix) { 315 string = acpi_ut_bound_string_output(string, end, '0'); 316 if (base == 16) { 317 string = 318 acpi_ut_bound_string_output(string, end, 319 upper ? 'X' : 'x'); 320 } 321 } 322 if (!(type & ACPI_FORMAT_LEFT)) { 323 while (--width >= 0) { 324 string = acpi_ut_bound_string_output(string, end, zero); 325 } 326 } 327 328 while (i <= --precision) { 329 string = acpi_ut_bound_string_output(string, end, '0'); 330 } 331 while (--i >= 0) { 332 string = acpi_ut_bound_string_output(string, end, 333 reversed_string[i]); 334 } 335 while (--width >= 0) { 336 string = acpi_ut_bound_string_output(string, end, ' '); 337 } 338 339 return (string); 340 } 341 342 /******************************************************************************* 343 * 344 * FUNCTION: acpi_ut_vsnprintf 345 * 346 * PARAMETERS: string - String with boundary 347 * size - Boundary of the string 348 * format - Standard printf format 349 * args - Argument list 350 * 351 * RETURN: Number of bytes actually written. 352 * 353 * DESCRIPTION: Formatted output to a string using argument list pointer. 354 * 355 ******************************************************************************/ 356 357 int 358 acpi_ut_vsnprintf(char *string, 359 acpi_size size, const char *format, va_list args) 360 { 361 u8 base; 362 u8 type; 363 s32 width; 364 s32 precision; 365 char qualifier; 366 u64 number; 367 char *pos; 368 char *end; 369 char c; 370 const char *s; 371 const void *p; 372 s32 length; 373 int i; 374 375 pos = string; 376 end = string + size; 377 378 for (; *format; ++format) { 379 if (*format != '%') { 380 pos = acpi_ut_bound_string_output(pos, end, *format); 381 continue; 382 } 383 384 type = 0; 385 base = 10; 386 387 /* Process sign */ 388 389 do { 390 ++format; 391 if (*format == '#') { 392 type |= ACPI_FORMAT_PREFIX; 393 } else if (*format == '0') { 394 type |= ACPI_FORMAT_ZERO; 395 } else if (*format == '+') { 396 type |= ACPI_FORMAT_SIGN_PLUS; 397 } else if (*format == ' ') { 398 type |= ACPI_FORMAT_SIGN_PLUS_SPACE; 399 } else if (*format == '-') { 400 type |= ACPI_FORMAT_LEFT; 401 } else { 402 break; 403 } 404 405 } while (1); 406 407 /* Process width */ 408 409 width = -1; 410 if (isdigit((int)*format)) { 411 format = acpi_ut_scan_number(format, &number); 412 width = (s32) number; 413 } else if (*format == '*') { 414 ++format; 415 width = va_arg(args, int); 416 if (width < 0) { 417 width = -width; 418 type |= ACPI_FORMAT_LEFT; 419 } 420 } 421 422 /* Process precision */ 423 424 precision = -1; 425 if (*format == '.') { 426 ++format; 427 if (isdigit((int)*format)) { 428 format = acpi_ut_scan_number(format, &number); 429 precision = (s32) number; 430 } else if (*format == '*') { 431 ++format; 432 precision = va_arg(args, int); 433 } 434 435 if (precision < 0) { 436 precision = 0; 437 } 438 } 439 440 /* Process qualifier */ 441 442 qualifier = -1; 443 if (*format == 'h' || *format == 'l' || *format == 'L') { 444 qualifier = *format; 445 ++format; 446 447 if (qualifier == 'l' && *format == 'l') { 448 qualifier = 'L'; 449 ++format; 450 } 451 } 452 453 switch (*format) { 454 case '%': 455 456 pos = acpi_ut_bound_string_output(pos, end, '%'); 457 continue; 458 459 case 'c': 460 461 if (!(type & ACPI_FORMAT_LEFT)) { 462 while (--width > 0) { 463 pos = 464 acpi_ut_bound_string_output(pos, 465 end, 466 ' '); 467 } 468 } 469 470 c = (char)va_arg(args, int); 471 pos = acpi_ut_bound_string_output(pos, end, c); 472 473 while (--width > 0) { 474 pos = 475 acpi_ut_bound_string_output(pos, end, ' '); 476 } 477 continue; 478 479 case 's': 480 481 s = va_arg(args, char *); 482 if (!s) { 483 s = "<NULL>"; 484 } 485 length = acpi_ut_bound_string_length(s, precision); 486 if (!(type & ACPI_FORMAT_LEFT)) { 487 while (length < width--) { 488 pos = 489 acpi_ut_bound_string_output(pos, 490 end, 491 ' '); 492 } 493 } 494 495 for (i = 0; i < length; ++i) { 496 pos = acpi_ut_bound_string_output(pos, end, *s); 497 ++s; 498 } 499 500 while (length < width--) { 501 pos = 502 acpi_ut_bound_string_output(pos, end, ' '); 503 } 504 continue; 505 506 case 'o': 507 508 base = 8; 509 break; 510 511 case 'X': 512 513 type |= ACPI_FORMAT_UPPER; 514 515 case 'x': 516 517 base = 16; 518 break; 519 520 case 'd': 521 case 'i': 522 523 type |= ACPI_FORMAT_SIGN; 524 525 case 'u': 526 527 break; 528 529 case 'p': 530 531 if (width == -1) { 532 width = 2 * sizeof(void *); 533 type |= ACPI_FORMAT_ZERO; 534 } 535 536 p = va_arg(args, void *); 537 pos = 538 acpi_ut_format_number(pos, end, ACPI_TO_INTEGER(p), 539 16, width, precision, type); 540 continue; 541 542 default: 543 544 pos = acpi_ut_bound_string_output(pos, end, '%'); 545 if (*format) { 546 pos = 547 acpi_ut_bound_string_output(pos, end, 548 *format); 549 } else { 550 --format; 551 } 552 continue; 553 } 554 555 if (qualifier == 'L') { 556 number = va_arg(args, u64); 557 if (type & ACPI_FORMAT_SIGN) { 558 number = (s64) number; 559 } 560 } else if (qualifier == 'l') { 561 number = va_arg(args, unsigned long); 562 if (type & ACPI_FORMAT_SIGN) { 563 number = (s32) number; 564 } 565 } else if (qualifier == 'h') { 566 number = (u16)va_arg(args, int); 567 if (type & ACPI_FORMAT_SIGN) { 568 number = (s16) number; 569 } 570 } else { 571 number = va_arg(args, unsigned int); 572 if (type & ACPI_FORMAT_SIGN) { 573 number = (signed int)number; 574 } 575 } 576 577 pos = acpi_ut_format_number(pos, end, number, base, 578 width, precision, type); 579 } 580 581 if (size > 0) { 582 if (pos < end) { 583 *pos = '\0'; 584 } else { 585 end[-1] = '\0'; 586 } 587 } 588 589 return (ACPI_PTR_DIFF(pos, string)); 590 } 591 592 /******************************************************************************* 593 * 594 * FUNCTION: acpi_ut_snprintf 595 * 596 * PARAMETERS: string - String with boundary 597 * size - Boundary of the string 598 * Format, ... - Standard printf format 599 * 600 * RETURN: Number of bytes actually written. 601 * 602 * DESCRIPTION: Formatted output to a string. 603 * 604 ******************************************************************************/ 605 606 int acpi_ut_snprintf(char *string, acpi_size size, const char *format, ...) 607 { 608 va_list args; 609 int length; 610 611 va_start(args, format); 612 length = acpi_ut_vsnprintf(string, size, format, args); 613 va_end(args); 614 615 return (length); 616 } 617 618 #ifdef ACPI_APPLICATION 619 /******************************************************************************* 620 * 621 * FUNCTION: acpi_ut_file_vprintf 622 * 623 * PARAMETERS: file - File descriptor 624 * format - Standard printf format 625 * args - Argument list 626 * 627 * RETURN: Number of bytes actually written. 628 * 629 * DESCRIPTION: Formatted output to a file using argument list pointer. 630 * 631 ******************************************************************************/ 632 633 int acpi_ut_file_vprintf(ACPI_FILE file, const char *format, va_list args) 634 { 635 acpi_cpu_flags flags; 636 int length; 637 638 flags = acpi_os_acquire_lock(acpi_gbl_print_lock); 639 length = acpi_ut_vsnprintf(acpi_gbl_print_buffer, 640 sizeof(acpi_gbl_print_buffer), format, args); 641 642 (void)acpi_os_write_file(file, acpi_gbl_print_buffer, length, 1); 643 acpi_os_release_lock(acpi_gbl_print_lock, flags); 644 645 return (length); 646 } 647 648 /******************************************************************************* 649 * 650 * FUNCTION: acpi_ut_file_printf 651 * 652 * PARAMETERS: file - File descriptor 653 * Format, ... - Standard printf format 654 * 655 * RETURN: Number of bytes actually written. 656 * 657 * DESCRIPTION: Formatted output to a file. 658 * 659 ******************************************************************************/ 660 661 int acpi_ut_file_printf(ACPI_FILE file, const char *format, ...) 662 { 663 va_list args; 664 int length; 665 666 va_start(args, format); 667 length = acpi_ut_file_vprintf(file, format, args); 668 va_end(args); 669 670 return (length); 671 } 672 #endif 673