diff options
| author | David Lamparter <equinox@diac24.net> | 2019-05-12 21:14:12 +0200 | 
|---|---|---|
| committer | David Lamparter <equinox@diac24.net> | 2019-06-03 16:44:18 +0200 | 
| commit | 7fa480984edc26617bc3c6bc4d9bc62d3b299a67 (patch) | |
| tree | 7b367650733b7b7eae44cd8f1d46b5adc4ce7be8 /lib/printf | |
| parent | 86bfbddf6ed922a755c29f23ffcef00240563a20 (diff) | |
lib/printf: use system printf for floats
We're not libc, we can just fall back to snprintf() to avoid all this
low-level float mangling.
Signed-off-by: David Lamparter <equinox@diac24.net>
Diffstat (limited to 'lib/printf')
| -rw-r--r-- | lib/printf/printfcommon.h | 54 | ||||
| -rw-r--r-- | lib/printf/vfprintf.c | 204 | 
2 files changed, 25 insertions, 233 deletions
diff --git a/lib/printf/printfcommon.h b/lib/printf/printfcommon.h index 68454bce1e..716177c57d 100644 --- a/lib/printf/printfcommon.h +++ b/lib/printf/printfcommon.h @@ -45,20 +45,6 @@   */ -#ifndef NO_FLOATING_POINT - -#define	dtoa		__dtoa -#define	freedtoa	__freedtoa - -#include <float.h> -#include <math.h> - -#define	DEFPREC		6 - -static int exponent(CHAR *, int, CHAR); - -#endif /* !NO_FLOATING_POINT */ -  static CHAR	*__ujtoa(uintmax_t, CHAR *, int, int, const char *);  static CHAR	*__ultoa(u_long, CHAR *, int, int, const char *); @@ -254,43 +240,3 @@ __ujtoa(uintmax_t val, CHAR *endp, int base, int octzero, const char *xdigs)  	}  	return (cp);  } - -#ifndef NO_FLOATING_POINT - -static int -exponent(CHAR *p0, int exp, CHAR fmtch) -{ -	CHAR *p, *t; -	CHAR expbuf[MAXEXPDIG]; - -	p = p0; -	*p++ = fmtch; -	if (exp < 0) { -		exp = -exp; -		*p++ = '-'; -	} -	else -		*p++ = '+'; -	t = expbuf + MAXEXPDIG; -	if (exp > 9) { -		do { -			*--t = to_char(exp % 10); -		} while ((exp /= 10) > 9); -		*--t = to_char(exp); -		for (; t < expbuf + MAXEXPDIG; *p++ = *t++); -	} -	else { -		/* -		 * Exponents for decimal floating point conversions -		 * (%[eEgG]) must be at least two characters long, -		 * whereas exponents for hexadecimal conversions can -		 * be only one character long. -		 */ -		if (fmtch == 'e' || fmtch == 'E') -			*p++ = '0'; -		*p++ = to_char(exp); -	} -	return (p - p0); -} - -#endif /* !NO_FLOATING_POINT */ diff --git a/lib/printf/vfprintf.c b/lib/printf/vfprintf.c index 69b9e2da9f..58412a48ce 100644 --- a/lib/printf/vfprintf.c +++ b/lib/printf/vfprintf.c @@ -143,7 +143,7 @@ __wcsconv(wchar_t *wcsarg, int prec)   * write a uintmax_t in octal (plus one byte).   */  #if UINTMAX_MAX <= UINT64_MAX -#define	BUF	32 +#define	BUF	64  #else  #error "BUF must be large enough to format a uintmax_t"  #endif @@ -165,36 +165,6 @@ __vfprintf(FILE *fp, const char *fmt0, va_list ap)  	int saved_errno;  	char sign;		/* sign prefix (' ', '+', '-', or \0) */ -#ifndef NO_FLOATING_POINT -	/* -	 * We can decompose the printed representation of floating -	 * point numbers into several parts, some of which may be empty: -	 * -	 * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ -	 *    A       B     ---C---      D       E   F -	 * -	 * A:	'sign' holds this value if present; '\0' otherwise -	 * B:	ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal -	 * C:	cp points to the string MMMNNN.  Leading and trailing -	 *	zeros are not in the string and must be added. -	 * D:	expchar holds this character; '\0' if no exponent, e.g. %f -	 * F:	at least two digits for decimal, at least one digit for hex -	 */ -	char *decimal_point;	/* locale specific decimal point */ -	int decpt_len;		/* length of decimal_point */ -	int signflag;		/* true if float is negative */ -	union {			/* floating point arguments %[aAeEfFgG] */ -		double dbl; -		long double ldbl; -	} fparg; -	int expt;		/* integer value of exponent */ -	char expchar;		/* exponent character: [eEpP\0] */ -	char *dtoaend;		/* pointer to end of converted digits */ -	int expsize;		/* character count for expstr */ -	int ndig;		/* actual number of digits returned by dtoa */ -	char expstr[MAXEXPDIG+2];	/* buffer for exponent string: e+ZZZ */ -	char *dtoaresult;	/* buffer allocated by dtoa */ -#endif  	u_long	ulval;		/* integer arguments %[diouxX] */  	uintmax_t ujval;	/* %j, %ll, %q, %t, %z integers */  	int base;		/* base for [diouxX] conversion */ @@ -305,12 +275,6 @@ __vfprintf(FILE *fp, const char *fmt0, va_list ap)  	va_copy(orgap, ap);  	io_init(&io, fp);  	ret = 0; -#ifndef NO_FLOATING_POINT -	dtoaresult = NULL; -	decimal_point = "."; -	/* The overwhelmingly common case is decpt_len == 1. */ -	decpt_len = (decimal_point[1] == '\0' ? 1 : strlen(decimal_point)); -#endif  	/*  	 * Scan the format for conversions (`%' character). @@ -489,121 +453,39 @@ reswitch:	switch (ch) {  #ifndef NO_FLOATING_POINT  		case 'a':  		case 'A': -			if (ch == 'a') { -				ox[1] = 'x'; -				xdigs = xdigs_lower; -				expchar = 'p'; -			} else { -				ox[1] = 'X'; -				xdigs = xdigs_upper; -				expchar = 'P'; -			} -			if (prec >= 0) -				prec++; -			if (dtoaresult != NULL) -				freedtoa(dtoaresult); -			if (flags & LONGDBL) { -				fparg.ldbl = GETARG(long double); -				dtoaresult = cp = -				    __hldtoa(fparg.ldbl, xdigs, prec, -				    &expt, &signflag, &dtoaend); -			} else { -				fparg.dbl = GETARG(double); -				dtoaresult = cp = -				    __hdtoa(fparg.dbl, xdigs, prec, -				    &expt, &signflag, &dtoaend); -			} -			if (prec < 0) -				prec = dtoaend - cp; -			if (expt == INT_MAX) -				ox[1] = '\0'; -			goto fp_common;  		case 'e':  		case 'E': -			expchar = ch; -			if (prec < 0)	/* account for digit before decpt */ -				prec = DEFPREC + 1; -			else -				prec++; -			goto fp_begin;  		case 'f':  		case 'F': -			expchar = '\0'; -			goto fp_begin;  		case 'g':  		case 'G': -			expchar = ch - ('g' - 'e'); -			if (prec == 0) -				prec = 1; -fp_begin: -			if (prec < 0) -				prec = DEFPREC; -			if (dtoaresult != NULL) -				freedtoa(dtoaresult);  			if (flags & LONGDBL) { -				fparg.ldbl = GETARG(long double); -				dtoaresult = cp = -				    __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec, -				    &expt, &signflag, &dtoaend); +				long double arg = GETARG(long double); +				char fmt[6] = "%.*L"; +				fmt[4] = ch; +				fmt[5] = '\0'; + +				snprintf(buf, sizeof(buf), fmt, prec, arg);  			} else { -				fparg.dbl = GETARG(double); -				dtoaresult = cp = -				    dtoa(fparg.dbl, expchar ? 2 : 3, prec, -				    &expt, &signflag, &dtoaend); -				if (expt == 9999) -					expt = INT_MAX; +				double arg = GETARG(double); +				char fmt[5] = "%.*"; +				fmt[3] = ch; +				fmt[4] = '\0'; + +				snprintf(buf, sizeof(buf), fmt, prec, arg);  			} -fp_common: -			if (signflag) +			cp = buf; +			/* for proper padding */ +			if (*cp == '-') { +				cp++;  				sign = '-'; -			if (expt == INT_MAX) {	/* inf or nan */ -				if (*cp == 'N') { -					cp = (ch >= 'a') ? "nan" : "NAN"; -					sign = '\0'; -				} else -					cp = (ch >= 'a') ? "inf" : "INF"; -				size = 3; -				flags &= ~ZEROPAD; -				break; -			} -			flags |= FPT; -			ndig = dtoaend - cp; -			if (ch == 'g' || ch == 'G') { -				if (expt > -4 && expt <= prec) { -					/* Make %[gG] smell like %[fF] */ -					expchar = '\0'; -					if (flags & ALT) -						prec -= expt; -					else -						prec = ndig - expt; -					if (prec < 0) -						prec = 0; -				} else { -					/* -					 * Make %[gG] smell like %[eE], but -					 * trim trailing zeroes if no # flag. -					 */ -					if (!(flags & ALT)) -						prec = ndig; -				} -			} -			if (expchar) { -				expsize = exponent(expstr, expt - 1, expchar); -				size = expsize + prec; -				if (prec > 1 || flags & ALT) -					size += decpt_len; -			} else { -				/* space for digits before decimal point */ -				if (expt > 0) -					size = expt; -				else	/* "0" */ -					size = 1; -				/* space for decimal pt and following digits */ -				if (prec || flags & ALT) -					size += prec + decpt_len;  			} +			/* "inf" */ +			if (!is_digit(*cp) && *cp != '.') +				flags &= ~ZEROPAD; +			size = strlen(buf);  			break; -#endif /* !NO_FLOATING_POINT */ +#endif  		case 'm':  			cp = strerror(saved_errno);  			size = (prec >= 0) ? strnlen(cp, prec) : strlen(cp); @@ -797,41 +679,9 @@ number:			if ((dprec = prec) >= 0)  			PAD(width - realsz, zeroes);  		/* the string or number proper */ -#ifndef NO_FLOATING_POINT -		if ((flags & FPT) == 0) { -#endif -			/* leading zeroes from decimal precision */ -			PAD(dprec - size, zeroes); -			PRINT(cp, size); -#ifndef NO_FLOATING_POINT -		} else {	/* glue together f_p fragments */ -			if (!expchar) {	/* %[fF] or sufficiently short %[gG] */ -				if (expt <= 0) { -					PRINT(zeroes, 1); -					if (prec || flags & ALT) -						PRINT(decimal_point,decpt_len); -					PAD(-expt, zeroes); -					/* already handled initial 0's */ -					prec += expt; -				} else { -					PRINTANDPAD(cp, dtoaend, expt, zeroes); -					cp += expt; -					if (prec || flags & ALT) -						PRINT(decimal_point,decpt_len); -				} -				PRINTANDPAD(cp, dtoaend, prec, zeroes); -			} else {	/* %[eE] or sufficiently long %[gG] */ -				if (prec > 1 || flags & ALT) { -					PRINT(cp++, 1); -					PRINT(decimal_point, decpt_len); -					PRINT(cp, ndig-1); -					PAD(prec - ndig, zeroes); -				} else	/* XeYYY */ -					PRINT(cp, 1); -				PRINT(expstr, expsize); -			} -		} -#endif +		/* leading zeroes from decimal precision */ +		PAD(dprec - size, zeroes); +		PRINT(cp, size);  		/* left-adjusting padding (always blank) */  		if (flags & LADJUST)  			PAD(width - realsz, blanks); @@ -845,10 +695,6 @@ done:  	FLUSH();  error:  	va_end(orgap); -#ifndef NO_FLOATING_POINT -	if (dtoaresult != NULL) -		freedtoa(dtoaresult); -#endif  	if (convbuf != NULL)  		free(convbuf);  	if ((argtable != NULL) && (argtable != statargtable))  | 
