/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#include "cmDependsC.h"

#include <utility>

#include "cmsys/FStream.hxx"

#include "cmFileTime.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
#include "cmProperty.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"

#define INCLUDE_REGEX_LINE                                                    \
  "^[ \t]*[#%][ \t]*(include|import)[ \t]*[<\"]([^\">]+)([\">])"

#define INCLUDE_REGEX_LINE_MARKER "#IncludeRegexLine: "
#define INCLUDE_REGEX_SCAN_MARKER "#IncludeRegexScan: "
#define INCLUDE_REGEX_COMPLAIN_MARKER "#IncludeRegexComplain: "
#define INCLUDE_REGEX_TRANSFORM_MARKER "#IncludeRegexTransform: "

cmDependsC::cmDependsC() = default;

cmDependsC::cmDependsC(cmLocalUnixMakefileGenerator3* lg,
                       const std::string& targetDir, const std::string& lang,
                       const DependencyMap* validDeps)
  : cmDepends(lg, targetDir)
  , ValidDeps(validDeps)
{
  cmMakefile* mf = lg->GetMakefile();

  // Configure the include file search path.
  this->SetIncludePathFromLanguage(lang);

  // Configure regular expressions.
  std::string scanRegex = "^.*$";
  std::string complainRegex = "^$";
  {
    std::string scanRegexVar = cmStrCat("CMAKE_", lang, "_INCLUDE_REGEX_SCAN");
    if (cmProp sr = mf->GetDefinition(scanRegexVar)) {
      scanRegex = *sr;
    }
    std::string complainRegexVar =
      cmStrCat("CMAKE_", lang, "_INCLUDE_REGEX_COMPLAIN");
    if (cmProp cr = mf->GetDefinition(complainRegexVar)) {
      complainRegex = *cr;
    }
  }

  this->IncludeRegexLine.compile(INCLUDE_REGEX_LINE);
  this->IncludeRegexScan.compile(scanRegex);
  this->IncludeRegexComplain.compile(complainRegex);
  this->IncludeRegexLineString = INCLUDE_REGEX_LINE_MARKER INCLUDE_REGEX_LINE;
  this->IncludeRegexScanString =
    cmStrCat(INCLUDE_REGEX_SCAN_MARKER, scanRegex);
  this->IncludeRegexComplainString =
    cmStrCat(INCLUDE_REGEX_COMPLAIN_MARKER, complainRegex);

  this->SetupTransforms();

  this->CacheFileName =
    cmStrCat(this->TargetDirectory, '/', lang, ".includecache");

  this->ReadCacheFile();
}

cmDependsC::~cmDependsC()
{
  this->WriteCacheFile();
}

