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

#include <cassert>
#include <memory>
#include <sstream>
#include <utility>

#include "cmListFileLexer.h"
#include "cmMessageType.h"
#include "cmMessenger.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"

struct cmListFileParser
{
  cmListFileParser(cmListFile* lf, cmListFileBacktrace lfbt,
                   cmMessenger* messenger);
  ~cmListFileParser();
  cmListFileParser(const cmListFileParser&) = delete;
  cmListFileParser& operator=(const cmListFileParser&) = delete;
  void IssueFileOpenError(std::string const& text) const;
  void IssueError(std::string const& text) const;
  bool ParseFile(const char* filename);
  bool ParseString(const char* str, const char* virtual_filename);
  bool Parse();
  bool ParseFunction(const char* name, long line);
  bool AddArgument(cmListFileLexer_Token* token,
                   cmListFileArgument::Delimiter delim);
  cmListFile* ListFile;
  cmListFileBacktrace Backtrace;
  cmMessenger* Messenger;
  const char* FileName;
  cmListFileLexer* Lexer;
  std::string FunctionName;
  long FunctionLine;
  std::vector<cmListFileArgument> FunctionArguments;
  enum
  {
    SeparationOkay,
    SeparationWarning,
    SeparationError
  } Separation;
};

cmListFileParser::cmListFileParser(cmListFile* lf, cmListFileBacktrace lfbt,
                                   cmMessenger* messenger)
  : ListFile(lf)
  , Backtrace(std::move(lfbt))
  , Messenger(messenger)
  , FileName(nullptr)
  , Lexer(cmListFileLexer_New())
{
}

cmListFileParser::~cmListFileParser()
{
  cmListFileLexer_Delete(this->Lexer);
}

void cmListFileParser::IssueFileOpenError(const std::string& text) const
{
  this->Messenger->IssueMessage(MessageType::FATAL_ERROR, text,
                                this->Backtrace);
}

void cmListFileParser::IssueError(const std::string& text) const
{
  cmListFileContext lfc;
  lfc.FilePath = this->FileName;
  lfc.Line = cmListFileLexer_GetCurrentLine(this->Lexer);
  cmListFileBacktrace lfbt = this->Backtrace;
  lfbt = lfbt.Push(lfc);
  this->Messenger->IssueMessage(MessageType::FATAL_ERROR, text, lfbt);
  cmSystemTools::SetFatalErrorOccured();
}

bool cmListFileParser::ParseFile(const char* filename)
{
  this->FileName = filename;

  // Open the file.
  cmListFileLexer_BOM bom;
  if (!cmListFileLexer_SetFileName(this->Lexer, this->FileName, &bom)) {
    this->IssueFileOpenError("cmListFileCache: error can not open file.");
    return false;
  }

  if (bom == cmListFileLexer_BOM_Broken) {
    cmListFileLexer_SetFileName(this->Lexer, nullptr, nullptr);
    this->IssueFileOpenError("Error while reading Byte-Order-Mark. "
                             "File not seekable?");
    return false;
  }

  // Verify the Byte-Order-Mark, if any.
  if (bom != cmListFileLexer_BOM_None && bom != cmListFileLexer_BOM_UTF8) {
    cmListFileLexer_SetFileName(this->Lexer, nullptr, nullptr);
    this->IssueFileOpenError(
      "File starts with a Byte-Order-Mark that is not UTF-8.");
    return false;
  }

  return Parse();
}

bool cmListFileParser::ParseString(const char* str,
                                   const char* virtual_filename)
{
  this->FileName = virtual_filename;

  if (!cmListFileLexer_SetString(this->Lexer, str)) {
    this->IssueFileOpenError("cmListFileCache: cannot allocate buffer.");
    return false;
  }

  return Parse();
}

