22cbd76a12d91e0ed1ab5e038382ba4d5e620e23
[mw/micromonitor-lm32.git] / umon_main / target / glib / strtod.c
1 //
2 // strtod.c
3 //
4 // Convert string to double 
5 //
6 // Copyright (C) 2002 Michael Ringgaard. All rights reserved.
7 //
8 // Redistribution and use in source and binary forms, with or without
9 // modification, are permitted provided that the following conditions
10 // are met:
11 // 
12 // 1. Redistributions of source code must retain the above copyright 
13 //    notice, this list of conditions and the following disclaimer.  
14 // 2. Redistributions in binary form must reproduce the above copyright
15 //    notice, this list of conditions and the following disclaimer in the
16 //    documentation and/or other materials provided with the distribution.  
17 // 3. Neither the name of the project nor the names of its contributors
18 //    may be used to endorse or promote products derived from this software
19 //    without specific prior written permission. 
20 // 
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 // ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
25 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
31 // SUCH DAMAGE.
32 // 
33
34 #include <ctype.h>
35 #include <float.h>
36 #include <stdlib.h>
37 #include <math.h>
38
39 double strtod(const char *str, char **endptr)
40 {
41   double number;
42   int exponent;
43   int negative;
44   char *p = (char *) str;
45   double p10;
46   int n;
47   int num_digits;
48   int num_decimals;
49
50   // Skip leading whitespace
51   while (isspace(*p)) p++;
52
53   // Handle optional sign
54   negative = 0;
55   switch (*p) 
56   {             
57     case '-': negative = 1; // Fall through to increment position
58     case '+': p++;
59   }
60
61   number = 0.;
62   exponent = 0;
63   num_digits = 0;
64   num_decimals = 0;
65
66   // Process string of digits
67   while (isdigit(*p))
68   {
69     number = number * 10. + (*p - '0');
70     p++;
71     num_digits++;
72   }
73
74   // Process decimal part
75   if (*p == '.') 
76   {
77     p++;
78
79     while (isdigit(*p))
80     {
81       number = number * 10. + (*p - '0');
82       p++;
83       num_digits++;
84       num_decimals++;
85     }
86
87     exponent -= num_decimals;
88   }
89
90   if (num_digits == 0)
91   {
92     //errno = ERANGE;
93     return 0.0;
94   }
95
96   // Correct for sign
97   if (negative) number = -number;
98
99   // Process an exponent string
100   if (*p == 'e' || *p == 'E') 
101   {
102     // Handle optional sign
103     negative = 0;
104     switch(*++p) 
105     {   
106       case '-': negative = 1;   // Fall through to increment pos
107       case '+': p++;
108     }
109
110     // Process string of digits
111     n = 0;
112     while (isdigit(*p)) 
113     {   
114       n = n * 10 + (*p - '0');
115       p++;
116     }
117
118     if (negative) 
119       exponent -= n;
120     else
121       exponent += n;
122   }
123
124   if (exponent < DBL_MIN_EXP  || exponent > DBL_MAX_EXP)
125   {
126     //errno = ERANGE;
127     return HUGE_VAL;
128   }
129
130   // Scale the result
131   p10 = 10.;
132   n = exponent;
133   if (n < 0) n = -n;
134   while (n) 
135   {
136     if (n & 1) 
137     {
138       if (exponent < 0)
139         number /= p10;
140       else
141         number *= p10;
142     }
143     n >>= 1;
144     p10 *= p10;
145   }
146
147   //if (number == HUGE_VAL) errno = ERANGE;
148   if (endptr) *endptr = p;
149
150   return number;
151 }
152
153 double atof(const char *str)
154 {
155   return strtod(str, NULL);
156 }
157