bool cmDependsC::WriteDependencies(const std::set<std::string>& sources,
                                   const std::string& obj,
                                   std::ostream& makeDepends,
                                   std::ostream& internalDepends)
{
  // Make sure this is a scanning instance.
  if (sources.empty() || sources.begin()->empty()) {
    cmSystemTools::Error("Cannot scan dependencies without a source file.");
    return false;
  }
  if (obj.empty()) {
    cmSystemTools::Error("Cannot scan dependencies without an object file.");
    return false;
  }

  std::set<std::string> dependencies;
  bool haveDeps = false;

  std::string binDir = this->LocalGenerator->GetBinaryDirectory();

  // Compute a path to the object file to write to the internal depend file.
  // Any existing content of the internal depend file has already been
  // loaded in ValidDeps with this path as a key.
  std::string obj_i =
    this->LocalGenerator->MaybeConvertToRelativePath(binDir, obj);

  if (this->ValidDeps != nullptr) {
    auto const tmpIt = this->ValidDeps->find(obj_i);
    if (tmpIt != this->ValidDeps->end()) {
      dependencies.insert(tmpIt->second.begin(), tmpIt->second.end());
      haveDeps = true;
    }
  }

  if (!haveDeps) {
    // Walk the dependency graph starting with the source file.
    int srcFiles = static_cast<int>(sources.size());
    this->Encountered.clear();

    for (std::string const& src : sources) {
      UnscannedEntry root;
      root.FileName = src;
      this->Unscanned.push(root);
      this->Encountered.insert(src);
    }

    std::set<std::string> scanned;
    while (!this->Unscanned.empty()) {
      // Get the next file to scan.
      UnscannedEntry current = this->Unscanned.front();
      this->Unscanned.pop();

      // If not a full path, find the file in the include path.
      std::string fullName;
      if ((srcFiles > 0) || cmSystemTools::FileIsFullPath(current.FileName)) {
        if (cmSystemTools::FileExists(current.FileName, true)) {
          fullName = current.FileName;
        }
      } else if (!current.QuotedLocation.empty() &&
                 cmSystemTools::FileExists(current.QuotedLocation, true)) {
        // The include statement producing this entry was a double-quote
        // include and the included file is present in the directory of
        // the source containing the include statement.
        fullName = current.QuotedLocation;
      } else {
        auto headerLocationIt =
          this->HeaderLocationCache.find(current.FileName);
        if (headerLocationIt != this->HeaderLocationCache.end()) {
          fullName = headerLocationIt->second;
        } else {
          for (std::string const& iPath : this->IncludePath) {
            // Construct the name of the file as if it were in the current
            // include directory.  Avoid using a leading "./".
            std::string tmpPath =
              cmSystemTools::CollapseFullPath(current.FileName, iPath);

            // Look for the file in this location.
            if (cmSystemTools::FileExists(tmpPath, true)) {
              fullName = tmpPath;
              this->HeaderLocationCache[current.FileName] = std::move(tmpPath);
              break;
            }
          }
        }
      }

      // Complain if the file cannot be found and matches the complain
      // regex.
      if (fullName.empty() &&
          this->IncludeRegexComplain.find(current.FileName)) {
        cmSystemTools::Error("Cannot find file \"" + current.FileName + "\".");
        return false;
      }

      // Scan the file if it was found and has not been scanned already.
      if (!fullName.empty() && (scanned.find(fullName) == scanned.end())) {
        // Record scanned files.
        scanned.insert(fullName);

        // Check whether this file is already in the cache
        auto fileIt = this->FileCache.find(fullName);
        if (fileIt != this->FileCache.end()) {
          fileIt->second.Used = true;
          dependencies.insert(fullName);
          for (UnscannedEntry const& inc : fileIt->second.UnscannedEntries) {
            if (this->Encountered.find(inc.FileName) ==
                this->Encountered.end()) {
              this->Encountered.insert(inc.FileName);
              this->Unscanned.push(inc);
            }
          }
        } else {

          // Try to scan the file.  Just leave it out if we cannot find
          // it.
          cmsys::ifstream fin(fullName.c_str());
          if (fin) {
            cmsys::FStream::BOM bom = cmsys::FStream::ReadBOM(fin);
            if (bom == cmsys::FStream::BOM_None ||
                bom == cmsys::FStream::BOM_UTF8) {
              // Add this file as a dependency.
              dependencies.insert(fullName);

              // Scan this file for new dependencies.  Pass the directory
              // containing the file to handle double-quote includes.
              std::string dir = cmSystemTools::GetFilenamePath(fullName);
              this->Scan(fin, dir, fullName);
            } else {
              // Skip file with encoding we do not implement.
            }
          }
        }
      }

      srcFiles--;
    }
  }

  // Write the dependencies to the output stream.  Makefile rules
  // written by the original local generator for this directory
  // convert the dependencies to paths relative to the home output
  // directory.  We must do the same here.
  std::string obj_m = this->LocalGenerator->ConvertToMakefilePath(obj_i);
  internalDepends << obj_i << '\n';

  for (std::string const& dep : dependencies) {
    makeDepends << obj_m << ": "
                << this->LocalGenerator->ConvertToMakefilePath(
                     this->LocalGenerator->MaybeConvertToRelativePath(binDir,
                                                                      dep))
                << '\n';
    internalDepends << ' ' << dep << '\n';
  }
  makeDepends << '\n';

  return true;
}

