summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormillert <>2010-09-25 13:19:19 +0000
committermillert <>2010-09-25 13:19:19 +0000
commit424deb351931af3fd885740bc351436321fad2f9 (patch)
tree3cf23e4a041ea0438257fe1b9ddf7281e18f5273 /src
parentca3efbcfa52175f6883523a4782ce280dd592054 (diff)
downloadopenbsd-424deb351931af3fd885740bc351436321fad2f9.tar.gz
openbsd-424deb351931af3fd885740bc351436321fad2f9.tar.bz2
openbsd-424deb351931af3fd885740bc351436321fad2f9.zip
Make gcvt() better match printf("%g") behavior, it now passes regress.
OK deraadt@
Diffstat (limited to 'src')
-rw-r--r--src/lib/libc/stdlib/gcvt.c34
1 files changed, 23 insertions, 11 deletions
diff --git a/src/lib/libc/stdlib/gcvt.c b/src/lib/libc/stdlib/gcvt.c
index e5488d912d..d9081a7d39 100644
--- a/src/lib/libc/stdlib/gcvt.c
+++ b/src/lib/libc/stdlib/gcvt.c
@@ -1,7 +1,8 @@
1/* $OpenBSD: gcvt.c,v 1.11 2009/10/16 12:15:03 martynas Exp $ */ 1/* $OpenBSD: gcvt.c,v 1.12 2010/09/25 13:19:19 millert Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2002, 2003, 2006 Todd C. Miller <Todd.Miller@courtesan.com> 4 * Copyright (c) 2002, 2003, 2006, 2010
5 * Todd C. Miller <Todd.Miller@courtesan.com>
5 * 6 *
6 * Permission to use, copy, modify, and distribute this software for any 7 * 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 * purpose with or without fee is hereby granted, provided that the above
@@ -28,6 +29,8 @@
28extern char *__dtoa(double, int, int, int *, int *, char **); 29extern char *__dtoa(double, int, int, int *, int *, char **);
29extern void __freedtoa(char *); 30extern void __freedtoa(char *);
30 31
32#define DEFPREC 6
33
31char * 34char *
32gcvt(double value, int ndigit, char *buf) 35gcvt(double value, int ndigit, char *buf)
33{ 36{
@@ -36,9 +39,9 @@ gcvt(double value, int ndigit, char *buf)
36 struct lconv *lconv; 39 struct lconv *lconv;
37 40
38 lconv = localeconv(); 41 lconv = localeconv();
39 if (ndigit == 0) { 42 if (ndigit <= 0) {
40 buf[0] = '\0'; 43 /* Match printf(3) behavior. */
41 return (buf); 44 ndigit = ndigit ? DEFPREC : 1;
42 } 45 }
43 46
44 digits = __dtoa(value, 2, ndigit, &decpt, &sign, NULL); 47 digits = __dtoa(value, 2, ndigit, &decpt, &sign, NULL);
@@ -47,9 +50,10 @@ gcvt(double value, int ndigit, char *buf)
47 if (decpt == 9999) { 50 if (decpt == 9999) {
48 /* 51 /*
49 * Infinity or NaN, convert to inf or nan with sign. 52 * Infinity or NaN, convert to inf or nan with sign.
50 * We assume the buffer is at least ndigit long. 53 * We can't infer buffer size based on ndigit.
54 * We have to assume it is at least 5 chars.
51 */ 55 */
52 snprintf(buf, ndigit + 1, "%s%s", sign ? "-" : "", 56 snprintf(buf, 5, "%s%s", sign ? "-" : "",
53 *digits == 'I' ? "inf" : "nan"); 57 *digits == 'I' ? "inf" : "nan");
54 __freedtoa(digits); 58 __freedtoa(digits);
55 return (buf); 59 return (buf);
@@ -59,7 +63,8 @@ gcvt(double value, int ndigit, char *buf)
59 if (sign) 63 if (sign)
60 *dst++ = '-'; 64 *dst++ = '-';
61 65
62 if (decpt < 0 || decpt > ndigit) { 66 /* Match printf(3) behavior for exponential vs. regular fomatting. */
67 if (decpt <= -4 || decpt > ndigit) {
63 /* exponential format (e.g. 1.2345e+13) */ 68 /* exponential format (e.g. 1.2345e+13) */
64 if (--decpt < 0) { 69 if (--decpt < 0) {
65 sign = 1; 70 sign = 1;
@@ -68,9 +73,12 @@ gcvt(double value, int ndigit, char *buf)
68 sign = 0; 73 sign = 0;
69 src = digits; 74 src = digits;
70 *dst++ = *src++; 75 *dst++ = *src++;
71 *dst++ = *lconv->decimal_point; 76 if (*src != '\0') {
72 while (*src != '\0') 77 *dst++ = *lconv->decimal_point;
73 *dst++ = *src++; 78 do {
79 *dst++ = *src++;
80 } while (*src != '\0');
81 }
74 *dst++ = 'e'; 82 *dst++ = 'e';
75 if (sign) 83 if (sign)
76 *dst++ = '-'; 84 *dst++ = '-';
@@ -102,6 +110,10 @@ gcvt(double value, int ndigit, char *buf)
102 if (src == digits) 110 if (src == digits)
103 *dst++ = '0'; /* zero before decimal point */ 111 *dst++ = '0'; /* zero before decimal point */
104 *dst++ = *lconv->decimal_point; 112 *dst++ = *lconv->decimal_point;
113 while (decpt < 0) {
114 *dst++ = '0';
115 decpt++;
116 }
105 for (i = decpt; digits[i] != '\0'; i++) { 117 for (i = decpt; digits[i] != '\0'; i++) {
106 *dst++ = digits[i]; 118 *dst++ = digits[i];
107 } 119 }