1 /* 2 * linux/lib/vsprintf.c 3 * 4 * Copyright (C) 1991, 1992 Linus Torvalds 5 */ 6 7 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ 8 /* 9 * Wirzenius wrote this portably, Torvalds fucked it up :-) 10 * 11 * from hush: simple_itoa() was lifted from boa-0.93.15 12 */ 13 14 #include <stdarg.h> 15 #include <linux/types.h> 16 #include <linux/string.h> 17 #include <linux/ctype.h> 18 19 #include <common.h> 20 #include <charset.h> 21 22 #include <div64.h> 23 #define noinline __attribute__((noinline)) 24 25 /* we use this so that we can do without the ctype library */ 26 #define is_digit(c) ((c) >= '0' && (c) <= '9') 27 28 static int skip_atoi(const char **s) 29 { 30 int i = 0; 31 32 while (is_digit(**s)) 33 i = i * 10 + *((*s)++) - '0'; 34 35 return i; 36 } 37 38 /* Decimal conversion is by far the most typical, and is used 39 * for /proc and /sys data. This directly impacts e.g. top performance 40 * with many processes running. We optimize it for speed 41 * using code from 42 * http://www.cs.uiowa.edu/~jones/bcd/decimal.html 43 * (with permission from the author, Douglas W. Jones). */ 44 45 /* Formats correctly any integer in [0,99999]. 46 * Outputs from one to five digits depending on input. 47 * On i386 gcc 4.1.2 -O2: ~250 bytes of code. */ 48 static char *put_dec_trunc(char *buf, unsigned q) 49 { 50 unsigned d3, d2, d1, d0; 51 d1 = (q>>4) & 0xf; 52 d2 = (q>>8) & 0xf; 53 d3 = (q>>12); 54 55 d0 = 6*(d3 + d2 + d1) + (q & 0xf); 56 q = (d0 * 0xcd) >> 11; 57 d0 = d0 - 10*q; 58 *buf++ = d0 + '0'; /* least significant digit */ 59 d1 = q + 9*d3 + 5*d2 + d1; 60 if (d1 != 0) { 61 q = (d1 * 0xcd) >> 11; 62 d1 = d1 - 10*q; 63 *buf++ = d1 + '0'; /* next digit */ 64 65 d2 = q + 2*d2; 66 if ((d2 != 0) || (d3 != 0)) { 67 q = (d2 * 0xd) >> 7; 68 d2 = d2 - 10*q; 69 *buf++ = d2 + '0'; /* next digit */ 70 71 d3 = q + 4*d3; 72 if (d3 != 0) { 73 q = (d3 * 0xcd) >> 11; 74 d3 = d3 - 10*q; 75 *buf++ = d3 + '0'; /* next digit */ 76 if (q != 0) 77 *buf++ = q + '0'; /* most sign. digit */ 78 } 79 } 80 } 81 return buf; 82 } 83 /* Same with if's removed. Always emits five digits */ 84 static char *put_dec_full(char *buf, unsigned q) 85 { 86 /* BTW, if q is in [0,9999], 8-bit ints will be enough, */ 87 /* but anyway, gcc produces better code with full-sized ints */ 88 unsigned d3, d2, d1, d0; 89 d1 = (q>>4) & 0xf; 90 d2 = (q>>8) & 0xf; 91 d3 = (q>>12); 92 93 /* 94 * Possible ways to approx. divide by 10 95 * gcc -O2 replaces multiply with shifts and adds 96 * (x * 0xcd) >> 11: 11001101 - shorter code than * 0x67 (on i386) 97 * (x * 0x67) >> 10: 1100111 98 * (x * 0x34) >> 9: 110100 - same 99 * (x * 0x1a) >> 8: 11010 - same 100 * (x * 0x0d) >> 7: 1101 - same, shortest code (on i386) 101 */ 102 103 d0 = 6*(d3 + d2 + d1) + (q & 0xf); 104 q = (d0 * 0xcd) >> 11; 105 d0 = d0 - 10*q; 106 *buf++ = d0 + '0'; 107 d1 = q + 9*d3 + 5*d2 + d1; 108 q = (d1 * 0xcd) >> 11; 109 d1 = d1 - 10*q; 110 *buf++ = d1 + '0'; 111 112 d2 = q + 2*d2; 113 q = (d2 * 0xd) >> 7; 114 d2 = d2 - 10*q; 115 *buf++ = d2 + '0'; 116 117 d3 = q + 4*d3; 118 q = (d3 * 0xcd) >> 11; /* - shorter code */ 119 /* q = (d3 * 0x67) >> 10; - would also work */ 120 d3 = d3 - 10*q; 121 *buf++ = d3 + '0'; 122 *buf++ = q + '0'; 123 return buf; 124 } 125 /* No inlining helps gcc to use registers better */ 126 static noinline char *put_dec(char *buf, uint64_t num) 127 { 128 while (1) { 129 unsigned rem; 130 if (num < 100000) 131 return put_dec_trunc(buf, num); 132 rem = do_div(num, 100000); 133 buf = put_dec_full(buf, rem); 134 } 135 } 136 137 #define ZEROPAD 1 /* pad with zero */ 138 #define SIGN 2 /* unsigned/signed long */ 139 #define PLUS 4 /* show plus */ 140 #define SPACE 8 /* space if plus */ 141 #define LEFT 16 /* left justified */ 142 #define SMALL 32 /* Must be 32 == 0x20 */ 143 #define SPECIAL 64 /* 0x */ 144 145 /* 146 * Macro to add a new character to our output string, but only if it will 147 * fit. The macro moves to the next character position in the output string. 148 */ 149 #define ADDCH(str, ch) do { \ 150 if ((str) < end) \ 151 *(str) = (ch); \ 152 ++str; \ 153 } while (0) 154 155 static char *number(char *buf, char *end, u64 num, 156 int base, int size, int precision, int type) 157 { 158 /* we are called with base 8, 10 or 16, only, thus don't need "G..." */ 159 static const char digits[16] = "0123456789ABCDEF"; 160 161 char tmp[66]; 162 char sign; 163 char locase; 164 int need_pfx = ((type & SPECIAL) && base != 10); 165 int i; 166 167 /* locase = 0 or 0x20. ORing digits or letters with 'locase' 168 * produces same digits or (maybe lowercased) letters */ 169 locase = (type & SMALL); 170 if (type & LEFT) 171 type &= ~ZEROPAD; 172 sign = 0; 173 if (type & SIGN) { 174 if ((s64) num < 0) { 175 sign = '-'; 176 num = -(s64) num; 177 size--; 178 } else if (type & PLUS) { 179 sign = '+'; 180 size--; 181 } else if (type & SPACE) { 182 sign = ' '; 183 size--; 184 } 185 } 186 if (need_pfx) { 187 size--; 188 if (base == 16) 189 size--; 190 } 191 192 /* generate full string in tmp[], in reverse order */ 193 i = 0; 194 if (num == 0) 195 tmp[i++] = '0'; 196 /* Generic code, for any base: 197 else do { 198 tmp[i++] = (digits[do_div(num,base)] | locase); 199 } while (num != 0); 200 */ 201 else if (base != 10) { /* 8 or 16 */ 202 int mask = base - 1; 203 int shift = 3; 204 205 if (base == 16) 206 shift = 4; 207 208 do { 209 tmp[i++] = (digits[((unsigned char)num) & mask] 210 | locase); 211 num >>= shift; 212 } while (num); 213 } else { /* base 10 */ 214 i = put_dec(tmp, num) - tmp; 215 } 216 217 /* printing 100 using %2d gives "100", not "00" */ 218 if (i > precision) 219 precision = i; 220 /* leading space padding */ 221 size -= precision; 222 if (!(type & (ZEROPAD + LEFT))) { 223 while (--size >= 0) 224 ADDCH(buf, ' '); 225 } 226 /* sign */ 227 if (sign) 228 ADDCH(buf, sign); 229 /* "0x" / "0" prefix */ 230 if (need_pfx) { 231 ADDCH(buf, '0'); 232 if (base == 16) 233 ADDCH(buf, 'X' | locase); 234 } 235 /* zero or space padding */ 236 if (!(type & LEFT)) { 237 char c = (type & ZEROPAD) ? '0' : ' '; 238 239 while (--size >= 0) 240 ADDCH(buf, c); 241 } 242 /* hmm even more zero padding? */ 243 while (i <= --precision) 244 ADDCH(buf, '0'); 245 /* actual digits of result */ 246 while (--i >= 0) 247 ADDCH(buf, tmp[i]); 248 /* trailing space padding */ 249 while (--size >= 0) 250 ADDCH(buf, ' '); 251 return buf; 252 } 253 254 static char *string(char *buf, char *end, char *s, int field_width, 255 int precision, int flags) 256 { 257 int len, i; 258 259 if (s == NULL) 260 s = "<NULL>"; 261 262 len = strnlen(s, precision); 263 264 if (!(flags & LEFT)) 265 while (len < field_width--) 266 ADDCH(buf, ' '); 267 for (i = 0; i < len; ++i) 268 ADDCH(buf, *s++); 269 while (len < field_width--) 270 ADDCH(buf, ' '); 271 return buf; 272 } 273 274 static char *string16(char *buf, char *end, u16 *s, int field_width, 275 int precision, int flags) 276 { 277 u16 *str = s ? s : L"<NULL>"; 278 int utf16_len = utf16_strnlen(str, precision); 279 u8 utf8[utf16_len * MAX_UTF8_PER_UTF16]; 280 int utf8_len, i; 281 282 utf8_len = utf16_to_utf8(utf8, str, utf16_len) - utf8; 283 284 if (!(flags & LEFT)) 285 while (utf8_len < field_width--) 286 ADDCH(buf, ' '); 287 for (i = 0; i < utf8_len; ++i) 288 ADDCH(buf, utf8[i]); 289 while (utf8_len < field_width--) 290 ADDCH(buf, ' '); 291 return buf; 292 } 293 294 #ifdef CONFIG_CMD_NET 295 static const char hex_asc[] = "0123456789abcdef"; 296 #define hex_asc_lo(x) hex_asc[((x) & 0x0f)] 297 #define hex_asc_hi(x) hex_asc[((x) & 0xf0) >> 4] 298 299 static inline char *pack_hex_byte(char *buf, u8 byte) 300 { 301 *buf++ = hex_asc_hi(byte); 302 *buf++ = hex_asc_lo(byte); 303 return buf; 304 } 305 306 static char *mac_address_string(char *buf, char *end, u8 *addr, int field_width, 307 int precision, int flags) 308 { 309 /* (6 * 2 hex digits), 5 colons and trailing zero */ 310 char mac_addr[6 * 3]; 311 char *p = mac_addr; 312 int i; 313 314 for (i = 0; i < 6; i++) { 315 p = pack_hex_byte(p, addr[i]); 316 if (!(flags & SPECIAL) && i != 5) 317 *p++ = ':'; 318 } 319 *p = '\0'; 320 321 return string(buf, end, mac_addr, field_width, precision, 322 flags & ~SPECIAL); 323 } 324 325 static char *ip6_addr_string(char *buf, char *end, u8 *addr, int field_width, 326 int precision, int flags) 327 { 328 /* (8 * 4 hex digits), 7 colons and trailing zero */ 329 char ip6_addr[8 * 5]; 330 char *p = ip6_addr; 331 int i; 332 333 for (i = 0; i < 8; i++) { 334 p = pack_hex_byte(p, addr[2 * i]); 335 p = pack_hex_byte(p, addr[2 * i + 1]); 336 if (!(flags & SPECIAL) && i != 7) 337 *p++ = ':'; 338 } 339 *p = '\0'; 340 341 return string(buf, end, ip6_addr, field_width, precision, 342 flags & ~SPECIAL); 343 } 344 345 static char *ip4_addr_string(char *buf, char *end, u8 *addr, int field_width, 346 int precision, int flags) 347 { 348 /* (4 * 3 decimal digits), 3 dots and trailing zero */ 349 char ip4_addr[4 * 4]; 350 char temp[3]; /* hold each IP quad in reverse order */ 351 char *p = ip4_addr; 352 int i, digits; 353 354 for (i = 0; i < 4; i++) { 355 digits = put_dec_trunc(temp, addr[i]) - temp; 356 /* reverse the digits in the quad */ 357 while (digits--) 358 *p++ = temp[digits]; 359 if (i != 3) 360 *p++ = '.'; 361 } 362 *p = '\0'; 363 364 return string(buf, end, ip4_addr, field_width, precision, 365 flags & ~SPECIAL); 366 } 367 #endif 368 369 /* 370 * Show a '%p' thing. A kernel extension is that the '%p' is followed 371 * by an extra set of alphanumeric characters that are extended format 372 * specifiers. 373 * 374 * Right now we handle: 375 * 376 * - 'M' For a 6-byte MAC address, it prints the address in the 377 * usual colon-separated hex notation 378 * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way (dot-separated 379 * decimal for v4 and colon separated network-order 16 bit hex for v6) 380 * - 'i' [46] for 'raw' IPv4/IPv6 addresses, IPv6 omits the colons, IPv4 is 381 * currently the same 382 * 383 * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 384 * function pointers are really function descriptors, which contain a 385 * pointer to the real address. 386 */ 387 static char *pointer(const char *fmt, char *buf, char *end, void *ptr, 388 int field_width, int precision, int flags) 389 { 390 u64 num = (uintptr_t)ptr; 391 392 /* 393 * Being a boot loader, we explicitly allow pointers to 394 * (physical) address null. 395 */ 396 #if 0 397 if (!ptr) 398 return string(buf, end, "(null)", field_width, precision, 399 flags); 400 #endif 401 402 #ifdef CONFIG_CMD_NET 403 switch (*fmt) { 404 case 'a': 405 flags |= SPECIAL | ZEROPAD; 406 407 switch (fmt[1]) { 408 case 'p': 409 default: 410 field_width = sizeof(phys_addr_t) * 2 + 2; 411 num = *(phys_addr_t *)ptr; 412 break; 413 } 414 break; 415 case 'm': 416 flags |= SPECIAL; 417 /* Fallthrough */ 418 case 'M': 419 return mac_address_string(buf, end, ptr, field_width, 420 precision, flags); 421 case 'i': 422 flags |= SPECIAL; 423 /* Fallthrough */ 424 case 'I': 425 if (fmt[1] == '6') 426 return ip6_addr_string(buf, end, ptr, field_width, 427 precision, flags); 428 if (fmt[1] == '4') 429 return ip4_addr_string(buf, end, ptr, field_width, 430 precision, flags); 431 flags &= ~SPECIAL; 432 break; 433 } 434 #endif 435 flags |= SMALL; 436 if (field_width == -1) { 437 field_width = 2*sizeof(void *); 438 flags |= ZEROPAD; 439 } 440 return number(buf, end, num, 16, field_width, precision, flags); 441 } 442 443 static int vsnprintf_internal(char *buf, size_t size, const char *fmt, 444 va_list args) 445 { 446 u64 num; 447 int base; 448 char *str; 449 450 int flags; /* flags to number() */ 451 452 int field_width; /* width of output field */ 453 int precision; /* min. # of digits for integers; max 454 number of chars for from string */ 455 int qualifier; /* 'h', 'l', or 'L' for integer fields */ 456 /* 'z' support added 23/7/1999 S.H. */ 457 /* 'z' changed to 'Z' --davidm 1/25/99 */ 458 /* 't' added for ptrdiff_t */ 459 char *end = buf + size; 460 461 /* Make sure end is always >= buf - do we want this in U-Boot? */ 462 if (end < buf) { 463 end = ((void *)-1); 464 size = end - buf; 465 } 466 str = buf; 467 468 for (; *fmt ; ++fmt) { 469 if (*fmt != '%') { 470 ADDCH(str, *fmt); 471 continue; 472 } 473 474 /* process flags */ 475 flags = 0; 476 repeat: 477 ++fmt; /* this also skips first '%' */ 478 switch (*fmt) { 479 case '-': 480 flags |= LEFT; 481 goto repeat; 482 case '+': 483 flags |= PLUS; 484 goto repeat; 485 case ' ': 486 flags |= SPACE; 487 goto repeat; 488 case '#': 489 flags |= SPECIAL; 490 goto repeat; 491 case '0': 492 flags |= ZEROPAD; 493 goto repeat; 494 } 495 496 /* get field width */ 497 field_width = -1; 498 if (is_digit(*fmt)) 499 field_width = skip_atoi(&fmt); 500 else if (*fmt == '*') { 501 ++fmt; 502 /* it's the next argument */ 503 field_width = va_arg(args, int); 504 if (field_width < 0) { 505 field_width = -field_width; 506 flags |= LEFT; 507 } 508 } 509 510 /* get the precision */ 511 precision = -1; 512 if (*fmt == '.') { 513 ++fmt; 514 if (is_digit(*fmt)) 515 precision = skip_atoi(&fmt); 516 else if (*fmt == '*') { 517 ++fmt; 518 /* it's the next argument */ 519 precision = va_arg(args, int); 520 } 521 if (precision < 0) 522 precision = 0; 523 } 524 525 /* get the conversion qualifier */ 526 qualifier = -1; 527 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || 528 *fmt == 'Z' || *fmt == 'z' || *fmt == 't') { 529 qualifier = *fmt; 530 ++fmt; 531 if (qualifier == 'l' && *fmt == 'l') { 532 qualifier = 'L'; 533 ++fmt; 534 } 535 } 536 537 /* default base */ 538 base = 10; 539 540 switch (*fmt) { 541 case 'c': 542 if (!(flags & LEFT)) { 543 while (--field_width > 0) 544 ADDCH(str, ' '); 545 } 546 ADDCH(str, (unsigned char) va_arg(args, int)); 547 while (--field_width > 0) 548 ADDCH(str, ' '); 549 continue; 550 551 case 's': 552 if (qualifier == 'l' && !IS_ENABLED(CONFIG_SPL_BUILD)) { 553 str = string16(str, end, va_arg(args, u16 *), 554 field_width, precision, flags); 555 } else { 556 str = string(str, end, va_arg(args, char *), 557 field_width, precision, flags); 558 } 559 continue; 560 561 case 'p': 562 str = pointer(fmt + 1, str, end, 563 va_arg(args, void *), 564 field_width, precision, flags); 565 /* Skip all alphanumeric pointer suffixes */ 566 while (isalnum(fmt[1])) 567 fmt++; 568 continue; 569 570 case 'n': 571 if (qualifier == 'l') { 572 long *ip = va_arg(args, long *); 573 *ip = (str - buf); 574 } else { 575 int *ip = va_arg(args, int *); 576 *ip = (str - buf); 577 } 578 continue; 579 580 case '%': 581 ADDCH(str, '%'); 582 continue; 583 584 /* integer number formats - set up the flags and "break" */ 585 case 'o': 586 base = 8; 587 break; 588 589 case 'x': 590 flags |= SMALL; 591 case 'X': 592 base = 16; 593 break; 594 595 case 'd': 596 case 'i': 597 flags |= SIGN; 598 case 'u': 599 break; 600 601 default: 602 ADDCH(str, '%'); 603 if (*fmt) 604 ADDCH(str, *fmt); 605 else 606 --fmt; 607 continue; 608 } 609 if (qualifier == 'L') /* "quad" for 64 bit variables */ 610 num = va_arg(args, unsigned long long); 611 else if (qualifier == 'l') { 612 num = va_arg(args, unsigned long); 613 if (flags & SIGN) 614 num = (signed long) num; 615 } else if (qualifier == 'Z' || qualifier == 'z') { 616 num = va_arg(args, size_t); 617 } else if (qualifier == 't') { 618 num = va_arg(args, ptrdiff_t); 619 } else if (qualifier == 'h') { 620 num = (unsigned short) va_arg(args, int); 621 if (flags & SIGN) 622 num = (signed short) num; 623 } else { 624 num = va_arg(args, unsigned int); 625 if (flags & SIGN) 626 num = (signed int) num; 627 } 628 str = number(str, end, num, base, field_width, precision, 629 flags); 630 } 631 632 if (size > 0) { 633 ADDCH(str, '\0'); 634 if (str > end) 635 end[-1] = '\0'; 636 --str; 637 } 638 /* the trailing null byte doesn't count towards the total */ 639 return str - buf; 640 } 641 642 int vsnprintf(char *buf, size_t size, const char *fmt, 643 va_list args) 644 { 645 return vsnprintf_internal(buf, size, fmt, args); 646 } 647 648 int vscnprintf(char *buf, size_t size, const char *fmt, va_list args) 649 { 650 int i; 651 652 i = vsnprintf(buf, size, fmt, args); 653 654 if (likely(i < size)) 655 return i; 656 if (size != 0) 657 return size - 1; 658 return 0; 659 } 660 661 int snprintf(char *buf, size_t size, const char *fmt, ...) 662 { 663 va_list args; 664 int i; 665 666 va_start(args, fmt); 667 i = vsnprintf(buf, size, fmt, args); 668 va_end(args); 669 670 return i; 671 } 672 673 int scnprintf(char *buf, size_t size, const char *fmt, ...) 674 { 675 va_list args; 676 int i; 677 678 va_start(args, fmt); 679 i = vscnprintf(buf, size, fmt, args); 680 va_end(args); 681 682 return i; 683 } 684 685 /** 686 * Format a string and place it in a buffer (va_list version) 687 * 688 * @param buf The buffer to place the result into 689 * @param fmt The format string to use 690 * @param args Arguments for the format string 691 * 692 * The function returns the number of characters written 693 * into @buf. Use vsnprintf() or vscnprintf() in order to avoid 694 * buffer overflows. 695 * 696 * If you're not already dealing with a va_list consider using sprintf(). 697 */ 698 int vsprintf(char *buf, const char *fmt, va_list args) 699 { 700 return vsnprintf_internal(buf, INT_MAX, fmt, args); 701 } 702 703 int sprintf(char *buf, const char *fmt, ...) 704 { 705 va_list args; 706 int i; 707 708 va_start(args, fmt); 709 i = vsprintf(buf, fmt, args); 710 va_end(args); 711 return i; 712 } 713 714 int printf(const char *fmt, ...) 715 { 716 va_list args; 717 uint i; 718 char printbuffer[CONFIG_SYS_PBSIZE]; 719 720 va_start(args, fmt); 721 722 /* 723 * For this to work, printbuffer must be larger than 724 * anything we ever want to print. 725 */ 726 i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args); 727 va_end(args); 728 729 /* Print the string */ 730 puts(printbuffer); 731 return i; 732 } 733 734 int vprintf(const char *fmt, va_list args) 735 { 736 uint i; 737 char printbuffer[CONFIG_SYS_PBSIZE]; 738 739 /* 740 * For this to work, printbuffer must be larger than 741 * anything we ever want to print. 742 */ 743 i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args); 744 745 /* Print the string */ 746 puts(printbuffer); 747 return i; 748 } 749 750 751 void __assert_fail(const char *assertion, const char *file, unsigned line, 752 const char *function) 753 { 754 /* This will not return */ 755 panic("%s:%u: %s: Assertion `%s' failed.", file, line, function, 756 assertion); 757 } 758 759 char *simple_itoa(ulong i) 760 { 761 /* 21 digits plus null terminator, good for 64-bit or smaller ints */ 762 static char local[22]; 763 char *p = &local[21]; 764 765 *p-- = '\0'; 766 do { 767 *p-- = '0' + i % 10; 768 i /= 10; 769 } while (i > 0); 770 return p + 1; 771 } 772 773 /* We don't seem to have %'d in U-Boot */ 774 void print_grouped_ull(unsigned long long int_val, int digits) 775 { 776 char str[21], *s; 777 int grab = 3; 778 779 digits = (digits + 2) / 3; 780 sprintf(str, "%*llu", digits * 3, int_val); 781 for (s = str; *s; s += grab) { 782 if (s != str) 783 putc(s[-1] != ' ' ? ',' : ' '); 784 printf("%.*s", grab, s); 785 grab = 3; 786 } 787 } 788 789 bool str2off(const char *p, loff_t *num) 790 { 791 char *endptr; 792 793 *num = simple_strtoull(p, &endptr, 16); 794 return *p != '\0' && *endptr == '\0'; 795 } 796 797 bool str2long(const char *p, ulong *num) 798 { 799 char *endptr; 800 801 *num = simple_strtoul(p, &endptr, 16); 802 return *p != '\0' && *endptr == '\0'; 803 } 804