1 |
|
|
/* $OpenBSD: ecvt.c,v 1.10 2015/12/28 22:08:18 mmcc Exp $ */ |
2 |
|
|
|
3 |
|
|
/* |
4 |
|
|
* Copyright (c) 2002, 2006 Todd C. Miller <Todd.Miller@courtesan.com> |
5 |
|
|
* |
6 |
|
|
* Permission to use, copy, modify, and distribute this software for any |
7 |
|
|
* purpose with or without fee is hereby granted, provided that the above |
8 |
|
|
* copyright notice and this permission notice appear in all copies. |
9 |
|
|
* |
10 |
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
11 |
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
12 |
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
13 |
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
14 |
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
15 |
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
16 |
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
17 |
|
|
* |
18 |
|
|
* Sponsored in part by the Defense Advanced Research Projects |
19 |
|
|
* Agency (DARPA) and Air Force Research Laboratory, Air Force |
20 |
|
|
* Materiel Command, USAF, under agreement number F39502-99-1-0512. |
21 |
|
|
*/ |
22 |
|
|
|
23 |
|
|
#include <stdio.h> |
24 |
|
|
#include <stdlib.h> |
25 |
|
|
#include <string.h> |
26 |
|
|
#include "gdtoa.h" |
27 |
|
|
|
28 |
|
|
static char *__cvt(double, int, int *, int *, int, int); |
29 |
|
|
|
30 |
|
|
static char * |
31 |
|
|
__cvt(double value, int ndigit, int *decpt, int *sign, int fmode, int pad) |
32 |
|
|
{ |
33 |
|
|
static char *s; |
34 |
|
|
char *p, *rve, c; |
35 |
|
|
size_t siz; |
36 |
|
|
|
37 |
|
|
if (ndigit == 0) { |
38 |
|
|
*sign = value < 0.0; |
39 |
|
|
*decpt = 0; |
40 |
|
|
return (""); |
41 |
|
|
} |
42 |
|
|
|
43 |
|
|
free(s); |
44 |
|
|
s = NULL; |
45 |
|
|
|
46 |
|
|
if (ndigit < 0) |
47 |
|
|
siz = -ndigit + 1; |
48 |
|
|
else |
49 |
|
|
siz = ndigit + 1; |
50 |
|
|
|
51 |
|
|
|
52 |
|
|
/* __dtoa() doesn't allocate space for 0 so we do it by hand */ |
53 |
|
|
if (value == 0.0) { |
54 |
|
|
*decpt = 1 - fmode; /* 1 for 'e', 0 for 'f' */ |
55 |
|
|
*sign = 0; |
56 |
|
|
if ((rve = s = malloc(siz)) == NULL) |
57 |
|
|
return(NULL); |
58 |
|
|
*rve++ = '0'; |
59 |
|
|
*rve = '\0'; |
60 |
|
|
} else { |
61 |
|
|
p = __dtoa(value, fmode + 2, ndigit, decpt, sign, &rve); |
62 |
|
|
if (p == NULL) |
63 |
|
|
return (NULL); |
64 |
|
|
if (*decpt == 9999) { |
65 |
|
|
/* Infinity or Nan, convert to inf or nan like printf */ |
66 |
|
|
*decpt = 0; |
67 |
|
|
c = *p; |
68 |
|
|
__freedtoa(p); |
69 |
|
|
return(c == 'I' ? "inf" : "nan"); |
70 |
|
|
} |
71 |
|
|
/* Make a local copy and adjust rve to be in terms of s */ |
72 |
|
|
if (pad && fmode) |
73 |
|
|
siz += *decpt; |
74 |
|
|
if ((s = malloc(siz)) == NULL) { |
75 |
|
|
__freedtoa(p); |
76 |
|
|
return(NULL); |
77 |
|
|
} |
78 |
|
|
(void) strlcpy(s, p, siz); |
79 |
|
|
rve = s + (rve - p); |
80 |
|
|
__freedtoa(p); |
81 |
|
|
} |
82 |
|
|
|
83 |
|
|
/* Add trailing zeros */ |
84 |
|
|
if (pad) { |
85 |
|
|
siz -= rve - s; |
86 |
|
|
while (--siz) |
87 |
|
|
*rve++ = '0'; |
88 |
|
|
*rve = '\0'; |
89 |
|
|
} |
90 |
|
|
|
91 |
|
|
return(s); |
92 |
|
|
} |
93 |
|
|
|
94 |
|
|
char * |
95 |
|
|
ecvt(double value, int ndigit, int *decpt, int *sign) |
96 |
|
|
{ |
97 |
|
|
return(__cvt(value, ndigit, decpt, sign, 0, 1)); |
98 |
|
|
} |
99 |
|
|
|
100 |
|
|
char * |
101 |
|
|
fcvt(double value, int ndigit, int *decpt, int *sign) |
102 |
|
|
{ |
103 |
|
|
return(__cvt(value, ndigit, decpt, sign, 1, 1)); |
104 |
|
|
} |