// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#ifndef RUNTIME_BIN_PLATFORM_H_
#define RUNTIME_BIN_PLATFORM_H_

#include "bin/builtin.h"

#include "platform/atomic.h"
#include "platform/globals.h"
#include "platform/utils.h"

#if defined(DART_HOST_OS_MACOS)
#include "bin/platform_macos.h"
#endif  // defined(DART_HOST_OS_MACOS)

namespace dart {
namespace bin {

class Platform {
 public:
  // Perform platform specific initialization.
  static bool Initialize();

  // Returns the number of processors on the machine.
  static int NumberOfProcessors();

  // Returns a string representing the operating system ("linux",
  // "macos", "windows", or "android"). The returned string should not be
  // deallocated by the caller.
  static const char* OperatingSystem();

  // Returns a string representing the version of the operating system. The
  // format of the string is determined by the platform. The returned string
  // should not be deallocated by the caller.
  static const char* OperatingSystemVersion();

  // Returns the architecture name of the processor the VM is running on
  // (ia32, x64, arm, or arm64).
  static const char* HostArchitecture() {
#if defined(HOST_ARCH_ARM)
    return "arm";
#elif defined(HOST_ARCH_ARM64)
    return "arm64";
#elif defined(HOST_ARCH_IA32)
    return "ia32";
#elif defined(HOST_ARCH_X64)
    return "x64";
#elif defined(HOST_ARCH_RISCV32)
    return "riscv32";
#elif defined(HOST_ARCH_RISCV64)
    return "riscv64";
#else
#error Architecture detection failed.
#endif
  }

  static const char* LibraryPrefix();

  // Returns a string representing the operating system's shared library
  // extension (e.g. 'so', 'dll', ...). The returned string should not be
  // deallocated by the caller.
  static const char* LibraryExtension();

  // Extracts the local hostname.
  static bool LocalHostname(char* buffer, intptr_t buffer_length);

  static const char* LocaleName();

  // Extracts the environment variables for the current process.  The array of
  // strings is Dart_ScopeAllocated. The number of elements in the array is
  // returned in the count argument.
  static char** Environment(intptr_t* count);

  static const char* ResolveExecutablePath();

  // This has the same effect as calling ResolveExecutablePath except that
  // Dart_ScopeAllocate is not called and that the result goes into the given
  // parameters.
  // WARNING: On Fuchsia it returns -1, i.e. doesn't work.
  // Note that `result` should be pre-allocated with size `result_size`.
  // The return-value is the length read into `result` or -1 on failure.
  static intptr_t ResolveExecutablePathInto(char* result, size_t result_size);

  // Stores the executable name.
  static void SetExecutableName(const char* executable_name) {
    executable_name_ = executable_name;
  }
  static const char* GetExecutableName();
  static const char* GetResolvedExecutableName() {
    if (resolved_executable_name_.load() == nullptr) {
      // Try to resolve the executable path using platform specific APIs.
      const char* resolved_name = Platform::ResolveExecutablePath();
      if (resolved_name != nullptr) {
        char* resolved_name_copy = Utils::StrDup(resolved_name);
        const char* expect_old_is_null = nullptr;
        if (!resolved_executable_name_.compare_exchange_strong(
                expect_old_is_null, resolved_name_copy)) {
          free(resolved_name_copy);
        }
      }
    }
    return resolved_executable_name_.load();
  }

  // Stores and gets the flags passed to the executable.
  static void SetExecutableArguments(int script_index, char** argv) {
    script_index_ = script_index;
    argv_ = argv;
  }
  static int GetScriptIndex() { return script_index_; }
  static char** GetArgv() { return argv_; }

  static void SetProcessName(const char* name);

  DART_NORETURN static void Exit(int exit_code);

  static void SetCoreDumpResourceLimit(int value);

 private:
  // The path to the executable.
  static const char* executable_name_;

  // The path to the resolved executable.
  //
  // We use require-release semantics to ensure initializing stores to the
  // string are visible when the string becomes visible.
  static AcqRelAtomic<const char*> resolved_executable_name_;

  static int script_index_;
  static char** argv_;  // VM flags are argv_[1 ... script_index_ - 1]

  DISALLOW_ALLOCATION();
  DISALLOW_IMPLICIT_CONSTRUCTORS(Platform);
};

}  // namespace bin
}  // namespace dart

#endif  // RUNTIME_BIN_PLATFORM_H_
