1 //===-- runtime/environment.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 "environment.h"
10 #include "memory.h"
11 #include "tools.h"
12 #include <cstdio>
13 #include <cstdlib>
14 #include <cstring>
15 #include <limits>
16
17 namespace Fortran::runtime {
18
19 ExecutionEnvironment executionEnvironment;
20
GetConvertFromString(const char * x,std::size_t n)21 std::optional<Convert> GetConvertFromString(const char *x, std::size_t n) {
22 static const char *keywords[]{
23 "UNKNOWN", "NATIVE", "LITTLE_ENDIAN", "BIG_ENDIAN", "SWAP", nullptr};
24 switch (IdentifyValue(x, n, keywords)) {
25 case 0:
26 return Convert::Unknown;
27 case 1:
28 return Convert::Native;
29 case 2:
30 return Convert::LittleEndian;
31 case 3:
32 return Convert::BigEndian;
33 case 4:
34 return Convert::Swap;
35 default:
36 return std::nullopt;
37 }
38 }
39
Configure(int ac,const char * av[],const char * env[])40 void ExecutionEnvironment::Configure(
41 int ac, const char *av[], const char *env[]) {
42 argc = ac;
43 argv = av;
44 envp = env;
45 listDirectedOutputLineLengthLimit = 79; // PGI default
46 defaultOutputRoundingMode =
47 decimal::FortranRounding::RoundNearest; // RP(==RN)
48 conversion = Convert::Unknown;
49
50 if (auto *x{std::getenv("FORT_FMT_RECL")}) {
51 char *end;
52 auto n{std::strtol(x, &end, 10)};
53 if (n > 0 && n < std::numeric_limits<int>::max() && *end == '\0') {
54 listDirectedOutputLineLengthLimit = n;
55 } else {
56 std::fprintf(
57 stderr, "Fortran runtime: FORT_FMT_RECL=%s is invalid; ignored\n", x);
58 }
59 }
60
61 if (auto *x{std::getenv("FORT_CONVERT")}) {
62 if (auto convert{GetConvertFromString(x, std::strlen(x))}) {
63 conversion = *convert;
64 } else {
65 std::fprintf(
66 stderr, "Fortran runtime: FORT_CONVERT=%s is invalid; ignored\n", x);
67 }
68 }
69
70 if (auto *x{std::getenv("NO_STOP_MESSAGE")}) {
71 char *end;
72 auto n{std::strtol(x, &end, 10)};
73 if (n >= 0 && n <= 1 && *end == '\0') {
74 noStopMessage = n != 0;
75 } else {
76 std::fprintf(stderr,
77 "Fortran runtime: NO_STOP_MESSAGE=%s is invalid; ignored\n", x);
78 }
79 }
80
81 if (auto *x{std::getenv("DEFAULT_UTF8")}) {
82 char *end;
83 auto n{std::strtol(x, &end, 10)};
84 if (n >= 0 && n <= 1 && *end == '\0') {
85 defaultUTF8 = n != 0;
86 } else {
87 std::fprintf(
88 stderr, "Fortran runtime: DEFAULT_UTF8=%s is invalid; ignored\n", x);
89 }
90 }
91
92 // TODO: Set RP/ROUND='PROCESSOR_DEFINED' from environment
93 }
94
GetEnv(const char * name,std::size_t name_length,const Terminator & terminator)95 const char *ExecutionEnvironment::GetEnv(
96 const char *name, std::size_t name_length, const Terminator &terminator) {
97 RUNTIME_CHECK(terminator, name && name_length);
98
99 OwningPtr<char> cStyleName{
100 SaveDefaultCharacter(name, name_length, terminator)};
101 RUNTIME_CHECK(terminator, cStyleName);
102
103 return std::getenv(cStyleName.get());
104 }
105 } // namespace Fortran::runtime
106