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 (ACPI_IS_DIGIT(*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 = 10; 361 u8 type = 0; 362 s32 width = -1; 363 s32 precision = -1; 364 char qualifier = 0; 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 /* Process sign */ 384 385 do { 386 ++format; 387 if (*format == '#') { 388 type |= ACPI_FORMAT_PREFIX; 389 } else if (*format == '0') { 390 type |= ACPI_FORMAT_ZERO; 391 } else if (*format == '+') { 392 type |= ACPI_FORMAT_SIGN_PLUS; 393 } else if (*format == ' ') { 394 type |= ACPI_FORMAT_SIGN_PLUS_SPACE; 395 } else if (*format == '-') { 396 type |= ACPI_FORMAT_LEFT; 397 } else { 398 break; 399 } 400 } while (1); 401 402 /* Process width */ 403 404 width = -1; 405 if (ACPI_IS_DIGIT(*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 (ACPI_IS_DIGIT(*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 if (precision < 0) { 430 precision = 0; 431 } 432 } 433 434 /* Process qualifier */ 435 436 qualifier = -1; 437 if (*format == 'h' || *format == 'l' || *format == 'L') { 438 qualifier = *format; 439 ++format; 440 441 if (qualifier == 'l' && *format == 'l') { 442 qualifier = 'L'; 443 ++format; 444 } 445 } 446 447 switch (*format) { 448 case '%': 449 450 pos = acpi_ut_bound_string_output(pos, end, '%'); 451 continue; 452 453 case 'c': 454 455 if (!(type & ACPI_FORMAT_LEFT)) { 456 while (--width > 0) { 457 pos = 458 acpi_ut_bound_string_output(pos, 459 end, 460 ' '); 461 } 462 } 463 464 c = (char)va_arg(args, int); 465 pos = acpi_ut_bound_string_output(pos, end, c); 466 467 while (--width > 0) { 468 pos = 469 acpi_ut_bound_string_output(pos, end, ' '); 470 } 471 continue; 472 473 case 's': 474 475 s = va_arg(args, char *); 476 if (!s) { 477 s = "<NULL>"; 478 } 479 length = acpi_ut_bound_string_length(s, precision); 480 if (!(type & ACPI_FORMAT_LEFT)) { 481 while (length < width--) { 482 pos = 483 acpi_ut_bound_string_output(pos, 484 end, 485 ' '); 486 } 487 } 488 for (i = 0; i < length; ++i) { 489 pos = acpi_ut_bound_string_output(pos, end, *s); 490 ++s; 491 } 492 while (length < width--) { 493 pos = 494 acpi_ut_bound_string_output(pos, end, ' '); 495 } 496 continue; 497 498 case 'o': 499 500 base = 8; 501 break; 502 503 case 'X': 504 505 type |= ACPI_FORMAT_UPPER; 506 507 case 'x': 508 509 base = 16; 510 break; 511 512 case 'd': 513 case 'i': 514 515 type |= ACPI_FORMAT_SIGN; 516 517 case 'u': 518 519 break; 520 521 case 'p': 522 523 if (width == -1) { 524 width = 2 * sizeof(void *); 525 type |= ACPI_FORMAT_ZERO; 526 } 527 528 p = va_arg(args, void *); 529 pos = acpi_ut_format_number(pos, end, 530 ACPI_TO_INTEGER(p), 16, 531 width, precision, type); 532 continue; 533 534 default: 535 536 pos = acpi_ut_bound_string_output(pos, end, '%'); 537 if (*format) { 538 pos = 539 acpi_ut_bound_string_output(pos, end, 540 *format); 541 } else { 542 --format; 543 } 544 continue; 545 } 546 547 if (qualifier == 'L') { 548 number = va_arg(args, u64); 549 if (type & ACPI_FORMAT_SIGN) { 550 number = (s64) number; 551 } 552 } else if (qualifier == 'l') { 553 number = va_arg(args, unsigned long); 554 if (type & ACPI_FORMAT_SIGN) { 555 number = (s32) number; 556 } 557 } else if (qualifier == 'h') { 558 number = (u16)va_arg(args, int); 559 if (type & ACPI_FORMAT_SIGN) { 560 number = (s16) number; 561 } 562 } else { 563 number = va_arg(args, unsigned int); 564 if (type & ACPI_FORMAT_SIGN) { 565 number = (signed int)number; 566 } 567 } 568 569 pos = acpi_ut_format_number(pos, end, number, base, 570 width, precision, type); 571 } 572 573 if (size > 0) { 574 if (pos < end) { 575 *pos = '\0'; 576 } else { 577 end[-1] = '\0'; 578 } 579 } 580 581 return (ACPI_PTR_DIFF(pos, string)); 582 } 583 584 /******************************************************************************* 585 * 586 * FUNCTION: acpi_ut_snprintf 587 * 588 * PARAMETERS: string - String with boundary 589 * size - Boundary of the string 590 * Format, ... - Standard printf format 591 * 592 * RETURN: Number of bytes actually written. 593 * 594 * DESCRIPTION: Formatted output to a string. 595 * 596 ******************************************************************************/ 597 598 int acpi_ut_snprintf(char *string, acpi_size size, const char *format, ...) 599 { 600 va_list args; 601 int length; 602 603 va_start(args, format); 604 length = acpi_ut_vsnprintf(string, size, format, args); 605 va_end(args); 606 607 return (length); 608 } 609 610 #ifdef ACPI_APPLICATION 611 /******************************************************************************* 612 * 613 * FUNCTION: acpi_ut_file_vprintf 614 * 615 * PARAMETERS: file - File descriptor 616 * format - Standard printf format 617 * args - Argument list 618 * 619 * RETURN: Number of bytes actually written. 620 * 621 * DESCRIPTION: Formatted output to a file using argument list pointer. 622 * 623 ******************************************************************************/ 624 625 int acpi_ut_file_vprintf(ACPI_FILE file, const char *format, va_list args) 626 { 627 acpi_cpu_flags flags; 628 int length; 629 630 flags = acpi_os_acquire_lock(acpi_gbl_print_lock); 631 length = acpi_ut_vsnprintf(acpi_gbl_print_buffer, 632 sizeof(acpi_gbl_print_buffer), format, args); 633 634 (void)acpi_os_write_file(file, acpi_gbl_print_buffer, length, 1); 635 acpi_os_release_lock(acpi_gbl_print_lock, flags); 636 637 return (length); 638 } 639 640 /******************************************************************************* 641 * 642 * FUNCTION: acpi_ut_file_printf 643 * 644 * PARAMETERS: file - File descriptor 645 * Format, ... - Standard printf format 646 * 647 * RETURN: Number of bytes actually written. 648 * 649 * DESCRIPTION: Formatted output to a file. 650 * 651 ******************************************************************************/ 652 653 int acpi_ut_file_printf(ACPI_FILE file, const char *format, ...) 654 { 655 va_list args; 656 int length; 657 658 va_start(args, format); 659 length = acpi_ut_file_vprintf(file, format, args); 660 va_end(args); 661 662 return (length); 663 } 664 #endif 665