1 /* $OpenBSD: gcvt.c,v 1.5 2003/06/17 21:56:24 millert Exp $ */ 2 3 /* 4 * Copyright (c) 2002, 2003 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: gcvt.c,v 1.5 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 33 char * 34 gcvt(double value, int ndigit, char *buf) 35 { 36 char *digits, *dst, *src; 37 int i, decpt, sign; 38 39 if (ndigit == 0) { 40 buf[0] = '\0'; 41 return (buf); 42 } 43 44 digits = __dtoa(value, 2, ndigit, &decpt, &sign, NULL); 45 if (decpt == 9999) { 46 /* Infinity or NaN, assume buffer is at least ndigit long. */ 47 strlcpy(buf, digits, ndigit + 1); 48 return (buf); 49 } 50 51 dst = buf; 52 if (sign) 53 *dst++ = '-'; 54 55 if (decpt < 0 || decpt > ndigit) { 56 /* exponential format */ 57 if (--decpt < 0) { 58 sign = 1; 59 decpt = -decpt; 60 } else 61 sign = 0; 62 for (src = digits; *src != '\0'; ) 63 *dst++ = *src++; 64 *dst++ = 'e'; 65 if (sign) 66 *dst++ = '-'; 67 else 68 *dst++ = '+'; 69 if (decpt < 10) { 70 *dst++ = '0'; 71 *dst++ = '0' + decpt; 72 *dst = '\0'; 73 } else { 74 /* XXX - optimize */ 75 for (sign = decpt, i = 0; (sign /= 10) != 0; i++) 76 sign /= 10; 77 while (decpt != 0) { 78 dst[i--] = '0' + decpt % 10; 79 decpt /= 10; 80 } 81 } 82 } else { 83 /* standard format */ 84 for (i = 0, src = digits; i < decpt; i++) { 85 if (*src != '\0') 86 *dst++ = *src++; 87 else 88 *dst++ = '0'; 89 } 90 if (*src != '\0') { 91 *dst++ = '.'; /* XXX - locale-specific (LC_NUMERIC) */ 92 for (i = decpt; digits[i] != '\0'; i++) { 93 *dst++ = digits[i]; 94 } 95 } 96 *dst = '\0'; 97 } 98 return (buf); 99 } 100