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