1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin *                                                                      *
3da2e3ebdSchin *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1985-2012 AT&T Intellectual Property          *
5da2e3ebdSchin *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
77c2fbfb3SApril Chin *                    by AT&T Intellectual Property                     *
8da2e3ebdSchin *                                                                      *
9da2e3ebdSchin *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12da2e3ebdSchin *                                                                      *
13da2e3ebdSchin *              Information and Software Systems Research               *
14da2e3ebdSchin *                            AT&T Research                             *
15da2e3ebdSchin *                           Florham Park NJ                            *
16da2e3ebdSchin *                                                                      *
17da2e3ebdSchin *                 Glenn Fowler <gsf@research.att.com>                  *
18da2e3ebdSchin *                  David Korn <dgk@research.att.com>                   *
19da2e3ebdSchin *                   Phong Vo <kpv@research.att.com>                    *
20da2e3ebdSchin *                                                                      *
21da2e3ebdSchin ***********************************************************************/
227c2fbfb3SApril Chin #if __STDC__
23*b30d1939SAndy Fiddaman #include	"FEATURE/standards"
247c2fbfb3SApril Chin #endif
25da2e3ebdSchin #include	"sfhdr.h"
26da2e3ebdSchin 
27da2e3ebdSchin /*	Convert a floating point value to ASCII.
28da2e3ebdSchin **
29da2e3ebdSchin **	Written by Kiem-Phong Vo and Glenn Fowler (SFFMT_AFORMAT)
30da2e3ebdSchin */
31da2e3ebdSchin 
32da2e3ebdSchin static char		*lc_inf = "inf", *uc_inf = "INF";
33da2e3ebdSchin static char		*lc_nan = "nan", *uc_nan = "NAN";
34da2e3ebdSchin static char		*Zero = "0";
35*b30d1939SAndy Fiddaman #define SF_INF		((_Sfi = 3), strlcpy(buf, (format & SFFMT_UPPER) ? uc_inf : lc_inf, size), buf)
36*b30d1939SAndy Fiddaman #define SF_NAN		((_Sfi = 3), strlcpy(buf, (format & SFFMT_UPPER) ? uc_nan : lc_nan, size), buf)
37*b30d1939SAndy Fiddaman #define SF_ZERO		((_Sfi = 1), strlcpy(buf, Zero, size), buf)
38da2e3ebdSchin #define SF_INTPART	(SF_IDIGITS/2)
39da2e3ebdSchin 
40*b30d1939SAndy Fiddaman #if !_lib_isnan
41*b30d1939SAndy Fiddaman #undef	isnan
42*b30d1939SAndy Fiddaman #undef	isnanl
43da2e3ebdSchin #if _lib_fpclassify
44da2e3ebdSchin #define isnan(n)	(fpclassify(n)==FP_NAN)
45da2e3ebdSchin #define isnanl(n)	(fpclassify(n)==FP_NAN)
46da2e3ebdSchin #else
47*b30d1939SAndy Fiddaman #error "This is an invalid test for NaN"
48da2e3ebdSchin #define isnan(n)	(memcmp((void*)&n,(void*)&_Sfdnan,sizeof(n))==0)
49da2e3ebdSchin #define isnanl(n)	(memcmp((void*)&n,(void*)&_Sflnan,sizeof(n))==0)
50da2e3ebdSchin #endif
51da2e3ebdSchin #else
52*b30d1939SAndy Fiddaman #if !_lib_isnanl
53*b30d1939SAndy Fiddaman #undef	isnanl
54da2e3ebdSchin #define isnanl(n)	isnan(n)
55da2e3ebdSchin #endif
56da2e3ebdSchin #endif
57da2e3ebdSchin 
58*b30d1939SAndy Fiddaman #if !_lib_signbit
59*b30d1939SAndy Fiddaman #if !_ast_fltmax_double
neg0ld(Sfdouble_t f)607c2fbfb3SApril Chin static int neg0ld(Sfdouble_t f)
617c2fbfb3SApril Chin {
62*b30d1939SAndy Fiddaman 	Sfdouble_t	z = 0;
63*b30d1939SAndy Fiddaman 	z = -z;
647c2fbfb3SApril Chin 	return !memcmp(&f, &z, sizeof(f));
657c2fbfb3SApril Chin }
667c2fbfb3SApril Chin #endif
neg0d(double f)677c2fbfb3SApril Chin static int neg0d(double f)
687c2fbfb3SApril Chin {
69*b30d1939SAndy Fiddaman 	double		z = 0;
70*b30d1939SAndy Fiddaman 	z = -z;
717c2fbfb3SApril Chin 	return !memcmp(&f, &z, sizeof(f));
727c2fbfb3SApril Chin }
737c2fbfb3SApril Chin #endif
747c2fbfb3SApril Chin 
757c2fbfb3SApril Chin #if ULONG_DIG && ULONG_DIG < (DBL_DIG-1)
767c2fbfb3SApril Chin #define CVT_LDBL_INT	long
777c2fbfb3SApril Chin #define CVT_LDBL_MAXINT	LONG_MAX
787c2fbfb3SApril Chin #else
797c2fbfb3SApril Chin #if UINT_DIG && UINT_DIG < (DBL_DIG-1)
807c2fbfb3SApril Chin #define CVT_LDBL_INT	int
817c2fbfb3SApril Chin #define CVT_LDBL_MAXINT	INT_MAX
827c2fbfb3SApril Chin #else
837c2fbfb3SApril Chin #define CVT_LDBL_INT	long
847c2fbfb3SApril Chin #define CVT_LDBL_MAXINT	SF_MAXLONG
857c2fbfb3SApril Chin #endif
867c2fbfb3SApril Chin #endif
877c2fbfb3SApril Chin 
887c2fbfb3SApril Chin #if ULONG_DIG && ULONG_DIG < (DBL_DIG-1)
897c2fbfb3SApril Chin #define CVT_DBL_INT	long
907c2fbfb3SApril Chin #define CVT_DBL_MAXINT	LONG_MAX
917c2fbfb3SApril Chin #else
927c2fbfb3SApril Chin #if UINT_DIG && UINT_DIG < (DBL_DIG-1)
937c2fbfb3SApril Chin #define CVT_DBL_INT	int
947c2fbfb3SApril Chin #define CVT_DBL_MAXINT	INT_MAX
957c2fbfb3SApril Chin #else
967c2fbfb3SApril Chin #define CVT_DBL_INT	long
977c2fbfb3SApril Chin #define CVT_DBL_MAXINT	SF_MAXLONG
987c2fbfb3SApril Chin #endif
997c2fbfb3SApril Chin #endif
1007c2fbfb3SApril Chin 
101da2e3ebdSchin #if __STD_C
_sfcvt(Void_t * vp,char * buf,size_t size,int n_digit,int * decpt,int * sign,int * len,int format)1027c2fbfb3SApril Chin char* _sfcvt(Void_t* vp, char* buf, size_t size, int n_digit,
103da2e3ebdSchin 		int* decpt, int* sign, int* len, int format)
104da2e3ebdSchin #else
1057c2fbfb3SApril Chin char* _sfcvt(vp,buf,size,n_digit,decpt,sign,len,format)
1067c2fbfb3SApril Chin Void_t*		vp;		/* pointer to value to convert	*/
107da2e3ebdSchin char*		buf;		/* conversion goes here		*/
108da2e3ebdSchin size_t		size;		/* size of buf			*/
109da2e3ebdSchin int		n_digit;	/* number of digits wanted	*/
110da2e3ebdSchin int*		decpt;		/* to return decimal point	*/
111da2e3ebdSchin int*		sign;		/* to return sign		*/
112da2e3ebdSchin int*		len;		/* return string length		*/
113da2e3ebdSchin int		format;		/* conversion format		*/
114da2e3ebdSchin #endif
115da2e3ebdSchin {
116da2e3ebdSchin 	reg char		*sp;
117da2e3ebdSchin 	reg long		n, v;
11834f9b3eeSRoland Mainz 	reg char		*ep, *b, *endsp, *t;
11934f9b3eeSRoland Mainz 	int			x;
120da2e3ebdSchin 	_ast_flt_unsigned_max_t	m;
121da2e3ebdSchin 
122da2e3ebdSchin 	static char		lx[] = "0123456789abcdef";
123da2e3ebdSchin 	static char		ux[] = "0123456789ABCDEF";
124da2e3ebdSchin 
125da2e3ebdSchin 	*sign = *decpt = 0;
126da2e3ebdSchin 
127da2e3ebdSchin #if !_ast_fltmax_double
128da2e3ebdSchin 	if(format&SFFMT_LDOUBLE)
1297c2fbfb3SApril Chin 	{	Sfdouble_t	f = *(Sfdouble_t*)vp;
1307c2fbfb3SApril Chin 
1317c2fbfb3SApril Chin 		if(isnanl(f))
1327c2fbfb3SApril Chin 		{
133da2e3ebdSchin #if _lib_signbit
1347c2fbfb3SApril Chin 			if (signbit(f))
135da2e3ebdSchin #else
1367c2fbfb3SApril Chin 			if (f < 0)
137da2e3ebdSchin #endif
1387c2fbfb3SApril Chin 				*sign = 1;
1397c2fbfb3SApril Chin 			return SF_NAN;
1407c2fbfb3SApril Chin 		}
1417c2fbfb3SApril Chin #if _lib_isinf
1427c2fbfb3SApril Chin 		if (n = isinf(f))
1437c2fbfb3SApril Chin 		{
1447c2fbfb3SApril Chin #if _lib_signbit
1457c2fbfb3SApril Chin 			if (signbit(f))
1467c2fbfb3SApril Chin #else
1477c2fbfb3SApril Chin 			if (n < 0 || f < 0)
148da2e3ebdSchin #endif
1497c2fbfb3SApril Chin 				*sign = 1;
1507c2fbfb3SApril Chin 			return SF_INF;
1517c2fbfb3SApril Chin 		}
152da2e3ebdSchin #endif
1537c2fbfb3SApril Chin # if _c99_in_the_wild
1547c2fbfb3SApril Chin #  if _lib_signbit
1557c2fbfb3SApril Chin 		if (signbit(f))
1567c2fbfb3SApril Chin #  else
1577c2fbfb3SApril Chin #   if _lib_copysignl
1587c2fbfb3SApril Chin 		if (copysignl(1.0, f) < 0.0)
1597c2fbfb3SApril Chin #   else
1607c2fbfb3SApril Chin #    if _lib_copysign
1617c2fbfb3SApril Chin 		if (copysign(1.0, (double)f) < 0.0)
1627c2fbfb3SApril Chin #    else
1637c2fbfb3SApril Chin 		if (f < 0.0)
1647c2fbfb3SApril Chin #    endif
1657c2fbfb3SApril Chin #   endif
1667c2fbfb3SApril Chin #  endif
167da2e3ebdSchin 		{	f = -f;
168da2e3ebdSchin 			*sign = 1;
169da2e3ebdSchin 		}
1707c2fbfb3SApril Chin #  if _lib_fpclassify
171da2e3ebdSchin 		switch (fpclassify(f))
172da2e3ebdSchin 		{
173da2e3ebdSchin 		case FP_INFINITE:
174da2e3ebdSchin 			return SF_INF;
175da2e3ebdSchin 		case FP_NAN:
176da2e3ebdSchin 			return SF_NAN;
177da2e3ebdSchin 		case FP_ZERO:
178da2e3ebdSchin 			return SF_ZERO;
179da2e3ebdSchin 		}
1807c2fbfb3SApril Chin #  endif
1817c2fbfb3SApril Chin # else
1827c2fbfb3SApril Chin #  if _lib_signbit
1837c2fbfb3SApril Chin 		if (signbit(f))
1847c2fbfb3SApril Chin #  else
1857c2fbfb3SApril Chin 		if (f < 0.0 || f == 0.0 && neg0ld(f))
1867c2fbfb3SApril Chin #  endif
187da2e3ebdSchin 		{	f = -f;
188da2e3ebdSchin 			*sign = 1;
189da2e3ebdSchin 		}
1907c2fbfb3SApril Chin # endif
191da2e3ebdSchin 		if(f < LDBL_MIN)
192da2e3ebdSchin 			return SF_ZERO;
193da2e3ebdSchin 		if(f > LDBL_MAX)
194da2e3ebdSchin 			return SF_INF;
195da2e3ebdSchin 
196da2e3ebdSchin 		if(format & SFFMT_AFORMAT)
197da2e3ebdSchin 		{	Sfdouble_t	g;
198da2e3ebdSchin 			b = sp = buf;
199da2e3ebdSchin 			ep = (format & SFFMT_UPPER) ? ux : lx;
200da2e3ebdSchin 			if(n_digit <= 0 || n_digit >= (size - 9))
201da2e3ebdSchin 				n_digit = size - 9;
202da2e3ebdSchin 			endsp = sp + n_digit + 1;
203da2e3ebdSchin 
204da2e3ebdSchin 			g = frexpl(f, &x);
205da2e3ebdSchin 			*decpt = x;
206da2e3ebdSchin 			f = ldexpl(g, 8 * sizeof(m) - 3);
207da2e3ebdSchin 
208da2e3ebdSchin 			for (;;)
209da2e3ebdSchin 			{	m = f;
210da2e3ebdSchin 				x = 8 * sizeof(m);
211da2e3ebdSchin 				while ((x -= 4) >= 0)
212da2e3ebdSchin 				{	*sp++ = ep[(m >> x) & 0xf];
213da2e3ebdSchin 					if (sp >= endsp)
21434f9b3eeSRoland Mainz 						goto around;
215da2e3ebdSchin 				}
216da2e3ebdSchin 				f -= m;
217da2e3ebdSchin 				f = ldexpl(f, 8 * sizeof(m));
218da2e3ebdSchin 			}
219da2e3ebdSchin 		}
220da2e3ebdSchin 
221da2e3ebdSchin 		n = 0;
2227c2fbfb3SApril Chin 		if(f >= (Sfdouble_t)CVT_LDBL_MAXINT)
223da2e3ebdSchin 		{	/* scale to a small enough number to fit an int */
224da2e3ebdSchin 			v = SF_MAXEXP10-1;
225da2e3ebdSchin 			do
226da2e3ebdSchin 			{	if(f < _Sfpos10[v])
227da2e3ebdSchin 					v -= 1;
228da2e3ebdSchin 				else
229da2e3ebdSchin 				{
230da2e3ebdSchin 					f *= _Sfneg10[v];
231da2e3ebdSchin 					if((n += (1<<v)) >= SF_IDIGITS)
232da2e3ebdSchin 						return SF_INF;
233da2e3ebdSchin 				}
2347c2fbfb3SApril Chin 			} while(f >= (Sfdouble_t)CVT_LDBL_MAXINT);
2357c2fbfb3SApril Chin 		}
2367c2fbfb3SApril Chin 		else if(f > 0.0 && f < 0.1)
2377c2fbfb3SApril Chin 		{	/* scale to avoid excessive multiply by 10 below */
2387c2fbfb3SApril Chin 			v = SF_MAXEXP10-1;
2397c2fbfb3SApril Chin 			do
2407c2fbfb3SApril Chin 			{	if(f <= _Sfneg10[v])
2417c2fbfb3SApril Chin 				{	f *= _Sfpos10[v];
2427c2fbfb3SApril Chin 					if((n += (1<<v)) >= SF_IDIGITS)
2437c2fbfb3SApril Chin 						return SF_INF;
2447c2fbfb3SApril Chin 				}
2457c2fbfb3SApril Chin 				else if (--v < 0)
2467c2fbfb3SApril Chin 					break;
2477c2fbfb3SApril Chin 			} while(f < 0.1);
2487c2fbfb3SApril Chin 			n = -n;
249da2e3ebdSchin 		}
250da2e3ebdSchin 		*decpt = (int)n;
251da2e3ebdSchin 
252da2e3ebdSchin 		b = sp = buf + SF_INTPART;
2537c2fbfb3SApril Chin 		if((v = (CVT_LDBL_INT)f) != 0)
254da2e3ebdSchin 		{	/* translate the integer part */
255da2e3ebdSchin 			f -= (Sfdouble_t)v;
256da2e3ebdSchin 
2577c2fbfb3SApril Chin 			sfucvt(v,sp,n,ep,CVT_LDBL_INT,unsigned CVT_LDBL_INT);
258da2e3ebdSchin 
259da2e3ebdSchin 			n = b-sp;
260da2e3ebdSchin 			if((*decpt += (int)n) >= SF_IDIGITS)
261da2e3ebdSchin 				return SF_INF;
262da2e3ebdSchin 			b = sp;
263da2e3ebdSchin 			sp = buf + SF_INTPART;
264da2e3ebdSchin 		}
265da2e3ebdSchin 		else	n = 0;
266da2e3ebdSchin 
267da2e3ebdSchin 		/* remaining number of digits to compute; add 1 for later rounding */
268da2e3ebdSchin 		n = (((format&SFFMT_EFORMAT) || *decpt <= 0) ? 1 : *decpt+1) - n;
269da2e3ebdSchin 		if(n_digit > 0)
270da2e3ebdSchin 		{	if(n_digit > LDBL_DIG)
271da2e3ebdSchin 				n_digit = LDBL_DIG;
272da2e3ebdSchin 			n += n_digit;
273da2e3ebdSchin 		}
274da2e3ebdSchin 
275da2e3ebdSchin 		if((ep = (sp+n)) > (endsp = buf+(size-2)))
276da2e3ebdSchin 			ep = endsp;
277da2e3ebdSchin 		if(sp > ep)
278da2e3ebdSchin 			sp = ep;
279da2e3ebdSchin 		else
280da2e3ebdSchin 		{
281da2e3ebdSchin 			if((format&SFFMT_EFORMAT) && *decpt == 0 && f > 0.)
282da2e3ebdSchin 			{	Sfdouble_t	d;
283da2e3ebdSchin 				while((long)(d = f*10.) == 0)
284da2e3ebdSchin 				{	f = d;
285da2e3ebdSchin 					*decpt -= 1;
286da2e3ebdSchin 				}
287da2e3ebdSchin 			}
288da2e3ebdSchin 
289da2e3ebdSchin 			while(sp < ep)
290da2e3ebdSchin 			{	/* generate fractional digits */
291da2e3ebdSchin 				if(f <= 0.)
292da2e3ebdSchin 				{	/* fill with 0's */
293da2e3ebdSchin 					do { *sp++ = '0'; } while(sp < ep);
294da2e3ebdSchin 					goto done;
295da2e3ebdSchin 				}
296da2e3ebdSchin 				else if((n = (long)(f *= 10.)) < 10)
297da2e3ebdSchin 				{	*sp++ = '0' + n;
298da2e3ebdSchin 					f -= n;
299da2e3ebdSchin 				}
300da2e3ebdSchin 				else /* n == 10 */
301da2e3ebdSchin 				{	do { *sp++ = '9'; } while(sp < ep);
302da2e3ebdSchin 				}
303da2e3ebdSchin 			}
304da2e3ebdSchin 		}
305da2e3ebdSchin 	} else
306da2e3ebdSchin #endif
3077c2fbfb3SApril Chin 	{	double	f = *(double*)vp;
308da2e3ebdSchin 
3097c2fbfb3SApril Chin 		if(isnan(f))
3107c2fbfb3SApril Chin 		{
3117c2fbfb3SApril Chin #if _lib_signbit
3127c2fbfb3SApril Chin 			if (signbit(f))
3137c2fbfb3SApril Chin #else
3147c2fbfb3SApril Chin 			if (f < 0)
3157c2fbfb3SApril Chin #endif
3167c2fbfb3SApril Chin 				*sign = 1;
3177c2fbfb3SApril Chin 			return SF_NAN;
3187c2fbfb3SApril Chin 		}
319da2e3ebdSchin #if _lib_isinf
320da2e3ebdSchin 		if (n = isinf(f))
3217c2fbfb3SApril Chin 		{
3227c2fbfb3SApril Chin #if _lib_signbit
3237c2fbfb3SApril Chin 			if (signbit(f))
3247c2fbfb3SApril Chin #else
3257c2fbfb3SApril Chin 			if (n < 0 || f < 0)
3267c2fbfb3SApril Chin #endif
327da2e3ebdSchin 				*sign = 1;
328da2e3ebdSchin 			return SF_INF;
329da2e3ebdSchin 		}
330da2e3ebdSchin #endif
331da2e3ebdSchin #if _c99_in_the_wild
3327c2fbfb3SApril Chin # if _lib_signbit
333da2e3ebdSchin 		if (signbit(f))
3347c2fbfb3SApril Chin # else
3357c2fbfb3SApril Chin #  if _lib_copysign
336da2e3ebdSchin 		if (copysign(1.0, f) < 0.0)
3377c2fbfb3SApril Chin #  else
338da2e3ebdSchin 		if (f < 0.0)
3397c2fbfb3SApril Chin #  endif
3407c2fbfb3SApril Chin # endif
341da2e3ebdSchin 		{	f = -f;
342da2e3ebdSchin 			*sign = 1;
343da2e3ebdSchin 		}
3447c2fbfb3SApril Chin # if _lib_fpclassify
345da2e3ebdSchin 		switch (fpclassify(f))
346da2e3ebdSchin 		{
347da2e3ebdSchin 		case FP_INFINITE:
348da2e3ebdSchin 			return SF_INF;
349da2e3ebdSchin 		case FP_NAN:
350da2e3ebdSchin 			return SF_NAN;
351da2e3ebdSchin 		case FP_ZERO:
352da2e3ebdSchin 			return SF_ZERO;
353da2e3ebdSchin 		}
3547c2fbfb3SApril Chin # endif
355da2e3ebdSchin #else
3567c2fbfb3SApril Chin # if _lib_signbit
3577c2fbfb3SApril Chin 		if (signbit(f))
3587c2fbfb3SApril Chin # else
3597c2fbfb3SApril Chin 		if (f < 0.0 || f == 0.0 && neg0d(f))
3607c2fbfb3SApril Chin # endif
361da2e3ebdSchin 		{	f = -f;
362da2e3ebdSchin 			*sign = 1;
363da2e3ebdSchin 		}
364da2e3ebdSchin #endif
365da2e3ebdSchin 		if(f < DBL_MIN)
366da2e3ebdSchin 			return SF_ZERO;
367da2e3ebdSchin 		if(f > DBL_MAX)
368da2e3ebdSchin 			return SF_INF;
369da2e3ebdSchin 
370da2e3ebdSchin 		if(format & SFFMT_AFORMAT)
37134f9b3eeSRoland Mainz 		{	double		g;
372da2e3ebdSchin 			b = sp = buf;
373da2e3ebdSchin 			ep = (format & SFFMT_UPPER) ? ux : lx;
374da2e3ebdSchin 			if(n_digit <= 0 || n_digit >= (size - 9))
375da2e3ebdSchin 				n_digit = size - 9;
37634f9b3eeSRoland Mainz 			endsp = sp + n_digit + 1;
377da2e3ebdSchin 
378da2e3ebdSchin 			g = frexp(f, &x);
379da2e3ebdSchin 			*decpt = x;
380da2e3ebdSchin 			f = ldexp(g, 8 * sizeof(m) - 3);
381da2e3ebdSchin 
382da2e3ebdSchin 			for (;;)
383da2e3ebdSchin 			{	m = f;
384da2e3ebdSchin 				x = 8 * sizeof(m);
385da2e3ebdSchin 				while ((x -= 4) >= 0)
386da2e3ebdSchin 				{	*sp++ = ep[(m >> x) & 0xf];
387da2e3ebdSchin 					if (sp >= endsp)
38834f9b3eeSRoland Mainz 						goto around;
389da2e3ebdSchin 				}
390da2e3ebdSchin 				f -= m;
391da2e3ebdSchin 				f = ldexp(f, 8 * sizeof(m));
392da2e3ebdSchin 			}
393da2e3ebdSchin 		}
394da2e3ebdSchin 		n = 0;
3957c2fbfb3SApril Chin 		if(f >= (double)CVT_DBL_MAXINT)
396da2e3ebdSchin 		{	/* scale to a small enough number to fit an int */
397da2e3ebdSchin 			v = SF_MAXEXP10-1;
398da2e3ebdSchin 			do
399da2e3ebdSchin 			{	if(f < _Sfpos10[v])
400da2e3ebdSchin 					v -= 1;
401da2e3ebdSchin 				else
402da2e3ebdSchin 				{	f *= _Sfneg10[v];
403da2e3ebdSchin 					if((n += (1<<v)) >= SF_IDIGITS)
404da2e3ebdSchin 						return SF_INF;
405da2e3ebdSchin 				}
4067c2fbfb3SApril Chin 			} while(f >= (double)CVT_DBL_MAXINT);
4077c2fbfb3SApril Chin 		}
4087c2fbfb3SApril Chin 		else if(f > 0.0 && f < 1e-8)
4097c2fbfb3SApril Chin 		{	/* scale to avoid excessive multiply by 10 below */
4107c2fbfb3SApril Chin 			v = SF_MAXEXP10-1;
4117c2fbfb3SApril Chin 			do
4127c2fbfb3SApril Chin 			{	if(f <= _Sfneg10[v])
4137c2fbfb3SApril Chin 				{	f *= _Sfpos10[v];
4147c2fbfb3SApril Chin 					if((n += (1<<v)) >= SF_IDIGITS)
4157c2fbfb3SApril Chin 						return SF_INF;
4167c2fbfb3SApril Chin 				}
4177c2fbfb3SApril Chin 				else if(--v < 0)
4187c2fbfb3SApril Chin 					break;
4197c2fbfb3SApril Chin 			} while(f < 0.1);
4207c2fbfb3SApril Chin 			n = -n;
421da2e3ebdSchin 		}
422da2e3ebdSchin 		*decpt = (int)n;
423da2e3ebdSchin 
424da2e3ebdSchin 		b = sp = buf + SF_INTPART;
4257c2fbfb3SApril Chin 		if((v = (CVT_DBL_INT)f) != 0)
426da2e3ebdSchin 		{	/* translate the integer part */
427da2e3ebdSchin 			f -= (double)v;
428da2e3ebdSchin 
4297c2fbfb3SApril Chin 			sfucvt(v,sp,n,ep,CVT_DBL_INT,unsigned CVT_DBL_INT);
430da2e3ebdSchin 
431da2e3ebdSchin 			n = b-sp;
432da2e3ebdSchin 			if((*decpt += (int)n) >= SF_IDIGITS)
433da2e3ebdSchin 				return SF_INF;
434da2e3ebdSchin 			b = sp;
435da2e3ebdSchin 			sp = buf + SF_INTPART;
436da2e3ebdSchin 		}
437da2e3ebdSchin 		else	n = 0;
438da2e3ebdSchin 
439da2e3ebdSchin 		/* remaining number of digits to compute; add 1 for later rounding */
440da2e3ebdSchin 		n = (((format&SFFMT_EFORMAT) || *decpt <= 0) ? 1 : *decpt+1) - n;
441da2e3ebdSchin 		if(n_digit > 0)
442da2e3ebdSchin 		{	if(n_digit > DBL_DIG)
443da2e3ebdSchin 				n_digit = DBL_DIG;
444da2e3ebdSchin 			n += n_digit;
445da2e3ebdSchin 		}
446da2e3ebdSchin 
447da2e3ebdSchin 		if((ep = (sp+n)) > (endsp = buf+(size-2)))
448da2e3ebdSchin 			ep = endsp;
449da2e3ebdSchin 		if(sp > ep)
450da2e3ebdSchin 			sp = ep;
451da2e3ebdSchin 		else
452da2e3ebdSchin 		{
453da2e3ebdSchin 			if((format&SFFMT_EFORMAT) && *decpt == 0 && f > 0.)
454da2e3ebdSchin 			{	reg double	d;
455da2e3ebdSchin 				while((long)(d = f*10.) == 0)
456da2e3ebdSchin 				{	f = d;
457da2e3ebdSchin 					*decpt -= 1;
458da2e3ebdSchin 				}
459da2e3ebdSchin 			}
460da2e3ebdSchin 
461da2e3ebdSchin 			while(sp < ep)
462da2e3ebdSchin 			{	/* generate fractional digits */
463da2e3ebdSchin 				if(f <= 0.)
464da2e3ebdSchin 				{	/* fill with 0's */
465da2e3ebdSchin 					do { *sp++ = '0'; } while(sp < ep);
466da2e3ebdSchin 					goto done;
467da2e3ebdSchin 				}
468da2e3ebdSchin 				else if((n = (long)(f *= 10.)) < 10)
469da2e3ebdSchin 				{	*sp++ = (char)('0' + n);
470da2e3ebdSchin 					f -= n;
471da2e3ebdSchin 				}
472da2e3ebdSchin 				else /* n == 10 */
473da2e3ebdSchin 				{	do { *sp++ = '9'; } while(sp < ep);
4747c2fbfb3SApril Chin 					break;
475da2e3ebdSchin 				}
476da2e3ebdSchin 			}
477da2e3ebdSchin 		}
478da2e3ebdSchin 	}
479da2e3ebdSchin 
480da2e3ebdSchin 	if(ep <= b)
481da2e3ebdSchin 		ep = b+1;
482da2e3ebdSchin 	else if(ep < endsp)
483da2e3ebdSchin 	{	/* round the last digit */
484da2e3ebdSchin 		*--sp += 5;
485da2e3ebdSchin 		while(*sp > '9')
486da2e3ebdSchin 		{	*sp = '0';
487da2e3ebdSchin 			if(sp > b)
488da2e3ebdSchin 				*--sp += 1;
489da2e3ebdSchin 			else
490da2e3ebdSchin 			{	/* next power of 10 */
491da2e3ebdSchin 				*sp = '1';
492da2e3ebdSchin 				*decpt += 1;
493da2e3ebdSchin 				if(!(format&SFFMT_EFORMAT))
494da2e3ebdSchin 				{	/* add one more 0 for %f precision */
495da2e3ebdSchin 					ep[-1] = '0';
496da2e3ebdSchin 					ep += 1;
497da2e3ebdSchin 				}
498da2e3ebdSchin 			}
499da2e3ebdSchin 		}
500da2e3ebdSchin 	}
501da2e3ebdSchin 
50234f9b3eeSRoland Mainz  done:
503da2e3ebdSchin 	*--ep = '\0';
504da2e3ebdSchin 	if(len)
505da2e3ebdSchin 		*len = ep-b;
506da2e3ebdSchin 	return b;
50734f9b3eeSRoland Mainz  around:
50834f9b3eeSRoland Mainz 	if (((m >> x) & 0xf) >= 8)
50934f9b3eeSRoland Mainz 	{	t = sp - 1;
51034f9b3eeSRoland Mainz 		for (;;)
51134f9b3eeSRoland Mainz 		{	if (--t <= b)
51234f9b3eeSRoland Mainz 			{	(*decpt)++;
51334f9b3eeSRoland Mainz 				break;
51434f9b3eeSRoland Mainz 			}
51534f9b3eeSRoland Mainz 			switch (*t)
51634f9b3eeSRoland Mainz 			{
51734f9b3eeSRoland Mainz 			case 'f':
51834f9b3eeSRoland Mainz 			case 'F':
51934f9b3eeSRoland Mainz 				*t = '0';
52034f9b3eeSRoland Mainz 				continue;
52134f9b3eeSRoland Mainz 			case '9':
52234f9b3eeSRoland Mainz 				*t = ep[10];
52334f9b3eeSRoland Mainz 				break;
52434f9b3eeSRoland Mainz 			default:
52534f9b3eeSRoland Mainz 				(*t)++;
52634f9b3eeSRoland Mainz 				break;
52734f9b3eeSRoland Mainz 			}
52834f9b3eeSRoland Mainz 			break;
52934f9b3eeSRoland Mainz 		}
53034f9b3eeSRoland Mainz 	}
53134f9b3eeSRoland Mainz 	ep = sp + 1;
53234f9b3eeSRoland Mainz 	goto done;
533da2e3ebdSchin }
534