1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
4*3e14f97fSRoger A. Faulkner * Copyright (c) 1985-2010 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6da2e3ebdSchin * Common Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * A copy of the License is available at *
10da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt *
11da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12da2e3ebdSchin * *
13da2e3ebdSchin * Information and Software Systems Research *
14da2e3ebdSchin * AT&T Research *
15da2e3ebdSchin * Florham Park NJ *
16da2e3ebdSchin * *
17da2e3ebdSchin * Glenn Fowler <gsf@research.att.com> *
18da2e3ebdSchin * David Korn <dgk@research.att.com> *
19da2e3ebdSchin * Phong Vo <kpv@research.att.com> *
20da2e3ebdSchin * *
21da2e3ebdSchin ***********************************************************************/
22da2e3ebdSchin /*
23da2e3ebdSchin * AT&T Research
24da2e3ebdSchin * Glenn Fowler & Phong Vo
25da2e3ebdSchin *
26da2e3ebdSchin * common header and implementation for
27da2e3ebdSchin *
28da2e3ebdSchin * strtof strtod strtold _sfdscan
29da2e3ebdSchin * strntof strntod strntold
30da2e3ebdSchin *
31da2e3ebdSchin * define these macros to instantiate an implementation:
32da2e3ebdSchin *
33da2e3ebdSchin * S2F_function the function name
34da2e3ebdSchin * S2F_static <0:export =0:extern >0:static
35da2e3ebdSchin * S2F_type 0:float 1:double 2:long.double
3634f9b3eeSRoland Mainz * S2F_qualifier 1 for optional [fFlL] qualifier suffix
37da2e3ebdSchin * S2F_size 1 for interface with size_t second arg
38da2e3ebdSchin * S2F_scan 1 for alternate interface with these arguments:
39da2e3ebdSchin * void* handle
40da2e3ebdSchin * int (*getchar)(void* handle, int flag)
41da2e3ebdSchin * exactly one extra (*getchar)() is done, i.e.,
42da2e3ebdSchin * the caller must do the pushback
43da2e3ebdSchin * flag==0 get next char
44da2e3ebdSchin * flag==1 no number seen
45da2e3ebdSchin * return 0 on error or EOF
46da2e3ebdSchin */
47da2e3ebdSchin
48da2e3ebdSchin #include "sfhdr.h"
49da2e3ebdSchin #include "FEATURE/float"
50da2e3ebdSchin
51da2e3ebdSchin /*
52da2e3ebdSchin * the default is _sfdscan for standalone sfio compatibility
53da2e3ebdSchin */
54da2e3ebdSchin
55da2e3ebdSchin #if !defined(S2F_function)
56da2e3ebdSchin #define S2F_function _sfdscan
57da2e3ebdSchin #define S2F_static 1
58da2e3ebdSchin #define S2F_type 2
59da2e3ebdSchin #define S2F_scan 1
60da2e3ebdSchin #ifndef elementsof
61da2e3ebdSchin #define elementsof(a) (sizeof(a)/sizeof(a[0]))
62da2e3ebdSchin #endif
63da2e3ebdSchin #endif
64da2e3ebdSchin
65da2e3ebdSchin #if S2F_type == 2 && _ast_fltmax_double
66da2e3ebdSchin #undef S2F_type
67da2e3ebdSchin #define S2F_type 1
68da2e3ebdSchin #endif
69da2e3ebdSchin
70da2e3ebdSchin #if S2F_type == 0
71da2e3ebdSchin #define S2F_number float
72da2e3ebdSchin #define S2F_ldexp ldexp
73da2e3ebdSchin #define S2F_pow10 _Sffpow10
74da2e3ebdSchin #define S2F_inf _Sffinf
75da2e3ebdSchin #define S2F_nan _Sffnan
76da2e3ebdSchin #define S2F_min (FLT_MIN)
77da2e3ebdSchin #define S2F_max (FLT_MAX)
78da2e3ebdSchin #define S2F_exp_10_min (FLT_MIN_10_EXP)
79da2e3ebdSchin #define S2F_exp_10_max (FLT_MAX_10_EXP)
80da2e3ebdSchin #define S2F_exp_2_min (FLT_MIN_EXP)
81da2e3ebdSchin #define S2F_exp_2_max (FLT_MAX_EXP)
82da2e3ebdSchin #endif
83da2e3ebdSchin #if S2F_type == 1
84da2e3ebdSchin #define S2F_number double
85da2e3ebdSchin #define S2F_ldexp ldexp
86da2e3ebdSchin #define S2F_pow10 _Sfdpow10
87da2e3ebdSchin #define S2F_inf _Sfdinf
88da2e3ebdSchin #define S2F_nan _Sfdnan
89da2e3ebdSchin #define S2F_min (DBL_MIN)
90da2e3ebdSchin #define S2F_max (DBL_MAX)
91da2e3ebdSchin #define S2F_exp_10_min (DBL_MIN_10_EXP)
92da2e3ebdSchin #define S2F_exp_10_max (DBL_MAX_10_EXP)
93da2e3ebdSchin #define S2F_exp_2_min (DBL_MIN_EXP)
94da2e3ebdSchin #define S2F_exp_2_max (DBL_MAX_EXP)
95da2e3ebdSchin #endif
96da2e3ebdSchin #if S2F_type == 2
97da2e3ebdSchin #define S2F_number long double
98da2e3ebdSchin #define S2F_ldexp ldexpl
99da2e3ebdSchin #define S2F_pow10 _Sflpow10
100da2e3ebdSchin #define S2F_inf _Sflinf
101da2e3ebdSchin #define S2F_nan _Sflnan
102da2e3ebdSchin #define S2F_min (LDBL_MIN)
103da2e3ebdSchin #define S2F_max (LDBL_MAX)
104da2e3ebdSchin #define S2F_exp_10_min (LDBL_MIN_10_EXP)
105da2e3ebdSchin #define S2F_exp_10_max (LDBL_MAX_10_EXP)
106da2e3ebdSchin #define S2F_exp_2_min (LDBL_MIN_EXP)
107da2e3ebdSchin #define S2F_exp_2_max (LDBL_MAX_EXP)
108da2e3ebdSchin #endif
109da2e3ebdSchin
110da2e3ebdSchin #if -S2F_exp_10_min < S2F_exp_10_max
111da2e3ebdSchin #define S2F_exp_10_abs (-S2F_exp_10_min)
112da2e3ebdSchin #else
113da2e3ebdSchin #define S2F_exp_10_abs S2F_exp_10_max
114da2e3ebdSchin #endif
115da2e3ebdSchin
116da2e3ebdSchin #define S2F_batch _ast_flt_unsigned_max_t
117da2e3ebdSchin
118da2e3ebdSchin #undef ERR /* who co-opted this namespace? */
119da2e3ebdSchin
120da2e3ebdSchin #if S2F_scan
121da2e3ebdSchin
122da2e3ebdSchin typedef int (*S2F_get_f)_ARG_((void*, int));
123da2e3ebdSchin
124da2e3ebdSchin #define ERR(e)
125da2e3ebdSchin #define GET(p) (*get)(p,0)
126da2e3ebdSchin #define NON(p) (*get)(p,1)
127da2e3ebdSchin #define PUT(p)
128da2e3ebdSchin #define REV(p,t,b)
129da2e3ebdSchin #define SET(p,t,b)
130da2e3ebdSchin
131da2e3ebdSchin #else
132da2e3ebdSchin
133da2e3ebdSchin #define ERR(e) (errno=(e))
134da2e3ebdSchin #define NON(p)
135da2e3ebdSchin
136da2e3ebdSchin #if S2F_size
137da2e3ebdSchin #define GET(p) (((p)<(z))?(*p++):(back=0))
138da2e3ebdSchin #define PUT(p) (end?(*end=(char*)p-back):(char*)0)
139da2e3ebdSchin #define REV(p,t,b) (p=t,back=b)
140da2e3ebdSchin #define SET(p,t,b) (t=p,b=back)
141da2e3ebdSchin #else
142da2e3ebdSchin #define GET(p) (*p++)
143da2e3ebdSchin #define PUT(p) (end?(*end=(char*)p-1):(char*)0)
144da2e3ebdSchin #define REV(p,t,b) (p=t)
145da2e3ebdSchin #define SET(p,t,b) (t=p)
146da2e3ebdSchin #endif
147da2e3ebdSchin
148da2e3ebdSchin #endif
149da2e3ebdSchin
150da2e3ebdSchin typedef struct S2F_part_s
151da2e3ebdSchin {
152da2e3ebdSchin S2F_batch batch;
153da2e3ebdSchin int digits;
154da2e3ebdSchin } S2F_part_t;
155da2e3ebdSchin
156da2e3ebdSchin #if !defined(ERANGE)
157da2e3ebdSchin #define ERANGE EINVAL
158da2e3ebdSchin #endif
159da2e3ebdSchin
160da2e3ebdSchin #if S2F_static > 0
161da2e3ebdSchin static
162da2e3ebdSchin #else
163da2e3ebdSchin #if S2F_static < 0 || !defined(S2F_static)
164da2e3ebdSchin #if defined(__EXPORT__)
165da2e3ebdSchin #define extern __EXPORT__
166da2e3ebdSchin #endif
167da2e3ebdSchin extern
168da2e3ebdSchin #undef extern
169da2e3ebdSchin #endif
170da2e3ebdSchin #endif
171da2e3ebdSchin S2F_number
172da2e3ebdSchin #if S2F_scan
173da2e3ebdSchin #if __STD_C
S2F_function(void * s,S2F_get_f get)174da2e3ebdSchin S2F_function(void* s, S2F_get_f get)
175da2e3ebdSchin #else
176da2e3ebdSchin S2F_function(s, get) void* s; S2F_get_f get;
177da2e3ebdSchin #endif
178da2e3ebdSchin #else
179da2e3ebdSchin #if S2F_size
180da2e3ebdSchin #if __STD_C
181da2e3ebdSchin S2F_function(const char* str, size_t size, char** end)
182da2e3ebdSchin #else
183da2e3ebdSchin S2F_function(str, size, end) char* str; size_t size; char** end;
184da2e3ebdSchin #endif
185da2e3ebdSchin #else
186da2e3ebdSchin #if __STD_C
187da2e3ebdSchin S2F_function(const char* str, char** end)
188da2e3ebdSchin #else
189da2e3ebdSchin S2F_function(str, end) char* str; char** end;
190da2e3ebdSchin #endif
191da2e3ebdSchin #endif
192da2e3ebdSchin #endif
193da2e3ebdSchin {
194da2e3ebdSchin #if !S2F_scan
195da2e3ebdSchin register unsigned char* s = (unsigned char*)str;
196da2e3ebdSchin #if S2F_size
197da2e3ebdSchin register unsigned char* z = s + size;
198da2e3ebdSchin int back = 1;
199da2e3ebdSchin int b;
200da2e3ebdSchin #endif
201da2e3ebdSchin unsigned char* t;
202da2e3ebdSchin #endif
203da2e3ebdSchin register S2F_batch n;
204da2e3ebdSchin register int c;
205da2e3ebdSchin register int digits;
206da2e3ebdSchin register int m;
207da2e3ebdSchin register unsigned char* cv;
208da2e3ebdSchin int negative;
209da2e3ebdSchin int enegative;
210da2e3ebdSchin int fraction;
211da2e3ebdSchin int decimal = 0;
212da2e3ebdSchin int thousand = 0;
213da2e3ebdSchin int part = 0;
214da2e3ebdSchin S2F_number v;
215da2e3ebdSchin S2F_number p;
216da2e3ebdSchin S2F_part_t parts[16];
217da2e3ebdSchin
218da2e3ebdSchin /*
219da2e3ebdSchin * radix char and thousands separator are locale specific
220da2e3ebdSchin */
221da2e3ebdSchin
222da2e3ebdSchin SFSETLOCALE(&decimal, &thousand);
223da2e3ebdSchin SFCVINIT();
224da2e3ebdSchin
225da2e3ebdSchin /*
226da2e3ebdSchin * skip initial blanks
227da2e3ebdSchin */
228da2e3ebdSchin
229da2e3ebdSchin do c = GET(s); while (isspace(c));
230da2e3ebdSchin SET(s, t, b);
231da2e3ebdSchin
232da2e3ebdSchin /*
233da2e3ebdSchin * get the sign
234da2e3ebdSchin */
235da2e3ebdSchin
236da2e3ebdSchin if ((negative = (c == '-')) || c == '+')
237da2e3ebdSchin c = GET(s);
238da2e3ebdSchin
239da2e3ebdSchin /*
240da2e3ebdSchin * drop leading 0's
241da2e3ebdSchin */
242da2e3ebdSchin
243da2e3ebdSchin digits = 0;
244da2e3ebdSchin fraction = -1;
245da2e3ebdSchin if (c == '0')
246da2e3ebdSchin {
247da2e3ebdSchin c = GET(s);
248da2e3ebdSchin if (c == 'x' || c == 'X')
249da2e3ebdSchin {
250da2e3ebdSchin /*
251da2e3ebdSchin * hex floating point -- easy
252da2e3ebdSchin */
253da2e3ebdSchin
254da2e3ebdSchin cv = _Sfcv36;
255da2e3ebdSchin v = 0;
256da2e3ebdSchin for (;;)
257da2e3ebdSchin {
258da2e3ebdSchin c = GET(s);
259da2e3ebdSchin if ((part = cv[c]) < 16)
260da2e3ebdSchin {
261da2e3ebdSchin digits++;
262da2e3ebdSchin v *= 16;
263da2e3ebdSchin v += part;
264da2e3ebdSchin }
265da2e3ebdSchin else if (c == decimal)
266da2e3ebdSchin {
267da2e3ebdSchin decimal = -1;
268da2e3ebdSchin fraction = digits;
269da2e3ebdSchin }
270da2e3ebdSchin else
271da2e3ebdSchin break;
272da2e3ebdSchin }
273da2e3ebdSchin m = 0;
274da2e3ebdSchin if (c == 'p' || c == 'P')
275da2e3ebdSchin {
276da2e3ebdSchin c = GET(s);
277da2e3ebdSchin if ((enegative = c == '-') || c == '+')
278da2e3ebdSchin c = GET(s);
279da2e3ebdSchin while (c >= '0' && c <= '9')
280da2e3ebdSchin {
281da2e3ebdSchin m = (m << 3) + (m << 1) + (c - '0');
282da2e3ebdSchin c = GET(s);
283da2e3ebdSchin }
284da2e3ebdSchin if (enegative)
285da2e3ebdSchin m = -m;
286da2e3ebdSchin }
287da2e3ebdSchin
28834f9b3eeSRoland Mainz #if S2F_qualifier
28934f9b3eeSRoland Mainz
290da2e3ebdSchin /*
291da2e3ebdSchin * consume the optional suffix
292da2e3ebdSchin */
293da2e3ebdSchin
294da2e3ebdSchin switch (c)
295da2e3ebdSchin {
296da2e3ebdSchin case 'f':
297da2e3ebdSchin case 'F':
298da2e3ebdSchin case 'l':
299da2e3ebdSchin case 'L':
300da2e3ebdSchin c = GET(s);
301da2e3ebdSchin break;
302da2e3ebdSchin }
30334f9b3eeSRoland Mainz #endif
304da2e3ebdSchin PUT(s);
305da2e3ebdSchin if (v == 0)
3067c2fbfb3SApril Chin return negative ? -v : v;
307da2e3ebdSchin if (fraction >= 0)
308da2e3ebdSchin m -= 4 * (digits - fraction);
309da2e3ebdSchin if (m < S2F_exp_2_min)
310da2e3ebdSchin {
311da2e3ebdSchin if ((m -= S2F_exp_2_min) < S2F_exp_2_min)
312da2e3ebdSchin {
313da2e3ebdSchin ERR(ERANGE);
314da2e3ebdSchin return 0;
315da2e3ebdSchin }
316da2e3ebdSchin v = S2F_ldexp(v, S2F_exp_2_min);
317da2e3ebdSchin }
318da2e3ebdSchin else if (m > S2F_exp_2_max)
319da2e3ebdSchin {
320da2e3ebdSchin ERR(ERANGE);
321da2e3ebdSchin return negative ? -S2F_inf : S2F_inf;
322da2e3ebdSchin }
323da2e3ebdSchin v = S2F_ldexp(v, m);
324da2e3ebdSchin goto check;
325da2e3ebdSchin }
326da2e3ebdSchin while (c == '0')
327da2e3ebdSchin c = GET(s);
328da2e3ebdSchin }
329da2e3ebdSchin else if (c == decimal)
330da2e3ebdSchin {
331da2e3ebdSchin decimal = -1;
332da2e3ebdSchin fraction = 0;
333da2e3ebdSchin for (;;)
334da2e3ebdSchin {
335da2e3ebdSchin c = GET(s);
336da2e3ebdSchin if (c != '0')
337da2e3ebdSchin break;
338da2e3ebdSchin digits++;
339da2e3ebdSchin }
340da2e3ebdSchin }
341da2e3ebdSchin else if (c == 'i' || c == 'I')
342da2e3ebdSchin {
343da2e3ebdSchin if ((c = GET(s)) != 'n' && c != 'N' ||
344da2e3ebdSchin (c = GET(s)) != 'f' && c != 'F')
345da2e3ebdSchin {
346da2e3ebdSchin REV(s, t, b);
347da2e3ebdSchin PUT(s);
348da2e3ebdSchin return 0;
349da2e3ebdSchin }
350da2e3ebdSchin c = GET(s);
351da2e3ebdSchin SET(s, t, b);
352da2e3ebdSchin if (((c) == 'i' || c == 'I') &&
353da2e3ebdSchin ((c = GET(s)) == 'n' || c == 'N') &&
354da2e3ebdSchin ((c = GET(s)) == 'i' || c == 'I') &&
355da2e3ebdSchin ((c = GET(s)) == 't' || c == 'T') &&
356da2e3ebdSchin ((c = GET(s)) == 'y' || c == 'Y'))
357da2e3ebdSchin {
358da2e3ebdSchin c = GET(s);
359da2e3ebdSchin SET(s, t, b);
360da2e3ebdSchin }
361da2e3ebdSchin REV(s, t, b);
362da2e3ebdSchin PUT(s);
363da2e3ebdSchin return negative ? -S2F_inf : S2F_inf;
364da2e3ebdSchin }
365da2e3ebdSchin else if (c == 'n' || c == 'N')
366da2e3ebdSchin {
367da2e3ebdSchin if ((c = GET(s)) != 'a' && c != 'A' ||
368da2e3ebdSchin (c = GET(s)) != 'n' && c != 'N')
369da2e3ebdSchin {
370da2e3ebdSchin REV(s, t, b);
371da2e3ebdSchin PUT(s);
372da2e3ebdSchin return 0;
373da2e3ebdSchin }
374da2e3ebdSchin do c = GET(s); while (c && !isspace(c));
375da2e3ebdSchin PUT(s);
3767c2fbfb3SApril Chin return negative ? -S2F_nan : S2F_nan;
377da2e3ebdSchin }
378da2e3ebdSchin else if (c < '1' || c > '9')
379da2e3ebdSchin {
380da2e3ebdSchin REV(s, t, b);
381da2e3ebdSchin PUT(s);
382da2e3ebdSchin NON(s);
383da2e3ebdSchin return 0;
384da2e3ebdSchin }
385da2e3ebdSchin
386da2e3ebdSchin /*
387da2e3ebdSchin * consume the integral and fractional parts
388da2e3ebdSchin */
389da2e3ebdSchin
390da2e3ebdSchin n = 0;
391da2e3ebdSchin m = 0;
392da2e3ebdSchin for (;;)
393da2e3ebdSchin {
394da2e3ebdSchin if (c >= '0' && c <= '9')
395da2e3ebdSchin {
396da2e3ebdSchin digits++;
397da2e3ebdSchin n = (n << 3) + (n << 1) + (c - '0');
398da2e3ebdSchin if (n >= ((~((S2F_batch)0)) / 10) && part < elementsof(parts))
399da2e3ebdSchin {
400da2e3ebdSchin parts[part].batch = n;
401da2e3ebdSchin n = 0;
402da2e3ebdSchin parts[part].digits = digits;
403da2e3ebdSchin part++;
404da2e3ebdSchin }
405da2e3ebdSchin }
406da2e3ebdSchin else if (m && (digits - m) != 3)
407da2e3ebdSchin break;
408da2e3ebdSchin else if (c == decimal)
409da2e3ebdSchin {
410da2e3ebdSchin decimal = -1;
411da2e3ebdSchin thousand = -1;
412da2e3ebdSchin m = 0;
413da2e3ebdSchin fraction = digits;
414da2e3ebdSchin }
415da2e3ebdSchin else if (c != thousand)
416da2e3ebdSchin break;
417da2e3ebdSchin else if (!(m = digits))
418da2e3ebdSchin break;
419da2e3ebdSchin c = GET(s);
420da2e3ebdSchin }
421da2e3ebdSchin
422da2e3ebdSchin /*
423da2e3ebdSchin * don't forget the last part
424da2e3ebdSchin */
425da2e3ebdSchin
426da2e3ebdSchin if (n && part < elementsof(parts))
427da2e3ebdSchin {
428da2e3ebdSchin parts[part].batch = n;
429da2e3ebdSchin parts[part].digits = digits;
430da2e3ebdSchin part++;
431da2e3ebdSchin }
432da2e3ebdSchin
433da2e3ebdSchin /*
434da2e3ebdSchin * consume the exponent
435da2e3ebdSchin */
436da2e3ebdSchin
437da2e3ebdSchin if (fraction >= 0)
438da2e3ebdSchin digits = fraction;
439da2e3ebdSchin if (c == 'e' || c == 'E')
440da2e3ebdSchin {
441da2e3ebdSchin c = GET(s);
442da2e3ebdSchin if ((enegative = (c == '-')) || c == '+')
443da2e3ebdSchin c = GET(s);
444da2e3ebdSchin n = 0;
445da2e3ebdSchin while (c >= '0' && c <= '9')
446da2e3ebdSchin {
447da2e3ebdSchin n = (n << 3) + (n << 1) + (c - '0');
448da2e3ebdSchin c = GET(s);
449da2e3ebdSchin }
450da2e3ebdSchin if (enegative)
451da2e3ebdSchin digits -= n;
452da2e3ebdSchin else
453da2e3ebdSchin digits += n;
454da2e3ebdSchin }
455da2e3ebdSchin
45634f9b3eeSRoland Mainz #if S2F_qualifier
45734f9b3eeSRoland Mainz
458da2e3ebdSchin /*
459da2e3ebdSchin * consume the optional suffix
460da2e3ebdSchin */
461da2e3ebdSchin
462da2e3ebdSchin switch (c)
463da2e3ebdSchin {
464da2e3ebdSchin case 'f':
465da2e3ebdSchin case 'F':
466da2e3ebdSchin case 'l':
467da2e3ebdSchin case 'L':
468da2e3ebdSchin c = GET(s);
469da2e3ebdSchin break;
470da2e3ebdSchin }
47134f9b3eeSRoland Mainz #endif
472da2e3ebdSchin PUT(s);
473da2e3ebdSchin
474da2e3ebdSchin /*
475da2e3ebdSchin * adjust for at most one multiply per part
476da2e3ebdSchin * and at most one divide overall
477da2e3ebdSchin */
478da2e3ebdSchin
4797c2fbfb3SApril Chin v = 0;
480da2e3ebdSchin if (!part)
4817c2fbfb3SApril Chin return negative ? -v : v;
482da2e3ebdSchin else if ((m = parts[part-1].digits - digits) > 0)
483da2e3ebdSchin digits += m;
484da2e3ebdSchin else
485da2e3ebdSchin m = 0;
486da2e3ebdSchin
487da2e3ebdSchin /*
488da2e3ebdSchin * combine the parts
489da2e3ebdSchin */
490da2e3ebdSchin
491da2e3ebdSchin while (part--)
492da2e3ebdSchin {
493da2e3ebdSchin p = parts[part].batch;
494da2e3ebdSchin c = digits - parts[part].digits;
495da2e3ebdSchin if (c > S2F_exp_10_max)
496da2e3ebdSchin {
497da2e3ebdSchin ERR(ERANGE);
498da2e3ebdSchin return negative ? -S2F_inf : S2F_inf;
499da2e3ebdSchin }
500da2e3ebdSchin if (c > 0)
501da2e3ebdSchin {
502da2e3ebdSchin #if _ast_mpy_overflow_fpe
503da2e3ebdSchin if ((S2F_max / p) < S2F_pow10[c])
504da2e3ebdSchin {
505da2e3ebdSchin ERR(ERANGE);
506da2e3ebdSchin return negative ? -S2F_inf : S2F_inf;
507da2e3ebdSchin }
508da2e3ebdSchin #endif
509da2e3ebdSchin p *= S2F_pow10[c];
510da2e3ebdSchin }
511da2e3ebdSchin v += p;
512da2e3ebdSchin }
513da2e3ebdSchin if (m)
514da2e3ebdSchin {
515da2e3ebdSchin while (m > S2F_exp_10_max)
516da2e3ebdSchin {
517da2e3ebdSchin m -= S2F_exp_10_max;
518da2e3ebdSchin v /= S2F_pow10[S2F_exp_10_max];
519da2e3ebdSchin }
520da2e3ebdSchin #if _ast_div_underflow_fpe
521da2e3ebdSchin if ((S2F_min * p) > S2F_pow10[c])
522da2e3ebdSchin {
523da2e3ebdSchin ERR(ERANGE);
524da2e3ebdSchin return negative ? -S2F_inf : S2F_inf;
525da2e3ebdSchin }
526da2e3ebdSchin #endif
527da2e3ebdSchin v /= S2F_pow10[m];
528da2e3ebdSchin }
529da2e3ebdSchin
530da2e3ebdSchin /*
531da2e3ebdSchin * check the range
532da2e3ebdSchin */
533da2e3ebdSchin
534da2e3ebdSchin check:
535da2e3ebdSchin if (v < S2F_min)
536da2e3ebdSchin {
537da2e3ebdSchin ERR(ERANGE);
538da2e3ebdSchin v = 0;
539da2e3ebdSchin }
540da2e3ebdSchin else if (v > S2F_max)
541da2e3ebdSchin {
542da2e3ebdSchin ERR(ERANGE);
543da2e3ebdSchin v = S2F_inf;
544da2e3ebdSchin }
545da2e3ebdSchin
546da2e3ebdSchin /*
547da2e3ebdSchin * done
548da2e3ebdSchin */
549da2e3ebdSchin
550da2e3ebdSchin return negative ? -v : v;
551da2e3ebdSchin }
552