Please use GitHub pull requests for new patches. Avoid migrating existing patches. Phabricator shutdown timeline
Changeset View
Changeset View
Standalone View
Standalone View
flang/runtime/command.cpp
Show All 31 Lines | if constexpr (sizeof(std::size_t) < sizeof(std::int64_t)) { | ||||
return static_cast<std::int64_t>(length); | return static_cast<std::int64_t>(length); | ||||
} else { | } else { | ||||
std::size_t max{std::numeric_limits<std::int64_t>::max()}; | std::size_t max{std::numeric_limits<std::int64_t>::max()}; | ||||
return length > max ? 0 // Just fail. | return length > max ? 0 // Just fail. | ||||
: static_cast<std::int64_t>(length); | : static_cast<std::int64_t>(length); | ||||
} | } | ||||
} | } | ||||
std::int64_t RTNAME(ArgumentLength)(std::int32_t n) { | |||||
if (n < 0 || n >= executionEnvironment.argc || | |||||
!executionEnvironment.argv[n]) { | |||||
return 0; | |||||
} | |||||
return StringLength(executionEnvironment.argv[n]); | |||||
} | |||||
static bool IsValidCharDescriptor(const Descriptor *value) { | static bool IsValidCharDescriptor(const Descriptor *value) { | ||||
return value && value->IsAllocated() && | return value && value->IsAllocated() && | ||||
value->type() == TypeCode(TypeCategory::Character, 1) && | value->type() == TypeCode(TypeCategory::Character, 1) && | ||||
value->rank() == 0; | value->rank() == 0; | ||||
} | } | ||||
static bool IsValidIntDescriptor(const Descriptor *length) { | static bool IsValidIntDescriptor(const Descriptor *length) { | ||||
auto typeCode{length->type().GetCategoryAndKind()}; | auto typeCode{length->type().GetCategoryAndKind()}; | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | static std::int32_t CheckAndCopyToDescriptor(const Descriptor *value, | ||||
if (haveValue) { | if (haveValue) { | ||||
stat = CopyToDescriptor(*value, rawValue, len, errmsg, offset); | stat = CopyToDescriptor(*value, rawValue, len, errmsg, offset); | ||||
} | } | ||||
offset += len; | offset += len; | ||||
return stat; | return stat; | ||||
} | } | ||||
std::int32_t RTNAME(ArgumentValue)( | static void StoreLengthToDescriptor( | ||||
std::int32_t n, const Descriptor *value, const Descriptor *errmsg) { | const Descriptor *length, std::int64_t value, Terminator &terminator) { | ||||
if (IsValidCharDescriptor(value)) { | auto typeCode{length->type().GetCategoryAndKind()}; | ||||
int kind{typeCode->second}; | |||||
Fortran::runtime::ApplyIntegerKind<Fortran::runtime::StoreIntegerAt, void>( | |||||
kind, terminator, *length, /* atIndex = */ 0, value); | |||||
} | |||||
template <int KIND> struct FitsInIntegerKind { | |||||
bool operator()(std::int64_t value) { | |||||
return value <= std::numeric_limits<Fortran::runtime::CppTypeFor< | |||||
Fortran::common::TypeCategory::Integer, KIND>>::max(); | |||||
} | |||||
}; | |||||
static bool FitsInDescriptor( | |||||
const Descriptor *length, std::int64_t value, Terminator &terminator) { | |||||
auto typeCode{length->type().GetCategoryAndKind()}; | |||||
int kind{typeCode->second}; | |||||
return Fortran::runtime::ApplyIntegerKind<FitsInIntegerKind, bool>( | |||||
kind, terminator, value); | |||||
} | |||||
std::int32_t RTNAME(GetCommandArgument)(std::int32_t n, const Descriptor *value, | |||||
const Descriptor *length, const Descriptor *errmsg, const char *sourceFile, | |||||
int line) { | |||||
Terminator terminator{sourceFile, line}; | |||||
if (value) { | |||||
RUNTIME_CHECK(terminator, IsValidCharDescriptor(value)); | |||||
FillWithSpaces(*value); | FillWithSpaces(*value); | ||||
} | } | ||||
// Store 0 in case we error out later on. | |||||
if (length) { | |||||
RUNTIME_CHECK(terminator, IsValidIntDescriptor(length)); | |||||
StoreLengthToDescriptor(length, 0, terminator); | |||||
} | |||||
if (n < 0 || n >= executionEnvironment.argc) { | if (n < 0 || n >= executionEnvironment.argc) { | ||||
return ToErrmsg(errmsg, StatInvalidArgumentNumber); | return ToErrmsg(errmsg, StatInvalidArgumentNumber); | ||||
} | } | ||||
if (IsValidCharDescriptor(value)) { | |||||
const char *arg{executionEnvironment.argv[n]}; | const char *arg{executionEnvironment.argv[n]}; | ||||
std::int64_t argLen{StringLength(arg)}; | std::int64_t argLen{StringLength(arg)}; | ||||
if (argLen <= 0) { | if (argLen <= 0) { | ||||
return ToErrmsg(errmsg, StatMissingArgument); | return ToErrmsg(errmsg, StatMissingArgument); | ||||
} | } | ||||
return CopyToDescriptor(*value, arg, argLen, errmsg); | if (length && FitsInDescriptor(length, argLen, terminator)) { | ||||
StoreLengthToDescriptor(length, argLen, terminator); | |||||
} | } | ||||
return StatOk; | if (value) { | ||||
return CopyToDescriptor(*value, arg, argLen, errmsg); | |||||
} | } | ||||
template <int KIND> struct FitsInIntegerKind { | return StatOk; | ||||
bool operator()(std::int64_t value) { | |||||
return value <= std::numeric_limits<Fortran::runtime::CppTypeFor< | |||||
Fortran::common::TypeCategory::Integer, KIND>>::max(); | |||||
} | } | ||||
}; | |||||
std::int32_t RTNAME(GetCommand)(const Descriptor *value, | std::int32_t RTNAME(GetCommand)(const Descriptor *value, | ||||
const Descriptor *length, const Descriptor *errmsg, const char *sourceFile, | const Descriptor *length, const Descriptor *errmsg, const char *sourceFile, | ||||
int line) { | int line) { | ||||
Terminator terminator{sourceFile, line}; | Terminator terminator{sourceFile, line}; | ||||
auto storeLength = [&](std::int64_t value) { | |||||
auto typeCode{length->type().GetCategoryAndKind()}; | |||||
int kind{typeCode->second}; | |||||
Fortran::runtime::ApplyIntegerKind<Fortran::runtime::StoreIntegerAt, void>( | |||||
kind, terminator, *length, /* atIndex = */ 0, value); | |||||
}; | |||||
if (value) { | if (value) { | ||||
RUNTIME_CHECK(terminator, IsValidCharDescriptor(value)); | RUNTIME_CHECK(terminator, IsValidCharDescriptor(value)); | ||||
} | } | ||||
// Store 0 in case we error out later on. | // Store 0 in case we error out later on. | ||||
if (length) { | if (length) { | ||||
RUNTIME_CHECK(terminator, IsValidIntDescriptor(length)); | RUNTIME_CHECK(terminator, IsValidIntDescriptor(length)); | ||||
storeLength(0); | StoreLengthToDescriptor(length, 0, terminator); | ||||
} | } | ||||
auto shouldContinue = [&](std::int32_t stat) -> bool { | auto shouldContinue = [&](std::int32_t stat) -> bool { | ||||
// We continue as long as everything is ok OR the value descriptor is | // We continue as long as everything is ok OR the value descriptor is | ||||
// too short, but we still need to compute the length. | // too short, but we still need to compute the length. | ||||
return stat == StatOk || (length && stat == StatValueTooShort); | return stat == StatOk || (length && stat == StatValueTooShort); | ||||
}; | }; | ||||
Show All 19 Lines | for (std::int32_t i{1}; i < executionEnvironment.argc; ++i) { | ||||
stat = CheckAndCopyToDescriptor( | stat = CheckAndCopyToDescriptor( | ||||
value, executionEnvironment.argv[i], errmsg, offset); | value, executionEnvironment.argv[i], errmsg, offset); | ||||
if (!shouldContinue(stat)) { | if (!shouldContinue(stat)) { | ||||
return stat; | return stat; | ||||
} | } | ||||
} | } | ||||
auto fitsInLength = [&](std::int64_t value) -> bool { | if (length && FitsInDescriptor(length, offset, terminator)) { | ||||
auto typeCode{length->type().GetCategoryAndKind()}; | StoreLengthToDescriptor(length, offset, terminator); | ||||
int kind{typeCode->second}; | |||||
return Fortran::runtime::ApplyIntegerKind<FitsInIntegerKind, bool>( | |||||
kind, terminator, value); | |||||
}; | |||||
if (length && fitsInLength(offset)) { | |||||
storeLength(offset); | |||||
} | } | ||||
// value += spaces for padding | // value += spaces for padding | ||||
if (value) { | if (value) { | ||||
FillWithSpaces(*value, offset); | FillWithSpaces(*value, offset); | ||||
} | } | ||||
return stat; | return stat; | ||||
▲ Show 20 Lines • Show All 52 Lines • Show Last 20 Lines |