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

#include "cmCommandArgumentLexer.h"
#include "cmMakefile.h"
#include "cmState.h"
#include "cmSystemTools.h"
#include "cmake.h"

#include <iostream>
#include <sstream>
#include <string.h>

int cmCommandArgument_yyparse(yyscan_t yyscanner);
//
cmCommandArgumentParserHelper::cmCommandArgumentParserHelper()
{
  this->WarnUninitialized = false;
  this->CheckSystemVars = false;
  this->FileLine = -1;
  this->FileName = nullptr;
  this->RemoveEmpty = true;

  this->NoEscapeMode = false;
  this->ReplaceAtSyntax = false;
}

cmCommandArgumentParserHelper::~cmCommandArgumentParserHelper()
{
  this->CleanupParser();
}

void cmCommandArgumentParserHelper::SetLineFile(long line, const char* file)
{
  this->FileLine = line;
  this->FileName = file;
}

const char* cmCommandArgumentParserHelper::AddString(const std::string& str)
{
  if (str.empty()) {
    return "";
  }
  char* stVal = new char[str.size() + 1];
  strcpy(stVal, str.c_str());
  this->Variables.push_back(stVal);
  return stVal;
}

const char* cmCommandArgumentParserHelper::ExpandSpecialVariable(
  const char* key, const char* var)
{
  if (!key) {
    return this->ExpandVariable(var);
  }
  if (!var) {
    return "";
  }
  if (strcmp(key, "ENV") == 0) {
    std::string str;
    if (cmSystemTools::GetEnv(var, str)) {
      if (this->EscapeQuotes) {
        return this->AddString(cmSystemTools::EscapeQuotes(str));
      }
      return this->AddString(str);
    }
    return "";
  }
  if (strcmp(key, "CACHE") == 0) {
    if (const char* c =
          this->Makefile->GetState()->GetInitializedCacheValue(var)) {
      if (this->EscapeQuotes) {
        return this->AddString(cmSystemTools::EscapeQuotes(c));
      }
      return this->AddString(c);
    }
    return "";
  }
  std::ostringstream e;
  e << "Syntax $" << key << "{} is not supported.  "
    << "Only ${}, $ENV{}, and $CACHE{} are allowed.";
  this->SetError(e.str());
  return nullptr;
}

const char* cmCommandArgumentParserHelper::ExpandVariable(const char* var)
{
  if (!var) {
    return nullptr;
  }
  if (this->FileLine >= 0 && strcmp(var, "CMAKE_CURRENT_LIST_LINE") == 0) {
    std::ostringstream ostr;
    ostr << this->FileLine;
    return this->AddString(ostr.str());
  }
  const char* value = this->Makefile->GetDefinition(var);
  if (!value && !this->RemoveEmpty) {
    // check to see if we need to print a warning
    // if strict mode is on and the variable has
    // not been "cleared"/initialized with a set(foo ) call
    if (this->WarnUninitialized && !this->Makefile->VariableInitialized(var)) {
      if (this->CheckSystemVars ||
          (this->FileName &&
           (cmSystemTools::IsSubDirectory(
              this->FileName, this->Makefile->GetHomeDirectory()) ||
            cmSystemTools::IsSubDirectory(
              this->FileName, this->Makefile->GetHomeOutputDirectory())))) {
        std::ostringstream msg;
        msg << "uninitialized variable \'" << var << "\'";
        this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, msg.str());
      }
    }
    return nullptr;
  }
  if (this->EscapeQuotes && value) {
    return this->AddString(cmSystemTools::EscapeQuotes(value));
  }
  return this->AddString(value ? value : "");
}

const char* cmCommandArgumentParserHelper::ExpandVariableForAt(const char* var)
{
  if (this->ReplaceAtSyntax) {
    // try to expand the variable
    const char* ret = this->ExpandVariable(var);
    // if the return was 0 and we want to replace empty strings
    // then return an empty string
    if (!ret && this->RemoveEmpty) {
      return this->AddString("");
    }
    // if the ret was not 0, then return it
    if (ret) {
      return ret;
    }
  }
  // at this point we want to put it back because of one of these cases:
  // - this->ReplaceAtSyntax is false
  // - this->ReplaceAtSyntax is true, but this->RemoveEmpty is false,
  //   and the variable was not defined
  std::string ref = "@";
  ref += var;
  ref += "@";
  return this->AddString(ref);
}

