https://gcc.gnu.org/g:b69eb2c594f8595718d876dc9811e3820eb68da1
commit r14-11246-gb69eb2c594f8595718d876dc9811e3820eb68da1 Author: Jerry DeLisle <jvdeli...@gcc.gnu.org> Date: Thu Jan 23 12:58:14 2025 -0800 Fortran: Fix UTF-8 output with A edit descriptor. This adjusts the source len for the case where the user has specified a field width with the A descriptor. PR libfortran/118571 libgfortran/ChangeLog: * io/write.c (write_utf8_char4): Adjust the src_len to the format width w_len when greater than zero. gcc/testsuite/ChangeLog: * gfortran.dg/utf8_3.f03: New test. (cherry picked from commit 4daf088123b2c4c3114a4b96d5353c3d72eb8ac9) Diff: --- gcc/testsuite/gfortran.dg/utf8_3.f03 | 57 ++++++++++++++++++++++++++++++++++++ libgfortran/io/write.c | 4 ++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/gcc/testsuite/gfortran.dg/utf8_3.f03 b/gcc/testsuite/gfortran.dg/utf8_3.f03 new file mode 100644 index 000000000000..e1688149e5dc --- /dev/null +++ b/gcc/testsuite/gfortran.dg/utf8_3.f03 @@ -0,0 +1,57 @@ +! { dg-do run } +! PR118571 UTF-8 output and the A edit descriptor. + +program test + + use iso_fortran_env + + implicit none + + integer, parameter :: ucs4 = selected_char_kind('ISO_10646') + + character(kind=ucs4, len=1), parameter :: alpha = char(int(z'03B1'), ucs4) + character(kind=ucs4, len=1), parameter :: beta = char(int(z'03B2'), ucs4) + character(kind=ucs4, len=1), parameter :: space = ucs4_' ' + + integer fd + character(kind=ucs4,len=:), allocatable :: str + character(kind=ucs4,len=25) :: instr, correct + + fd = 42 + + open (fd, encoding='UTF-8', status="scratch") + open (output_unit, encoding='UTF-8') + str = repeat(space,6)//alpha//beta//alpha//beta + + write(fd,'(I4,1X,A)') len_trim(str), str + rewind(fd) + read(fd,'(a)') instr + if (trim(instr) /= ucs4_' 10 '//trim(str)) stop 1 + + str = alpha // beta // alpha // beta + rewind(fd) + write(fd,'(I4,1X,">",A,"<")') len_trim(str(1:1)), str(1:1) + rewind(fd) + read(fd,'(a)') instr + if (trim(instr) /= ucs4_' 1 >'//alpha//ucs4_'<') stop 2 + + rewind(fd) + write(fd,*) len_trim(str(1:1)), str(1:1) + rewind(fd) + read(fd,'(a)') instr + if (trim(instr) /= ucs4_' 1 '//alpha) stop 3 + + rewind(fd) + write(fd,'(I4,1X,">",A1,"<")') len_trim(str(1:1)), str(1:1) + rewind(fd) + read(fd, '(a)') instr + if (trim(instr) /= ucs4_' 1 >'//alpha//ucs4_'<') stop 4 + + rewind(fd) + write(fd,'(I4,1X,">",A1,"<")') len_trim(str), str + rewind(fd) + read(fd, '(a)') instr + if (trim(instr) /= ucs4_' 4 >'//alpha//ucs4_'<') stop 5 + close(fd) +end program + diff --git a/libgfortran/io/write.c b/libgfortran/io/write.c index 9d0a0d6102b3..bc22054fee96 100644 --- a/libgfortran/io/write.c +++ b/libgfortran/io/write.c @@ -177,7 +177,9 @@ write_utf8_char4 (st_parameter_dt *dtp, gfc_char4_t *source, break; } - /* Now process the remaining characters, one at a time. */ + /* Now process the remaining characters, one at a time. We need to + adjust the src_len if the user has specified a field width. */ + src_len = w_len > 0 ? w_len : src_len; for (j = k; j < src_len; j++) { c = source[j];