]> granicus.if.org Git - php/commitdiff
use BSD licensed implementation of double-to-string utilities instead of LGPL one
authorAntony Dovgal <tony2001@php.net>
Wed, 6 Dec 2006 09:50:28 +0000 (09:50 +0000)
committerAntony Dovgal <tony2001@php.net>
Wed, 6 Dec 2006 09:50:28 +0000 (09:50 +0000)
this patch also fixes thread safety issues in zend_strtod()

Zend/zend.c
Zend/zend_strtod.c
Zend/zend_strtod.h
ext/standard/formatted_print.c
ext/standard/tests/serialize/003.phpt
ext/standard/tests/strings/sprintf_f.phpt
main/snprintf.c
main/snprintf.h
main/spprintf.c

index 23ac1e13af5f853203e7764dc718d52b93955581..3e919d38d0d2b9b9a158163b7351babc769caff8 100644 (file)
@@ -994,6 +994,7 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions, i
        fpsetmask(0);
 #endif
 
+       zend_startup_strtod();
        zend_startup_extensions_mechanism();
 
        /* Set up utility functions and values */
@@ -1177,6 +1178,7 @@ void zend_shutdown(TSRMLS_D)
 
        zend_hash_destroy(GLOBAL_CONSTANTS_TABLE);
        free(GLOBAL_CONSTANTS_TABLE);
+       zend_shutdown_strtod();
 
 #ifdef ZTS
        GLOBAL_FUNCTION_TABLE = NULL;
index 6c2c3ba560c52b127eab45fa7e4e421f77dcd8af..e7414da34c910dadd5c191656382571cb5902d7a 100644 (file)
  ***************************************************************/
 
 /* Please send bug reports to
-       David M. Gay
-       AT&T Bell Laboratories, Room 2C-463
-       600 Mountain Avenue
-       Murray Hill, NJ 07974-2070
-       U.S.A.
-       dmg@research.att.com or research!dmg
- */
+   David M. Gay
+   AT&T Bell Laboratories, Room 2C-463
+   600 Mountain Avenue
+   Murray Hill, NJ 07974-2070
+   U.S.A.
+   dmg@research.att.com or research!dmg
  */
 
 /* strtod for IEEE-, VAX-, and IBM-arithmetic machines.
  *
 #include <zend.h>
 #include <unicode/utypes.h>
 #include <unicode/ustdio.h>
+#include <zend_strtod.h>
+
+#ifdef ZTS
+#include <TSRM.h>
+#endif
+
+#include <stddef.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
 
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
@@ -127,10 +144,10 @@ typedef unsigned long int uint32_t;
 
 #if defined(__arm__) && !defined(__VFP_FP__)
 /*
- * Although the CPU is little endian the FP has different
- * byte and word endianness. The byte order is still little endian
- * but the word order is big endian.
- */
+ *  * Although the CPU is little endian the FP has different
+ *   * byte and word endianness. The byte order is still little endian
+ *    * but the word order is big endian.
+ *     */
 #define IEEE_BIG_ENDIAN
 #undef IEEE_LITTLE_ENDIAN
 #endif
@@ -145,8 +162,8 @@ typedef unsigned long int uint32_t;
 #define IEEE_LITTLE_ENDIAN
 #endif
 
-#define Long   int32_t
-#define ULong  uint32_t
+#define Long    int32_t
+#define ULong   uint32_t
 
 #ifdef __cplusplus
 #include "malloc.h"
@@ -210,6 +227,7 @@ extern void *MALLOC(size_t);
 #define DBL_MAX 1.7014118346046923e+38
 #endif
 
+
 #ifndef LONG_MAX
 #define LONG_MAX 2147483647
 #endif
@@ -220,9 +238,7 @@ extern void *MALLOC(size_t);
 #include "math.h"
 #endif
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+BEGIN_EXTERN_C()
 
 #ifndef CONST
 #ifdef KR_headers
@@ -239,15 +255,15 @@ extern "C" {
 #endif
 
 #if defined(IEEE_LITTLE_ENDIAN) + defined(IEEE_BIG_ENDIAN) + defined(VAX) + \
-    defined(IBM) != 1
-Exactly one of IEEE_LITTLE_ENDIAN IEEE_BIG_ENDIAN, VAX, or
-IBM should be defined.
+                   defined(IBM) != 1
+       Exactly one of IEEE_LITTLE_ENDIAN IEEE_BIG_ENDIAN, VAX, or
+       IBM should be defined.
 #endif
 
-typedef union {
-       double d;
-       ULong ul[2];
-} _double;
+       typedef union {
+                   double d;
+                           ULong ul[2];
+       } _double;
 #define value(x) ((x).d)
 #ifdef IEEE_LITTLE_ENDIAN
 #define word0(x) ((x).ul[1])
@@ -258,15 +274,15 @@ typedef union {
 #endif
 
 /* The following definition of Storeinc is appropriate for MIPS processors.
- * An alternative that might be better on some machines is
- * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff)
- */
+ *  * An alternative that might be better on some machines is
+ *   * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff)
+ *    */
 #if defined(IEEE_LITTLE_ENDIAN) + defined(VAX) + defined(__arm__)
 #define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \
-((unsigned short *)a)[0] = (unsigned short)c, a++)
+               ((unsigned short *)a)[0] = (unsigned short)c, a++)
 #else
 #define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \
-((unsigned short *)a)[1] = (unsigned short)c, a++)
+               ((unsigned short *)a)[1] = (unsigned short)c, a++)
 #endif
 
 /* #define P DBL_MANT_DIG */
@@ -315,7 +331,7 @@ typedef union {
 #define Bias 65
 #define Exp_1  0x41000000
 #define Exp_11 0x41000000
-#define Ebits 8        /* exponent has 7 bits, but 8 is the right value in b2d */
+#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */
 #define Frac_mask  0xffffff
 #define Frac_mask1 0xffffff
 #define Bletch 4
@@ -378,10 +394,10 @@ extern double rnd_prod(double, double), rnd_quot(double, double);
 
 #ifndef Just_16
 /* When Pack_32 is not defined, we store 16 bits per 32-bit Long.
- * This makes some inner loops simpler and sometimes saves work
- * during multiplications, but it often seems to make things slightly
- * slower.  Hence the default is now to store 32 bits per Long.
- */
+ *  * This makes some inner loops simpler and sometimes saves work
+ *   * during multiplications, but it often seems to make things slightly
+ *    * slower.  Hence the default is now to store 32 bits per Long.
+ *     */
 #ifndef Pack_32
 #define Pack_32
 #endif
@@ -389,65 +405,120 @@ extern double rnd_prod(double, double), rnd_quot(double, double);
 
 #define Kmax 15
 
- struct
-Bigint {
+struct Bigint {
        struct Bigint *next;
        int k, maxwds, sign, wds;
        ULong x[1];
-       };
+};
 
- typedef struct Bigint Bigint;
+typedef struct Bigint Bigint;
 
- static Bigint *freelist[Kmax+1];
+static Bigint *freelist[Kmax+1];
+static void destroy_freelist(void);
 
- static Bigint *
-Balloc
-#ifdef KR_headers
-       (k) int k;
-#else
-       (int k)
+#ifdef ZTS
+
+static MUTEX_T dtoa_mutex;
+static MUTEX_T pow5mult_mutex; 
+
+#define _THREAD_PRIVATE_MUTEX_LOCK(x) tsrm_mutex_lock(x);
+#define _THREAD_PRIVATE_MUTEX_UNLOCK(x) tsrm_mutex_unlock(x);
+
+#else 
+
+#define _THREAD_PRIVATE_MUTEX_LOCK(x)
+#define _THREAD_PRIVATE_MUTEX_UNLOCK(x)
+
+#endif /* ZTS */
+
+ZEND_API int zend_startup_strtod(void) /* {{{ */
+{
+#ifdef ZTS
+       dtoa_mutex = tsrm_mutex_alloc();
+       pow5mult_mutex = tsrm_mutex_alloc();
+#endif
+       return 1;
+}
+/* }}} */
+ZEND_API int zend_shutdown_strtod(void) /* {{{ */
+{
+#ifdef ZTS
+       tsrm_mutex_free(dtoa_mutex);
+       dtoa_mutex = NULL;
+
+       tsrm_mutex_free(pow5mult_mutex);
+       pow5mult_mutex = NULL;
 #endif
+       destroy_freelist();
+       return 1;
+}
+/* }}} */
+
+static Bigint * Balloc(int k)
 {
        int x;
        Bigint *rv;
 
+       _THREAD_PRIVATE_MUTEX_LOCK(dtoa_mutex);
        if ((rv = freelist[k])) {
                freelist[k] = rv->next;
-               }
-       else {
+       } else {
                x = 1 << k;
                rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(Long));
                rv->k = k;
                rv->maxwds = x;
-               }
+       }
+       _THREAD_PRIVATE_MUTEX_UNLOCK(dtoa_mutex);
        rv->sign = rv->wds = 0;
        return rv;
-       }
+}
 
- static void
-Bfree
-#ifdef KR_headers
-       (v) Bigint *v;
-#else
-       (Bigint *v)
-#endif
+static void Bfree(Bigint *v)
 {
        if (v) {
+               _THREAD_PRIVATE_MUTEX_LOCK(dtoa_mutex);
                v->next = freelist[v->k];
                freelist[v->k] = v;
-               }
+               _THREAD_PRIVATE_MUTEX_UNLOCK(dtoa_mutex);
        }
+}
 
 #define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \
-y->wds*sizeof(Long) + 2*sizeof(int))
+               y->wds*sizeof(Long) + 2*sizeof(int))
 
- static Bigint *
-multadd
-#ifdef KR_headers
-       (b, m, a) Bigint *b; int m, a;
-#else
-       (Bigint *b, int m, int a)       /* multiply by m and add a */
-#endif
+/* return value is only used as a simple string, so mis-aligned parts
+ * inside the Bigint are not at risk on strict align architectures
+ */
+static char * rv_alloc(int i) {
+       int j, k, *r;
+
+       j = sizeof(ULong);
+       for(k = 0;
+                       sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= i;
+                       j <<= 1) {
+               k++;
+       }
+       r = (int*)Balloc(k);
+       *r = k;
+       return (char *)(r+1);
+}
+
+
+static char * nrv_alloc(char *s, char **rve, int n)
+{
+       char *rv, *t;
+
+       t = rv = rv_alloc(n);
+       while((*t = *s++) !=0) {
+               t++;
+       }
+       if (rve) {
+               *rve = t;
+       }
+       return rv;
+}
+
+static Bigint * multadd(Bigint *b, int m, int a) /* multiply by m and add a */
 {
        int i, wds;
        ULong *x, y;
@@ -471,148 +542,95 @@ multadd
                a = (int)(y >> 16);
                *x++ = y & 0xffff;
 #endif
-               }
-               while(++i < wds);
+       }
+       while(++i < wds);
        if (a) {
                if (wds >= b->maxwds) {
                        b1 = Balloc(b->k+1);
                        Bcopy(b1, b);
                        Bfree(b);
                        b = b1;
-                       }
+               }
                b->x[wds++] = a;
                b->wds = wds;
-               }
-       return b;
        }
-
- static Bigint *
-s2b
-#ifdef KR_headers
-       (s, nd0, nd, y9) CONST char *s; int nd0, nd; ULong y9;
-#else
-       (CONST char *s, int nd0, int nd, ULong y9)
-#endif
-{
-       Bigint *b;
-       int i, k;
-       Long x, y;
-
-       x = (nd + 8) / 9;
-       for(k = 0, y = 1; x > y; y <<= 1, k++) ;
-#ifdef Pack_32
-       b = Balloc(k);
-       b->x[0] = y9;
-       b->wds = 1;
-#else
-       b = Balloc(k+1);
-       b->x[0] = y9 & 0xffff;
-       b->wds = (b->x[1] = y9 >> 16) ? 2 : 1;
-#endif
-
-       i = 9;
-       if (9 < nd0) {
-               s += 9;
-               do b = multadd(b, 10, *s++ - '0');
-                       while(++i < nd0);
-               s++;
-               }
-       else
-               s += 10;
-       for(; i < nd; i++)
-               b = multadd(b, 10, *s++ - '0');
        return b;
-       }
+}
 
