summaryrefslogtreecommitdiff
path: root/lib9/charstod.c
diff options
context:
space:
mode:
authorCharles Forsyth <charles.forsyth@gmail.com>2013-06-06 21:01:19 +0000
committerCharles Forsyth <charles.forsyth@gmail.com>2013-06-06 21:01:19 +0000
commit7ded4a527bdfd0e8b3a9049955f2af89e5f039ee (patch)
tree7ee0f03dd4e5cad072bc0c816468ebfd0dd17c67 /lib9/charstod.c
parent8bdf904b6a23b93336ae2837772110bcdad234ce (diff)
sync with Plan 9
Diffstat (limited to 'lib9/charstod.c')
-rw-r--r--lib9/charstod.c94
1 files changed, 53 insertions, 41 deletions
diff --git a/lib9/charstod.c b/lib9/charstod.c
index 53140695..10d0b220 100644
--- a/lib9/charstod.c
+++ b/lib9/charstod.c
@@ -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);
}