/* 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 "cmListFileLexer.h"
#include "cmMessageType.h"
#include "cmMessenger.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmSystemTools.h"

#include <assert.h>
#include <memory>
#include <sstream>
#include <utility>

cmCommandContext::cmCommandName& cmCommandContext::cmCommandName::operator=(
  std::string const& name)
{
  this->Original = name;
  this->Lower = cmSystemTools::LowerCase(name);
  return *this;
}

struct cmListFileParser
{
  cmListFileParser(cmListFile* lf, cmListFileBacktrace lfbt,
                   cmMessenger* messenger, const char* filename);
  ~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();
  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;
  cmListFileFunction Function;
  enum
  {
    SeparationOkay,
    SeparationWarning,
    SeparationError
  } Separation;
};

cmListFileParser::cmListFileParser(cmListFile* lf, cmListFileBacktrace lfbt,
                                   cmMessenger* messenger,
                                   const char* filename)
  : ListFile(lf)
  , Backtrace(std::move(lfbt))
  , Messenger(messenger)
  , FileName(filename)
  , 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()
{
  // 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;
  }

  // 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.push_back(this->Function);
        } 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, filename);
    parseError = !parser.ParseFile();
  }

  return !parseError;
}

bool cmListFileParser::ParseFunction(const char* name, long line)
{
  // Ininitialize a new function call.
  this->Function = cmListFileFunction();
  this->Function.Name = name;
  this->Function.Line = 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 lastLine;
  unsigned long parenDepth = 0;
  this->Separation = SeparationOkay;
  while (
    (static_cast<void>(lastLine = cmListFileLexer_GetCurrentLine(this->Lexer)),
     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 = lastLine;
  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->Function.Arguments.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()))
{
}

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()) {
      // 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) {
    os << ":" << lfc.Line;
    if (!lfc.Name.empty()) {
      os << " (" << lfc.Name << ")";
    }
  }
  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;
  cmSystemTools::ExpandListArgument(list, tmp);
  result.reserve(tmp.size());
  for (std::string& i : tmp) {
    result.emplace_back(std::move(i), bt);
  }
  return result;
}
