12c7d1e30SArvind Sankar // SPDX-License-Identifier: GPL-2.0-only 22c7d1e30SArvind Sankar /* -*- linux-c -*- ------------------------------------------------------- * 32c7d1e30SArvind Sankar * 42c7d1e30SArvind Sankar * Copyright (C) 1991, 1992 Linus Torvalds 52c7d1e30SArvind Sankar * Copyright 2007 rPath, Inc. - All Rights Reserved 62c7d1e30SArvind Sankar * 72c7d1e30SArvind Sankar * ----------------------------------------------------------------------- */ 82c7d1e30SArvind Sankar 92c7d1e30SArvind Sankar /* 10ce5e3f90SArvind Sankar * Oh, it's a waste of space, but oh-so-yummy for debugging. 112c7d1e30SArvind Sankar */ 122c7d1e30SArvind Sankar 132c7d1e30SArvind Sankar #include <stdarg.h> 142c7d1e30SArvind Sankar 152c7d1e30SArvind Sankar #include <linux/compiler.h> 162c7d1e30SArvind Sankar #include <linux/ctype.h> 172c7d1e30SArvind Sankar #include <linux/string.h> 182c7d1e30SArvind Sankar 192c7d1e30SArvind Sankar static int skip_atoi(const char **s) 202c7d1e30SArvind Sankar { 212c7d1e30SArvind Sankar int i = 0; 222c7d1e30SArvind Sankar 232c7d1e30SArvind Sankar while (isdigit(**s)) 242c7d1e30SArvind Sankar i = i * 10 + *((*s)++) - '0'; 252c7d1e30SArvind Sankar return i; 262c7d1e30SArvind Sankar } 272c7d1e30SArvind Sankar 28ce5e3f90SArvind Sankar /* 29ce5e3f90SArvind Sankar * put_dec_full4 handles numbers in the range 0 <= r < 10000. 30ce5e3f90SArvind Sankar * The multiplier 0xccd is round(2^15/10), and the approximation 31ce5e3f90SArvind Sankar * r/10 == (r * 0xccd) >> 15 is exact for all r < 16389. 32ce5e3f90SArvind Sankar */ 33ce5e3f90SArvind Sankar static 34ce5e3f90SArvind Sankar void put_dec_full4(char *buf, unsigned int r) 35ce5e3f90SArvind Sankar { 36ce5e3f90SArvind Sankar int i; 37ce5e3f90SArvind Sankar 38ce5e3f90SArvind Sankar for (i = 0; i < 3; i++) { 39ce5e3f90SArvind Sankar unsigned int q = (r * 0xccd) >> 15; 40ce5e3f90SArvind Sankar *buf++ = '0' + (r - q * 10); 41ce5e3f90SArvind Sankar r = q; 42ce5e3f90SArvind Sankar } 43ce5e3f90SArvind Sankar *buf++ = '0' + r; 44ce5e3f90SArvind Sankar } 45ce5e3f90SArvind Sankar 46ce5e3f90SArvind Sankar /* put_dec is copied from lib/vsprintf.c with small modifications */ 47ce5e3f90SArvind Sankar 48ce5e3f90SArvind Sankar /* 49ce5e3f90SArvind Sankar * Call put_dec_full4 on x % 10000, return x / 10000. 50ce5e3f90SArvind Sankar * The approximation x/10000 == (x * 0x346DC5D7) >> 43 51ce5e3f90SArvind Sankar * holds for all x < 1,128,869,999. The largest value this 52ce5e3f90SArvind Sankar * helper will ever be asked to convert is 1,125,520,955. 53ce5e3f90SArvind Sankar * (second call in the put_dec code, assuming n is all-ones). 54ce5e3f90SArvind Sankar */ 55ce5e3f90SArvind Sankar static 56ce5e3f90SArvind Sankar unsigned int put_dec_helper4(char *buf, unsigned int x) 57ce5e3f90SArvind Sankar { 58ce5e3f90SArvind Sankar unsigned int q = (x * 0x346DC5D7ULL) >> 43; 59ce5e3f90SArvind Sankar 60ce5e3f90SArvind Sankar put_dec_full4(buf, x - q * 10000); 61ce5e3f90SArvind Sankar return q; 62ce5e3f90SArvind Sankar } 63ce5e3f90SArvind Sankar 64ce5e3f90SArvind Sankar /* Based on code by Douglas W. Jones found at 65ce5e3f90SArvind Sankar * <http://www.cs.uiowa.edu/~jones/bcd/decimal.html#sixtyfour> 66ce5e3f90SArvind Sankar * (with permission from the author). 67ce5e3f90SArvind Sankar * Performs no 64-bit division and hence should be fast on 32-bit machines. 68ce5e3f90SArvind Sankar */ 69ce5e3f90SArvind Sankar static 70ce5e3f90SArvind Sankar int put_dec(char *buf, unsigned long long n) 71ce5e3f90SArvind Sankar { 72ce5e3f90SArvind Sankar unsigned int d3, d2, d1, q, h; 73ce5e3f90SArvind Sankar char *p = buf; 74ce5e3f90SArvind Sankar 75ce5e3f90SArvind Sankar d1 = ((unsigned int)n >> 16); /* implicit "& 0xffff" */ 76ce5e3f90SArvind Sankar h = (n >> 32); 77ce5e3f90SArvind Sankar d2 = (h ) & 0xffff; 78ce5e3f90SArvind Sankar d3 = (h >> 16); /* implicit "& 0xffff" */ 79ce5e3f90SArvind Sankar 80ce5e3f90SArvind Sankar /* n = 2^48 d3 + 2^32 d2 + 2^16 d1 + d0 81ce5e3f90SArvind Sankar = 281_4749_7671_0656 d3 + 42_9496_7296 d2 + 6_5536 d1 + d0 */ 82ce5e3f90SArvind Sankar q = 656 * d3 + 7296 * d2 + 5536 * d1 + ((unsigned int)n & 0xffff); 83ce5e3f90SArvind Sankar q = put_dec_helper4(p, q); 84ce5e3f90SArvind Sankar p += 4; 85ce5e3f90SArvind Sankar 86ce5e3f90SArvind Sankar q += 7671 * d3 + 9496 * d2 + 6 * d1; 87ce5e3f90SArvind Sankar q = put_dec_helper4(p, q); 88ce5e3f90SArvind Sankar p += 4; 89ce5e3f90SArvind Sankar 90ce5e3f90SArvind Sankar q += 4749 * d3 + 42 * d2; 91ce5e3f90SArvind Sankar q = put_dec_helper4(p, q); 92ce5e3f90SArvind Sankar p += 4; 93ce5e3f90SArvind Sankar 94ce5e3f90SArvind Sankar q += 281 * d3; 95ce5e3f90SArvind Sankar q = put_dec_helper4(p, q); 96ce5e3f90SArvind Sankar p += 4; 97ce5e3f90SArvind Sankar 98ce5e3f90SArvind Sankar put_dec_full4(p, q); 99ce5e3f90SArvind Sankar p += 4; 100ce5e3f90SArvind Sankar 101ce5e3f90SArvind Sankar /* strip off the extra 0's we printed */ 102ce5e3f90SArvind Sankar while (p > buf && p[-1] == '0') 103ce5e3f90SArvind Sankar --p; 104ce5e3f90SArvind Sankar 105ce5e3f90SArvind Sankar return p - buf; 106ce5e3f90SArvind Sankar } 107ce5e3f90SArvind Sankar 1082c7d1e30SArvind Sankar #define ZEROPAD 1 /* pad with zero */ 1092c7d1e30SArvind Sankar #define SIGN 2 /* unsigned/signed long */ 1102c7d1e30SArvind Sankar #define PLUS 4 /* show plus */ 1112c7d1e30SArvind Sankar #define SPACE 8 /* space if plus */ 1122c7d1e30SArvind Sankar #define LEFT 16 /* left justified */ 1132c7d1e30SArvind Sankar #define SMALL 32 /* Must be 32 == 0x20 */ 1142c7d1e30SArvind Sankar #define SPECIAL 64 /* 0x */ 1152c7d1e30SArvind Sankar 116ce5e3f90SArvind Sankar static char *number(char *str, long long num, int base, int size, int precision, 1172c7d1e30SArvind Sankar int type) 1182c7d1e30SArvind Sankar { 1192c7d1e30SArvind Sankar /* we are called with base 8, 10 or 16, only, thus don't need "G..." */ 1202c7d1e30SArvind Sankar static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */ 1212c7d1e30SArvind Sankar 1222c7d1e30SArvind Sankar char tmp[66]; 1232c7d1e30SArvind Sankar char c, sign, locase; 1242c7d1e30SArvind Sankar int i; 1252c7d1e30SArvind Sankar 1262c7d1e30SArvind Sankar /* locase = 0 or 0x20. ORing digits or letters with 'locase' 1272c7d1e30SArvind Sankar * produces same digits or (maybe lowercased) letters */ 1282c7d1e30SArvind Sankar locase = (type & SMALL); 1292c7d1e30SArvind Sankar if (type & LEFT) 1302c7d1e30SArvind Sankar type &= ~ZEROPAD; 1312c7d1e30SArvind Sankar c = (type & ZEROPAD) ? '0' : ' '; 1322c7d1e30SArvind Sankar sign = 0; 1332c7d1e30SArvind Sankar if (type & SIGN) { 1342c7d1e30SArvind Sankar if (num < 0) { 1352c7d1e30SArvind Sankar sign = '-'; 1362c7d1e30SArvind Sankar num = -num; 1372c7d1e30SArvind Sankar size--; 1382c7d1e30SArvind Sankar } else if (type & PLUS) { 1392c7d1e30SArvind Sankar sign = '+'; 1402c7d1e30SArvind Sankar size--; 1412c7d1e30SArvind Sankar } else if (type & SPACE) { 1422c7d1e30SArvind Sankar sign = ' '; 1432c7d1e30SArvind Sankar size--; 1442c7d1e30SArvind Sankar } 1452c7d1e30SArvind Sankar } 1462c7d1e30SArvind Sankar if (type & SPECIAL) { 1472c7d1e30SArvind Sankar if (base == 16) 1482c7d1e30SArvind Sankar size -= 2; 1492c7d1e30SArvind Sankar else if (base == 8) 1502c7d1e30SArvind Sankar size--; 1512c7d1e30SArvind Sankar } 1522c7d1e30SArvind Sankar i = 0; 1532c7d1e30SArvind Sankar if (num == 0) 1542c7d1e30SArvind Sankar tmp[i++] = '0'; 155ce5e3f90SArvind Sankar else { 156ce5e3f90SArvind Sankar switch (base) { 157ce5e3f90SArvind Sankar case 10: 158ce5e3f90SArvind Sankar i += put_dec(&tmp[i], num); 159ce5e3f90SArvind Sankar break; 160ce5e3f90SArvind Sankar case 8: 161ce5e3f90SArvind Sankar while (num != 0) { 162ce5e3f90SArvind Sankar tmp[i++] = '0' + (num & 07); 163ce5e3f90SArvind Sankar num = (unsigned long long)num >> 3; 164ce5e3f90SArvind Sankar } 165ce5e3f90SArvind Sankar break; 166ce5e3f90SArvind Sankar case 16: 167ce5e3f90SArvind Sankar while (num != 0) { 168ce5e3f90SArvind Sankar tmp[i++] = digits[num & 0xf] | locase; 169ce5e3f90SArvind Sankar num = (unsigned long long)num >> 4; 170ce5e3f90SArvind Sankar } 171ce5e3f90SArvind Sankar break; 172ce5e3f90SArvind Sankar default: 173ce5e3f90SArvind Sankar unreachable(); 174ce5e3f90SArvind Sankar } 175ce5e3f90SArvind Sankar } 176ce5e3f90SArvind Sankar 1772c7d1e30SArvind Sankar if (i > precision) 1782c7d1e30SArvind Sankar precision = i; 1792c7d1e30SArvind Sankar size -= precision; 1802c7d1e30SArvind Sankar if (!(type & (ZEROPAD + LEFT))) 1812c7d1e30SArvind Sankar while (size-- > 0) 1822c7d1e30SArvind Sankar *str++ = ' '; 1832c7d1e30SArvind Sankar if (sign) 1842c7d1e30SArvind Sankar *str++ = sign; 1852c7d1e30SArvind Sankar if (type & SPECIAL) { 1862c7d1e30SArvind Sankar if (base == 8) { 1872c7d1e30SArvind Sankar *str++ = '0'; 1882c7d1e30SArvind Sankar } else if (base == 16) { 1892c7d1e30SArvind Sankar *str++ = '0'; 1902c7d1e30SArvind Sankar *str++ = ('X' | locase); 1912c7d1e30SArvind Sankar } 1922c7d1e30SArvind Sankar } 1932c7d1e30SArvind Sankar if (!(type & LEFT)) 1942c7d1e30SArvind Sankar while (size-- > 0) 1952c7d1e30SArvind Sankar *str++ = c; 1962c7d1e30SArvind Sankar while (i < precision--) 1972c7d1e30SArvind Sankar *str++ = '0'; 1982c7d1e30SArvind Sankar while (i-- > 0) 1992c7d1e30SArvind Sankar *str++ = tmp[i]; 2002c7d1e30SArvind Sankar while (size-- > 0) 2012c7d1e30SArvind Sankar *str++ = ' '; 2022c7d1e30SArvind Sankar return str; 2032c7d1e30SArvind Sankar } 2042c7d1e30SArvind Sankar 2053b835095SArvind Sankar static 2063b835095SArvind Sankar int get_flags(const char **fmt) 2073b835095SArvind Sankar { 2083b835095SArvind Sankar int flags = 0; 2093b835095SArvind Sankar 2103b835095SArvind Sankar do { 2113b835095SArvind Sankar switch (**fmt) { 2123b835095SArvind Sankar case '-': 2133b835095SArvind Sankar flags |= LEFT; 2143b835095SArvind Sankar break; 2153b835095SArvind Sankar case '+': 2163b835095SArvind Sankar flags |= PLUS; 2173b835095SArvind Sankar break; 2183b835095SArvind Sankar case ' ': 2193b835095SArvind Sankar flags |= SPACE; 2203b835095SArvind Sankar break; 2213b835095SArvind Sankar case '#': 2223b835095SArvind Sankar flags |= SPECIAL; 2233b835095SArvind Sankar break; 2243b835095SArvind Sankar case '0': 2253b835095SArvind Sankar flags |= ZEROPAD; 2263b835095SArvind Sankar break; 2273b835095SArvind Sankar default: 2283b835095SArvind Sankar return flags; 2293b835095SArvind Sankar } 2303b835095SArvind Sankar ++(*fmt); 2313b835095SArvind Sankar } while (1); 2323b835095SArvind Sankar } 2333b835095SArvind Sankar 2343fbcf75bSArvind Sankar static 2353fbcf75bSArvind Sankar int get_int(const char **fmt, va_list *ap) 2363fbcf75bSArvind Sankar { 2373fbcf75bSArvind Sankar if (isdigit(**fmt)) 2383fbcf75bSArvind Sankar return skip_atoi(fmt); 2393fbcf75bSArvind Sankar if (**fmt == '*') { 2403fbcf75bSArvind Sankar ++(*fmt); 2413fbcf75bSArvind Sankar /* it's the next argument */ 2423fbcf75bSArvind Sankar return va_arg(*ap, int); 2433fbcf75bSArvind Sankar } 2443fbcf75bSArvind Sankar return 0; 2453fbcf75bSArvind Sankar } 2463fbcf75bSArvind Sankar 247*dec61199SArvind Sankar static 248*dec61199SArvind Sankar unsigned long long get_number(int sign, int qualifier, va_list *ap) 249*dec61199SArvind Sankar { 250*dec61199SArvind Sankar if (sign) { 251*dec61199SArvind Sankar switch (qualifier) { 252*dec61199SArvind Sankar case 'L': 253*dec61199SArvind Sankar return va_arg(*ap, long long); 254*dec61199SArvind Sankar case 'l': 255*dec61199SArvind Sankar return va_arg(*ap, long); 256*dec61199SArvind Sankar case 'h': 257*dec61199SArvind Sankar return (short)va_arg(*ap, int); 258*dec61199SArvind Sankar case 'H': 259*dec61199SArvind Sankar return (signed char)va_arg(*ap, int); 260*dec61199SArvind Sankar default: 261*dec61199SArvind Sankar return va_arg(*ap, int); 262*dec61199SArvind Sankar }; 263*dec61199SArvind Sankar } else { 264*dec61199SArvind Sankar switch (qualifier) { 265*dec61199SArvind Sankar case 'L': 266*dec61199SArvind Sankar return va_arg(*ap, unsigned long long); 267*dec61199SArvind Sankar case 'l': 268*dec61199SArvind Sankar return va_arg(*ap, unsigned long); 269*dec61199SArvind Sankar case 'h': 270*dec61199SArvind Sankar return (unsigned short)va_arg(*ap, int); 271*dec61199SArvind Sankar case 'H': 272*dec61199SArvind Sankar return (unsigned char)va_arg(*ap, int); 273*dec61199SArvind Sankar default: 274*dec61199SArvind Sankar return va_arg(*ap, unsigned int); 275*dec61199SArvind Sankar } 276*dec61199SArvind Sankar } 277*dec61199SArvind Sankar } 278*dec61199SArvind Sankar 2793fbcf75bSArvind Sankar int vsprintf(char *buf, const char *fmt, va_list ap) 2802c7d1e30SArvind Sankar { 2812c7d1e30SArvind Sankar int len; 282ce5e3f90SArvind Sankar unsigned long long num; 2832c7d1e30SArvind Sankar int i, base; 2842c7d1e30SArvind Sankar char *str; 2852c7d1e30SArvind Sankar const char *s; 2862c7d1e30SArvind Sankar 2872c7d1e30SArvind Sankar int flags; /* flags to number() */ 2882c7d1e30SArvind Sankar 2892c7d1e30SArvind Sankar int field_width; /* width of output field */ 2902c7d1e30SArvind Sankar int precision; /* min. # of digits for integers; max 2912c7d1e30SArvind Sankar number of chars for from string */ 292ce5e3f90SArvind Sankar int qualifier; /* 'h', 'hh', 'l' or 'll' for integer fields */ 2932c7d1e30SArvind Sankar 2943fbcf75bSArvind Sankar va_list args; 2953fbcf75bSArvind Sankar 2963fbcf75bSArvind Sankar /* 2973fbcf75bSArvind Sankar * We want to pass our input va_list to helper functions by reference, 2983fbcf75bSArvind Sankar * but there's an annoying edge case. If va_list was originally passed 2993fbcf75bSArvind Sankar * to us by value, we could just pass &ap down to the helpers. This is 3003fbcf75bSArvind Sankar * the case on, for example, X86_32. 3013fbcf75bSArvind Sankar * However, on X86_64 (and possibly others), va_list is actually a 3023fbcf75bSArvind Sankar * size-1 array containing a structure. Our function parameter ap has 3033fbcf75bSArvind Sankar * decayed from T[1] to T*, and &ap has type T** rather than T(*)[1], 3043fbcf75bSArvind Sankar * which is what will be expected by a function taking a va_list * 3053fbcf75bSArvind Sankar * parameter. 3063fbcf75bSArvind Sankar * One standard way to solve this mess is by creating a copy in a local 3073fbcf75bSArvind Sankar * variable of type va_list and then passing a pointer to that local 3083fbcf75bSArvind Sankar * copy instead, which is what we do here. 3093fbcf75bSArvind Sankar */ 3103fbcf75bSArvind Sankar va_copy(args, ap); 3113fbcf75bSArvind Sankar 3122c7d1e30SArvind Sankar for (str = buf; *fmt; ++fmt) { 3133b835095SArvind Sankar if (*fmt != '%' || *++fmt == '%') { 3142c7d1e30SArvind Sankar *str++ = *fmt; 3152c7d1e30SArvind Sankar continue; 3162c7d1e30SArvind Sankar } 3172c7d1e30SArvind Sankar 3182c7d1e30SArvind Sankar /* process flags */ 3193b835095SArvind Sankar flags = get_flags(&fmt); 3202c7d1e30SArvind Sankar 3212c7d1e30SArvind Sankar /* get field width */ 3223fbcf75bSArvind Sankar field_width = get_int(&fmt, &args); 3232c7d1e30SArvind Sankar if (field_width < 0) { 3242c7d1e30SArvind Sankar field_width = -field_width; 3252c7d1e30SArvind Sankar flags |= LEFT; 3262c7d1e30SArvind Sankar } 3272c7d1e30SArvind Sankar 3282c7d1e30SArvind Sankar /* get the precision */ 3292c7d1e30SArvind Sankar precision = -1; 3302c7d1e30SArvind Sankar if (*fmt == '.') { 3312c7d1e30SArvind Sankar ++fmt; 3323fbcf75bSArvind Sankar precision = get_int(&fmt, &args); 33377e48db0SArvind Sankar if (precision >= 0) 33477e48db0SArvind Sankar flags &= ~ZEROPAD; 33577e48db0SArvind Sankar } 3362c7d1e30SArvind Sankar 3372c7d1e30SArvind Sankar /* get the conversion qualifier */ 3382c7d1e30SArvind Sankar qualifier = -1; 33929a28066SArvind Sankar if (*fmt == 'h' || *fmt == 'l') { 3402c7d1e30SArvind Sankar qualifier = *fmt; 3412c7d1e30SArvind Sankar ++fmt; 342ce5e3f90SArvind Sankar if (qualifier == *fmt) { 343ce5e3f90SArvind Sankar qualifier -= 'a'-'A'; 344ce5e3f90SArvind Sankar ++fmt; 345ce5e3f90SArvind Sankar } 3462c7d1e30SArvind Sankar } 3472c7d1e30SArvind Sankar 3482c7d1e30SArvind Sankar switch (*fmt) { 3492c7d1e30SArvind Sankar case 'c': 3502c7d1e30SArvind Sankar if (!(flags & LEFT)) 3512c7d1e30SArvind Sankar while (--field_width > 0) 3522c7d1e30SArvind Sankar *str++ = ' '; 3532c7d1e30SArvind Sankar *str++ = (unsigned char)va_arg(args, int); 3542c7d1e30SArvind Sankar while (--field_width > 0) 3552c7d1e30SArvind Sankar *str++ = ' '; 3562c7d1e30SArvind Sankar continue; 3572c7d1e30SArvind Sankar 3582c7d1e30SArvind Sankar case 's': 3592c7d1e30SArvind Sankar s = va_arg(args, char *); 3602c7d1e30SArvind Sankar len = strnlen(s, precision); 3612c7d1e30SArvind Sankar 3622c7d1e30SArvind Sankar if (!(flags & LEFT)) 3632c7d1e30SArvind Sankar while (len < field_width--) 3642c7d1e30SArvind Sankar *str++ = ' '; 3652c7d1e30SArvind Sankar for (i = 0; i < len; ++i) 3662c7d1e30SArvind Sankar *str++ = *s++; 3672c7d1e30SArvind Sankar while (len < field_width--) 3682c7d1e30SArvind Sankar *str++ = ' '; 3692c7d1e30SArvind Sankar continue; 3702c7d1e30SArvind Sankar 3712c7d1e30SArvind Sankar /* integer number formats - set up the flags and "break" */ 3722c7d1e30SArvind Sankar case 'o': 3732c7d1e30SArvind Sankar base = 8; 3742c7d1e30SArvind Sankar break; 3752c7d1e30SArvind Sankar 3767c30fd79SArvind Sankar case 'p': 3777c30fd79SArvind Sankar if (precision < 0) 3787c30fd79SArvind Sankar precision = 2 * sizeof(void *); 3797c30fd79SArvind Sankar fallthrough; 3802c7d1e30SArvind Sankar case 'x': 3812c7d1e30SArvind Sankar flags |= SMALL; 3822c7d1e30SArvind Sankar fallthrough; 3832c7d1e30SArvind Sankar case 'X': 3842c7d1e30SArvind Sankar base = 16; 3852c7d1e30SArvind Sankar break; 3862c7d1e30SArvind Sankar 3872c7d1e30SArvind Sankar case 'd': 3882c7d1e30SArvind Sankar case 'i': 3892c7d1e30SArvind Sankar flags |= SIGN; 3902c7d1e30SArvind Sankar fallthrough; 3912c7d1e30SArvind Sankar case 'u': 3927c30fd79SArvind Sankar base = 10; 3932c7d1e30SArvind Sankar break; 3942c7d1e30SArvind Sankar 3952c7d1e30SArvind Sankar default: 3962c7d1e30SArvind Sankar *str++ = '%'; 3972c7d1e30SArvind Sankar if (*fmt) 3982c7d1e30SArvind Sankar *str++ = *fmt; 3992c7d1e30SArvind Sankar else 4002c7d1e30SArvind Sankar --fmt; 4012c7d1e30SArvind Sankar continue; 4022c7d1e30SArvind Sankar } 4037c30fd79SArvind Sankar if (*fmt == 'p') { 4047c30fd79SArvind Sankar num = (unsigned long)va_arg(args, void *); 4052c7d1e30SArvind Sankar } else { 406*dec61199SArvind Sankar num = get_number(flags & SIGN, qualifier, &args); 407ce5e3f90SArvind Sankar } 4082c7d1e30SArvind Sankar str = number(str, num, base, field_width, precision, flags); 4092c7d1e30SArvind Sankar } 4102c7d1e30SArvind Sankar *str = '\0'; 4113fbcf75bSArvind Sankar 4123fbcf75bSArvind Sankar va_end(args); 4133fbcf75bSArvind Sankar 4142c7d1e30SArvind Sankar return str - buf; 4152c7d1e30SArvind Sankar } 4162c7d1e30SArvind Sankar 4172c7d1e30SArvind Sankar int sprintf(char *buf, const char *fmt, ...) 4182c7d1e30SArvind Sankar { 4192c7d1e30SArvind Sankar va_list args; 4202c7d1e30SArvind Sankar int i; 4212c7d1e30SArvind Sankar 4222c7d1e30SArvind Sankar va_start(args, fmt); 4232c7d1e30SArvind Sankar i = vsprintf(buf, fmt, args); 4242c7d1e30SArvind Sankar va_end(args); 4252c7d1e30SArvind Sankar return i; 4262c7d1e30SArvind Sankar } 427