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 
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 
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   // TODO: Set RP/ROUND='PROCESSOR_DEFINED' from environment
71 }
72 
73 const char *ExecutionEnvironment::GetEnv(
74     const char *name, std::size_t name_length, const Terminator &terminator) {
75   RUNTIME_CHECK(terminator, name && name_length);
76 
77   OwningPtr<char> cStyleName{
78       SaveDefaultCharacter(name, name_length, terminator)};
79   RUNTIME_CHECK(terminator, cStyleName);
80 
81   return std::getenv(cStyleName.get());
82 }
83 } // namespace Fortran::runtime
84