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> 17*6c4bcd8aSArvind Sankar #include <linux/kernel.h> 18fb031937SArvind Sankar #include <linux/limits.h> 192c7d1e30SArvind Sankar #include <linux/string.h> 202c7d1e30SArvind Sankar 21*6c4bcd8aSArvind Sankar static 22*6c4bcd8aSArvind Sankar int skip_atoi(const char **s) 232c7d1e30SArvind Sankar { 242c7d1e30SArvind Sankar int i = 0; 252c7d1e30SArvind Sankar 262c7d1e30SArvind Sankar while (isdigit(**s)) 272c7d1e30SArvind Sankar i = i * 10 + *((*s)++) - '0'; 282c7d1e30SArvind Sankar return i; 292c7d1e30SArvind Sankar } 302c7d1e30SArvind Sankar 31ce5e3f90SArvind Sankar /* 32ce5e3f90SArvind Sankar * put_dec_full4 handles numbers in the range 0 <= r < 10000. 33ce5e3f90SArvind Sankar * The multiplier 0xccd is round(2^15/10), and the approximation 34ce5e3f90SArvind Sankar * r/10 == (r * 0xccd) >> 15 is exact for all r < 16389. 35ce5e3f90SArvind Sankar */ 36ce5e3f90SArvind Sankar static 37*6c4bcd8aSArvind Sankar void put_dec_full4(char *end, unsigned int r) 38ce5e3f90SArvind Sankar { 39ce5e3f90SArvind Sankar int i; 40ce5e3f90SArvind Sankar 41ce5e3f90SArvind Sankar for (i = 0; i < 3; i++) { 42ce5e3f90SArvind Sankar unsigned int q = (r * 0xccd) >> 15; 43*6c4bcd8aSArvind Sankar *--end = '0' + (r - q * 10); 44ce5e3f90SArvind Sankar r = q; 45ce5e3f90SArvind Sankar } 46*6c4bcd8aSArvind Sankar *--end = '0' + r; 47ce5e3f90SArvind Sankar } 48ce5e3f90SArvind Sankar 49ce5e3f90SArvind Sankar /* put_dec is copied from lib/vsprintf.c with small modifications */ 50ce5e3f90SArvind Sankar 51ce5e3f90SArvind Sankar /* 52ce5e3f90SArvind Sankar * Call put_dec_full4 on x % 10000, return x / 10000. 53ce5e3f90SArvind Sankar * The approximation x/10000 == (x * 0x346DC5D7) >> 43 54ce5e3f90SArvind Sankar * holds for all x < 1,128,869,999. The largest value this 55ce5e3f90SArvind Sankar * helper will ever be asked to convert is 1,125,520,955. 56ce5e3f90SArvind Sankar * (second call in the put_dec code, assuming n is all-ones). 57ce5e3f90SArvind Sankar */ 58ce5e3f90SArvind Sankar static 59*6c4bcd8aSArvind Sankar unsigned int put_dec_helper4(char *end, unsigned int x) 60ce5e3f90SArvind Sankar { 61ce5e3f90SArvind Sankar unsigned int q = (x * 0x346DC5D7ULL) >> 43; 62ce5e3f90SArvind Sankar 63*6c4bcd8aSArvind Sankar put_dec_full4(end, x - q * 10000); 64ce5e3f90SArvind Sankar return q; 65ce5e3f90SArvind Sankar } 66ce5e3f90SArvind Sankar 67ce5e3f90SArvind Sankar /* Based on code by Douglas W. Jones found at 68ce5e3f90SArvind Sankar * <http://www.cs.uiowa.edu/~jones/bcd/decimal.html#sixtyfour> 69ce5e3f90SArvind Sankar * (with permission from the author). 70ce5e3f90SArvind Sankar * Performs no 64-bit division and hence should be fast on 32-bit machines. 71ce5e3f90SArvind Sankar */ 72ce5e3f90SArvind Sankar static 73*6c4bcd8aSArvind Sankar char *put_dec(char *end, unsigned long long n) 74ce5e3f90SArvind Sankar { 75ce5e3f90SArvind Sankar unsigned int d3, d2, d1, q, h; 76*6c4bcd8aSArvind Sankar char *p = end; 77ce5e3f90SArvind Sankar 78ce5e3f90SArvind Sankar d1 = ((unsigned int)n >> 16); /* implicit "& 0xffff" */ 79ce5e3f90SArvind Sankar h = (n >> 32); 80ce5e3f90SArvind Sankar d2 = (h ) & 0xffff; 81ce5e3f90SArvind Sankar d3 = (h >> 16); /* implicit "& 0xffff" */ 82ce5e3f90SArvind Sankar 83ce5e3f90SArvind Sankar /* n = 2^48 d3 + 2^32 d2 + 2^16 d1 + d0 84ce5e3f90SArvind Sankar = 281_4749_7671_0656 d3 + 42_9496_7296 d2 + 6_5536 d1 + d0 */ 85ce5e3f90SArvind Sankar q = 656 * d3 + 7296 * d2 + 5536 * d1 + ((unsigned int)n & 0xffff); 86ce5e3f90SArvind Sankar q = put_dec_helper4(p, q); 87*6c4bcd8aSArvind Sankar p -= 4; 88ce5e3f90SArvind Sankar 89ce5e3f90SArvind Sankar q += 7671 * d3 + 9496 * d2 + 6 * d1; 90ce5e3f90SArvind Sankar q = put_dec_helper4(p, q); 91*6c4bcd8aSArvind Sankar p -= 4; 92ce5e3f90SArvind Sankar 93ce5e3f90SArvind Sankar q += 4749 * d3 + 42 * d2; 94ce5e3f90SArvind Sankar q = put_dec_helper4(p, q); 95*6c4bcd8aSArvind Sankar p -= 4; 96ce5e3f90SArvind Sankar 97ce5e3f90SArvind Sankar q += 281 * d3; 98ce5e3f90SArvind Sankar q = put_dec_helper4(p, q); 99*6c4bcd8aSArvind Sankar p -= 4; 100ce5e3f90SArvind Sankar 101ce5e3f90SArvind Sankar put_dec_full4(p, q); 102*6c4bcd8aSArvind Sankar p -= 4; 103ce5e3f90SArvind Sankar 104ce5e3f90SArvind Sankar /* strip off the extra 0's we printed */ 105*6c4bcd8aSArvind Sankar while (p < end && *p == '0') 106*6c4bcd8aSArvind Sankar ++p; 107ce5e3f90SArvind Sankar 108*6c4bcd8aSArvind Sankar return p; 109*6c4bcd8aSArvind Sankar } 110*6c4bcd8aSArvind Sankar 111*6c4bcd8aSArvind Sankar static 112*6c4bcd8aSArvind Sankar char *number(char *end, unsigned long long num, int base, char locase) 113*6c4bcd8aSArvind Sankar { 114*6c4bcd8aSArvind Sankar /* 115*6c4bcd8aSArvind Sankar * locase = 0 or 0x20. ORing digits or letters with 'locase' 116*6c4bcd8aSArvind Sankar * produces same digits or (maybe lowercased) letters 117*6c4bcd8aSArvind Sankar */ 118*6c4bcd8aSArvind Sankar 119*6c4bcd8aSArvind Sankar /* we are called with base 8, 10 or 16, only, thus don't need "G..." */ 120*6c4bcd8aSArvind Sankar static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */ 121*6c4bcd8aSArvind Sankar 122*6c4bcd8aSArvind Sankar switch (base) { 123*6c4bcd8aSArvind Sankar case 10: 124*6c4bcd8aSArvind Sankar if (num != 0) 125*6c4bcd8aSArvind Sankar end = put_dec(end, num); 126*6c4bcd8aSArvind Sankar break; 127*6c4bcd8aSArvind Sankar case 8: 128*6c4bcd8aSArvind Sankar for (; num != 0; num >>= 3) 129*6c4bcd8aSArvind Sankar *--end = '0' + (num & 07); 130*6c4bcd8aSArvind Sankar break; 131*6c4bcd8aSArvind Sankar case 16: 132*6c4bcd8aSArvind Sankar for (; num != 0; num >>= 4) 133*6c4bcd8aSArvind Sankar *--end = digits[num & 0xf] | locase; 134*6c4bcd8aSArvind Sankar break; 135*6c4bcd8aSArvind Sankar default: 136*6c4bcd8aSArvind Sankar unreachable(); 137*6c4bcd8aSArvind Sankar }; 138*6c4bcd8aSArvind Sankar 139*6c4bcd8aSArvind Sankar return end; 140ce5e3f90SArvind Sankar } 141ce5e3f90SArvind Sankar 1422c7d1e30SArvind Sankar #define ZEROPAD 1 /* pad with zero */ 1432c7d1e30SArvind Sankar #define SIGN 2 /* unsigned/signed long */ 1442c7d1e30SArvind Sankar #define PLUS 4 /* show plus */ 1452c7d1e30SArvind Sankar #define SPACE 8 /* space if plus */ 1462c7d1e30SArvind Sankar #define LEFT 16 /* left justified */ 1472c7d1e30SArvind Sankar #define SMALL 32 /* Must be 32 == 0x20 */ 1482c7d1e30SArvind Sankar #define SPECIAL 64 /* 0x */ 1492c7d1e30SArvind Sankar 1503b835095SArvind Sankar static 1513b835095SArvind Sankar int get_flags(const char **fmt) 1523b835095SArvind Sankar { 1533b835095SArvind Sankar int flags = 0; 1543b835095SArvind Sankar 1553b835095SArvind Sankar do { 1563b835095SArvind Sankar switch (**fmt) { 1573b835095SArvind Sankar case '-': 1583b835095SArvind Sankar flags |= LEFT; 1593b835095SArvind Sankar break; 1603b835095SArvind Sankar case '+': 1613b835095SArvind Sankar flags |= PLUS; 1623b835095SArvind Sankar break; 1633b835095SArvind Sankar case ' ': 1643b835095SArvind Sankar flags |= SPACE; 1653b835095SArvind Sankar break; 1663b835095SArvind Sankar case '#': 1673b835095SArvind Sankar flags |= SPECIAL; 1683b835095SArvind Sankar break; 1693b835095SArvind Sankar case '0': 1703b835095SArvind Sankar flags |= ZEROPAD; 1713b835095SArvind Sankar break; 1723b835095SArvind Sankar default: 1733b835095SArvind Sankar return flags; 1743b835095SArvind Sankar } 1753b835095SArvind Sankar ++(*fmt); 1763b835095SArvind Sankar } while (1); 1773b835095SArvind Sankar } 1783b835095SArvind Sankar 1793fbcf75bSArvind Sankar static 1803fbcf75bSArvind Sankar int get_int(const char **fmt, va_list *ap) 1813fbcf75bSArvind Sankar { 1823fbcf75bSArvind Sankar if (isdigit(**fmt)) 1833fbcf75bSArvind Sankar return skip_atoi(fmt); 1843fbcf75bSArvind Sankar if (**fmt == '*') { 1853fbcf75bSArvind Sankar ++(*fmt); 1863fbcf75bSArvind Sankar /* it's the next argument */ 1873fbcf75bSArvind Sankar return va_arg(*ap, int); 1883fbcf75bSArvind Sankar } 1893fbcf75bSArvind Sankar return 0; 1903fbcf75bSArvind Sankar } 1913fbcf75bSArvind Sankar 192dec61199SArvind Sankar static 193dec61199SArvind Sankar unsigned long long get_number(int sign, int qualifier, va_list *ap) 194dec61199SArvind Sankar { 195dec61199SArvind Sankar if (sign) { 196dec61199SArvind Sankar switch (qualifier) { 197dec61199SArvind Sankar case 'L': 198dec61199SArvind Sankar return va_arg(*ap, long long); 199dec61199SArvind Sankar case 'l': 200dec61199SArvind Sankar return va_arg(*ap, long); 201dec61199SArvind Sankar case 'h': 202dec61199SArvind Sankar return (short)va_arg(*ap, int); 203dec61199SArvind Sankar case 'H': 204dec61199SArvind Sankar return (signed char)va_arg(*ap, int); 205dec61199SArvind Sankar default: 206dec61199SArvind Sankar return va_arg(*ap, int); 207dec61199SArvind Sankar }; 208dec61199SArvind Sankar } else { 209dec61199SArvind Sankar switch (qualifier) { 210dec61199SArvind Sankar case 'L': 211dec61199SArvind Sankar return va_arg(*ap, unsigned long long); 212dec61199SArvind Sankar case 'l': 213dec61199SArvind Sankar return va_arg(*ap, unsigned long); 214dec61199SArvind Sankar case 'h': 215dec61199SArvind Sankar return (unsigned short)va_arg(*ap, int); 216dec61199SArvind Sankar case 'H': 217dec61199SArvind Sankar return (unsigned char)va_arg(*ap, int); 218dec61199SArvind Sankar default: 219dec61199SArvind Sankar return va_arg(*ap, unsigned int); 220dec61199SArvind Sankar } 221dec61199SArvind Sankar } 222dec61199SArvind Sankar } 223dec61199SArvind Sankar 224*6c4bcd8aSArvind Sankar static 225*6c4bcd8aSArvind Sankar char get_sign(long long *num, int flags) 226*6c4bcd8aSArvind Sankar { 227*6c4bcd8aSArvind Sankar if (!(flags & SIGN)) 228*6c4bcd8aSArvind Sankar return 0; 229*6c4bcd8aSArvind Sankar if (*num < 0) { 230*6c4bcd8aSArvind Sankar *num = -(*num); 231*6c4bcd8aSArvind Sankar return '-'; 232*6c4bcd8aSArvind Sankar } 233*6c4bcd8aSArvind Sankar if (flags & PLUS) 234*6c4bcd8aSArvind Sankar return '+'; 235*6c4bcd8aSArvind Sankar if (flags & SPACE) 236*6c4bcd8aSArvind Sankar return ' '; 237*6c4bcd8aSArvind Sankar return 0; 238*6c4bcd8aSArvind Sankar } 239*6c4bcd8aSArvind Sankar 2403fbcf75bSArvind Sankar int vsprintf(char *buf, const char *fmt, va_list ap) 2412c7d1e30SArvind Sankar { 242*6c4bcd8aSArvind Sankar /* The maximum space required is to print a 64-bit number in octal */ 243*6c4bcd8aSArvind Sankar char tmp[(sizeof(unsigned long long) * 8 + 2) / 3]; 244*6c4bcd8aSArvind Sankar char *tmp_end = &tmp[ARRAY_SIZE(tmp)]; 245*6c4bcd8aSArvind Sankar long long num; 246*6c4bcd8aSArvind Sankar int base; 2472c7d1e30SArvind Sankar char *str; 2482c7d1e30SArvind Sankar const char *s; 249*6c4bcd8aSArvind Sankar int len; 250*6c4bcd8aSArvind Sankar char sign; 2512c7d1e30SArvind Sankar 2522c7d1e30SArvind Sankar int flags; /* flags to number() */ 2532c7d1e30SArvind Sankar 2542c7d1e30SArvind Sankar int field_width; /* width of output field */ 2552c7d1e30SArvind Sankar int precision; /* min. # of digits for integers; max 2562c7d1e30SArvind Sankar number of chars for from string */ 257ce5e3f90SArvind Sankar int qualifier; /* 'h', 'hh', 'l' or 'll' for integer fields */ 2582c7d1e30SArvind Sankar 2593fbcf75bSArvind Sankar va_list args; 2603fbcf75bSArvind Sankar 2613fbcf75bSArvind Sankar /* 2623fbcf75bSArvind Sankar * We want to pass our input va_list to helper functions by reference, 2633fbcf75bSArvind Sankar * but there's an annoying edge case. If va_list was originally passed 2643fbcf75bSArvind Sankar * to us by value, we could just pass &ap down to the helpers. This is 2653fbcf75bSArvind Sankar * the case on, for example, X86_32. 2663fbcf75bSArvind Sankar * However, on X86_64 (and possibly others), va_list is actually a 2673fbcf75bSArvind Sankar * size-1 array containing a structure. Our function parameter ap has 2683fbcf75bSArvind Sankar * decayed from T[1] to T*, and &ap has type T** rather than T(*)[1], 2693fbcf75bSArvind Sankar * which is what will be expected by a function taking a va_list * 2703fbcf75bSArvind Sankar * parameter. 2713fbcf75bSArvind Sankar * One standard way to solve this mess is by creating a copy in a local 2723fbcf75bSArvind Sankar * variable of type va_list and then passing a pointer to that local 2733fbcf75bSArvind Sankar * copy instead, which is what we do here. 2743fbcf75bSArvind Sankar */ 2753fbcf75bSArvind Sankar va_copy(args, ap); 2763fbcf75bSArvind Sankar 2772c7d1e30SArvind Sankar for (str = buf; *fmt; ++fmt) { 2783b835095SArvind Sankar if (*fmt != '%' || *++fmt == '%') { 2792c7d1e30SArvind Sankar *str++ = *fmt; 2802c7d1e30SArvind Sankar continue; 2812c7d1e30SArvind Sankar } 2822c7d1e30SArvind Sankar 2832c7d1e30SArvind Sankar /* process flags */ 2843b835095SArvind Sankar flags = get_flags(&fmt); 2852c7d1e30SArvind Sankar 2862c7d1e30SArvind Sankar /* get field width */ 2873fbcf75bSArvind Sankar field_width = get_int(&fmt, &args); 2882c7d1e30SArvind Sankar if (field_width < 0) { 2892c7d1e30SArvind Sankar field_width = -field_width; 2902c7d1e30SArvind Sankar flags |= LEFT; 2912c7d1e30SArvind Sankar } 2922c7d1e30SArvind Sankar 293*6c4bcd8aSArvind Sankar if (flags & LEFT) 294*6c4bcd8aSArvind Sankar flags &= ~ZEROPAD; 295*6c4bcd8aSArvind Sankar 2962c7d1e30SArvind Sankar /* get the precision */ 2972c7d1e30SArvind Sankar precision = -1; 2982c7d1e30SArvind Sankar if (*fmt == '.') { 2992c7d1e30SArvind Sankar ++fmt; 3003fbcf75bSArvind Sankar precision = get_int(&fmt, &args); 30177e48db0SArvind Sankar if (precision >= 0) 30277e48db0SArvind Sankar flags &= ~ZEROPAD; 30377e48db0SArvind Sankar } 3042c7d1e30SArvind Sankar 3052c7d1e30SArvind Sankar /* get the conversion qualifier */ 3062c7d1e30SArvind Sankar qualifier = -1; 30729a28066SArvind Sankar if (*fmt == 'h' || *fmt == 'l') { 3082c7d1e30SArvind Sankar qualifier = *fmt; 3092c7d1e30SArvind Sankar ++fmt; 310ce5e3f90SArvind Sankar if (qualifier == *fmt) { 311ce5e3f90SArvind Sankar qualifier -= 'a'-'A'; 312ce5e3f90SArvind Sankar ++fmt; 313ce5e3f90SArvind Sankar } 3142c7d1e30SArvind Sankar } 3152c7d1e30SArvind Sankar 316*6c4bcd8aSArvind Sankar sign = 0; 317*6c4bcd8aSArvind Sankar 3182c7d1e30SArvind Sankar switch (*fmt) { 3192c7d1e30SArvind Sankar case 'c': 320*6c4bcd8aSArvind Sankar flags &= LEFT; 321*6c4bcd8aSArvind Sankar tmp[0] = (unsigned char)va_arg(args, int); 322*6c4bcd8aSArvind Sankar s = tmp; 323*6c4bcd8aSArvind Sankar precision = len = 1; 324*6c4bcd8aSArvind Sankar goto output; 3252c7d1e30SArvind Sankar 3262c7d1e30SArvind Sankar case 's': 327*6c4bcd8aSArvind Sankar flags &= LEFT; 328fb031937SArvind Sankar if (precision < 0) 329fb031937SArvind Sankar precision = INT_MAX; 3302c7d1e30SArvind Sankar s = va_arg(args, char *); 331fb031937SArvind Sankar if (!s) 332fb031937SArvind Sankar s = precision < 6 ? "" : "(null)"; 333*6c4bcd8aSArvind Sankar precision = len = strnlen(s, precision); 334*6c4bcd8aSArvind Sankar goto output; 3352c7d1e30SArvind Sankar 3362c7d1e30SArvind Sankar /* integer number formats - set up the flags and "break" */ 3372c7d1e30SArvind Sankar case 'o': 3382c7d1e30SArvind Sankar base = 8; 3392c7d1e30SArvind Sankar break; 3402c7d1e30SArvind Sankar 3417c30fd79SArvind Sankar case 'p': 3427c30fd79SArvind Sankar if (precision < 0) 3437c30fd79SArvind Sankar precision = 2 * sizeof(void *); 3447c30fd79SArvind Sankar fallthrough; 3452c7d1e30SArvind Sankar case 'x': 3462c7d1e30SArvind Sankar flags |= SMALL; 3472c7d1e30SArvind Sankar fallthrough; 3482c7d1e30SArvind Sankar case 'X': 3492c7d1e30SArvind Sankar base = 16; 3502c7d1e30SArvind Sankar break; 3512c7d1e30SArvind Sankar 3522c7d1e30SArvind Sankar case 'd': 3532c7d1e30SArvind Sankar case 'i': 3542c7d1e30SArvind Sankar flags |= SIGN; 3552c7d1e30SArvind Sankar fallthrough; 3562c7d1e30SArvind Sankar case 'u': 357*6c4bcd8aSArvind Sankar flags &= ~SPECIAL; 3587c30fd79SArvind Sankar base = 10; 3592c7d1e30SArvind Sankar break; 3602c7d1e30SArvind Sankar 3612c7d1e30SArvind Sankar default: 3622c7d1e30SArvind Sankar *str++ = '%'; 3632c7d1e30SArvind Sankar if (*fmt) 3642c7d1e30SArvind Sankar *str++ = *fmt; 3652c7d1e30SArvind Sankar else 3662c7d1e30SArvind Sankar --fmt; 3672c7d1e30SArvind Sankar continue; 3682c7d1e30SArvind Sankar } 3697c30fd79SArvind Sankar if (*fmt == 'p') { 3707c30fd79SArvind Sankar num = (unsigned long)va_arg(args, void *); 3712c7d1e30SArvind Sankar } else { 372dec61199SArvind Sankar num = get_number(flags & SIGN, qualifier, &args); 373ce5e3f90SArvind Sankar } 374*6c4bcd8aSArvind Sankar 375*6c4bcd8aSArvind Sankar sign = get_sign(&num, flags); 376*6c4bcd8aSArvind Sankar if (sign) 377*6c4bcd8aSArvind Sankar --field_width; 378*6c4bcd8aSArvind Sankar 379*6c4bcd8aSArvind Sankar s = number(tmp_end, num, base, flags & SMALL); 380*6c4bcd8aSArvind Sankar len = tmp_end - s; 381*6c4bcd8aSArvind Sankar /* default precision is 1 */ 382*6c4bcd8aSArvind Sankar if (precision < 0) 383*6c4bcd8aSArvind Sankar precision = 1; 384*6c4bcd8aSArvind Sankar /* precision is minimum number of digits to print */ 385*6c4bcd8aSArvind Sankar if (precision < len) 386*6c4bcd8aSArvind Sankar precision = len; 387*6c4bcd8aSArvind Sankar if (flags & SPECIAL) { 388*6c4bcd8aSArvind Sankar /* 389*6c4bcd8aSArvind Sankar * For octal, a leading 0 is printed only if necessary, 390*6c4bcd8aSArvind Sankar * i.e. if it's not already there because of the 391*6c4bcd8aSArvind Sankar * precision. 392*6c4bcd8aSArvind Sankar */ 393*6c4bcd8aSArvind Sankar if (base == 8 && precision == len) 394*6c4bcd8aSArvind Sankar ++precision; 395*6c4bcd8aSArvind Sankar /* 396*6c4bcd8aSArvind Sankar * For hexadecimal, the leading 0x is skipped if the 397*6c4bcd8aSArvind Sankar * output is empty, i.e. both the number and the 398*6c4bcd8aSArvind Sankar * precision are 0. 399*6c4bcd8aSArvind Sankar */ 400*6c4bcd8aSArvind Sankar if (base == 16 && precision > 0) 401*6c4bcd8aSArvind Sankar field_width -= 2; 402*6c4bcd8aSArvind Sankar else 403*6c4bcd8aSArvind Sankar flags &= ~SPECIAL; 404*6c4bcd8aSArvind Sankar } 405*6c4bcd8aSArvind Sankar /* 406*6c4bcd8aSArvind Sankar * For zero padding, increase the precision to fill the field 407*6c4bcd8aSArvind Sankar * width. 408*6c4bcd8aSArvind Sankar */ 409*6c4bcd8aSArvind Sankar if ((flags & ZEROPAD) && field_width > precision) 410*6c4bcd8aSArvind Sankar precision = field_width; 411*6c4bcd8aSArvind Sankar 412*6c4bcd8aSArvind Sankar output: 413*6c4bcd8aSArvind Sankar /* Calculate the padding necessary */ 414*6c4bcd8aSArvind Sankar field_width -= precision; 415*6c4bcd8aSArvind Sankar /* Leading padding with ' ' */ 416*6c4bcd8aSArvind Sankar if (!(flags & LEFT)) 417*6c4bcd8aSArvind Sankar while (field_width-- > 0) 418*6c4bcd8aSArvind Sankar *str++ = ' '; 419*6c4bcd8aSArvind Sankar /* sign */ 420*6c4bcd8aSArvind Sankar if (sign) 421*6c4bcd8aSArvind Sankar *str++ = sign; 422*6c4bcd8aSArvind Sankar /* 0x/0X for hexadecimal */ 423*6c4bcd8aSArvind Sankar if (flags & SPECIAL) { 424*6c4bcd8aSArvind Sankar *str++ = '0'; 425*6c4bcd8aSArvind Sankar *str++ = 'X' | (flags & SMALL); 426*6c4bcd8aSArvind Sankar } 427*6c4bcd8aSArvind Sankar /* Zero padding and excess precision */ 428*6c4bcd8aSArvind Sankar while (precision-- > len) 429*6c4bcd8aSArvind Sankar *str++ = '0'; 430*6c4bcd8aSArvind Sankar /* Actual output */ 431*6c4bcd8aSArvind Sankar while (len-- > 0) 432*6c4bcd8aSArvind Sankar *str++ = *s++; 433*6c4bcd8aSArvind Sankar /* Trailing padding with ' ' */ 434*6c4bcd8aSArvind Sankar while (field_width-- > 0) 435*6c4bcd8aSArvind Sankar *str++ = ' '; 4362c7d1e30SArvind Sankar } 4372c7d1e30SArvind Sankar *str = '\0'; 4383fbcf75bSArvind Sankar 4393fbcf75bSArvind Sankar va_end(args); 4403fbcf75bSArvind Sankar 4412c7d1e30SArvind Sankar return str - buf; 4422c7d1e30SArvind Sankar } 4432c7d1e30SArvind Sankar 4442c7d1e30SArvind Sankar int sprintf(char *buf, const char *fmt, ...) 4452c7d1e30SArvind Sankar { 4462c7d1e30SArvind Sankar va_list args; 4472c7d1e30SArvind Sankar int i; 4482c7d1e30SArvind Sankar 4492c7d1e30SArvind Sankar va_start(args, fmt); 4502c7d1e30SArvind Sankar i = vsprintf(buf, fmt, args); 4512c7d1e30SArvind Sankar va_end(args); 4522c7d1e30SArvind Sankar return i; 4532c7d1e30SArvind Sankar } 454