branch update for HEAD-2003021201
[reactos.git] / lib / crtdll / stdlib / strtold.c
1 /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
2 #include <msvcrt/stdlib.h>
3 #include <msvcrt/ctype.h>
4 //#include <msvcrt/unconst.h>
5
6 static double powten[] =
7 {
8   1e1L, 1e2L, 1e4L, 1e8L, 1e16L, 1e32L, 1e64L, 1e128L, 1e256L,
9 #ifdef __GNUC__
10   1e512L, 1e512L*1e512L, 1e2048L, 1e4096L
11 #else
12   1e256L, 1e256L, 1e256L, 1e256L
13 #endif
14 };
15
16 long double
17 _strtold(const char *s, char **sret)
18 {       
19   double r;             /* result */
20   int e, ne;                    /* exponent */
21   int sign;                     /* +- 1.0 */
22   int esign;
23   int flags=0;
24   int l2powm1;
25
26   r = 0.0L;
27   sign = 1;
28   e = ne = 0;
29   esign = 1;
30
31   while(*s && isspace(*s))
32     s++;
33
34   if (*s == '+')
35     s++;
36   else if (*s == '-')
37   {
38     sign = -1;
39     s++;
40   }
41
42   while ((*s >= '0') && (*s <= '9'))
43   {
44     flags |= 1;
45     r *= 10.0L;
46     r += *s - '0';
47     s++;
48   }
49
50   if (*s == '.')
51   {
52     s++;
53     while ((*s >= '0') && (*s <= '9'))
54     {
55       flags |= 2;
56       r *= 10.0L;
57       r += *s - '0';
58       s++;
59       ne++;
60     }
61   }
62   if (flags == 0)
63   {
64     if (sret)
65       *sret = (char *)s;
66     return 0.0L;
67   }
68
69   if ((*s == 'e') || (*s == 'E'))
70   {
71     s++;
72     if (*s == '+')
73       s++;
74     else if (*s == '-')
75     {
76       s++;
77       esign = -1;
78     }
79     while ((*s >= '0') && (*s <= '9'))
80     {
81       e *= 10;
82       e += *s - '0';
83       s++;
84     }
85   }
86   if (esign < 0)
87   {
88     esign = -esign;
89     e = -e;
90   }
91   e = e - ne;
92   if (e < -4096)
93   {
94     /* possibly subnormal number, 10^e would overflow */
95     r *= 1.0e-2048L;
96     e += 2048;
97   }
98   if (e < 0)
99   {
100     e = -e;
101     esign = -esign;
102   }
103   if (e >= 8192)
104     e = 8191;
105   if (e)
106   {
107     double d = 1.0L;
108     l2powm1 = 0;
109     while (e)
110     {
111       if (e & 1)
112         d *= powten[l2powm1];
113       e >>= 1;
114       l2powm1++;
115     }
116     if (esign > 0)
117       r *= d;
118     else
119       r /= d;
120   }
121   if (sret)
122     *sret = (char *)s;
123   return r * sign;
124
125   return 0;
126 }