void cmDependsC::ReadCacheFile()
{
  if (this->CacheFileName.empty()) {
    return;
  }
  cmsys::ifstream fin(this->CacheFileName.c_str());
  if (!fin) {
    return;
  }

  std::string line;
  cmIncludeLines* cacheEntry = nullptr;
  bool haveFileName = false;

  cmFileTime cacheFileTime;
  bool const cacheFileTimeGood = cacheFileTime.Load(this->CacheFileName);
  while (cmSystemTools::GetLineFromStream(fin, line)) {
    if (line.empty()) {
      cacheEntry = nullptr;
      haveFileName = false;
      continue;
    }
    // the first line after an empty line is the name of the parsed file
    if (!haveFileName) {
      haveFileName = true;

      cmFileTime fileTime;
      bool const res = cacheFileTimeGood && fileTime.Load(line);
      bool const newer = res && cacheFileTime.Newer(fileTime);

      if (res && newer) // cache is newer than the parsed file
      {
        cacheEntry = &this->FileCache[line];
      }
      // file doesn't exist, check that the regular expressions
      // haven't changed
      else if (!res) {
        if (cmHasLiteralPrefix(line, INCLUDE_REGEX_LINE_MARKER)) {
          if (line != this->IncludeRegexLineString) {
            return;
          }
        } else if (cmHasLiteralPrefix(line, INCLUDE_REGEX_SCAN_MARKER)) {
          if (line != this->IncludeRegexScanString) {
            return;
          }
        } else if (cmHasLiteralPrefix(line, INCLUDE_REGEX_COMPLAIN_MARKER)) {
          if (line != this->IncludeRegexComplainString) {
            return;
          }
        } else if (cmHasLiteralPrefix(line, INCLUDE_REGEX_TRANSFORM_MARKER)) {
          if (line != this->IncludeRegexTransformString) {
            return;
          }
        }
      }
    } else if (cacheEntry != nullptr) {
      UnscannedEntry entry;
      entry.FileName = line;
      if (cmSystemTools::GetLineFromStream(fin, line)) {
        if (line != "-") {
          entry.QuotedLocation = line;
        }
        cacheEntry->UnscannedEntries.push_back(std::move(entry));
      }
    }
  }
}

void cmDependsC::WriteCacheFile() const
{
  if (this->CacheFileName.empty()) {
    return;
  }
  cmsys::ofstream cacheOut(this->CacheFileName.c_str());
  if (!cacheOut) {
    return;
  }

  cacheOut << this->IncludeRegexLineString << "\n\n";
  cacheOut << this->IncludeRegexScanString << "\n\n";
  cacheOut << this->IncludeRegexComplainString << "\n\n";
  cacheOut << this->IncludeRegexTransformString << "\n\n";

  for (auto const& fileIt : this->FileCache) {
    if (fileIt.second.Used) {
      cacheOut << fileIt.first << '\n';

      for (UnscannedEntry const& inc : fileIt.second.UnscannedEntries) {
        cacheOut << inc.FileName << '\n';
        if (inc.QuotedLocation.empty()) {
          cacheOut << '-' << '\n';
        } else {
          cacheOut << inc.QuotedLocation << '\n';
        }
      }
      cacheOut << '\n';
    }
  }
}