- static int
-hi0bits
-#ifdef KR_headers
-       (x) register ULong x;
-#else
-       (register ULong x)
-#endif
+static int hi0bits(ULong x)
 {
-       register int k = 0;
+       int k = 0;
 
        if (!(x & 0xffff0000)) {
                k = 16;
                x <<= 16;
-               }
+       }
        if (!(x & 0xff000000)) {
                k += 8;
                x <<= 8;
-               }
+       }
        if (!(x & 0xf0000000)) {
                k += 4;
                x <<= 4;
-               }
+       }
        if (!(x & 0xc0000000)) {
                k += 2;
                x <<= 2;
-               }
+       }
        if (!(x & 0x80000000)) {
                k++;
-               if (!(x & 0x40000000))
+               if (!(x & 0x40000000)) {
                        return 32;
                }
-       return k;
        }
+       return k;
+}
 
- static int
-lo0bits
-#ifdef KR_headers
-       (y) ULong *y;
-#else
-       (ULong *y)
-#endif
+static int lo0bits(ULong *y)
 {
-       register int k;
-       register ULong x = *y;
+       int k;
+       ULong x = *y;
 
        if (x & 7) {
-               if (x & 1)
+               if (x & 1) {
                        return 0;
+               }
                if (x & 2) {
                        *y = x >> 1;
                        return 1;
-                       }
+               }
                *y = x >> 2;
                return 2;
-               }
+       }
        k = 0;
        if (!(x & 0xffff)) {
                k = 16;
                x >>= 16;
-               }
+       }
        if (!(x & 0xff)) {
                k += 8;
                x >>= 8;
-               }
+       }
        if (!(x & 0xf)) {
                k += 4;
                x >>= 4;
-               }
+       }
        if (!(x & 0x3)) {
                k += 2;
                x >>= 2;
-               }
+       }
        if (!(x & 1)) {
                k++;
                x >>= 1;
-               if (!x & 1)
+               if (!(x & 1)) {
                        return 32;
                }
+       }
        *y = x;
        return k;
-       }
+}
 
- static Bigint *
-i2b
-#ifdef KR_headers
-       (i) int i;
-#else
-       (int i)
-#endif
+static Bigint * i2b(int i)
 {
        Bigint *b;
 
@@ -620,15 +638,9 @@ i2b
        b->x[0] = i;
        b->wds = 1;
        return b;
-       }
+}
 
- static Bigint *
-mult
-#ifdef KR_headers
-       (a, b) Bigint *a, *b;
-#else
-       (Bigint *a, Bigint *b)
-#endif
+static Bigint * mult(Bigint *a, Bigint *b)
 {
        Bigint *c;
        int k, wa, wb, wc;
@@ -642,16 +654,18 @@ mult
                c = a;
                a = b;
                b = c;
-               }
+       }
        k = a->k;
        wa = a->wds;
        wb = b->wds;
        wc = wa + wb;
-       if (wc > a->maxwds)
+       if (wc > a->maxwds) {
                k++;
+       }
        c = Balloc(k);
-       for(x = c->x, xa = x + wc; x < xa; x++)
+       for(x = c->x, xa = x + wc; x < xa; x++) {
                *x = 0;
+       }
        xa = a->x;
        xae = xa + wa;
        xb = b->x;
@@ -669,10 +683,10 @@ mult
                                z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
                                carry = z2 >> 16;
                                Storeinc(xc, z2, z);
-                               }
-                               while(x < xae);
-                       *xc = carry;
                        }
+                       while(x < xae);
+                       *xc = carry;
+               }
                if ((y = *xb >> 16)) {
                        x = xa;
                        xc = xc0;
@@ -684,11 +698,11 @@ mult
                                Storeinc(xc, z, z2);
                                z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
                                carry = z2 >> 16;
-                               }
-                               while(x < xae);
-                       *xc = z2;
                        }
+                       while(x < xae);
+                       *xc = z2;
                }
+       }
 #else
        for(; xb < xbe; xc0++) {
                if (y = *xb++) {
@@ -699,65 +713,97 @@ mult
                                z = *x++ * y + *xc + carry;
                                carry = z >> 16;
                                *xc++ = z & 0xffff;
-                               }
-                               while(x < xae);
-                       *xc = carry;
                        }
+                       while(x < xae);
+                       *xc = carry;
                }
+       }
 #endif
        for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
        c->wds = wc;
        return c;
-       }
+}
 
- static Bigint *p5s;
+static Bigint * s2b (CONST char *s, int nd0, int nd, ULong y9)
+{
+       Bigint *b;
+       int i, k;
+       Long x, y;
 
- static Bigint *
-pow5mult
-#ifdef KR_headers
-       (b, k) Bigint *b; int k;
+       x = (nd + 8) / 9;
+       for(k = 0, y = 1; x > y; y <<= 1, k++) ;
+#ifdef Pack_32
+       b = Balloc(k);
+       b->x[0] = y9;
+       b->wds = 1;
 #else
-       (Bigint *b, int k)
+       b = Balloc(k+1);
+       b->x[0] = y9 & 0xffff;
+       b->wds = (b->x[1] = y9 >> 16) ? 2 : 1;
 #endif
+
+       i = 9;
+       if (9 < nd0) {
+               s += 9;
+               do b = multadd(b, 10, *s++ - '0');
+               while(++i < nd0);
+               s++;
+       } else {
+               s += 10;
+       }
+       for(; i < nd; i++) {
+               b = multadd(b, 10, *s++ - '0');
+       }
+       return b;
+}
+
+
+static Bigint *p5s;
+
+static Bigint * pow5mult(Bigint *b, int k)
 {
        Bigint *b1, *p5, *p51;
        int i;
        static int p05[3] = { 5, 25, 125 };
 
-       if ((i = k & 3))
+       if ((i = k & 3)) {
                b = multadd(b, p05[i-1], 0);
+       }
 
-       if (!(k >>= 2))
+       if (!(k >>= 2)) {
                return b;
+       }
        if (!(p5 = p5s)) {
                /* first time */
+               _THREAD_PRIVATE_MUTEX_LOCK(pow5mult_mutex);
                p5 = p5s = i2b(625);
                p5->next = 0;
-               }
+               _THREAD_PRIVATE_MUTEX_UNLOCK(pow5mult_mutex);
+       }
        for(;;) {
                if (k & 1) {
                        b1 = mult(b, p5);
                        Bfree(b);
                        b = b1;
-                       }
-               if (!(k >>= 1))
+               }
+               if (!(k >>= 1)) {
                        break;
+               }
                if (!(p51 = p5->next)) {
-                       p51 = p5->next = mult(p5,p5);
-                       p51->next = 0;
+                       _THREAD_PRIVATE_MUTEX_LOCK(pow5mult_mutex);
+                       if (!(p51 = p5->next)) {
+                               p51 = p5->next = mult(p5,p5);
+                               p51->next = 0;
                        }
-               p5 = p51;
+                       _THREAD_PRIVATE_MUTEX_UNLOCK(pow5mult_mutex);
                }
-       return b;
+               p5 = p51;
        }
+       return b;
+}
 
- static Bigint *
-lshift
-#ifdef KR_headers
-       (b, k) Bigint *b; int k;
-#else
-       (Bigint *b, int k)
-#endif
+
+static Bigint *lshift(Bigint *b, int k)
 {
        int i, k1, n, n1;
        Bigint *b1;
@@ -770,12 +816,14 @@ lshift
 #endif
        k1 = b->k;
        n1 = n + b->wds + 1;
-       for(i = b->maxwds; n1 > i; i <<= 1)
+       for(i = b->maxwds; n1 > i; i <<= 1) {
                k1++;
+       }
        b1 = Balloc(k1);
        x1 = b1->x;
-       for(i = 0; i < n; i++)
+       for(i = 0; i < n; i++) {
                *x1++ = 0;
+       }
        x = b->x;
        xe = x + b->wds;
 #ifdef Pack_32
@@ -785,11 +833,12 @@ lshift
                do {
                        *x1++ = *x << k | z;
                        z = *x++ >> k1;
-                       }
-                       while(x < xe);
-               if ((*x1 = z))
+               }
+               while(x < xe);
+               if ((*x1 = z)) {
                        ++n1;
                }
+       }
 #else
        if (k &= 0xf) {
                k1 = 16 - k;
@@ -797,27 +846,22 @@ lshift
                do {
                        *x1++ = *x << k  & 0xffff | z;
                        z = *x++ >> k1;
-                       }
-                       while(x < xe);
-               if (*x1 = z)
+               }
+               while(x < xe);
+               if (*x1 = z) {
                        ++n1;
                }
+       }
 #endif
        else do
                *x1++ = *x++;
-               while(x < xe);
+       while(x < xe);
        b1->wds = n1 - 1;
        Bfree(b);
        return b1;
-       }
+}
 
- static int
-cmp
-#ifdef KR_headers
-       (a, b) Bigint *a, *b;
-#else
-       (Bigint *a, Bigint *b)
-#endif
+static int cmp(Bigint *a, Bigint *b)
 {
        ULong *xa, *xa0, *xb, *xb0;
        int i, j;
@@ -841,21 +885,16 @@ cmp
                        return *xa < *xb ? -1 : 1;
                if (xa <= xa0)
                        break;
-               }
-       return 0;
        }
+       return 0;
+}
 
- static Bigint *
-diff
-#ifdef KR_headers
-       (a, b) Bigint *a, *b;
-#else
-       (Bigint *a, Bigint *b)
-#endif
+
+static Bigint * diff(Bigint *a, Bigint *b)
 {
        Bigint *c;
        int i, wa, wb;
-       Long borrow, y; /* We need signed shifts here. */
+       Long borrow, y; /* We need signed shifts here. */
        ULong *xa, *xae, *xb, *xbe, *xc;
 #ifdef Pack_32
        Long z;
@@ -867,15 +906,15 @@ diff
                c->wds = 1;
                c->x[0] = 0;
                return c;
-               }
+       }
        if (i < 0) {
                c = a;
                a = b;
                b = c;
                i = 1;
-               }
-       else
+       } else {
                i = 0;
+       }
        c = Balloc(a->k);
        c->sign = i;
        wa = a->wds;
@@ -895,8 +934,7 @@ diff
                borrow = z >> 16;
                Sign_Extend(borrow, z);
                Storeinc(xc, z, y);
-               }
-               while(xb < xbe);
+       } while(xb < xbe);
        while(xa < xae) {
                y = (*xa & 0xffff) + borrow;
                borrow = y >> 16;
@@ -905,35 +943,29 @@ diff
                borrow = z >> 16;
                Sign_Extend(borrow, z);
                Storeinc(xc, z, y);
-               }
+       }
 #else
        do {
                y = *xa++ - *xb++ + borrow;
                borrow = y >> 16;
                Sign_Extend(borrow, y);
                *xc++ = y & 0xffff;
-               }
-               while(xb < xbe);
+       } while(xb < xbe);
        while(xa < xae) {
                y = *xa++ + borrow;
                borrow = y >> 16;
                Sign_Extend(borrow, y);
                *xc++ = y & 0xffff;
-               }
+       }
 #endif
-       while(!*--xc)
+       while(!*--xc) {
                wa--;
+       }
        c->wds = wa;
        return c;
-       }
+}
 
- static double
-ulp
-#ifdef KR_headers
-       (_x) double _x;
-#else
-       (double _x)
-#endif
+static double ulp (double _x)
 {
        _double x;
        register Long L;
@@ -950,29 +982,29 @@ ulp
                word0(a) = L;
                word1(a) = 0;
 #ifndef Sudden_Underflow
-               }
+       }
        else {
                L = -L >> Exp_shift;
                if (L < Exp_shift) {
                        word0(a) = 0x80000 >> L;
                        word1(a) = 0;
-                       }
+               }
                else {
                        word0(a) = 0;
                        L -= Exp_shift;
                        word1(a) = L >= 31 ? 1 : 1 << (31 - L);
-                       }
                }
