summaryrefslogtreecommitdiff
path: root/src/stdlib
diff options
context:
space:
mode:
Diffstat (limited to 'src/stdlib')
-rw-r--r--src/stdlib/strtod.c11
-rw-r--r--src/stdlib/strtof.c11
-rw-r--r--src/stdlib/strtold.c103
3 files changed, 31 insertions, 94 deletions
diff --git a/src/stdlib/strtod.c b/src/stdlib/strtod.c
index 388058fe..98b992a1 100644
--- a/src/stdlib/strtod.c
+++ b/src/stdlib/strtod.c
@@ -1,6 +1,15 @@
#include <stdlib.h>
+#include "floatscan.h"
+#include "stdio_impl.h"
double strtod(const char *s, char **p)
{
- return strtold(s, p);
+ FILE f = {
+ .buf = (void *)s, .rpos = (void *)s,
+ .rend = (void *)-1, .lock = -1
+ };
+ off_t cnt;
+ double y = __floatscan(&f, -1, 1, 1, &cnt);
+ if (p) *p = (char *)s + cnt;
+ return y;
}
diff --git a/src/stdlib/strtof.c b/src/stdlib/strtof.c
index 07b32df4..2dc349a9 100644
--- a/src/stdlib/strtof.c
+++ b/src/stdlib/strtof.c
@@ -1,6 +1,15 @@
#include <stdlib.h>
+#include "floatscan.h"
+#include "stdio_impl.h"
float strtof(const char *s, char **p)
{
- return strtold(s, p);
+ FILE f = {
+ .buf = (void *)s, .rpos = (void *)s,
+ .rend = (void *)-1, .lock = -1
+ };
+ off_t cnt;
+ float y = __floatscan(&f, -1, 0, 1, &cnt);
+ if (p) *p = (char *)s + cnt;
+ return y;
}
diff --git a/src/stdlib/strtold.c b/src/stdlib/strtold.c
index ec464c15..40ecc122 100644
--- a/src/stdlib/strtold.c
+++ b/src/stdlib/strtold.c
@@ -1,96 +1,15 @@
#include <stdlib.h>
-#include <errno.h>
-#include <ctype.h>
+#include "floatscan.h"
+#include "stdio_impl.h"
-static int valid_exp(const unsigned char *s)
+long double strtold(const char *s, char **p)
{
- return isdigit(*s) || ((s[0]=='+'||s[0]=='-') && isdigit(s[1]));
-}
-
-long double strtold(const char *s1, char **p)
-{
- const unsigned char *s = (void *)s1;
- long double x = 0;
- long double frac;
- int sign = 0;
- int nonzero = 0;
- int radix = '.';
- long e;
- int saved_errno = errno;
-
- if (!p) p = (char **)&s1;
-
- /* Initial whitespace */
- for (; isspace(*s); s++);
-
- /* Optional sign */
- if (*s == '-') sign = *s++;
- else if (*s == '+') s++;
-
- /* Handle infinities and NaNs. */
- if ((s[0]|32)=='i' && (s[1]|32)=='n' && (s[2]|32)=='f') {
- *p = (char *)s + 3;
- return sign ? -1.0/0.0 : 1.0/0.0;
- } else if ((s[0]|32)=='n' && (s[1]|32)=='a' && (s[2]|32)=='n') {
- *p = (char *)s + 3;
- return 0.0/0.0;
- }
-
- /* Possible hex float */
- if (s[0]=='0' && (s[1]|32)=='x') {
- /* Mantissa must be non-degenerate */
- if (!isxdigit(s[2]) && (s[2]!=radix || !isxdigit(s[3]))) {
- /* Decimal float 0, 'x' extraneous */
- *p = (char *)++s;
- return 0;
- }
- /* We have a real hex float */
- s += 2;
- for (; isxdigit(*s); s++) {
- x = 16*x + (isdigit(*s)?*s-'0':(*s|32)-'a'+10);
- if (*s!='0') nonzero=1;
- }
- if (*s == radix) {
- frac = 1.0/16.0;
- for (s++; isxdigit(*s); s++) {
- x += frac * (isdigit(*s)?*s-'0':(*s|32)-'a'+10);
- frac *= 1.0/16.0;
- if (*s!='0') nonzero=1;
- }
- }
- if ((*s|32) == 'p' && valid_exp(s+1)) {
- e = strtol((void *)(s+1), (void *)&s, 10);
- for (; e>0; e--) x *= 2.0;
- for (; e<0; e++) x *= 0.5;
- }
- goto finish;
- }
-
- /* Mantissa must be non-degenerate */
- if (!isdigit(s[0]) && (s[0]!=radix || !isdigit(s[1]))) {
- *p = (char *)s1;
- return 0;
- }
-
- for (; isdigit(*s); s++) {
- x = 10*x + *s-'0';
- if (*s!='0') nonzero=1;
- }
- if (*s == radix) {
- frac = 10.0;
- for (s++; isdigit(*s); s++) {
- x += (*s-'0') / frac;
- frac *= 10.0;
- if (*s!='0') nonzero=1;
- }
- }
- if ((*s|32)=='e' && valid_exp(s+1)) {
- e = strtol((void *)++s, (void *)&s, 10);
- for (; e>0; e--) x *= 10.0;
- for (; e<0; e++) x /= 10.0;
- }
-finish:
- errno = ((nonzero && !x) || !(1.0/x)) ? ERANGE : saved_errno;
- *p = (char*)s;
- return sign ? -x : x;
+ FILE f = {
+ .buf = (void *)s, .rpos = (void *)s,
+ .rend = (void *)-1, .lock = -1
+ };
+ off_t cnt;
+ long double y = __floatscan(&f, -1, 2, 1, &cnt);
+ if (p) *p = (char *)s + cnt;
+ return y;
}