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/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 sign; 246 char zero; 247 u8 need_prefix; 248 u8 upper; 249 s32 i; 250 char reversed_string[66]; 251 252 /* Parameter validation */ 253 254 if (base < 2 || base > 16) { 255 return (NULL); 256 } 257 258 if (type & ACPI_FORMAT_LEFT) { 259 type &= ~ACPI_FORMAT_ZERO; 260 } 261 262 need_prefix = ((type & ACPI_FORMAT_PREFIX) 263 && base != 10) ? TRUE : FALSE; 264 upper = (type & ACPI_FORMAT_UPPER) ? TRUE : FALSE; 265 zero = (type & ACPI_FORMAT_ZERO) ? '0' : ' '; 266 267 /* Calculate size according to sign and prefix */ 268 269 sign = '\0'; 270 if (type & ACPI_FORMAT_SIGN) { 271 if ((s64) number < 0) { 272 sign = '-'; 273 number = -(s64) number; 274 width--; 275 } else if (type & ACPI_FORMAT_SIGN_PLUS) { 276 sign = '+'; 277 width--; 278 } else if (type & ACPI_FORMAT_SIGN_PLUS_SPACE) { 279 sign = ' '; 280 width--; 281 } 282 } 283 if (need_prefix) { 284 width--; 285 if (base == 16) { 286 width--; 287 } 288 } 289 290 /* Generate full string in reverse order */ 291 292 i = ACPI_PTR_DIFF(acpi_ut_put_number 293 (reversed_string, number, base, upper), 294 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 if (ACPI_IS_DIGIT(*format)) { 405 format = acpi_ut_scan_number(format, &number); 406 width = (s32) number; 407 } else if (*format == '*') { 408 ++format; 409 width = va_arg(args, int); 410 if (width < 0) { 411 width = -width; 412 type |= ACPI_FORMAT_LEFT; 413 } 414 } 415 416 /* Process precision */ 417 418 if (*format == '.') { 419 ++format; 420 if (ACPI_IS_DIGIT(*format)) { 421 format = acpi_ut_scan_number(format, &number); 422 precision = (s32) number; 423 } else if (*format == '*') { 424 ++format; 425 precision = va_arg(args, int); 426 } 427 if (precision < 0) { 428 precision = 0; 429 } 430 } 431 432 /* Process qualifier */ 433 434 if (*format == 'h' || *format == 'l' || *format == 'L') { 435 qualifier = *format; 436 ++format; 437 438 if (qualifier == 'l' && *format == 'l') { 439 qualifier = 'L'; 440 ++format; 441 } 442 } 443 444 switch (*format) { 445 case '%': 446 447 pos = acpi_ut_bound_string_output(pos, end, '%'); 448 continue; 449 450 case 'c': 451 452 if (!(type & ACPI_FORMAT_LEFT)) { 453 while (--width > 0) { 454 pos = 455 acpi_ut_bound_string_output(pos, 456 end, 457 ' '); 458 } 459 } 460 461 c = (char)va_arg(args, int); 462 pos = acpi_ut_bound_string_output(pos, end, c); 463 464 while (--width > 0) { 465 pos = 466 acpi_ut_bound_string_output(pos, end, ' '); 467 } 468 continue; 469 470 case 's': 471 472 s = va_arg(args, char *); 473 if (!s) { 474 s = "<NULL>"; 475 } 476 length = acpi_ut_bound_string_length(s, precision); 477 if (!(type & ACPI_FORMAT_LEFT)) { 478 while (length < width--) { 479 pos = 480 acpi_ut_bound_string_output(pos, 481 end, 482 ' '); 483 } 484 } 485 for (i = 0; i < length; ++i) { 486 pos = acpi_ut_bound_string_output(pos, end, *s); 487 ++s; 488 } 489 while (length < width--) { 490 pos = 491 acpi_ut_bound_string_output(pos, end, ' '); 492 } 493 continue; 494 495 case 'o': 496 497 base = 8; 498 break; 499 500 case 'X': 501 502 type |= ACPI_FORMAT_UPPER; 503 504 case 'x': 505 506 base = 16; 507 break; 508 509 case 'd': 510 case 'i': 511 512 type |= ACPI_FORMAT_SIGN; 513 514 case 'u': 515 516 break; 517 518 case 'p': 519 520 if (width == -1) { 521 width = 2 * sizeof(void *); 522 type |= ACPI_FORMAT_ZERO; 523 } 524 525 p = va_arg(args, void *); 526 pos = acpi_ut_format_number(pos, end, 527 ACPI_TO_INTEGER(p), 16, 528 width, precision, type); 529 continue; 530 531 default: 532 533 pos = acpi_ut_bound_string_output(pos, end, '%'); 534 if (*format) { 535 pos = 536 acpi_ut_bound_string_output(pos, end, 537 *format); 538 } else { 539 --format; 540 } 541 continue; 542 } 543 544 if (qualifier == 'L') { 545 number = va_arg(args, u64); 546 if (type & ACPI_FORMAT_SIGN) { 547 number = (s64) number; 548 } 549 } else if (qualifier == 'l') { 550 number = va_arg(args, unsigned long); 551 if (type & ACPI_FORMAT_SIGN) { 552 number = (s32) number; 553 } 554 } else if (qualifier == 'h') { 555 number = (u16)va_arg(args, int); 556 if (type & ACPI_FORMAT_SIGN) { 557 number = (s16) number; 558 } 559 } else { 560 number = va_arg(args, unsigned int); 561 if (type & ACPI_FORMAT_SIGN) { 562 number = (signed int)number; 563 } 564 } 565 566 pos = acpi_ut_format_number(pos, end, number, base, 567 width, precision, type); 568 } 569 570 if (size > 0) { 571 if (pos < end) { 572 *pos = '\0'; 573 } else { 574 end[-1] = '\0'; 575 } 576 } 577 578 return (ACPI_PTR_DIFF(pos, string)); 579 } 580 581 /******************************************************************************* 582 * 583 * FUNCTION: acpi_ut_snprintf 584 * 585 * PARAMETERS: string - String with boundary 586 * size - Boundary of the string 587 * Format, ... - Standard printf format 588 * 589 * RETURN: Number of bytes actually written. 590 * 591 * DESCRIPTION: Formatted output to a string. 592 * 593 ******************************************************************************/ 594 595 int acpi_ut_snprintf(char *string, acpi_size size, const char *format, ...) 596 { 597 va_list args; 598 int length; 599 600 va_start(args, format); 601 length = acpi_ut_vsnprintf(string, size, format, args); 602 va_end(args); 603 604 return (length); 605 } 606 607 #ifdef ACPI_APPLICATION 608 /******************************************************************************* 609 * 610 * FUNCTION: acpi_ut_file_vprintf 611 * 612 * PARAMETERS: file - File descriptor 613 * format - Standard printf format 614 * args - Argument list 615 * 616 * RETURN: Number of bytes actually written. 617 * 618 * DESCRIPTION: Formatted output to a file using argument list pointer. 619 * 620 ******************************************************************************/ 621 622 int acpi_ut_file_vprintf(ACPI_FILE file, const char *format, va_list args) 623 { 624 acpi_cpu_flags flags; 625 int length; 626 627 flags = acpi_os_acquire_lock(acpi_gbl_print_lock); 628 length = acpi_ut_vsnprintf(acpi_gbl_print_buffer, 629 sizeof(acpi_gbl_print_buffer), format, args); 630 631 (void)acpi_os_write_file(file, acpi_gbl_print_buffer, length, 1); 632 acpi_os_release_lock(acpi_gbl_print_lock, flags); 633 634 return (length); 635 } 636 637 /******************************************************************************* 638 * 639 * FUNCTION: acpi_ut_file_printf 640 * 641 * PARAMETERS: file - File descriptor 642 * Format, ... - Standard printf format 643 * 644 * RETURN: Number of bytes actually written. 645 * 646 * DESCRIPTION: Formatted output to a file. 647 * 648 ******************************************************************************/ 649 650 int acpi_ut_file_printf(ACPI_FILE file, const char *format, ...) 651 { 652 va_list args; 653 int length; 654 655 va_start(args, format); 656 length = acpi_ut_file_vprintf(file, format, args); 657 va_end(args); 658 659 return (length); 660 } 661 #endif 662