+       }
 #endif
        return value(a);
-       }
+}
 
- static double
+static double
 b2d
 #ifdef KR_headers
-       (a, e) Bigint *a; int *e;
+(a, e) Bigint *a; int *e;
 #else
-       (Bigint *a, int *e)
+(Bigint *a, int *e)
 #endif
 {
        ULong *xa, *xa0, w, y, z;
@@ -999,17 +1031,17 @@ b2d
                w = xa > xa0 ? *--xa : 0;
                d1 = y << ((32-Ebits) + k) | w >> (Ebits - k);
                goto ret_d;
-               }
+       }
        z = xa > xa0 ? *--xa : 0;
        if (k -= Ebits) {
                d0 = Exp_1 | y << k | z >> (32 - k);
                y = xa > xa0 ? *--xa : 0;
                d1 = z << k | y >> (32 - k);
-               }
+       }
        else {
                d0 = Exp_1 | y;
                d1 = z;
-               }
+       }
 #else
        if (k < Ebits + 16) {
                z = xa > xa0 ? *--xa : 0;
@@ -1018,7 +1050,7 @@ b2d
                y = xa > xa0 ? *--xa : 0;
                d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
                goto ret_d;
-               }
+       }
        z = xa > xa0 ? *--xa : 0;
        w = xa > xa0 ? *--xa : 0;
        k -= Ebits + 16;
@@ -1026,7 +1058,7 @@ b2d
        y = xa > xa0 ? *--xa : 0;
        d1 = w << k + 16 | y << k;
 #endif
- ret_d:
+ret_d:
 #ifdef VAX
        word0(d) = d0 >> 16 | d0 << 16;
        word1(d) = d1 >> 16 | d1 << 16;
@@ -1035,15 +1067,10 @@ b2d
 #undef d1
 #endif
        return value(d);
-       }
+}
 
- static Bigint *
-d2b
-#ifdef KR_headers
-       (_d, e, bits) double d; int *e, *bits;
-#else
-       (double _d, int *e, int *bits)
-#endif
+
+static Bigint * d2b(double _d, int *e, int *bits)
 {
        Bigint *b;
        int de, i, k;
@@ -1070,7 +1097,7 @@ d2b
        x = b->x;
 
        z = d0 & Frac_mask;
-       d0 &= 0x7fffffff;       /* clear sign bit, which we ignore */
+       d0 &= 0x7fffffff;   /* clear sign bit, which we ignore */
 #ifdef Sudden_Underflow
        de = (int)(d0 >> Exp_shift);
 #ifndef IBM
@@ -1083,14 +1110,13 @@ d2b
 #ifdef Pack_32
        if ((y = d1)) {
                if ((k = lo0bits(&y))) {
-                       x[0] = y | z << (32 - k);
+                       x[0] = y | (z << (32 - k));
                        z >>= k;
-                       }
-               else
+               } else {
                        x[0] = y;
-               i = b->wds = (x[1] = z) ? 2 : 1;
                }
-       else {
+               i = b->wds = (x[1] = z) ? 2 : 1;
+       } else {
 #ifdef DEBUG
                if (!z)
                        Bug("Zero passed to d2b");
@@ -1099,32 +1125,30 @@ d2b
                x[0] = z;
                i = b->wds = 1;
                k += 32;
-               }
+       }
 #else
        if (y = d1) {
-               if (k = lo0bits(&y))
+               if (k = lo0bits(&y)) {
                        if (k >= 16) {
                                x[0] = y | z << 32 - k & 0xffff;
                                x[1] = z >> k - 16 & 0xffff;
                                x[2] = z >> k;
                                i = 2;
-                               }
-                       else {
+                       } else {
                                x[0] = y & 0xffff;
                                x[1] = y >> 16 | z << 16 - k & 0xffff;
                                x[2] = z >> k & 0xffff;
                                x[3] = z >> k+16;
                                i = 3;
-                               }
-               else {
+                       }
+               else {
                        x[0] = y & 0xffff;
                        x[1] = y >> 16;
                        x[2] = z & 0xffff;
                        x[3] = z >> 16;
                        i = 3;
-                       }
                }
-       else {
+       else {
 #ifdef DEBUG
                if (!z)
                        Bug("Zero passed to d2b");
@@ -1133,14 +1157,13 @@ d2b
                if (k >= 16) {
                        x[0] = z;
                        i = 0;
-                       }
-               else {
+               } else {
                        x[0] = z & 0xffff;
                        x[1] = z >> 16;
                        i = 1;
-                       }
-               k += 32;
                }
+               k += 32;
+       }
        while(!x[i])
                --i;
        b->wds = i + 1;
@@ -1156,28 +1179,22 @@ d2b
                *bits = P - k;
 #endif
 #ifndef Sudden_Underflow
-               }
-       else {
+       } else {
                *e = de - Bias - (P-1) + 1 + k;
 #ifdef Pack_32
                *bits = 32*i - hi0bits(x[i-1]);
 #else
                *bits = (i+2)*16 - hi0bits(x[i]);
 #endif
-               }
+       }
 #endif
        return b;
-       }
+}
 #undef d0
 #undef d1
 
- static double
-ratio
-#ifdef KR_headers
-       (a, b) Bigint *a, *b;
-#else
-       (Bigint *a, Bigint *b)
-#endif
+
+static double ratio (Bigint *a, Bigint *b)
 {
        _double da, db;
        int k, ka, kb;
@@ -1192,35 +1209,35 @@ ratio
 #ifdef IBM
        if (k > 0) {
                word0(da) += (k >> 2)*Exp_msk1;
-               if (k &= 3)
+               if (k &= 3) {
                        da *= 1 << k;
                }
-       else {
+       else {
                k = -k;
                word0(db) += (k >> 2)*Exp_msk1;
                if (k &= 3)
                        db *= 1 << k;
-               }
+       }
 #else
-       if (k > 0)
+       if (k > 0) {
                word0(da) += k*Exp_msk1;
-       else {
+       else {
                k = -k;
                word0(db) += k*Exp_msk1;
-               }
+       }
 #endif
        return value(da) / value(db);
-       }
+}
 
 static CONST double
 tens[] = {
-               1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
-               1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
-               1e20, 1e21, 1e22
+       1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
+       1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
+       1e20, 1e21, 1e22
 #ifdef VAX
                , 1e23, 1e24
 #endif
-               };
+};
 
 #ifdef IEEE_Arith
 static CONST double bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
@@ -1238,16 +1255,768 @@ static CONST double tinytens[] = { 1e-16, 1e-32 };
 #endif
 #endif
 
