xref: /onnv-gate/usr/src/lib/libast/common/sfio/sfcvt.c (revision 12068:08a39a083754)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1985-2010 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
78462SApril.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 ***********************************************************************/
228462SApril.Chin@Sun.COM #if __STDC__
238462SApril.Chin@Sun.COM #include	"FEATURE/isoc99"
248462SApril.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 
548462SApril.Chin@Sun.COM #if ! _lib_signbit && defined(signbit)
558462SApril.Chin@Sun.COM #undef	_lib_signbit
568462SApril.Chin@Sun.COM #define _lib_signbit	1
578462SApril.Chin@Sun.COM #endif
588462SApril.Chin@Sun.COM 
598462SApril.Chin@Sun.COM #if ! _lib_signbit
608462SApril.Chin@Sun.COM #if ! _ast_fltmax_double
neg0ld(Sfdouble_t f)618462SApril.Chin@Sun.COM static int neg0ld(Sfdouble_t f)
628462SApril.Chin@Sun.COM {
638462SApril.Chin@Sun.COM 	Sfdouble_t	z = -0.0;
648462SApril.Chin@Sun.COM 	return !memcmp(&f, &z, sizeof(f));
658462SApril.Chin@Sun.COM }
668462SApril.Chin@Sun.COM #endif
neg0d(double f)678462SApril.Chin@Sun.COM static int neg0d(double f)
688462SApril.Chin@Sun.COM {
698462SApril.Chin@Sun.COM 	double		z = -0.0;
708462SApril.Chin@Sun.COM 	return !memcmp(&f, &z, sizeof(f));
718462SApril.Chin@Sun.COM }
728462SApril.Chin@Sun.COM #endif
738462SApril.Chin@Sun.COM 
748462SApril.Chin@Sun.COM #if ULONG_DIG && ULONG_DIG < (DBL_DIG-1)
758462SApril.Chin@Sun.COM #define CVT_LDBL_INT	long
768462SApril.Chin@Sun.COM #define CVT_LDBL_MAXINT	LONG_MAX
778462SApril.Chin@Sun.COM #else
788462SApril.Chin@Sun.COM #if UINT_DIG && UINT_DIG < (DBL_DIG-1)
798462SApril.Chin@Sun.COM #define CVT_LDBL_INT	int
808462SApril.Chin@Sun.COM #define CVT_LDBL_MAXINT	INT_MAX
818462SApril.Chin@Sun.COM #else
828462SApril.Chin@Sun.COM #define CVT_LDBL_INT	long
838462SApril.Chin@Sun.COM #define CVT_LDBL_MAXINT	SF_MAXLONG
848462SApril.Chin@Sun.COM #endif
858462SApril.Chin@Sun.COM #endif
868462SApril.Chin@Sun.COM 
878462SApril.Chin@Sun.COM #if ULONG_DIG && ULONG_DIG < (DBL_DIG-1)
888462SApril.Chin@Sun.COM #define CVT_DBL_INT	long
898462SApril.Chin@Sun.COM #define CVT_DBL_MAXINT	LONG_MAX
908462SApril.Chin@Sun.COM #else
918462SApril.Chin@Sun.COM #if UINT_DIG && UINT_DIG < (DBL_DIG-1)
928462SApril.Chin@Sun.COM #define CVT_DBL_INT	int
938462SApril.Chin@Sun.COM #define CVT_DBL_MAXINT	INT_MAX
948462SApril.Chin@Sun.COM #else
958462SApril.Chin@Sun.COM #define CVT_DBL_INT	long
968462SApril.Chin@Sun.COM #define CVT_DBL_MAXINT	SF_MAXLONG
978462SApril.Chin@Sun.COM #endif
988462SApril.Chin@Sun.COM #endif
998462SApril.Chin@Sun.COM 
1004887Schin #if __STD_C
_sfcvt(Void_t * vp,char * buf,size_t size,int n_digit,int * decpt,int * sign,int * len,int format)1018462SApril.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
1048462SApril.Chin@Sun.COM char* _sfcvt(vp,buf,size,n_digit,decpt,sign,len,format)
1058462SApril.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;
11710898Sroland.mainz@nrubsig.org 	reg char		*ep, *b, *endsp, *t;
11810898Sroland.mainz@nrubsig.org 	int			x;
1194887Schin 	_ast_flt_unsigned_max_t	m;
1204887Schin 
1214887Schin 	static char		lx[] = "0123456789abcdef";
1224887Schin 	static char		ux[] = "0123456789ABCDEF";
1234887Schin 
1244887Schin 	*sign = *decpt = 0;
1254887Schin 
1264887Schin #if !_ast_fltmax_double
1274887Schin 	if(format&SFFMT_LDOUBLE)
1288462SApril.Chin@Sun.COM 	{	Sfdouble_t	f = *(Sfdouble_t*)vp;
1298462SApril.Chin@Sun.COM 
1308462SApril.Chin@Sun.COM 		if(isnanl(f))
1318462SApril.Chin@Sun.COM 		{
1324887Schin #if _lib_signbit
1338462SApril.Chin@Sun.COM 			if (signbit(f))
1344887Schin #else
1358462SApril.Chin@Sun.COM 			if (f < 0)
1368462SApril.Chin@Sun.COM #endif
1378462SApril.Chin@Sun.COM 				*sign = 1;
1388462SApril.Chin@Sun.COM 			return SF_NAN;
1398462SApril.Chin@Sun.COM 		}
1408462SApril.Chin@Sun.COM #if _lib_isinf
1418462SApril.Chin@Sun.COM 		if (n = isinf(f))
1428462SApril.Chin@Sun.COM 		{
1438462SApril.Chin@Sun.COM #if _lib_signbit
1448462SApril.Chin@Sun.COM 			if (signbit(f))
1454887Schin #else
1468462SApril.Chin@Sun.COM 			if (n < 0 || f < 0)
1478462SApril.Chin@Sun.COM #endif
1488462SApril.Chin@Sun.COM 				*sign = 1;
1498462SApril.Chin@Sun.COM 			return SF_INF;
1508462SApril.Chin@Sun.COM 		}
1518462SApril.Chin@Sun.COM #endif
1528462SApril.Chin@Sun.COM # if _c99_in_the_wild
1538462SApril.Chin@Sun.COM #  if _lib_signbit
1548462SApril.Chin@Sun.COM 		if (signbit(f))
1558462SApril.Chin@Sun.COM #  else
1568462SApril.Chin@Sun.COM #   if _lib_copysignl
1578462SApril.Chin@Sun.COM 		if (copysignl(1.0, f) < 0.0)
1588462SApril.Chin@Sun.COM #   else
1598462SApril.Chin@Sun.COM #    if _lib_copysign
1604887Schin 		if (copysign(1.0, (double)f) < 0.0)
1618462SApril.Chin@Sun.COM #    else
1624887Schin 		if (f < 0.0)
1638462SApril.Chin@Sun.COM #    endif
1648462SApril.Chin@Sun.COM #   endif
1658462SApril.Chin@Sun.COM #  endif
1664887Schin 		{	f = -f;
1674887Schin 			*sign = 1;
1684887Schin 		}
1698462SApril.Chin@Sun.COM #  if _lib_fpclassify
1704887Schin 		switch (fpclassify(f))
1714887Schin 		{
1724887Schin 		case FP_INFINITE:
1734887Schin 			return SF_INF;
1744887Schin 		case FP_NAN:
1754887Schin 			return SF_NAN;
1764887Schin 		case FP_ZERO:
1774887Schin 			return SF_ZERO;
1784887Schin 		}
1798462SApril.Chin@Sun.COM #  endif
1808462SApril.Chin@Sun.COM # else
1818462SApril.Chin@Sun.COM #  if _lib_signbit
1828462SApril.Chin@Sun.COM 		if (signbit(f))
1838462SApril.Chin@Sun.COM #  else
1848462SApril.Chin@Sun.COM 		if (f < 0.0 || f == 0.0 && neg0ld(f))
1858462SApril.Chin@Sun.COM #  endif
1864887Schin 		{	f = -f;
1874887Schin 			*sign = 1;
1884887Schin 		}
1898462SApril.Chin@Sun.COM # endif
1904887Schin 		if(f < LDBL_MIN)
1914887Schin 			return SF_ZERO;
1924887Schin 		if(f > LDBL_MAX)
1934887Schin 			return SF_INF;
1944887Schin 
1954887Schin 		if(format & SFFMT_AFORMAT)
1964887Schin 		{	Sfdouble_t	g;
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)
21310898Sroland.mainz@nrubsig.org 						goto around;
2144887Schin 				}
2154887Schin 				f -= m;
2164887Schin 				f = ldexpl(f, 8 * sizeof(m));
2174887Schin 			}
2184887Schin 		}
2194887Schin 
2204887Schin 		n = 0;
2218462SApril.Chin@Sun.COM 		if(f >= (Sfdouble_t)CVT_LDBL_MAXINT)
2224887Schin 		{	/* scale to a small enough number to fit an int */
2234887Schin 			v = SF_MAXEXP10-1;
2244887Schin 			do
2254887Schin 			{	if(f < _Sfpos10[v])
2264887Schin 					v -= 1;
2274887Schin 				else
2284887Schin 				{
2294887Schin 					f *= _Sfneg10[v];
2304887Schin 					if((n += (1<<v)) >= SF_IDIGITS)
2314887Schin 						return SF_INF;
2324887Schin 				}
2338462SApril.Chin@Sun.COM 			} while(f >= (Sfdouble_t)CVT_LDBL_MAXINT);
2348462SApril.Chin@Sun.COM 		}
2358462SApril.Chin@Sun.COM 		else if(f > 0.0 && f < 0.1)
2368462SApril.Chin@Sun.COM 		{	/* scale to avoid excessive multiply by 10 below */
2378462SApril.Chin@Sun.COM 			v = SF_MAXEXP10-1;
2388462SApril.Chin@Sun.COM 			do
2398462SApril.Chin@Sun.COM 			{	if(f <= _Sfneg10[v])
2408462SApril.Chin@Sun.COM 				{	f *= _Sfpos10[v];
2418462SApril.Chin@Sun.COM 					if((n += (1<<v)) >= SF_IDIGITS)
2428462SApril.Chin@Sun.COM 						return SF_INF;
2438462SApril.Chin@Sun.COM 				}
2448462SApril.Chin@Sun.COM 				else if (--v < 0)
2458462SApril.Chin@Sun.COM 					break;
2468462SApril.Chin@Sun.COM 			} while(f < 0.1);
2478462SApril.Chin@Sun.COM 			n = -n;
2484887Schin 		}
2494887Schin 		*decpt = (int)n;
2504887Schin 
2514887Schin 		b = sp = buf + SF_INTPART;
2528462SApril.Chin@Sun.COM 		if((v = (CVT_LDBL_INT)f) != 0)
2534887Schin 		{	/* translate the integer part */
2544887Schin 			f -= (Sfdouble_t)v;
2554887Schin 
2568462SApril.Chin@Sun.COM 			sfucvt(v,sp,n,ep,CVT_LDBL_INT,unsigned CVT_LDBL_INT);
2574887Schin 
2584887Schin 			n = b-sp;
2594887Schin 			if((*decpt += (int)n) >= SF_IDIGITS)
2604887Schin 				return SF_INF;
2614887Schin 			b = sp;
2624887Schin 			sp = buf + SF_INTPART;
2634887Schin 		}
2644887Schin 		else	n = 0;
2654887Schin 
2664887Schin 		/* remaining number of digits to compute; add 1 for later rounding */
2674887Schin 		n = (((format&SFFMT_EFORMAT) || *decpt <= 0) ? 1 : *decpt+1) - n;
2684887Schin 		if(n_digit > 0)
2694887Schin 		{	if(n_digit > LDBL_DIG)
2704887Schin 				n_digit = LDBL_DIG;
2714887Schin 			n += n_digit;
2724887Schin 		}
2734887Schin 
2744887Schin 		if((ep = (sp+n)) > (endsp = buf+(size-2)))
2754887Schin 			ep = endsp;
2764887Schin 		if(sp > ep)
2774887Schin 			sp = ep;
2784887Schin 		else
2794887Schin 		{
2804887Schin 			if((format&SFFMT_EFORMAT) && *decpt == 0 && f > 0.)
2814887Schin 			{	Sfdouble_t	d;
2824887Schin 				while((long)(d = f*10.) == 0)
2834887Schin 				{	f = d;
2844887Schin 					*decpt -= 1;
2854887Schin 				}
2864887Schin 			}
2874887Schin 
2884887Schin 			while(sp < ep)
2894887Schin 			{	/* generate fractional digits */
2904887Schin 				if(f <= 0.)
2914887Schin 				{	/* fill with 0's */
2924887Schin 					do { *sp++ = '0'; } while(sp < ep);
2934887Schin 					goto done;
2944887Schin 				}
2954887Schin 				else if((n = (long)(f *= 10.)) < 10)
2964887Schin 				{	*sp++ = '0' + n;
2974887Schin 					f -= n;
2984887Schin 				}
2994887Schin 				else /* n == 10 */
3004887Schin 				{	do { *sp++ = '9'; } while(sp < ep);
3014887Schin 				}
3024887Schin 			}
3034887Schin 		}
3044887Schin 	} else
3054887Schin #endif
3068462SApril.Chin@Sun.COM 	{	double	f = *(double*)vp;
3074887Schin 
3088462SApril.Chin@Sun.COM 		if(isnan(f))
3098462SApril.Chin@Sun.COM 		{
3108462SApril.Chin@Sun.COM #if _lib_signbit
3118462SApril.Chin@Sun.COM 			if (signbit(f))
3128462SApril.Chin@Sun.COM #else
3138462SApril.Chin@Sun.COM 			if (f < 0)
3148462SApril.Chin@Sun.COM #endif
3158462SApril.Chin@Sun.COM 				*sign = 1;
3168462SApril.Chin@Sun.COM 			return SF_NAN;
3178462SApril.Chin@Sun.COM 		}
3184887Schin #if _lib_isinf
3194887Schin 		if (n = isinf(f))
3208462SApril.Chin@Sun.COM 		{
3218462SApril.Chin@Sun.COM #if _lib_signbit
3228462SApril.Chin@Sun.COM 			if (signbit(f))
3238462SApril.Chin@Sun.COM #else
3248462SApril.Chin@Sun.COM 			if (n < 0 || f < 0)
3258462SApril.Chin@Sun.COM #endif
3264887Schin 				*sign = 1;
3274887Schin 			return SF_INF;
3284887Schin 		}
3294887Schin #endif
3304887Schin #if _c99_in_the_wild
3318462SApril.Chin@Sun.COM # if _lib_signbit
3324887Schin 		if (signbit(f))
3338462SApril.Chin@Sun.COM # else
3348462SApril.Chin@Sun.COM #  if _lib_copysign
3354887Schin 		if (copysign(1.0, f) < 0.0)
3368462SApril.Chin@Sun.COM #  else
3374887Schin 		if (f < 0.0)
3388462SApril.Chin@Sun.COM #  endif
3398462SApril.Chin@Sun.COM # endif
3404887Schin 		{	f = -f;
3414887Schin 			*sign = 1;
3424887Schin 		}
3438462SApril.Chin@Sun.COM # if _lib_fpclassify
3444887Schin 		switch (fpclassify(f))
3454887Schin 		{
3464887Schin 		case FP_INFINITE:
3474887Schin 			return SF_INF;
3484887Schin 		case FP_NAN:
3494887Schin 			return SF_NAN;
3504887Schin 		case FP_ZERO:
3514887Schin 			return SF_ZERO;
3524887Schin 		}
3538462SApril.Chin@Sun.COM # endif
3544887Schin #else
3558462SApril.Chin@Sun.COM # if _lib_signbit
3568462SApril.Chin@Sun.COM 		if (signbit(f))
3578462SApril.Chin@Sun.COM # else
3588462SApril.Chin@Sun.COM 		if (f < 0.0 || f == 0.0 && neg0d(f))
3598462SApril.Chin@Sun.COM # endif
3604887Schin 		{	f = -f;
3614887Schin 			*sign = 1;
3624887Schin 		}
3634887Schin #endif
3644887Schin 		if(f < DBL_MIN)
3654887Schin 			return SF_ZERO;
3664887Schin 		if(f > DBL_MAX)
3674887Schin 			return SF_INF;
3684887Schin 
3694887Schin 		if(format & SFFMT_AFORMAT)
37010898Sroland.mainz@nrubsig.org 		{	double		g;
3714887Schin 			b = sp = buf;
3724887Schin 			ep = (format & SFFMT_UPPER) ? ux : lx;
3734887Schin 			if(n_digit <= 0 || n_digit >= (size - 9))
3744887Schin 				n_digit = size - 9;
37510898Sroland.mainz@nrubsig.org 			endsp = sp + n_digit + 1;
3764887Schin 
3774887Schin 			g = frexp(f, &x);
3784887Schin 			*decpt = x;
3794887Schin 			f = ldexp(g, 8 * sizeof(m) - 3);
3804887Schin 
3814887Schin 			for (;;)
3824887Schin 			{	m = f;
3834887Schin 				x = 8 * sizeof(m);
3844887Schin 				while ((x -= 4) >= 0)
3854887Schin 				{	*sp++ = ep[(m >> x) & 0xf];
3864887Schin 					if (sp >= endsp)
38710898Sroland.mainz@nrubsig.org 						goto around;
3884887Schin 				}
3894887Schin 				f -= m;
3904887Schin 				f = ldexp(f, 8 * sizeof(m));
3914887Schin 			}
3924887Schin 		}
3934887Schin 		n = 0;
3948462SApril.Chin@Sun.COM 		if(f >= (double)CVT_DBL_MAXINT)
3954887Schin 		{	/* scale to a small enough number to fit an int */
3964887Schin 			v = SF_MAXEXP10-1;
3974887Schin 			do
3984887Schin 			{	if(f < _Sfpos10[v])
3994887Schin 					v -= 1;
4004887Schin 				else
4014887Schin 				{	f *= _Sfneg10[v];
4024887Schin 					if((n += (1<<v)) >= SF_IDIGITS)
4034887Schin 						return SF_INF;
4044887Schin 				}
4058462SApril.Chin@Sun.COM 			} while(f >= (double)CVT_DBL_MAXINT);
4068462SApril.Chin@Sun.COM 		}
4078462SApril.Chin@Sun.COM 		else if(f > 0.0 && f < 1e-8)
4088462SApril.Chin@Sun.COM 		{	/* scale to avoid excessive multiply by 10 below */
4098462SApril.Chin@Sun.COM 			v = SF_MAXEXP10-1;
4108462SApril.Chin@Sun.COM 			do
4118462SApril.Chin@Sun.COM 			{	if(f <= _Sfneg10[v])
4128462SApril.Chin@Sun.COM 				{	f *= _Sfpos10[v];
4138462SApril.Chin@Sun.COM 					if((n += (1<<v)) >= SF_IDIGITS)
4148462SApril.Chin@Sun.COM 						return SF_INF;
4158462SApril.Chin@Sun.COM 				}
4168462SApril.Chin@Sun.COM 				else if(--v < 0)
4178462SApril.Chin@Sun.COM 					break;
4188462SApril.Chin@Sun.COM 			} while(f < 0.1);
4198462SApril.Chin@Sun.COM 			n = -n;
4204887Schin 		}
4214887Schin 		*decpt = (int)n;
4224887Schin 
4234887Schin 		b = sp = buf + SF_INTPART;
4248462SApril.Chin@Sun.COM 		if((v = (CVT_DBL_INT)f) != 0)
4254887Schin 		{	/* translate the integer part */
4264887Schin 			f -= (double)v;
4274887Schin 
4288462SApril.Chin@Sun.COM 			sfucvt(v,sp,n,ep,CVT_DBL_INT,unsigned CVT_DBL_INT);
4294887Schin 
4304887Schin 			n = b-sp;
4314887Schin 			if((*decpt += (int)n) >= SF_IDIGITS)
4324887Schin 				return SF_INF;
4334887Schin 			b = sp;
4344887Schin 			sp = buf + SF_INTPART;
4354887Schin 		}
4364887Schin 		else	n = 0;
4374887Schin 
4384887Schin 		/* remaining number of digits to compute; add 1 for later rounding */
4394887Schin 		n = (((format&SFFMT_EFORMAT) || *decpt <= 0) ? 1 : *decpt+1) - n;
4404887Schin 		if(n_digit > 0)
4414887Schin 		{	if(n_digit > DBL_DIG)
4424887Schin 				n_digit = DBL_DIG;
4434887Schin 			n += n_digit;
4444887Schin 		}
4454887Schin 
4464887Schin 		if((ep = (sp+n)) > (endsp = buf+(size-2)))
4474887Schin 			ep = endsp;
4484887Schin 		if(sp > ep)
4494887Schin 			sp = ep;
4504887Schin 		else
4514887Schin 		{
4524887Schin 			if((format&SFFMT_EFORMAT) && *decpt == 0 && f > 0.)
4534887Schin 			{	reg double	d;
4544887Schin 				while((long)(d = f*10.) == 0)
4554887Schin 				{	f = d;
4564887Schin 					*decpt -= 1;
4574887Schin 				}
4584887Schin 			}
4594887Schin 
4604887Schin 			while(sp < ep)
4614887Schin 			{	/* generate fractional digits */
4624887Schin 				if(f <= 0.)
4634887Schin 				{	/* fill with 0's */
4644887Schin 					do { *sp++ = '0'; } while(sp < ep);
4654887Schin 					goto done;
4664887Schin 				}
4674887Schin 				else if((n = (long)(f *= 10.)) < 10)
4684887Schin 				{	*sp++ = (char)('0' + n);
4694887Schin 					f -= n;
4704887Schin 				}
4714887Schin 				else /* n == 10 */
4724887Schin 				{	do { *sp++ = '9'; } while(sp < ep);
4738462SApril.Chin@Sun.COM 					break;
4744887Schin 				}
4754887Schin 			}
4764887Schin 		}
4774887Schin 	}
4784887Schin 
4794887Schin 	if(ep <= b)
4804887Schin 		ep = b+1;
4814887Schin 	else if(ep < endsp)
4824887Schin 	{	/* round the last digit */
4834887Schin 		*--sp += 5;
4844887Schin 		while(*sp > '9')
4854887Schin 		{	*sp = '0';
4864887Schin 			if(sp > b)
4874887Schin 				*--sp += 1;
4884887Schin 			else
4894887Schin 			{	/* next power of 10 */
4904887Schin 				*sp = '1';
4914887Schin 				*decpt += 1;
4924887Schin 				if(!(format&SFFMT_EFORMAT))
4934887Schin 				{	/* add one more 0 for %f precision */
4944887Schin 					ep[-1] = '0';
4954887Schin 					ep += 1;
4964887Schin 				}
4974887Schin 			}
4984887Schin 		}
4994887Schin 	}
5004887Schin 
50110898Sroland.mainz@nrubsig.org  done:
5024887Schin 	*--ep = '\0';
5034887Schin 	if(len)
5044887Schin 		*len = ep-b;
5054887Schin 	return b;
50610898Sroland.mainz@nrubsig.org  around:
50710898Sroland.mainz@nrubsig.org 	if (((m >> x) & 0xf) >= 8)
50810898Sroland.mainz@nrubsig.org 	{	t = sp - 1;
50910898Sroland.mainz@nrubsig.org 		for (;;)
51010898Sroland.mainz@nrubsig.org 		{	if (--t <= b)
51110898Sroland.mainz@nrubsig.org 			{	(*decpt)++;
51210898Sroland.mainz@nrubsig.org 				break;
51310898Sroland.mainz@nrubsig.org 			}
51410898Sroland.mainz@nrubsig.org 			switch (*t)
51510898Sroland.mainz@nrubsig.org 			{
51610898Sroland.mainz@nrubsig.org 			case 'f':
51710898Sroland.mainz@nrubsig.org 			case 'F':
51810898Sroland.mainz@nrubsig.org 				*t = '0';
51910898Sroland.mainz@nrubsig.org 				continue;
52010898Sroland.mainz@nrubsig.org 			case '9':
52110898Sroland.mainz@nrubsig.org 				*t = ep[10];
52210898Sroland.mainz@nrubsig.org 				break;
52310898Sroland.mainz@nrubsig.org 			default:
52410898Sroland.mainz@nrubsig.org 				(*t)++;
52510898Sroland.mainz@nrubsig.org 				break;
52610898Sroland.mainz@nrubsig.org 			}
52710898Sroland.mainz@nrubsig.org 			break;
52810898Sroland.mainz@nrubsig.org 		}
52910898Sroland.mainz@nrubsig.org 	}
53010898Sroland.mainz@nrubsig.org 	ep = sp + 1;
53110898Sroland.mainz@nrubsig.org 	goto done;
5324887Schin }
533