1
#include <ctype.h>
2
#include <errno.h>
3
#include <float.h>
4
#include <stdbool.h>
5
#include <stdlib.h>
6
7
static long double _ld_abs(long double value) {
8
return value < 0.0L ? -value : value;
9
}10
11
long double strtold(char const *restrict str, char **restrict endptr) {
12
if (!str) {
13
errno = EINVAL;
14
if (endptr) {
15
*endptr = NULL;
16
}17
return 0.0L;
18
}19
20
const char *cursor = str;
21
while (isspace((unsigned char)*cursor)) {
22
cursor++;
23
}24
25
int sign = 1;
26
if (*cursor == '+' || *cursor == '-') {
27
if (*cursor == '-') {
28
sign = -1;
29
}30
cursor++;
31
}32
33
long double value = 0.0L;
34
bool has_digits = false;
35
36
while (isdigit((unsigned char)*cursor)) {
37
has_digits = true;
38
value = value * 10.0L + (long double)(*cursor - '0');
39
cursor++;
40
}41
42
if (*cursor == '.') {
43
long double scale = 0.1L;
44
cursor++;
45
46
while (isdigit((unsigned char)*cursor)) {
47
has_digits = true;
48
value += (long double)(*cursor - '0') * scale;
49
scale *= 0.1L;
50
cursor++;
51
}52
}53
54
if (!has_digits) {
55
if (endptr) {
56
*endptr = (char *)str;
57
}58
return 0.0L;
59
}60
61
int exp_sign = 1;
62
int exp_value = 0;
63
64
const char *exp_mark = cursor;
65
if (*cursor == 'e' || *cursor == 'E') {
66
cursor++;
67
68
if (*cursor == '+' || *cursor == '-') {
69
if (*cursor == '-') {
70
exp_sign = -1;
71
}72
cursor++;
73
}74
75
const char *exp_start = cursor;
76
while (isdigit((unsigned char)*cursor)) {
77
if (exp_value < 1000000) {
78
exp_value = exp_value * 10 + (*cursor - '0');
79
}80
cursor++;
81
}82
83
if (cursor == exp_start) {
84
cursor = exp_mark;
85
exp_value = 0;
86
exp_sign = 1;
87
}88
}89
90
int exponent = exp_sign * exp_value;
91
bool overflow = false;
92
bool underflow = false;
93
94
if (exponent > 0) {
95
for (int i = 0; i < exponent; i++) {
96
if (value > LDBL_MAX / 10.0L) {
97
value = LDBL_MAX;
98
overflow = true;
99
break;
100
}101
102
value *= 10.0L;
103
}104
} else if (exponent < 0) {
105
for (int i = exponent; i < 0; i++) {
106
value /= 10.0L;
107
if (value != 0.0L && _ld_abs(value) < LDBL_MIN) {
108
underflow = true;
109
}110
}111
}112
113
if (overflow || underflow) {
114
errno = ERANGE;
115
}116
117
if (endptr) {
118
*endptr = (char *)cursor;
119
}120
121
return sign < 0 ? -value : value;
122
}123
124
double strtod(char const *restrict str, char **restrict endptr) {
125
long double value = strtold(str, endptr);
126
long double abs_value = _ld_abs(value);
127
128
if (abs_value > (long double)DBL_MAX) {
129
errno = ERANGE;
130
return value < 0 ? -DBL_MAX : DBL_MAX;
131
}132
133
if (abs_value != 0.0L && abs_value < (long double)DBL_MIN) {
134
errno = ERANGE;
135
}136
137
return (double)value;
138
}139
140
float strtof(char const *restrict str, char **restrict endptr) {
141
long double value = strtold(str, endptr);
142
long double abs_value = _ld_abs(value);
143
144
if (abs_value > (long double)FLT_MAX) {
145
errno = ERANGE;
146
return value < 0 ? -FLT_MAX : FLT_MAX;
147
}148
149
if (abs_value != 0.0L && abs_value < (long double)FLT_MIN) {
150
errno = ERANGE;
151
}152
153
return (float)value;
154
}155
156
double atof(char const *str) {
157
return strtod(str, NULL);
158
}