//===-- GccUtils.cpp ------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Gcc installation detector and related code.
//
//===----------------------------------------------------------------------===//

#include <sstream>

#include "GccUtils.h"

#include "llvm/Support/FileSystem.h"

namespace gnutools {

namespace gccdetect {

stringvec InspectRealFS::scanDir(const std::string &dir)
{
  stringvec result;
  std::error_code ec;
  llvm::sys::fs::directory_iterator dend, dit(dir, ec);
  if (ec)
    return stringvec();
  while (dit != dend) {
    result.push_back(dit->path());
    dit.increment(ec);
    if (ec)
      return stringvec();
  }
  return result;
}

bool InspectRealFS::is_directory(const std::string &path)
{
  return llvm::sys::fs::is_directory(path);
}

bool InspectRealFS::exists(const std::string &path)
{
  return llvm::sys::fs::exists(path);
}

//........................................................................

GCCVersion::GCCVersion()
    : maj_(-1), min_(-1)
{
}

// Break up a string into (up to) three chunks/tokens based on a specific
// delimitor.

static llvm::SmallVector<std::string, 4> tokenize3(const std::string &s,
                                                  char delim)
{
  llvm::SmallVector<std::string, 4> result;
  size_t cur;
  size_t nxt = -1;
  for (unsigned chunks = 0; chunks < 2; ++ chunks) {
    cur = nxt + 1;
    nxt = s.find_first_of(delim, cur);
    size_t rem = (nxt == std::string::npos ? nxt : nxt - cur);
    result.push_back(s.substr(cur, rem));
    if (nxt == std::string::npos)
      break;
  }
  if (nxt != std::string::npos)
    result.push_back(s.substr(nxt+1, std::string::npos));
  return result;
}

GCCVersion GCCVersion::parse(llvm::StringRef vtext)
{
  const GCCVersion bad;
  GCCVersion result;
  std::string vts(vtext.str());
  auto tokens = tokenize3(vts, '.');

  // Major version.
  if (tokens.empty() ||
      llvm::StringRef(tokens[0]).getAsInteger(10, result.maj_) ||
      result.maj_ < 4)
    return bad;
  result.text_ = vtext;
  if (tokens.size() == 1)
    return result;

  // Minor version
  if (llvm::StringRef(tokens[1]).getAsInteger(10, result.min_) ||
      result.min_ < 0)
    return bad;
  if (tokens.size() == 2)
    return result;

  // Store away remainder (patch or equivalent).
  result.remainder_ = tokens[2];
  return result;
}

bool GCCVersion::operator<(const GCCVersion &rhs) const
{
  if (maj_ != rhs.maj_)
    return maj_ < rhs.maj_;
  if (min_ != rhs.min_)
    return min_ < rhs.min_;
  return remainder_.compare(rhs.remainder_) < 0;
}

std::string GCCVersion::toString() const
{
  std::stringstream ss;
  ss << "maj=" << maj_ << " min=" << min_ << " rem=" << remainder_;
  return ss.str();
}

//........................................................................

GCCInstallationDetector::
GCCInstallationDetector(const llvm::Triple &targetTriple,
                        const std::string &gccToolchainDir,
                        const std::string &sysroot,
                        InspectFS &inspector)
    : triple_(targetTriple),
      gccToolchainDir_(gccToolchainDir),
      sysroot_(sysroot),
      inspector_(inspector),
      version_(new GCCVersion())
{
}

struct GCCInstallationDetector::state {
  // requested triple
  llvm::Triple triple;
  // list of triple aliases to use when searching
  std::vector<std::string> tripleAliases;
  // libdirs to look for within prefix dir
  stringvec libdirs;
  // biarch suffixes (or empty string)
  std::vector<std::string> suffixes;
  // best version so far
  GCCVersion version;
  // path to best verison
  std::string candidate;
  // found suffix
  std::string suffix;
  // found triple
  llvm::Triple candTriple;
};

bool GCCInstallationDetector::selectLibDirs(state &s)
{
  // TODO: add more cases as additional architectures brought on.

  switch (triple_.getArch()) {
    case llvm::Triple::x86:
    case llvm::Triple::x86_64:
      s.tripleAliases = {
        triple_.str(),
        "x86_64-linux-gnu",       "x86_64-unknown-linux-gnu",
        "x86_64-pc-linux-gnu",    "x86_64-redhat-linux6E",
        "x86_64-redhat-linux",    "x86_64-suse-linux"
      };
      s.libdirs.push_back("lib");
      s.libdirs.push_back("lib64");
      if (triple_.getArch() == llvm::Triple::x86) {
        s.triple.setTriple(triple_.get64BitArchVariant().str());
        s.suffixes = {"/32", "/lib32"};
      } else {
        s.triple.setTriple(triple_.str());
        s.suffixes = {""};
      }
      break;
    default:
      llvm::errs() << "error: unsupported triple "
                   << triple_.str() << " in " << __FUNCTION__ << "\n";
      assert(false);
      return false;
  }
  return true;
}

// From comments in Clang it appears that there are some Linux systems
// that do not use crtbegin.o; if need be this could be switched to libgcc.a.

bool GCCInstallationDetector::validCandidate(const std::string &cand,
                                             const std::string &suffix)
{
  // is there an actual installation?
  std::stringstream ss;
  ss << cand << suffix << "/crtbegin.o";
  std::string crtb = ss.str();
  if (!inspector_.exists(crtb))
    return false;
  return true;
}

void GCCInstallationDetector::scanCandidate(state &s,
                                            const std::string &cand,
                                            const std::string &alias,
                                            const std::string &suffix)
{
  stringvec dirents = inspector_.scanDir(cand);
  for (auto &ent : dirents) {
    std::size_t pos = ent.find_last_of('/');
    assert(pos != std::string::npos);
    std::string base(ent.substr(pos+1));
    // gcc version valid?
    GCCVersion v = GCCVersion::parse(base);
    if (!v.valid())
      continue;
    if (!validCandidate(ent, suffix))
      continue;
    // more recent than previously found version?
    if (s.version < v) {
      s.version = v;
      s.candidate = ent;
      s.suffix = suffix;
      s.candTriple.setTriple(alias);
    }
  }
}

void GCCInstallationDetector::scanPrefix(state &s, const std::string &pref)
{
  for (auto &lib : s.libdirs) {
    // Form candidate dir
    for (auto &tripleAlias : s.tripleAliases) {
      std::stringstream ss;
      ss << pref << "/" << lib << "/gcc/" << tripleAlias;
      for (auto &suffix : s.suffixes)
        scanCandidate(s, ss.str(), tripleAlias, suffix);
    }
  }
}

void GCCInstallationDetector::init()
{
  state s;

  // Setup
  if (!selectLibDirs(s))
    return;

  if (!gccToolchainDir_.empty())
    scanPrefix(s, gccToolchainDir_);

  if (!s.version.valid() && !sysroot_.empty()) {
    // If sysroot is non-empty, then perform a search there first.
    std::string srp(sysroot_);
    srp += "/usr";
    scanPrefix(s, srp);
  }

  // If we found something viable in the sysroot, then don't look any
  // farther (this differs from clang AFAICT). The intent here is that
  // if the sysroot provides GCC X but the system has GCC X+1, we
  // still want to use the version in the sysroot.
  if (!s.version.valid()) {
    // Examine the host system.
    scanPrefix(s, "/usr");
  }

  // Incorporate results.
  if (s.version.valid()) {
    *version_ = s.version;
    foundTriple_.setTriple(s.candTriple.str());
    installPath_ = s.candidate;
    libPath_ = s.candidate;
    libPath_ += s.suffix;
    parentLibPath_ = installPath_ + "/../.." +
        (s.suffix.empty() ? "" : "/..");
  }
}

std::string GCCInstallationDetector::toString()
{
  std::stringstream ss;
  ss << "version: " << version_->text() << "\n";
  ss << "foundTriple: " << foundTriple_.str() << "\n";
  ss << "libPath: " << libPath_ << "\n";
  ss << "parentLibPath: " << parentLibPath_ << "\n";
  ss << "installPath: " << installPath_ << "\n";
  return ss.str();
}

} // end namespace gccdetect

} // end namespace gnutools
