1 //===-- runtime/format.h ----------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // FORMAT string processing
11 #ifndef FORTRAN_RUNTIME_FORMAT_H_
12 #define FORTRAN_RUNTIME_FORMAT_H_
14 #include "environment.h"
16 #include "flang/Common/Fortran.h"
17 #include "flang/Decimal/decimal.h"
21 namespace Fortran::runtime
{
23 } // namespace Fortran::runtime
25 namespace Fortran::runtime::io
{
27 class IoStatementState
;
30 blankZero
= 1, // BLANK=ZERO or BZ edit
31 decimalComma
= 2, // DECIMAL=COMMA or DC edit
32 signPlus
= 4, // SIGN=PLUS or SP edit
36 std::uint8_t editingFlags
{0}; // BN, DP, SS
37 enum decimal::FortranRounding round
{
39 .defaultOutputRoundingMode
}; // RP/ROUND='PROCESSOR_DEFAULT'
40 bool pad
{true}; // PAD= mode on READ
41 char delim
{'\0'}; // DELIM=
43 bool inNamelist
{false}; // skip ! comments
44 bool nonAdvancing
{false}; // ADVANCE='NO', or $ or \ in FORMAT
47 // A single edit descriptor extracted from a FORMAT
49 char descriptor
; // capitalized: one of A, I, B, O, Z, F, E(N/S/X), D, G
51 // Special internal data edit descriptors for list-directed & NAMELIST I/O
52 static constexpr char ListDirected
{'g'}; // non-COMPLEX list-directed
53 static constexpr char ListDirectedRealPart
{'r'}; // emit "(r," or "(r;"
54 static constexpr char ListDirectedImaginaryPart
{'z'}; // emit "z)"
55 static constexpr char ListDirectedNullValue
{'n'}; // see 13.10.3.2
56 constexpr bool IsListDirected() const {
57 return descriptor
== ListDirected
|| descriptor
== ListDirectedRealPart
||
58 descriptor
== ListDirectedImaginaryPart
;
60 constexpr bool IsNamelist() const {
61 return IsListDirected() && modes
.inNamelist
;
64 static constexpr char DefinedDerivedType
{'d'}; // DT defined I/O
66 char variation
{'\0'}; // N, S, or X for EN, ES, EX
67 std::optional
<int> width
; // the 'w' field; optional for A
68 std::optional
<int> digits
; // the 'm' or 'd' field
69 std::optional
<int> expoDigits
; // 'Ee' field
73 // "iotype" &/or "v_list" values for a DT'iotype'(v_list)
74 // defined I/O data edit descriptor
75 static constexpr std::size_t maxIoTypeChars
{32};
76 static constexpr std::size_t maxVListEntries
{4};
77 std::uint8_t ioTypeChars
{0};
78 std::uint8_t vListEntries
{0};
79 char ioType
[maxIoTypeChars
];
80 int vList
[maxVListEntries
];
83 // Generates a sequence of DataEdits from a FORMAT statement or
84 // default-CHARACTER string. Driven by I/O item list processing.
85 // Errors are fatal. See subclause 13.4 in Fortran 2018 for background.
86 template <typename CONTEXT
> class FormatControl
{
88 using Context
= CONTEXT
;
89 using CharType
= char; // formats are always default kind CHARACTER
92 FormatControl(const Terminator
&, const CharType
*format
,
93 std::size_t formatLength
, const Descriptor
*formatDescriptor
= nullptr,
94 int maxHeight
= maxMaxHeight
);
96 // For attempting to allocate in a user-supplied stack area
97 static std::size_t GetNeededSize(int maxHeight
) {
98 return sizeof(FormatControl
) -
99 sizeof(Iteration
) * (maxMaxHeight
- maxHeight
);
102 // Extracts the next data edit descriptor, handling control edit descriptors
103 // along the way. If maxRepeat==0, this is a peek at the next data edit
105 std::optional
<DataEdit
> GetNextDataEdit(Context
&, int maxRepeat
= 1);
107 // Emit any remaining character literals after the last data item (on output)
108 // and perform remaining record positioning actions.
109 void Finish(Context
&);
112 static constexpr std::uint8_t maxMaxHeight
{100};
115 static constexpr int unlimited
{-1};
116 int start
{0}; // offset in format_ of '(' or a repeated edit descriptor
117 int remaining
{0}; // while >0, decrement and iterate
121 while (offset_
< formatLength_
&&
122 (format_
[offset_
] == ' ' || format_
[offset_
] == '\t' ||
123 format_
[offset_
] == '\v')) {
127 CharType
PeekNext() {
129 return offset_
< formatLength_
? format_
[offset_
] : '\0';
131 CharType
GetNextChar(IoErrorHandler
&handler
) {
133 if (offset_
>= formatLength_
) {
134 if (formatLength_
== 0) {
136 IostatErrorInFormat
, "Empty or badly assigned FORMAT");
139 IostatErrorInFormat
, "FORMAT missing at least one ')'");
143 return format_
[offset_
++];
146 IoErrorHandler
&, CharType firstCh
= '\0', bool *hadError
= nullptr);
148 // Advances through the FORMAT until the next data edit
149 // descriptor has been found; handles control edit descriptors
150 // along the way. Returns the repeat count that appeared
151 // before the descriptor (defaulting to 1) and leaves offset_
152 // pointing to the data edit.
153 int CueUpNextDataEdit(Context
&, bool stop
= false);
155 static constexpr CharType
Capitalize(CharType ch
) {
156 return ch
>= 'a' && ch
<= 'z' ? ch
+ 'A' - 'a' : ch
;
159 void ReportBadFormat(Context
&context
, const char *msg
, int offset
) const {
160 if constexpr (std::is_same_v
<CharType
, char>) {
161 // Echo the bad format in the error message, but trim any leading or
163 int firstNonBlank
{0};
164 while (firstNonBlank
< formatLength_
&& format_
[firstNonBlank
] == ' ') {
167 int lastNonBlank
{formatLength_
- 1};
168 while (lastNonBlank
> firstNonBlank
&& format_
[lastNonBlank
] == ' ') {
171 if (firstNonBlank
<= lastNonBlank
) {
172 context
.SignalError(IostatErrorInFormat
,
173 "%s; at offset %d in format '%.*s'", msg
, offset
,
174 lastNonBlank
- firstNonBlank
+ 1, format_
+ firstNonBlank
);
178 context
.SignalError(IostatErrorInFormat
, "%s; at offset %d", msg
, offset
);
181 // Data members are arranged and typed so as to reduce size.
182 // This structure may be allocated in stack space loaned by the
183 // user program for internal I/O.
184 const std::uint8_t maxHeight_
{maxMaxHeight
};
185 std::uint8_t height_
{0};
186 bool freeFormat_
{false};
187 const CharType
*format_
{nullptr};
188 int formatLength_
{0}; // in units of characters
189 int offset_
{0}; // next item is at format_[offset_]
191 // must be last, may be incomplete
192 Iteration stack_
[maxMaxHeight
];
194 } // namespace Fortran::runtime::io
195 #endif // FORTRAN_RUNTIME_FORMAT_H_