update for HEAD-2003021201
[reactos.git] / lib / crtdll / stdlib / fcvtbuf.c
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>
8
9 void __ecvround (char *, char *, const char *, int *);
10 char *ecvtbuf (double, int, int *, int *, char *);
11
12 char *
13 fcvtbuf (double value, int ndigits, int *decpt, int *sign, char *buf)
14 {
15   static char INFINITY[] = "Infinity";
16   char decimal = '.' /* localeconv()->decimal_point[0] */;
17   int digits = ndigits >= 0 ? ndigits : 0;
18   char *cvtbuf = (char *)alloca (2*DBL_MAX_10_EXP + 16);
19   char *s = cvtbuf;
20   char *dot;
21
22   sprintf (cvtbuf, "%-+#.*f", DBL_MAX_10_EXP + digits + 1, value);
23
24   /* The sign.  */
25   if (*s++ == '-')
26     *sign = 1;
27   else
28     *sign = 0;
29
30   /* Where's the decimal point?  */
31   dot = strchr (s, decimal);
32   *decpt = dot ? dot - s : strlen (s);
33
34   /* SunOS docs says if NDIGITS is 8 or more, produce "Infinity"
35      instead of "Inf".  */
36   if (strncmp (s, "Inf", 3) == 0)
37     {
38       memcpy (buf, INFINITY, ndigits >= 8 ? 9 : 3);
39       if (ndigits < 8)
40         buf[3] = '\0';
41       return buf;
42     }
43   else if (ndigits < 0)
44     return ecvtbuf (value, *decpt + ndigits, decpt, sign, buf);
45   else if (*s == '0' && value != 0.0)
46     return ecvtbuf (value, ndigits, decpt, sign, buf);
47   else
48     {
49       memcpy (buf, s, *decpt);
50       if (s[*decpt] == decimal)
51         {
52           memcpy (buf + *decpt, s + *decpt + 1, ndigits);
53           buf[*decpt + ndigits] = '\0';
54         }
55       else
56         buf[*decpt] = '\0';
57       __ecvround (buf, buf + *decpt + ndigits - 1,
58                 s + *decpt + ndigits + 1, decpt);
59       return buf;
60     }
61 }