llvm-project/flang/runtime/command.cpp
Diana Picus 0446f1299f [flang] GET_COMMAND_ARGUMENT(ERRMSG) runtime implementation
Implement the final part of GET_COMMAND_ARGUMENT, i.e. the handling of
ERRMSG. This uses some of the infrastructure in stat.h and gets rid of
the magic numbers that we were using for return codes.

Differential Revision: https://reviews.llvm.org/D109814
2021-09-28 08:32:19 +00:00

83 lines
2.4 KiB
C++

//===-- runtime/command.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 "flang/Runtime/command.h"
#include "environment.h"
#include "stat.h"
#include "flang/Runtime/descriptor.h"
#include <limits>
namespace Fortran::runtime {
std::int32_t RTNAME(ArgumentCount)() {
int argc{executionEnvironment.argc};
if (argc > 1) {
// C counts the command name as one of the arguments, but Fortran doesn't.
return argc - 1;
}
return 0;
}
// Returns the length of the \p n'th argument. Assumes \p n is valid.
static std::int64_t ArgumentLength(std::int32_t n) {
std::size_t length{std::strlen(executionEnvironment.argv[n])};
if constexpr (sizeof(std::size_t) <= sizeof(std::int64_t)) {
return static_cast<std::int64_t>(length);
} else {
std::size_t max{std::numeric_limits<std::int64_t>::max()};
return length > max ? 0 // Just fail.
: static_cast<std::int64_t>(length);
}
}
std::int64_t RTNAME(ArgumentLength)(std::int32_t n) {
if (n < 0 || n >= executionEnvironment.argc) {
return 0;
}
return ArgumentLength(n);
}
static bool IsValidCharDescriptor(const Descriptor *value) {
return value && value->IsAllocated() &&
value->type() == TypeCode(TypeCategory::Character, 1) &&
value->rank() == 0;
}
static void FillWithSpaces(const Descriptor *value) {
std::memset(value->OffsetElement(), ' ', value->ElementBytes());
}
std::int32_t RTNAME(ArgumentValue)(
std::int32_t n, const Descriptor *value, const Descriptor *errmsg) {
if (IsValidCharDescriptor(value)) {
FillWithSpaces(value);
}
if (n < 0 || n >= executionEnvironment.argc) {
return ToErrmsg(errmsg, StatInvalidArgumentNumber);
}
if (IsValidCharDescriptor(value)) {
std::int64_t argLen{ArgumentLength(n)};
if (argLen <= 0) {
return ToErrmsg(errmsg, StatMissingArgument);
}
std::int64_t toCopy{
std::min(argLen, static_cast<std::int64_t>(value->ElementBytes()))};
std::strncpy(value->OffsetElement(), executionEnvironment.argv[n], toCopy);
if (argLen > toCopy) {
return ToErrmsg(errmsg, StatValueTooShort);
}
}
return StatOk;
}
} // namespace Fortran::runtime