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