xref: /openbsd-src/lib/libc/stdlib/ecvt.c (revision 47911bd667ac77dc523b8a13ef40b012dbffa741)
1 /*	$OpenBSD: ecvt.c,v 1.1 2002/12/02 15:38:54 millert Exp $	*/
2 
3 /*
4  * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
19  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
21  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #if defined(LIBC_SCCS) && !defined(lint)
31 static char rcsid[] = "$OpenBSD: ecvt.c,v 1.1 2002/12/02 15:38:54 millert Exp $";
32 #endif /* LIBC_SCCS and not lint */
33 
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 
38 extern char *__dtoa(double, int, int, int *, int *, char **);
39 static char *__cvt(double, int, int *, int *, int, int);
40 
41 static char *
42 __cvt(double value, int ndigit, int *decpt, int *sign, int fmode, int pad)
43 {
44 	static char *s;
45 	char *p, *rve;
46 	size_t siz;
47 
48 	if (ndigit == 0) {
49 		*sign = value < 0.0;
50 		*decpt = 0;
51 		return ("");
52 	}
53 
54 	if (s) {
55 		free(s);
56 		s = NULL;
57 	}
58 
59 	if (ndigit < 0)
60 		siz = -ndigit + 1;
61 	else
62 		siz = ndigit + 1;
63 
64 
65 	/* __dtoa() doesn't allocate space for 0 so we do it by hand */
66 	if (value == 0.0) {
67 		*decpt = 1 - fmode;	/* 1 for 'e', 0 for 'f' */
68 		*sign = 0;
69 		if ((rve = s = (char *)malloc(siz)) == NULL)
70 			return(NULL);
71 		*rve++ = '0';
72 		*rve = '\0';
73 	} else {
74 		p = __dtoa(value, fmode + 2, ndigit, decpt, sign, &rve);
75 		if (*decpt == 9999) {
76 			/* Nan or Infinity */
77 			*decpt = 0;
78 			return(p);
79 		}
80 		/* make a local copy and adjust rve to be in terms of s */
81 		if (pad && fmode)
82 			siz += *decpt;
83 		if ((s = (char *)malloc(siz)) == NULL)
84 			return(NULL);
85 		(void) strlcpy(s, p, siz);
86 		rve = s + (rve - p);
87 	}
88 
89 	/* Add trailing zeros (unless we got NaN or Inf) */
90 	if (pad && *decpt != 9999) {
91 		siz -= rve - s;
92 		while (--siz)
93 			*rve++ = '0';
94 		*rve = '\0';
95 	}
96 
97 	return(s);
98 }
99 
100 char *
101 ecvt(double value, int ndigit, int *decpt, int *sign)
102 {
103 	return(__cvt(value, ndigit, decpt, sign, 0, 1));
104 }
105 
106 char *
107 fcvt(double value, int ndigit, int *decpt, int *sign)
108 {
109 	return(__cvt(value, ndigit, decpt, sign, 1, 1));
110 }
111