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