use BSD licensed implementation of double-to-string utilities instead of LGPL one

this patch also fixes thread safety issues in zend_strtod()
This commit is contained in:
Antony Dovgal 2006-12-06 09:50:28 +00:00
parent d0792dc615
commit 4789badd3a
9 changed files with 1551 additions and 903 deletions

View 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;

File diff suppressed because it is too large Load Diff

View 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 |
@ -25,7 +25,12 @@
#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

View 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);
switch (fmt) {
case 'e':
if (precision) {
precision--;
}
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++;
}
break;
if (sign) {
numbuf[i++] = '-';
} else if (always_sign) {
numbuf[i++] = '+';
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;
}
s_len = strlen(s);
if (fmt == 'G' && (q = strchr(s, 'e')) != NULL) {
*q = 'E';
}
break;
}
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';
}
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++];
}
} 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++);
}
} else {
numbuf[i++] = '0';
}
} else {
numbuf[i++] = cvt[j++];
if (precision > 0)
numbuf[i++] = decimal_point;
}
while (cvt[j]) {
numbuf[i++] = cvt[j++];
}
numbuf[i] = '\0';
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 */

View 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\)

View File

@ -37,4 +37,4 @@ string(7) "-5.60 "
string(7) "-005.60"
string(7) "-5.6000"
string(105) "12345678%d00000000000000000000000000000000000000000000000000.0000"
string(105) "1234567%d.0000"

View File

@ -18,6 +18,210 @@
/* $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.
*
@ -73,20 +277,6 @@
* <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)

View 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 */

View 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)