[flang-commits] [flang] fc2ba5e - [flang] Implement GET_ENVIRONMENT_VARIABLE(LENGTH)
Diana Picus via flang-commits
flang-commits at lists.llvm.org
Wed Oct 13 01:45:47 PDT 2021
Author: Diana Picus
Date: 2021-10-13T08:42:03Z
New Revision: fc2ba5e53d47a07f505ddee2441b3768e446624c
URL: https://github.com/llvm/llvm-project/commit/fc2ba5e53d47a07f505ddee2441b3768e446624c
DIFF: https://github.com/llvm/llvm-project/commit/fc2ba5e53d47a07f505ddee2441b3768e446624c.diff
LOG: [flang] Implement GET_ENVIRONMENT_VARIABLE(LENGTH)
Search for the environment variable in the envp string passed to
ProgramStart. This doesn't work if the main program isn't Fortran.
Differential Revision: https://reviews.llvm.org/D111394
Added:
Modified:
flang/runtime/command.cpp
flang/runtime/environment.cpp
flang/runtime/environment.h
flang/unittests/Runtime/CommandTest.cpp
Removed:
################################################################################
diff --git a/flang/runtime/command.cpp b/flang/runtime/command.cpp
index 5fc2d28305ffb..81daf64b6b7e7 100644
--- a/flang/runtime/command.cpp
+++ b/flang/runtime/command.cpp
@@ -10,6 +10,7 @@
#include "environment.h"
#include "stat.h"
#include "flang/Runtime/descriptor.h"
+#include <cstdlib>
#include <limits>
namespace Fortran::runtime {
@@ -79,4 +80,27 @@ std::int32_t RTNAME(ArgumentValue)(
return StatOk;
}
+
+static std::size_t LengthWithoutTrailingSpaces(const Descriptor &d) {
+ std::size_t s{d.ElementBytes() - 1};
+ while (*d.OffsetElement(s) == ' ') {
+ --s;
+ }
+ return s + 1;
+}
+
+std::int64_t RTNAME(EnvVariableLength)(const Descriptor &name, bool trim_name) {
+ std::size_t nameLength{
+ trim_name ? LengthWithoutTrailingSpaces(name) : name.ElementBytes()};
+ if (nameLength == 0) {
+ return 0;
+ }
+
+ const char *value{
+ executionEnvironment.GetEnv(name.OffsetElement(), nameLength)};
+ if (!value) {
+ return 0;
+ }
+ return std::strlen(value);
+}
} // namespace Fortran::runtime
diff --git a/flang/runtime/environment.cpp b/flang/runtime/environment.cpp
index badcbbca562f0..2ba8faf6882ce 100644
--- a/flang/runtime/environment.cpp
+++ b/flang/runtime/environment.cpp
@@ -68,4 +68,28 @@ void ExecutionEnvironment::Configure(
// TODO: Set RP/ROUND='PROCESSOR_DEFINED' from environment
}
+
+const char *ExecutionEnvironment::GetEnv(
+ const char *name, std::size_t name_length) {
+ if (!envp) {
+ // TODO: Ask std::getenv.
+ return nullptr;
+ }
+
+ // envp is an array of strings of the form "name=value".
+ for (const char **var{envp}; *var != nullptr; ++var) {
+ const char *eq{std::strchr(*var, '=')};
+ if (!eq) {
+ // Found a malformed environment string, just ignore it.
+ continue;
+ }
+ if (static_cast<std::size_t>(eq - *var) != name_length) {
+ continue;
+ }
+ if (std::memcmp(*var, name, name_length) == 0) {
+ return eq + 1;
+ }
+ }
+ return nullptr;
+}
} // namespace Fortran::runtime
diff --git a/flang/runtime/environment.h b/flang/runtime/environment.h
index 5e6b7b85b7272..1d04cb110b378 100644
--- a/flang/runtime/environment.h
+++ b/flang/runtime/environment.h
@@ -29,6 +29,7 @@ std::optional<Convert> GetConvertFromString(const char *, std::size_t);
struct ExecutionEnvironment {
void Configure(int argc, const char *argv[], const char *envp[]);
+ const char *GetEnv(const char *name, std::size_t name_length);
int argc;
const char **argv;
diff --git a/flang/unittests/Runtime/CommandTest.cpp b/flang/unittests/Runtime/CommandTest.cpp
index a13addd75a214..194860f8797a7 100644
--- a/flang/unittests/Runtime/CommandTest.cpp
+++ b/flang/unittests/Runtime/CommandTest.cpp
@@ -24,12 +24,25 @@ static OwningPtr<Descriptor> CreateEmptyCharDescriptor() {
return descriptor;
}
+static OwningPtr<Descriptor> CharDescriptor(const char *value) {
+ std::size_t n{std::strlen(value)};
+ OwningPtr<Descriptor> descriptor{Descriptor::Create(
+ sizeof(char), n, nullptr, 0, nullptr, CFI_attribute_allocatable)};
+ if (descriptor->Allocate() != 0) {
+ return nullptr;
+ }
+ std::memcpy(descriptor->OffsetElement(), value, n);
+ return descriptor;
+}
+
class CommandFixture : public ::testing::Test {
protected:
CommandFixture(int argc, const char *argv[]) {
RTNAME(ProgramStart)(argc, argv, {});
}
+ CommandFixture(const char *envp[]) { RTNAME(ProgramStart)(0, nullptr, envp); }
+
std::string GetPaddedStr(const char *text, std::size_t len) const {
std::string res{text};
assert(res.length() <= len && "No room to pad");
@@ -175,3 +188,20 @@ TEST_F(SeveralArguments, ErrMsgTooShort) {
EXPECT_GT(RTNAME(ArgumentValue)(-1, nullptr, errMsg.get()), 0);
CheckDescriptorEqStr(errMsg.get(), "Inv");
}
+
+static const char *env[]{"NAME=value", nullptr};
+class EnvironmentVariables : public CommandFixture {
+protected:
+ EnvironmentVariables() : CommandFixture(env) {}
+};
+
+TEST_F(EnvironmentVariables, Length) {
+ EXPECT_EQ(5, RTNAME(EnvVariableLength)(*CharDescriptor("NAME")));
+ EXPECT_EQ(0, RTNAME(EnvVariableLength)(*CharDescriptor("DOESNT_EXIST")));
+
+ EXPECT_EQ(5, RTNAME(EnvVariableLength)(*CharDescriptor("NAME ")));
+ EXPECT_EQ(0,
+ RTNAME(EnvVariableLength)(*CharDescriptor("NAME "), /*trim_name=*/false));
+
+ EXPECT_EQ(0, RTNAME(EnvVariableLength)(*CharDescriptor(" ")));
+}
More information about the flang-commits
mailing list