-ZEND_API double
-zend_strtod
-#ifdef KR_headers
-       (s00, se) CONST char *s00; char **se;
+
+static int quorem(Bigint *b, Bigint *S)
+{
+       int n;
+       Long borrow, y;
+       ULong carry, q, ys;
+       ULong *bx, *bxe, *sx, *sxe;
+#ifdef Pack_32
+       Long z;
+       ULong si, zs;
+#endif
+
+       n = S->wds;
+#ifdef DEBUG
+       /*debug*/ if (b->wds > n)
+               /*debug*/   Bug("oversize b in quorem");
+#endif
+       if (b->wds < n)
+               return 0;
+       sx = S->x;
+       sxe = sx + --n;
+       bx = b->x;
+       bxe = bx + n;
+       q = *bxe / (*sxe + 1);  /* ensure q <= true quotient */
+#ifdef DEBUG
+       /*debug*/ if (q > 9)
+               /*debug*/   Bug("oversized quotient in quorem");
+#endif
+       if (q) {
+               borrow = 0;
+               carry = 0;
+               do {
+#ifdef Pack_32
+                       si = *sx++;
+                       ys = (si & 0xffff) * q + carry;
+                       zs = (si >> 16) * q + (ys >> 16);
+                       carry = zs >> 16;
+                       y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
+                       borrow = y >> 16;
+                       Sign_Extend(borrow, y);
+                       z = (*bx >> 16) - (zs & 0xffff) + borrow;
+                       borrow = z >> 16;
+                       Sign_Extend(borrow, z);
+                       Storeinc(bx, z, y);
+#else
+                       ys = *sx++ * q + carry;
+                       carry = ys >> 16;
+                       y = *bx - (ys & 0xffff) + borrow;
+                       borrow = y >> 16;
+                       Sign_Extend(borrow, y);
+                       *bx++ = y & 0xffff;
+#endif
+               }
+               while(sx <= sxe);
+               if (!*bxe) {
+                       bx = b->x;
+                       while(--bxe > bx && !*bxe)
+                               --n;
+                       b->wds = n;
+               }
+       }
+       if (cmp(b, S) >= 0) {
+               q++;
+               borrow = 0;
+               carry = 0;
+               bx = b->x;
+               sx = S->x;
+               do {
+#ifdef Pack_32
+                       si = *sx++;
+                       ys = (si & 0xffff) + carry;
+                       zs = (si >> 16) + (ys >> 16);
+                       carry = zs >> 16;
+                       y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
+                       borrow = y >> 16;
+                       Sign_Extend(borrow, y);
+                       z = (*bx >> 16) - (zs & 0xffff) + borrow;
+                       borrow = z >> 16;
+                       Sign_Extend(borrow, z);
+                       Storeinc(bx, z, y);
+#else
+                       ys = *sx++ + carry;
+                       carry = ys >> 16;
+                       y = *bx - (ys & 0xffff) + borrow;
+                       borrow = y >> 16;
+                       Sign_Extend(borrow, y);
+                       *bx++ = y & 0xffff;
+#endif
+               }
+               while(sx <= sxe);
+               bx = b->x;
+               bxe = bx + n;
+               if (!*bxe) {
+                       while(--bxe > bx && !*bxe)
+                               --n;
+                       b->wds = n;
+               }
+       }
+       return q;
+}
+
+static void destroy_freelist(void)
+{
+       int i;
+       Bigint *tmp;
+
+       _THREAD_PRIVATE_MUTEX_LOCK(dtoa_mutex);
+       for (i = 0; i <= Kmax; i++) {
+               Bigint **listp = &freelist[i];
+               while ((tmp = *listp) != NULL) {
+                       *listp = tmp->next;
+                       free(tmp);
+               }
+               freelist[i] = NULL;
+       }
+       _THREAD_PRIVATE_MUTEX_UNLOCK(dtoa_mutex);
+       
+}
+
+
+ZEND_API void zend_freedtoa(char *s)
+{
+       Bigint *b = (Bigint *)((int *)s - 1);
+       b->maxwds = 1 << (b->k = *(int*)b);
+       Bfree(b);
+}
+
+/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
+ *
+ * Inspired by "How to Print Floating-Point Numbers Accurately" by
+ * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101].
+ *
+ * Modifications:
+ *  1. Rather than iterating, we use a simple numeric overestimate
+ *     to determine k = floor(log10(d)).  We scale relevant
+ *     quantities using O(log2(k)) rather than O(k) multiplications.
+ *  2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
+ *     try to generate digits strictly left to right.  Instead, we
+ *     compute with fewer bits and propagate the carry if necessary
+ *     when rounding the final digit up.  This is often faster.
+ *  3. Under the assumption that input will be rounded nearest,
+ *     mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
+ *     That is, we allow equality in stopping tests when the
+ *     round-nearest rule will give the same floating-point value
+ *     as would satisfaction of the stopping test with strict
+ *     inequality.
+ *  4. We remove common factors of powers of 2 from relevant
+ *     quantities.
+ *  5. When converting floating-point integers less than 1e16,
+ *     we use floating-point arithmetic rather than resorting
+ *     to multiple-precision integers.
+ *  6. When asked to produce fewer than 15 digits, we first try
+ *     to get by with floating-point arithmetic; we resort to
+ *     multiple-precision integer arithmetic only if we cannot
+ *     guarantee that the floating-point calculation has given
+ *     the correctly rounded result.  For k requested digits and
+ *     "uniformly" distributed input, the probability is
+ *     something like 10^(k-15) that we must resort to the Long
+ *     calculation.
+ */
+
+ZEND_API char * zend_dtoa(double _d, int mode, int ndigits, int *decpt, int *sign, char **rve)
+{
+ /* Arguments ndigits, decpt, sign are similar to those
+    of ecvt and fcvt; trailing zeros are suppressed from
+    the returned string.  If not null, *rve is set to point
+    to the end of the return value.  If d is +-Infinity or NaN,
+    then *decpt is set to 9999.
+
+    mode:
+        0 ==> shortest string that yields d when read in
+            and rounded to nearest.
+        1 ==> like 0, but with Steele & White stopping rule;
+            e.g. with IEEE P754 arithmetic , mode 0 gives
+            1e23 whereas mode 1 gives 9.999999999999999e22.
+        2 ==> max(1,ndigits) significant digits.  This gives a
+            return value similar to that of ecvt, except
+            that trailing zeros are suppressed.
+        3 ==> through ndigits past the decimal point.  This
+            gives a return value similar to that from fcvt,
+            except that trailing zeros are suppressed, and
+            ndigits can be negative.
+        4-9 should give the same return values as 2-3, i.e.,
+            4 <= mode <= 9 ==> same return as mode
+            2 + (mode & 1).  These modes are mainly for
+            debugging; often they run slower but sometimes
+            faster than modes 2-3.
+        4,5,8,9 ==> left-to-right digit generation.
+        6-9 ==> don't try fast floating-point estimate
+            (if applicable).
+
+        Values of mode other than 0-9 are treated as mode 0.
+
+        Sufficient space is allocated to the return value
+        to hold the suppressed trailing zeros.
+    */
+
+       int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1,
+               j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
+               spec_case, try_quick;
+       Long L;
+#ifndef Sudden_Underflow
+       int denorm;
+       ULong x;
+#endif
+       Bigint *b, *b1, *delta, *mlo, *mhi, *S, *tmp;
+       double ds;
+       char *s, *s0;
+       _double d, d2, eps;
+
+       value(d) = _d;
+
+       if (word0(d) & Sign_bit) {
+               /* set sign for everything, including 0's and NaNs */
+               *sign = 1;
+               word0(d) &= ~Sign_bit;  /* clear sign bit */
+       }
+       else
+               *sign = 0;
+
+#if defined(IEEE_Arith) + defined(VAX)
+#ifdef IEEE_Arith
+       if ((word0(d) & Exp_mask) == Exp_mask)
+#else
+               if (word0(d)  == 0x8000)
+#endif
+               {
+                       /* Infinity or NaN */
+                       *decpt = 9999;
+#ifdef IEEE_Arith
+                       if (!word1(d) && !(word0(d) & 0xfffff))
+                               return nrv_alloc("Infinity", rve, 8);
+#endif
+                       return nrv_alloc("NaN", rve, 3);
+               }
+#endif
+#ifdef IBM
+       value(d) += 0; /* normalize */
+#endif
+       if (!value(d)) {
+               *decpt = 1;
+               return nrv_alloc("0", rve, 1);
+       }
+
+       b = d2b(value(d), &be, &bbits);
+#ifdef Sudden_Underflow
+       i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
+#else
+       if ((i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)))) {
+#endif
+               value(d2) = value(d);
+               word0(d2) &= Frac_mask1;
+               word0(d2) |= Exp_11;
+#ifdef IBM
+               if (j = 11 - hi0bits(word0(d2) & Frac_mask))
+                       value(d2) /= 1 << j;
+#endif
+
+               /* log(x)   ~=~ log(1.5) + (x-1.5)/1.5
+                * log10(x)  =  log(x) / log(10)
+                *      ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
+                * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
+                *
+                * This suggests computing an approximation k to log10(d) by
+                *
+                * k = (i - Bias)*0.301029995663981
+                *  + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
+                *
+                * We want k to be too large rather than too small.
+                * The error in the first-order Taylor series approximation
+                * is in our favor, so we just round up the constant enough
+                * to compensate for any error in the multiplication of
+                * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
+                * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
+                * adding 1e-13 to the constant term more than suffices.
+                * Hence we adjust the constant term to 0.1760912590558.
+                * (We could get a more accurate k by invoking log10,
+                *  but this is probably not worthwhile.)
+                */
+
+               i -= Bias;
+#ifdef IBM
+               i <<= 2;
+               i += j;
+#endif
+#ifndef Sudden_Underflow
+               denorm = 0;
+       }
+       else {
+               /* d is denormalized */
+
+               i = bbits + be + (Bias + (P-1) - 1);
+               x = i > 32  ? (word0(d) << (64 - i)) | (word1(d) >> (i - 32))
+                       : (word1(d) << (32 - i));
+               value(d2) = x;
+               word0(d2) -= 31*Exp_msk1; /* adjust exponent */
+               i -= (Bias + (P-1) - 1) + 1;
+               denorm = 1;
+       }
+#endif
+       ds = (value(d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
+       k = (int)ds;
+       if (ds < 0. && ds != k)
+               k--;    /* want k = floor(ds) */
+       k_check = 1;
+       if (k >= 0 && k <= Ten_pmax) {
+               if (value(d) < tens[k])
+                       k--;
+               k_check = 0;
+       }
+       j = bbits - i - 1;
+       if (j >= 0) {
+               b2 = 0;
+               s2 = j;
+       }
+       else {
+               b2 = -j;
+               s2 = 0;
+       }
+       if (k >= 0) {
+               b5 = 0;
+               s5 = k;
+               s2 += k;
+       }
+       else {
+               b2 -= k;
+               b5 = -k;
+               s5 = 0;
+       }
+       if (mode < 0 || mode > 9)
+               mode = 0;
+       try_quick = 1;
+       if (mode > 5) {
+               mode -= 4;
+               try_quick = 0;
+       }
+       leftright = 1;
+       switch(mode) {
+               case 0:
+               case 1:
+                       ilim = ilim1 = -1;
+                       i = 18;
+                       ndigits = 0;
+                       break;
+               case 2:
+                       leftright = 0;
+                       /* no break */
+               case 4:
+                       if (ndigits <= 0)
+                               ndigits = 1;
+                       ilim = ilim1 = i = ndigits;
+                       break;
+               case 3:
+                       leftright = 0;
+                       /* no break */
+               case 5:
+                       i = ndigits + k + 1;
+                       ilim = i;
+                       ilim1 = i - 1;
+                       if (i <= 0)
+                               i = 1;
+       }
+       s = s0 = rv_alloc(i);
+
+       if (ilim >= 0 && ilim <= Quick_max && try_quick) {
+
+               /* Try to get by with floating-point arithmetic. */
+
+               i = 0;
+               value(d2) = value(d);
+               k0 = k;
+               ilim0 = ilim;
+               ieps = 2; /* conservative */
+               if (k > 0) {
+                       ds = tens[k&0xf];
+                       j = k >> 4;
+                       if (j & Bletch) {
+                               /* prevent overflows */
+                               j &= Bletch - 1;
+                               value(d) /= bigtens[n_bigtens-1];
+                               ieps++;
+                       }
+                       for(; j; j >>= 1, i++)
+                               if (j & 1) {
+                                       ieps++;
+                                       ds *= bigtens[i];
+                               }
+                       value(d) /= ds;
+               }
+               else if ((j1 = -k)) {
+                       value(d) *= tens[j1 & 0xf];
+                       for(j = j1 >> 4; j; j >>= 1, i++)
+                               if (j & 1) {
+                                       ieps++;
+                                       value(d) *= bigtens[i];
+                               }
+               }
+               if (k_check && value(d) < 1. && ilim > 0) {
+                       if (ilim1 <= 0)
+                               goto fast_failed;
+                       ilim = ilim1;
+                       k--;
+                       value(d) *= 10.;
+                       ieps++;
+               }
+               value(eps) = ieps*value(d) + 7.;
+               word0(eps) -= (P-1)*Exp_msk1;
+               if (ilim == 0) {
+                       S = mhi = 0;
+                       value(d) -= 5.;
+                       if (value(d) > value(eps))
+                               goto one_digit;
+                       if (value(d) < -value(eps))
+                               goto no_digits;
+                       goto fast_failed;
+               }
+#ifndef No_leftright
+               if (leftright) {
+                       /* Use Steele & White method of only
+                        * generating digits needed.
+                        */
+                       value(eps) = 0.5/tens[ilim-1] - value(eps);
+                       for(i = 0;;) {
+                               L = value(d);
+                               value(d) -= L;
+                               *s++ = '0' + (int)L;
+                               if (value(d) < value(eps))
+                                       goto ret1;
+                               if (1. - value(d) < value(eps))
+                                       goto bump_up;
+                               if (++i >= ilim)
+                                       break;
+                               value(eps) *= 10.;
+                               value(d) *= 10.;
+                       }
+               }
+               else {
+#endif
+                       /* Generate ilim digits, then fix them up. */
+                       value(eps) *= tens[ilim-1];
+                       for(i = 1;; i++, value(d) *= 10.) {
+                               L = value(d);
+                               value(d) -= L;
+                               *s++ = '0' + (int)L;
+                               if (i == ilim) {
+                                       if (value(d) > 0.5 + value(eps))
+                                               goto bump_up;
+                                       else if (value(d) < 0.5 - value(eps)) {
+                                               while(*--s == '0');
+                                               s++;
+                                               goto ret1;
+                                       }
+                                       break;
+                               }
+                       }
+#ifndef No_leftright
+               }
+#endif
+fast_failed:
+               s = s0;
+               value(d) = value(d2);
+               k = k0;
+               ilim = ilim0;
+       }
+
+       /* Do we have a "small" integer? */
+
+       if (be >= 0 && k <= Int_max) {
+               /* Yes. */
+               ds = tens[k];
+               if (ndigits < 0 && ilim <= 0) {
+                       S = mhi = 0;
+                       if (ilim < 0 || value(d) <= 5*ds)
+                               goto no_digits;
+                       goto one_digit;
+               }
+               for(i = 1;; i++) {
+                       L = value(d) / ds;
+                       value(d) -= L*ds;
+#ifdef Check_FLT_ROUNDS
+                       /* If FLT_ROUNDS == 2, L will usually be high by 1 */
+                       if (value(d) < 0) {
+                               L--;
+                               value(d) += ds;
+                       }
+#endif
+                       *s++ = '0' + (int)L;
+                       if (i == ilim) {
+                               value(d) += value(d);
+                               if (value(d) > ds || (value(d) == ds && (L & 1))) {
+bump_up:
+                                       while(*--s == '9')
+                                               if (s == s0) {
+                                                       k++;
+                                                       *s = '0';
+                                                       break;
+                                               }
+                                       ++*s++;
+                               }
+                               break;
+                       }
+                       if (!(value(d) *= 10.))
+                               break;
+               }
+               goto ret1;
+       }
+
+       m2 = b2;
+       m5 = b5;
+       mhi = mlo = 0;
+       if (leftright) {
+               if (mode < 2) {
+                       i =
+#ifndef Sudden_Underflow
+                               denorm ? be + (Bias + (P-1) - 1 + 1) :
+#endif
+#ifdef IBM
+                               1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3);
+#else
+                       1 + P - bbits;
+#endif
+               }
+               else {
+                       j = ilim - 1;
+                       if (m5 >= j)
+                               m5 -= j;
+                       else {
+                               s5 += j -= m5;
+                               b5 += j;
+                               m5 = 0;
+                       }
+                       if ((i = ilim) < 0) {
+                               m2 -= i;
+                               i = 0;
+                       }
+               }
+               b2 += i;
+               s2 += i;
+               mhi = i2b(1);
+       }
+       if (m2 > 0 && s2 > 0) {
+               i = m2 < s2 ? m2 : s2;
+               b2 -= i;
+               m2 -= i;
+               s2 -= i;
+       }
+       if (b5 > 0) {
+               if (leftright) {
+                       if (m5 > 0) {
+                               mhi = pow5mult(mhi, m5);
+                               b1 = mult(mhi, b);
+                               Bfree(b);
+                               b = b1;
+                       }
+                       if ((j = b5 - m5)) {
+                               b = pow5mult(b, j);
+                       }
+               } else {
+                       b = pow5mult(b, b5);
+               }
+       }
+       S = i2b(1);
+       if (s5 > 0)
+               S = pow5mult(S, s5);
+       /* Check for special case that d is a normalized power of 2. */
+
+       if (mode < 2) {
+               if (!word1(d) && !(word0(d) & Bndry_mask)
+#ifndef Sudden_Underflow
+                               && word0(d) & Exp_mask
+#endif
+                  ) {
+                       /* The special case */
+                       b2 += Log2P;
+                       s2 += Log2P;
+                       spec_case = 1;
+               }
+               else
+                       spec_case = 0;
+       }
+
+       /* Arrange for convenient computation of quotients:
+        * shift left if necessary so divisor has 4 leading 0 bits.
+        *
+        * Perhaps we should just compute leading 28 bits of S once
+        * and for all and pass them and a shift to quorem, so it
+        * can do shifts and ors to compute the numerator for q.
+        */
+#ifdef Pack_32
+       if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f))
+               i = 32 - i;
 #else
