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