1 /* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */
2 #include <msvcrt/stdlib.h>
3 #include <msvcrt/stdio.h>
4 #include <msvcrt/string.h>
5 #include <msvcrt/float.h>
6 #include <msvcrt/alloc.h>
7 // #include <msvcrt/locale.h>
9 void __ecvround (char *, char *, const char *, int *);
12 __ecvround (char *numbuf, char *last_digit, const char *after_last, int *decpt)
17 /* Do we have at all to round the last digit? */
18 if (*after_last > '4')
23 /* Propagate the rounding through trailing '9' digits. */
27 *p-- = sum - carry * 10;
28 } while (carry && p >= numbuf);
30 /* We have 9999999... which needs to be rounded to 100000.. */
31 if (carry && p == numbuf)
40 ecvtbuf (double value, int ndigits, int *decpt, int *sign, char *buf)
42 static char INFINITY[] = "Infinity";
43 char decimal = '.' /* localeconv()->decimal_point[0] */;
44 char *cvtbuf = (char *)alloca (ndigits + 20); /* +3 for sign, dot, null; */
45 /* two extra for rounding */
46 /* 15 extra for alignment */
47 char *s = cvtbuf, *d = buf;
49 /* Produce two extra digits, so we could round properly. */
50 sprintf (cvtbuf, "%-+.*E", ndigits + 2, value);
59 /* Special values get special treatment. */
60 if (strncmp (s, "Inf", 3) == 0)
62 /* SunOS docs says we have return "Infinity" for NDIGITS >= 8. */
63 memcpy (buf, INFINITY, ndigits >= 8 ? 9 : 3);
67 else if (strcmp (s, "NaN") == 0)
71 char *last_digit, *digit_after_last;
73 /* Copy (the single) digit before the decimal. */
74 while (*s && *s != decimal && d - buf < ndigits)
77 /* If we don't see any exponent, here's our decimal point. */
82 /* Copy the fraction digits. */
83 while (*s && *s != 'E' && d - buf < ndigits)
86 /* Remember the last digit copied and the one after it. */
87 last_digit = d > buf ? d - 1 : d;
90 /* Get past the E in exponent field. */
91 while (*s && *s++ != 'E')
94 /* Adjust the decimal point by the exponent value. */
97 /* Pad with zeroes if needed. */
98 while (d - buf < ndigits)
101 /* Zero-terminate. */
104 /* Round if necessary. */
105 __ecvround (buf, last_digit, digit_after_last, decpt);