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