xref: /plan9/sys/src/cmd/unix/drawterm/libc/fltfmt.c (revision 2282df4ee19682a10ae95200202320ff2912f104)
18ccd4a63SDavid du Colombier #include <u.h>
28ccd4a63SDavid du Colombier #include <libc.h>
3*0d601874SDavid du Colombier #include <float.h>
48ccd4a63SDavid du Colombier #include <ctype.h>
58ccd4a63SDavid du Colombier #include "fmtdef.h"
68ccd4a63SDavid du Colombier 
78ccd4a63SDavid du Colombier enum
88ccd4a63SDavid du Colombier {
98ccd4a63SDavid du Colombier 	FDIGIT	= 30,
108ccd4a63SDavid du Colombier 	FDEFLT	= 6,
11*0d601874SDavid du Colombier 	NSIGNIF	= 17
128ccd4a63SDavid du Colombier };
138ccd4a63SDavid du Colombier 
14*0d601874SDavid du Colombier /*
15*0d601874SDavid du Colombier  * first few powers of 10, enough for about 1/2 of the
16*0d601874SDavid du Colombier  * total space for doubles.
17*0d601874SDavid du Colombier  */
18*0d601874SDavid du Colombier static double pows10[] =
19*0d601874SDavid du Colombier {
20*0d601874SDavid du Colombier 	  1e0,   1e1,   1e2,   1e3,   1e4,   1e5,   1e6,   1e7,   1e8,   1e9,
21*0d601874SDavid du Colombier 	 1e10,  1e11,  1e12,  1e13,  1e14,  1e15,  1e16,  1e17,  1e18,  1e19,
22*0d601874SDavid du Colombier 	 1e20,  1e21,  1e22,  1e23,  1e24,  1e25,  1e26,  1e27,  1e28,  1e29,
23*0d601874SDavid du Colombier 	 1e30,  1e31,  1e32,  1e33,  1e34,  1e35,  1e36,  1e37,  1e38,  1e39,
24*0d601874SDavid du Colombier 	 1e40,  1e41,  1e42,  1e43,  1e44,  1e45,  1e46,  1e47,  1e48,  1e49,
25*0d601874SDavid du Colombier 	 1e50,  1e51,  1e52,  1e53,  1e54,  1e55,  1e56,  1e57,  1e58,  1e59,
26*0d601874SDavid du Colombier 	 1e60,  1e61,  1e62,  1e63,  1e64,  1e65,  1e66,  1e67,  1e68,  1e69,
27*0d601874SDavid du Colombier 	 1e70,  1e71,  1e72,  1e73,  1e74,  1e75,  1e76,  1e77,  1e78,  1e79,
28*0d601874SDavid du Colombier 	 1e80,  1e81,  1e82,  1e83,  1e84,  1e85,  1e86,  1e87,  1e88,  1e89,
29*0d601874SDavid du Colombier 	 1e90,  1e91,  1e92,  1e93,  1e94,  1e95,  1e96,  1e97,  1e98,  1e99,
30*0d601874SDavid du Colombier 	1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109,
31*0d601874SDavid du Colombier 	1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119,
32*0d601874SDavid du Colombier 	1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129,
33*0d601874SDavid du Colombier 	1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139,
34*0d601874SDavid du Colombier 	1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149,
35*0d601874SDavid du Colombier 	1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159,
36*0d601874SDavid du Colombier };
37*0d601874SDavid du Colombier 
38*0d601874SDavid du Colombier #undef pow10
39*0d601874SDavid du Colombier #define  pow10(x)  fmtpow10(x)
40*0d601874SDavid du Colombier 
41*0d601874SDavid du Colombier static double
pow10(int n)42*0d601874SDavid du Colombier pow10(int n)
43*0d601874SDavid du Colombier {
44*0d601874SDavid du Colombier 	double d;
45*0d601874SDavid du Colombier 	int neg;
46*0d601874SDavid du Colombier 
47*0d601874SDavid du Colombier 	neg = 0;
48*0d601874SDavid du Colombier 	if(n < 0){
49*0d601874SDavid du Colombier 		if(n < DBL_MIN_10_EXP){
50*0d601874SDavid du Colombier 			return 0.;
51*0d601874SDavid du Colombier 		}
52*0d601874SDavid du Colombier 		neg = 1;
53*0d601874SDavid du Colombier 		n = -n;
54*0d601874SDavid du Colombier 	}else if(n > DBL_MAX_10_EXP){
55*0d601874SDavid du Colombier 		return HUGE_VAL;
56*0d601874SDavid du Colombier 	}
57*0d601874SDavid du Colombier 	if(n < (int)(sizeof(pows10)/sizeof(pows10[0])))
58*0d601874SDavid du Colombier 		d = pows10[n];
59*0d601874SDavid du Colombier 	else{
60*0d601874SDavid du Colombier 		d = pows10[sizeof(pows10)/sizeof(pows10[0]) - 1];
61*0d601874SDavid du Colombier 		for(;;){
62*0d601874SDavid du Colombier 			n -= sizeof(pows10)/sizeof(pows10[0]) - 1;
63*0d601874SDavid du Colombier 			if(n < (int)(sizeof(pows10)/sizeof(pows10[0]))){
64*0d601874SDavid du Colombier 				d *= pows10[n];
65*0d601874SDavid du Colombier 				break;
66*0d601874SDavid du Colombier 			}
67*0d601874SDavid du Colombier 			d *= pows10[sizeof(pows10)/sizeof(pows10[0]) - 1];
68*0d601874SDavid du Colombier 		}
69*0d601874SDavid du Colombier 	}
70*0d601874SDavid du Colombier 	if(neg){
71*0d601874SDavid du Colombier 		return 1./d;
72*0d601874SDavid du Colombier 	}
73*0d601874SDavid du Colombier 	return d;
74*0d601874SDavid du Colombier }
75*0d601874SDavid du Colombier 
768ccd4a63SDavid du Colombier static int
xadd(char * a,int n,int v)778ccd4a63SDavid du Colombier xadd(char *a, int n, int v)
788ccd4a63SDavid du Colombier {
798ccd4a63SDavid du Colombier 	char *b;
808ccd4a63SDavid du Colombier 	int c;
818ccd4a63SDavid du Colombier 
828ccd4a63SDavid du Colombier 	if(n < 0 || n >= NSIGNIF)
838ccd4a63SDavid du Colombier 		return 0;
848ccd4a63SDavid du Colombier 	for(b = a+n; b >= a; b--) {
858ccd4a63SDavid du Colombier 		c = *b + v;
868ccd4a63SDavid du Colombier 		if(c <= '9') {
878ccd4a63SDavid du Colombier 			*b = c;
888ccd4a63SDavid du Colombier 			return 0;
898ccd4a63SDavid du Colombier 		}
908ccd4a63SDavid du Colombier 		*b = '0';
918ccd4a63SDavid du Colombier 		v = 1;
928ccd4a63SDavid du Colombier 	}
93*0d601874SDavid du Colombier 	*a = '1';	/* overflow adding */
948ccd4a63SDavid du Colombier 	return 1;
958ccd4a63SDavid du Colombier }
968ccd4a63SDavid du Colombier 
978ccd4a63SDavid du Colombier static int
xsub(char * a,int n,int v)988ccd4a63SDavid du Colombier xsub(char *a, int n, int v)
998ccd4a63SDavid du Colombier {
1008ccd4a63SDavid du Colombier 	char *b;
1018ccd4a63SDavid du Colombier 	int c;
1028ccd4a63SDavid du Colombier 
1038ccd4a63SDavid du Colombier 	for(b = a+n; b >= a; b--) {
1048ccd4a63SDavid du Colombier 		c = *b - v;
1058ccd4a63SDavid du Colombier 		if(c >= '0') {
1068ccd4a63SDavid du Colombier 			*b = c;
1078ccd4a63SDavid du Colombier 			return 0;
1088ccd4a63SDavid du Colombier 		}
1098ccd4a63SDavid du Colombier 		*b = '9';
1108ccd4a63SDavid du Colombier 		v = 1;
1118ccd4a63SDavid du Colombier 	}
112*0d601874SDavid du Colombier 	*a = '9';	/* underflow subtracting */
1138ccd4a63SDavid du Colombier 	return 1;
1148ccd4a63SDavid du Colombier }
1158ccd4a63SDavid du Colombier 
1168ccd4a63SDavid du Colombier static void
xdtoa(Fmt * fmt,char * s2,double f)1178ccd4a63SDavid du Colombier xdtoa(Fmt *fmt, char *s2, double f)
1188ccd4a63SDavid du Colombier {
1198ccd4a63SDavid du Colombier 	char s1[NSIGNIF+10];
1208ccd4a63SDavid du Colombier 	double g, h;
1218ccd4a63SDavid du Colombier 	int e, d, i, n;
1228ccd4a63SDavid du Colombier 	int c1, c2, c3, c4, ucase, sign, chr, prec;
1238ccd4a63SDavid du Colombier 
1248ccd4a63SDavid du Colombier 	prec = FDEFLT;
1258ccd4a63SDavid du Colombier 	if(fmt->flags & FmtPrec)
1268ccd4a63SDavid du Colombier 		prec = fmt->prec;
1278ccd4a63SDavid du Colombier 	if(prec > FDIGIT)
1288ccd4a63SDavid du Colombier 		prec = FDIGIT;
1298ccd4a63SDavid du Colombier 	if(__isNaN(f)) {
1308ccd4a63SDavid du Colombier 		strcpy(s2, "NaN");
1318ccd4a63SDavid du Colombier 		return;
1328ccd4a63SDavid du Colombier 	}
1338ccd4a63SDavid du Colombier 	if(__isInf(f, 1)) {
1348ccd4a63SDavid du Colombier 		strcpy(s2, "+Inf");
1358ccd4a63SDavid du Colombier 		return;
1368ccd4a63SDavid du Colombier 	}
1378ccd4a63SDavid du Colombier 	if(__isInf(f, -1)) {
1388ccd4a63SDavid du Colombier 		strcpy(s2, "-Inf");
1398ccd4a63SDavid du Colombier 		return;
1408ccd4a63SDavid du Colombier 	}
1418ccd4a63SDavid du Colombier 	sign = 0;
1428ccd4a63SDavid du Colombier 	if(f < 0) {
1438ccd4a63SDavid du Colombier 		f = -f;
1448ccd4a63SDavid du Colombier 		sign++;
1458ccd4a63SDavid du Colombier 	}
1468ccd4a63SDavid du Colombier 	ucase = 0;
1478ccd4a63SDavid du Colombier 	chr = fmt->r;
1488ccd4a63SDavid du Colombier 	if(isupper(chr)) {
1498ccd4a63SDavid du Colombier 		ucase = 1;
1508ccd4a63SDavid du Colombier 		chr = tolower(chr);
1518ccd4a63SDavid du Colombier 	}
1528ccd4a63SDavid du Colombier 
1538ccd4a63SDavid du Colombier 	e = 0;
1548ccd4a63SDavid du Colombier 	g = f;
1558ccd4a63SDavid du Colombier 	if(g != 0) {
1568ccd4a63SDavid du Colombier 		frexp(f, &e);
1578ccd4a63SDavid du Colombier 		e = e * .301029995664;
1588ccd4a63SDavid du Colombier 		if(e >= -150 && e <= +150) {
1598ccd4a63SDavid du Colombier 			d = 0;
1608ccd4a63SDavid du Colombier 			h = f;
1618ccd4a63SDavid du Colombier 		} else {
1628ccd4a63SDavid du Colombier 			d = e/2;
1638ccd4a63SDavid du Colombier 			h = f * pow10(-d);
1648ccd4a63SDavid du Colombier 		}
1658ccd4a63SDavid du Colombier 		g = h * pow10(d-e);
1668ccd4a63SDavid du Colombier 		while(g < 1) {
1678ccd4a63SDavid du Colombier 			e--;
1688ccd4a63SDavid du Colombier 			g = h * pow10(d-e);
1698ccd4a63SDavid du Colombier 		}
1708ccd4a63SDavid du Colombier 		while(g >= 10) {
1718ccd4a63SDavid du Colombier 			e++;
1728ccd4a63SDavid du Colombier 			g = h * pow10(d-e);
1738ccd4a63SDavid du Colombier 		}
1748ccd4a63SDavid du Colombier 	}
1758ccd4a63SDavid du Colombier 
1768ccd4a63SDavid du Colombier 	/*
1778ccd4a63SDavid du Colombier 	 * convert NSIGNIF digits and convert
1788ccd4a63SDavid du Colombier 	 * back to get accuracy.
1798ccd4a63SDavid du Colombier 	 */
1808ccd4a63SDavid du Colombier 	for(i=0; i<NSIGNIF; i++) {
1818ccd4a63SDavid du Colombier 		d = g;
1828ccd4a63SDavid du Colombier 		s1[i] = d + '0';
1838ccd4a63SDavid du Colombier 		g = (g - d) * 10;
1848ccd4a63SDavid du Colombier 	}
1858ccd4a63SDavid du Colombier 	s1[i] = 0;
1868ccd4a63SDavid du Colombier 
1878ccd4a63SDavid du Colombier 	/*
1888ccd4a63SDavid du Colombier 	 * try decimal rounding to eliminate 9s
1898ccd4a63SDavid du Colombier 	 */
1908ccd4a63SDavid du Colombier 	c2 = prec + 1;
1918ccd4a63SDavid du Colombier 	if(chr == 'f')
1928ccd4a63SDavid du Colombier 		c2 += e;
1938ccd4a63SDavid du Colombier 	if(c2 >= NSIGNIF-2) {
1948ccd4a63SDavid du Colombier 		strcpy(s2, s1);
1958ccd4a63SDavid du Colombier 		d = e;
1968ccd4a63SDavid du Colombier 		s1[NSIGNIF-2] = '0';
1978ccd4a63SDavid du Colombier 		s1[NSIGNIF-1] = '0';
1988ccd4a63SDavid du Colombier 		sprint(s1+NSIGNIF, "e%d", e-NSIGNIF+1);
1998ccd4a63SDavid du Colombier 		g = strtod(s1, nil);
2008ccd4a63SDavid du Colombier 		if(g == f)
2018ccd4a63SDavid du Colombier 			goto found;
2028ccd4a63SDavid du Colombier 		if(xadd(s1, NSIGNIF-3, 1)) {
2038ccd4a63SDavid du Colombier 			e++;
2048ccd4a63SDavid du Colombier 			sprint(s1+NSIGNIF, "e%d", e-NSIGNIF+1);
2058ccd4a63SDavid du Colombier 		}
2068ccd4a63SDavid du Colombier 		g = strtod(s1, nil);
2078ccd4a63SDavid du Colombier 		if(g == f)
2088ccd4a63SDavid du Colombier 			goto found;
2098ccd4a63SDavid du Colombier 		strcpy(s1, s2);
2108ccd4a63SDavid du Colombier 		e = d;
2118ccd4a63SDavid du Colombier 	}
2128ccd4a63SDavid du Colombier 
2138ccd4a63SDavid du Colombier 	/*
2148ccd4a63SDavid du Colombier 	 * convert back so s1 gets exact answer
2158ccd4a63SDavid du Colombier 	 */
2168ccd4a63SDavid du Colombier 	for(;;) {
2178ccd4a63SDavid du Colombier 		sprint(s1+NSIGNIF, "e%d", e-NSIGNIF+1);
2188ccd4a63SDavid du Colombier 		g = strtod(s1, nil);
2198ccd4a63SDavid du Colombier 		if(f > g) {
2208ccd4a63SDavid du Colombier 			if(xadd(s1, NSIGNIF-1, 1))
2218ccd4a63SDavid du Colombier 				e--;
2228ccd4a63SDavid du Colombier 			continue;
2238ccd4a63SDavid du Colombier 		}
2248ccd4a63SDavid du Colombier 		if(f < g) {
2258ccd4a63SDavid du Colombier 			if(xsub(s1, NSIGNIF-1, 1))
2268ccd4a63SDavid du Colombier 				e++;
2278ccd4a63SDavid du Colombier 			continue;
2288ccd4a63SDavid du Colombier 		}
2298ccd4a63SDavid du Colombier 		break;
2308ccd4a63SDavid du Colombier 	}
2318ccd4a63SDavid du Colombier 
2328ccd4a63SDavid du Colombier found:
2338ccd4a63SDavid du Colombier 	/*
2348ccd4a63SDavid du Colombier 	 * sign
2358ccd4a63SDavid du Colombier 	 */
2368ccd4a63SDavid du Colombier 	d = 0;
2378ccd4a63SDavid du Colombier 	i = 0;
2388ccd4a63SDavid du Colombier 	if(sign)
2398ccd4a63SDavid du Colombier 		s2[d++] = '-';
2408ccd4a63SDavid du Colombier 	else if(fmt->flags & FmtSign)
2418ccd4a63SDavid du Colombier 		s2[d++] = '+';
2428ccd4a63SDavid du Colombier 	else if(fmt->flags & FmtSpace)
2438ccd4a63SDavid du Colombier 		s2[d++] = ' ';
2448ccd4a63SDavid du Colombier 
2458ccd4a63SDavid du Colombier 	/*
2468ccd4a63SDavid du Colombier 	 * copy into final place
2478ccd4a63SDavid du Colombier 	 * c1 digits of leading '0'
2488ccd4a63SDavid du Colombier 	 * c2 digits from conversion
2498ccd4a63SDavid du Colombier 	 * c3 digits of trailing '0'
2508ccd4a63SDavid du Colombier 	 * c4 digits after '.'
2518ccd4a63SDavid du Colombier 	 */
2528ccd4a63SDavid du Colombier 	c1 = 0;
2538ccd4a63SDavid du Colombier 	c2 = prec + 1;
2548ccd4a63SDavid du Colombier 	c3 = 0;
2558ccd4a63SDavid du Colombier 	c4 = prec;
2568ccd4a63SDavid du Colombier 	switch(chr) {
2578ccd4a63SDavid du Colombier 	default:
2588ccd4a63SDavid du Colombier 		if(xadd(s1, c2, 5))
2598ccd4a63SDavid du Colombier 			e++;
2608ccd4a63SDavid du Colombier 		break;
2618ccd4a63SDavid du Colombier 	case 'g':
2628ccd4a63SDavid du Colombier 		/*
2638ccd4a63SDavid du Colombier 		 * decide on 'e' of 'f' style convers
2648ccd4a63SDavid du Colombier 		 */
2658ccd4a63SDavid du Colombier 		if(xadd(s1, c2, 5))
2668ccd4a63SDavid du Colombier 			e++;
2678ccd4a63SDavid du Colombier 		if(e >= -5 && e <= prec) {
2688ccd4a63SDavid du Colombier 			c1 = -e - 1;
2698ccd4a63SDavid du Colombier 			c4 = prec - e;
2708ccd4a63SDavid du Colombier 			chr = 'h';	// flag for 'f' style
2718ccd4a63SDavid du Colombier 		}
2728ccd4a63SDavid du Colombier 		break;
2738ccd4a63SDavid du Colombier 	case 'f':
2748ccd4a63SDavid du Colombier 		if(xadd(s1, c2+e, 5))
2758ccd4a63SDavid du Colombier 			e++;
2768ccd4a63SDavid du Colombier 		c1 = -e;
2778ccd4a63SDavid du Colombier 		if(c1 > prec)
2788ccd4a63SDavid du Colombier 			c1 = c2;
2798ccd4a63SDavid du Colombier 		c2 += e;
2808ccd4a63SDavid du Colombier 		break;
2818ccd4a63SDavid du Colombier 	}
2828ccd4a63SDavid du Colombier 
2838ccd4a63SDavid du Colombier 	/*
2848ccd4a63SDavid du Colombier 	 * clean up c1 c2 and c3
2858ccd4a63SDavid du Colombier 	 */
2868ccd4a63SDavid du Colombier 	if(c1 < 0)
2878ccd4a63SDavid du Colombier 		c1 = 0;
2888ccd4a63SDavid du Colombier 	if(c2 < 0)
2898ccd4a63SDavid du Colombier 		c2 = 0;
2908ccd4a63SDavid du Colombier 	if(c2 > NSIGNIF) {
2918ccd4a63SDavid du Colombier 		c3 = c2-NSIGNIF;
2928ccd4a63SDavid du Colombier 		c2 = NSIGNIF;
2938ccd4a63SDavid du Colombier 	}
2948ccd4a63SDavid du Colombier 
2958ccd4a63SDavid du Colombier 	/*
2968ccd4a63SDavid du Colombier 	 * copy digits
2978ccd4a63SDavid du Colombier 	 */
2988ccd4a63SDavid du Colombier 	while(c1 > 0) {
2998ccd4a63SDavid du Colombier 		if(c1+c2+c3 == c4)
3008ccd4a63SDavid du Colombier 			s2[d++] = '.';
3018ccd4a63SDavid du Colombier 		s2[d++] = '0';
3028ccd4a63SDavid du Colombier 		c1--;
3038ccd4a63SDavid du Colombier 	}
3048ccd4a63SDavid du Colombier 	while(c2 > 0) {
3058ccd4a63SDavid du Colombier 		if(c2+c3 == c4)
3068ccd4a63SDavid du Colombier 			s2[d++] = '.';
3078ccd4a63SDavid du Colombier 		s2[d++] = s1[i++];
3088ccd4a63SDavid du Colombier 		c2--;
3098ccd4a63SDavid du Colombier 	}
3108ccd4a63SDavid du Colombier 	while(c3 > 0) {
3118ccd4a63SDavid du Colombier 		if(c3 == c4)
3128ccd4a63SDavid du Colombier 			s2[d++] = '.';
3138ccd4a63SDavid du Colombier 		s2[d++] = '0';
3148ccd4a63SDavid du Colombier 		c3--;
3158ccd4a63SDavid du Colombier 	}
3168ccd4a63SDavid du Colombier 
3178ccd4a63SDavid du Colombier 	/*
3188ccd4a63SDavid du Colombier 	 * strip trailing '0' on g conv
3198ccd4a63SDavid du Colombier 	 */
3208ccd4a63SDavid du Colombier 	if(fmt->flags & FmtSharp) {
3218ccd4a63SDavid du Colombier 		if(0 == c4)
3228ccd4a63SDavid du Colombier 			s2[d++] = '.';
3238ccd4a63SDavid du Colombier 	} else
3248ccd4a63SDavid du Colombier 	if(chr == 'g' || chr == 'h') {
3258ccd4a63SDavid du Colombier 		for(n=d-1; n>=0; n--)
3268ccd4a63SDavid du Colombier 			if(s2[n] != '0')
3278ccd4a63SDavid du Colombier 				break;
3288ccd4a63SDavid du Colombier 		for(i=n; i>=0; i--)
3298ccd4a63SDavid du Colombier 			if(s2[i] == '.') {
3308ccd4a63SDavid du Colombier 				d = n;
3318ccd4a63SDavid du Colombier 				if(i != n)
3328ccd4a63SDavid du Colombier 					d++;
3338ccd4a63SDavid du Colombier 				break;
3348ccd4a63SDavid du Colombier 			}
3358ccd4a63SDavid du Colombier 	}
3368ccd4a63SDavid du Colombier 	if(chr == 'e' || chr == 'g') {
3378ccd4a63SDavid du Colombier 		if(ucase)
3388ccd4a63SDavid du Colombier 			s2[d++] = 'E';
3398ccd4a63SDavid du Colombier 		else
3408ccd4a63SDavid du Colombier 			s2[d++] = 'e';
3418ccd4a63SDavid du Colombier 		c1 = e;
3428ccd4a63SDavid du Colombier 		if(c1 < 0) {
3438ccd4a63SDavid du Colombier 			s2[d++] = '-';
3448ccd4a63SDavid du Colombier 			c1 = -c1;
3458ccd4a63SDavid du Colombier 		} else
3468ccd4a63SDavid du Colombier 			s2[d++] = '+';
3478ccd4a63SDavid du Colombier 		if(c1 >= 100) {
3488ccd4a63SDavid du Colombier 			s2[d++] = c1/100 + '0';
3498ccd4a63SDavid du Colombier 			c1 = c1%100;
3508ccd4a63SDavid du Colombier 		}
3518ccd4a63SDavid du Colombier 		s2[d++] = c1/10 + '0';
3528ccd4a63SDavid du Colombier 		s2[d++] = c1%10 + '0';
3538ccd4a63SDavid du Colombier 	}
3548ccd4a63SDavid du Colombier 	s2[d] = 0;
3558ccd4a63SDavid du Colombier }
3568ccd4a63SDavid du Colombier 
357*0d601874SDavid du Colombier static int
floatfmt(Fmt * fmt,double f)358*0d601874SDavid du Colombier floatfmt(Fmt *fmt, double f)
3598ccd4a63SDavid du Colombier {
360*0d601874SDavid du Colombier 	char s[341];		/* precision+exponent+sign+'.'+null */
3618ccd4a63SDavid du Colombier 
3628ccd4a63SDavid du Colombier 	xdtoa(fmt, s, f);
3638ccd4a63SDavid du Colombier 	fmt->flags &= FmtWidth|FmtLeft;
364*0d601874SDavid du Colombier 	__fmtcpy(fmt, s, strlen(s), strlen(s));
3658ccd4a63SDavid du Colombier 	return 0;
3668ccd4a63SDavid du Colombier }
3678ccd4a63SDavid du Colombier 
3688ccd4a63SDavid du Colombier int
__efgfmt(Fmt * f)369*0d601874SDavid du Colombier __efgfmt(Fmt *f)
3708ccd4a63SDavid du Colombier {
3718ccd4a63SDavid du Colombier 	double d;
3728ccd4a63SDavid du Colombier 
3738ccd4a63SDavid du Colombier 	d = va_arg(f->args, double);
374*0d601874SDavid du Colombier 	return floatfmt(f, d);
3758ccd4a63SDavid du Colombier }
376