1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
4*3e14f97fSRoger A. Faulkner * Copyright (c) 1985-2010 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6da2e3ebdSchin * Common Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * A copy of the License is available at *
10da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt *
11da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
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__
237c2fbfb3SApril Chin #include "FEATURE/isoc99"
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";
35da2e3ebdSchin #define SF_INF ((_Sfi = 3), strncpy(buf, (format & SFFMT_UPPER) ? uc_inf : lc_inf, size))
36da2e3ebdSchin #define SF_NAN ((_Sfi = 3), strncpy(buf, (format & SFFMT_UPPER) ? uc_nan : lc_nan, size))
37da2e3ebdSchin #define SF_ZERO ((_Sfi = 1), strncpy(buf, Zero, size))
38da2e3ebdSchin #define SF_INTPART (SF_IDIGITS/2)
39da2e3ebdSchin
40da2e3ebdSchin #if ! _lib_isnan
41da2e3ebdSchin #if _lib_fpclassify
42da2e3ebdSchin #define isnan(n) (fpclassify(n)==FP_NAN)
43da2e3ebdSchin #define isnanl(n) (fpclassify(n)==FP_NAN)
44da2e3ebdSchin #else
45da2e3ebdSchin #define isnan(n) (memcmp((void*)&n,(void*)&_Sfdnan,sizeof(n))==0)
46da2e3ebdSchin #define isnanl(n) (memcmp((void*)&n,(void*)&_Sflnan,sizeof(n))==0)
47da2e3ebdSchin #endif
48da2e3ebdSchin #else
49da2e3ebdSchin #if ! _lib_isnanl
50da2e3ebdSchin #define isnanl(n) isnan(n)
51da2e3ebdSchin #endif
52da2e3ebdSchin #endif
53da2e3ebdSchin
547c2fbfb3SApril Chin #if ! _lib_signbit && defined(signbit)
557c2fbfb3SApril Chin #undef _lib_signbit
567c2fbfb3SApril Chin #define _lib_signbit 1
577c2fbfb3SApril Chin #endif
587c2fbfb3SApril Chin
597c2fbfb3SApril Chin #if ! _lib_signbit
607c2fbfb3SApril Chin #if ! _ast_fltmax_double
neg0ld(Sfdouble_t f)617c2fbfb3SApril Chin static int neg0ld(Sfdouble_t f)
627c2fbfb3SApril Chin {
637c2fbfb3SApril Chin Sfdouble_t z = -0.0;
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 {
697c2fbfb3SApril Chin double z = -0.0;
707c2fbfb3SApril Chin return !memcmp(&f, &z, sizeof(f));
717c2fbfb3SApril Chin }
727c2fbfb3SApril Chin #endif
737c2fbfb3SApril Chin
747c2fbfb3SApril Chin #if ULONG_DIG && ULONG_DIG < (DBL_DIG-1)
757c2fbfb3SApril Chin #define CVT_LDBL_INT long
767c2fbfb3SApril Chin #define CVT_LDBL_MAXINT LONG_MAX
777c2fbfb3SApril Chin #else
787c2fbfb3SApril Chin #if UINT_DIG && UINT_DIG < (DBL_DIG-1)
797c2fbfb3SApril Chin #define CVT_LDBL_INT int
807c2fbfb3SApril Chin #define CVT_LDBL_MAXINT INT_MAX
817c2fbfb3SApril Chin #else
827c2fbfb3SApril Chin #define CVT_LDBL_INT long
837c2fbfb3SApril Chin #define CVT_LDBL_MAXINT SF_MAXLONG
847c2fbfb3SApril Chin #endif
857c2fbfb3SApril Chin #endif
867c2fbfb3SApril Chin
877c2fbfb3SApril Chin #if ULONG_DIG && ULONG_DIG < (DBL_DIG-1)
887c2fbfb3SApril Chin #define CVT_DBL_INT long
897c2fbfb3SApril Chin #define CVT_DBL_MAXINT LONG_MAX
907c2fbfb3SApril Chin #else
917c2fbfb3SApril Chin #if UINT_DIG && UINT_DIG < (DBL_DIG-1)
927c2fbfb3SApril Chin #define CVT_DBL_INT int
937c2fbfb3SApril Chin #define CVT_DBL_MAXINT INT_MAX
947c2fbfb3SApril Chin #else
957c2fbfb3SApril Chin #define CVT_DBL_INT long
967c2fbfb3SApril Chin #define CVT_DBL_MAXINT SF_MAXLONG
977c2fbfb3SApril Chin #endif
987c2fbfb3SApril Chin #endif
997c2fbfb3SApril Chin
100da2e3ebdSchin #if __STD_C
_sfcvt(Void_t * vp,char * buf,size_t size,int n_digit,int * decpt,int * sign,int * len,int format)1017c2fbfb3SApril Chin char* _sfcvt(Void_t* vp, char* buf, size_t size, int n_digit,
102da2e3ebdSchin int* decpt, int* sign, int* len, int format)
103da2e3ebdSchin #else
1047c2fbfb3SApril Chin char* _sfcvt(vp,buf,size,n_digit,decpt,sign,len,format)
1057c2fbfb3SApril Chin Void_t* vp; /* pointer to value to convert */
106da2e3ebdSchin char* buf; /* conversion goes here */
107da2e3ebdSchin size_t size; /* size of buf */
108da2e3ebdSchin int n_digit; /* number of digits wanted */
109da2e3ebdSchin int* decpt; /* to return decimal point */
110da2e3ebdSchin int* sign; /* to return sign */
111da2e3ebdSchin int* len; /* return string length */
112da2e3ebdSchin int format; /* conversion format */
113da2e3ebdSchin #endif
114da2e3ebdSchin {
115da2e3ebdSchin reg char *sp;
116da2e3ebdSchin reg long n, v;
11734f9b3eeSRoland Mainz reg char *ep, *b, *endsp, *t;
11834f9b3eeSRoland Mainz int x;
119da2e3ebdSchin _ast_flt_unsigned_max_t m;
120da2e3ebdSchin
121da2e3ebdSchin static char lx[] = "0123456789abcdef";
122da2e3ebdSchin static char ux[] = "0123456789ABCDEF";
123da2e3ebdSchin
124da2e3ebdSchin *sign = *decpt = 0;
125da2e3ebdSchin
1267c2fbfb3SApril Chin #if !_ast_fltmax_double
1277c2fbfb3SApril Chin if(format&SFFMT_LDOUBLE)
1287c2fbfb3SApril Chin { Sfdouble_t f = *(Sfdouble_t*)vp;
1297c2fbfb3SApril Chin
1307c2fbfb3SApril Chin if(isnanl(f))
1317c2fbfb3SApril Chin {
1327c2fbfb3SApril Chin #if _lib_signbit
1337c2fbfb3SApril Chin if (signbit(f))
1347c2fbfb3SApril Chin #else
1357c2fbfb3SApril Chin if (f < 0)
1367c2fbfb3SApril Chin #endif
1377c2fbfb3SApril Chin *sign = 1;
138da2e3ebdSchin return SF_NAN;
1397c2fbfb3SApril Chin }
140da2e3ebdSchin #if _lib_isinf
1417c2fbfb3SApril Chin if (n = isinf(f))
1427c2fbfb3SApril Chin {
1437c2fbfb3SApril Chin #if _lib_signbit
1447c2fbfb3SApril Chin if (signbit(f))
1457c2fbfb3SApril Chin #else
1467c2fbfb3SApril Chin if (n < 0 || f < 0)
1477c2fbfb3SApril Chin #endif
148da2e3ebdSchin *sign = 1;
149da2e3ebdSchin return SF_INF;
150da2e3ebdSchin }
151da2e3ebdSchin #endif
152da2e3ebdSchin # if _c99_in_the_wild
153da2e3ebdSchin # if _lib_signbit
154da2e3ebdSchin if (signbit(f))
155da2e3ebdSchin # else
156da2e3ebdSchin # if _lib_copysignl
157da2e3ebdSchin if (copysignl(1.0, f) < 0.0)
158da2e3ebdSchin # else
159da2e3ebdSchin # if _lib_copysign
160da2e3ebdSchin if (copysign(1.0, (double)f) < 0.0)
161da2e3ebdSchin # else
162da2e3ebdSchin if (f < 0.0)
163da2e3ebdSchin # endif
164da2e3ebdSchin # endif
165da2e3ebdSchin # endif
166da2e3ebdSchin { f = -f;
167da2e3ebdSchin *sign = 1;
168da2e3ebdSchin }
169da2e3ebdSchin # if _lib_fpclassify
170da2e3ebdSchin switch (fpclassify(f))
171da2e3ebdSchin {
172da2e3ebdSchin case FP_INFINITE:
173da2e3ebdSchin return SF_INF;
174da2e3ebdSchin case FP_NAN:
175da2e3ebdSchin return SF_NAN;
176da2e3ebdSchin case FP_ZERO:
177da2e3ebdSchin return SF_ZERO;
178da2e3ebdSchin }
179da2e3ebdSchin # endif
180da2e3ebdSchin # else
1817c2fbfb3SApril Chin # if _lib_signbit
1827c2fbfb3SApril Chin if (signbit(f))
1837c2fbfb3SApril Chin # else
1847c2fbfb3SApril Chin if (f < 0.0 || f == 0.0 && neg0ld(f))
1857c2fbfb3SApril Chin # endif
186da2e3ebdSchin { f = -f;
187da2e3ebdSchin *sign = 1;
188da2e3ebdSchin }
189da2e3ebdSchin # endif
190da2e3ebdSchin if(f < LDBL_MIN)
191da2e3ebdSchin return SF_ZERO;
192da2e3ebdSchin if(f > LDBL_MAX)
193da2e3ebdSchin return SF_INF;
194da2e3ebdSchin
195da2e3ebdSchin if(format & SFFMT_AFORMAT)
196da2e3ebdSchin { Sfdouble_t g;
197da2e3ebdSchin b = sp = buf;
198da2e3ebdSchin ep = (format & SFFMT_UPPER) ? ux : lx;
199da2e3ebdSchin if(n_digit <= 0 || n_digit >= (size - 9))
200da2e3ebdSchin n_digit = size - 9;
201da2e3ebdSchin endsp = sp + n_digit + 1;
202da2e3ebdSchin
203da2e3ebdSchin g = frexpl(f, &x);
204da2e3ebdSchin *decpt = x;
205da2e3ebdSchin f = ldexpl(g, 8 * sizeof(m) - 3);
206da2e3ebdSchin
207da2e3ebdSchin for (;;)
208da2e3ebdSchin { m = f;
209da2e3ebdSchin x = 8 * sizeof(m);
210da2e3ebdSchin while ((x -= 4) >= 0)
211da2e3ebdSchin { *sp++ = ep[(m >> x) & 0xf];
212da2e3ebdSchin if (sp >= endsp)
21334f9b3eeSRoland Mainz goto around;
214da2e3ebdSchin }
215da2e3ebdSchin f -= m;
216da2e3ebdSchin f = ldexpl(f, 8 * sizeof(m));
217da2e3ebdSchin }
218da2e3ebdSchin }
219da2e3ebdSchin
220da2e3ebdSchin n = 0;
2217c2fbfb3SApril Chin if(f >= (Sfdouble_t)CVT_LDBL_MAXINT)
222da2e3ebdSchin { /* scale to a small enough number to fit an int */
223da2e3ebdSchin v = SF_MAXEXP10-1;
224da2e3ebdSchin do
225da2e3ebdSchin { if(f < _Sfpos10[v])
226da2e3ebdSchin v -= 1;
227da2e3ebdSchin else
228da2e3ebdSchin {
229da2e3ebdSchin f *= _Sfneg10[v];
230da2e3ebdSchin if((n += (1<<v)) >= SF_IDIGITS)
231da2e3ebdSchin return SF_INF;
232da2e3ebdSchin }
2337c2fbfb3SApril Chin } while(f >= (Sfdouble_t)CVT_LDBL_MAXINT);
2347c2fbfb3SApril Chin }
2357c2fbfb3SApril Chin else if(f > 0.0 && f < 0.1)
2367c2fbfb3SApril Chin { /* scale to avoid excessive multiply by 10 below */
2377c2fbfb3SApril Chin v = SF_MAXEXP10-1;
2387c2fbfb3SApril Chin do
2397c2fbfb3SApril Chin { if(f <= _Sfneg10[v])
2407c2fbfb3SApril Chin { f *= _Sfpos10[v];
2417c2fbfb3SApril Chin if((n += (1<<v)) >= SF_IDIGITS)
2427c2fbfb3SApril Chin return SF_INF;
2437c2fbfb3SApril Chin }
2447c2fbfb3SApril Chin else if (--v < 0)
2457c2fbfb3SApril Chin break;
2467c2fbfb3SApril Chin } while(f < 0.1);
2477c2fbfb3SApril Chin n = -n;
248da2e3ebdSchin }
249da2e3ebdSchin *decpt = (int)n;
250da2e3ebdSchin
251da2e3ebdSchin b = sp = buf + SF_INTPART;
2527c2fbfb3SApril Chin if((v = (CVT_LDBL_INT)f) != 0)
253da2e3ebdSchin { /* translate the integer part */
254da2e3ebdSchin f -= (Sfdouble_t)v;
255da2e3ebdSchin
2567c2fbfb3SApril Chin sfucvt(v,sp,n,ep,CVT_LDBL_INT,unsigned CVT_LDBL_INT);
257da2e3ebdSchin
258da2e3ebdSchin n = b-sp;
259da2e3ebdSchin if((*decpt += (int)n) >= SF_IDIGITS)
260da2e3ebdSchin return SF_INF;
261da2e3ebdSchin b = sp;
262da2e3ebdSchin sp = buf + SF_INTPART;
263da2e3ebdSchin }
264da2e3ebdSchin else n = 0;
265da2e3ebdSchin
266da2e3ebdSchin /* remaining number of digits to compute; add 1 for later rounding */
267da2e3ebdSchin n = (((format&SFFMT_EFORMAT) || *decpt <= 0) ? 1 : *decpt+1) - n;
268da2e3ebdSchin if(n_digit > 0)
269da2e3ebdSchin { if(n_digit > LDBL_DIG)
270da2e3ebdSchin n_digit = LDBL_DIG;
271da2e3ebdSchin n += n_digit;
272da2e3ebdSchin }
273da2e3ebdSchin
274da2e3ebdSchin if((ep = (sp+n)) > (endsp = buf+(size-2)))
275da2e3ebdSchin ep = endsp;
276da2e3ebdSchin if(sp > ep)
277da2e3ebdSchin sp = ep;
278da2e3ebdSchin else
279da2e3ebdSchin {
280da2e3ebdSchin if((format&SFFMT_EFORMAT) && *decpt == 0 && f > 0.)
281da2e3ebdSchin { Sfdouble_t d;
282da2e3ebdSchin while((long)(d = f*10.) == 0)
283da2e3ebdSchin { f = d;
284da2e3ebdSchin *decpt -= 1;
285da2e3ebdSchin }
286da2e3ebdSchin }
287da2e3ebdSchin
288da2e3ebdSchin while(sp < ep)
289da2e3ebdSchin { /* generate fractional digits */
290da2e3ebdSchin if(f <= 0.)
291da2e3ebdSchin { /* fill with 0's */
292da2e3ebdSchin do { *sp++ = '0'; } while(sp < ep);
293da2e3ebdSchin goto done;
294da2e3ebdSchin }
295da2e3ebdSchin else if((n = (long)(f *= 10.)) < 10)
296da2e3ebdSchin { *sp++ = '0' + n;
297da2e3ebdSchin f -= n;
298da2e3ebdSchin }
299da2e3ebdSchin else /* n == 10 */
300da2e3ebdSchin { do { *sp++ = '9'; } while(sp < ep);
301da2e3ebdSchin }
302da2e3ebdSchin }
303da2e3ebdSchin }
304da2e3ebdSchin } else
305da2e3ebdSchin #endif
3067c2fbfb3SApril Chin { double f = *(double*)vp;
307da2e3ebdSchin
3087c2fbfb3SApril Chin if(isnan(f))
3097c2fbfb3SApril Chin {
3107c2fbfb3SApril Chin #if _lib_signbit
3117c2fbfb3SApril Chin if (signbit(f))
3127c2fbfb3SApril Chin #else
3137c2fbfb3SApril Chin if (f < 0)
3147c2fbfb3SApril Chin #endif
3157c2fbfb3SApril Chin *sign = 1;
3167c2fbfb3SApril Chin return SF_NAN;
3177c2fbfb3SApril Chin }
318da2e3ebdSchin #if _lib_isinf
319da2e3ebdSchin if (n = isinf(f))
3207c2fbfb3SApril Chin {
3217c2fbfb3SApril Chin #if _lib_signbit
3227c2fbfb3SApril Chin if (signbit(f))
3237c2fbfb3SApril Chin #else
3247c2fbfb3SApril Chin if (n < 0 || f < 0)
3257c2fbfb3SApril Chin #endif
326da2e3ebdSchin *sign = 1;
327da2e3ebdSchin return SF_INF;
328da2e3ebdSchin }
329da2e3ebdSchin #endif
330da2e3ebdSchin #if _c99_in_the_wild
331da2e3ebdSchin # if _lib_signbit
332da2e3ebdSchin if (signbit(f))
333da2e3ebdSchin # else
334da2e3ebdSchin # if _lib_copysign
335da2e3ebdSchin if (copysign(1.0, f) < 0.0)
336da2e3ebdSchin # else
337da2e3ebdSchin if (f < 0.0)
338da2e3ebdSchin # endif
339da2e3ebdSchin # endif
340da2e3ebdSchin { f = -f;
341da2e3ebdSchin *sign = 1;
342da2e3ebdSchin }
343da2e3ebdSchin # if _lib_fpclassify
344da2e3ebdSchin switch (fpclassify(f))
345da2e3ebdSchin {
346da2e3ebdSchin case FP_INFINITE:
347da2e3ebdSchin return SF_INF;
348da2e3ebdSchin case FP_NAN:
349da2e3ebdSchin return SF_NAN;
350da2e3ebdSchin case FP_ZERO:
351da2e3ebdSchin return SF_ZERO;
352da2e3ebdSchin }
353da2e3ebdSchin # endif
354da2e3ebdSchin #else
3557c2fbfb3SApril Chin # if _lib_signbit
3567c2fbfb3SApril Chin if (signbit(f))
3577c2fbfb3SApril Chin # else
3587c2fbfb3SApril Chin if (f < 0.0 || f == 0.0 && neg0d(f))
3597c2fbfb3SApril Chin # endif
360da2e3ebdSchin { f = -f;
361da2e3ebdSchin *sign = 1;
362da2e3ebdSchin }
363da2e3ebdSchin #endif
364da2e3ebdSchin if(f < DBL_MIN)
365da2e3ebdSchin return SF_ZERO;
366da2e3ebdSchin if(f > DBL_MAX)
367da2e3ebdSchin return SF_INF;
368da2e3ebdSchin
369da2e3ebdSchin if(format & SFFMT_AFORMAT)
370da2e3ebdSchin { double g;
371da2e3ebdSchin b = sp = buf;
372da2e3ebdSchin ep = (format & SFFMT_UPPER) ? ux : lx;
373da2e3ebdSchin if(n_digit <= 0 || n_digit >= (size - 9))
374da2e3ebdSchin n_digit = size - 9;
37534f9b3eeSRoland Mainz endsp = sp + n_digit + 1;
376da2e3ebdSchin
377da2e3ebdSchin g = frexp(f, &x);
378da2e3ebdSchin *decpt = x;
379da2e3ebdSchin f = ldexp(g, 8 * sizeof(m) - 3);
380da2e3ebdSchin
381da2e3ebdSchin for (;;)
382da2e3ebdSchin { m = f;
383da2e3ebdSchin x = 8 * sizeof(m);
384da2e3ebdSchin while ((x -= 4) >= 0)
385da2e3ebdSchin { *sp++ = ep[(m >> x) & 0xf];
386da2e3ebdSchin if (sp >= endsp)
38734f9b3eeSRoland Mainz goto around;
388da2e3ebdSchin }
389da2e3ebdSchin f -= m;
390da2e3ebdSchin f = ldexp(f, 8 * sizeof(m));
391da2e3ebdSchin }
392da2e3ebdSchin }
393da2e3ebdSchin n = 0;
3947c2fbfb3SApril Chin if(f >= (double)CVT_DBL_MAXINT)
395da2e3ebdSchin { /* scale to a small enough number to fit an int */
396da2e3ebdSchin v = SF_MAXEXP10-1;
397da2e3ebdSchin do
398da2e3ebdSchin { if(f < _Sfpos10[v])
399da2e3ebdSchin v -= 1;
400da2e3ebdSchin else
401da2e3ebdSchin { f *= _Sfneg10[v];
402da2e3ebdSchin if((n += (1<<v)) >= SF_IDIGITS)
403da2e3ebdSchin return SF_INF;
404da2e3ebdSchin }
4057c2fbfb3SApril Chin } while(f >= (double)CVT_DBL_MAXINT);
4067c2fbfb3SApril Chin }
4077c2fbfb3SApril Chin else if(f > 0.0 && f < 1e-8)
4087c2fbfb3SApril Chin { /* scale to avoid excessive multiply by 10 below */
4097c2fbfb3SApril Chin v = SF_MAXEXP10-1;
4107c2fbfb3SApril Chin do
4117c2fbfb3SApril Chin { if(f <= _Sfneg10[v])
4127c2fbfb3SApril Chin { f *= _Sfpos10[v];
4137c2fbfb3SApril Chin if((n += (1<<v)) >= SF_IDIGITS)
4147c2fbfb3SApril Chin return SF_INF;
4157c2fbfb3SApril Chin }
4167c2fbfb3SApril Chin else if(--v < 0)
4177c2fbfb3SApril Chin break;
4187c2fbfb3SApril Chin } while(f < 0.1);
4197c2fbfb3SApril Chin n = -n;
420da2e3ebdSchin }
421da2e3ebdSchin *decpt = (int)n;
422da2e3ebdSchin
423da2e3ebdSchin b = sp = buf + SF_INTPART;
4247c2fbfb3SApril Chin if((v = (CVT_DBL_INT)f) != 0)
425da2e3ebdSchin { /* translate the integer part */
426da2e3ebdSchin f -= (double)v;
427da2e3ebdSchin
4287c2fbfb3SApril Chin sfucvt(v,sp,n,ep,CVT_DBL_INT,unsigned CVT_DBL_INT);
429da2e3ebdSchin
430da2e3ebdSchin n = b-sp;
431da2e3ebdSchin if((*decpt += (int)n) >= SF_IDIGITS)
432da2e3ebdSchin return SF_INF;
433da2e3ebdSchin b = sp;
434da2e3ebdSchin sp = buf + SF_INTPART;
435da2e3ebdSchin }
436da2e3ebdSchin else n = 0;
437da2e3ebdSchin
438da2e3ebdSchin /* remaining number of digits to compute; add 1 for later rounding */
439da2e3ebdSchin n = (((format&SFFMT_EFORMAT) || *decpt <= 0) ? 1 : *decpt+1) - n;
440da2e3ebdSchin if(n_digit > 0)
441da2e3ebdSchin { if(n_digit > DBL_DIG)
442da2e3ebdSchin n_digit = DBL_DIG;
443da2e3ebdSchin n += n_digit;
444da2e3ebdSchin }
445da2e3ebdSchin
446da2e3ebdSchin if((ep = (sp+n)) > (endsp = buf+(size-2)))
447da2e3ebdSchin ep = endsp;
448da2e3ebdSchin if(sp > ep)
449da2e3ebdSchin sp = ep;
450da2e3ebdSchin else
451da2e3ebdSchin {
452da2e3ebdSchin if((format&SFFMT_EFORMAT) && *decpt == 0 && f > 0.)
453da2e3ebdSchin { reg double d;
454da2e3ebdSchin while((long)(d = f*10.) == 0)
455da2e3ebdSchin { f = d;
456da2e3ebdSchin *decpt -= 1;
457da2e3ebdSchin }
458da2e3ebdSchin }
459da2e3ebdSchin
460da2e3ebdSchin while(sp < ep)
461da2e3ebdSchin { /* generate fractional digits */
462da2e3ebdSchin if(f <= 0.)
463da2e3ebdSchin { /* fill with 0's */
464da2e3ebdSchin do { *sp++ = '0'; } while(sp < ep);
465da2e3ebdSchin goto done;
466da2e3ebdSchin }
467da2e3ebdSchin else if((n = (long)(f *= 10.)) < 10)
468da2e3ebdSchin { *sp++ = (char)('0' + n);
469da2e3ebdSchin f -= n;
470da2e3ebdSchin }
471da2e3ebdSchin else /* n == 10 */
472da2e3ebdSchin { do { *sp++ = '9'; } while(sp < ep);
4737c2fbfb3SApril Chin break;
474da2e3ebdSchin }
475da2e3ebdSchin }
476da2e3ebdSchin }
477da2e3ebdSchin }
478da2e3ebdSchin
479da2e3ebdSchin if(ep <= b)
480da2e3ebdSchin ep = b+1;
481da2e3ebdSchin else if(ep < endsp)
482da2e3ebdSchin { /* round the last digit */
483da2e3ebdSchin *--sp += 5;
484da2e3ebdSchin while(*sp > '9')
485da2e3ebdSchin { *sp = '0';
486da2e3ebdSchin if(sp > b)
487da2e3ebdSchin *--sp += 1;
488da2e3ebdSchin else
489da2e3ebdSchin { /* next power of 10 */
490da2e3ebdSchin *sp = '1';
491da2e3ebdSchin *decpt += 1;
492da2e3ebdSchin if(!(format&SFFMT_EFORMAT))
493da2e3ebdSchin { /* add one more 0 for %f precision */
494da2e3ebdSchin ep[-1] = '0';
495da2e3ebdSchin ep += 1;
496da2e3ebdSchin }
497da2e3ebdSchin }
498da2e3ebdSchin }
499da2e3ebdSchin }
500da2e3ebdSchin
501da2e3ebdSchin done:
502da2e3ebdSchin *--ep = '\0';
503da2e3ebdSchin if(len)
504da2e3ebdSchin *len = ep-b;
505da2e3ebdSchin return b;
50634f9b3eeSRoland Mainz around:
50734f9b3eeSRoland Mainz if (((m >> x) & 0xf) >= 8)
50834f9b3eeSRoland Mainz { t = sp - 1;
50934f9b3eeSRoland Mainz for (;;)
51034f9b3eeSRoland Mainz { if (--t <= b)
51134f9b3eeSRoland Mainz { (*decpt)++;
51234f9b3eeSRoland Mainz break;
51334f9b3eeSRoland Mainz }
51434f9b3eeSRoland Mainz switch (*t)
51534f9b3eeSRoland Mainz {
51634f9b3eeSRoland Mainz case 'f':
51734f9b3eeSRoland Mainz case 'F':
51834f9b3eeSRoland Mainz *t = '0';
51934f9b3eeSRoland Mainz continue;
52034f9b3eeSRoland Mainz case '9':
52134f9b3eeSRoland Mainz *t = ep[10];
52234f9b3eeSRoland Mainz break;
52334f9b3eeSRoland Mainz default:
52434f9b3eeSRoland Mainz (*t)++;
52534f9b3eeSRoland Mainz break;
52634f9b3eeSRoland Mainz }
52734f9b3eeSRoland Mainz break;
52834f9b3eeSRoland Mainz }
52934f9b3eeSRoland Mainz }
53034f9b3eeSRoland Mainz ep = sp + 1;
53134f9b3eeSRoland Mainz goto done;
532da2e3ebdSchin }
533