bool cmListFileParser::Parse()
{
  // Use a simple recursive-descent parser to process the token
  // stream.
  bool haveNewline = true;
  while (cmListFileLexer_Token* token = cmListFileLexer_Scan(this->Lexer)) {
    if (token->type == cmListFileLexer_Token_Space) {
    } else if (token->type == cmListFileLexer_Token_Newline) {
      haveNewline = true;
    } else if (token->type == cmListFileLexer_Token_CommentBracket) {
      haveNewline = false;
    } else if (token->type == cmListFileLexer_Token_Identifier) {
      if (haveNewline) {
        haveNewline = false;
        if (this->ParseFunction(token->text, token->line)) {
          this->ListFile->Functions.emplace_back(
            std::move(this->FunctionName), this->FunctionLine,
            std::move(this->FunctionArguments));
        } else {
          return false;
        }
      } else {
        std::ostringstream error;
        error << "Parse error.  Expected a newline, got "
              << cmListFileLexer_GetTypeAsString(this->Lexer, token->type)
              << " with text \"" << token->text << "\".";
        this->IssueError(error.str());
        return false;
      }
    } else {
      std::ostringstream error;
      error << "Parse error.  Expected a command name, got "
            << cmListFileLexer_GetTypeAsString(this->Lexer, token->type)
            << " with text \"" << token->text << "\".";
      this->IssueError(error.str());
      return false;
    }
  }
  return true;
}

bool cmListFile::ParseFile(const char* filename, cmMessenger* messenger,
                           cmListFileBacktrace const& lfbt)
{
  if (!cmSystemTools::FileExists(filename) ||
      cmSystemTools::FileIsDirectory(filename)) {
    return false;
  }

  bool parseError = false;

  {
    cmListFileParser parser(this, lfbt, messenger);
    parseError = !parser.ParseFile(filename);
  }

  return !parseError;
}

bool cmListFile::ParseString(const char* str, const char* virtual_filename,
                             cmMessenger* messenger,
                             const cmListFileBacktrace& lfbt)
{
  bool parseError = false;

  {
    cmListFileParser parser(this, lfbt, messenger);
    parseError = !parser.ParseString(str, virtual_filename);
  }

  return !parseError;
}

bool cmListFileParser::ParseFunction(const char* name, long line)
{
  // Ininitialize a new function call.
  this->FunctionName = name;
  this->FunctionLine = line;

  // Command name has already been parsed.  Read the left paren.
  cmListFileLexer_Token* token;
  while ((token = cmListFileLexer_Scan(this->Lexer)) &&
         token->type == cmListFileLexer_Token_Space) {
  }
  if (!token) {
    std::ostringstream error;
    /* clang-format off */
    error << "Unexpected end of file.\n"
          << "Parse error.  Function missing opening \"(\".";
    /* clang-format on */
    this->IssueError(error.str());
    return false;
  }
  if (token->type != cmListFileLexer_Token_ParenLeft) {
    std::ostringstream error;
    error << "Parse error.  Expected \"(\", got "
          << cmListFileLexer_GetTypeAsString(this->Lexer, token->type)
          << " with text \"" << token->text << "\".";
    this->IssueError(error.str());
    return false;
  }

  // Arguments.
  unsigned long parenDepth = 0;
  this->Separation = SeparationOkay;
  while ((token = cmListFileLexer_Scan(this->Lexer))) {
    if (token->type == cmListFileLexer_Token_Space ||
        token->type == cmListFileLexer_Token_Newline) {
      this->Separation = SeparationOkay;
      continue;
    }
    if (token->type == cmListFileLexer_Token_ParenLeft) {
      parenDepth++;
      this->Separation = SeparationOkay;
      if (!this->AddArgument(token, cmListFileArgument::Unquoted)) {
        return false;
      }
    } else if (token->type == cmListFileLexer_Token_ParenRight) {
      if (parenDepth == 0) {
        return true;
      }
      parenDepth--;
      this->Separation = SeparationOkay;
      if (!this->AddArgument(token, cmListFileArgument::Unquoted)) {
        return false;
      }
      this->Separation = SeparationWarning;
    } else if (token->type == cmListFileLexer_Token_Identifier ||
               token->type == cmListFileLexer_Token_ArgumentUnquoted) {
      if (!this->AddArgument(token, cmListFileArgument::Unquoted)) {
        return false;
      }
      this->Separation = SeparationWarning;
    } else if (token->type == cmListFileLexer_Token_ArgumentQuoted) {
      if (!this->AddArgument(token, cmListFileArgument::Quoted)) {
        return false;
      }
      this->Separation = SeparationWarning;
    } else if (token->type == cmListFileLexer_Token_ArgumentBracket) {
      if (!this->AddArgument(token, cmListFileArgument::Bracket)) {
        return false;
      }
      this->Separation = SeparationError;
    } else if (token->type == cmListFileLexer_Token_CommentBracket) {
      this->Separation = SeparationError;
    } else {
      // Error.
      std::ostringstream error;
      error << "Parse error.  Function missing ending \")\".  "
            << "Instead found "
            << cmListFileLexer_GetTypeAsString(this->Lexer, token->type)
            << " with text \"" << token->text << "\".";
      this->IssueError(error.str());
      return false;
    }
  }

  std::ostringstream error;
  cmListFileContext lfc;
  lfc.FilePath = this->FileName;
  lfc.Line = line;
  cmListFileBacktrace lfbt = this->Backtrace;
  lfbt = lfbt.Push(lfc);
  error << "Parse error.  Function missing ending \")\".  "
        << "End of file reached.";
  this->Messenger->IssueMessage(MessageType::FATAL_ERROR, error.str(), lfbt);
  return false;
}

