1651f58bfSDiana Picus //===-- runtime/stat.cpp --------------------------------------------------===//
28df28f0aSpeter klausler //
38df28f0aSpeter klausler // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
48df28f0aSpeter klausler // See https://llvm.org/LICENSE.txt for license information.
58df28f0aSpeter klausler // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
68df28f0aSpeter klausler //
78df28f0aSpeter klausler //===----------------------------------------------------------------------===//
88df28f0aSpeter klausler 
98df28f0aSpeter klausler #include "stat.h"
108df28f0aSpeter klausler #include "terminator.h"
11830c0b90SPeter Klausler #include "flang/Runtime/descriptor.h"
128df28f0aSpeter klausler 
138df28f0aSpeter klausler namespace Fortran::runtime {
StatErrorString(int stat)148df28f0aSpeter klausler const char *StatErrorString(int stat) {
158df28f0aSpeter klausler   switch (stat) {
168df28f0aSpeter klausler   case StatOk:
178df28f0aSpeter klausler     return "No error";
188df28f0aSpeter klausler 
198df28f0aSpeter klausler   case StatBaseNull:
208df28f0aSpeter klausler     return "Base address is null";
218df28f0aSpeter klausler   case StatBaseNotNull:
228df28f0aSpeter klausler     return "Base address is not null";
238df28f0aSpeter klausler   case StatInvalidElemLen:
248df28f0aSpeter klausler     return "Invalid element length";
258df28f0aSpeter klausler   case StatInvalidRank:
268df28f0aSpeter klausler     return "Invalid rank";
278df28f0aSpeter klausler   case StatInvalidType:
288df28f0aSpeter klausler     return "Invalid type";
298df28f0aSpeter klausler   case StatInvalidAttribute:
308df28f0aSpeter klausler     return "Invalid attribute";
318df28f0aSpeter klausler   case StatInvalidExtent:
328df28f0aSpeter klausler     return "Invalid extent";
338df28f0aSpeter klausler   case StatInvalidDescriptor:
348df28f0aSpeter klausler     return "Invalid descriptor";
358df28f0aSpeter klausler   case StatMemAllocation:
368df28f0aSpeter klausler     return "Memory allocation failed";
378df28f0aSpeter klausler   case StatOutOfBounds:
388df28f0aSpeter klausler     return "Out of bounds";
398df28f0aSpeter klausler 
408df28f0aSpeter klausler   case StatFailedImage:
418df28f0aSpeter klausler     return "Failed image";
428df28f0aSpeter klausler   case StatLocked:
438df28f0aSpeter klausler     return "Locked";
448df28f0aSpeter klausler   case StatLockedOtherImage:
458df28f0aSpeter klausler     return "Other image locked";
468df28f0aSpeter klausler   case StatStoppedImage:
478df28f0aSpeter klausler     return "Image stopped";
488df28f0aSpeter klausler   case StatUnlocked:
498df28f0aSpeter klausler     return "Unlocked";
508df28f0aSpeter klausler   case StatUnlockedFailedImage:
518df28f0aSpeter klausler     return "Failed image unlocked";
528df28f0aSpeter klausler 
5337089baeSDiana Picus   case StatInvalidArgumentNumber:
5437089baeSDiana Picus     return "Invalid argument number";
5537089baeSDiana Picus   case StatMissingArgument:
5637089baeSDiana Picus     return "Missing argument";
5737089baeSDiana Picus   case StatValueTooShort:
5837089baeSDiana Picus     return "Value too short";
5937089baeSDiana Picus 
60*9df0ba59SDiana Picus   case StatMissingEnvVariable:
61*9df0ba59SDiana Picus     return "Missing environment variable";
62*9df0ba59SDiana Picus 
638df28f0aSpeter klausler   default:
648df28f0aSpeter klausler     return nullptr;
658df28f0aSpeter klausler   }
668df28f0aSpeter klausler }
678df28f0aSpeter klausler 
ToErrmsg(const Descriptor * errmsg,int stat)68170e9061Speter klausler int ToErrmsg(const Descriptor *errmsg, int stat) {
698df28f0aSpeter klausler   if (stat != StatOk && errmsg && errmsg->raw().base_addr &&
708df28f0aSpeter klausler       errmsg->type() == TypeCode(TypeCategory::Character, 1) &&
718df28f0aSpeter klausler       errmsg->rank() == 0) {
728df28f0aSpeter klausler     if (const char *msg{StatErrorString(stat)}) {
738df28f0aSpeter klausler       char *buffer{errmsg->OffsetElement()};
748df28f0aSpeter klausler       std::size_t bufferLength{errmsg->ElementBytes()};
758df28f0aSpeter klausler       std::size_t msgLength{std::strlen(msg)};
76170e9061Speter klausler       if (msgLength >= bufferLength) {
778df28f0aSpeter klausler         std::memcpy(buffer, msg, bufferLength);
788df28f0aSpeter klausler       } else {
798df28f0aSpeter klausler         std::memcpy(buffer, msg, msgLength);
808df28f0aSpeter klausler         std::memset(buffer + msgLength, ' ', bufferLength - msgLength);
818df28f0aSpeter klausler       }
828df28f0aSpeter klausler     }
838df28f0aSpeter klausler   }
848df28f0aSpeter klausler   return stat;
858df28f0aSpeter klausler }
868df28f0aSpeter klausler 
ReturnError(Terminator & terminator,int stat,const Descriptor * errmsg,bool hasStat)878df28f0aSpeter klausler int ReturnError(
88170e9061Speter klausler     Terminator &terminator, int stat, const Descriptor *errmsg, bool hasStat) {
898df28f0aSpeter klausler   if (stat == StatOk || hasStat) {
908df28f0aSpeter klausler     return ToErrmsg(errmsg, stat);
918df28f0aSpeter klausler   } else if (const char *msg{StatErrorString(stat)}) {
928df28f0aSpeter klausler     terminator.Crash(msg);
938df28f0aSpeter klausler   } else {
948df28f0aSpeter klausler     terminator.Crash("Invalid Fortran runtime STAT= code %d", stat);
958df28f0aSpeter klausler   }
968df28f0aSpeter klausler   return stat;
978df28f0aSpeter klausler }
988df28f0aSpeter klausler } // namespace Fortran::runtime
99