-       (CONST char *s00, char **se)
+       if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf))
+               i = 16 - i;
+#endif
+       if (i > 4) {
+               i -= 4;
+               b2 += i;
+               m2 += i;
+               s2 += i;
+       }
+       else if (i < 4) {
+               i += 28;
+               b2 += i;
+               m2 += i;
+               s2 += i;
+       }
+       if (b2 > 0)
+               b = lshift(b, b2);
+       if (s2 > 0)
+               S = lshift(S, s2);
+       if (k_check) {
+               if (cmp(b,S) < 0) {
+                       k--;
+                       b = multadd(b, 10, 0);  /* we botched the k estimate */
+                       if (leftright)
+                               mhi = multadd(mhi, 10, 0);
+                       ilim = ilim1;
+               }
+       }
+       if (ilim <= 0 && mode > 2) {
+               if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) {
+                       /* no digits, fcvt style */
+no_digits:
+                       k = -1 - ndigits;
+                       goto ret;
+               }
+one_digit:
+               *s++ = '1';
+               k++;
+               goto ret;
+       }
+       if (leftright) {
+               if (m2 > 0)
+                       mhi = lshift(mhi, m2);
+
+               /* Compute mlo -- check for special case
+                * that d is a normalized power of 2.
+                */
+
+               mlo = mhi;
+               if (spec_case) {
+                       mhi = Balloc(mhi->k);
+                       Bcopy(mhi, mlo);
+                       mhi = lshift(mhi, Log2P);
+               }
+
+               for(i = 1;;i++) {
+                       dig = quorem(b,S) + '0';
+                       /* Do we yet have the shortest decimal string
+                        * that will round to d?
+                        */
+                       j = cmp(b, mlo);
+                       delta = diff(S, mhi);
+                       j1 = delta->sign ? 1 : cmp(b, delta);
+                       Bfree(delta);
+#ifndef ROUND_BIASED
+                       if (j1 == 0 && !mode && !(word1(d) & 1)) {
+                               if (dig == '9')
+                                       goto round_9_up;
+                               if (j > 0)
+                                       dig++;
+                               *s++ = dig;
+                               goto ret;
+                       }
 #endif
+                       if (j < 0 || (j == 0 && !mode
+#ifndef ROUND_BIASED
+                                               && !(word1(d) & 1)
+#endif
+                                               )) {
+                               if (j1 > 0) {
+                                       b = lshift(b, 1);
+                                       j1 = cmp(b, S);
+                                       if ((j1 > 0 || (j1 == 0 && (dig & 1)))
+                                                       && dig++ == '9')
+                                               goto round_9_up;
+                               }
+                               *s++ = dig;
+                               goto ret;
+                       }
+                       if (j1 > 0) {
+                               if (dig == '9') { /* possible if i == 1 */
+round_9_up:
+                                       *s++ = '9';
+                                       goto roundoff;
+                               }
+                               *s++ = dig + 1;
+                               goto ret;
+                       }
+                       *s++ = dig;
+                       if (i == ilim)
+                               break;
+                       b = multadd(b, 10, 0);
+                       if (mlo == mhi)
+                               mlo = mhi = multadd(mhi, 10, 0);
+                       else {
+                               mlo = multadd(mlo, 10, 0);
+                               mhi = multadd(mhi, 10, 0);
+                       }
+               }
+       }
+       else
+               for(i = 1;; i++) {
+                       *s++ = dig = quorem(b,S) + '0';
+                       if (i >= ilim)
+                               break;
+                       b = multadd(b, 10, 0);
+               }
+
+       /* Round off last digit */
+
+       b = lshift(b, 1);
+       j = cmp(b, S);
+       if (j > 0 || (j == 0 && (dig & 1))) {
+roundoff:
+               while(*--s == '9')
+                       if (s == s0) {
+                               k++;
+                               *s++ = '1';
+                               goto ret;
+                       }
+               ++*s++;
+       }
+       else {
+               while(*--s == '0');
+               s++;
+       }
+ret:
+       Bfree(S);
+       if (mhi) {
+               if (mlo && mlo != mhi)
+                       Bfree(mlo);
+               Bfree(mhi);
+       }
+ret1:
+
+       _THREAD_PRIVATE_MUTEX_LOCK(pow5mult_mutex);
+       while (p5s) {
+               tmp = p5s;
+               p5s = p5s->next;
+               free(tmp);
+       }
+       _THREAD_PRIVATE_MUTEX_UNLOCK(pow5mult_mutex);
+
+       Bfree(b);
+
+       if (s == s0) {              /* don't return empty string */
+               *s++ = '0';
+               k = 0;
+       }
+       *s = 0;
+       *decpt = k + 1;
+       if (rve)
+               *rve = s;
+       return s0;
+}
+
+ZEND_API double zend_strtod (CONST char *s00, char **se)
 {
        int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
-                e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
+               e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
        CONST char *s, *s0, *s1;
        double aadj, aadj1, adj;
        _double rv, rv0;
@@ -1282,7 +2051,7 @@ zend_strtod
                while(*++s == '0') ;
                if (!*s)
                        goto ret;
-               }
+       }
        s0 = s;
        y = z = 0;
        for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
@@ -1301,11 +2070,11 @@ zend_strtod
                                nf += nz;
                                nz = 0;
                                goto have_dig;
-                               }
-                       goto dig_done;
                        }
+                       goto dig_done;
+               }
                for(; c >= '0' && c <= '9'; c = *++s) {
- have_dig:
+have_dig:
                        nz++;
                        if (c -= '0') {
                                nf += nz;
@@ -1319,16 +2088,16 @@ zend_strtod
                                else if (nd <= DBL_DIG + 1)
                                        z = 10*z + c;
                                nz = 0;
-                               }
                        }
                }
- dig_done:
+       }
+dig_done:
        e = 0;
        if (c == 'e' || c == 'E') {
                if (!nd && !nz && !nz0) {
                        s = s00;
                        goto ret;
-                       }
+               }
                s00 = s;
                esign = 0;
                switch(c = *++s) {
@@ -1336,7 +2105,7 @@ zend_strtod
                                esign = 1;
                        case '+':
                                c = *++s;
-                       }
+               }
                if (c >= '0' && c <= '9') {
                        while(c == '0')
                                c = *++s;
@@ -1354,18 +2123,18 @@ zend_strtod
                                        e = (int)L;
                                if (esign)
                                        e = -e;
-                               }
+                       }
                        else
                                e = 0;
-                       }
+               }
                else
                        s = s00;
-               }
+       }
        if (!nd) {
                if (!nz && !nz0)
                        s = s00;
                goto ret;
-               }
+       }
        e1 = e -= nf;
 
        /* Now we have nd0 digits, starting at s0, followed by a
@@ -1382,9 +2151,9 @@ zend_strtod
        bd0 = 0;
        if (nd <= DBL_DIG
 #ifndef RND_PRODQUOT
-               && FLT_ROUNDS == 1
+                       && FLT_ROUNDS == 1
 #endif
-                       ) {
+          ) {
                if (!e)
                        goto ret;
                if (e > 0) {
@@ -1393,10 +2162,10 @@ zend_strtod
                                goto vax_ovfl_check;
 #else
                                /* value(rv) = */ rounded_product(value(rv),
-                                   tens[e]);
+                                               tens[e]);
                                goto ret;
 #endif
-                               }
+                       }
                        i = DBL_DIG - nd;
                        if (e <= Ten_pmax + i) {
                                /* A fancier test would sometimes let us do
@@ -1408,29 +2177,29 @@ zend_strtod
                                /* VAX exponent range is so narrow we must
                                 * worry about overflow here...
                                 */
- vax_ovfl_check:
+vax_ovfl_check:
                                word0(rv) -= P*Exp_msk1;
                                /* value(rv) = */ rounded_product(value(rv),
-                                   tens[e]);
+                                               tens[e]);
                                if ((word0(rv) & Exp_mask)
-                                > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
+                                               > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
                                        goto ovfl;
                                word0(rv) += P*Exp_msk1;
 #else
                                /* value(rv) = */ rounded_product(value(rv),
-                                   tens[e]);
+                                               tens[e]);
 #endif
                                goto ret;
-                               }
                        }
+               }
 #ifndef Inaccurate_Divide
                else if (e >= -Ten_pmax) {
                        /* value(rv) = */ rounded_quotient(value(rv),
-                           tens[-e]);
+                                       tens[-e]);
                        goto ret;
-                       }
-#endif
                }
+#endif
+       }
        e1 += nd - k;
 
        /* Get starting approximation = rv * 10**e1 */
@@ -1440,7 +2209,7 @@ zend_strtod
                        value(rv) *= tens[i];
                if (e1 &= ~15) {
                        if (e1 > DBL_MAX_10_EXP) {
- ovfl:
+ovfl:
                                errno = ERANGE;
 #ifndef Bad_float_h
                                value(rv) = HUGE_VAL;
@@ -1457,29 +2226,29 @@ zend_strtod
                                if (bd0)
                                        goto retfree;
                                goto ret;
-                               }
+                       }
                        if (e1 >>= 4) {
                                for(j = 0; e1 > 1; j++, e1 >>= 1)
                                        if (e1 & 1)
                                                value(rv) *= bigtens[j];
-                       /* The last multiplication could overflow. */
+                               /* The last multiplication could overflow. */
                                word0(rv) -= P*Exp_msk1;
                                value(rv) *= bigtens[j];
                                if ((z = word0(rv) & Exp_mask)
-                                > Exp_msk1*(DBL_MAX_EXP+Bias-P))
+                                               > Exp_msk1*(DBL_MAX_EXP+Bias-P))
                                        goto ovfl;
                                if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {
                                        /* set to largest number */
                                        /* (Can't trust DBL_MAX) */
                                        word0(rv) = Big0;
                                        word1(rv) = Big1;
-                                       }
+                               }
                                else
                                        word0(rv) += P*Exp_msk1;
-                               }
-
                        }
+
                }
+       }
        else if (e1 < 0) {
                e1 = -e1;
                if ((i = e1 & 15))
@@ -1498,21 +2267,21 @@ zend_strtod
                                value(rv) = 2.*value(rv0);
                                value(rv) *= tinytens[j];
                                if (!value(rv)) {
- undfl:
+undfl:
                                        value(rv) = 0.;
                                        errno = ERANGE;
                                        if (bd0)
                                                goto retfree;
                                        goto ret;
-                                       }
+                               }
                                word0(rv) = Tiny0;
                                word1(rv) = Tiny1;
                                /* The refinement below will clean
                                 * this approximation up.
                                 */
-                               }
                        }
                }
+       }
 
        /* Now the hard part -- adjusting rv to the correct value.*/
 
@@ -1529,11 +2298,11 @@ zend_strtod
                if (e >= 0) {
                        bb2 = bb5 = 0;
                        bd2 = bd5 = e;
-                       }
+               }
                else {
                        bb2 = bb5 = -e;
                        bd2 = bd5 = 0;
-                       }
+               }
                if (bbe >= 0)
                        bb2 += bbe;
                else
@@ -1561,13 +2330,13 @@ zend_strtod
                        bb2 -= i;
                        bd2 -= i;
                        bs2 -= i;
-                       }
+               }
                if (bb5 > 0) {
                        bs = pow5mult(bs, bb5);
                        bb1 = mult(bs, bb);
                        Bfree(bb);
                        bb = bb1;
-                       }
+               }
                if (bb2 > 0)
                        bb = lshift(bb, bb2);
                if (bd5 > 0)
@@ -1590,12 +2359,12 @@ zend_strtod
                        if (cmp(delta, bs) > 0)
                                goto drop_down;
                        break;
-                       }
+               }
                if (i == 0) {
                        /* exactly half-way between */
                        if (dsign) {
                                if ((word0(rv) & Bndry_mask1) == Bndry_mask1
-                                &&  word1(rv) == 0xffffffff) {
+                                               &&  word1(rv) == 0xffffffff) {
                                        /*boundary case -- increment exponent*/
                                        word0(rv) = (word0(rv) & Exp_mask)
                                                + Exp_msk1
@@ -1605,19 +2374,19 @@ zend_strtod
                                                ;
                                        word1(rv) = 0;
                                        break;
-                                       }
                                }
+                       }
                        else if (!(word0(rv) & Bndry_mask) && !word1(rv)) {
- drop_down:
+drop_down:
                                /* boundary case -- decrement exponent */
 #ifdef Sudden_Underflow
                                L = word0(rv) & Exp_mask;
 #ifdef IBM
                                if (L <  Exp_msk1)
 #else
-                               if (L <= Exp_msk1)
+                                       if (L <= Exp_msk1)
 #endif
-                                       goto undfl;
+                                               goto undfl;
                                L -= Exp_msk1;
 #else
                                L = (word0(rv) & Exp_mask) - Exp_msk1;
@@ -1629,7 +2398,7 @@ zend_strtod
 #else
                                break;
 #endif
-                               }
+                       }
 #ifndef ROUND_BIASED
                        if (!(word1(rv) & LSB))
                                break;
@@ -1643,10 +2412,10 @@ zend_strtod
                                if (!value(rv))
                                        goto undfl;
 #endif
-                               }
+                       }
 #endif
                        break;
-                       }
+               }
                if ((aadj = ratio(delta, bs)) <= 2.) {
                        if (dsign)
                                aadj = aadj1 = 1.;
@@ -1657,7 +2426,7 @@ zend_strtod
 #endif
                                aadj = 1.;
                                aadj1 = -1.;
-                               }
+                       }
                        else {
                                /* special case -- power of FLT_RADIX to be */
                                /* rounded down... */
@@ -1667,8 +2436,8 @@ zend_strtod
                                else
                                        aadj *= 0.5;
                                aadj1 = -aadj;
-                               }
                        }
+               }
                else {
                        aadj *= 0.5;
                        aadj1 = dsign ? aadj : -aadj;
@@ -1680,12 +2449,12 @@ zend_strtod
                                case 0: /* towards 0 */
                                case 3: /* towards -infinity */
                                        aadj1 += 0.5;
-                               }
+                       }
 #else
                        if (FLT_ROUNDS == 0)
                                aadj1 += 0.5;
 #endif
-                       }
+               }
                y = word0(rv) & Exp_mask;
 
                /* Check for overflow */
@@ -1702,10 +2471,10 @@ zend_strtod
                                word0(rv) = Big0;
                                word1(rv) = Big1;
                                goto cont;
-                               }
+                       }
                        else
                                word0(rv) += P*Exp_msk1;
-                       }
+               }
                else {
 #ifdef Sudden_Underflow
                        if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
@@ -1716,23 +2485,23 @@ zend_strtod
 #ifdef IBM
                                if ((word0(rv) & Exp_mask) <  P*Exp_msk1)
 #else
-                               if ((word0(rv) & Exp_mask) <= P*Exp_msk1)
+                                       if ((word0(rv) & Exp_mask) <= P*Exp_msk1)
 #endif
                                        {
-                                       if (word0(rv0) == Tiny0
-                                        && word1(rv0) == Tiny1)
-                                               goto undfl;
-                                       word0(rv) = Tiny0;
-                                       word1(rv) = Tiny1;
-                                       goto cont;
+                                               if (word0(rv0) == Tiny0
+                                                               && word1(rv0) == Tiny1)
+                                                       goto undfl;
+                                               word0(rv) = Tiny0;
+                                               word1(rv) = Tiny1;
+                                               goto cont;
                                        }
-                               else
-                                       word0(rv) -= P*Exp_msk1;
-                               }
+                                       else
+                                               word0(rv) -= P*Exp_msk1;
+                       }
                        else {
                                adj = aadj1 * ulp(value(rv));
                                value(rv) += adj;
-                               }
+                       }
 #else
                        /* Compute adj so that the IEEE rounding rules will
                         * correctly round rv + adj in some half-way cases.
@@ -1745,11 +2514,11 @@ zend_strtod
                                aadj1 = (double)(int)(aadj + 0.5);
                                if (!dsign)
                                        aadj1 = -aadj1;
-                               }
+                       }
                        adj = aadj1 * ulp(value(rv));
                        value(rv) += adj;
 #endif
-                       }
+               }
                z = word0(rv) & Exp_mask;
                if (y == z) {
                        /* Can we stop now? */
@@ -1759,44 +2528,37 @@ zend_strtod
                        if (dsign || word1(rv) || word0(rv) & Bndry_mask) {
                                if (aadj < .4999999 || aadj > .5000001)
                                        break;
-                               }
+                       }
                        else if (aadj < .4999999/FLT_RADIX)
                                break;
-                       }
- cont:
+               }
+cont:
                Bfree(bb);
                Bfree(bd);
                Bfree(bs);
                Bfree(delta);
-               }
- retfree:
+       }
+retfree:
        Bfree(bb);
        Bfree(bd);
        Bfree(bs);
        Bfree(bd0);
        Bfree(delta);
- ret:
+ret:
        if (se)
                *se = (char *)s;
        result = sign ? -value(rv) : value(rv);
 
-       for (i = 0; i <= Kmax; i++) {
-               Bigint **listp = &freelist[i];
-               while ((tmp = *listp) != NULL) {
-                       *listp = tmp->next;
-                       free(tmp);
-               }
-               freelist[i] = NULL;
-       }
-
+       _THREAD_PRIVATE_MUTEX_LOCK(pow5mult_mutex);
        while (p5s) {
                tmp = p5s;
                p5s = p5s->next;
                free(tmp);
        }
+       _THREAD_PRIVATE_MUTEX_UNLOCK(pow5mult_mutex);
 
        return result;
-       }
+}
 
 /* UTODO: someone can reimplement this using the code above, if they really want to. */
 ZEND_API double zend_u_strtod(const UChar *nptr, UChar **endptr)
@@ -1817,3 +2579,12 @@ ZEND_API double zend_u_strtod(const UChar *nptr, UChar **endptr)
                return 0;
        }
 }
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
index f740ccf1b72f093b3ac4572198597c3376e29cdc..8d18a09e01bd58a8ae110f981627c0e332f6c108 100644 (file)
@@ -5,7 +5,7 @@
    | Copyright (c) 1998-2006 Zend Technologies Ltd. (http://www.zend.com) |
    +----------------------------------------------------------------------+
    | This source file is subject to version 2.00 of the Zend license,     |
-   | that is bundled with this package in the file LICENSE, and is        |
+   | that is bundled with this package in the file LICENSE, and is        | 
    | available through the world-wide-web at the following url:           |
    | http://www.zend.com/license/2_00.txt.                                |
    | If you did not receive a copy of the Zend license and are unable to  |
 #include <zend.h>
 
 BEGIN_EXTERN_C()
+ZEND_API void zend_freedtoa(char *s);
+ZEND_API char * zend_dtoa(double _d, int mode, int ndigits, int *decpt, int *sign, char **rve);
 ZEND_API double zend_strtod(const char *s00, char **se);
+ZEND_API double zend_u_strtod(const UChar *nptr, UChar **endptr);
+ZEND_API int zend_startup_strtod(void);
+ZEND_API int zend_shutdown_strtod(void);
 END_EXTERN_C()
 
 #endif
index 454eacdc068beb8bb2b623add70fc5444dfccd74..bd9627720a5224362bd1c5be13542ee365d823cd 100644 (file)
@@ -51,110 +51,6 @@ static char hexchars[] = "0123456789abcdef";
 static char HEXCHARS[] = "0123456789ABCDEF";
 
 
-/*
- * cvt.c - IEEE floating point formatting routines for FreeBSD
- * from GNU libc-4.6.27
- */
-
-/*
- *    php_convert_to_decimal converts to decimal
- *      the number of digits is specified by ndigit
- *      decpt is set to the position of the decimal point
- *      sign is set to 0 for positive, 1 for negative
- */
-static char *php_convert_to_decimal(double arg, int ndigits, int *decpt, int *sign, int eflag)
-{
-       register int r2;
-       int mvl;
-       double fi, fj;
-       register char *p, *p1;
-       /*THREADX*/
-#ifndef THREAD_SAFE
-       static char cvt_buf[NDIG];
-#endif
-
-       if (ndigits >= NDIG - 1)
-               ndigits = NDIG - 2;
-       r2 = 0;
-       *sign = 0;
-       p = &cvt_buf[0];
-       if (arg < 0) {
-               *sign = 1;
-               arg = -arg;
-       }
-       arg = modf(arg, &fi);
-       p1 = &cvt_buf[NDIG];
-       /*
-        * Do integer part
-        */
-       if (fi != 0) {
-               p1 = &cvt_buf[NDIG];
-               while (fi != 0) {
-                       fj = modf(fi / 10, &fi);
-                       if (p1 <= &cvt_buf[0]) {
-                               mvl = NDIG - ndigits;
-                               memmove(&cvt_buf[mvl], &cvt_buf[0], NDIG-mvl-1);
-                               p1 += mvl;
-                       }
-                       *--p1 = (int) ((fj + .03) * 10) + '0';
-                       r2++;
-               }
-               while (p1 < &cvt_buf[NDIG])
-                       *p++ = *p1++;
-       } else if (arg > 0) {
-               while ((fj = arg * 10) < 1) {
-                       if (!eflag && (r2 * -1) < ndigits) {
-                               break;
-                       }
-                       arg = fj;
-                       r2--;
-               }
-       }
-       p1 = &cvt_buf[ndigits];
-       if (eflag == 0)
-               p1 += r2;
-       *decpt = r2;
-       if (p1 < &cvt_buf[0]) {
-               cvt_buf[0] = '\0';
-               return (cvt_buf);
-       }
-       if (p <= p1 && p < &cvt_buf[NDIG]) {
-               arg = modf(arg * 10, &fj);
-               if ((int)fj==10) {
-                       *p++ = '1';
-                       fj = 0;
-                       *decpt = ++r2;
-               }
-               while (p <= p1 && p < &cvt_buf[NDIG]) {
-               *p++ = (int) fj + '0';
-                       arg = modf(arg * 10, &fj);
-               }
-       }
-       if (p1 >= &cvt_buf[NDIG]) {
-               cvt_buf[NDIG - 1] = '\0';
-               return (cvt_buf);
-       }
-       p = p1;
-       *p1 += 5;
-       while (*p1 > '9') {
-               *p1 = '0';
-               if (p1 > cvt_buf)
-                       ++ * --p1;
-               else {
-                       *p1 = '1';
-                       (*decpt)++;
-                       if (eflag == 0) {
-                               if (p > cvt_buf)
-                                       *p = '0';
-                               p++;
-                       }
-               }
-       }
-       *p = '\0';
-       return (cvt_buf);
-}
-
-
 inline static void
 php_sprintf_appendchar(char **buffer, int *pos, int *size, char add TSRMLS_DC)
 {
@@ -299,19 +195,10 @@ php_sprintf_appenddouble(char **buffer, int *pos,
                                                 int always_sign
                                                 TSRMLS_DC)
 {
-       char numbuf[NUM_BUF_SIZE];
-       char *cvt;
-       register int i = 0, j = 0;
-       int sign, decpt, cvt_len;
-       char decimal_point = '.';
-#ifdef HAVE_LOCALE_H
-       struct lconv lc;
-       char locale_decimal_point;
-       localeconv_r(&lc);
-       locale_decimal_point = (lc.decimal_point)[0];
-#else
-       char locale_decimal_point = '.';
-#endif
+       char num_buf[NUM_BUF_SIZE];
+       char *s, *q;
+       int s_len;
+       int is_negative;
 
        PRINTF_DEBUG(("sprintf: appenddouble(%x, %x, %x, %f, %d, '%c', %d, %c)\n",
                                  *buffer, pos, size, number, width, padding, alignment, fmt));
@@ -322,92 +209,66 @@ php_sprintf_appenddouble(char **buffer, int *pos,
        }
        
        if (zend_isnan(number)) {
-               sign = (number<0);
+               is_negative = (number<0);
                php_sprintf_appendstring(buffer, pos, size, "NaN", 3, 0, padding,
-                                                                alignment, precision, sign, 0, always_sign);
+                                                                alignment, precision, is_negative, 0, always_sign);
                return;
        }
 
        if (zend_isinf(number)) {
-               sign = (number<0);
+               is_negative = (number<0);
                php_sprintf_appendstring(buffer, pos, size, "INF", 3, 0, padding,
-                                                                alignment, precision, sign, 0, always_sign);
+                                                                alignment, precision, is_negative, 0, always_sign);
                return;
        }
 
-       cvt = php_convert_to_decimal(number, precision, &decpt, &sign, (fmt == 'e'));
-       cvt_len = strlen(cvt);
-
-       if (sign) {
-               numbuf[i++] = '-';
-       } else if (always_sign) {
-               numbuf[i++] = '+';
-       }
-
-       if (fmt == 'f' || fmt == 'F') {
-               if (decpt <= 0) {
-                       numbuf[i++] = '0';
-                       if (precision > 0) {
-                               int k = precision;
-                               numbuf[i++] = fmt == 'F' ? decimal_point : locale_decimal_point;
-                               while ((decpt++ < 0) && k--) {
-                                       numbuf[i++] = '0';
-                               }
-                       }
-               } else {
-                       while (decpt-- > 0) {
-                               numbuf[i++] = j < cvt_len ? cvt[j++] : '0';
+       switch (fmt) {                  
+               case 'e':
+                       if (precision) {
+                               precision--;
                        }
-                       if (precision > 0) {
-                               numbuf[i++] = fmt == 'F' ? decimal_point : locale_decimal_point;
-                               while (precision-- > 0) {
-                                       numbuf[i++] = j < cvt_len ? cvt[j++] : '0';
-                               }
-                       }
-               }
-       } else if (fmt == 'e' || fmt == 'E') {
-               char *exp_p;
-               int dec2;
-               
-               decpt--;
-               
-               numbuf[i++] = cvt[j++];
-               numbuf[i++] = decimal_point;    
-
-               if (precision > 0) {
-                       int k = precision;
-                               
-                       while (k-- && cvt[j]) {
-                               numbuf[i++] = cvt[j++];
+               case 'E':
+               case 'f':
+                       s = ap_php_conv_fp(fmt, number, 0, precision,
+                                               &is_negative, &num_buf[1], &s_len);
+                       if (is_negative) {
+                               num_buf[0] = '-';
+                               s = num_buf;
+                               s_len++;
+                       } else if (always_sign) {
+                               num_buf[0] = '+';
+                               s = num_buf;
+                               s_len++;
                        }
-               } else {
-                       numbuf[i++] = '0';
-               }
-               
-               numbuf[i++] = fmt;
-               exp_p = php_convert_to_decimal(decpt, 0, &dec2, &sign, 0);
-               numbuf[i++] = sign ? '-' : '+';
-               if (*exp_p) { 
-                       while (*exp_p) {
-                               numbuf[i++] = *(exp_p++);
+                       break;
+
+               case 'g':
+               case 'G':
+                       if (precision == 0)
+                               precision = 1;
+                       /*
+                        * * We use &num_buf[ 1 ], so that we have room for the sign
+                        */
+                       s = bsd_gcvt(number, precision, &num_buf[1]);
+                       is_negative = 0;
+                       if (*s == '-') {
+                               is_negative = 1;
+                               s = &num_buf[1];
+                       } else if (always_sign) {
+                               num_buf[0] = '+';
+                               s = num_buf;
                        }
-               } else {
-                       numbuf[i++] = '0';
-               }
-       } else {
-               numbuf[i++] = cvt[j++];
-               if (precision > 0)
-                       numbuf[i++] = decimal_point;
-       }
 
-       while (cvt[j]) {
-               numbuf[i++] = cvt[j++];
-       }
+                       s_len = strlen(s);
 
-       numbuf[i] = '\0';
+                       if (fmt == 'G' && (q = strchr(s, 'e')) != NULL) {
+                               *q = 'E';
+                       }
+                       break;
+       }
 
-       php_sprintf_appendstring(buffer, pos, size, numbuf, width, 0, padding,
-                                                        alignment, i, sign, 0, always_sign);
+       php_sprintf_appendstring(buffer, pos, size, s, width, 0, padding,
+                                                        alignment, s_len, is_negative, 0, always_sign);
 }
 
 
@@ -690,7 +551,10 @@ php_formatted_print(int ht, int *len, int use_array, int format_offset TSRMLS_DC
                                                                                  width, padding, alignment);
                                        break;
 
+                               case 'g':
+                               case 'G':
                                case 'e':
+                               case 'E':
                                case 'f':
                                case 'F':
                                        /* XXX not done */
index 173f57b72c1c5ebec02d765abdc5cd19adc67dc7..edbcb1f0f008566e4e3b645950896f279551b545 100644 (file)
@@ -15,11 +15,11 @@ foreach(array(1e2, 5.2e25, 85.29e-23, 9e-9) AS $value) {
 d:100;
 float\(100\)
 
-d:5\.2E\+25;
+d:5[0-9]*;
 float\(5\.2E\+25\)
 
 d:8\.52[89][0-9]+E-22;
 float\(8\.529E-22\)
 
-d:9\.[0-9]*E-9;
+d:8\.[9]*[0-9]*E-9;
 float\(9\.0E-9\)
index 6135270d23ee857294882c72fafd1281ad37a2da..6cba6d10b4d7fbaf16116790b7e42de2a7816565 100755 (executable)
@@ -37,4 +37,4 @@ string(7) "-5.60  "
 string(7) "-005.60"
 string(7) "-5.6000"
 
-string(105) "12345678%d00000000000000000000000000000000000000000000000000.0000"
\ No newline at end of file
+string(105) "1234567%d.0000"
index caaf3b78c0458302beeb44539618dd7545ef9ef1..3dd2ebf93fff62d50d0e8f7f079abe3ee779b17e 100644 (file)
 
 /* $Id$ */
 
+
+#include "php.h"
+
+#include <zend_strtod.h>
+
+#include <stddef.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
+/*
+ * Copyright (c) 2002, 2006 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+static char * __cvt(double value, int ndigit, int *decpt, int *sign, int fmode, int pad)
+{
+       register char *s = NULL;
+       char *p, *rve, c;
+       size_t siz;
+
+       if (ndigit < 0) {
+               siz = -ndigit + 1;
+       } else {
+               siz = ndigit + 1;
+       }
+
+       /* __dtoa() doesn't allocate space for 0 so we do it by hand */
+       if (value == 0.0) {
+               *decpt = 1 - fmode; /* 1 for 'e', 0 for 'f' */
+               *sign = 0;
+               if ((rve = s = (char *)malloc(ndigit?siz:2)) == NULL)
+                       return(NULL);
+               *rve++ = '0';
+               *rve = '\0';
+               if (!ndigit) {
+                       return(s);
+               }
+       } else {
+               p = zend_dtoa(value, fmode + 2, ndigit, decpt, sign, &rve);
+               if (*decpt == 9999) {
+                       /* Infinity or Nan, convert to inf or nan like printf */
+                       *decpt = 0;
+                       c = *p;
+                       zend_freedtoa(p);
+                       return(c == 'I' ? "inf" : "nan");
+               }
+               /* Make a local copy and adjust rve to be in terms of s */
+               if (pad && fmode)
+                       siz += *decpt;
+               if ((s = (char *)malloc(siz+1)) == NULL) {
+                       zend_freedtoa(p);
+                       return(NULL);
+               }
+               (void) strlcpy(s, p, siz);
+               rve = s + (rve - p);
+               zend_freedtoa(p);
+       }
+
+       /* Add trailing zeros */
+       if (pad) {
+               siz -= rve - s;
+               while (--siz)
+                       *rve++ = '0';
+               *rve = '\0';
+       }
+
+       return(s);
+}
+
+char *bsd_ecvt(double value, int ndigit, int *decpt, int *sign)
+{
+       return(__cvt(value, ndigit, decpt, sign, 0, 1));
+}
+
+char *bsd_fcvt(double value, int ndigit, int *decpt, int *sign)
+{
+    return(__cvt(value, ndigit, decpt, sign, 1, 1));
+}
+
+char *bsd_gcvt(double value, int ndigit, char *buf)
+{
+       char *digits, *dst, *src;
+       int i, decpt, sign;
+       struct lconv *lconv;
+
+       lconv = localeconv();
+
+       digits = zend_dtoa(value, 2, ndigit, &decpt, &sign, NULL);
+       if (decpt == 9999) {
+               /*
+                * Infinity or NaN, convert to inf or nan with sign.
+                * We assume the buffer is at least ndigit long.
+                */
+               snprintf(buf, ndigit + 1, "%s%s", sign ? "-" : "",
+                               *digits == 'I' ? "inf" : "nan");
+               zend_freedtoa(digits);
+               return (buf);
+       }
+
+       dst = buf;
+       if (sign)
+               *dst++ = '-';
+
+       for (i = 0; i < ndigit && digits[i] != '\0'; i++);
+       
+       if ((decpt >= 0 && decpt - i > 4)
+                       || (decpt < 0 && decpt < -3)) {     /* use E-style */
+               /* exponential format (e.g. 1.2345e+13) */
+               if (--decpt < 0) {
+                       sign = 1;
+                       decpt = -decpt;
+               } else
+                       sign = 0;
+               src = digits;
+               *dst++ = *src++;
+               *dst++ = *lconv->decimal_point;
+               if (*src == '\0') {
+                       *dst++ = '0';
+               } else {
+                       do {
+                               *dst++ = *src++;
+                       } while (*src != '\0');
+               }
+               *dst++ = 'e';
+               if (sign)
+                       *dst++ = '-';
+               else
+                       *dst++ = '+';
+               if (decpt < 10) {
+                       *dst++ = '0' + decpt;
+                       *dst = '\0';
+               } else {
+                       /* XXX - optimize */
+                       for (sign = decpt, i = 0; (sign /= 10) != 0; i++)
+                               continue;
+                       dst[i + 1] = '\0';
+                       while (decpt != 0) {
+                               dst[i--] = '0' + decpt % 10;
+                               decpt /= 10;
+                       }
+               }
+       } else if (decpt < 0) {
+               /* standard format 0. */
+               *dst++ = '0';   /* zero before decimal point */
+               *dst++ = *lconv->decimal_point;
+               do {
+                       *dst++ = '0';
+               } while (++decpt < 0);
+               src = digits;
+               while (*src != '\0') {
+                       *dst++ = *src++;
+               }
+               *dst = '\0';
+       } else {
+               /* standard format */
+               for (i = 0, src = digits; i < decpt; i++) {
+                       if (*src != '\0')
+                               *dst++ = *src++;
+                       else
+                               *dst++ = '0';
+               }
+               if (*src != '\0') {
+                       if (src == digits)
+                               *dst++ = '0';   /* zero before decimal point */
+                       *dst++ = *lconv->decimal_point;
+                       for (i = decpt; digits[i] != '\0'; i++) {
+                *dst++ = digits[i];
+            }
+        }
+        *dst = '\0';
+    }
+    zend_freedtoa(digits);
+    return (buf);
+}
+
+
 /* ====================================================================
  * Copyright (c) 1995-1998 The Apache Group.  All rights reserved.
  *
  * <panos@alumni.cs.colorado.edu> for xinetd.
  */
 
-#include "php.h"
-
-#include <stddef.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <stdarg.h>
-#include <string.h>
-#include <stdlib.h>
-#include <math.h>
-#ifdef HAVE_INTTYPES_H
-#include <inttypes.h>
-#endif
-
 #define FALSE                  0
 #define TRUE                   1
 #define NUL                    '\0'
@@ -171,14 +361,17 @@ char * ap_php_conv_fp(register char format, register double num,
                 boolean_e add_dp, int precision, bool_int * is_negative, char *buf, int *len)
 {
        register char *s = buf;
-       register char *p;
+       register char *p, *p_orig;
        int decimal_point;
-       char buf1[NDIG];
+
+       if (precision >= NDIG - 1) {
+               precision = NDIG - 2;
+       }
 
        if (format == 'f')
-               p = ap_php_fcvt(num, precision, &decimal_point, is_negative, buf1);
+               p_orig = p = bsd_fcvt(num, precision, &decimal_point, is_negative);
        else                                            /* either e or E format */
-               p = ap_php_ecvt(num, precision + 1, &decimal_point, is_negative, buf1);
+               p_orig = p = bsd_ecvt(num, precision + 1, &decimal_point, is_negative);
 
        /*
         * Check for Infinity and NaN
@@ -187,17 +380,20 @@ char * ap_php_conv_fp(register char format, register double num,
                *len = strlen(p);
                memcpy(buf, p, *len + 1);
                *is_negative = FALSE;
+               free(p_orig);
                return (buf);
        }
        if (format == 'f') {
                if (decimal_point <= 0) {
-                       *s++ = '0';
-                       if (precision > 0) {
-                               *s++ = '.';
-                               while (decimal_point++ < 0)
-                                       *s++ = '0';
-                       } else if (add_dp) {
-                               *s++ = '.';
+                       if (num != 0 || precision > 0) {
+                               *s++ = '0';
+                               if (precision > 0) {
+                                       *s++ = '.';
+                                       while (decimal_point++ < 0)
+                                               *s++ = '0';
+                               } else if (add_dp) {
+                                       *s++ = '.';
+                               }
                        }
                } else {
                        int addz = decimal_point >= NDIG ? decimal_point - NDIG + 1 : 0;
@@ -239,21 +435,18 @@ char * ap_php_conv_fp(register char format, register double num,
                        /*
                         * Make sure the exponent has at least 2 digits
                         */
-                       if (t_len == 1)
-                               *s++ = '0';
                        while (t_len--)
                                *s++ = *p++;
                } else {
                        *s++ = '+';
                        *s++ = '0';
-                       *s++ = '0';
                }
        }
        *len = s - buf;
+       free(p_orig);
        return (buf);
 }
 
-
 /*
  * Convert num to a base X number where X is a power of 2. nbits determines X.
  * For example, if nbits is 3, we do base 8 conversion
@@ -283,189 +476,6 @@ char * ap_php_conv_p2(register u_wide_int num, register int nbits,
        return (p);
 }
 
-/*
- * cvt.c - IEEE floating point formatting routines for FreeBSD
- * from GNU libc-4.6.27
- */
-
-/*
- *    ap_php_ecvt converts to decimal
- *      the number of digits is specified by ndigit
- *      decpt is set to the position of the decimal point
- *      sign is set to 0 for positive, 1 for negative
- */
-
-
-char * ap_php_cvt(double arg, int ndigits, int *decpt, int *sign, int eflag, char *buf)
-{
-       register int r2;
-       int mvl;
-       double fi, fj;
-       register char *p, *p1;
-
-       if (ndigits >= NDIG - 1)
-               ndigits = NDIG - 2;
-       r2 = 0;
-       *sign = 0;
-       p = &buf[0];
-       if (arg < 0) {
-               *sign = 1;
-               arg = -arg;
-       }
-       arg = modf(arg, &fi);
-       p1 = &buf[NDIG];
-       /*
-        * Do integer part
-        */
-       if (fi != 0) {
-               while (fi != 0) {
-                       fj = modf(fi / 10, &fi);
-                       if (p1 <= &buf[0]) {
-                               mvl = NDIG - ndigits;
-                               if (ndigits > 0) {
-                                       memmove(&buf[mvl], &buf[0], NDIG-mvl-1);
-                               }
-                               p1 += mvl;
-                       }
-                       *--p1 = (int) ((fj + .03) * 10) + '0';
-                       r2++;
-               }
-               while (p1 < &buf[NDIG]) {
-                       *p++ = *p1++;
-               }
-       } else if (arg > 0) {
-               while ((fj = arg * 10) < 1) {
-                       if (!eflag && (r2 * -1) < ndigits) {
-                               break;
-                       }
-                       arg = fj;
-                       r2--;
-               }
-       }
-       p1 = &buf[ndigits];
-       if (eflag == 0)
-               p1 += r2;
-       *decpt = r2;
-       if (p1 < &buf[0]) {
-               buf[0] = '\0';
-               return (buf);
-       }
-       if (p <= p1 && p < &buf[NDIG]) {
-               arg = modf(arg * 10, &fj);
-               if ((int)fj==10) {
-                       *p++ = '1';
-                       fj = 0;
-                       *decpt = ++r2;
-               }
-               while (p <= p1 && p < &buf[NDIG]) {
-                       *p++ = (int) fj + '0';
-                       arg = modf(arg * 10, &fj);
-               }
-       }
-       if (p1 >= &buf[NDIG]) {
-               buf[NDIG - 1] = '\0';
-               return (buf);
-       }
-       p = p1;
-       *p1 += 5;
-       while (*p1 > '9') {
-               *p1 = '0';
-               if (p1 > buf)
-                       ++ * --p1;
-               else {
-                       *p1 = '1';
-                       (*decpt)++;
-                       if (eflag == 0) {
-                               if (p > buf)
-                                       *p = '0';
-                               p++;
-                       }
-               }
-       }
-       *p = '\0';
-       return (buf);
-}
-
-char * ap_php_ecvt(double arg, int ndigits, int *decpt, int *sign, char *buf)
-{
-       return (ap_php_cvt(arg, ndigits, decpt, sign, 1, buf));
-}
-
-char * ap_php_fcvt(double arg, int ndigits, int *decpt, int *sign, char *buf)
-{
-       return (ap_php_cvt(arg, ndigits, decpt, sign, 0, buf));
-}
-
-/*
- * ap_php_gcvt  - Floating output conversion to
- * minimal length string
- */
-
-char * ap_php_gcvt(double number, int ndigit, char *buf, boolean_e altform)
-{
-       int sign, decpt;
-       register char *p1, *p2;
-       register int i;
-       char buf1[NDIG];
-
-       if (ndigit >= NDIG - 1) {
-               ndigit = NDIG - 2;      
-       }
-
-       p1 = ap_php_ecvt(number, ndigit, &decpt, &sign, buf1);
-       p2 = buf;
-       if (sign)
-               *p2++ = '-';
-       for (i = ndigit - 1; i > 0 && p1[i] == '0'; i--)
-               ndigit--;
-       if ((decpt >= 0 && decpt - ndigit > 4)
-               || (decpt < 0 && decpt < -3)) {         /* use E-style */
-               decpt--;
-               *p2++ = *p1++;
-               *p2++ = '.';
-               for (i = 1; i < ndigit; i++)
-                       *p2++ = *p1++;
-               if (*(p2 - 1) == '.') {
-                       *p2++ = '0';
-               }       
-               *p2++ = 'e';
-               if (decpt < 0) {
-                       decpt = -decpt;
-                       *p2++ = '-';
-               } else
-                       *p2++ = '+';
-               if (decpt / 100 > 0)
-                       *p2++ = decpt / 100 + '0';
-               if (decpt / 10 > 0)
-                       *p2++ = (decpt % 100) / 10 + '0';
-               *p2++ = decpt % 10 + '0';
-       } else {
-               if (decpt <= 0) {
-                       if (*p1 != '0') {
-                               *p2++ = '0';
-                               *p2++ = '.';
-                       }
-                       while (decpt < 0) {
-                               decpt++;
-                               *p2++ = '0';
-                       }
-               }
-               for (i = 1; i <= ndigit; i++) {
-                       *p2++ = *p1++;
-                       if (i == decpt)
-                               *p2++ = '.';
-               }
-               if (ndigit < decpt) {
-                       while (ndigit++ < decpt)
-                               *p2++ = '0';
-                       *p2++ = '.';
-               }
-       }
-       if (p2[-1] == '.' && !altform)
-               p2--;
-       *p2 = '\0';
-       return (buf);
-}
 
 /*
  * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions
@@ -909,7 +919,7 @@ static int format_converter(register buffy * odp, const char *fmt,
                                        pad_char = ' ';
                                        break;
 
-
+                               
                                case 'f':
                                case 'e':
                                case 'E':
@@ -979,8 +989,7 @@ static int format_converter(register buffy * odp, const char *fmt,
                                        /*
                                         * * We use &num_buf[ 1 ], so that we have room for the sign
                                         */
-                                       s = ap_php_gcvt(fp_num, precision, &num_buf[1],
-                                                       alternate_form);
+                                       s = bsd_gcvt(fp_num, precision, &num_buf[1]);
                                        if (*s == '-')
                                                prefix_char = *s++;
                                        else if (print_sign)
index 38575b2b2ffd44547310fcb040c1828f59a11ac2..2512ca79b3a46b548f4ad0b645367f56a8b6db01 100644 (file)
@@ -106,11 +106,6 @@ typedef enum {
        LM_LONG_DOUBLE
 } length_modifier_e;
 
-extern char * ap_php_cvt(double arg, int ndigits, int *decpt, int *sign, int eflag, char *buf);
-extern char * ap_php_ecvt(double arg, int ndigits, int *decpt, int *sign, char *buf);
-extern char * ap_php_fcvt(double arg, int ndigits, int *decpt, int *sign, char *buf);
-extern char * ap_php_gcvt(double number, int ndigit, char *buf, boolean_e altform);
-
 #ifdef PHP_WIN32
 # define WIDE_INT              __int64
 #elif SIZEOF_LONG_LONG_INT
@@ -134,6 +129,9 @@ extern char * ap_php_conv_fp(register char format, register double num,
 extern char * ap_php_conv_p2(register u_wide_int num, register int nbits,
                 char format, char *buf_end, register int *len);
 
+extern char * bsd_ecvt(double value, int ndigit, int *decpt, int *sign);
+extern char * bsd_fcvt(double value, int ndigit, int *decpt, int *sign);
+extern char * bsd_gcvt(double value, int ndigit, char *buf);
 
 #endif /* SNPRINTF_H */
 
index 477c03100f33088a02e24d6dd0214235b117cf1c..c46bd70c61d7b3003f19cd559665e7b6ee6b8d03 100644 (file)
@@ -685,8 +685,7 @@ fmt_string:
                                        /*
                                         * * We use &num_buf[ 1 ], so that we have room for the sign
                                         */
-                                       s = ap_php_gcvt(fp_num, precision, &num_buf[1],
-                                                       alternate_form);
+                                       s = bsd_gcvt(fp_num, precision, &num_buf[1]);
                                        if (*s == '-')
                                                prefix_char = *s++;
                                        else if (print_sign)