Mercurial > hg > CbC > CbC_llvm
comparison flang/runtime/internal-unit.cpp @ 173:0572611fdcc8 llvm10 llvm12
reorgnization done
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 25 May 2020 11:55:54 +0900 |
parents | |
children | 2e18cbf3894f |
comparison
equal
deleted
inserted
replaced
172:9fbae9c8bf63 | 173:0572611fdcc8 |
---|---|
1 //===-- runtime/internal-unit.cpp -------------------------------*- C++ -*-===// | |
2 // | |
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 | |
6 // | |
7 //===----------------------------------------------------------------------===// | |
8 | |
9 #include "internal-unit.h" | |
10 #include "descriptor.h" | |
11 #include "io-error.h" | |
12 #include <algorithm> | |
13 #include <type_traits> | |
14 | |
15 namespace Fortran::runtime::io { | |
16 | |
17 template <Direction DIR> | |
18 InternalDescriptorUnit<DIR>::InternalDescriptorUnit( | |
19 Scalar scalar, std::size_t length) { | |
20 recordLength = length; | |
21 endfileRecordNumber = 2; | |
22 void *pointer{reinterpret_cast<void *>(const_cast<char *>(scalar))}; | |
23 descriptor().Establish(TypeCode{CFI_type_char}, length, pointer, 0, nullptr, | |
24 CFI_attribute_pointer); | |
25 } | |
26 | |
27 template <Direction DIR> | |
28 InternalDescriptorUnit<DIR>::InternalDescriptorUnit( | |
29 const Descriptor &that, const Terminator &terminator) { | |
30 RUNTIME_CHECK(terminator, that.type().IsCharacter()); | |
31 Descriptor &d{descriptor()}; | |
32 RUNTIME_CHECK( | |
33 terminator, that.SizeInBytes() <= d.SizeInBytes(maxRank, true, 0)); | |
34 new (&d) Descriptor{that}; | |
35 d.Check(); | |
36 recordLength = d.ElementBytes(); | |
37 endfileRecordNumber = d.Elements() + 1; | |
38 } | |
39 | |
40 template <Direction DIR> void InternalDescriptorUnit<DIR>::EndIoStatement() { | |
41 if constexpr (DIR == Direction::Output) { // blank fill | |
42 while (char *record{CurrentRecord()}) { | |
43 if (furthestPositionInRecord < | |
44 recordLength.value_or(furthestPositionInRecord)) { | |
45 std::fill_n(record + furthestPositionInRecord, | |
46 *recordLength - furthestPositionInRecord, ' '); | |
47 } | |
48 furthestPositionInRecord = 0; | |
49 ++currentRecordNumber; | |
50 } | |
51 } | |
52 } | |
53 | |
54 template <Direction DIR> | |
55 bool InternalDescriptorUnit<DIR>::Emit( | |
56 const char *data, std::size_t bytes, IoErrorHandler &handler) { | |
57 if constexpr (DIR == Direction::Input) { | |
58 handler.Crash("InternalDescriptorUnit<Direction::Input>::Emit() called"); | |
59 return false && data[bytes] != 0; // bogus compare silences GCC warning | |
60 } else { | |
61 if (bytes <= 0) { | |
62 return true; | |
63 } | |
64 char *record{CurrentRecord()}; | |
65 if (!record) { | |
66 handler.SignalError(IostatInternalWriteOverrun); | |
67 return false; | |
68 } | |
69 auto furthestAfter{std::max(furthestPositionInRecord, | |
70 positionInRecord + static_cast<std::int64_t>(bytes))}; | |
71 bool ok{true}; | |
72 if (furthestAfter > static_cast<std::int64_t>(recordLength.value_or(0))) { | |
73 handler.SignalError(IostatRecordWriteOverrun); | |
74 furthestAfter = recordLength.value_or(0); | |
75 bytes = std::max(std::int64_t{0}, furthestAfter - positionInRecord); | |
76 ok = false; | |
77 } else if (positionInRecord > furthestPositionInRecord) { | |
78 std::fill_n(record + furthestPositionInRecord, | |
79 positionInRecord - furthestPositionInRecord, ' '); | |
80 } | |
81 std::memcpy(record + positionInRecord, data, bytes); | |
82 positionInRecord += bytes; | |
83 furthestPositionInRecord = furthestAfter; | |
84 return ok; | |
85 } | |
86 } | |
87 | |
88 template <Direction DIR> | |
89 std::optional<char32_t> InternalDescriptorUnit<DIR>::GetCurrentChar( | |
90 IoErrorHandler &handler) { | |
91 if constexpr (DIR == Direction::Output) { | |
92 handler.Crash( | |
93 "InternalDescriptorUnit<Direction::Output>::GetCurrentChar() called"); | |
94 return std::nullopt; | |
95 } | |
96 const char *record{CurrentRecord()}; | |
97 if (!record) { | |
98 handler.SignalEnd(); | |
99 return std::nullopt; | |
100 } | |
101 if (positionInRecord >= recordLength.value_or(positionInRecord)) { | |
102 return std::nullopt; | |
103 } | |
104 if (isUTF8) { | |
105 // TODO: UTF-8 decoding | |
106 } | |
107 return record[positionInRecord]; | |
108 } | |
109 | |
110 template <Direction DIR> | |
111 bool InternalDescriptorUnit<DIR>::AdvanceRecord(IoErrorHandler &handler) { | |
112 if (currentRecordNumber >= endfileRecordNumber.value_or(0)) { | |
113 handler.SignalEnd(); | |
114 return false; | |
115 } | |
116 if constexpr (DIR == Direction::Output) { // blank fill | |
117 if (furthestPositionInRecord < | |
118 recordLength.value_or(furthestPositionInRecord)) { | |
119 char *record{CurrentRecord()}; | |
120 RUNTIME_CHECK(handler, record != nullptr); | |
121 std::fill_n(record + furthestPositionInRecord, | |
122 *recordLength - furthestPositionInRecord, ' '); | |
123 } | |
124 } | |
125 ++currentRecordNumber; | |
126 positionInRecord = 0; | |
127 furthestPositionInRecord = 0; | |
128 return true; | |
129 } | |
130 | |
131 template <Direction DIR> | |
132 void InternalDescriptorUnit<DIR>::BackspaceRecord(IoErrorHandler &handler) { | |
133 RUNTIME_CHECK(handler, currentRecordNumber > 1); | |
134 --currentRecordNumber; | |
135 positionInRecord = 0; | |
136 furthestPositionInRecord = 0; | |
137 } | |
138 | |
139 template class InternalDescriptorUnit<Direction::Output>; | |
140 template class InternalDescriptorUnit<Direction::Input>; | |
141 } // namespace Fortran::runtime::io |