Browse Source

Make gcvt() better match printf("%g") behavior, it now passes regress.

OK deraadt@
OPENBSD_4_9
millert 14 years ago
parent
commit
ee4033dab1
1 changed files with 23 additions and 11 deletions
  1. +23
    -11
      src/lib/libc/stdlib/gcvt.c

+ 23
- 11
src/lib/libc/stdlib/gcvt.c View File

@ -1,7 +1,8 @@
/* $OpenBSD: gcvt.c,v 1.11 2009/10/16 12:15:03 martynas Exp $ */
/* $OpenBSD: gcvt.c,v 1.12 2010/09/25 13:19:19 millert Exp $ */
/* /*
* Copyright (c) 2002, 2003, 2006 Todd C. Miller <Todd.Miller@courtesan.com>
* Copyright (c) 2002, 2003, 2006, 2010
* Todd C. Miller <Todd.Miller@courtesan.com>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -28,6 +29,8 @@
extern char *__dtoa(double, int, int, int *, int *, char **); extern char *__dtoa(double, int, int, int *, int *, char **);
extern void __freedtoa(char *); extern void __freedtoa(char *);
#define DEFPREC 6
char * char *
gcvt(double value, int ndigit, char *buf) gcvt(double value, int ndigit, char *buf)
{ {
@ -36,9 +39,9 @@ gcvt(double value, int ndigit, char *buf)
struct lconv *lconv; struct lconv *lconv;
lconv = localeconv(); lconv = localeconv();
if (ndigit == 0) {
buf[0] = '\0';
return (buf);
if (ndigit <= 0) {
/* Match printf(3) behavior. */
ndigit = ndigit ? DEFPREC : 1;
} }
digits = __dtoa(value, 2, ndigit, &decpt, &sign, NULL); digits = __dtoa(value, 2, ndigit, &decpt, &sign, NULL);
@ -47,9 +50,10 @@ gcvt(double value, int ndigit, char *buf)
if (decpt == 9999) { if (decpt == 9999) {
/* /*
* Infinity or NaN, convert to inf or nan with sign. * Infinity or NaN, convert to inf or nan with sign.
* We assume the buffer is at least ndigit long.
* We can't infer buffer size based on ndigit.
* We have to assume it is at least 5 chars.
*/ */
snprintf(buf, ndigit + 1, "%s%s", sign ? "-" : "",
snprintf(buf, 5, "%s%s", sign ? "-" : "",
*digits == 'I' ? "inf" : "nan"); *digits == 'I' ? "inf" : "nan");
__freedtoa(digits); __freedtoa(digits);
return (buf); return (buf);
@ -59,7 +63,8 @@ gcvt(double value, int ndigit, char *buf)
if (sign) if (sign)
*dst++ = '-'; *dst++ = '-';
if (decpt < 0 || decpt > ndigit) {
/* Match printf(3) behavior for exponential vs. regular fomatting. */
if (decpt <= -4 || decpt > ndigit) {
/* exponential format (e.g. 1.2345e+13) */ /* exponential format (e.g. 1.2345e+13) */
if (--decpt < 0) { if (--decpt < 0) {
sign = 1; sign = 1;
@ -68,9 +73,12 @@ gcvt(double value, int ndigit, char *buf)
sign = 0; sign = 0;
src = digits; src = digits;
*dst++ = *src++; *dst++ = *src++;
*dst++ = *lconv->decimal_point;
while (*src != '\0')
*dst++ = *src++;
if (*src != '\0') {
*dst++ = *lconv->decimal_point;
do {
*dst++ = *src++;
} while (*src != '\0');
}
*dst++ = 'e'; *dst++ = 'e';
if (sign) if (sign)
*dst++ = '-'; *dst++ = '-';
@ -102,6 +110,10 @@ gcvt(double value, int ndigit, char *buf)
if (src == digits) if (src == digits)
*dst++ = '0'; /* zero before decimal point */ *dst++ = '0'; /* zero before decimal point */
*dst++ = *lconv->decimal_point; *dst++ = *lconv->decimal_point;
while (decpt < 0) {
*dst++ = '0';
decpt++;
}
for (i = decpt; digits[i] != '\0'; i++) { for (i = decpt; digits[i] != '\0'; i++) {
*dst++ = digits[i]; *dst++ = digits[i];
} }


Loading…
Cancel
Save