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