3 <<ecvtbuf>>, <<fcvtbuf>>---double or float to string
13 char *ecvtbuf(double <[val]>, int <[chars]>, int *<[decpt]>,
14 int *<[sgn]>, char *<[buf]>);
16 char *fcvtbuf(double <[val]>, int <[decimals]>, int *<[decpt]>,
17 int *<[sgn]>, char *<[buf]>);
20 <<ecvtbuf>> and <<fcvtbuf>> produce (null-terminated) strings
21 of digits representating the <<double>> number <[val]>.
23 The only difference between <<ecvtbuf>> and <<fcvtbuf>> is the
24 interpretation of the second argument (<[chars]> or
25 <[decimals]>). For <<ecvtbuf>>, the second argument <[chars]>
26 specifies the total number of characters to write (which is
27 also the number of significant digits in the formatted string,
28 since these two functions write only digits). For <<fcvtbuf>>,
29 the second argument <[decimals]> specifies the number of
30 characters to write after the decimal point; all digits for
31 the integer part of <[val]> are always included.
33 Since <<ecvtbuf>> and <<fcvtbuf>> write only digits in the
34 output string, they record the location of the decimal point
35 in <<*<[decpt]>>>, and the sign of the number in <<*<[sgn]>>>.
36 After formatting a number, <<*<[decpt]>>> contains the number
37 of digits to the left of the decimal point. <<*<[sgn]>>>
38 contains <<0>> if the number is positive, and <<1>> if it is
39 negative. For both functions, you supply a pointer <[buf]> to
40 an area of memory to hold the converted string.
43 Both functions return a pointer to <[buf]>, the string
44 containing a character representation of <[val]>.
47 Neither function is ANSI C.
49 Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
50 <<lseek>>, <<read>>, <<sbrk>>, <<write>>.
60 #ifdef _REENT_THREAD_LOCAL
61 _Thread_local
char *_tls_cvtbuf
;
62 _Thread_local
int _tls_cvtlen
;
66 print_f (struct _reent
*ptr
,
76 char *p
, *start
, *end
;
78 start
= p
= _dtoa_r (ptr
, invalue
, mode
, ndigit
, &decpt
, &sign
, &end
);
85 while (*p
&& decpt
> 0)
90 /* Even if not in buffer */
101 if (decpt
< 0 && ndigit
> 0)
103 while (decpt
< 0 && ndigit
> 0)
110 /* Print rest of stuff */
111 while (*p
&& ndigit
> 0)
116 /* And trailing zeros */
126 /* Print number in e format with width chars after.
128 TYPE is one of 'e' or 'E'. It may also be one of 'g' or 'G' indicating
129 that _gcvt is calling us and we should remove trailing zeroes.
131 WIDTH is the number of digits of precision after the decimal point. */
134 print_e (struct _reent
*ptr
,
148 p
= _dtoa_r (ptr
, invalue
, 2, width
+ 1, &decpt
, &sign
, &end
);
160 while (*p
&& ndigit
> 0)
170 /* Add trailing zeroes to fill out to ndigits unless this is 'g' format.
171 Also, convert g/G to e/E. */
175 else if (type
== 'G')
190 /* Add the exponent. */
205 int top
= decpt
/ 100;
212 *buf
++ = decpt
+ '0';
219 /* Undocumented behaviour: when given NULL as a buffer, return a
220 pointer to static space in the rent structure. This is only to
221 support ecvt and fcvt, which aren't ANSI anyway. */
224 fcvtbuf (double invalue
,
230 struct _reent
*reent
= _REENT
;
236 if (fcvt_buf
== NULL
)
238 if (_REENT_CVTLEN(reent
) <= ndigit
+ 35)
240 if ((fcvt_buf
= (char *) _realloc_r (reent
, _REENT_CVTBUF(reent
),
241 ndigit
+ 36)) == NULL
)
243 _REENT_CVTLEN(reent
) = ndigit
+ 36;
244 _REENT_CVTBUF(reent
) = fcvt_buf
;
247 fcvt_buf
= _REENT_CVTBUF(reent
) ;
252 p
= _dtoa_r (reent
, invalue
, 3, ndigit
, decpt
, sign
, &end
);
262 /* And unsuppress the trailing zeroes */
263 while (done
< ndigit
)
273 ecvtbuf (double invalue
,
279 struct _reent
*reent
= _REENT
;
285 if (fcvt_buf
== NULL
)
287 if (_REENT_CVTLEN(reent
) <= ndigit
)
289 if ((fcvt_buf
= (char *) _realloc_r (reent
, _REENT_CVTBUF(reent
),
290 ndigit
+ 1)) == NULL
)
292 _REENT_CVTLEN(reent
) = ndigit
+ 1;
293 _REENT_CVTBUF(reent
) = fcvt_buf
;
296 fcvt_buf
= _REENT_CVTBUF(reent
) ;
301 p
= _dtoa_r (reent
, invalue
, 2, ndigit
, decpt
, sign
, &end
);
310 /* And unsuppress the trailing zeroes */
311 while (done
< ndigit
)
323 _gcvt (struct _reent
*ptr
,
343 /* Which one to print ?
344 ANSI says that anything with more that 4 zeros after the . or more
345 than precision digits before is printed in e with the qualification
346 that trailing zeroes are removed from the fraction portion. */
348 if (0.0001 >= invalue
|| invalue
>= _mprec_log10 (ndigit
))
350 /* We subtract 1 from ndigit because in the 'e' format the precision is
351 the number of digits after the . but in 'g' format it is the number
352 of significant digits.
354 We defer changing type to e/E so that print_e() can know it's us
355 calling and thus should remove trailing zeroes. */
357 print_e (ptr
, buf
, invalue
, ndigit
- 1, type
, dot
);
366 /* We always want ndigits of precision, even if that means printing
367 * a bunch of leading zeros for numbers < 1.0
369 p
= _dtoa_r (ptr
, invalue
, 2, ndigit
, &decpt
, &sign
, &end
);
376 while (*p
&& decpt
> 0)
382 /* Even if not in buffer */
383 while (decpt
> 0 && ndigit
> 0)
396 /* Leading zeros don't count towards 'ndigit' */
403 /* Print rest of stuff */
404 while (*p
&& ndigit
> 0)
409 /* And trailing zeros */
426 _dcvt (struct _reent
*ptr
,
438 print_f (ptr
, buffer
, invalue
, precision
, type
, precision
== 0 ? dot
: 1, 3);
444 _gcvt (ptr
, invalue
, precision
, buffer
, type
, dot
);
448 print_e (ptr
, buffer
, invalue
, precision
, type
, dot
);