bool cmListFileParser::AddArgument(cmListFileLexer_Token* token,
                                   cmListFileArgument::Delimiter delim)
{
  this->FunctionArguments.emplace_back(token->text, delim, token->line);
  if (this->Separation == SeparationOkay) {
    return true;
  }
  bool isError = (this->Separation == SeparationError ||
                  delim == cmListFileArgument::Bracket);
  std::ostringstream m;
  cmListFileContext lfc;
  lfc.FilePath = this->FileName;
  lfc.Line = token->line;
  cmListFileBacktrace lfbt = this->Backtrace;
  lfbt = lfbt.Push(lfc);

  m << "Syntax " << (isError ? "Error" : "Warning") << " in cmake code at "
    << "column " << token->column << "\n"
    << "Argument not separated from preceding token by whitespace.";
  /* clang-format on */
  if (isError) {
    this->Messenger->IssueMessage(MessageType::FATAL_ERROR, m.str(), lfbt);
    return false;
  }
  this->Messenger->IssueMessage(MessageType::AUTHOR_WARNING, m.str(), lfbt);
  return true;
}

// We hold either the bottom scope of a directory or a call/file context.
// Discriminate these cases via the parent pointer.
struct cmListFileBacktrace::Entry
{
  Entry(cmStateSnapshot bottom)
    : Bottom(bottom)
  {
  }

  Entry(std::shared_ptr<Entry const> parent, cmListFileContext lfc)
    : Context(std::move(lfc))
    , Parent(std::move(parent))
  {
  }

  ~Entry()
  {
    if (this->Parent) {
      this->Context.~cmListFileContext();
    } else {
      this->Bottom.~cmStateSnapshot();
    }
  }

  bool IsBottom() const { return !this->Parent; }

  union
  {
    cmStateSnapshot Bottom;
    cmListFileContext Context;
  };
  std::shared_ptr<Entry const> Parent;
};

cmListFileBacktrace::cmListFileBacktrace(cmStateSnapshot const& snapshot)
  : TopEntry(std::make_shared<Entry const>(snapshot.GetCallStackBottom()))
{
}

/* NOLINTNEXTLINE(performance-unnecessary-value-param) */
cmListFileBacktrace::cmListFileBacktrace(std::shared_ptr<Entry const> parent,
                                         cmListFileContext const& lfc)
  : TopEntry(std::make_shared<Entry const>(std::move(parent), lfc))
{
}

cmListFileBacktrace::cmListFileBacktrace(std::shared_ptr<Entry const> top)
  : TopEntry(std::move(top))
{
}

cmStateSnapshot cmListFileBacktrace::GetBottom() const
{
  cmStateSnapshot bottom;
  if (Entry const* cur = this->TopEntry.get()) {
    while (Entry const* parent = cur->Parent.get()) {
      cur = parent;
    }
    bottom = cur->Bottom;
  }
  return bottom;
}

cmListFileBacktrace cmListFileBacktrace::Push(std::string const& file) const
{
  // We are entering a file-level scope but have not yet reached
  // any specific line or command invocation within it.  This context
  // is useful to print when it is at the top but otherwise can be
  // skipped during call stack printing.
  cmListFileContext lfc;
  lfc.FilePath = file;
  return this->Push(lfc);
}

cmListFileBacktrace cmListFileBacktrace::Push(
  cmListFileContext const& lfc) const
{
  assert(this->TopEntry);
  assert(!this->TopEntry->IsBottom() || this->TopEntry->Bottom.IsValid());
  return cmListFileBacktrace(this->TopEntry, lfc);
}

