Module Name: src Committed By: martin Date: Thu Aug 22 19:40:51 UTC 2024
Modified Files: src/lib/libc/include [netbsd-9]: extern.h src/lib/libc/stdio [netbsd-9]: Makefile.inc vfwprintf.c src/tests/lib/libc/stdio [netbsd-9]: t_printf.c Log Message: Pull up following revision(s) (requested by riastradh in ticket #1865): lib/libc/stdio/Makefile.inc: revision 1.48 tests/lib/libc/stdio/t_printf.c: revision 1.9 lib/libc/stdio/vfwprintf.c: revision 1.40 lib/libc/include/extern.h: revision 1.27 tests/lib/libc/stdio/t_printf.c: revision 1.10 PR/57250: Martin Husemann: dtoa mishandles infinite doubles on 32bit big endian machines. When long double support was added, the old code was kept for the regular double code. This code was never used because WIDE_DOUBLE was always defined in the Makefile. Remove that old code, and conditionalize the WIDE_DOUBLE code based on if long doubles are different than doubles on the specific platform. Add a test for PR/57250 from Havard Eidnes Fix the test for "inf" output, also include newline in printf format... To generate a diff of this commit: cvs rdiff -u -r1.25 -r1.25.16.1 src/lib/libc/include/extern.h cvs rdiff -u -r1.47 -r1.47.18.1 src/lib/libc/stdio/Makefile.inc cvs rdiff -u -r1.36 -r1.36.8.1 src/lib/libc/stdio/vfwprintf.c cvs rdiff -u -r1.8 -r1.8.34.1 src/tests/lib/libc/stdio/t_printf.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libc/include/extern.h diff -u src/lib/libc/include/extern.h:1.25 src/lib/libc/include/extern.h:1.25.16.1 --- src/lib/libc/include/extern.h:1.25 Thu Jan 12 00:43:55 2017 +++ src/lib/libc/include/extern.h Thu Aug 22 19:40:50 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: extern.h,v 1.25 2017/01/12 00:43:55 christos Exp $ */ +/* $NetBSD: extern.h,v 1.25.16.1 2024/08/22 19:40:50 martin Exp $ */ /* * Copyright (c) 1997 Christos Zoulas. All rights reserved. @@ -49,11 +49,17 @@ struct sigaction; int __sigaction_sigtramp(int, const struct sigaction *, struct sigaction *, const void *, int); +/* is "long double" and "double" different? */ +#if (__LDBL_MANT_DIG__ != __DBL_MANT_DIG__) || \ + (__LDBL_MAX_EXP__ != __DBL_MAX_EXP__) +#define WIDE_DOUBLE +#endif + #ifdef WIDE_DOUBLE -char *__hdtoa(double, const char *, int, int *, int *, char **); char *__hldtoa(long double, const char *, int, int *, int *, char **); char *__ldtoa(long double *, int, int, int *, int *, char **); #endif +char *__hdtoa(double, const char *, int, int *, int *, char **); #ifndef __LIBC12_SOURCE__ struct syslog_data; Index: src/lib/libc/stdio/Makefile.inc diff -u src/lib/libc/stdio/Makefile.inc:1.47 src/lib/libc/stdio/Makefile.inc:1.47.18.1 --- src/lib/libc/stdio/Makefile.inc:1.47 Tue Dec 29 17:55:23 2015 +++ src/lib/libc/stdio/Makefile.inc Thu Aug 22 19:40:50 2024 @@ -1,11 +1,9 @@ # from: @(#)Makefile.inc 5.7 (Berkeley) 6/27/91 -# $NetBSD: Makefile.inc,v 1.47 2015/12/29 17:55:23 christos Exp $ +# $NetBSD: Makefile.inc,v 1.47.18.1 2024/08/22 19:40:50 martin Exp $ # stdio sources .PATH: ${.CURDIR}/stdio -CPPFLAGS+=-DWIDE_DOUBLE - SRCS+= clrerr.c dprintf.c fclose.c fdopen.c feof.c ferror.c \ fflush.c fgetc.c fgetln.c fgetpos.c fgets.c fgetstr.c fgetwc.c \ fgetwln.c fgetws.c fileno.c findfp.c flags.c flockfile.c fopen.c \ Index: src/lib/libc/stdio/vfwprintf.c diff -u src/lib/libc/stdio/vfwprintf.c:1.36 src/lib/libc/stdio/vfwprintf.c:1.36.8.1 --- src/lib/libc/stdio/vfwprintf.c:1.36 Tue Jul 11 19:36:38 2017 +++ src/lib/libc/stdio/vfwprintf.c Thu Aug 22 19:40:50 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: vfwprintf.c,v 1.36 2017/07/11 19:36:38 perseant Exp $ */ +/* $NetBSD: vfwprintf.c,v 1.36.8.1 2024/08/22 19:40:50 martin Exp $ */ /*- * Copyright (c) 1990, 1993 @@ -38,7 +38,7 @@ static char sccsid[] = "@(#)vfprintf.c 8.1 (Berkeley) 6/4/93"; __FBSDID("$FreeBSD: src/lib/libc/stdio/vfwprintf.c,v 1.27 2007/01/09 00:28:08 imp Exp $"); #else -__RCSID("$NetBSD: vfwprintf.c,v 1.36 2017/07/11 19:36:38 perseant Exp $"); +__RCSID("$NetBSD: vfwprintf.c,v 1.36.8.1 2024/08/22 19:40:50 martin Exp $"); #endif #endif /* LIBC_SCCS and not lint */ @@ -578,9 +578,6 @@ WDECL(vf,printf_l)(FILE * __restrict fp, #define DEFPREC 6 static int exponent(CHAR_T *, int, int); -#ifndef WIDE_DOUBLE -static char *cvt(double, int, int, char *, int *, int, int *); -#endif #endif /* !NO_FLOATING_POINT */ @@ -646,17 +643,14 @@ WDECL(__vf,printf_unlocked_l)(FILE *fp, * F: at least two digits for decimal, at least one digit for hex */ char *decimal_point; /* locale specific decimal point */ -#ifdef WIDE_DOUBLE int signflag; /* true if float is negative */ union { /* floating point arguments %[aAeEfFgG] */ double dbl; +#ifdef WIDE_DOUBLE long double ldbl; +#endif } fparg; char *dtoaend; /* pointer to end of converted digits */ -#else - double _double; /* double precision arguments %[eEfgG] */ - char softsign; /* temporary negative sign for floats */ -#endif char *dtoaresult; /* buffer allocated by dtoa */ int expt; /* integer value of exponent */ char expchar; /* exponent character: [eEpP\0] */ @@ -1055,7 +1049,6 @@ reswitch: switch (ch) { base = 10; goto number; #ifndef NO_FLOATING_POINT -#ifdef WIDE_DOUBLE case 'a': case 'A': if (ch == 'a') { @@ -1069,12 +1062,15 @@ reswitch: switch (ch) { } if (prec >= 0) prec++; +#ifdef WIDE_DOUBLE if (flags & LONGDBL) { fparg.ldbl = GETARG(long double); dtoaresult = __hldtoa(fparg.ldbl, xdigs, prec, &expt, &signflag, &dtoaend); - } else { + } else +#endif + { fparg.dbl = GETARG(double); dtoaresult = __hdtoa(fparg.dbl, xdigs, prec, @@ -1124,12 +1120,15 @@ reswitch: switch (ch) { fp_begin: if (prec < 0) prec = DEFPREC; +#ifdef WIDE_DOUBLE if (flags & LONGDBL) { fparg.ldbl = GETARG(long double); dtoaresult = __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec, &expt, &signflag, &dtoaend); - } else { + } else +#endif + { fparg.dbl = GETARG(double); dtoaresult = __dtoa(fparg.dbl, expchar ? 2 : 3, prec, @@ -1167,67 +1166,8 @@ fp_common: flags &= ~ZEROPAD; break; } -#else - case 'e': - case 'E': - case 'f': - case 'F': - case 'g': - case 'G': - if (prec == -1) { - prec = DEFPREC; - } else if ((ch == 'g' || ch == 'G') && prec == 0) { - prec = 1; - } - - if (flags & LONGDBL) { - _double = (double) GETARG(long double); - } else { - _double = GETARG(double); - } - - /* do this before tricky precision changes */ - if (isinf(_double)) { - if (_double < 0) - sign = '-'; - if (ch == 'E' || ch == 'F' || ch == 'G') - result = STRCONST("INF"); - else - result = STRCONST("inf"); - size = 3; - flags &= ~ZEROPAD; - break; - } - if (isnan(_double)) { - if (ch == 'E' || ch == 'F' || ch == 'G') - result = STRCONST("NAN"); - else - result = STRCONST("nan"); - size = 3; - flags &= ~ZEROPAD; - break; - } flags |= FPT; - dtoaresult = cvt(_double, prec, flags, &softsign, - &expt, ch, &ndig); - if (dtoaresult == NULL) - goto oomem; - if (convbuf != NULL) - free(convbuf); -#ifndef NARROW - result = convbuf = __mbsconv(dtoaresult, -1, loc); -#else - /*XXX inefficient*/ - result = convbuf = strdup(dtoaresult); -#endif - if (result == NULL) - goto oomem; - __freedtoa(dtoaresult); - if (softsign) - sign = '-'; -#endif - flags |= FPT; if (ch == 'g' || ch == 'G') { if (expt > -4 && expt <= prec) { /* Make %[gG] smell like %[fF] */ @@ -1993,57 +1933,7 @@ __grow_type_table (size_t nextarg, enum return 0; } - #ifndef NO_FLOATING_POINT -#ifndef WIDE_DOUBLE -static char * -cvt(double value, int ndigits, int flags, char *sign, int *decpt, int ch, - int *length) -{ - int mode, dsgn; - char *digits, *bp, *rve; - - _DIAGASSERT(decpt != NULL); - _DIAGASSERT(length != NULL); - _DIAGASSERT(sign != NULL); - - if (ch == 'f') { - mode = 3; /* ndigits after the decimal point */ - } else { - /* To obtain ndigits after the decimal point for the 'e' - * and 'E' formats, round to ndigits + 1 significant - * figures. - */ - if (ch == 'e' || ch == 'E') { - ndigits++; - } - mode = 2; /* ndigits significant digits */ - } - - digits = __dtoa(value, mode, ndigits, decpt, &dsgn, &rve); - if (digits == NULL) - return NULL; - if (dsgn) { - value = -value; - *sign = '-'; - } else - *sign = '\000'; - if ((ch != 'g' && ch != 'G') || flags & ALT) { /* Print trailing zeros */ - bp = digits + ndigits; - if (ch == 'f') { - if (*digits == '0' && value) - *decpt = -ndigits + 1; - bp += *decpt; - } - if (value == 0) /* kludge for __dtoa irregularity */ - rve = bp; - while (rve < bp) - *rve++ = '0'; - } - *length = rve - digits; - return digits; -} -#endif static int exponent(CHAR_T *p0, int expo, int fmtch) Index: src/tests/lib/libc/stdio/t_printf.c diff -u src/tests/lib/libc/stdio/t_printf.c:1.8 src/tests/lib/libc/stdio/t_printf.c:1.8.34.1 --- src/tests/lib/libc/stdio/t_printf.c:1.8 Wed Apr 11 16:21:42 2012 +++ src/tests/lib/libc/stdio/t_printf.c Thu Aug 22 19:40:50 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: t_printf.c,v 1.8 2012/04/11 16:21:42 jruoho Exp $ */ +/* $NetBSD: t_printf.c,v 1.8.34.1 2024/08/22 19:40:50 martin Exp $ */ /*- * Copyright (c) 2010 The NetBSD Foundation, Inc. @@ -35,6 +35,7 @@ #include <string.h> #include <time.h> #include <stdlib.h> +#include <errno.h> ATF_TC(snprintf_c99); ATF_TC_HEAD(snprintf_c99, tc) @@ -179,6 +180,50 @@ ATF_TC_BODY(sprintf_zeropad, tc) #endif } +ATF_TC(snprintf_double_a); +ATF_TC_HEAD(snprintf_double_a, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test printf a format"); +} + +ATF_TC_BODY(snprintf_double_a, tc) +{ + char buf[1000]; + + snprintf(buf, sizeof buf, "%.3a", (double)10.6); + ATF_REQUIRE_STREQ("0x1.533p+3", buf); +} + +/* is "long double" and "double" different? */ +#if (__LDBL_MANT_DIG__ != __DBL_MANT_DIG__) || \ + (__LDBL_MAX_EXP__ != __DBL_MAX_EXP__) +#define WIDE_DOUBLE +#endif + +#ifndef WIDE_DOUBLE +ATF_TC(pr57250_fix); +ATF_TC_HEAD(pr57250_fix, tc) +{ + atf_tc_set_md_var(tc, "descr", "Test for PR57250"); +} + +ATF_TC_BODY(pr57250_fix, tc) +{ + char *eptr; + char buf[1000]; + long double ld; + + errno = 0; + ld = strtold("1e309", &eptr); + ATF_CHECK(errno != 0); + ld = (double)ld; + ATF_CHECK(isfinite(ld) == 0); + snprintf(buf, sizeof buf, "%Lf\n", ld); + ATF_REQUIRE_STREQ(buf, "inf\n"); +} +#endif + + ATF_TP_ADD_TCS(tp) { @@ -189,6 +234,10 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, snprintf_posarg_error); ATF_TP_ADD_TC(tp, snprintf_float); ATF_TP_ADD_TC(tp, sprintf_zeropad); + ATF_TP_ADD_TC(tp, snprintf_double_a); +#ifndef WIDE_DOUBLE + ATF_TP_ADD_TC(tp, pr57250_fix); +#endif return atf_no_error(); }