Commit 5b0e27a7 by Jerry DeLisle

re PR libfortran/48852 (Invalid spaces in list-directed output of complex constants)

2016-06-23  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

	PR libgfortran/48852
	* io/write.c: Cleaned up whitespace.
	(write_d, write_e, write_f, write_es, write_en): Use new helper function
	write_float_0. (write_float_0): New helper function.
	(get_precision, select_buffer, select_string, write_float_string): New
	helper functions used in remaining float writing functions. Helper function
	write_float_string now contains code for writing to kind=4 character
	internal units.
	(write_real): Modified to establish working buffers at this level and to
	use new helper functions.
	(write_real_g0): Likewise modified.
	(write_complex): Likewise modified. Gets both float strings before
	output so that final lengths can be determined which allows right
	justifying the complex number with no intervening spaces.
	* io/write_float.def (build_float_string): Renamed from previosly
	output_float, modified to use buffers passed in from higher functions,
	builds a null terminated string of the floating point value. Character
	kind=4 code eliminated.
	(write_infnan): Likewise modified to use incoming buffers and eliminate
	kind=4 related code.
	(OUTPUT_FLOAT_FMT_G): Deleted, functionality moved into FORMAT_FLOAT.
	(FORMAT_FLOAT): Renamed macro from WRITE_FLOAT. Use build_float_string.
	(get_float_string): Renamed from write_float, uses FORMAT_FLOAT macro.
	Buffer allocation removed, now at higher level.

	PR libgfortran/48852
	* gfortran.dg/char4_iunit_1.f03: Update test.
	* gfortran.dg/f2003_io_5.f03: Update test.
	* gfortran.dg/real_const_3.f90: Update test.

From-SVN: r237735
parent cd64be5b
2016-06-23 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR libgfortran/48852
* gfortran.dg/char4_iunit_1.f03: Update test.
* gfortran.dg/f2003_io_5.f03: Update test.
* gfortran.dg/real_const_3.f90: Update test.
2016-06-23 Andi Kleen <ak@linux.intel.com>
* g++.dg/bprob/bprob.exp: Support autofdo.
......
......@@ -30,5 +30,5 @@ program char4_iunit_1
write(string, '(10x,f3.1,3x,f9.1)') nan, inf
if (string .ne. 4_" NaN Infinity ") call abort
write(string, *) (1.2, 3.4 )
if (string .ne. 4_" ( 1.20000005 , 3.40000010 ) ") call abort
if (string .ne. 4_" (1.20000005,3.40000010)") call abort
end program char4_iunit_1
......@@ -18,9 +18,9 @@ close(99, status="delete")
c = (3.123,4.456)
write(complex,*,decimal="comma") c
if (complex.ne." ( 3,12299991 ; 4,45599985 )") call abort
if (complex.ne." (3,12299991;4,45599985)") call abort
c = (0.0, 0.0)
read(complex,*,decimal="comma") c
if (complex.ne." ( 3,12299991 ; 4,45599985 )") call abort
if (complex.ne." (3,12299991;4,45599985)") call abort
end
......@@ -42,15 +42,14 @@ program main
if (trim(adjustl(str)) .ne. 'NaN') call abort
write(str,*) z
if (trim(adjustl(str)) .ne. '( NaN, NaN)') call abort
if (trim(adjustl(str)) .ne. '(NaN,NaN)') call abort
write(str,*) z2
if (trim(adjustl(str)) .ne. '( NaN, NaN)') call abort
if (trim(adjustl(str)) .ne. '(NaN,NaN)') call abort
write(str,*) z3
if (trim(adjustl(str)) .ne. '( Infinity, -Infinity)') call abort
if (trim(adjustl(str)) .ne. '(Inf,-Inf)') call abort
write(str,*) z4
if (trim(adjustl(str)) .ne. '( 0.00000000 , -0.00000000 )') call abort
if (trim(adjustl(str)) .ne. '(0.00000000,-0.00000000)') call abort
end program main
2016-06-23 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR libgfortran/48852
* io/write.c: Cleaned up whitespace.
(write_d, write_e, write_f, write_es, write_en): Use new helper function
write_float_0. (write_float_0): New helper function.
(get_precision, select_buffer, select_string, write_float_string): New
helper functions used in remaining float writing functions. Helper function
write_float_string now contains code for writing to kind=4 character
internal units.
(write_real): Modified to establish working buffers at this level and to
use new helper functions.
(write_real_g0): Likewise modified.
(write_complex): Likewise modified. Gets both float strings before
output so that final lengths can be determined which allows right
justifying the complex number with no intervening spaces.
* io/write_float.def (build_float_string): Renamed from previosly
output_float, modified to use buffers passed in from higher functions,
builds a null terminated string of the floating point value. Character
kind=4 code eliminated.
(write_infnan): Likewise modified to use incoming buffers and eliminate
kind=4 related code.
(OUTPUT_FLOAT_FMT_G): Deleted, functionality moved into FORMAT_FLOAT.
(FORMAT_FLOAT): Renamed macro from WRITE_FLOAT. Use build_float_string.
(get_float_string): Renamed from write_float, uses FORMAT_FLOAT macro.
Buffer allocation removed, now at higher level.
2016-05-23 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR libgfortran/71123
......
......@@ -1101,42 +1101,6 @@ write_z (st_parameter_dt *dtp, const fnode *f, const char *source, int len)
}
}
void
write_d (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
{
write_float (dtp, f, p, len, 0);
}
void
write_e (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
{
write_float (dtp, f, p, len, 0);
}
void
write_f (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
{
write_float (dtp, f, p, len, 0);
}
void
write_en (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
{
write_float (dtp, f, p, len, 0);
}
void
write_es (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
{
write_float (dtp, f, p, len, 0);
}
/* Take care of the X/TR descriptor. */
void
......@@ -1380,6 +1344,119 @@ write_character (st_parameter_dt *dtp, const char *source, int kind, int length,
}
}
/* Floating point helper functions. */
#define BUF_STACK_SZ 256
static int
get_precision (st_parameter_dt *dtp, const fnode *f, const char *source, int kind)
{
if (f->format != FMT_EN)
return determine_precision (dtp, f, kind);
else
return determine_en_precision (dtp, f, source, kind);
}
static char *
select_buffer (int precision, char *buf, size_t *size)
{
char *result;
*size = BUF_STACK_SZ / 2 + precision;
if (*size > BUF_STACK_SZ)
result = xmalloc (*size);
else
result = buf;
return result;
}
static char *
select_string (const fnode *f, char *buf, size_t *size)
{
char *result;
*size = f->u.real.w + 1;
if (*size > BUF_STACK_SZ)
result = xmalloc (*size);
else
result = buf;
return result;
}
static void
write_float_string (st_parameter_dt *dtp, char *fstr, size_t len)
{
char *p = write_block (dtp, len);
if (p == NULL)
return;
if (unlikely (is_char4_unit (dtp)))
{
gfc_char4_t *p4 = (gfc_char4_t *) p;
memcpy4 (p4, fstr, len);
return;
}
memcpy (p, fstr, len);
}
static void
write_float_0 (st_parameter_dt *dtp, const fnode *f, const char *source, int kind)
{
char buf_stack[BUF_STACK_SZ];
char str_buf[BUF_STACK_SZ];
char *buffer, *result;
size_t buf_size, res_len;
/* Precision for snprintf call. */
int precision = get_precision (dtp, f, source, kind);
/* String buffer to hold final result. */
result = select_string (f, str_buf, &res_len);
buffer = select_buffer (precision, buf_stack, &buf_size);
get_float_string (dtp, f, source , kind, 0, buffer,
precision, buf_size, result, &res_len);
write_float_string (dtp, result, res_len);
if (buf_size > BUF_STACK_SZ)
free (buffer);
if (res_len > BUF_STACK_SZ)
free (result);
}
void
write_d (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
{
write_float_0 (dtp, f, p, len);
}
void
write_e (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
{
write_float_0 (dtp, f, p, len);
}
void
write_f (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
{
write_float_0 (dtp, f, p, len);
}
void
write_en (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
{
write_float_0 (dtp, f, p, len);
}
void
write_es (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
{
write_float_0 (dtp, f, p, len);
}
/* Set an fnode to default format. */
......@@ -1422,12 +1499,12 @@ set_fnode_default (st_parameter_dt *dtp, fnode *f, int length)
}
}
/* Output a real number with default format. To guarantee that a
binary -> decimal -> binary roundtrip conversion recovers the
original value, IEEE 754-2008 requires 9, 17, 21 and 36 significant
digits for REAL kinds 4, 8, 10, and 16, respectively. Thus, we use
1PG16.9E2 for REAL(4), 1PG25.17E3 for REAL(8), 1PG30.21E4 for
REAL(10) and 1PG45.36E4 for REAL(16). The exception is that the
/* Output a real number with default format.
To guarantee that a binary -> decimal -> binary roundtrip conversion
recovers the original value, IEEE 754-2008 requires 9, 17, 21 and 36
significant digits for REAL kinds 4, 8, 10, and 16, respectively.
Thus, we use 1PG16.9E2 for REAL(4), 1PG25.17E3 for REAL(8), 1PG30.21E4
for REAL(10) and 1PG45.36E4 for REAL(16). The exception is that the
Fortran standard requires outputting an extra digit when the scale
factor is 1 and when the magnitude of the value is such that E
editing is used. However, gfortran compensates for this, and thus
......@@ -1435,25 +1512,51 @@ set_fnode_default (st_parameter_dt *dtp, fnode *f, int length)
generated both when using F and E editing. */
void
write_real (st_parameter_dt *dtp, const char *source, int length)
write_real (st_parameter_dt *dtp, const char *source, int kind)
{
fnode f ;
int org_scale = dtp->u.p.scale_factor;
char buf_stack[BUF_STACK_SZ];
char str_buf[BUF_STACK_SZ];
char *buffer, *result;
size_t buf_size, res_len;
int orig_scale = dtp->u.p.scale_factor;
dtp->u.p.scale_factor = 1;
set_fnode_default (dtp, &f, length);
write_float (dtp, &f, source , length, 1);
dtp->u.p.scale_factor = org_scale;
set_fnode_default (dtp, &f, kind);
/* Precision for snprintf call. */
int precision = get_precision (dtp, &f, source, kind);
/* String buffer to hold final result. */
result = select_string (&f, str_buf, &res_len);
/* scratch buffer to hold final result. */
buffer = select_buffer (precision, buf_stack, &buf_size);
get_float_string (dtp, &f, source , kind, 1, buffer,
precision, buf_size, result, &res_len);
write_float_string (dtp, result, res_len);
dtp->u.p.scale_factor = orig_scale;
if (buf_size > BUF_STACK_SZ)
free (buffer);
if (res_len > BUF_STACK_SZ)
free (result);
}
/* Similar to list formatted REAL output, for kPG0 where k > 0 we
compensate for the extra digit. */
void
write_real_g0 (st_parameter_dt *dtp, const char *source, int length, int d)
write_real_g0 (st_parameter_dt *dtp, const char *source, int kind, int d)
{
fnode f;
char buf_stack[BUF_STACK_SZ];
char str_buf[BUF_STACK_SZ];
char *buffer, *result;
size_t buf_size, res_len;
int comp_d;
set_fnode_default (dtp, &f, length);
set_fnode_default (dtp, &f, kind);
if (d > 0)
f.u.real.d = d;
......@@ -1464,8 +1567,24 @@ write_real_g0 (st_parameter_dt *dtp, const char *source, int length, int d)
else
comp_d = 0;
dtp->u.p.g0_no_blanks = 1;
write_float (dtp, &f, source , length, comp_d);
/* Precision for snprintf call. */
int precision = get_precision (dtp, &f, source, kind);
/* String buffer to hold final result. */
result = select_string (&f, str_buf, &res_len);
buffer = select_buffer (precision, buf_stack, &buf_size);
get_float_string (dtp, &f, source , kind, comp_d, buffer,
precision, buf_size, result, &res_len);
write_float_string (dtp, result, res_len);
dtp->u.p.g0_no_blanks = 0;
if (buf_size > BUF_STACK_SZ)
free (buffer);
if (res_len > BUF_STACK_SZ)
free (result);
}
......@@ -1475,15 +1594,58 @@ write_complex (st_parameter_dt *dtp, const char *source, int kind, size_t size)
char semi_comma =
dtp->u.p.current_unit->decimal_status == DECIMAL_POINT ? ',' : ';';
if (write_char (dtp, '('))
return;
write_real (dtp, source, kind);
/* Set for no blanks so we get a string result with no leading
blanks. We will pad left later. */
dtp->u.p.g0_no_blanks = 1;
if (write_char (dtp, semi_comma))
return;
write_real (dtp, source + size / 2, kind);
fnode f ;
char buf_stack[BUF_STACK_SZ];
char str1_buf[BUF_STACK_SZ];
char str2_buf[BUF_STACK_SZ];
char *buffer, *result1, *result2;
size_t buf_size, res_len1, res_len2;
int width, lblanks, orig_scale = dtp->u.p.scale_factor;
dtp->u.p.scale_factor = 1;
set_fnode_default (dtp, &f, kind);
/* Set width for two values, parenthesis, and comma. */
width = 2 * f.u.real.w + 3;
/* Set for no blanks so we get a string result with no leading
blanks. We will pad left later. */
dtp->u.p.g0_no_blanks = 1;
/* Precision for snprintf call. */
int precision = get_precision (dtp, &f, source, kind);
/* String buffers to hold final result. */
result1 = select_string (&f, str1_buf, &res_len1);
result2 = select_string (&f, str2_buf, &res_len2);
buffer = select_buffer (precision, buf_stack, &buf_size);
get_float_string (dtp, &f, source , kind, 0, buffer,
precision, buf_size, result1, &res_len1);
get_float_string (dtp, &f, source + size / 2 , kind, 0, buffer,
precision, buf_size, result2, &res_len2);
lblanks = width - res_len1 - res_len2 - 3;
write_x (dtp, lblanks, lblanks);
write_char (dtp, '(');
write_float_string (dtp, result1, res_len1);
write_char (dtp, semi_comma);
write_float_string (dtp, result2, res_len2);
write_char (dtp, ')');
dtp->u.p.scale_factor = orig_scale;
dtp->u.p.g0_no_blanks = 0;
if (buf_size > BUF_STACK_SZ)
free (buffer);
if (res_len1 > BUF_STACK_SZ)
free (result1);
if (res_len2 > BUF_STACK_SZ)
free (result2);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment