Skip to content

Commit e0950eb

Browse files
authored
[flang][runtime] Tweak width-free I/G formatted I&O (#135047)
For Fujitsu test case 0561/0561_0168.f90, adjust both input and output sides of the extension I (and G) edit descriptors with no width (as distinct from I0/G0). On input, be sure to halt on a separator character rather than complaining about an invalid character; on output, be sure to emit a leading space.
1 parent 0ae9bb9 commit e0950eb

File tree

2 files changed

+30
-26
lines changed

2 files changed

+30
-26
lines changed

flang-rt/lib/runtime/edit-output.cpp

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ namespace Fortran::runtime::io {
1717
RT_OFFLOAD_API_GROUP_BEGIN
1818

1919
// In output statement, add a space between numbers and characters.
20-
static RT_API_ATTRS void addSpaceBeforeCharacter(IoStatementState &io) {
20+
static RT_API_ATTRS void AddSpaceBeforeCharacter(IoStatementState &io) {
2121
if (auto *list{io.get_if<ListDirectedStatementState<Direction::Output>>()}) {
2222
list->set_lastWasUndelimitedCharacter(false);
2323
}
@@ -29,7 +29,7 @@ static RT_API_ATTRS void addSpaceBeforeCharacter(IoStatementState &io) {
2929
template <int LOG2_BASE>
3030
static RT_API_ATTRS bool EditBOZOutput(IoStatementState &io,
3131
const DataEdit &edit, const unsigned char *data0, std::size_t bytes) {
32-
addSpaceBeforeCharacter(io);
32+
AddSpaceBeforeCharacter(io);
3333
int digits{static_cast<int>((bytes * 8) / LOG2_BASE)};
3434
int get{static_cast<int>(bytes * 8) - digits * LOG2_BASE};
3535
if (get > 0) {
@@ -110,27 +110,11 @@ static RT_API_ATTRS bool EditBOZOutput(IoStatementState &io,
110110
template <int KIND>
111111
bool RT_API_ATTRS EditIntegerOutput(IoStatementState &io, const DataEdit &edit,
112112
common::HostSignedIntType<8 * KIND> n, bool isSigned) {
113-
addSpaceBeforeCharacter(io);
114-
char buffer[130], *end{&buffer[sizeof buffer]}, *p{end};
115-
bool isNegative{isSigned && n < 0};
116-
using Unsigned = common::HostUnsignedIntType<8 * KIND>;
117-
Unsigned un{static_cast<Unsigned>(n)};
118-
int signChars{0};
113+
AddSpaceBeforeCharacter(io);
119114
switch (edit.descriptor) {
120115
case DataEdit::ListDirected:
121116
case 'G':
122117
case 'I':
123-
if (isNegative) {
124-
un = -un;
125-
}
126-
if (isNegative || (edit.modes.editingFlags & signPlus)) {
127-
signChars = 1; // '-' or '+'
128-
}
129-
while (un > 0) {
130-
auto quotient{un / 10u};
131-
*--p = '0' + static_cast<int>(un - Unsigned{10} * quotient);
132-
un = quotient;
133-
}
134118
break;
135119
case 'B':
136120
return EditBOZOutput<1>(
@@ -152,7 +136,22 @@ bool RT_API_ATTRS EditIntegerOutput(IoStatementState &io, const DataEdit &edit,
152136
edit.descriptor);
153137
return false;
154138
}
155-
139+
char buffer[130], *end{&buffer[sizeof buffer]}, *p{end};
140+
bool isNegative{isSigned && n < 0};
141+
using Unsigned = common::HostUnsignedIntType<8 * KIND>;
142+
Unsigned un{static_cast<Unsigned>(n)};
143+
int signChars{0};
144+
if (isNegative) {
145+
un = -un;
146+
}
147+
if (isNegative || (edit.modes.editingFlags & signPlus)) {
148+
signChars = 1; // '-' or '+'
149+
}
150+
while (un > 0) {
151+
auto quotient{un / 10u};
152+
*--p = '0' + static_cast<int>(un - Unsigned{10} * quotient);
153+
un = quotient;
154+
}
156155
int digits = end - p;
157156
int leadingZeroes{0};
158157
int editWidth{edit.width.value_or(0)};
@@ -181,6 +180,10 @@ bool RT_API_ATTRS EditIntegerOutput(IoStatementState &io, const DataEdit &edit,
181180
return false;
182181
}
183182
leadingSpaces = 1;
183+
} else if (!edit.width) {
184+
// Bare 'I' and 'G' are interpreted with various default widths in the
185+
// compilers that support them, so there's always some leading space.
186+
leadingSpaces = std::max(1, leadingSpaces);
184187
}
185188
return EmitRepeated(io, ' ', leadingSpaces) &&
186189
EmitAscii(io, n < 0 ? "-" : "+", signChars) &&
@@ -291,7 +294,7 @@ static RT_API_ATTRS bool IsInfOrNaN(const char *p, int length) {
291294
template <int KIND>
292295
RT_API_ATTRS bool RealOutputEditing<KIND>::EditEorDOutput(
293296
const DataEdit &edit) {
294-
addSpaceBeforeCharacter(io_);
297+
AddSpaceBeforeCharacter(io_);
295298
int editDigits{edit.digits.value_or(0)}; // 'd' field
296299
int editWidth{edit.width.value_or(0)}; // 'w' field
297300
int significantDigits{editDigits};
@@ -427,7 +430,7 @@ RT_API_ATTRS bool RealOutputEditing<KIND>::EditEorDOutput(
427430
// 13.7.2.3.2 in F'2018
428431
template <int KIND>
429432
RT_API_ATTRS bool RealOutputEditing<KIND>::EditFOutput(const DataEdit &edit) {
430-
addSpaceBeforeCharacter(io_);
433+
AddSpaceBeforeCharacter(io_);
431434
int fracDigits{edit.digits.value_or(0)}; // 'd' field
432435
const int editWidth{edit.width.value_or(0)}; // 'w' field
433436
enum decimal::FortranRounding rounding{edit.modes.round};
@@ -702,7 +705,7 @@ RT_API_ATTRS auto RealOutputEditing<KIND>::ConvertToHexadecimal(
702705

703706
template <int KIND>
704707
RT_API_ATTRS bool RealOutputEditing<KIND>::EditEXOutput(const DataEdit &edit) {
705-
addSpaceBeforeCharacter(io_);
708+
AddSpaceBeforeCharacter(io_);
706709
int editDigits{edit.digits.value_or(0)}; // 'd' field
707710
int significantDigits{editDigits + 1};
708711
int flags{0};

flang-rt/lib/runtime/io-stmt.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -631,10 +631,11 @@ Fortran::common::optional<char32_t> IoStatementState::GetCurrentChar(
631631
Fortran::common::optional<char32_t> IoStatementState::NextInField(
632632
Fortran::common::optional<int> &remaining, const DataEdit &edit) {
633633
std::size_t byteCount{0};
634-
if (!remaining) { // Stream, list-directed, or NAMELIST
634+
if (!remaining) { // Stream, list-directed, NAMELIST, &c.
635635
if (auto next{GetCurrentChar(byteCount)}) {
636-
if (edit.IsListDirected()) {
637-
// list-directed or NAMELIST: check for separators
636+
if (edit.width.value_or(0) == 0) {
637+
// list-directed, NAMELIST, I0 &c., or width-free I/G:
638+
// check for separator character
638639
switch (*next) {
639640
case ' ':
640641
case '\t':

0 commit comments

Comments
 (0)