[flang-commits] [flang] [llvm] Flang improve fidelity of unformatted I/O endianness with FORT_CONVERT_UNIT (PR #223831)

David Parks via flang-commits flang-commits at lists.llvm.org
Fri Sep 18 09:12:55 PDT 2026


================
@@ -97,6 +98,157 @@ common::optional<Convert> GetConvertFromString(const char *x, std::size_t n) {
 }
 RT_OFFLOAD_API_GROUP_END
 
+bool ExecutionEnvironment::ParseFortConvertUnit(const char *cenvStr) {
+  bool success{true};
+  char *envStr{strdup(cenvStr)};
+
+  if (nullptr == envStr) {
+    Terminator{__FILE__, __LINE__}.Crash(
+        "FORT_CONVERT_UNIT: could not allocate memory");
+  }
+
+  char *exceptionSvptr{nullptr};
+  char *exceptionStr;
+  char *unitListStr;
+  bool firstException{true};
+  Convert gblConversion{conversion};
+
+  // Flang's FORT_CONVERT_UNIT syntax follows NVIDIA's FORT_CONVERT_UNIT and
+  // GNU's gfortran GFORTRAN_CONVERT_UNIT.
+  //
+  // FORT_CONVERT_UNIT: mode | mode ';' exception | exception ;
+  // mode: 'native' | 'swap' | 'big_endian' | 'little_endian' ;
+  // exception: mode ':' unit_list | unit_list ;
+  // unit_list: unit_spec | unit_list ',' unit_spec ;
+  // unit_spec: INTEGER | INTEGER '-' INTEGER ;
+
+  while (success) {
+#if _WIN32
+    exceptionStr =
+        strtok_s(exceptionSvptr ? nullptr : envStr, ";", &exceptionSvptr);
+#else
+    exceptionStr =
+        strtok_r(exceptionSvptr ? nullptr : envStr, ";", &exceptionSvptr);
+#endif
+    if (nullptr == exceptionStr) {
+      break;
+    }
+
+    // unitList is not yet correct, might be nullptr or pointing to ':'.
+    unitListStr = strchr(exceptionStr, ':');
+
+    if (firstException && (nullptr == unitListStr) &&
+        !isdigit(exceptionStr[0])) {
+      // if first pass extracting an exception, and exceptionStr does not
+      // contain a ':' this becomes the global setting.
+      // Akin to specifying FORT_CONVERT=<mode>.
+      if (auto convert{
+              GetConvertFromString(exceptionStr, std::strlen(exceptionStr))}) {
+        gblConversion = *convert;
+      } else {
+        success = false;
+        break;
+      }
+      firstException = false;
+      continue;
+    }
+
+    // mode ';' exception | exception
+    char *unitListSvptr{nullptr};
+    // For the case where <mode> is unspecified
+    Convert conversion{Convert::BigEndian};
+
+    // If unitListStr != nullptr extract mode from modeStr[:unitListStr-1].
+    if (nullptr != unitListStr) {
+      *unitListStr++ = '\0'; // Advance unitListStr
+      if (auto convert{
+              GetConvertFromString(exceptionStr, std::strlen(exceptionStr))}) {
+        conversion = *convert;
+      } else {
+        success = false;
+        break;
+      }
+    } else {
+      unitListStr = exceptionStr;
+    }
+
+    unitListSvptr = nullptr;
+
+    // Loop over unit list extracting individual or ranges of units, separated
+    // by commas.
+
+    while (success) {
+      char *units;
+      int lb, ub;
+      char remStr[2];
+      int nread;
+      int nexpected;
+
+      lb = ub = -1;
+#if _WIN32
+      units =
+          strtok_s(unitListSvptr ? nullptr : unitListStr, ";", &unitListSvptr);
----------------
d-parks wrote:

Fixed.

https://github.com/llvm/llvm-project/pull/223831


More information about the flang-commits mailing list