summaryrefslogtreecommitdiffstats
path: root/mdk-stage1/dietlibc/lib/strtod.c
diff options
context:
space:
mode:
Diffstat (limited to 'mdk-stage1/dietlibc/lib/strtod.c')
-rw-r--r--mdk-stage1/dietlibc/lib/strtod.c104
1 files changed, 59 insertions, 45 deletions
diff --git a/mdk-stage1/dietlibc/lib/strtod.c b/mdk-stage1/dietlibc/lib/strtod.c
index cbe983d84..5d50cc535 100644
--- a/mdk-stage1/dietlibc/lib/strtod.c
+++ b/mdk-stage1/dietlibc/lib/strtod.c
@@ -1,52 +1,66 @@
#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
-extern char isspace(char c);
-
-#ifdef __GNUC__
-static inline char isdigit(char c) { return (c>='0' && c<='9'); }
-#endif
-
-double strtod(const char *nptr, char **endptr) {
- double d=0;
- register const char *c=nptr;
- char neg=0;
- while (*c && isspace(*c)) ++c;
- switch (*c) {
- case '-': neg=1;
- case '+': c++; break;
- default: break;
- }
- while (isdigit(*c)) {
- d=d*10+(*c-'0');
- ++c;
- }
- if (*c=='.') {
- double factor=.1;
- while (isdigit(*++c)) {
- d=d+(factor*(*c-'0'));
- factor/=10;
+double strtod(const char* s, char** endptr) {
+ register const char* p = s;
+ register long double value = 0.L;
+ int sign = +1;
+ long double factor;
+ unsigned int expo;
+
+ while ( isspace(*p) )
+ p++;
+
+ switch (*p) {
+ case '-': sign = -1;
+ case '+': p++;
+ default : break;
}
- }
- if ((*c|32)=='e') {
- int exp=0;
- double factor=10;
- if (c[1]<'0') {
- switch (c[1]) {
- case '-': factor=0.1;
- case '+': c++; break;
- default:
- d=0;
- c=nptr;
- goto done;
- }
+
+ while ( (unsigned int)(*p - '0') < 10u )
+ value = value*10 + (*p++ - '0');
+
+ if ( *p == '.' ) {
+ factor = 1.;
+
+ p++;
+ while ( (unsigned int)(*p - '0') < 10u ) {
+ factor *= 0.1;
+ value += (*p++ - '0') * factor;
+ }
}
- while (isdigit(*++c))
- exp=exp*10+(*c-'0');
- while (exp) { /* XXX: this introduces rounding errors */
- d*=factor; --exp;
+
+ if ( (*p | 32) == 'e' ) {
+ expo = 0;
+ factor = 10.L;
+
+ switch (*++p) { // ja hier weiß ich nicht, was mindestens nach einem 'E' folgenden MUSS.
+ case '-': factor = 0.1;
+ case '+': p++;
+ break;
+ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
+ break;
+ default : value = 0.L;
+ p = s;
+ goto done;
+ }
+
+ while ( (unsigned int)(*p - '0') < 10u )
+ expo = 10 * expo + (*p++ - '0');
+
+ while ( 1 ) {
+ if ( expo & 1 )
+ value *= factor;
+ if ( (expo >>= 1) == 0 )
+ break;
+ factor *= factor;
+ }
}
- }
+
done:
- if (endptr) *endptr=(char*)c;
- return d;
+ if ( endptr != NULL )
+ *endptr = (char*)p;
+
+ return value * sign;
}