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

#include <algorithm>
#include <cstdio>
#include <string>
#include <vector>

#include "cmGccDepfileReaderTypes.h"

#include "LexerParser/cmGccDepfileLexer.h"

#ifdef _WIN32
#  include <cctype>

#  include "cmsys/Encoding.h"
#endif

bool cmGccDepfileLexerHelper::readFile(char const* filePath)
{
#ifdef _WIN32
  wchar_t* wpath = cmsysEncoding_DupToWide(filePath);
  FILE* file = _wfopen(wpath, L"rb");
  free(wpath);
#else
  FILE* file = fopen(filePath, "r");
#endif
  if (!file) {
    return false;
  }
  this->newEntry();
  yyscan_t scanner;
  cmGccDepfile_yylex_init(&scanner);
  cmGccDepfile_yyset_extra(this, scanner);
  cmGccDepfile_yyrestart(file, scanner);
  cmGccDepfile_yylex(scanner);
  cmGccDepfile_yylex_destroy(scanner);
  this->sanitizeContent();
  fclose(file);
  return this->HelperState != State::Failed;
}

void cmGccDepfileLexerHelper::newEntry()
{
  if (this->HelperState == State::Rule && !this->Content.empty()) {
    if (!this->Content.back().rules.empty() &&
        !this->Content.back().rules.back().empty()) {
      this->HelperState = State::Failed;
    }
    return;
  }
  this->HelperState = State::Rule;
  this->Content.emplace_back();
  this->newRule();
}

void cmGccDepfileLexerHelper::newRule()
{
  auto& entry = this->Content.back();
  if (entry.rules.empty() || !entry.rules.back().empty()) {
    entry.rules.emplace_back();
  }
}

void cmGccDepfileLexerHelper::newDependency()
{
  if (this->HelperState == State::Failed) {
    return;
  }
  this->HelperState = State::Dependency;
  auto& entry = this->Content.back();
  if (entry.paths.empty() || !entry.paths.back().empty()) {
    entry.paths.emplace_back();
  }
}

void cmGccDepfileLexerHelper::newRuleOrDependency()
{
  if (this->HelperState == State::Rule) {
    this->newRule();
  } else if (this->HelperState == State::Dependency) {
    this->newDependency();
  }
}

void cmGccDepfileLexerHelper::addToCurrentPath(char const* s)
{
  if (this->Content.empty()) {
    return;
  }
  cmGccStyleDependency* dep = &this->Content.back();
  std::string* dst = nullptr;
  switch (this->HelperState) {
    case State::Rule: {
      if (dep->rules.empty()) {
        return;
      }
      dst = &dep->rules.back();
    } break;
    case State::Dependency: {
      if (dep->paths.empty()) {
        return;
      }
      dst = &dep->paths.back();
    } break;
    case State::Failed:
      return;
  }
  dst->append(s);
}

void cmGccDepfileLexerHelper::sanitizeContent()
{
  for (auto it = this->Content.begin(); it != this->Content.end();) {
    // remove duplicate path entries
    std::sort(it->paths.begin(), it->paths.end());
    auto last = std::unique(it->paths.begin(), it->paths.end());
    it->paths.erase(last, it->paths.end());

    // Remove empty paths and normalize windows paths
    for (auto pit = it->paths.begin(); pit != it->paths.end();) {
      if (pit->empty()) {
        pit = it->paths.erase(pit);
      } else {
#if defined(_WIN32)
        // Unescape the colon following the drive letter.
        // Some versions of GNU compilers can escape this character.
        // c\:\path must be transformed to c:\path
        if (pit->size() >= 3 && std::toupper((*pit)[0]) >= 'A' &&
            std::toupper((*pit)[0]) <= 'Z' && (*pit)[1] == '\\' &&
            (*pit)[2] == ':') {
          pit->erase(1, 1);
        }
#endif
        ++pit;
      }
    }
    // Remove empty rules
    for (auto rit = it->rules.begin(); rit != it->rules.end();) {
      if (rit->empty()) {
        rit = it->rules.erase(rit);
      } else {
        ++rit;
      }
    }
    // Remove the entry if rules are empty
    if (it->rules.empty()) {
      it = this->Content.erase(it);
    } else {
      ++it;
    }
  }
}
