xref: /openbsd-src/lib/libc/stdlib/ecvt.c (revision bf198cc6eba0ca1f6d79f71e8e2243d386241fa8)
1*bf198cc6Smillert /*	$OpenBSD: ecvt.c,v 1.11 2019/01/25 00:19:25 millert Exp $	*/
280944f19Smillert 
380944f19Smillert /*
4*bf198cc6Smillert  * Copyright (c) 2002, 2006 Todd C. Miller <millert@openbsd.org>
580944f19Smillert  *
606f01696Smillert  * Permission to use, copy, modify, and distribute this software for any
706f01696Smillert  * purpose with or without fee is hereby granted, provided that the above
806f01696Smillert  * copyright notice and this permission notice appear in all copies.
980944f19Smillert  *
10328f1f07Smillert  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11328f1f07Smillert  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12328f1f07Smillert  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13328f1f07Smillert  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14328f1f07Smillert  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15328f1f07Smillert  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16328f1f07Smillert  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17328f1f07Smillert  *
18328f1f07Smillert  * Sponsored in part by the Defense Advanced Research Projects
19328f1f07Smillert  * Agency (DARPA) and Air Force Research Laboratory, Air Force
20328f1f07Smillert  * Materiel Command, USAF, under agreement number F39502-99-1-0512.
2180944f19Smillert  */
2280944f19Smillert 
2380944f19Smillert #include <stdio.h>
2480944f19Smillert #include <stdlib.h>
2580944f19Smillert #include <string.h>
26def3c8f6Sguenther #include "gdtoa.h"
2780944f19Smillert 
2880944f19Smillert static char *__cvt(double, int, int *, int *, int, int);
2980944f19Smillert 
3080944f19Smillert static char *
__cvt(double value,int ndigit,int * decpt,int * sign,int fmode,int pad)3180944f19Smillert __cvt(double value, int ndigit, int *decpt, int *sign, int fmode, int pad)
3280944f19Smillert {
3380944f19Smillert 	static char *s;
3457536318Sderaadt 	char *p, *rve, c;
3580944f19Smillert 	size_t siz;
3680944f19Smillert 
3780944f19Smillert 	if (ndigit == 0) {
3880944f19Smillert 		*sign = value < 0.0;
3980944f19Smillert 		*decpt = 0;
4080944f19Smillert 		return ("");
4180944f19Smillert 	}
4280944f19Smillert 
4380944f19Smillert 	free(s);
4480944f19Smillert 	s = NULL;
4580944f19Smillert 
4680944f19Smillert 	if (ndigit < 0)
4780944f19Smillert 		siz = -ndigit + 1;
4880944f19Smillert 	else
4980944f19Smillert 		siz = ndigit + 1;
5080944f19Smillert 
5180944f19Smillert 
5280944f19Smillert 	/* __dtoa() doesn't allocate space for 0 so we do it by hand */
5380944f19Smillert 	if (value == 0.0) {
5480944f19Smillert 		*decpt = 1 - fmode;	/* 1 for 'e', 0 for 'f' */
5580944f19Smillert 		*sign = 0;
56fa713987Sderaadt 		if ((rve = s = malloc(siz)) == NULL)
5780944f19Smillert 			return(NULL);
5880944f19Smillert 		*rve++ = '0';
5980944f19Smillert 		*rve = '\0';
6080944f19Smillert 	} else {
6180944f19Smillert 		p = __dtoa(value, fmode + 2, ndigit, decpt, sign, &rve);
62384cfdc1Smartynas 		if (p == NULL)
63384cfdc1Smartynas 			return (NULL);
6480944f19Smillert 		if (*decpt == 9999) {
653a59a6c9Smillert 			/* Infinity or Nan, convert to inf or nan like printf */
6680944f19Smillert 			*decpt = 0;
6757536318Sderaadt 			c = *p;
6857536318Sderaadt 			__freedtoa(p);
6957536318Sderaadt 			return(c == 'I' ? "inf" : "nan");
7080944f19Smillert 		}
713a59a6c9Smillert 		/* Make a local copy and adjust rve to be in terms of s */
7280944f19Smillert 		if (pad && fmode)
7380944f19Smillert 			siz += *decpt;
74fa713987Sderaadt 		if ((s = malloc(siz)) == NULL) {
7557536318Sderaadt 			__freedtoa(p);
7680944f19Smillert 			return(NULL);
7757536318Sderaadt 		}
7880944f19Smillert 		(void) strlcpy(s, p, siz);
7980944f19Smillert 		rve = s + (rve - p);
8057536318Sderaadt 		__freedtoa(p);
8180944f19Smillert 	}
8280944f19Smillert 
833a59a6c9Smillert 	/* Add trailing zeros */
843a59a6c9Smillert 	if (pad) {
8580944f19Smillert 		siz -= rve - s;
8680944f19Smillert 		while (--siz)
8780944f19Smillert 			*rve++ = '0';
8880944f19Smillert 		*rve = '\0';
8980944f19Smillert 	}
9080944f19Smillert 
9180944f19Smillert 	return(s);
9280944f19Smillert }
9380944f19Smillert 
9480944f19Smillert char *
ecvt(double value,int ndigit,int * decpt,int * sign)9580944f19Smillert ecvt(double value, int ndigit, int *decpt, int *sign)
9680944f19Smillert {
9780944f19Smillert 	return(__cvt(value, ndigit, decpt, sign, 0, 1));
9880944f19Smillert }
9980944f19Smillert 
10080944f19Smillert char *
fcvt(double value,int ndigit,int * decpt,int * sign)10180944f19Smillert fcvt(double value, int ndigit, int *decpt, int *sign)
10280944f19Smillert {
10380944f19Smillert 	return(__cvt(value, ndigit, decpt, sign, 1, 1));
10480944f19Smillert }
105