Mercurial > gnulib
comparison lib/strtod.c @ 12421:e8d2c6fc33ad
Use spaces for indentation, not tabs.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Thu, 10 Dec 2009 20:28:30 +0100 |
parents | 48eddbd8edd5 |
children | f7842310a565 |
comparison
equal
deleted
inserted
replaced
12420:5850b9a81029 | 12421:e8d2c6fc33ad |
---|---|
36 bool negative = false; | 36 bool negative = false; |
37 | 37 |
38 /* The number so far. */ | 38 /* The number so far. */ |
39 double num; | 39 double num; |
40 | 40 |
41 bool got_dot; /* Found a decimal point. */ | 41 bool got_dot; /* Found a decimal point. */ |
42 bool got_digit; /* Seen any digits. */ | 42 bool got_digit; /* Seen any digits. */ |
43 bool hex = false; /* Look for hex float exponent. */ | 43 bool hex = false; /* Look for hex float exponent. */ |
44 | 44 |
45 /* The exponent of the number. */ | 45 /* The exponent of the number. */ |
46 long int exponent; | 46 long int exponent; |
47 | 47 |
48 if (nptr == NULL) | 48 if (nptr == NULL) |
73 && (c_isxdigit (s[2]) || ('.' == s[2] && c_isxdigit (s[3])))) | 73 && (c_isxdigit (s[2]) || ('.' == s[2] && c_isxdigit (s[3])))) |
74 { | 74 { |
75 hex = true; | 75 hex = true; |
76 s += 2; | 76 s += 2; |
77 for (;; ++s) | 77 for (;; ++s) |
78 { | 78 { |
79 if (c_isxdigit (*s)) | 79 if (c_isxdigit (*s)) |
80 { | 80 { |
81 got_digit = true; | 81 got_digit = true; |
82 | 82 |
83 /* Make sure that multiplication by 16 will not overflow. */ | 83 /* Make sure that multiplication by 16 will not overflow. */ |
84 if (num > DBL_MAX / 16) | 84 if (num > DBL_MAX / 16) |
85 /* The value of the digit doesn't matter, since we have already | 85 /* The value of the digit doesn't matter, since we have already |
86 gotten as many digits as can be represented in a `double'. | 86 gotten as many digits as can be represented in a `double'. |
87 This doesn't necessarily mean the result will overflow. | 87 This doesn't necessarily mean the result will overflow. |
88 The exponent may reduce it to within range. | 88 The exponent may reduce it to within range. |
89 | 89 |
90 We just need to record that there was another | 90 We just need to record that there was another |
91 digit so that we can multiply by 16 later. */ | 91 digit so that we can multiply by 16 later. */ |
92 ++exponent; | 92 ++exponent; |
93 else | 93 else |
94 num = ((num * 16.0) | 94 num = ((num * 16.0) |
95 + (c_tolower (*s) - (c_isdigit (*s) ? '0' : 'a' - 10))); | 95 + (c_tolower (*s) - (c_isdigit (*s) ? '0' : 'a' - 10))); |
96 | 96 |
97 /* Keep track of the number of digits after the decimal point. | 97 /* Keep track of the number of digits after the decimal point. |
98 If we just divided by 16 here, we would lose precision. */ | 98 If we just divided by 16 here, we would lose precision. */ |
99 if (got_dot) | 99 if (got_dot) |
100 --exponent; | 100 --exponent; |
101 } | 101 } |
102 else if (!got_dot && *s == '.') | 102 else if (!got_dot && *s == '.') |
103 /* Record that we have found the decimal point. */ | 103 /* Record that we have found the decimal point. */ |
104 got_dot = true; | 104 got_dot = true; |
105 else | 105 else |
106 /* Any other character terminates the number. */ | 106 /* Any other character terminates the number. */ |
107 break; | 107 break; |
108 } | 108 } |
109 } | 109 } |
110 | 110 |
111 /* Not a hex float. */ | 111 /* Not a hex float. */ |
112 else | 112 else |
113 { | 113 { |
114 for (;; ++s) | 114 for (;; ++s) |
115 { | 115 { |
116 if (c_isdigit (*s)) | 116 if (c_isdigit (*s)) |
117 { | 117 { |
118 got_digit = true; | 118 got_digit = true; |
119 | 119 |
120 /* Make sure that multiplication by 10 will not overflow. */ | 120 /* Make sure that multiplication by 10 will not overflow. */ |
121 if (num > DBL_MAX * 0.1) | 121 if (num > DBL_MAX * 0.1) |
122 /* The value of the digit doesn't matter, since we have already | 122 /* The value of the digit doesn't matter, since we have already |
123 gotten as many digits as can be represented in a `double'. | 123 gotten as many digits as can be represented in a `double'. |
124 This doesn't necessarily mean the result will overflow. | 124 This doesn't necessarily mean the result will overflow. |
125 The exponent may reduce it to within range. | 125 The exponent may reduce it to within range. |
126 | 126 |
127 We just need to record that there was another | 127 We just need to record that there was another |
128 digit so that we can multiply by 10 later. */ | 128 digit so that we can multiply by 10 later. */ |
129 ++exponent; | 129 ++exponent; |
130 else | 130 else |
131 num = (num * 10.0) + (*s - '0'); | 131 num = (num * 10.0) + (*s - '0'); |
132 | 132 |
133 /* Keep track of the number of digits after the decimal point. | 133 /* Keep track of the number of digits after the decimal point. |
134 If we just divided by 10 here, we would lose precision. */ | 134 If we just divided by 10 here, we would lose precision. */ |
135 if (got_dot) | 135 if (got_dot) |
136 --exponent; | 136 --exponent; |
137 } | 137 } |
138 else if (!got_dot && *s == '.') | 138 else if (!got_dot && *s == '.') |
139 /* Record that we have found the decimal point. */ | 139 /* Record that we have found the decimal point. */ |
140 got_dot = true; | 140 got_dot = true; |
141 else | 141 else |
142 /* Any other character terminates the number. */ | 142 /* Any other character terminates the number. */ |
143 break; | 143 break; |
144 } | 144 } |
145 } | 145 } |
146 | 146 |
147 if (!got_digit) | 147 if (!got_digit) |
148 { | 148 { |
149 /* Check for infinities and NaNs. */ | 149 /* Check for infinities and NaNs. */ |
150 if (c_tolower (*s) == 'i' | 150 if (c_tolower (*s) == 'i' |
151 && c_tolower (s[1]) == 'n' | 151 && c_tolower (s[1]) == 'n' |
152 && c_tolower (s[2]) == 'f') | 152 && c_tolower (s[2]) == 'f') |
153 { | 153 { |
154 s += 3; | 154 s += 3; |
155 num = HUGE_VAL; | 155 num = HUGE_VAL; |
156 if (c_tolower (*s) == 'i' | 156 if (c_tolower (*s) == 'i' |
157 && c_tolower (s[1]) == 'n' | 157 && c_tolower (s[1]) == 'n' |
158 && c_tolower (s[2]) == 'i' | 158 && c_tolower (s[2]) == 'i' |
159 && c_tolower (s[3]) == 't' | 159 && c_tolower (s[3]) == 't' |
160 && c_tolower (s[4]) == 'y') | 160 && c_tolower (s[4]) == 'y') |
161 s += 5; | 161 s += 5; |
162 goto valid; | 162 goto valid; |
163 } | 163 } |
164 #ifdef NAN | 164 #ifdef NAN |
165 else if (c_tolower (*s) == 'n' | 165 else if (c_tolower (*s) == 'n' |
166 && c_tolower (s[1]) == 'a' | 166 && c_tolower (s[1]) == 'a' |
167 && c_tolower (s[2]) == 'n') | 167 && c_tolower (s[2]) == 'n') |
168 { | 168 { |
169 s += 3; | 169 s += 3; |
170 num = NAN; | 170 num = NAN; |
171 /* Since nan(<n-char-sequence>) is implementation-defined, | 171 /* Since nan(<n-char-sequence>) is implementation-defined, |
172 we define it by ignoring <n-char-sequence>. A nicer | 172 we define it by ignoring <n-char-sequence>. A nicer |
173 implementation would populate the bits of the NaN | 173 implementation would populate the bits of the NaN |
174 according to interpreting n-char-sequence as a | 174 according to interpreting n-char-sequence as a |
175 hexadecimal number, but the result is still a NaN. */ | 175 hexadecimal number, but the result is still a NaN. */ |
176 if (*s == '(') | 176 if (*s == '(') |
177 { | 177 { |
178 const unsigned char *p = s + 1; | 178 const unsigned char *p = s + 1; |
179 while (c_isalnum (*p)) | 179 while (c_isalnum (*p)) |
180 p++; | 180 p++; |
181 if (*p == ')') | 181 if (*p == ')') |
182 s = p + 1; | 182 s = p + 1; |
183 } | 183 } |
184 goto valid; | 184 goto valid; |
185 } | 185 } |
186 #endif | 186 #endif |
187 goto noconv; | 187 goto noconv; |
188 } | 188 } |
189 | 189 |
190 if (c_tolower (*s) == (hex ? 'p' : 'e') && !isspace (s[1])) | 190 if (c_tolower (*s) == (hex ? 'p' : 'e') && !isspace (s[1])) |
196 | 196 |
197 errno = 0; | 197 errno = 0; |
198 ++s; | 198 ++s; |
199 value = strtol ((char *) s, &end, 10); | 199 value = strtol ((char *) s, &end, 10); |
200 if (errno == ERANGE && num) | 200 if (errno == ERANGE && num) |
201 { | 201 { |
202 /* The exponent overflowed a `long int'. It is probably a safe | 202 /* The exponent overflowed a `long int'. It is probably a safe |
203 assumption that an exponent that cannot be represented by | 203 assumption that an exponent that cannot be represented by |
204 a `long int' exceeds the limits of a `double'. */ | 204 a `long int' exceeds the limits of a `double'. */ |
205 if (endptr != NULL) | 205 if (endptr != NULL) |
206 *endptr = end; | 206 *endptr = end; |
207 if (value < 0) | 207 if (value < 0) |
208 goto underflow; | 208 goto underflow; |
209 else | 209 else |
210 goto overflow; | 210 goto overflow; |
211 } | 211 } |
212 else if (end == (char *) s) | 212 else if (end == (char *) s) |
213 /* There was no exponent. Reset END to point to | 213 /* There was no exponent. Reset END to point to |
214 the 'e' or 'E', so *ENDPTR will be set there. */ | 214 the 'e' or 'E', so *ENDPTR will be set there. */ |
215 end = (char *) s - 1; | 215 end = (char *) s - 1; |
216 errno = save; | 216 errno = save; |
217 s = (unsigned char *) end; | 217 s = (unsigned char *) end; |
218 exponent += value; | 218 exponent += value; |
219 } | 219 } |
220 | 220 |
232 checking for overflow and underflow. */ | 232 checking for overflow and underflow. */ |
233 | 233 |
234 if (exponent < 0) | 234 if (exponent < 0) |
235 { | 235 { |
236 if (num < DBL_MIN * pow (10.0, (double) -exponent)) | 236 if (num < DBL_MIN * pow (10.0, (double) -exponent)) |
237 goto underflow; | 237 goto underflow; |
238 } | 238 } |
239 else if (exponent > 0) | 239 else if (exponent > 0) |
240 { | 240 { |
241 if (num > DBL_MAX * pow (10.0, (double) -exponent)) | 241 if (num > DBL_MAX * pow (10.0, (double) -exponent)) |
242 goto overflow; | 242 goto overflow; |
243 } | 243 } |
244 | 244 |
245 num *= pow (10.0, (double) exponent); | 245 num *= pow (10.0, (double) exponent); |
246 | 246 |
247 valid: | 247 valid: |