1 /* $OpenBSD: ecvt.c,v 1.3 2003/06/17 21:56:24 millert Exp $ */ 2 3 /* 4 * Copyright (c) 2002 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 #if defined(LIBC_SCCS) && !defined(lint) 24 static char rcsid[] = "$OpenBSD: ecvt.c,v 1.3 2003/06/17 21:56:24 millert Exp $"; 25 #endif /* LIBC_SCCS and not lint */ 26 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <string.h> 30 31 extern char *__dtoa(double, int, int, int *, int *, char **); 32 static char *__cvt(double, int, int *, int *, int, int); 33 34 static char * 35 __cvt(double value, int ndigit, int *decpt, int *sign, int fmode, int pad) 36 { 37 static char *s; 38 char *p, *rve; 39 size_t siz; 40 41 if (ndigit == 0) { 42 *sign = value < 0.0; 43 *decpt = 0; 44 return (""); 45 } 46 47 if (s) { 48 free(s); 49 s = NULL; 50 } 51 52 if (ndigit < 0) 53 siz = -ndigit + 1; 54 else 55 siz = ndigit + 1; 56 57 58 /* __dtoa() doesn't allocate space for 0 so we do it by hand */ 59 if (value == 0.0) { 60 *decpt = 1 - fmode; /* 1 for 'e', 0 for 'f' */ 61 *sign = 0; 62 if ((rve = s = (char *)malloc(siz)) == NULL) 63 return(NULL); 64 *rve++ = '0'; 65 *rve = '\0'; 66 } else { 67 p = __dtoa(value, fmode + 2, ndigit, decpt, sign, &rve); 68 if (*decpt == 9999) { 69 /* Nan or Infinity */ 70 *decpt = 0; 71 return(p); 72 } 73 /* make a local copy and adjust rve to be in terms of s */ 74 if (pad && fmode) 75 siz += *decpt; 76 if ((s = (char *)malloc(siz)) == NULL) 77 return(NULL); 78 (void) strlcpy(s, p, siz); 79 rve = s + (rve - p); 80 } 81 82 /* Add trailing zeros (unless we got NaN or Inf) */ 83 if (pad && *decpt != 9999) { 84 siz -= rve - s; 85 while (--siz) 86 *rve++ = '0'; 87 *rve = '\0'; 88 } 89 90 return(s); 91 } 92 93 char * 94 ecvt(double value, int ndigit, int *decpt, int *sign) 95 { 96 return(__cvt(value, ndigit, decpt, sign, 0, 1)); 97 } 98 99 char * 100 fcvt(double value, int ndigit, int *decpt, int *sign) 101 { 102 return(__cvt(value, ndigit, decpt, sign, 1, 1)); 103 } 104