1 //===-- runtime/command.cpp -----------------------------------------------===// 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 "flang/Runtime/command.h" 10 #include "environment.h" 11 #include "stat.h" 12 #include "flang/Runtime/descriptor.h" 13 #include <limits> 14 15 namespace Fortran::runtime { 16 std::int32_t RTNAME(ArgumentCount)() { 17 int argc{executionEnvironment.argc}; 18 if (argc > 1) { 19 // C counts the command name as one of the arguments, but Fortran doesn't. 20 return argc - 1; 21 } 22 return 0; 23 } 24 25 // Returns the length of the \p n'th argument. Assumes \p n is valid. 26 static std::int64_t ArgumentLength(std::int32_t n) { 27 std::size_t length{std::strlen(executionEnvironment.argv[n])}; 28 if constexpr (sizeof(std::size_t) <= sizeof(std::int64_t)) { 29 return static_cast<std::int64_t>(length); 30 } else { 31 std::size_t max{std::numeric_limits<std::int64_t>::max()}; 32 return length > max ? 0 // Just fail. 33 : static_cast<std::int64_t>(length); 34 } 35 } 36 37 std::int64_t RTNAME(ArgumentLength)(std::int32_t n) { 38 if (n < 0 || n >= executionEnvironment.argc) { 39 return 0; 40 } 41 42 return ArgumentLength(n); 43 } 44 45 static bool IsValidCharDescriptor(const Descriptor *value) { 46 return value && value->IsAllocated() && 47 value->type() == TypeCode(TypeCategory::Character, 1) && 48 value->rank() == 0; 49 } 50 51 static void FillWithSpaces(const Descriptor *value) { 52 std::memset(value->OffsetElement(), ' ', value->ElementBytes()); 53 } 54 55 std::int32_t RTNAME(ArgumentValue)( 56 std::int32_t n, const Descriptor *value, const Descriptor *errmsg) { 57 if (IsValidCharDescriptor(value)) { 58 FillWithSpaces(value); 59 } 60 61 if (n < 0 || n >= executionEnvironment.argc) { 62 return ToErrmsg(errmsg, StatInvalidArgumentNumber); 63 } 64 65 if (IsValidCharDescriptor(value)) { 66 std::int64_t argLen{ArgumentLength(n)}; 67 if (argLen <= 0) { 68 return ToErrmsg(errmsg, StatMissingArgument); 69 } 70 71 std::int64_t toCopy{ 72 std::min(argLen, static_cast<std::int64_t>(value->ElementBytes()))}; 73 std::memcpy(value->OffsetElement(), executionEnvironment.argv[n], toCopy); 74 75 if (argLen > toCopy) { 76 return ToErrmsg(errmsg, StatValueTooShort); 77 } 78 } 79 80 return StatOk; 81 } 82 } // namespace Fortran::runtime 83