Index: flang/include/flang/Runtime/iostat.h =================================================================== --- flang/include/flang/Runtime/iostat.h +++ flang/include/flang/Runtime/iostat.h @@ -68,6 +68,7 @@ IostatBadUnformattedRecord, IostatUTF8Decoding, IostatUnitOverflow, + IostatBadRealInput, }; const char *IostatErrorString(int); Index: flang/runtime/edit-input.cpp =================================================================== --- flang/runtime/edit-input.cpp +++ flang/runtime/edit-input.cpp @@ -57,12 +57,15 @@ // Returns true if there's a '-' sign. static bool ScanNumericPrefix(IoStatementState &io, const DataEdit &edit, std::optional &next, std::optional &remaining) { - next = io.PrepareInput(edit, remaining); + bool bzMode{(edit.modes.editingFlags & blankZero) != 0}; + next = io.PrepareInput(edit, remaining, !bzMode); bool negative{false}; if (next) { negative = *next == '-'; if (negative || *next == '+') { - io.SkipSpaces(remaining); + if (!bzMode) { + io.SkipSpaces(remaining); + } next = io.NextInField(remaining, edit); } } @@ -152,7 +155,8 @@ if (ScanNumericPrefix(io, edit, next, remaining)) { Put('-'); } - if (next.value_or(' ') == ' ') { // empty/blank field means zero + bool bzMode{(edit.modes.editingFlags & blankZero) != 0}; + if (!next || (!bzMode && *next == ' ')) { // empty/blank field means zero remaining.reset(); if (!io.GetConnectionState().IsAtEOF()) { Put('0'); @@ -180,10 +184,11 @@ } exponent = 0; } else if (first == decimal || (first >= '0' && first <= '9') || - first == 'E' || first == 'D' || first == 'Q') { + (bzMode && (first == ' ' || first == '\t')) || first == 'E' || + first == 'D' || first == 'Q') { Put('.'); // input field is normalized to a fraction auto start{got}; - bool bzMode{(edit.modes.editingFlags & blankZero) != 0}; + bool anyDigit{false}; for (; next; next = io.NextInField(remaining, edit)) { char32_t ch{*next}; if (ch == ' ' || ch == '\t') { @@ -194,8 +199,10 @@ } } if (ch == '0' && got == start && !decimalPoint) { + anyDigit = true; // omit leading zeroes before the decimal } else if (ch >= '0' && ch <= '9') { + anyDigit = true; Put(ch); } else if (ch == decimal && !decimalPoint) { // the decimal point is *not* copied to the buffer @@ -205,7 +212,11 @@ } } if (got == start) { - Put('0'); // emit at least one digit + if (anyDigit) { + Put('0'); // emit at least one digit + } else { + return 0; // no digits, invalid input + } } if (next && (*next == 'e' || *next == 'E' || *next == 'd' || *next == 'D' || @@ -349,7 +360,7 @@ return false; } if (got == 0) { - io.GetIoErrorHandler().SignalError("Bad REAL input value"); + io.GetIoErrorHandler().SignalError(IostatBadRealInput); return false; } bool hadExtra{got > maxDigits}; Index: flang/runtime/io-stmt.h =================================================================== --- flang/runtime/io-stmt.h +++ flang/runtime/io-stmt.h @@ -132,8 +132,8 @@ // For fixed-width fields, initialize the number of remaining characters. // Skip over leading blanks, then return the first non-blank character (if // any). - std::optional PrepareInput( - const DataEdit &edit, std::optional &remaining) { + std::optional PrepareInput(const DataEdit &edit, + std::optional &remaining, bool skipSpaces = true) { remaining.reset(); if (edit.descriptor == DataEdit::ListDirected) { std::size_t byteCount{0}; @@ -142,7 +142,9 @@ if (edit.width.value_or(0) > 0) { remaining = *edit.width; } - SkipSpaces(remaining); + if (skipSpaces) { + SkipSpaces(remaining); + } } return NextInField(remaining, edit); } Index: flang/runtime/iostat.cpp =================================================================== --- flang/runtime/iostat.cpp +++ flang/runtime/iostat.cpp @@ -79,6 +79,8 @@ return "UTF-8 decoding error"; case IostatUnitOverflow: return "UNIT number is out of range"; + case IostatBadRealInput: + return "Bad REAL input value"; default: return nullptr; } Index: flang/unittests/Runtime/NumericalFormatTest.cpp =================================================================== --- flang/unittests/Runtime/NumericalFormatTest.cpp +++ flang/unittests/Runtime/NumericalFormatTest.cpp @@ -686,6 +686,8 @@ {"(1P,F18.0)", " 125", 0x4029000000000000}, // 12.5 {"(BZ,F18.0)", " 125 ", 0x4093880000000000}, // 1250 {"(BZ,F18.0)", " 125 . e +1 ", 0x42a6bcc41e900000}, // 1.25e13 + {"(BZ,F18.0)", " . ", 0x0}, + {"(BZ,F18.0)", " . e +1 ", 0x0}, {"(DC,F18.0)", " 12,5", 0x4029000000000000}, }; for (auto const &[format, data, want] : testCases) {