2710 lines · 63.4 KB · C
RawDownload
/* *  linux/lib/vsprintf.c * *  Copyright (C) 1991, 1992  Linus Torvalds */ /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. *//* * Wirzenius wrote this portably, Torvalds fucked it up :-) */ /* * Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@datastacks.com> * - changed to provide snprintf and vsnprintf functions * So Feb  1 16:51:32 CET 2004 Juergen Quade <quade@hsnr.de> * - scnprintf and vscnprintf */ #include <stdarg.h>#include <linux/clk-provider.h>#include <linux/module.h>	/* for KSYM_SYMBOL_LEN */#include <linux/types.h>#include <linux/string.h>#include <linux/ctype.h>#include <linux/kernel.h>#include <linux/kallsyms.h>#include <linux/math64.h>#include <linux/uaccess.h>#include <linux/ioport.h>#include <linux/dcache.h>#include <linux/cred.h>#include <net/addrconf.h> #include <asm/page.h>		/* for PAGE_SIZE */#include <asm/sections.h>	/* for dereference_function_descriptor() */#include <asm/byteorder.h>	/* cpu_to_le16 */ #include <linux/string_helpers.h>#include "kstrtox.h" /** * simple_strtoull - convert a string to an unsigned long long * @cp: The start of the string * @endp: A pointer to the end of the parsed string will be placed here * @base: The number base to use * * This function is obsolete. Please use kstrtoull instead. */unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base){	unsigned long long result;	unsigned int rv; 	cp = _parse_integer_fixup_radix(cp, &base);	rv = _parse_integer(cp, base, &result);	/* FIXME */	cp += (rv & ~KSTRTOX_OVERFLOW); 	if (endp)		*endp = (char *)cp; 	return result;}EXPORT_SYMBOL(simple_strtoull); /** * simple_strtoul - convert a string to an unsigned long * @cp: The start of the string * @endp: A pointer to the end of the parsed string will be placed here * @base: The number base to use * * This function is obsolete. Please use kstrtoul instead. */unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base){	return simple_strtoull(cp, endp, base);}EXPORT_SYMBOL(simple_strtoul); /** * simple_strtol - convert a string to a signed long * @cp: The start of the string * @endp: A pointer to the end of the parsed string will be placed here * @base: The number base to use * * This function is obsolete. Please use kstrtol instead. */long simple_strtol(const char *cp, char **endp, unsigned int base){	if (*cp == '-')		return -simple_strtoul(cp + 1, endp, base); 	return simple_strtoul(cp, endp, base);}EXPORT_SYMBOL(simple_strtol); /** * simple_strtoll - convert a string to a signed long long * @cp: The start of the string * @endp: A pointer to the end of the parsed string will be placed here * @base: The number base to use * * This function is obsolete. Please use kstrtoll instead. */long long simple_strtoll(const char *cp, char **endp, unsigned int base){	if (*cp == '-')		return -simple_strtoull(cp + 1, endp, base); 	return simple_strtoull(cp, endp, base);}EXPORT_SYMBOL(simple_strtoll); static noinline_for_stackint skip_atoi(const char **s){	int i = 0; 	do {		i = i*10 + *((*s)++) - '0';	} while (isdigit(**s)); 	return i;} /* * Decimal conversion is by far the most typical, and is used for * /proc and /sys data. This directly impacts e.g. top performance * with many processes running. We optimize it for speed by emitting * two characters at a time, using a 200 byte lookup table. This * roughly halves the number of multiplications compared to computing * the digits one at a time. Implementation strongly inspired by the * previous version, which in turn used ideas described at * <http://www.cs.uiowa.edu/~jones/bcd/divide.html> (with permission * from the author, Douglas W. Jones). * * It turns out there is precisely one 26 bit fixed-point * approximation a of 64/100 for which x/100 == (x * (u64)a) >> 32 * holds for all x in [0, 10^8-1], namely a = 0x28f5c29. The actual * range happens to be somewhat larger (x <= 1073741898), but that's * irrelevant for our purpose. * * For dividing a number in the range [10^4, 10^6-1] by 100, we still * need a 32x32->64 bit multiply, so we simply use the same constant. * * For dividing a number in the range [100, 10^4-1] by 100, there are * several options. The simplest is (x * 0x147b) >> 19, which is valid * for all x <= 43698. */ static const u16 decpair[100] = {#define _(x) (__force u16) cpu_to_le16(((x % 10) | ((x / 10) << 8)) + 0x3030)	_( 0), _( 1), _( 2), _( 3), _( 4), _( 5), _( 6), _( 7), _( 8), _( 9),	_(10), _(11), _(12), _(13), _(14), _(15), _(16), _(17), _(18), _(19),	_(20), _(21), _(22), _(23), _(24), _(25), _(26), _(27), _(28), _(29),	_(30), _(31), _(32), _(33), _(34), _(35), _(36), _(37), _(38), _(39),	_(40), _(41), _(42), _(43), _(44), _(45), _(46), _(47), _(48), _(49),	_(50), _(51), _(52), _(53), _(54), _(55), _(56), _(57), _(58), _(59),	_(60), _(61), _(62), _(63), _(64), _(65), _(66), _(67), _(68), _(69),	_(70), _(71), _(72), _(73), _(74), _(75), _(76), _(77), _(78), _(79),	_(80), _(81), _(82), _(83), _(84), _(85), _(86), _(87), _(88), _(89),	_(90), _(91), _(92), _(93), _(94), _(95), _(96), _(97), _(98), _(99),#undef _}; /* * This will print a single '0' even if r == 0, since we would * immediately jump to out_r where two 0s would be written but only * one of them accounted for in buf. This is needed by ip4_string * below. All other callers pass a non-zero value of r.*/static noinline_for_stackchar *put_dec_trunc8(char *buf, unsigned r){	unsigned q; 	/* 1 <= r < 10^8 */	if (r < 100)		goto out_r; 	/* 100 <= r < 10^8 */	q = (r * (u64)0x28f5c29) >> 32;	*((u16 *)buf) = decpair[r - 100*q];	buf += 2; 	/* 1 <= q < 10^6 */	if (q < 100)		goto out_q; 	/*  100 <= q < 10^6 */	r = (q * (u64)0x28f5c29) >> 32;	*((u16 *)buf) = decpair[q - 100*r];	buf += 2; 	/* 1 <= r < 10^4 */	if (r < 100)		goto out_r; 	/* 100 <= r < 10^4 */	q = (r * 0x147b) >> 19;	*((u16 *)buf) = decpair[r - 100*q];	buf += 2;out_q:	/* 1 <= q < 100 */	r = q;out_r:	/* 1 <= r < 100 */	*((u16 *)buf) = decpair[r];	buf += r < 10 ? 1 : 2;	return buf;} #if BITS_PER_LONG == 64 && BITS_PER_LONG_LONG == 64static noinline_for_stackchar *put_dec_full8(char *buf, unsigned r){	unsigned q; 	/* 0 <= r < 10^8 */	q = (r * (u64)0x28f5c29) >> 32;	*((u16 *)buf) = decpair[r - 100*q];	buf += 2; 	/* 0 <= q < 10^6 */	r = (q * (u64)0x28f5c29) >> 32;	*((u16 *)buf) = decpair[q - 100*r];	buf += 2; 	/* 0 <= r < 10^4 */	q = (r * 0x147b) >> 19;	*((u16 *)buf) = decpair[r - 100*q];	buf += 2; 	/* 0 <= q < 100 */	*((u16 *)buf) = decpair[q];	buf += 2;	return buf;} static noinline_for_stackchar *put_dec(char *buf, unsigned long long n){	if (n >= 100*1000*1000)		buf = put_dec_full8(buf, do_div(n, 100*1000*1000));	/* 1 <= n <= 1.6e11 */	if (n >= 100*1000*1000)		buf = put_dec_full8(buf, do_div(n, 100*1000*1000));	/* 1 <= n < 1e8 */	return put_dec_trunc8(buf, n);} #elif BITS_PER_LONG == 32 && BITS_PER_LONG_LONG == 64 static voidput_dec_full4(char *buf, unsigned r){	unsigned q; 	/* 0 <= r < 10^4 */	q = (r * 0x147b) >> 19;	*((u16 *)buf) = decpair[r - 100*q];	buf += 2;	/* 0 <= q < 100 */	*((u16 *)buf) = decpair[q];} /* * Call put_dec_full4 on x % 10000, return x / 10000. * The approximation x/10000 == (x * 0x346DC5D7) >> 43 * holds for all x < 1,128,869,999.  The largest value this * helper will ever be asked to convert is 1,125,520,955. * (second call in the put_dec code, assuming n is all-ones). */static noinline_for_stackunsigned put_dec_helper4(char *buf, unsigned x){        uint32_t q = (x * (uint64_t)0x346DC5D7) >> 43;         put_dec_full4(buf, x - q * 10000);        return q;} /* Based on code by Douglas W. Jones found at * <http://www.cs.uiowa.edu/~jones/bcd/decimal.html#sixtyfour> * (with permission from the author). * Performs no 64-bit division and hence should be fast on 32-bit machines. */staticchar *put_dec(char *buf, unsigned long long n){	uint32_t d3, d2, d1, q, h; 	if (n < 100*1000*1000)		return put_dec_trunc8(buf, n); 	d1  = ((uint32_t)n >> 16); /* implicit "& 0xffff" */	h   = (n >> 32);	d2  = (h      ) & 0xffff;	d3  = (h >> 16); /* implicit "& 0xffff" */ 	/* n = 2^48 d3 + 2^32 d2 + 2^16 d1 + d0	     = 281_4749_7671_0656 d3 + 42_9496_7296 d2 + 6_5536 d1 + d0 */	q   = 656 * d3 + 7296 * d2 + 5536 * d1 + ((uint32_t)n & 0xffff);	q = put_dec_helper4(buf, q); 	q += 7671 * d3 + 9496 * d2 + 6 * d1;	q = put_dec_helper4(buf+4, q); 	q += 4749 * d3 + 42 * d2;	q = put_dec_helper4(buf+8, q); 	q += 281 * d3;	buf += 12;	if (q)		buf = put_dec_trunc8(buf, q);	else while (buf[-1] == '0')		--buf; 	return buf;} #endif /* * Convert passed number to decimal string. * Returns the length of string.  On buffer overflow, returns 0. * * If speed is not important, use snprintf(). It's easy to read the code. */int num_to_str(char *buf, int size, unsigned long long num){	/* put_dec requires 2-byte alignment of the buffer. */	char tmp[sizeof(num) * 3] __aligned(2);	int idx, len; 	/* put_dec() may work incorrectly for num = 0 (generate "", not "0") */	if (num <= 9) {		tmp[0] = '0' + num;		len = 1;	} else {		len = put_dec(tmp, num) - tmp;	} 	if (len > size)		return 0;	for (idx = 0; idx < len; ++idx)		buf[idx] = tmp[len - idx - 1];	return len;} #define SIGN	1		/* unsigned/signed, must be 1 */#define LEFT	2		/* left justified */#define PLUS	4		/* show plus */#define SPACE	8		/* space if plus */#define ZEROPAD	16		/* pad with zero, must be 16 == '0' - ' ' */#define SMALL	32		/* use lowercase in hex (must be 32 == 0x20) */#define SPECIAL	64		/* prefix hex with "0x", octal with "0" */ enum format_type {	FORMAT_TYPE_NONE, /* Just a string part */	FORMAT_TYPE_WIDTH,	FORMAT_TYPE_PRECISION,	FORMAT_TYPE_CHAR,	FORMAT_TYPE_STR,	FORMAT_TYPE_PTR,	FORMAT_TYPE_PERCENT_CHAR,	FORMAT_TYPE_INVALID,	FORMAT_TYPE_LONG_LONG,	FORMAT_TYPE_ULONG,	FORMAT_TYPE_LONG,	FORMAT_TYPE_UBYTE,	FORMAT_TYPE_BYTE,	FORMAT_TYPE_USHORT,	FORMAT_TYPE_SHORT,	FORMAT_TYPE_UINT,	FORMAT_TYPE_INT,	FORMAT_TYPE_SIZE_T,	FORMAT_TYPE_PTRDIFF}; struct printf_spec {	u8	type;		/* format_type enum */	u8	flags;		/* flags to number() */	u8	base;		/* number base, 8, 10 or 16 only */	u8	qualifier;	/* number qualifier, one of 'hHlLtzZ' */	s16	field_width;	/* width of output field */	s16	precision;	/* # of digits/chars */}; static noinline_for_stackchar *number(char *buf, char *end, unsigned long long num,	     struct printf_spec spec){	/* put_dec requires 2-byte alignment of the buffer. */	char tmp[3 * sizeof(num)] __aligned(2);	char sign;	char locase;	int need_pfx = ((spec.flags & SPECIAL) && spec.base != 10);	int i;	bool is_zero = num == 0LL; 	/* locase = 0 or 0x20. ORing digits or letters with 'locase'	 * produces same digits or (maybe lowercased) letters */	locase = (spec.flags & SMALL);	if (spec.flags & LEFT)		spec.flags &= ~ZEROPAD;	sign = 0;	if (spec.flags & SIGN) {		if ((signed long long)num < 0) {			sign = '-';			num = -(signed long long)num;			spec.field_width--;		} else if (spec.flags & PLUS) {			sign = '+';			spec.field_width--;		} else if (spec.flags & SPACE) {			sign = ' ';			spec.field_width--;		}	}	if (need_pfx) {		if (spec.base == 16)			spec.field_width -= 2;		else if (!is_zero)			spec.field_width--;	} 	/* generate full string in tmp[], in reverse order */	i = 0;	if (num < spec.base)		tmp[i++] = hex_asc_upper[num] | locase;	else if (spec.base != 10) { /* 8 or 16 */		int mask = spec.base - 1;		int shift = 3; 		if (spec.base == 16)			shift = 4;		do {			tmp[i++] = (hex_asc_upper[((unsigned char)num) & mask] | locase);			num >>= shift;		} while (num);	} else { /* base 10 */		i = put_dec(tmp, num) - tmp;	} 	/* printing 100 using %2d gives "100", not "00" */	if (i > spec.precision)		spec.precision = i;	/* leading space padding */	spec.field_width -= spec.precision;	if (!(spec.flags & (ZEROPAD | LEFT))) {		while (--spec.field_width >= 0) {			if (buf < end)				*buf = ' ';			++buf;		}	}	/* sign */	if (sign) {		if (buf < end)			*buf = sign;		++buf;	}	/* "0x" / "0" prefix */	if (need_pfx) {		if (spec.base == 16 || !is_zero) {			if (buf < end)				*buf = '0';			++buf;		}		if (spec.base == 16) {			if (buf < end)				*buf = ('X' | locase);			++buf;		}	}	/* zero or space padding */	if (!(spec.flags & LEFT)) {		char c = ' ' + (spec.flags & ZEROPAD);		BUILD_BUG_ON(' ' + ZEROPAD != '0');		while (--spec.field_width >= 0) {			if (buf < end)				*buf = c;			++buf;		}	}	/* hmm even more zero padding? */	while (i <= --spec.precision) {		if (buf < end)			*buf = '0';		++buf;	}	/* actual digits of result */	while (--i >= 0) {		if (buf < end)			*buf = tmp[i];		++buf;	}	/* trailing space padding */	while (--spec.field_width >= 0) {

Lines 1–500 of 2710.