[flang-commits] [flang] 52a0b02 - [flang][runtime] Reset the left tab limit when flushing output

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Thu Apr 13 09:43:52 PDT 2023


Author: Peter Klausler
Date: 2023-04-13T09:43:40-07:00
New Revision: 52a0b02c25d2c9bff215ad541ed7bd5d8fdecacc

URL: https://github.com/llvm/llvm-project/commit/52a0b02c25d2c9bff215ad541ed7bd5d8fdecacc
DIFF: https://github.com/llvm/llvm-project/commit/52a0b02c25d2c9bff215ad541ed7bd5d8fdecacc.diff

LOG: [flang][runtime] Reset the left tab limit when flushing output

When flushing output to a non-positionable tty or socket file, reset the
left tab limit.  Otherwise, non-advancing output to that file will contain
an increasing amount of leading spaces in each flush.  Also, detect
newline characters in stream output, and treat them as record
advancement.

Differential Revision: https://reviews.llvm.org/D148157

Added: 
    

Modified: 
    flang/runtime/emit-encoded.h
    flang/runtime/tools.h
    flang/runtime/unit.cpp

Removed: 
    


################################################################################
diff  --git a/flang/runtime/emit-encoded.h b/flang/runtime/emit-encoded.h
index 192c7ec068a4e..864848c3b19c6 100644
--- a/flang/runtime/emit-encoded.h
+++ b/flang/runtime/emit-encoded.h
@@ -13,6 +13,7 @@
 
 #include "connection.h"
 #include "environment.h"
+#include "tools.h"
 #include "utf.h"
 
 namespace Fortran::runtime::io {
@@ -20,6 +21,20 @@ namespace Fortran::runtime::io {
 template <typename CONTEXT, typename CHAR>
 bool EmitEncoded(CONTEXT &to, const CHAR *data, std::size_t chars) {
   ConnectionState &connection{to.GetConnectionState()};
+  if (connection.access == Access::Stream &&
+      connection.internalIoCharKind == 0) {
+    // Stream output: treat newlines as record advancements so that the left tab
+    // limit is correctly managed
+    while (const CHAR * nl{FindCharacter(data, CHAR{'\n'}, chars)}) {
+      auto pos{static_cast<std::size_t>(nl - data)};
+      if (!EmitEncoded(to, data, pos)) {
+        return false;
+      }
+      data += pos + 1;
+      chars -= pos + 1;
+      to.AdvanceRecord();
+    }
+  }
   if (connection.useUTF8<CHAR>()) {
     using UnsignedChar = std::make_unsigned_t<CHAR>;
     const UnsignedChar *uData{reinterpret_cast<const UnsignedChar *>(data)};
@@ -61,7 +76,8 @@ bool EmitEncoded(CONTEXT &to, const CHAR *data, std::size_t chars) {
 template <typename CONTEXT>
 bool EmitAscii(CONTEXT &to, const char *data, std::size_t chars) {
   ConnectionState &connection{to.GetConnectionState()};
-  if (connection.internalIoCharKind <= 1) {
+  if (connection.internalIoCharKind <= 1 &&
+      connection.access != Access::Stream) {
     return to.Emit(data, chars);
   } else {
     return EmitEncoded(to, data, chars);
@@ -74,7 +90,9 @@ bool EmitRepeated(CONTEXT &to, char ch, std::size_t n) {
     return true;
   }
   ConnectionState &connection{to.GetConnectionState()};
-  if (connection.internalIoCharKind <= 1) {
+  if (connection.internalIoCharKind <= 1 &&
+      connection.access != Access::Stream) {
+    // faster path, no encoding needed
     while (n-- > 0) {
       if (!to.Emit(&ch, 1)) {
         return false;

diff  --git a/flang/runtime/tools.h b/flang/runtime/tools.h
index a9c942d53eea4..d96d8481b23ac 100644
--- a/flang/runtime/tools.h
+++ b/flang/runtime/tools.h
@@ -13,6 +13,7 @@
 #include "flang/Runtime/cpp-type.h"
 #include "flang/Runtime/descriptor.h"
 #include "flang/Runtime/memory.h"
+#include <cstring>
 #include <functional>
 #include <map>
 #include <type_traits>
@@ -356,5 +357,24 @@ using AccumulationType = CppTypeFor<CAT,
         ? std::max(KIND, static_cast<int>(sizeof(double)))
         : KIND>;
 
+// memchr() for any character type
+template <typename CHAR>
+static inline const CHAR *FindCharacter(
+    const CHAR *data, CHAR ch, std::size_t chars) {
+  const CHAR *end{data + chars};
+  for (const CHAR *p{data}; p < end; ++p) {
+    if (*p == ch) {
+      return p;
+    }
+  }
+  return nullptr;
+}
+
+template <>
+inline const char *FindCharacter(const char *data, char ch, std::size_t chars) {
+  return reinterpret_cast<const char *>(
+      std::memchr(data, static_cast<int>(ch), chars));
+}
+
 } // namespace Fortran::runtime
 #endif // FORTRAN_RUNTIME_TOOLS_H_

diff  --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp
index 092a0a27b5c23..af2c83509b773 100644
--- a/flang/runtime/unit.cpp
+++ b/flang/runtime/unit.cpp
@@ -9,6 +9,7 @@
 #include "unit.h"
 #include "io-error.h"
 #include "lock.h"
+#include "tools.h"
 #include "unit-map.h"
 #include <cstdio>
 #include <limits>
@@ -417,8 +418,7 @@ bool ExternalFileUnit::SetVariableFormattedRecordLength() {
   } else if (FrameLength() > recordOffsetInFrame_) {
     const char *record{Frame() + recordOffsetInFrame_};
     std::size_t bytes{FrameLength() - recordOffsetInFrame_};
-    if (const char *nl{
-            reinterpret_cast<const char *>(std::memchr(record, '\n', bytes))}) {
+    if (const char *nl{FindCharacter(record, '\n', bytes)}) {
       recordLength = nl - record;
       if (*recordLength > 0 && record[*recordLength - 1] == '\r') {
         --*recordLength;
@@ -621,6 +621,7 @@ void ExternalFileUnit::FlushOutput(IoErrorHandler &handler) {
       // needs to advance frameOffsetInFile_ to prevent attempts at
       // impossible seeks
       CommitWrites();
+      leftTabLimit.reset();
     }
   }
   Flush(handler);


        


More information about the flang-commits mailing list