void cmDependsC::Scan(std::istream& is, const std::string& directory,
                      const std::string& fullName)
{
  cmIncludeLines& newCacheEntry = this->FileCache[fullName];
  newCacheEntry.Used = true;

  // Read one line at a time.
  std::string line;
  while (cmSystemTools::GetLineFromStream(is, line)) {
    // Transform the line content first.
    if (!this->TransformRules.empty()) {
      this->TransformLine(line);
    }

    // Match include directives.
    if (this->IncludeRegexLine.find(line)) {
      // Get the file being included.
      UnscannedEntry entry;
      entry.FileName = this->IncludeRegexLine.match(2);
      cmSystemTools::ConvertToUnixSlashes(entry.FileName);
      if (this->IncludeRegexLine.match(3) == "\"" &&
          !cmSystemTools::FileIsFullPath(entry.FileName)) {
        // This was a double-quoted include with a relative path.  We
        // must check for the file in the directory containing the
        // file we are scanning.
        entry.QuotedLocation =
          cmSystemTools::CollapseFullPath(entry.FileName, directory);
      }

      // Queue the file if it has not yet been encountered and it
      // matches the regular expression for recursive scanning.  Note
      // that this check does not account for the possibility of two
      // headers with the same name in different directories when one
      // is included by double-quotes and the other by angle brackets.
      // It also does not work properly if two header files with the same
      // name exist in different directories, and both are included from a
      // file their own directory by simply using "filename.h" (#12619)
      // This kind of problem will be fixed when a more
      // preprocessor-like implementation of this scanner is created.
      if (this->IncludeRegexScan.find(entry.FileName)) {
        newCacheEntry.UnscannedEntries.push_back(entry);
        if (this->Encountered.find(entry.FileName) ==
            this->Encountered.end()) {
          this->Encountered.insert(entry.FileName);
          this->Unscanned.push(entry);
        }
      }
    }
  }
}

void cmDependsC::SetupTransforms()
{
  // Get the transformation rules.
  std::vector<std::string> transformRules;
  cmMakefile* mf = this->LocalGenerator->GetMakefile();
  mf->GetDefExpandList("CMAKE_INCLUDE_TRANSFORMS", transformRules, true);
  for (std::string const& tr : transformRules) {
    this->ParseTransform(tr);
  }

  this->IncludeRegexTransformString = INCLUDE_REGEX_TRANSFORM_MARKER;
  if (!this->TransformRules.empty()) {
    // Construct the regular expression to match lines to be
    // transformed.
    std::string xform = "^([ \t]*[#%][ \t]*(include|import)[ \t]*)(";
    const char* sep = "";
    for (auto const& tr : this->TransformRules) {
      xform += sep;
      xform += tr.first;
      sep = "|";
    }
    xform += ")[ \t]*\\(([^),]*)\\)";
    this->IncludeRegexTransform.compile(xform);

    // Build a string that encodes all transformation rules and will
    // change when rules are changed.
    this->IncludeRegexTransformString += xform;
    for (auto const& tr : this->TransformRules) {
      this->IncludeRegexTransformString += " ";
      this->IncludeRegexTransformString += tr.first;
      this->IncludeRegexTransformString += "(%)=";
      this->IncludeRegexTransformString += tr.second;
    }
  }
}

void cmDependsC::ParseTransform(std::string const& xform)
{
  // A transform rule is of the form SOME_MACRO(%)=value-with-%
  // We can simply separate with "(%)=".
  std::string::size_type pos = xform.find("(%)=");
  if (pos == std::string::npos || pos == 0) {
    return;
  }
  std::string name = xform.substr(0, pos);
  std::string value = xform.substr(pos + 4);
  this->TransformRules[name] = value;
}

void cmDependsC::TransformLine(std::string& line)
{
  // Check for a transform rule match.  Return if none.
  if (!this->IncludeRegexTransform.find(line)) {
    return;
  }
  auto tri = this->TransformRules.find(this->IncludeRegexTransform.match(3));
  if (tri == this->TransformRules.end()) {
    return;
  }

  // Construct the transformed line.
  std::string newline = this->IncludeRegexTransform.match(1);
  std::string arg = this->IncludeRegexTransform.match(4);
  for (char c : tri->second) {
    if (c == '%') {
      newline += arg;
    } else {
      newline += c;
    }
  }

  // Return the transformed line.
  line = newline;
}
