From owner-freebsd-standards@FreeBSD.ORG Tue Apr 22 13:30:09 2003 Return-Path: Delivered-To: freebsd-standards@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id CB01937B404 for ; Tue, 22 Apr 2003 13:30:09 -0700 (PDT) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 8B2ED43FE3 for ; Tue, 22 Apr 2003 13:30:07 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.12.9/8.12.9) with ESMTP id h3MKU7Up019492 for ; Tue, 22 Apr 2003 13:30:07 -0700 (PDT) (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.9/8.12.9/Submit) id h3MKU7o0019488; Tue, 22 Apr 2003 13:30:07 -0700 (PDT) Resent-Date: Tue, 22 Apr 2003 13:30:07 -0700 (PDT) Resent-Message-Id: <200304222030.h3MKU7o0019488@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-standards@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, "Sergey A.Osokin" Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 72CED37B401 for ; Tue, 22 Apr 2003 13:26:51 -0700 (PDT) Received: from freebsd.org.ru (www.freebsd.org.ru [194.84.67.5]) by mx1.FreeBSD.org (Postfix) with ESMTP id A738E43FB1 for ; Tue, 22 Apr 2003 13:26:49 -0700 (PDT) (envelope-from osa@freebsd.org.ru) Received: by freebsd.org.ru (Postfix, from userid 1000) id 7D3D4C4; Wed, 23 Apr 2003 00:26:47 +0400 (MSD) Message-Id: <20030422202647.7D3D4C4@freebsd.org.ru> Date: Wed, 23 Apr 2003 00:26:47 +0400 (MSD) From: "Sergey A.Osokin" To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Subject: standards/51292: [PATCH] add ecvt()/fcvt()/gcvt() functions (SUSv3) X-BeenThere: freebsd-standards@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list Reply-To: "Sergey A.Osokin" List-Id: Standards compliance List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 22 Apr 2003 20:30:10 -0000 >Number: 51292 >Category: standards >Synopsis: [PATCH] add ecvt()/fcvt()/gcvt() functions (SUSv3) >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-standards >State: open >Quarter: >Keywords: >Date-Required: >Class: update >Submitter-Id: current-users >Arrival-Date: Tue Apr 22 13:30:06 PDT 2003 >Closed-Date: >Last-Modified: >Originator: Sergey A. Osokin >Release: FreeBSD 5.0-CURRENT i386 >Organization: n/a >Environment: System: FreeBSD 5.0-CURRENT i386 >Description: add ecvt()/fcvt()/gcvt() functions (SUSv3) (obtained from OpenBSD) + add locale-specific tricks >How-To-Repeat: >Fix: Index: src/lib/libc/stdlib/Makefile.inc =================================================================== RCS file: /home/ncvs/src/lib/libc/stdlib/Makefile.inc,v retrieving revision 1.45 diff -u -r1.45 Makefile.inc --- src/lib/libc/stdlib/Makefile.inc 5 Apr 2003 07:33:46 -0000 1.45 +++ src/lib/libc/stdlib/Makefile.inc 22 Apr 2003 16:44:44 -0000 @@ -5,13 +5,13 @@ .PATH: ${.CURDIR}/${MACHINE_ARCH}/stdlib ${.CURDIR}/stdlib MISRCS+=_Exit.c abort.c abs.c atexit.c atof.c atoi.c atol.c atoll.c \ - bsearch.c calloc.c div.c exit.c getenv.c getopt.c getopt_long.c \ - getsubopt.c grantpt.c hcreate.c heapsort.c imaxabs.c imaxdiv.c \ - insque.c labs.c ldiv.c llabs.c lldiv.c lsearch.c malloc.c merge.c \ - putenv.c qsort.c qsort_r.c radixsort.c rand.c random.c reallocf.c \ - realpath.c remque.c setenv.c strfmon.c strhash.c strtoimax.c \ - strtol.c strtoll.c strtoq.c strtoul.c strtoull.c strtoumax.c strtouq.c \ - system.c tdelete.c tfind.c tsearch.c twalk.c + bsearch.c calloc.c div.c exit.c ecvt.c gcvt.c getenv.c getopt.c \ + getopt_long.c getsubopt.c grantpt.c hcreate.c heapsort.c imaxabs.c \ + imaxdiv.c insque.c labs.c ldiv.c llabs.c lldiv.c lsearch.c malloc.c \ + merge.c putenv.c qsort.c qsort_r.c radixsort.c rand.c random.c \ + reallocf.c realpath.c remque.c setenv.c strfmon.c strhash.c \ + strtoimax.c strtol.c strtoll.c strtoq.c strtoul.c strtoull.c \ + strtoumax.c strtouq.c system.c tdelete.c tfind.c tsearch.c twalk.c # machine-dependent stdlib sources .if exists(${.CURDIR}/${MACHINE_ARCH}/stdlib/Makefile.inc) @@ -19,12 +19,13 @@ .endif MAN+= abort.3 abs.3 alloca.3 atexit.3 atof.3 atoi.3 atol.3 bsearch.3 \ - div.3 exit.3 getenv.3 getopt.3 getopt_long.3 getsubopt.3 grantpt.3 \ - hcreate.3 imaxabs.3 imaxdiv.3 insque.3 labs.3 ldiv.3 llabs.3 lldiv.3 \ - lsearch.3 malloc.3 memory.3 qsort.3 radixsort.3 rand.3 random.3 \ + div.3 ecvt.3 exit.3 getenv.3 getopt.3 getopt_long.3 getsubopt.3 \ + grantpt.3 hcreate.3 imaxabs.3 imaxdiv.3 insque.3 labs.3 ldiv.3 llabs.3 \ + lldiv.3 lsearch.3 malloc.3 memory.3 qsort.3 radixsort.3 rand.3 random.3 \ realpath.3 strfmon.3 strtod.3 strtol.3 strtoul.3 system.3 tsearch.3 MLINKS+=atol.3 atoll.3 +MLINKS+=ecvt.3 fcvt.3 ecvt.3 gcvt.3 MLINKS+=exit.3 _Exit.3 MLINKS+=getenv.3 putenv.3 getenv.3 setenv.3 getenv.3 unsetenv.3 MLINKS+=grantpt.3 posix_openpt.3 grantpt.3 ptsname.3 grantpt.3 unlockpt.3 --- /dev/null Tue Apr 22 14:58:19 2003 +++ src/lib/libc/stdlib/ecvt.3 Tue Apr 22 16:49:38 2003 @@ -0,0 +1,174 @@ +.\" $OpenBSD +.\" +.\" Copyright (c) 2002 Todd C. Miller +.\" 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 April 22, 2003 +.Dt ECVT 3 +.Os +.Sh NAME +.Nm ecvt , +.Nm fcvt , +.Nm gcvt +.Nd convert double to +.Tn ASCII +string +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.Fd #include +.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 . --- /dev/null Tue Apr 22 14:58:19 2003 +++ src/lib/libc/stdlib/ecvt.c Tue Apr 22 17:52:36 2003 @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2002 Todd C. Miller + * 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. + */ + +#include +#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 */ +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +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)); +} --- /dev/null Tue Apr 22 14:58:19 2003 +++ src/lib/libc/stdlib/gcvt.c Tue Apr 22 20:42:51 2003 @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2002 Todd C. Miller + * 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. + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$OpenBSD: gcvt.c,v 1.2 2003/04/02 02:43:50 millert Exp $"; +#endif /* LIBC_SCCS and not lint */ +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include "../locale/setlocale.h" /* for ENCODING_LEN */ + +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; + char *lang; + struct lconv *lc: + + if (ndigit == 0) { + buf[0] = '\0'; + return (buf); + } + + lang = getenv("LANG"); + + if (lang == NULL || *lang == '\0' || strlen(lang) > ENCODING_LEN || + (lang[0] == '.' && + (lang[1] == '\0' || (lang[1] == '.' && lang[2] == '\0'))) || + strchr(lang, '/') != NULL) + lang = "C"; + + if (setlocale(LC_ALL, lang) == NULL) + setlocale(LC_ALL, NULL); + + lc = localeconv(); + + digits = __dtoa(value, 2, ndigit, &decpt, &sign, NULL); + if (decpt == 9999) { + /* Infinity or NaN, assume buffer is at least ndigit long. */ + strlcpy(buf, digits, ndigit); + return (buf); + } + + dst = buf; + if (sign) + *dst++ = (*lc->negative_sign == '\0') ? '-' + : *lc->negative_sign; + + 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++ = (*lc->negative_sign == '\0') ? '-' + : *lc->negative_sign; + else + *dst++ = (*lc->positive_sign == '\0') ? '+' + : *lc->positive_sign; + 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++ = (*lc->decimal_point == '\0' ? '.' + : *lc->decimal_point; + for (i = decpt; digits[i] != '\0'; i++) { + *dst++ = digits[i]; + } + } + *dst = '\0'; + } + return (buf); +} Index: src/include/stdlib.h =================================================================== RCS file: /home/ncvs/src/include/stdlib.h,v retrieving revision 1.48 diff -u -r1.48 stdlib.h --- src/include/stdlib.h 12 Mar 2003 20:29:58 -0000 1.48 +++ src/include/stdlib.h 22 Apr 2003 16:44:45 -0000 @@ -176,10 +176,10 @@ /* XXX XSI requires pollution from here. We'd rather not. */ /* long a64l(const char *); */ double drand48(void); -/* char *ecvt(double, int, int * __restrict, int * __restrict); */ +char *ecvt(double, int, int * __restrict, int * __restrict); double erand48(unsigned short[3]); -/* char *fcvt(double, int, int * __restrict, int * __restrict); */ -/* char *gcvt(double, int, int * __restrict, int * __restrict); */ +char *fcvt(double, int, int * __restrict, int * __restrict); +char *gcvt(double, int, char *); #ifndef _GETSUBOPT_DECLARED int getsubopt(char **, char *const *, char **); #define _GETSUBOPT_DECLARED >Release-Note: >Audit-Trail: >Unformatted: