1 /****************************************************************************** 2 * 3 * Module Name: utprint - Formatted printing routines 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2015, 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 = acpi_ut_bound_string_output(string, end, 318 upper ? 'X' : 'x'); 319 } 320 } 321 if (!(type & ACPI_FORMAT_LEFT)) { 322 while (--width >= 0) { 323 string = acpi_ut_bound_string_output(string, end, zero); 324 } 325 } 326 327 while (i <= --precision) { 328 string = acpi_ut_bound_string_output(string, end, '0'); 329 } 330 while (--i >= 0) { 331 string = acpi_ut_bound_string_output(string, end, 332 reversed_string[i]); 333 } 334 while (--width >= 0) { 335 string = acpi_ut_bound_string_output(string, end, ' '); 336 } 337 338 return (string); 339 } 340 341 /******************************************************************************* 342 * 343 * FUNCTION: acpi_ut_vsnprintf 344 * 345 * PARAMETERS: string - String with boundary 346 * size - Boundary of the string 347 * format - Standard printf format 348 * args - Argument list 349 * 350 * RETURN: Number of bytes actually written. 351 * 352 * DESCRIPTION: Formatted output to a string using argument list pointer. 353 * 354 ******************************************************************************/ 355 356 int 357 acpi_ut_vsnprintf(char *string, 358 acpi_size size, const char *format, va_list args) 359 { 360 u8 base; 361 u8 type; 362 s32 width; 363 s32 precision; 364 char qualifier; 365 u64 number; 366 char *pos; 367 char *end; 368 char c; 369 const char *s; 370 const void *p; 371 s32 length; 372 int i; 373 374 pos = string; 375 end = string + size; 376 377 for (; *format; ++format) { 378 if (*format != '%') { 379 pos = acpi_ut_bound_string_output(pos, end, *format); 380 continue; 381 } 382 383 type = 0; 384 base = 10; 385 386 /* Process sign */ 387 388 do { 389 ++format; 390 if (*format == '#') { 391 type |= ACPI_FORMAT_PREFIX; 392 } else if (*format == '0') { 393 type |= ACPI_FORMAT_ZERO; 394 } else if (*format == '+') { 395 type |= ACPI_FORMAT_SIGN_PLUS; 396 } else if (*format == ' ') { 397 type |= ACPI_FORMAT_SIGN_PLUS_SPACE; 398 } else if (*format == '-') { 399 type |= ACPI_FORMAT_LEFT; 400 } else { 401 break; 402 } 403 } while (1); 404 405 /* Process width */ 406 407 width = -1; 408 if (isdigit((int)*format)) { 409 format = acpi_ut_scan_number(format, &number); 410 width = (s32) number; 411 } else if (*format == '*') { 412 ++format; 413 width = va_arg(args, int); 414 if (width < 0) { 415 width = -width; 416 type |= ACPI_FORMAT_LEFT; 417 } 418 } 419 420 /* Process precision */ 421 422 precision = -1; 423 if (*format == '.') { 424 ++format; 425 if (isdigit((int)*format)) { 426 format = acpi_ut_scan_number(format, &number); 427 precision = (s32) number; 428 } else if (*format == '*') { 429 ++format; 430 precision = va_arg(args, int); 431 } 432 if (precision < 0) { 433 precision = 0; 434 } 435 } 436 437 /* Process qualifier */ 438 439 qualifier = -1; 440 if (*format == 'h' || *format == 'l' || *format == 'L') { 441 qualifier = *format; 442 ++format; 443 444 if (qualifier == 'l' && *format == 'l') { 445 qualifier = 'L'; 446 ++format; 447 } 448 } 449 450 switch (*format) { 451 case '%': 452 453 pos = acpi_ut_bound_string_output(pos, end, '%'); 454 continue; 455 456 case 'c': 457 458 if (!(type & ACPI_FORMAT_LEFT)) { 459 while (--width > 0) { 460 pos = 461 acpi_ut_bound_string_output(pos, 462 end, 463 ' '); 464 } 465 } 466 467 c = (char)va_arg(args, int); 468 pos = acpi_ut_bound_string_output(pos, end, c); 469 470 while (--width > 0) { 471 pos = 472 acpi_ut_bound_string_output(pos, end, ' '); 473 } 474 continue; 475 476 case 's': 477 478 s = va_arg(args, char *); 479 if (!s) { 480 s = "<NULL>"; 481 } 482 length = acpi_ut_bound_string_length(s, precision); 483 if (!(type & ACPI_FORMAT_LEFT)) { 484 while (length < width--) { 485 pos = 486 acpi_ut_bound_string_output(pos, 487 end, 488 ' '); 489 } 490 } 491 for (i = 0; i < length; ++i) { 492 pos = acpi_ut_bound_string_output(pos, end, *s); 493 ++s; 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 = acpi_ut_format_number(pos, end, 533 ACPI_TO_INTEGER(p), 16, 534 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