initial check-in, version 0.5.0
[musl] / src / stdlib / strtold.c
1 #include <stdlib.h>
2 #include <errno.h>
3 #include <ctype.h>
4
5 long double strtold(const char *s1, char **p)
6 {
7         const unsigned char *s = s1;
8         long double x = 0;
9         long double frac;
10         int sign = 0;
11         int nonzero = 0;
12         int radix = '.';
13         long e;
14
15         if (!p) p = (char **)&s1;
16
17         /* Initial whitespace */
18         for (; isspace(*s); s++);
19
20         /* Optional sign */
21         if (*s == '-') sign = *s++;
22         else if (*s == '+') s++;
23
24         /* Handle infinities and NaNs. */
25         if ((s[0]|32)=='i' && (s[1]|32)=='n' && (s[2]|32)=='f') {
26                 *p = (char *)s + 3;
27                 return sign ? -1.0/0.0 : 1.0/0.0;
28         } else if ((s[0]|32)=='n' && (s[1]|32)=='a' && (s[2]|32)=='n') {
29                 *p = (char *)s + 3;
30                 return 0.0/0.0;
31         }
32
33         /* Possible hex float */
34         if (s[0]=='0' && (s[1]|32)=='x') {
35                 /* Mantissa must be non-degenerate */
36                 if (!isxdigit(s[2]) && (s[2]!=radix || !isxdigit(s[3]))) {
37                         /* Decimal float 0, 'x' extraneous */
38                         *p = (char *)++s;
39                         return 0;
40                 }
41                 /* We have a real hex float */
42                 s += 2;
43                 for (; isxdigit(*s); s++) {
44                         x = 16*x + (isdigit(*s)?*s-'0':(*s|32)-'a');
45                         if (*s!='0') nonzero=1;
46                 }
47                 if (*s == radix) {
48                         frac = 1.0/16.0;
49                         for (s++; isxdigit(*s); s++) {
50                                 x += frac * (isdigit(*s)?*s-'0':(*s|32)-'a');
51                                 frac *= 1.0/16.0;
52                                 if (*s!='0') nonzero=1;
53                         }
54                 }
55                 if ((*s|32) == 'p') {
56                         e = strtol(s+1, (void *)&s, 10);
57                         for (; e>0; e--) x *= 2.0;
58                         for (; e<0; e++) x *= 0.5;
59                 }
60                 if ((nonzero && !x) || !(1.0/x))
61                         errno = ERANGE;
62                 *p = (char *)s;
63                 return sign ? -x : x;
64         }
65
66         /* Mantissa must be non-degenerate */
67         if (!isdigit(s[0]) && (s[0]!=radix || !isdigit(s[1]))) {
68                 *p = (char *)s1;
69                 return 0;
70         }
71
72         for (; isdigit(*s); s++) {
73                 x = 10*x + *s-'0';
74                 if (*s!='0') nonzero=1;
75         }
76         if (*s == radix) {
77                 frac = 10.0;
78                 for (s++; isdigit(*s); s++) {
79                         x += (*s-'0') / frac;
80                         frac *= 10.0;
81                         if (*s!='0') nonzero=1;
82                 }
83         }
84         if ((*s|32)=='e') {
85                 e = strtol(++s, (void *)&s, 10);
86                 for (; e>0; e--) x *= 10.0;
87                 for (; e<0; e++) x /= 10.0;
88         }
89         if ((nonzero && !x) || !(1.0/x))
90                 errno = ERANGE;
91         *p = (char*)s;
92         return sign ? -x : x;
93 }