/* 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 "cmsys/FStream.hxx"
#include <utility>

#include "cmAlgorithms.h"
#include "cmFileTimeComparison.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.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()
  : ValidDeps(nullptr)
{
}

cmDependsC::cmDependsC(
  cmLocalGenerator* lg, const char* targetDir, const std::string& lang,
  const std::map<std::string, DependencyVector>* 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 = "CMAKE_";
    scanRegexVar += lang;
    scanRegexVar += "_INCLUDE_REGEX_SCAN";
    if (const char* sr = mf->GetDefinition(scanRegexVar)) {
      scanRegex = sr;
    }
    std::string complainRegexVar = "CMAKE_";
    complainRegexVar += lang;
    complainRegexVar += "_INCLUDE_REGEX_COMPLAIN";
    if (const char* cr = mf->GetDefinition(complainRegexVar)) {
      complainRegex = cr;
    }
  }

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

  this->SetupTransforms();

  this->CacheFileName = this->TargetDirectory;
  this->CacheFileName += "/";
  this->CacheFileName += lang;
  this->CacheFileName += ".includecache";

  this->ReadCacheFile();
}

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

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->ConvertToRelativePath(binDir, obj);

  if (this->ValidDeps != nullptr) {
    std::map<std::string, DependencyVector>::const_iterator 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;

    // Use reserve to allocate enough memory for tempPathStr
    // so that during the loops no memory is allocated or freed
    std::string tempPathStr;
    tempPathStr.reserve(4 * 1024);

    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 {
        std::map<std::string, std::string>::iterator headerLocationIt =
          this->HeaderLocationCache.find(current.FileName);
        if (headerLocationIt != this->HeaderLocationCache.end()) {
          fullName = headerLocationIt->second;
        } else {
          for (std::string const& i : this->IncludePath) {
            // Construct the name of the file as if it were in the current
            // include directory.  Avoid using a leading "./".

            tempPathStr =
              cmSystemTools::CollapseCombinedPath(i, current.FileName);

            // Look for the file in this location.
            if (cmSystemTools::FileExists(tempPathStr, true)) {
              fullName = tempPathStr;
              HeaderLocationCache[current.FileName] = fullName;
              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.c_str(),
                             "\".");
        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
        std::map<std::string, cmIncludeLines*>::iterator 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.c_str(), 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 = cmSystemTools::ConvertToOutputPath(obj_i);
  internalDepends << obj_i << std::endl;

  for (std::string const& dep : dependencies) {
    makeDepends << obj_m << ": "
                << cmSystemTools::ConvertToOutputPath(
                     this->LocalGenerator->ConvertToRelativePath(binDir, dep))
                << std::endl;
    internalDepends << " " << dep << std::endl;
  }
  makeDepends << std::endl;

  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;

  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;
      int newer = 0;
      cmFileTimeComparison comp;
      bool res = comp.FileTimeCompare(this->CacheFileName.c_str(),
                                      line.c_str(), &newer);

      if (res && newer == 1) // cache is newer than the parsed file
      {
        cacheEntry = new cmIncludeLines;
        this->FileCache[line] = cacheEntry;
      }
      // file doesn't exist, check that the regular expressions
      // haven't changed
      else if (!res) {
        if (line.find(INCLUDE_REGEX_LINE_MARKER) == 0) {
          if (line != this->IncludeRegexLineString) {
            return;
          }
        } else if (line.find(INCLUDE_REGEX_SCAN_MARKER) == 0) {
          if (line != this->IncludeRegexScanString) {
            return;
          }
        } else if (line.find(INCLUDE_REGEX_COMPLAIN_MARKER) == 0) {
          if (line != this->IncludeRegexComplainString) {
            return;
          }
        } else if (line.find(INCLUDE_REGEX_TRANSFORM_MARKER) == 0) {
          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 << std::endl;

      for (UnscannedEntry const& inc : fileIt.second->UnscannedEntries) {
        cacheOut << inc.FileName << std::endl;
        if (inc.QuotedLocation.empty()) {
          cacheOut << "-" << std::endl;
        } else {
          cacheOut << inc.QuotedLocation << std::endl;
        }
      }
      cacheOut << std::endl;
    }
  }
}

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

  // 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::CollapseCombinedPath(directory, entry.FileName);
      }

      // 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();
  if (const char* xform = mf->GetDefinition("CMAKE_INCLUDE_TRANSFORMS")) {
    cmSystemTools::ExpandListArgument(xform, 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.c_str());

    // 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;
  }
  TransformRulesType::const_iterator 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 (const char* c = tri->second.c_str(); *c; ++c) {
    if (*c == '%') {
      newline += arg;
    } else {
      newline += *c;
    }
  }

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