cmListFileBacktrace cmListFileBacktrace::Pop() const
{
  assert(this->TopEntry);
  assert(!this->TopEntry->IsBottom());
  return cmListFileBacktrace(this->TopEntry->Parent);
}

cmListFileContext const& cmListFileBacktrace::Top() const
{
  assert(this->TopEntry);
  assert(!this->TopEntry->IsBottom());
  return this->TopEntry->Context;
}

void cmListFileBacktrace::PrintTitle(std::ostream& out) const
{
  // The title exists only if we have a call on top of the bottom.
  if (!this->TopEntry || this->TopEntry->IsBottom()) {
    return;
  }
  cmListFileContext lfc = this->TopEntry->Context;
  cmStateSnapshot bottom = this->GetBottom();
  if (!bottom.GetState()->GetIsInTryCompile()) {
    lfc.FilePath = bottom.GetDirectory().ConvertToRelPathIfNotContained(
      bottom.GetState()->GetSourceDirectory(), lfc.FilePath);
  }
  out << (lfc.Line ? " at " : " in ") << lfc;
}

void cmListFileBacktrace::PrintCallStack(std::ostream& out) const
{
  // The call stack exists only if we have at least two calls on top
  // of the bottom.
  if (!this->TopEntry || this->TopEntry->IsBottom() ||
      this->TopEntry->Parent->IsBottom()) {
    return;
  }

  bool first = true;
  cmStateSnapshot bottom = this->GetBottom();
  for (Entry const* cur = this->TopEntry->Parent.get(); !cur->IsBottom();
       cur = cur->Parent.get()) {
    if (cur->Context.Name.empty() &&
        cur->Context.Line != cmListFileContext::DeferPlaceholderLine) {
      // Skip this whole-file scope.  When we get here we already will
      // have printed a more-specific context within the file.
      continue;
    }
    if (first) {
      first = false;
      out << "Call Stack (most recent call first):\n";
    }
    cmListFileContext lfc = cur->Context;
    if (!bottom.GetState()->GetIsInTryCompile()) {
      lfc.FilePath = bottom.GetDirectory().ConvertToRelPathIfNotContained(
        bottom.GetState()->GetSourceDirectory(), lfc.FilePath);
    }
    out << "  " << lfc << "\n";
  }
}

size_t cmListFileBacktrace::Depth() const
{
  size_t depth = 0;
  if (Entry const* cur = this->TopEntry.get()) {
    for (; !cur->IsBottom(); cur = cur->Parent.get()) {
      ++depth;
    }
  }
  return depth;
}

bool cmListFileBacktrace::Empty() const
{
  return !this->TopEntry || this->TopEntry->IsBottom();
}

std::ostream& operator<<(std::ostream& os, cmListFileContext const& lfc)
{
  os << lfc.FilePath;
  if (lfc.Line > 0) {
    os << ":" << lfc.Line;
    if (!lfc.Name.empty()) {
      os << " (" << lfc.Name << ")";
    }
  } else if (lfc.Line == cmListFileContext::DeferPlaceholderLine) {
    os << ":DEFERRED";
  }
  return os;
}

bool operator<(const cmListFileContext& lhs, const cmListFileContext& rhs)
{
  if (lhs.Line != rhs.Line) {
    return lhs.Line < rhs.Line;
  }
  return lhs.FilePath < rhs.FilePath;
}

bool operator==(const cmListFileContext& lhs, const cmListFileContext& rhs)
{
  return lhs.Line == rhs.Line && lhs.FilePath == rhs.FilePath;
}

bool operator!=(const cmListFileContext& lhs, const cmListFileContext& rhs)
{
  return !(lhs == rhs);
}

std::ostream& operator<<(std::ostream& os, BT<std::string> const& s)
{
  return os << s.Value;
}

std::vector<BT<std::string>> ExpandListWithBacktrace(
  std::string const& list, cmListFileBacktrace const& bt)
{
  std::vector<BT<std::string>> result;
  std::vector<std::string> tmp = cmExpandedList(list);
  result.reserve(tmp.size());
  for (std::string& i : tmp) {
    result.emplace_back(std::move(i), bt);
  }
  return result;
}
