aboutsummaryrefslogtreecommitdiff
path: root/libgfortran
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2006-04-10 14:02:55 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2006-04-10 14:02:55 +0200
commit55fc9243b7fc0a6c84fb7ff6bf896614bbde91ce (patch)
tree0e8c336cdc630af721734cfe83d6403b782d64d8 /libgfortran
parent9f889fcf528e9c42a0c17c8bc63afe89f749f786 (diff)
downloadgcc-55fc9243b7fc0a6c84fb7ff6bf896614bbde91ce.zip
gcc-55fc9243b7fc0a6c84fb7ff6bf896614bbde91ce.tar.gz
gcc-55fc9243b7fc0a6c84fb7ff6bf896614bbde91ce.tar.bz2
re PR libfortran/24685 (real(16) formatted input is broken for huge values (gfortran.dg/default_format_2.f90))
PR libgfortran/24685 * io/write.c (MIN_FIELD_WIDTH, STR, STR1): Define. (output_float): Increase buffer sizes for IEEE quad and IBM extended long double. (write_real): Output REAL(16) as 1PG43.34E4 rather than 1PG40.31E4. From-SVN: r112819
Diffstat (limited to 'libgfortran')
-rw-r--r--libgfortran/ChangeLog8
-rw-r--r--libgfortran/io/write.c38
2 files changed, 32 insertions, 14 deletions
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index e486c5a..4f2c6ce 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -1,3 +1,11 @@
+2006-04-10 Jakub Jelinek <jakub@redhat.com>
+
+ PR libgfortran/24685
+ * io/write.c (MIN_FIELD_WIDTH, STR, STR1): Define.
+ (output_float): Increase buffer sizes for IEEE quad and IBM extended
+ long double.
+ (write_real): Output REAL(16) as 1PG43.34E4 rather than 1PG40.31E4.
+
2006-04-07 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR libgfortran/26890
diff --git a/libgfortran/io/write.c b/libgfortran/io/write.c
index 39192dd..bee367c 100644
--- a/libgfortran/io/write.c
+++ b/libgfortran/io/write.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
Contributed by Andy Vaught
Namelist output contibuted by Paul Thomas
@@ -376,8 +376,15 @@ calculate_G_format (st_parameter_dt *dtp, const fnode *f,
static void
output_float (st_parameter_dt *dtp, const fnode *f, GFC_REAL_LARGEST value)
{
+#if defined(HAVE_GFC_REAL_16) && __LDBL_DIG__ > 18
+# define MIN_FIELD_WIDTH 46
+#else
+# define MIN_FIELD_WIDTH 31
+#endif
+#define STR(x) STR1(x)
+#define STR1(x) #x
/* This must be large enough to accurately hold any value. */
- char buffer[32];
+ char buffer[MIN_FIELD_WIDTH+1];
char *out;
char *digits;
int e;
@@ -413,8 +420,8 @@ output_float (st_parameter_dt *dtp, const fnode *f, GFC_REAL_LARGEST value)
internal_error (&dtp->common, "Unspecified precision");
/* Use sprintf to print the number in the format +D.DDDDe+ddd
- For an N digit exponent, this gives us (32-6)-N digits after the
- decimal point, plus another one before the decimal point. */
+ For an N digit exponent, this gives us (MIN_FIELD_WIDTH-5)-N digits
+ after the decimal point, plus another one before the decimal point. */
sign = calculate_sign (dtp, value < 0.0);
if (value < 0)
value = -value;
@@ -439,7 +446,7 @@ output_float (st_parameter_dt *dtp, const fnode *f, GFC_REAL_LARGEST value)
|| ((ft == FMT_D || ft == FMT_E) && dtp->u.p.scale_factor != 0))
{
/* Always convert at full precision to avoid double rounding. */
- ndigits = 27 - edigits;
+ ndigits = MIN_FIELD_WIDTH - 4 - edigits;
}
else
{
@@ -449,8 +456,8 @@ output_float (st_parameter_dt *dtp, const fnode *f, GFC_REAL_LARGEST value)
ndigits = d + 1;
else
ndigits = d;
- if (ndigits > 27 - edigits)
- ndigits = 27 - edigits;
+ if (ndigits > MIN_FIELD_WIDTH - 4 - edigits)
+ ndigits = MIN_FIELD_WIDTH - 4 - edigits;
}
/* # The result will always contain a decimal point, even if no
@@ -460,7 +467,7 @@ output_float (st_parameter_dt *dtp, const fnode *f, GFC_REAL_LARGEST value)
*
* + A sign (+ or -) always be placed before a number
*
- * 31 minimum field width
+ * MIN_FIELD_WIDTH minimum field width
*
* * (ndigits-1) is used as the precision
*
@@ -469,8 +476,8 @@ output_float (st_parameter_dt *dtp, const fnode *f, GFC_REAL_LARGEST value)
* equal to the precision. The exponent always contains at least two
* digits; if the value is zero, the exponent is 00.
*/
- sprintf (buffer, "%+-#31.*" GFC_REAL_LARGEST_FORMAT "e",
- ndigits - 1, value);
+ sprintf (buffer, "%+-#" STR(MIN_FIELD_WIDTH) ".*"
+ GFC_REAL_LARGEST_FORMAT "e", ndigits - 1, value);
/* Check the resulting string has punctuation in the correct places. */
if (d != 0 && (buffer[2] != '.' || buffer[ndigits + 2] != 'e'))
@@ -777,7 +784,7 @@ output_float (st_parameter_dt *dtp, const fnode *f, GFC_REAL_LARGEST value)
edigits--;
}
#if HAVE_SNPRINTF
- snprintf (buffer, 32, "%+0*d", edigits, e);
+ snprintf (buffer, sizeof (buffer), "%+0*d", edigits, e);
#else
sprintf (buffer, "%+0*d", edigits, e);
#endif
@@ -790,6 +797,9 @@ output_float (st_parameter_dt *dtp, const fnode *f, GFC_REAL_LARGEST value)
memset( out , ' ' , nblanks );
dtp->u.p.no_leading_blank = 0;
}
+#undef STR
+#undef STR1
+#undef MIN_FIELD_WIDTH
}
@@ -1352,7 +1362,7 @@ write_character (st_parameter_dt *dtp, const char *source, int length)
/* Output a real number with default format.
This is 1PG14.7E2 for REAL(4), 1PG23.15E3 for REAL(8),
- 1PG24.15E4 for REAL(10) and 1PG40.31E4 for REAL(16). */
+ 1PG28.19E4 for REAL(10) and 1PG43.34E4 for REAL(16). */
static void
write_real (st_parameter_dt *dtp, const char *source, int length)
@@ -1379,8 +1389,8 @@ write_real (st_parameter_dt *dtp, const char *source, int length)
f.u.real.e = 4;
break;
case 16:
- f.u.real.w = 40;
- f.u.real.d = 31;
+ f.u.real.w = 43;
+ f.u.real.d = 34;
f.u.real.e = 4;
break;
default: