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