[flang-commits] [flang] e6873bf - [flang][runtime] Don't skip input spaces when they are significant
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Thu Apr 14 21:30:56 PDT 2022
Author: Peter Klausler
Date: 2022-04-14T21:30:43-07:00
New Revision: e6873bfbcd356c6aeb0e0bc165326f9fc8f02cbd
URL: https://github.com/llvm/llvm-project/commit/e6873bfbcd356c6aeb0e0bc165326f9fc8f02cbd
DIFF: https://github.com/llvm/llvm-project/commit/e6873bfbcd356c6aeb0e0bc165326f9fc8f02cbd.diff
LOG: [flang][runtime] Don't skip input spaces when they are significant
When formatted input (not list-directed or NAMELIST) is in "BZ" mode,
either because a BZ control edit descriptor appeared in a FORMAT or
BLANK="ZERO" appeared in OPEN or READ, input editing must not skip
over blanks before or within the input field.
Differential Revision: https://reviews.llvm.org/D123725
Added:
Modified:
flang/include/flang/Runtime/iostat.h
flang/runtime/edit-input.cpp
flang/runtime/io-stmt.h
flang/runtime/iostat.cpp
flang/unittests/Runtime/NumericalFormatTest.cpp
Removed:
################################################################################
diff --git a/flang/include/flang/Runtime/iostat.h b/flang/include/flang/Runtime/iostat.h
index 15985b74dd3ce..0303d3de16d09 100644
--- a/flang/include/flang/Runtime/iostat.h
+++ b/flang/include/flang/Runtime/iostat.h
@@ -68,6 +68,7 @@ enum Iostat {
IostatBadUnformattedRecord,
IostatUTF8Decoding,
IostatUnitOverflow,
+ IostatBadRealInput,
};
const char *IostatErrorString(int);
diff --git a/flang/runtime/edit-input.cpp b/flang/runtime/edit-input.cpp
index 73a3478fbbe31..d7cace7b34c3f 100644
--- a/flang/runtime/edit-input.cpp
+++ b/flang/runtime/edit-input.cpp
@@ -58,12 +58,15 @@ static inline char32_t GetDecimalPoint(const DataEdit &edit) {
// Returns true if there's a '-' sign.
static bool ScanNumericPrefix(IoStatementState &io, const DataEdit &edit,
std::optional<char32_t> &next, std::optional<int> &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);
}
}
@@ -153,7 +156,8 @@ static int ScanRealInput(char *buffer, int bufferSize, IoStatementState &io,
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');
@@ -181,10 +185,11 @@ static int ScanRealInput(char *buffer, int bufferSize, IoStatementState &io,
}
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') {
@@ -195,8 +200,10 @@ static int ScanRealInput(char *buffer, int bufferSize, IoStatementState &io,
}
}
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
@@ -206,7 +213,11 @@ static int ScanRealInput(char *buffer, int bufferSize, IoStatementState &io,
}
}
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' ||
@@ -372,7 +383,7 @@ bool EditCommonRealInput(IoStatementState &io, const DataEdit &edit, void *n) {
return false;
}
if (got == 0) {
- io.GetIoErrorHandler().SignalError("Bad REAL input value");
+ io.GetIoErrorHandler().SignalError(IostatBadRealInput);
return false;
}
bool hadExtra{got > maxDigits};
diff --git a/flang/runtime/io-stmt.h b/flang/runtime/io-stmt.h
index 72d6bf6b3b629..41bcfa3bb217d 100644
--- a/flang/runtime/io-stmt.h
+++ b/flang/runtime/io-stmt.h
@@ -132,8 +132,8 @@ class IoStatementState {
// 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<char32_t> PrepareInput(
- const DataEdit &edit, std::optional<int> &remaining) {
+ std::optional<char32_t> PrepareInput(const DataEdit &edit,
+ std::optional<int> &remaining, bool skipSpaces = true) {
remaining.reset();
if (edit.descriptor == DataEdit::ListDirected) {
std::size_t byteCount{0};
@@ -142,7 +142,9 @@ class IoStatementState {
if (edit.width.value_or(0) > 0) {
remaining = *edit.width;
}
- SkipSpaces(remaining);
+ if (skipSpaces) {
+ SkipSpaces(remaining);
+ }
}
return NextInField(remaining, edit);
}
diff --git a/flang/runtime/iostat.cpp b/flang/runtime/iostat.cpp
index 5b761369206cb..e31fb83678301 100644
--- a/flang/runtime/iostat.cpp
+++ b/flang/runtime/iostat.cpp
@@ -79,6 +79,8 @@ const char *IostatErrorString(int iostat) {
return "UTF-8 decoding error";
case IostatUnitOverflow:
return "UNIT number is out of range";
+ case IostatBadRealInput:
+ return "Bad REAL input value";
default:
return nullptr;
}
diff --git a/flang/unittests/Runtime/NumericalFormatTest.cpp b/flang/unittests/Runtime/NumericalFormatTest.cpp
index 3bc7b6dbf4221..a0c9680977413 100644
--- a/flang/unittests/Runtime/NumericalFormatTest.cpp
+++ b/flang/unittests/Runtime/NumericalFormatTest.cpp
@@ -688,6 +688,8 @@ TEST(IOApiTests, FormatDoubleInputValues) {
{"(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) {
More information about the flang-commits
mailing list