xref: /onnv-gate/usr/src/lib/libast/common/sfio/sfcvt.c (revision 8462:6e341f5569ba)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*8462SApril.Chin@Sun.COM *          Copyright (c) 1985-2008 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
7*8462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
84887Schin *                                                                      *
94887Schin *                A copy of the License is available at                 *
104887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
114887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
124887Schin *                                                                      *
134887Schin *              Information and Software Systems Research               *
144887Schin *                            AT&T Research                             *
154887Schin *                           Florham Park NJ                            *
164887Schin *                                                                      *
174887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
184887Schin *                  David Korn <dgk@research.att.com>                   *
194887Schin *                   Phong Vo <kpv@research.att.com>                    *
204887Schin *                                                                      *
214887Schin ***********************************************************************/
22*8462SApril.Chin@Sun.COM #if __STDC__
23*8462SApril.Chin@Sun.COM #include	"FEATURE/isoc99"
24*8462SApril.Chin@Sun.COM #endif
254887Schin #include	"sfhdr.h"
264887Schin 
274887Schin /*	Convert a floating point value to ASCII.
284887Schin **
294887Schin **	Written by Kiem-Phong Vo and Glenn Fowler (SFFMT_AFORMAT)
304887Schin */
314887Schin 
324887Schin static char		*lc_inf = "inf", *uc_inf = "INF";
334887Schin static char		*lc_nan = "nan", *uc_nan = "NAN";
344887Schin static char		*Zero = "0";
354887Schin #define SF_INF		((_Sfi = 3), strncpy(buf, (format & SFFMT_UPPER) ? uc_inf : lc_inf, size))
364887Schin #define SF_NAN		((_Sfi = 3), strncpy(buf, (format & SFFMT_UPPER) ? uc_nan : lc_nan, size))
374887Schin #define SF_ZERO		((_Sfi = 1), strncpy(buf, Zero, size))
384887Schin #define SF_INTPART	(SF_IDIGITS/2)
394887Schin 
404887Schin #if ! _lib_isnan
414887Schin #if _lib_fpclassify
424887Schin #define isnan(n)	(fpclassify(n)==FP_NAN)
434887Schin #define isnanl(n)	(fpclassify(n)==FP_NAN)
444887Schin #else
454887Schin #define isnan(n)	(memcmp((void*)&n,(void*)&_Sfdnan,sizeof(n))==0)
464887Schin #define isnanl(n)	(memcmp((void*)&n,(void*)&_Sflnan,sizeof(n))==0)
474887Schin #endif
484887Schin #else
494887Schin #if ! _lib_isnanl
504887Schin #define isnanl(n)	isnan(n)
514887Schin #endif
524887Schin #endif
534887Schin 
54*8462SApril.Chin@Sun.COM #if ! _lib_signbit && defined(signbit)
55*8462SApril.Chin@Sun.COM #undef	_lib_signbit
56*8462SApril.Chin@Sun.COM #define _lib_signbit	1
57*8462SApril.Chin@Sun.COM #endif
58*8462SApril.Chin@Sun.COM 
59*8462SApril.Chin@Sun.COM #if ! _lib_signbit
60*8462SApril.Chin@Sun.COM #if ! _ast_fltmax_double
61*8462SApril.Chin@Sun.COM static int neg0ld(Sfdouble_t f)
62*8462SApril.Chin@Sun.COM {
63*8462SApril.Chin@Sun.COM 	Sfdouble_t	z = -0.0;
64*8462SApril.Chin@Sun.COM 	return !memcmp(&f, &z, sizeof(f));
65*8462SApril.Chin@Sun.COM }
66*8462SApril.Chin@Sun.COM #endif
67*8462SApril.Chin@Sun.COM static int neg0d(double f)
68*8462SApril.Chin@Sun.COM {
69*8462SApril.Chin@Sun.COM 	double		z = -0.0;
70*8462SApril.Chin@Sun.COM 	return !memcmp(&f, &z, sizeof(f));
71*8462SApril.Chin@Sun.COM }
72*8462SApril.Chin@Sun.COM #endif
73*8462SApril.Chin@Sun.COM 
74*8462SApril.Chin@Sun.COM #if ULONG_DIG && ULONG_DIG < (DBL_DIG-1)
75*8462SApril.Chin@Sun.COM #define CVT_LDBL_INT	long
76*8462SApril.Chin@Sun.COM #define CVT_LDBL_MAXINT	LONG_MAX
77*8462SApril.Chin@Sun.COM #else
78*8462SApril.Chin@Sun.COM #if UINT_DIG && UINT_DIG < (DBL_DIG-1)
79*8462SApril.Chin@Sun.COM #define CVT_LDBL_INT	int
80*8462SApril.Chin@Sun.COM #define CVT_LDBL_MAXINT	INT_MAX
81*8462SApril.Chin@Sun.COM #else
82*8462SApril.Chin@Sun.COM #define CVT_LDBL_INT	long
83*8462SApril.Chin@Sun.COM #define CVT_LDBL_MAXINT	SF_MAXLONG
84*8462SApril.Chin@Sun.COM #endif
85*8462SApril.Chin@Sun.COM #endif
86*8462SApril.Chin@Sun.COM 
87*8462SApril.Chin@Sun.COM #if ULONG_DIG && ULONG_DIG < (DBL_DIG-1)
88*8462SApril.Chin@Sun.COM #define CVT_DBL_INT	long
89*8462SApril.Chin@Sun.COM #define CVT_DBL_MAXINT	LONG_MAX
90*8462SApril.Chin@Sun.COM #else
91*8462SApril.Chin@Sun.COM #if UINT_DIG && UINT_DIG < (DBL_DIG-1)
92*8462SApril.Chin@Sun.COM #define CVT_DBL_INT	int
93*8462SApril.Chin@Sun.COM #define CVT_DBL_MAXINT	INT_MAX
94*8462SApril.Chin@Sun.COM #else
95*8462SApril.Chin@Sun.COM #define CVT_DBL_INT	long
96*8462SApril.Chin@Sun.COM #define CVT_DBL_MAXINT	SF_MAXLONG
97*8462SApril.Chin@Sun.COM #endif
98*8462SApril.Chin@Sun.COM #endif
99*8462SApril.Chin@Sun.COM 
1004887Schin #if __STD_C
101*8462SApril.Chin@Sun.COM char* _sfcvt(Void_t* vp, char* buf, size_t size, int n_digit,
1024887Schin 		int* decpt, int* sign, int* len, int format)
1034887Schin #else
104*8462SApril.Chin@Sun.COM char* _sfcvt(vp,buf,size,n_digit,decpt,sign,len,format)
105*8462SApril.Chin@Sun.COM Void_t*		vp;		/* pointer to value to convert	*/
1064887Schin char*		buf;		/* conversion goes here		*/
1074887Schin size_t		size;		/* size of buf			*/
1084887Schin int		n_digit;	/* number of digits wanted	*/
1094887Schin int*		decpt;		/* to return decimal point	*/
1104887Schin int*		sign;		/* to return sign		*/
1114887Schin int*		len;		/* return string length		*/
1124887Schin int		format;		/* conversion format		*/
1134887Schin #endif
1144887Schin {
1154887Schin 	reg char		*sp;
1164887Schin 	reg long		n, v;
1174887Schin 	reg char		*ep, *b, *endsp;
1184887Schin 	_ast_flt_unsigned_max_t	m;
1194887Schin 
1204887Schin 	static char		lx[] = "0123456789abcdef";
1214887Schin 	static char		ux[] = "0123456789ABCDEF";
1224887Schin 
1234887Schin 	*sign = *decpt = 0;
1244887Schin 
1254887Schin #if !_ast_fltmax_double
1264887Schin 	if(format&SFFMT_LDOUBLE)
127*8462SApril.Chin@Sun.COM 	{	Sfdouble_t	f = *(Sfdouble_t*)vp;
128*8462SApril.Chin@Sun.COM 
129*8462SApril.Chin@Sun.COM 		if(isnanl(f))
130*8462SApril.Chin@Sun.COM 		{
1314887Schin #if _lib_signbit
132*8462SApril.Chin@Sun.COM 			if (signbit(f))
1334887Schin #else
134*8462SApril.Chin@Sun.COM 			if (f < 0)
135*8462SApril.Chin@Sun.COM #endif
136*8462SApril.Chin@Sun.COM 				*sign = 1;
137*8462SApril.Chin@Sun.COM 			return SF_NAN;
138*8462SApril.Chin@Sun.COM 		}
139*8462SApril.Chin@Sun.COM #if _lib_isinf
140*8462SApril.Chin@Sun.COM 		if (n = isinf(f))
141*8462SApril.Chin@Sun.COM 		{
142*8462SApril.Chin@Sun.COM #if _lib_signbit
143*8462SApril.Chin@Sun.COM 			if (signbit(f))
1444887Schin #else
145*8462SApril.Chin@Sun.COM 			if (n < 0 || f < 0)
146*8462SApril.Chin@Sun.COM #endif
147*8462SApril.Chin@Sun.COM 				*sign = 1;
148*8462SApril.Chin@Sun.COM 			return SF_INF;
149*8462SApril.Chin@Sun.COM 		}
150*8462SApril.Chin@Sun.COM #endif
151*8462SApril.Chin@Sun.COM # if _c99_in_the_wild
152*8462SApril.Chin@Sun.COM #  if _lib_signbit
153*8462SApril.Chin@Sun.COM 		if (signbit(f))
154*8462SApril.Chin@Sun.COM #  else
155*8462SApril.Chin@Sun.COM #   if _lib_copysignl
156*8462SApril.Chin@Sun.COM 		if (copysignl(1.0, f) < 0.0)
157*8462SApril.Chin@Sun.COM #   else
158*8462SApril.Chin@Sun.COM #    if _lib_copysign
1594887Schin 		if (copysign(1.0, (double)f) < 0.0)
160*8462SApril.Chin@Sun.COM #    else
1614887Schin 		if (f < 0.0)
162*8462SApril.Chin@Sun.COM #    endif
163*8462SApril.Chin@Sun.COM #   endif
164*8462SApril.Chin@Sun.COM #  endif
1654887Schin 		{	f = -f;
1664887Schin 			*sign = 1;
1674887Schin 		}
168*8462SApril.Chin@Sun.COM #  if _lib_fpclassify
1694887Schin 		switch (fpclassify(f))
1704887Schin 		{
1714887Schin 		case FP_INFINITE:
1724887Schin 			return SF_INF;
1734887Schin 		case FP_NAN:
1744887Schin 			return SF_NAN;
1754887Schin 		case FP_ZERO:
1764887Schin 			return SF_ZERO;
1774887Schin 		}
178*8462SApril.Chin@Sun.COM #  endif
179*8462SApril.Chin@Sun.COM # else
180*8462SApril.Chin@Sun.COM #  if _lib_signbit
181*8462SApril.Chin@Sun.COM 		if (signbit(f))
182*8462SApril.Chin@Sun.COM #  else
183*8462SApril.Chin@Sun.COM 		if (f < 0.0 || f == 0.0 && neg0ld(f))
184*8462SApril.Chin@Sun.COM #  endif
1854887Schin 		{	f = -f;
1864887Schin 			*sign = 1;
1874887Schin 		}
188*8462SApril.Chin@Sun.COM # endif
1894887Schin 		if(f < LDBL_MIN)
1904887Schin 			return SF_ZERO;
1914887Schin 		if(f > LDBL_MAX)
1924887Schin 			return SF_INF;
1934887Schin 
1944887Schin 		if(format & SFFMT_AFORMAT)
1954887Schin 		{	Sfdouble_t	g;
1964887Schin 			int		x;
1974887Schin 			b = sp = buf;
1984887Schin 			ep = (format & SFFMT_UPPER) ? ux : lx;
1994887Schin 			if(n_digit <= 0 || n_digit >= (size - 9))
2004887Schin 				n_digit = size - 9;
2014887Schin 			endsp = sp + n_digit + 1;
2024887Schin 
2034887Schin 			g = frexpl(f, &x);
2044887Schin 			*decpt = x;
2054887Schin 			f = ldexpl(g, 8 * sizeof(m) - 3);
2064887Schin 
2074887Schin 			for (;;)
2084887Schin 			{	m = f;
2094887Schin 				x = 8 * sizeof(m);
2104887Schin 				while ((x -= 4) >= 0)
2114887Schin 				{	*sp++ = ep[(m >> x) & 0xf];
2124887Schin 					if (sp >= endsp)
2134887Schin 					{	ep = sp + 1;
2144887Schin 						goto done;
2154887Schin 					}
2164887Schin 				}
2174887Schin 				f -= m;
2184887Schin 				f = ldexpl(f, 8 * sizeof(m));
2194887Schin 			}
2204887Schin 		}
2214887Schin 
2224887Schin 		n = 0;
223*8462SApril.Chin@Sun.COM 		if(f >= (Sfdouble_t)CVT_LDBL_MAXINT)
2244887Schin 		{	/* scale to a small enough number to fit an int */
2254887Schin 			v = SF_MAXEXP10-1;
2264887Schin 			do
2274887Schin 			{	if(f < _Sfpos10[v])
2284887Schin 					v -= 1;
2294887Schin 				else
2304887Schin 				{
2314887Schin 					f *= _Sfneg10[v];
2324887Schin 					if((n += (1<<v)) >= SF_IDIGITS)
2334887Schin 						return SF_INF;
2344887Schin 				}
235*8462SApril.Chin@Sun.COM 			} while(f >= (Sfdouble_t)CVT_LDBL_MAXINT);
236*8462SApril.Chin@Sun.COM 		}
237*8462SApril.Chin@Sun.COM 		else if(f > 0.0 && f < 0.1)
238*8462SApril.Chin@Sun.COM 		{	/* scale to avoid excessive multiply by 10 below */
239*8462SApril.Chin@Sun.COM 			v = SF_MAXEXP10-1;
240*8462SApril.Chin@Sun.COM 			do
241*8462SApril.Chin@Sun.COM 			{	if(f <= _Sfneg10[v])
242*8462SApril.Chin@Sun.COM 				{	f *= _Sfpos10[v];
243*8462SApril.Chin@Sun.COM 					if((n += (1<<v)) >= SF_IDIGITS)
244*8462SApril.Chin@Sun.COM 						return SF_INF;
245*8462SApril.Chin@Sun.COM 				}
246*8462SApril.Chin@Sun.COM 				else if (--v < 0)
247*8462SApril.Chin@Sun.COM 					break;
248*8462SApril.Chin@Sun.COM 			} while(f < 0.1);
249*8462SApril.Chin@Sun.COM 			n = -n;
2504887Schin 		}
2514887Schin 		*decpt = (int)n;
2524887Schin 
2534887Schin 		b = sp = buf + SF_INTPART;
254*8462SApril.Chin@Sun.COM 		if((v = (CVT_LDBL_INT)f) != 0)
2554887Schin 		{	/* translate the integer part */
2564887Schin 			f -= (Sfdouble_t)v;
2574887Schin 
258*8462SApril.Chin@Sun.COM 			sfucvt(v,sp,n,ep,CVT_LDBL_INT,unsigned CVT_LDBL_INT);
2594887Schin 
2604887Schin 			n = b-sp;
2614887Schin 			if((*decpt += (int)n) >= SF_IDIGITS)
2624887Schin 				return SF_INF;
2634887Schin 			b = sp;
2644887Schin 			sp = buf + SF_INTPART;
2654887Schin 		}
2664887Schin 		else	n = 0;
2674887Schin 
2684887Schin 		/* remaining number of digits to compute; add 1 for later rounding */
2694887Schin 		n = (((format&SFFMT_EFORMAT) || *decpt <= 0) ? 1 : *decpt+1) - n;
2704887Schin 		if(n_digit > 0)
2714887Schin 		{	if(n_digit > LDBL_DIG)
2724887Schin 				n_digit = LDBL_DIG;
2734887Schin 			n += n_digit;
2744887Schin 		}
2754887Schin 
2764887Schin 		if((ep = (sp+n)) > (endsp = buf+(size-2)))
2774887Schin 			ep = endsp;
2784887Schin 		if(sp > ep)
2794887Schin 			sp = ep;
2804887Schin 		else
2814887Schin 		{
2824887Schin 			if((format&SFFMT_EFORMAT) && *decpt == 0 && f > 0.)
2834887Schin 			{	Sfdouble_t	d;
2844887Schin 				while((long)(d = f*10.) == 0)
2854887Schin 				{	f = d;
2864887Schin 					*decpt -= 1;
2874887Schin 				}
2884887Schin 			}
2894887Schin 
2904887Schin 			while(sp < ep)
2914887Schin 			{	/* generate fractional digits */
2924887Schin 				if(f <= 0.)
2934887Schin 				{	/* fill with 0's */
2944887Schin 					do { *sp++ = '0'; } while(sp < ep);
2954887Schin 					goto done;
2964887Schin 				}
2974887Schin 				else if((n = (long)(f *= 10.)) < 10)
2984887Schin 				{	*sp++ = '0' + n;
2994887Schin 					f -= n;
3004887Schin 				}
3014887Schin 				else /* n == 10 */
3024887Schin 				{	do { *sp++ = '9'; } while(sp < ep);
3034887Schin 				}
3044887Schin 			}
3054887Schin 		}
3064887Schin 	} else
3074887Schin #endif
308*8462SApril.Chin@Sun.COM 	{	double	f = *(double*)vp;
3094887Schin 
310*8462SApril.Chin@Sun.COM 		if(isnan(f))
311*8462SApril.Chin@Sun.COM 		{
312*8462SApril.Chin@Sun.COM #if _lib_signbit
313*8462SApril.Chin@Sun.COM 			if (signbit(f))
314*8462SApril.Chin@Sun.COM #else
315*8462SApril.Chin@Sun.COM 			if (f < 0)
316*8462SApril.Chin@Sun.COM #endif
317*8462SApril.Chin@Sun.COM 				*sign = 1;
318*8462SApril.Chin@Sun.COM 			return SF_NAN;
319*8462SApril.Chin@Sun.COM 		}
3204887Schin #if _lib_isinf
3214887Schin 		if (n = isinf(f))
322*8462SApril.Chin@Sun.COM 		{
323*8462SApril.Chin@Sun.COM #if _lib_signbit
324*8462SApril.Chin@Sun.COM 			if (signbit(f))
325*8462SApril.Chin@Sun.COM #else
326*8462SApril.Chin@Sun.COM 			if (n < 0 || f < 0)
327*8462SApril.Chin@Sun.COM #endif
3284887Schin 				*sign = 1;
3294887Schin 			return SF_INF;
3304887Schin 		}
3314887Schin #endif
3324887Schin #if _c99_in_the_wild
333*8462SApril.Chin@Sun.COM # if _lib_signbit
3344887Schin 		if (signbit(f))
335*8462SApril.Chin@Sun.COM # else
336*8462SApril.Chin@Sun.COM #  if _lib_copysign
3374887Schin 		if (copysign(1.0, f) < 0.0)
338*8462SApril.Chin@Sun.COM #  else
3394887Schin 		if (f < 0.0)
340*8462SApril.Chin@Sun.COM #  endif
341*8462SApril.Chin@Sun.COM # endif
3424887Schin 		{	f = -f;
3434887Schin 			*sign = 1;
3444887Schin 		}
345*8462SApril.Chin@Sun.COM # if _lib_fpclassify
3464887Schin 		switch (fpclassify(f))
3474887Schin 		{
3484887Schin 		case FP_INFINITE:
3494887Schin 			return SF_INF;
3504887Schin 		case FP_NAN:
3514887Schin 			return SF_NAN;
3524887Schin 		case FP_ZERO:
3534887Schin 			return SF_ZERO;
3544887Schin 		}
355*8462SApril.Chin@Sun.COM # endif
3564887Schin #else
357*8462SApril.Chin@Sun.COM # if _lib_signbit
358*8462SApril.Chin@Sun.COM 		if (signbit(f))
359*8462SApril.Chin@Sun.COM # else
360*8462SApril.Chin@Sun.COM 		if (f < 0.0 || f == 0.0 && neg0d(f))
361*8462SApril.Chin@Sun.COM # endif
3624887Schin 		{	f = -f;
3634887Schin 			*sign = 1;
3644887Schin 		}
3654887Schin #endif
3664887Schin 		if(f < DBL_MIN)
3674887Schin 			return SF_ZERO;
3684887Schin 		if(f > DBL_MAX)
3694887Schin 			return SF_INF;
3704887Schin 
3714887Schin 		if(format & SFFMT_AFORMAT)
3724887Schin 		{	double	g;
3734887Schin 			int	x;
3744887Schin 			b = sp = buf;
3754887Schin 			ep = (format & SFFMT_UPPER) ? ux : lx;
3764887Schin 			if(n_digit <= 0 || n_digit >= (size - 9))
3774887Schin 				n_digit = size - 9;
3784887Schin 			endsp = sp + n_digit;
3794887Schin 
3804887Schin 			g = frexp(f, &x);
3814887Schin 			*decpt = x;
3824887Schin 			f = ldexp(g, 8 * sizeof(m) - 3);
3834887Schin 
3844887Schin 			for (;;)
3854887Schin 			{	m = f;
3864887Schin 				x = 8 * sizeof(m);
3874887Schin 				while ((x -= 4) >= 0)
3884887Schin 				{	*sp++ = ep[(m >> x) & 0xf];
3894887Schin 					if (sp >= endsp)
3904887Schin 					{	ep = sp + 1;
3914887Schin 						goto done;
3924887Schin 					}
3934887Schin 				}
3944887Schin 				f -= m;
3954887Schin 				f = ldexp(f, 8 * sizeof(m));
3964887Schin 			}
3974887Schin 		}
3984887Schin 		n = 0;
399*8462SApril.Chin@Sun.COM 		if(f >= (double)CVT_DBL_MAXINT)
4004887Schin 		{	/* scale to a small enough number to fit an int */
4014887Schin 			v = SF_MAXEXP10-1;
4024887Schin 			do
4034887Schin 			{	if(f < _Sfpos10[v])
4044887Schin 					v -= 1;
4054887Schin 				else
4064887Schin 				{	f *= _Sfneg10[v];
4074887Schin 					if((n += (1<<v)) >= SF_IDIGITS)
4084887Schin 						return SF_INF;
4094887Schin 				}
410*8462SApril.Chin@Sun.COM 			} while(f >= (double)CVT_DBL_MAXINT);
411*8462SApril.Chin@Sun.COM 		}
412*8462SApril.Chin@Sun.COM 		else if(f > 0.0 && f < 1e-8)
413*8462SApril.Chin@Sun.COM 		{	/* scale to avoid excessive multiply by 10 below */
414*8462SApril.Chin@Sun.COM 			v = SF_MAXEXP10-1;
415*8462SApril.Chin@Sun.COM 			do
416*8462SApril.Chin@Sun.COM 			{	if(f <= _Sfneg10[v])
417*8462SApril.Chin@Sun.COM 				{	f *= _Sfpos10[v];
418*8462SApril.Chin@Sun.COM 					if((n += (1<<v)) >= SF_IDIGITS)
419*8462SApril.Chin@Sun.COM 						return SF_INF;
420*8462SApril.Chin@Sun.COM 				}
421*8462SApril.Chin@Sun.COM 				else if(--v < 0)
422*8462SApril.Chin@Sun.COM 					break;
423*8462SApril.Chin@Sun.COM 			} while(f < 0.1);
424*8462SApril.Chin@Sun.COM 			n = -n;
4254887Schin 		}
4264887Schin 		*decpt = (int)n;
4274887Schin 
4284887Schin 		b = sp = buf + SF_INTPART;
429*8462SApril.Chin@Sun.COM 		if((v = (CVT_DBL_INT)f) != 0)
4304887Schin 		{	/* translate the integer part */
4314887Schin 			f -= (double)v;
4324887Schin 
433*8462SApril.Chin@Sun.COM 			sfucvt(v,sp,n,ep,CVT_DBL_INT,unsigned CVT_DBL_INT);
4344887Schin 
4354887Schin 			n = b-sp;
4364887Schin 			if((*decpt += (int)n) >= SF_IDIGITS)
4374887Schin 				return SF_INF;
4384887Schin 			b = sp;
4394887Schin 			sp = buf + SF_INTPART;
4404887Schin 		}
4414887Schin 		else	n = 0;
4424887Schin 
4434887Schin 		/* remaining number of digits to compute; add 1 for later rounding */
4444887Schin 		n = (((format&SFFMT_EFORMAT) || *decpt <= 0) ? 1 : *decpt+1) - n;
4454887Schin 		if(n_digit > 0)
4464887Schin 		{	if(n_digit > DBL_DIG)
4474887Schin 				n_digit = DBL_DIG;
4484887Schin 			n += n_digit;
4494887Schin 		}
4504887Schin 
4514887Schin 		if((ep = (sp+n)) > (endsp = buf+(size-2)))
4524887Schin 			ep = endsp;
4534887Schin 		if(sp > ep)
4544887Schin 			sp = ep;
4554887Schin 		else
4564887Schin 		{
4574887Schin 			if((format&SFFMT_EFORMAT) && *decpt == 0 && f > 0.)
4584887Schin 			{	reg double	d;
4594887Schin 				while((long)(d = f*10.) == 0)
4604887Schin 				{	f = d;
4614887Schin 					*decpt -= 1;
4624887Schin 				}
4634887Schin 			}
4644887Schin 
4654887Schin 			while(sp < ep)
4664887Schin 			{	/* generate fractional digits */
4674887Schin 				if(f <= 0.)
4684887Schin 				{	/* fill with 0's */
4694887Schin 					do { *sp++ = '0'; } while(sp < ep);
4704887Schin 					goto done;
4714887Schin 				}
4724887Schin 				else if((n = (long)(f *= 10.)) < 10)
4734887Schin 				{	*sp++ = (char)('0' + n);
4744887Schin 					f -= n;
4754887Schin 				}
4764887Schin 				else /* n == 10 */
4774887Schin 				{	do { *sp++ = '9'; } while(sp < ep);
478*8462SApril.Chin@Sun.COM 					break;
4794887Schin 				}
4804887Schin 			}
4814887Schin 		}
4824887Schin 	}
4834887Schin 
4844887Schin 	if(ep <= b)
4854887Schin 		ep = b+1;
4864887Schin 	else if(ep < endsp)
4874887Schin 	{	/* round the last digit */
4884887Schin 		*--sp += 5;
4894887Schin 		while(*sp > '9')
4904887Schin 		{	*sp = '0';
4914887Schin 			if(sp > b)
4924887Schin 				*--sp += 1;
4934887Schin 			else
4944887Schin 			{	/* next power of 10 */
4954887Schin 				*sp = '1';
4964887Schin 				*decpt += 1;
4974887Schin 				if(!(format&SFFMT_EFORMAT))
4984887Schin 				{	/* add one more 0 for %f precision */
4994887Schin 					ep[-1] = '0';
5004887Schin 					ep += 1;
5014887Schin 				}
5024887Schin 			}
5034887Schin 		}
5044887Schin 	}
5054887Schin 
5064887Schin done:
5074887Schin 	*--ep = '\0';
5084887Schin 	if(len)
5094887Schin 		*len = ep-b;
5104887Schin 	return b;
5114887Schin }
512