summaryrefslogtreecommitdiff
path: root/libkern/charstod.c
diff options
context:
space:
mode:
authorCharles Forsyth <charles.forsyth@gmail.com>2014-06-30 10:57:08 +0100
committerCharles Forsyth <charles.forsyth@gmail.com>2014-06-30 10:57:08 +0100
commit3cd4f1d15146c08f05206d6328ecbc1c7fdc8dfa (patch)
treea546acadca10b43d6b5eafc6d85f4aed361e9988 /libkern/charstod.c
parentee030d07b2cf167be70f1dc36f56bdf3012860ae (diff)
update to match lib9
Diffstat (limited to 'libkern/charstod.c')
-rw-r--r--libkern/charstod.c96
1 files changed, 54 insertions, 42 deletions
diff --git a/libkern/charstod.c b/libkern/charstod.c
index 203e5379..10d0b220 100644
--- a/libkern/charstod.c
+++ b/libkern/charstod.c
@@ -1,4 +1,4 @@
-#include <lib9.h>
+#include "lib9.h"
/*
* Reads a floating-point number by interpreting successive characters
@@ -7,62 +7,74 @@
* necessary to back up the input stream up one byte after calling charstod.
*/
+#define ADVANCE *s++ = c; if(s>=e) return NaN(); c = (*f)(vp)
+
double
charstod(int(*f)(void*), void *vp)
{
- double num, dem;
- int neg, eneg, dig, exp, c;
-
- num = 0;
- neg = 0;
- dig = 0;
- exp = 0;
- eneg = 0;
+ char str[400], *s, *e, *start;
+ int c;
+ s = str;
+ e = str + sizeof str - 1;
c = (*f)(vp);
while(c == ' ' || c == '\t')
c = (*f)(vp);
if(c == '-' || c == '+'){
- if(c == '-')
- neg = 1;
- c = (*f)(vp);
+ ADVANCE;
}
+ start = s;
while(c >= '0' && c <= '9'){
- num = num*10 + c-'0';
- c = (*f)(vp);
+ ADVANCE;
}
- if(c == '.')
- c = (*f)(vp);
- while(c >= '0' && c <= '9'){
- num = num*10 + c-'0';
- dig++;
- c = (*f)(vp);
+ if(c == '.'){
+ ADVANCE;
+ while(c >= '0' && c <= '9'){
+ ADVANCE;
+ }
}
- if(c == 'e' || c == 'E'){
- c = (*f)(vp);
+ if(s > start && (c == 'e' || c == 'E')){
+ ADVANCE;
if(c == '-' || c == '+'){
- if(c == '-'){
- dig = -dig;
- eneg = 1;
- }
- c = (*f)(vp);
+ ADVANCE;
}
while(c >= '0' && c <= '9'){
- exp = exp*10 + c-'0';
- c = (*f)(vp);
+ ADVANCE;
}
+ }else if(s == start && (c == 'i' || c == 'I')){
+ ADVANCE;
+ if(c != 'n' && c != 'N')
+ return NaN();
+ ADVANCE;
+ if(c != 'f' && c != 'F')
+ return NaN();
+ ADVANCE;
+ if(c != 'i' && c != 'I')
+ return NaN();
+ ADVANCE;
+ if(c != 'n' && c != 'N')
+ return NaN();
+ ADVANCE;
+ if(c != 'i' && c != 'I')
+ return NaN();
+ ADVANCE;
+ if(c != 't' && c != 'T')
+ return NaN();
+ ADVANCE;
+ if(c != 'y' && c != 'Y')
+ return NaN();
+ ADVANCE; /* so caller can back up uniformly */
+ USED(c);
+ }else if(s == str && (c == 'n' || c == 'N')){
+ ADVANCE;
+ if(c != 'a' && c != 'A')
+ return NaN();
+ ADVANCE;
+ if(c != 'n' && c != 'N')
+ return NaN();
+ ADVANCE; /* so caller can back up uniformly */
+ USED(c);
}
- exp -= dig;
- if(exp < 0){
- exp = -exp;
- eneg = !eneg;
- }
- dem = pow10(exp);
- if(eneg)
- num /= dem;
- else
- num *= dem;
- if(neg)
- return -num;
- return num;
+ *s = 0;
+ return strtod(str, &s);
}