Added strtod.c, use it in atof
authorceriel <none@none>
Thu, 11 Aug 1988 12:49:06 +0000 (12:49 +0000)
committerceriel <none@none>
Thu, 11 Aug 1988 12:49:06 +0000 (12:49 +0000)
lang/cem/libcc/gen/LIST
lang/cem/libcc/gen/atof.c
lang/cem/libcc/gen/strtod.c [new file with mode: 0644]

index 97fac09..cbb4adf 100644 (file)
@@ -1,6 +1,7 @@
 tail_cc.2g.a
 abs.c
 atof.c
+strtod.c
 atoi.c
 atol.c
 bcmp.c
index 256db5e..80f84ba 100644 (file)
@@ -1,81 +1,12 @@
 /* $Header$ */
 #ifndef NOFLOAT
-#include <ctype.h>
 
-extern double ldexp();
+extern double strtod();
 
 double
 atof(p)
        register char *p;
 {
-       register int c;
-       int exp = 0, sign = 1, expsign = 0;
-       double fl;
-       double big = (double)(1L << 30) * (1L << 22);
-
-       while (isspace(*p)) p++;
-       c = *p;
-
-       switch (c) {
-       case '-':
-               sign = -1;
-       case '+': 
-               p++;
-       }
-
-       fl = 0.0;
-       while (isdigit(c = *p++)) {
-               if (fl < big)
-                       fl = 10.0 * fl + (double)(c - '0');
-               else
-                       exp++;
-       }
-       if (c == '.') {
-               while (isdigit(c = *p++)) {
-                       if (fl < big) {
-                               fl = 10.0 * fl + (double) (c - '0');
-                               exp--;
-                       }
-               }
-       }
-       if (fl == 0) return 0;
-       if (c == 'E' || c == 'e') {
-               int exp1 = 0;
-               int sign = 1;
-
-               switch (*p) {
-               case '-':
-                       sign = -1;
-               case '+':
-                       p++;
-               }
-               while (isdigit(c = *p++)) {
-                       exp1 = 10 * exp1 + c - '0';
-               }
-               exp += sign * exp1;
-       }
-
-       if (exp < 0) {
-               expsign = 1;
-               exp = -exp;
-       }
-
-       if (exp != 0) {
-               int oldexp = exp;
-               double exp5 = 5.0;
-               double correction = 1.0;
-
-               while (exp) {
-                       if (exp % 2) correction *= exp5;
-                       exp /= 2;
-                       if (exp != 0) exp5 *= exp5;
-               }
-               if (expsign) fl = fl / correction;
-               else    fl = fl * correction;
-
-               fl = ldexp(fl, expsign ? -oldexp : oldexp);
-       }
-
-       return sign * fl;
+       return strtod(p, (char **) 0);
 }
 #endif
diff --git a/lang/cem/libcc/gen/strtod.c b/lang/cem/libcc/gen/strtod.c
new file mode 100644 (file)
index 0000000..88370ad
--- /dev/null
@@ -0,0 +1,97 @@
+/* $Header$ */
+#ifndef NOFLOAT
+#include <ctype.h>
+
+extern double ldexp();
+
+#define MAX    (0x7fffffffL/10)
+
+double
+strtod(p, pp)
+       register char *p;
+       char **pp;
+{
+       register int c;
+       int exp = 0, sign = 1, expsign = 0;
+       double fl;
+       long lowl = 0, highl = 0, pos = 1;
+       int dotseen = 0;
+       int digitseen = 0;
+
+       if (pp) *pp = p;
+       while (isspace(*p)) p++;
+       c = *p;
+
+       switch (c) {
+       case '-':
+               sign = -1;
+       case '+': 
+               p++;
+       }
+
+       while (isdigit(c = *p++) || (c == '.' && ! dotseen++)) {
+               if (c == '.') continue;
+               digit_seen = 1;
+               if (highl < MAX) {
+                       highl = (highl << 3) + (highl << 1) + (c - '0');
+               }
+               else if (pos < MAX) {
+                       pos = (pos << 3) + (pos << 1);
+                       lowl = (lowl << 3) + (lowl << 1) + (c - '0');
+               }
+               else exp++;
+               if (dotseen) exp--;
+       }
+       if (! digit_seen) return 0.0;
+       fl = highl;
+       if (pos > 1) {
+               fl = pos * fl + lowl;
+       }
+
+       if (pp) *pp = p-1;
+
+       if (c == 'E' || c == 'e') {
+               int exp1 = 0;
+               int sign = 1;
+
+               switch (*p) {
+               case '-':
+                       sign = -1;
+               case '+':
+                       p++;
+               }
+               if (isdigit(c = *p)) {
+                       do {
+                               exp1 = 10 * exp1 + c - '0';
+                       } while (isdigit(c = *++p));
+                       if (pp) *pp = p;
+               }
+               exp += sign * exp1;
+       }
+
+       if (fl == 0.0) return 0.0;
+
+       if (exp < 0) {
+               expsign = 1;
+               exp = -exp;
+       }
+
+       if (exp != 0) {
+                int oldexp = exp;
+                double exp5 = 5.0;
+                double correction = 1.0;
+                while (exp) {
+                        if (exp % 2) correction *= exp5;
+                        exp /= 2;
+                        if (exp != 0) exp5 *= exp5;
+                }
+                if (expsign) fl = fl / correction;
+                else    fl = fl * correction;
+                fl = ldexp(fl, expsign ? -oldexp : oldexp);
+       }
+
+       return sign * fl;
+}
+#endif