text: //===-- runtime/stat.cpp --------------------------------------------------===//
  //
  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  // See https://llvm.org/LICENSE.txt for license information.
  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  //
  //===----------------------------------------------------------------------===//
  
  #include "stat.h"
  #include "terminator.h"
  #include "flang/Runtime/descriptor.h"
  
  namespace Fortran::runtime {
  const char *StatErrorString(int stat) {
    switch (stat) {
    case StatOk:
      return "No error";
  
    case StatBaseNull:
      return "Base address is null";
    case StatBaseNotNull:
      return "Base address is not null";
    case StatInvalidElemLen:
      return "Invalid element length";
    case StatInvalidRank:
      return "Invalid rank";
    case StatInvalidType:
      return "Invalid type";
    case StatInvalidAttribute:
      return "Invalid attribute";
    case StatInvalidExtent:
      return "Invalid extent";
    case StatInvalidDescriptor:
      return "Invalid descriptor";
    case StatMemAllocation:
      return "Memory allocation failed";
    case StatOutOfBounds:
      return "Out of bounds";
  
    case StatFailedImage:
      return "Failed image";
    case StatLocked:
      return "Locked";
    case StatLockedOtherImage:
      return "Other image locked";
    case StatStoppedImage:
      return "Image stopped";
    case StatUnlocked:
      return "Unlocked";
    case StatUnlockedFailedImage:
      return "Failed image unlocked";
  
    case StatInvalidArgumentNumber:
      return "Invalid argument number";
    case StatMissingArgument:
      return "Missing argument";
    case StatValueTooShort:
      return "Value too short";
  
    default:
      return nullptr;
    }
  }
  
  int ToErrmsg(const Descriptor *errmsg, int stat) {
    if (stat != StatOk && errmsg && errmsg->raw().base_addr &&
        errmsg->type() == TypeCode(TypeCategory::Character, 1) &&
        errmsg->rank() == 0) {
      if (const char *msg{StatErrorString(stat)}) {
        char *buffer{errmsg->OffsetElement()};
        std::size_t bufferLength{errmsg->ElementBytes()};
        std::size_t msgLength{std::strlen(msg)};
        if (msgLength >= bufferLength) {
          std::memcpy(buffer, msg, bufferLength);
        } else {
          std::memcpy(buffer, msg, msgLength);
          std::memset(buffer + msgLength, ' ', bufferLength - msgLength);
        }
      }
    }
    return stat;
  }
  
  int ReturnError(
      Terminator &terminator, int stat, const Descriptor *errmsg, bool hasStat) {
    if (stat == StatOk || hasStat) {
      return ToErrmsg(errmsg, stat);
    } else if (const char *msg{StatErrorString(stat)}) {
      terminator.Crash(msg);
    } else {
      terminator.Crash("Invalid Fortran runtime STAT= code %d", stat);
    }
    return stat;
  }
  } // namespace Fortran::runtime
  