summaryrefslogtreecommitdiff
path: root/flang/runtime/format.h
diff options
context:
space:
mode:
authorpeter klausler <pklausler@nvidia.com>2020-02-04 16:55:45 -0800
committerpeter klausler <pklausler@nvidia.com>2020-02-13 10:31:26 -0800
commit95696d563b927cb51f4a55976e7f64992e1c0acf (patch)
tree959b42e045042b29aeb94066d393c7ef739badc1 /flang/runtime/format.h
parentdbea781d199babb68a71d08a0694522184b93e2d (diff)
downloadllvm-95696d563b927cb51f4a55976e7f64992e1c0acf.tar.gz
[flang] Progress on Fortran I/O runtime
Use internal units for internal I/O state Replace use of virtual functions reference_wrapper Internal formatted output to array descriptor Delete dead code Begin list-directed internal output Refactorings and renamings for clarity List-directed external I/O (character) COMPLEX list-directed output Control list items First cut at unformatted I/O More OPEN statement work; rename class to ExternalFileUnit Complete OPEN (exc. for POSITION=), add CLOSE() OPEN(POSITION=) Flush buffers on crash and for terminal output; clean up Documentation Fix backquote in documentation Fix typo in comment Begin implementation of input Refactor binary floating-point properties to a new header, simplify numeric output editing Dodge spurious GCC 7.2 build warning Address review comments Original-commit: flang-compiler/f18@9c4bba11cf2329575ea9ee446f69e9caa797135c Reviewed-on: https://github.com/flang-compiler/f18/pull/982
Diffstat (limited to 'flang/runtime/format.h')
-rw-r--r--flang/runtime/format.h72
1 files changed, 39 insertions, 33 deletions
diff --git a/flang/runtime/format.h b/flang/runtime/format.h
index c954c7f3872f..c072b3b9805d 100644
--- a/flang/runtime/format.h
+++ b/flang/runtime/format.h
@@ -12,8 +12,10 @@
#define FORTRAN_RUNTIME_FORMAT_H_
#include "environment.h"
+#include "io-error.h"
#include "terminator.h"
#include "flang/common/Fortran.h"
+#include "flang/decimal/decimal.h"
#include <cinttypes>
#include <optional>
@@ -27,7 +29,7 @@ enum EditingFlags {
struct MutableModes {
std::uint8_t editingFlags{0}; // BN, DP, SS
- common::RoundingMode roundingMode{
+ enum decimal::FortranRounding round{
executionEnvironment
.defaultOutputRoundingMode}; // RP/ROUND='PROCESSOR_DEFAULT'
bool pad{false}; // PAD= mode on READ
@@ -38,6 +40,16 @@ struct MutableModes {
// A single edit descriptor extracted from a FORMAT
struct DataEdit {
char descriptor; // capitalized: one of A, I, B, O, Z, F, E(N/S/X), D, G
+
+ // Special internal data edit descriptors to distinguish list-directed I/O
+ static constexpr char ListDirected{'g'}; // non-COMPLEX list-directed
+ static constexpr char ListDirectedRealPart{'r'}; // emit "(r," or "(r;"
+ static constexpr char ListDirectedImaginaryPart{'z'}; // emit "z)"
+ constexpr bool IsListDirected() const {
+ return descriptor == ListDirected || descriptor == ListDirectedRealPart ||
+ descriptor == ListDirectedImaginaryPart;
+ }
+
char variation{'\0'}; // N, S, or X for EN, ES, EX
std::optional<int> width; // the 'w' field; optional for A
std::optional<int> digits; // the 'm' or 'd' field
@@ -46,37 +58,35 @@ struct DataEdit {
int repeat{1};
};
-class FormatContext : virtual public Terminator {
-public:
- FormatContext() {}
- virtual ~FormatContext() {}
- explicit FormatContext(const MutableModes &modes) : mutableModes_{modes} {}
- virtual bool Emit(const char *, std::size_t) = 0;
- virtual bool Emit(const char16_t *, std::size_t) = 0;
- virtual bool Emit(const char32_t *, std::size_t) = 0;
- virtual bool HandleSlash(int = 1) = 0;
- virtual bool HandleRelativePosition(std::int64_t) = 0;
- virtual bool HandleAbsolutePosition(std::int64_t) = 0;
- MutableModes &mutableModes() { return mutableModes_; }
-
-private:
- MutableModes mutableModes_;
+// FormatControl<A> requires that A have these member functions;
+// these default implementations just crash if called.
+struct DefaultFormatControlCallbacks : public IoErrorHandler {
+ using IoErrorHandler::IoErrorHandler;
+ DataEdit GetNextDataEdit(int = 1);
+ bool Emit(const char *, std::size_t);
+ bool Emit(const char16_t *, std::size_t);
+ bool Emit(const char32_t *, std::size_t);
+ bool AdvanceRecord(int = 1);
+ bool HandleAbsolutePosition(std::int64_t);
+ bool HandleRelativePosition(std::int64_t);
};
// Generates a sequence of DataEdits from a FORMAT statement or
// default-CHARACTER string. Driven by I/O item list processing.
// Errors are fatal. See clause 13.4 in Fortran 2018 for background.
-template<typename CHAR = char> class FormatControl {
+template<typename CONTEXT> class FormatControl {
public:
+ using Context = CONTEXT;
+ using CharType = typename Context::CharType;
+
FormatControl() {}
- // TODO: make 'format' a reference here and below
- FormatControl(Terminator &, const CHAR *format, std::size_t formatLength,
- int maxHeight = maxMaxHeight);
+ FormatControl(const Terminator &, const CharType *format,
+ std::size_t formatLength, int maxHeight = maxMaxHeight);
// Determines the max parenthesis nesting level by scanning and validating
// the FORMAT string.
static int GetMaxParenthesisNesting(
- Terminator &, const CHAR *format, std::size_t formatLength);
+ const Terminator &, const CharType *format, std::size_t formatLength);
// For attempting to allocate in a user-supplied stack area
static std::size_t GetNeededSize(int maxHeight) {
@@ -86,10 +96,10 @@ public:
// Extracts the next data edit descriptor, handling control edit descriptors
// along the way.
- void GetNext(FormatContext &, DataEdit &, int maxRepeat = 1);
+ DataEdit GetNextDataEdit(Context &, int maxRepeat = 1);
// Emit any remaining character literals after the last data item.
- void FinishOutput(FormatContext &);
+ void FinishOutput(Context &);
private:
static constexpr std::uint8_t maxMaxHeight{100};
@@ -105,27 +115,27 @@ private:
++offset_;
}
}
- CHAR PeekNext() {
+ CharType PeekNext() {
SkipBlanks();
return offset_ < formatLength_ ? format_[offset_] : '\0';
}
- CHAR GetNextChar(Terminator &terminator) {
+ CharType GetNextChar(const Terminator &terminator) {
SkipBlanks();
if (offset_ >= formatLength_) {
terminator.Crash("FORMAT missing at least one ')'");
}
return format_[offset_++];
}
- int GetIntField(Terminator &, CHAR firstCh = '\0');
+ int GetIntField(const Terminator &, CharType firstCh = '\0');
// Advances through the FORMAT until the next data edit
// descriptor has been found; handles control edit descriptors
// along the way. Returns the repeat count that appeared
// before the descriptor (defaulting to 1) and leaves offset_
// pointing to the data edit.
- int CueUpNextDataEdit(FormatContext &, bool stop = false);
+ int CueUpNextDataEdit(Context &, bool stop = false);
- static constexpr CHAR Capitalize(CHAR ch) {
+ static constexpr CharType Capitalize(CharType ch) {
return ch >= 'a' && ch <= 'z' ? ch + 'A' - 'a' : ch;
}
@@ -134,16 +144,12 @@ private:
// user program for internal I/O.
const std::uint8_t maxHeight_{maxMaxHeight};
std::uint8_t height_{0};
- const CHAR *format_{nullptr};
+ const CharType *format_{nullptr};
int formatLength_{0};
int offset_{0}; // next item is at format_[offset_]
// must be last, may be incomplete
Iteration stack_[maxMaxHeight];
};
-
-extern template class FormatControl<char>;
-extern template class FormatControl<char16_t>;
-extern template class FormatControl<char32_t>;
}
#endif // FORTRAN_RUNTIME_FORMAT_H_