@ -0,0 +1,172 @@ | |||
.\" $OpenBSD | |||
.\" | |||
.\" Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com> | |||
.\" All rights reserved. | |||
.\" | |||
.\" Redistribution and use in source and binary forms, with or without | |||
.\" modification, are permitted provided that the following conditions | |||
.\" are met: | |||
.\" 1. Redistributions of source code must retain the above copyright | |||
.\" notice, this list of conditions and the following disclaimer. | |||
.\" 2. Redistributions in binary form must reproduce the above copyright | |||
.\" notice, this list of conditions and the following disclaimer in the | |||
.\" documentation and/or other materials provided with the distribution. | |||
.\" 3. The name of the author may not be used to endorse or promote products | |||
.\" derived from this software without specific prior written permission. | |||
.\" | |||
.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, | |||
.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY | |||
.\" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | |||
.\" THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |||
.\" EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |||
.\" PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |||
.\" OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |||
.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |||
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |||
.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
.\" | |||
.Dd December 1, 2002 | |||
.Dt ECVT 3 | |||
.Os | |||
.Sh NAME | |||
.Nm ecvt , | |||
.Nm fcvt , | |||
.Nm gcvt | |||
.Nd convert double to | |||
.Tn ASCII | |||
string | |||
.Sh SYNOPSIS | |||
.Fd #include <stdlib.h> | |||
.Ft char * | |||
.Fn ecvt "double value" "int ndigit" "int *decpt" "int *sign" | |||
.Ft char * | |||
.Fn fcvt "double value" "int ndigit" "int *decpt" "int *sign" | |||
.Ft char * | |||
.Fn gcvt "double value" "int ndigit" "char *buf" | |||
.Sh DESCRIPTION | |||
.Bf -symbolic | |||
These functions are provided for compatibility with legacy code. | |||
New code should use the | |||
.Xr snprintf 3 | |||
function for improved safety and portability. | |||
.Ef | |||
.Pp | |||
The | |||
.Fn ecvt , | |||
.Fn fcvt | |||
and | |||
.Fn gcvt | |||
functions convert the double precision floating-point number | |||
.Fa value | |||
to a NUL-terminated | |||
.Tn ASCII | |||
string. | |||
.Pp | |||
The | |||
.Fn ecvt | |||
function converts | |||
.Fa value | |||
to a NUL-terminated string of exactly | |||
.Fa ndigit | |||
digits and returns a pointer to that string. | |||
The result is padded with zeroes from left to right as needed. | |||
There are no leading zeroes unless | |||
.Fa value | |||
itself is 0. | |||
The least significant digit is rounded in an implementation-dependent manner. | |||
The position of the decimal point relative to the beginning of the string | |||
is stored in | |||
.Fa decpt . | |||
A negative value indicates that the decimal point is located | |||
to the left of the returned digits (this occurs when there is no | |||
whole number component to | |||
.Fa value ) . | |||
If | |||
.Fa value | |||
is zero, it is unspecified whether the integer pointed to by | |||
.Fa decpt | |||
will be 0 or 1. | |||
The decimal point itself is not included in the returned string. | |||
If the sign of the result is negative, the integer pointed to by | |||
.Fa sign | |||
is non-zero; otherwise, it is 0. | |||
.Pp | |||
If the converted value is out of range or is not representable, | |||
the contents of the returned string are unspecified. | |||
.Pp | |||
The | |||
.Fn fcvt | |||
function is identical to | |||
.Fn ecvt | |||
with the exception that | |||
.Fa ndigit | |||
specifies the number of digits after the decimal point (zero-padded as | |||
needed). | |||
.Pp | |||
The | |||
.Fn gcvt | |||
function converts | |||
.Fa value | |||
to a NUL-terminated string similar to the %g | |||
.Xr printf 3 | |||
format specifier and stores the result in | |||
.Fa buf . | |||
It produces | |||
.Fa ndigit | |||
significant digits similar to the %f | |||
.Xr printf 3 | |||
format specifier where possible. | |||
If | |||
.Fa ndigit | |||
does allow sufficient precision, the result is stored in | |||
exponential notation similar to the %e | |||
.Xr printf 3 | |||
format specifier. | |||
If | |||
.Fa value | |||
is less than zero, | |||
.Fa buf | |||
will be prefixed with a minus sign. | |||
A decimal point is included in the returned string if | |||
.Fa value | |||
is not a whole number. | |||
Unlike the | |||
.Fn ecvt | |||
and | |||
.Fn fcvt | |||
functions, | |||
.Fa buf | |||
is not zero-padded. | |||
.Sh RETURN VALUES | |||
The | |||
.Fn ecvt , | |||
.Fn fcvt | |||
and | |||
.Fn gcvt | |||
functions return a NUL-terminated string representation of | |||
.Fa value . | |||
.Sh WARNINGS | |||
The | |||
.Fn ecvt | |||
and | |||
.Fn fcvt | |||
functions return a pointer to internal storage space that will be | |||
overwritten by subsequent calls to either function. | |||
.Pp | |||
The maximum possible precision of the return value is limited by the | |||
precision of a double and may not be the same on all architectures. | |||
.Pp | |||
The | |||
.Xr snprintf 3 | |||
function is preferred over these functions for new code. | |||
.Sh SEE ALSO | |||
.Xr printf 3 , | |||
.Xr strtod 3 | |||
.Sh STANDARDS | |||
The | |||
.Fn ecvt , | |||
.Fn fcvt | |||
and | |||
.Fn gcvt | |||
functions conform to | |||
.St -susv3 . |
@ -0,0 +1,110 @@ | |||
/* $OpenBSD: ecvt.c,v 1.1 2002/12/02 15:38:54 millert Exp $ */ | |||
/* | |||
* Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com> | |||
* All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in the | |||
* documentation and/or other materials provided with the distribution. | |||
* 3. The name of the author may not be used to endorse or promote products | |||
* derived from this software without specific prior written permission. | |||
* | |||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, | |||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY | |||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | |||
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
*/ | |||
#if defined(LIBC_SCCS) && !defined(lint) | |||
static char rcsid[] = "$OpenBSD: ecvt.c,v 1.1 2002/12/02 15:38:54 millert Exp $"; | |||
#endif /* LIBC_SCCS and not lint */ | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
extern char *__dtoa(double, int, int, int *, int *, char **); | |||
static char *__cvt(double, int, int *, int *, int, int); | |||
static char * | |||
__cvt(double value, int ndigit, int *decpt, int *sign, int fmode, int pad) | |||
{ | |||
static char *s; | |||
char *p, *rve; | |||
size_t siz; | |||
if (ndigit == 0) { | |||
*sign = value < 0.0; | |||
*decpt = 0; | |||
return (""); | |||
} | |||
if (s) { | |||
free(s); | |||
s = NULL; | |||
} | |||
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(siz)) == NULL) | |||
return(NULL); | |||
*rve++ = '0'; | |||
*rve = '\0'; | |||
} else { | |||
p = __dtoa(value, fmode + 2, ndigit, decpt, sign, &rve); | |||
if (*decpt == 9999) { | |||
/* Nan or Infinity */ | |||
*decpt = 0; | |||
return(p); | |||
} | |||
/* make a local copy and adjust rve to be in terms of s */ | |||
if (pad && fmode) | |||
siz += *decpt; | |||
if ((s = (char *)malloc(siz)) == NULL) | |||
return(NULL); | |||
(void) strlcpy(s, p, siz); | |||
rve = s + (rve - p); | |||
} | |||
/* Add trailing zeros (unless we got NaN or Inf) */ | |||
if (pad && *decpt != 9999) { | |||
siz -= rve - s; | |||
while (--siz) | |||
*rve++ = '0'; | |||
*rve = '\0'; | |||
} | |||
return(s); | |||
} | |||
char * | |||
ecvt(double value, int ndigit, int *decpt, int *sign) | |||
{ | |||
return(__cvt(value, ndigit, decpt, sign, 0, 1)); | |||
} | |||
char * | |||
fcvt(double value, int ndigit, int *decpt, int *sign) | |||
{ | |||
return(__cvt(value, ndigit, decpt, sign, 1, 1)); | |||
} |
@ -0,0 +1,103 @@ | |||
/* $OpenBSD: gcvt.c,v 1.1 2002/12/02 15:38:54 millert Exp $ */ | |||
/* | |||
* Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com> | |||
* All rights reserved. | |||
* | |||
* Redistribution and use in source and binary forms, with or without | |||
* modification, are permitted provided that the following conditions | |||
* are met: | |||
* 1. Redistributions of source code must retain the above copyright | |||
* notice, this list of conditions and the following disclaimer. | |||
* 2. Redistributions in binary form must reproduce the above copyright | |||
* notice, this list of conditions and the following disclaimer in the | |||
* documentation and/or other materials provided with the distribution. | |||
* 3. The name of the author may not be used to endorse or promote products | |||
* derived from this software without specific prior written permission. | |||
* | |||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, | |||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY | |||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | |||
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
*/ | |||
#if defined(LIBC_SCCS) && !defined(lint) | |||
static char rcsid[] = "$OpenBSD: gcvt.c,v 1.1 2002/12/02 15:38:54 millert Exp $"; | |||
#endif /* LIBC_SCCS and not lint */ | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
extern char *__dtoa(double, int, int, int *, int *, char **); | |||
char * | |||
gcvt(double value, int ndigit, char *buf) | |||
{ | |||
char *digits, *dst, *src; | |||
int i, decpt, sign; | |||
if (ndigit == 0) { | |||
buf[0] = '\0'; | |||
return (buf); | |||
} | |||
digits = __dtoa(value, 2, ndigit, &decpt, &sign, NULL); | |||
if (decpt == 9999) | |||
return (strcpy(buf, digits)); | |||
dst = buf; | |||
if (sign) | |||
*dst++ = '-'; | |||
if (decpt < 0 || decpt > ndigit) { | |||
/* exponential format */ | |||
if (--decpt < 0) { | |||
sign = 1; | |||
decpt = -decpt; | |||
} else | |||
sign = 0; | |||
for (src = digits; *src != '\0'; ) | |||
*dst++ = *src++; | |||
*dst++ = 'e'; | |||
if (sign) | |||
*dst++ = '-'; | |||
else | |||
*dst++ = '+'; | |||
if (decpt < 10) { | |||
*dst++ = '0'; | |||
*dst++ = '0' + decpt; | |||
*dst = '\0'; | |||
} else { | |||
/* XXX - optimize */ | |||
for (sign = decpt, i = 0; (sign /= 10) != 0; i++) | |||
sign /= 10; | |||
while (decpt != 0) { | |||
dst[i--] = '0' + decpt % 10; | |||
decpt /= 10; | |||
} | |||
} | |||
} else { | |||
/* standard format */ | |||
for (i = 0, src = digits; i < decpt; i++) { | |||
if (*src != '\0') | |||
*dst++ = *src++; | |||
else | |||
*dst++ = '0'; | |||
} | |||
if (*src != '\0') { | |||
*dst++ = '.'; /* XXX - locale-specific (LC_NUMERIC) */ | |||
for (i = decpt; digits[i] != '\0'; i++) { | |||
*dst++ = digits[i]; | |||
} | |||
} | |||
*dst = '\0'; | |||
} | |||
return (buf); | |||
} |