const char* cmCommandArgumentParserHelper::CombineUnions(const char* in1,
                                                         const char* in2)
{
  if (!in1) {
    return in2;
  }
  if (!in2) {
    return in1;
  }
  size_t len = strlen(in1) + strlen(in2) + 1;
  char* out = new char[len];
  strcpy(out, in1);
  strcat(out, in2);
  this->Variables.push_back(out);
  return out;
}

void cmCommandArgumentParserHelper::AllocateParserType(
  cmCommandArgumentParserHelper::ParserType* pt, const char* str, int len)
{
  pt->str = nullptr;
  if (len == 0) {
    len = static_cast<int>(strlen(str));
  }
  if (len == 0) {
    return;
  }
  char* out = new char[len + 1];
  strncpy(out, str, len);
  out[len] = 0;
  pt->str = out;
  this->Variables.push_back(out);
}

bool cmCommandArgumentParserHelper::HandleEscapeSymbol(
  cmCommandArgumentParserHelper::ParserType* pt, char symbol)
{
  switch (symbol) {
    case '\\':
    case '"':
    case ' ':
    case '#':
    case '(':
    case ')':
    case '$':
    case '@':
    case '^':
      this->AllocateParserType(pt, &symbol, 1);
      break;
    case ';':
      this->AllocateParserType(pt, "\\;", 2);
      break;
    case 't':
      this->AllocateParserType(pt, "\t", 1);
      break;
    case 'n':
      this->AllocateParserType(pt, "\n", 1);
      break;
    case 'r':
      this->AllocateParserType(pt, "\r", 1);
      break;
    case '0':
      this->AllocateParserType(pt, "\0", 1);
      break;
    default: {
      std::ostringstream e;
      e << "Invalid escape sequence \\" << symbol;
      this->SetError(e.str());
    }
      return false;
  }
  return true;
}

void cmCommandArgument_SetupEscapes(yyscan_t yyscanner, bool noEscapes);

int cmCommandArgumentParserHelper::ParseString(const char* str, int verb)
{
  if (!str) {
    return 0;
  }
  this->Verbose = verb;
  this->InputBuffer = str;
  this->InputBufferPos = 0;
  this->CurrentLine = 0;

  this->Result.clear();

  yyscan_t yyscanner;
  cmCommandArgument_yylex_init(&yyscanner);
  cmCommandArgument_yyset_extra(this, yyscanner);
  cmCommandArgument_SetupEscapes(yyscanner, this->NoEscapeMode);
  int res = cmCommandArgument_yyparse(yyscanner);
  cmCommandArgument_yylex_destroy(yyscanner);
  if (res != 0) {
    return 0;
  }

  this->CleanupParser();

  if (Verbose) {
    std::cerr << "Expanding [" << str << "] produced: [" << this->Result << "]"
              << std::endl;
  }
  return 1;
}

void cmCommandArgumentParserHelper::CleanupParser()
{
  std::vector<char*>::iterator sit;
  for (char* var : this->Variables) {
    delete[] var;
  }
  this->Variables.erase(this->Variables.begin(), this->Variables.end());
}

int cmCommandArgumentParserHelper::LexInput(char* buf, int maxlen)
{
  if (maxlen < 1) {
    return 0;
  }
  if (this->InputBufferPos < this->InputBuffer.size()) {
    buf[0] = this->InputBuffer[this->InputBufferPos++];
    if (buf[0] == '\n') {
      this->CurrentLine++;
    }
    return (1);
  }
  buf[0] = '\n';
  return (0);
}

void cmCommandArgumentParserHelper::Error(const char* str)
{
  unsigned long pos = static_cast<unsigned long>(this->InputBufferPos);
  std::ostringstream ostr;
  ostr << str << " (" << pos << ")";
  this->SetError(ostr.str());
}

void cmCommandArgumentParserHelper::SetMakefile(const cmMakefile* mf)
{
  this->Makefile = mf;
  this->WarnUninitialized = mf->GetCMakeInstance()->GetWarnUninitialized();
  this->CheckSystemVars = mf->GetCMakeInstance()->GetCheckSystemVars();
}

void cmCommandArgumentParserHelper::SetResult(const char* value)
{
  if (!value) {
    this->Result.clear();
    return;
  }
  this->Result = value;
}

void cmCommandArgumentParserHelper::SetError(std::string const& msg)
{
  // Keep only the first error.
  if (this->ErrorString.empty()) {
    this->ErrorString = msg;
  }
}
