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