/* 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();
  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;
}
