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