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