@ -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); | |||||
} |