/*
 Copyright 2019 Alain Dargelas

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

/*
 * File:   PreprocessFile.cpp
 * Author: alain
 *
 * Created on February 24, 2017, 9:38 PM
 */
#include "SymbolTable.h"
#include "CommandLine/CommandLineParser.hpp"
#include "ErrorReporting/ErrorContainer.h"
#include "CompilationUnit.h"
#include "PreprocessFile.h"
#include "CompileSourceFile.h"
#include "Compiler.h"
#include "Utils/StringUtils.h"
#include "Cache/PPCache.h"
#include "ErrorReporting/Waiver.h"
#include <cstdlib>
#include <iostream>
#include <regex>
#include <algorithm>

using namespace std;
using namespace SURELOG;

#include "parser/SV3_1aPpLexer.h"
#include "parser/SV3_1aPpParser.h"
#include "parser/SV3_1aPpParserBaseListener.h"
using namespace antlr4;
#include "Utils/ParseUtils.h"
#include "Utils/FileUtils.h"
#include "antlr4-runtime.h"
#include "atn/ParserATNSimulator.h"
#include "Parser.h"
std::string PreprocessFile::MacroNotDefined = "SURELOG_MACRO_NOT_DEFINED";
std::string PreprocessFile::PP__Line__Marking = "SURELOG__LINE__MARKING";
std::string PreprocessFile::PP__File__Marking = "SURELOG__FILE__MARKING";

#include "SV3_1aPpTreeShapeListener.h"

void PreprocessFile::setDebug(int level) {
  switch (level) {
    case 0:
      m_debugPP = false;
      m_debugPPResult = false;
      m_debugPPTokens = false;
      m_debugPPTree = false;
      m_debugMacro = false;
      break;
    case 1:
      m_debugPP = true;
      m_debugPPResult = false;
      m_debugPPTokens = false;
      m_debugPPTree = false;
      m_debugMacro = false;
      break;
    case 2:
      m_debugPP = true;
      m_debugPPResult = false;
      m_debugPPTokens = true;
      m_debugPPTree = true;
      m_debugMacro = false;
      break;
    case 3:
      m_debugPP = true;
      m_debugPPResult = true;
      m_debugPPTokens = false;
      m_debugPPTree = false;
      m_debugMacro = true;
      break;
    case 4:
      m_debugPP = true;
      m_debugPPResult = true;
      m_debugPPTokens = true;
      m_debugPPTree = true;
      m_debugMacro = true;
      break;
    default:
      break;
  }
}
class PreprocessFile::DescriptiveErrorListener : public ANTLRErrorListener {
 public:
  DescriptiveErrorListener(PreprocessFile* pp, std::string filename)
      : m_pp(pp), m_fileName(filename) {}

  void syntaxError(Recognizer* recognizer, Token* offendingSymbol, size_t line,
                   size_t charPositionInLine, const std::string& msg,
                   std::exception_ptr e);

  void reportAmbiguity(Parser* recognizer, const dfa::DFA& dfa,
                       size_t startIndex, size_t stopIndex, bool exact,
                       const antlrcpp::BitSet& ambigAlts,
                       atn::ATNConfigSet* configs);

  void reportAttemptingFullContext(Parser* recognizer, const dfa::DFA& dfa,
                                   size_t startIndex, size_t stopIndex,
                                   const antlrcpp::BitSet& conflictingAlts,
                                   atn::ATNConfigSet* configs);

  void reportContextSensitivity(Parser* recognizer, const dfa::DFA& dfa,
                                size_t startIndex, size_t stopIndex,
                                size_t prediction, atn::ATNConfigSet* configs);

  PreprocessFile* m_pp;
  std::string m_fileName;
  std::string m_fileContent;
};

void PreprocessFile::DescriptiveErrorListener::syntaxError(
    Recognizer* recognizer, Token* offendingSymbol, size_t line,
    size_t charPositionInLine, const std::string& msg, std::exception_ptr e) {
  SymbolId msgId = m_pp->registerSymbol(msg);

  if (m_pp->m_macroInfo) {
    std::string lineText = m_pp->getMacroBody();
    for (unsigned int i = 0; i < charPositionInLine; i++) lineText += " ";
    lineText += "^-- " + m_fileName + ":" + std::to_string(line) +
                " col:" + std::to_string(charPositionInLine);
    msgId = m_pp->registerSymbol(msg + "," + lineText);
    Location loc(m_pp->getMacroInfo()->m_file,
                 m_pp->getMacroInfo()->m_line + line - 1, charPositionInLine,
                 msgId);
    Location extraLoc(m_pp->getIncluderFileId(m_pp->getIncluderLine()),
                      m_pp->getIncluderLine(), 0, 0);
    Error err(ErrorDefinition::PP_MACRO_SYNTAX_ERROR, loc, extraLoc);
    m_pp->addError(err);
  } else {
    if (m_fileContent == "") {
      m_fileContent = FileUtils::getFileContent(m_fileName);
    }

    std::string lineText;
    if (m_fileContent != "") {
      lineText = StringUtils::getLineInString(m_fileContent, line);
      if (lineText != "") {
        if (!strstr(lineText.c_str(), "\n")) {
          lineText += "\n";
        }
        for (unsigned int i = 0; i < charPositionInLine; i++) lineText += " ";
        lineText += "^-- " + m_fileName + ":" + std::to_string(line) +
                    " col:" + std::to_string(charPositionInLine);
      }
    }

    Location loc2(0, 0, 0, m_pp->registerSymbol(lineText));

    Location loc(m_pp->getFileId(line), line, charPositionInLine, msgId);
    Error err(ErrorDefinition::PP_SYNTAX_ERROR, loc, loc2);
    m_pp->addError(err);
  }
}

void PreprocessFile::DescriptiveErrorListener::reportAmbiguity(
    Parser* recognizer, const dfa::DFA& dfa, size_t startIndex,
    size_t stopIndex, bool exact, const antlrcpp::BitSet& ambigAlts,
    atn::ATNConfigSet* configs) {}

void PreprocessFile::DescriptiveErrorListener::reportAttemptingFullContext(
    Parser* recognizer, const dfa::DFA& dfa, size_t startIndex,
    size_t stopIndex, const antlrcpp::BitSet& conflictingAlts,
    atn::ATNConfigSet* configs) {}

void PreprocessFile::DescriptiveErrorListener::reportContextSensitivity(
    Parser* recognizer, const dfa::DFA& dfa, size_t startIndex,
    size_t stopIndex, size_t prediction, atn::ATNConfigSet* configs) {}

PreprocessFile::PreprocessFile(SymbolId fileId, CompileSourceFile* csf,
                               SpecialInstructions& instructions,
                               CompilationUnit* comp_unit, Library* library)
    : m_fileId(fileId),
      m_library(library),
      m_result(""),
      m_macroBody(""),
      m_includer(NULL),
      m_includerLine(0),
      m_compileSourceFile(csf),
      m_lineCount(0),
      m_listener(NULL),
      m_instructions(instructions),
      m_antlrParserHandler(NULL),
      m_macroInfo(NULL),
      m_compilationUnit(comp_unit),
      m_pauseAppend(false),
      m_usingCachedVersion(false),
      m_embeddedMacroCallLine(0),
      m_embeddedMacroCallFile(0) {
  setDebug(m_compileSourceFile->m_commandLineParser->getDebugLevel());
  IncludeFileInfo info(1, m_fileId, 1, 1);
  info.m_indexClosing = 0;
  info.m_indexOpening = 0;
  getIncludeFileInfo().push_back(info);
}

PreprocessFile::PreprocessFile(SymbolId fileId, PreprocessFile* includedIn,
                               unsigned int includerLine,
                               CompileSourceFile* csf,
                               SpecialInstructions& instructions,
                               CompilationUnit* comp_unit, Library* library,
                               std::string macroBody, MacroInfo* macroInfo,
                               unsigned int embeddedMacroCallLine,
                               SymbolId embeddedMacroCallFile)
    : m_fileId(fileId),
      m_library(library),
      m_result(""),
      m_macroBody(macroBody),
      m_compileSourceFile(csf),
      m_lineCount(0),
      m_listener(NULL),
      m_instructions(instructions),
      m_antlrParserHandler(NULL),
      m_macroInfo(macroInfo),
      m_compilationUnit(comp_unit),
      m_pauseAppend(false),
      m_usingCachedVersion(false),
      m_embeddedMacroCallLine(embeddedMacroCallLine),
      m_embeddedMacroCallFile(embeddedMacroCallFile) {
  setDebug(m_compileSourceFile->m_commandLineParser->getDebugLevel());
  m_includer = includedIn;
  m_includerLine = includerLine;
  if (includedIn) {
    includedIn->m_includes.push_back(this);
  }
}

void PreprocessFile::addError(Error& error) {
  if (!m_instructions.m_mute)
    getCompileSourceFile()->getErrorContainer()->addError(error);
}

const std::string PreprocessFile::getSymbol(SymbolId id) {
  return getCompileSourceFile()->getSymbolTable()->getSymbol(id);
}

const std::string PreprocessFile::getFileName(unsigned int line) {
  return getSymbol(getFileId(line));
}

SymbolId PreprocessFile::getMacroSignature() {
  std::string macroSignature = getSymbol(m_fileId);
  if (m_macroInfo) {
    macroSignature += "|" + getSymbol(m_macroInfo->m_file);
    macroSignature += "|" + std::to_string(m_macroInfo->m_line);
  }
  macroSignature += "|" + m_macroBody;
  SymbolId sigId = registerSymbol(macroSignature);
  return sigId;
}

PreprocessFile::PreprocessFile(const PreprocessFile& orig) {}

PreprocessFile::~PreprocessFile() {
  if (m_listener) delete m_listener;
}

PreprocessFile::AntlrParserHandler::~AntlrParserHandler() {
  delete m_errorListener;
  // delete m_pptree;  // INVALID MEMORY READ can be seen in AdvancedDebug
  delete m_ppparser;
  delete m_pptokens;
  delete m_pplexer;
  delete m_inputStream;
}

bool PreprocessFile::preprocess() {
  PPCache cache(this);
  if (cache.restore()) {
    m_usingCachedVersion = true;
    getCompilationUnit()->setCurrentTimeInfo(getFileId(0));
    return true;
  }

  m_result = "";
  std::string fileName = getSymbol(m_fileId);

  m_antlrParserHandler = getCompileSourceFile()->getAntlrPpHandlerForId(
      (m_macroBody == "") ? m_fileId : getMacroSignature());

  if (m_antlrParserHandler == NULL) {
    m_antlrParserHandler = new AntlrParserHandler();
    if (m_macroBody != "") {
      if (m_debugPP) {
        std::cout << "PP PREPROCESS MACRO: " << m_macroBody << endl;
      }
      m_antlrParserHandler->m_inputStream = new ANTLRInputStream(m_macroBody);
    } else {
      if (m_debugPP) std::cout << "PP PREPROCESS FILE: " << fileName << endl;
      std::ifstream stream;
      stream.open(fileName);
      if (!stream.good()) {
        if (m_includer == NULL) {
          Location loc(m_fileId);
          Error err(ErrorDefinition::PP_CANNOT_OPEN_FILE, loc);
          addError(err);
        } else {
          Location includeFile(m_includer->m_fileId, m_includerLine, 0,
                               m_fileId);
          Error err(ErrorDefinition::PP_CANNOT_OPEN_INCLUDE_FILE, includeFile);
          addError(err);
        }
        return false;
      }
      // Remove ^M (DOS) from text file
      std::string text;
      char c = stream.get();
      while (stream.good()) {
        if (c != 0x0D)
          text+=c;
        c = stream.get();
      }
      stream.close();
      
      try {
        m_antlrParserHandler->m_inputStream = new ANTLRInputStream(text);
      } catch (...) {
        Location loc(0);
        if (m_includer == NULL) {
          Location file(m_fileId);
          loc = file;
        } else {
          Location includeFile(m_includer->m_fileId, m_includerLine, 0,
                               m_fileId);
          loc = includeFile;
        }
        Error err(ErrorDefinition::PP_CANNOT_READ_FILE_CONTENT, loc);
        addError(err);
        return false;
      }
    }
    m_antlrParserHandler->m_errorListener =
        new PreprocessFile::DescriptiveErrorListener(
            this, (m_macroBody == "") ? fileName : "in macro " + fileName);
    m_antlrParserHandler->m_pplexer =
        new SV3_1aPpLexer(m_antlrParserHandler->m_inputStream);
    m_antlrParserHandler->m_pplexer->removeErrorListeners();
    m_antlrParserHandler->m_pplexer->addErrorListener(
        m_antlrParserHandler->m_errorListener);
    m_antlrParserHandler->m_pptokens =
        new CommonTokenStream(m_antlrParserHandler->m_pplexer);
    m_antlrParserHandler->m_pptokens->fill();

    if (m_debugPPTokens) {
      std::cout << "PP TOKENS: " << std::endl;
      for (auto token : m_antlrParserHandler->m_pptokens->getTokens()) {
        std::cout << token->toString() << std::endl;
      }
    }

    m_antlrParserHandler->m_ppparser =
        new SV3_1aPpParser(m_antlrParserHandler->m_pptokens);
    m_antlrParserHandler->m_ppparser->getInterpreter<atn::ParserATNSimulator>()
        ->setPredictionMode(atn::PredictionMode::SLL);
    m_antlrParserHandler->m_ppparser->removeErrorListeners();
    m_antlrParserHandler->m_ppparser->setErrorHandler(
        std::make_shared<BailErrorStrategy>());
    try {
      m_antlrParserHandler->m_pptree =
          m_antlrParserHandler->m_ppparser->source_text();
    } catch (ParseCancellationException& pex) {
      m_antlrParserHandler->m_pptokens->reset();
      m_antlrParserHandler->m_ppparser->reset();
      m_antlrParserHandler->m_ppparser->addErrorListener(
          m_antlrParserHandler->m_errorListener);
      m_antlrParserHandler->m_ppparser->setErrorHandler(
          std::make_shared<DefaultErrorStrategy>());
      m_antlrParserHandler->m_ppparser
          ->getInterpreter<atn::ParserATNSimulator>()
          ->setPredictionMode(atn::PredictionMode::LL);
      m_antlrParserHandler->m_pptree =
          m_antlrParserHandler->m_ppparser->source_text();
    }

    if (m_debugPPTree)
      std::cout << "PP TREE: "
                << m_antlrParserHandler->m_pptree->toStringTree(
                       m_antlrParserHandler->m_ppparser)
                << std::endl
                << std::endl;

    getCompileSourceFile()->registerAntlrPpHandlerForId(
        (m_macroBody == "") ? m_fileId : getMacroSignature(),
        m_antlrParserHandler);
  }
  if (m_listener == NULL)
    m_listener = new SV3_1aPpTreeShapeListener(this, m_instructions);
  tree::ParseTreeWalker::DEFAULT.walk(m_listener,
                                      m_antlrParserHandler->m_pptree);

  return true;
}

unsigned int PreprocessFile::getSumLineCount() {
  unsigned int total = m_lineCount;
  if (m_includer) total += m_includer->getSumLineCount();
  return total;
}

static unsigned int LinesCount(const std::string& s) {
  return std::count(s.begin(), s.end(), '\n');
}

void PreprocessFile::append(const std::string& s) {
  if (!m_pauseAppend) {
    m_lineCount += LinesCount(s);
    m_result += s;
  }
}

void PreprocessFile::recordMacro(const std::string name, unsigned int line,
                                 unsigned short int column,
                                 const std::string arguments,
                                 const std::vector<std::string> tokens) {
  // *** Argument processing
  std::string arguments_short = arguments;
  // Remove (
  size_t p = arguments_short.find('(');
  if (p != string::npos) {
    arguments_short.erase(p, 1);
  }
  // Remove )
  p = arguments_short.find(')');
  if (p != string::npos) {
    arguments_short.erase(p, 1);
  }
  // Tokenize args
  std::vector<std::string> args;
  StringUtils::tokenize(arguments_short, ",", args);

  if (m_debugMacro) {
    std::string body;
    for (auto token : tokens) {
      body += token;
    }
    std::cout << "PP RECORDING MACRO: " << name << ": | " << body << " | "
              << endl;
  }

  // std::cout << "PP RECORDING MACRO: " << name  << ", FILE: " <<
  // getSymbol(getFileId(line)) << "" << endl;

  MacroInfo* macroInfo = new MacroInfo(
      name, arguments.size() ? MacroInfo::WITH_ARGS : MacroInfo::NO_ARGS,
      getFileId(line), line, column, args, tokens);
  m_macros.insert(std::make_pair(name, macroInfo));
  m_compilationUnit->registerMacroInfo(name, macroInfo);
  checkMacroArguments_(name, line, column, args, tokens);
}

std::string PreprocessFile::reportIncludeInfo() {
  std::string report;
  for (auto info : m_includeFileInfo) {
    std::string type = (info.m_type == 1) ? "in" : "out";
    report += std::to_string(info.m_originalLine) + " " +
              getSymbol(info.m_sectionFile) + " " +
              std::to_string(info.m_sectionStartLine) + " " + type + "\n";
  }

  return report;
}

void PreprocessFile::recordMacro(const std::string name, unsigned int line,
                                 unsigned short int column,
                                 const std::vector<std::string> arguments,
                                 const std::vector<std::string> tokens) {
  MacroInfo* macroInfo = new MacroInfo(
      name, arguments.size() ? MacroInfo::WITH_ARGS : MacroInfo::NO_ARGS,
      getFileId(line), line, column, arguments, tokens);
  m_macros.insert(std::make_pair(name, macroInfo));
  m_compilationUnit->registerMacroInfo(name, macroInfo);
}

void PreprocessFile::checkMacroArguments_(
    const std::string& name, unsigned int line, unsigned short column,
    const std::vector<std::string>& arguments,
    const std::vector<std::string>& tokens) {
  std::set<std::string> argSet;
  std::set<std::string> tokenSet;
  for (auto s : arguments) {
    argSet.insert(
        StringUtils::trim(StringUtils::rtrimEqual(StringUtils::trim(s))));
  }
  for (auto s : tokens) {
    tokenSet.insert(StringUtils::trim(s));
  }
  for (auto s : argSet) {
    if (tokenSet.find(s) == tokenSet.end() &&
        tokenSet.find("``" + s + "``") == tokenSet.end() &&
        tokenSet.find(s + "``") == tokenSet.end()) {
      Location loc(m_fileId, line, column, registerSymbol(s));
      Error err(ErrorDefinition::PP_MACRO_UNUSED_ARGUMENT, loc);
      addError(err);
    }
  }
  for (unsigned int i = 0; i < tokens.size(); i++) {
    std::string s1 = tokens[i];
    std::string s2 = tokens[i];
    bool check = false;
    if ((s1.find("``") != std::string::npos) && (s1 != "``"))  // ``a``
    {
      s1 = std::regex_replace(s1, std::regex("``"), "");
      s2 = s1;
      check = true;
    } else if (s1 == "``") {
      if (i > 0) s1 = tokens[i - 1];
      s1 = StringUtils::trim(s1);
      s2 = tokens[i + 1];
      s2 = StringUtils::trim(s2);
      check = true;
    }
    if (check) {
      if ((argSet.find(s1) == argSet.end()) &&
          (argSet.find(s2) == argSet.end())) {
        for (auto s : {s1, s2}) {
          if (argSet.find(s) == argSet.end()) {
            if (s.find("`") != std::string::npos) continue;
            if (s.find("//") != std::string::npos) continue;
            if (!std::isalpha(s[0])) continue;
            Location loc(m_fileId, line, column, registerSymbol(s));
            Error err(ErrorDefinition::PP_MACRO_UNDEFINED_ARGUMENT, loc);
            addError(err);
          }
        }
      }
    }
  }
}

SymbolId PreprocessFile::getIncluderFileId(unsigned int line) {
  PreprocessFile* tmp = this;
  while (tmp->m_includer != NULL) {
    tmp = tmp->m_includer;
  }
  return tmp->getFileId(line);
}

PreprocessFile* PreprocessFile::getSourceFile() {
  PreprocessFile* tmp = this;
  while (tmp->m_includer != NULL) {
    tmp = tmp->m_includer;
  }
  return tmp;
}

void PreprocessFile::forgetPreprocessor_(PreprocessFile* inc,
                                         PreprocessFile* pp) {
  for (std::vector<PreprocessFile*>::iterator itr = inc->m_includes.begin();
       itr != inc->m_includes.end(); itr++) {
    if ((*itr) == pp) {
      inc->m_includes.erase(itr);
      break;
    }
  }
}

SymbolId PreprocessFile::registerSymbol(const std::string symbol) {
  return getCompileSourceFile()->getSymbolTable()->registerSymbol(symbol);
}

SymbolId PreprocessFile::getId(const std::string symbol) {
  return getCompileSourceFile()->getSymbolTable()->getId(symbol);
}

std::string PreprocessFile::evaluateMacroInstance(
    const std::string macro_instance, PreprocessFile* callingFile,
    unsigned int callingLine,
    SpecialInstructions::CheckLoopInstr checkMacroLoop,
    SpecialInstructions::AsIsUndefinedMacroInstr asisUndefMacro) {
  std::string result;
  // SymbolId macroArgs = registerSymbol (macro_instance);
  SpecialInstructions instructions(
      SpecialInstructions::Mute, SpecialInstructions::Mark,
      SpecialInstructions::Filter, checkMacroLoop, asisUndefMacro);
  PreprocessFile* pp = new PreprocessFile(
      0, /*macroArgs,*/ NULL,
      0 /*m_includer ? m_includer : callingFile, callingLine*/,
      m_compileSourceFile, instructions,
      m_includer ? m_includer->m_compilationUnit
                 : callingFile->m_compilationUnit,
      callingFile->m_library, macro_instance);
  if (!pp->preprocess()) {
    result = MacroNotDefined;
  } else {
    result = pp->getPreProcessedFileContent();
  }
  forgetPreprocessor_(m_includer ? m_includer : callingFile, pp);
  delete pp;
  return result;
}

std::pair<bool, std::string> PreprocessFile::evaluateMacro_(
    const std::string name, std::vector<std::string>& actual_args,
    PreprocessFile* callingFile, unsigned int callingLine,
    LoopCheck& loopChecker, MacroInfo* macroInfo,
    SpecialInstructions& instructions, unsigned int embeddedMacroCallLine,
    SymbolId embeddedMacroCallFile) {
  std::string result;
  bool found = false;
  std::vector<std::string>& formal_args = macroInfo->m_arguments;
  // Don't modify the actual tokens of the macro, make a copy...
  std::vector<std::string> body_tokens = macroInfo->m_tokens;

  if (instructions.m_check_macro_loop) {
    bool loop = loopChecker.addEdge(callingFile->m_fileId, getId(name));
    if (loop) {
      std::vector<SymbolId> loop = loopChecker.reportLoop();
      for (auto id : loop) {
        MacroInfo* macroInfo2 = m_compilationUnit->getMacroInfo(getSymbol(id));
        if (macroInfo2) {
          Location loc(macroInfo2->m_file, macroInfo2->m_line, 0, id);
          Location exloc(macroInfo->m_file, macroInfo->m_line, 0, getId(name));
          Error err(ErrorDefinition::PP_RECURSIVE_MACRO_DEFINITION, loc, exloc);
          addError(err);
          return std::make_pair(false, getCompileSourceFile()
                                           ->getCompiler()
                                           ->getSymbolTable()
                                           ->getBadSymbol());
        }
      }
    }
  }

  StringUtils::replaceInTokenVector(body_tokens, "`\"", "\"");
  StringUtils::replaceInTokenVector(body_tokens, "`\\`\"", "\\\"");

  // argument substitution
  for (unsigned int i = 0; i < actual_args.size(); i++) {
    if (actual_args[i].find('`') != std::string::npos) {
      actual_args[i] = evaluateMacroInstance(
          actual_args[i], callingFile, callingLine,
          SpecialInstructions::CheckLoop,
          SpecialInstructions::AsIsUndefinedMacroInstr::ComplainUndefinedMacro);
    }
  }
  
  if ((actual_args.size() > formal_args.size() && (!m_instructions.m_mute))) {
    if (formal_args.size() == 0 &&
        (StringUtils::getFirstNonEmptyToken(body_tokens) == "(")) {
      Location loc(macroInfo->m_file, macroInfo->m_line,
                   macroInfo->m_column + name.size() + 1, getId(name));
      Error err(ErrorDefinition::PP_MACRO_HAS_SPACE_BEFORE_ARGS, loc);
      addError(err);
    } else {
      if (!Waiver::macroArgCheck(name)) {
        Location loc(callingFile->getFileId(callingLine),
                     callingFile->getLineNb(callingLine), 0, getId(name));
        Location arg(0, 0, 0,
                     registerSymbol(std::to_string(actual_args.size())));
        Location def(macroInfo->m_file, macroInfo->m_line, 0,
                     registerSymbol(std::to_string(formal_args.size())));
        std::vector<Location> locs = {arg, def};
        Error err(ErrorDefinition::PP_TOO_MANY_ARGS_MACRO, loc, &locs);
        addError(err);
      }
    }
  }

  for (unsigned int i = 0; i < formal_args.size(); i++) {
    std::vector<std::string> formal_arg_default;
    StringUtils::tokenize(formal_args[i], "=", formal_arg_default);
    std::string formal =
        std::regex_replace(formal_arg_default[0], std::regex("[ \t]*"), "");
    bool empty_actual = true;
    if (i < actual_args.size()) {
      for (unsigned int ii = 0; ii < actual_args[i].size(); ii++) {
        if (actual_args[i][ii] != ' ') {
          empty_actual = false;
          break;
        }
      }
    }
    if (!empty_actual) {
      if (actual_args[i] == SymbolTable::getEmptyMacroMarker()) {
        actual_args[i] = "";
      }

      StringUtils::replaceInTokenVector(body_tokens, {"``", formal, "``"},
                                        actual_args[i]);
      StringUtils::replaceInTokenVector(body_tokens, "``" + formal + "``",
                                        actual_args[i]);
      StringUtils::replaceInTokenVector(body_tokens, {formal, "``"},
                                        actual_args[i]);
      StringUtils::replaceInTokenVector(body_tokens, {"``", formal},
                                        actual_args[i]);
      StringUtils::replaceInTokenVector(body_tokens, {formal, " ", "``"},
                                        actual_args[i]);
      StringUtils::replaceInTokenVector(body_tokens, formal + "``",
                                        actual_args[i]);
      StringUtils::replaceInTokenVector(body_tokens, formal, actual_args[i]);
    } else {
      if (formal_arg_default.size() == 2) {
        std::string default_val =
            std::regex_replace(formal_arg_default[1], std::regex("[ \t]*"), "");
        StringUtils::replaceInTokenVector(body_tokens, {"``", formal, "``"},
                                          default_val);
        StringUtils::replaceInTokenVector(body_tokens, "``" + formal + "``",
                                          default_val);
        StringUtils::replaceInTokenVector(body_tokens, {formal, "``"},
                                          default_val);
        StringUtils::replaceInTokenVector(body_tokens, {"``", formal},
                                          default_val);
        StringUtils::replaceInTokenVector(body_tokens, {formal, " ", "``"},
                                          default_val);
        StringUtils::replaceInTokenVector(body_tokens, formal + "``",
                                          default_val);
        StringUtils::replaceInTokenVector(body_tokens, formal, default_val);
      } else {
        StringUtils::replaceInTokenVector(body_tokens, {"``", formal, "``"},
                                          "");
        StringUtils::replaceInTokenVector(body_tokens, "``" + formal + "``",
                                          "");
        StringUtils::replaceInTokenVector(body_tokens, {formal, "``"}, "");
        StringUtils::replaceInTokenVector(body_tokens, {"``", formal}, "");
        StringUtils::replaceInTokenVector(body_tokens, {formal, " ", "``"}, "");
        StringUtils::replaceInTokenVector(body_tokens, formal + "``", "");
        StringUtils::replaceInTokenVector(body_tokens, formal, "");

        if ((int)i > (int)(((int)actual_args.size()) - 1)) {
          if (!instructions.m_mute) {
            Location loc(callingFile->getFileId(callingLine),
                         callingFile->getLineNb(callingLine), 0, getId(name));
            SymbolId id =
                registerSymbol(std::to_string(i + 1) + " (" + formal + ")");
            Location arg(0, 0, 0, id);
            Location def(macroInfo->m_file, macroInfo->m_line, 0, id);
            std::vector<Location> locs = {arg, def};
            Error err(ErrorDefinition::PP_MACRO_NO_DEFAULT_VALUE, loc, &locs);
            addError(err);
          }
        }
      }
    }
  }

  std::string body;
  for (auto token : body_tokens) {
    body += token;
  }

  // *** Body processing
  std::string body_short = body;
  // Replace \\n by \n

  for (string::iterator itr = body_short.end(); itr != body_short.begin();
       itr--) {
    if ((*itr) == '\n') {
      if ((itr != body_short.begin()) && (*(itr - 1) == '\\')) {
        body_short.erase(itr - 1);
      }
    }
  }

  // Truncate trailing carriage returns (up to 2)

  for (int i = 0; i < 2; i++) {
    if (body_short.size()) {
      if (body_short.at(body_short.size() - 1) == '\n') {
        body_short.erase(body_short.size() - 1);
      } else {
        break;
      }
    }
  }

  // If it is a Multiline macro, insert a \n at the end

  if (body_short.find('\n') != string::npos) {
    body_short.push_back('\n');
  }

  if (body_short.find('`') != std::string::npos) {
    // Recursively resolve macro instantiation within the macro
    if (m_debugMacro) {
      const std::string fileName = getSymbol(m_fileId);
      std::cout << "PP BODY EXPANSION FOR " << name << " in : " << fileName
                << std::endl;
      for (auto arg : actual_args) {
        std::cout << "PP ARG: " << arg << "\n";
      }
    }
    SymbolId macroId = registerSymbol(name);
    SpecialInstructions instructions(
        m_instructions.m_mute, SpecialInstructions::DontMark,
        SpecialInstructions::Filter, m_instructions.m_check_macro_loop,
        m_instructions.m_as_is_undefined_macro);
    PreprocessFile* pp = new PreprocessFile(
        macroId, callingFile ? callingFile : m_includer, callingLine,
        m_compileSourceFile, instructions,
        callingFile ? callingFile->m_compilationUnit
                    : m_includer->m_compilationUnit,
        callingFile ? callingFile->m_library : m_includer->m_library,
        body_short, macroInfo, embeddedMacroCallLine, embeddedMacroCallFile);
    getCompileSourceFile()->registerPP(pp);
    if (!pp->preprocess()) {
      result = MacroNotDefined;
    } else {
      std::string pp_result = pp->getPreProcessedFileContent();

      if (callingLine && callingFile && !callingFile->isMacroBody()) {
        pp_result = std::regex_replace(
            pp_result, std::regex(PP__File__Marking),
            "\"" +
                FileUtils::getFullPath(callingFile->getFileName(callingLine)) +
                "\"");
        pp_result = std::regex_replace(pp_result, std::regex(PP__Line__Marking),
                                       std::to_string(callingLine));
      }
      result = pp_result;
      found = true;
    }
  } else {
    result = body_short;
    found = true;
  }
  return std::make_pair(found, result);
}

MacroInfo* PreprocessFile::getMacro(const std::string name) {
  registerSymbol(name);
  return m_compilationUnit->getMacroInfo(name);
}

bool PreprocessFile::deleteMacro(const std::string name,
                                 std::set<PreprocessFile*>& visited) {
  /*SymbolId macroId = */ registerSymbol(name);
  if (m_debugMacro)
    std::cout << "PP CALL TO deleteMacro for " << name << std::endl;
  bool found = false;
  // Try CommandLine overrides
  // const std::map<SymbolId,std::string>& defines =
  // m_compileSourceFile->m_commandLineParser->getDefineList();
  // std::map<SymbolId,std::string>::const_iterator itMap =
  // defines.find(macroId);
  // if (itMap != defines.end())
  //  {
  //    result = (*itMap).second;
  //    found = true;
  //  }

  // Try local file scope
  if (found == false) {
    MacroStorage::iterator itr = m_macros.find(name);
    if (itr != m_macros.end()) {
      m_macros.erase(itr);
      m_compilationUnit->deleteMacro(name);
      found = true;
    }
  }
  // Try in included files
  if (found == false) {
    for (std::vector<PreprocessFile*>::iterator iitr = m_includes.begin();
         iitr != m_includes.end(); iitr++) {
      PreprocessFile* pFile = *iitr;
      if (visited.find(pFile) == visited.end()) {
        visited.insert(pFile);
        bool tmp = pFile->deleteMacro(name, visited);
        if (tmp == true) {
          found = true;
          break;
        }
      }
    }
  }
  // Try in file that included this file
  if (found == false) {
    if (m_includer) {
      if (visited.find(m_includer) == visited.end()) {
        visited.insert(m_includer);
        bool tmp = m_includer->deleteMacro(name, visited);
        if (tmp == true) {
          found = true;
        }
      }
    }
  }
  return found;
}

void PreprocessFile::undefineAllMacros(std::set<PreprocessFile*>& visited) {
  if (m_debugMacro) std::cout << "PP CALL TO undefineAllMacros" << std::endl;
  m_macros.clear();
  m_compilationUnit->deleteAllMacros();

  for (std::vector<PreprocessFile*>::iterator iitr = m_includes.begin();
       iitr != m_includes.end(); iitr++) {
    PreprocessFile* pFile = *iitr;
    if (visited.find(pFile) == visited.end()) {
      visited.insert(pFile);
      pFile->undefineAllMacros(visited);
    }
  }

  if (m_includer) {
    if (visited.find(m_includer) == visited.end()) {
      visited.insert(m_includer);
      m_includer->undefineAllMacros(visited);
    }
  }
}

std::string PreprocessFile::getMacro(
    const std::string name, std::vector<std::string>& arguments,
    PreprocessFile* callingFile, unsigned int callingLine,
    LoopCheck& loopChecker, SpecialInstructions& instructions,
    unsigned int embeddedMacroCallLine, SymbolId embeddedMacroCallFile) {
  SymbolId macroId = registerSymbol(name);
  if (m_debugMacro) {
    std::cout << "PP CALL TO getMacro for " << name << "\n";
    for (auto arg : arguments) {
      std::cout << "PP ARG: " << arg << "\n";
    }
    instructions.print();
  }
  std::string result;
  bool found = false;
  // Try CommandLine overrides
  const std::map<SymbolId, std::string>& defines =
      m_compileSourceFile->m_commandLineParser->getDefineList();
  std::map<SymbolId, std::string>::const_iterator itMap = defines.find(macroId);
  if (itMap != defines.end()) {
    result = (*itMap).second;
    found = true;
  }

  // Try local file scope
  if (found == false) {
    MacroInfo* info = m_compilationUnit->getMacroInfo(name);
    if (info) {
      std::pair<bool, std::string> evalResult = evaluateMacro_(
          name, arguments, callingFile, callingLine, loopChecker, info,
          instructions, embeddedMacroCallLine, embeddedMacroCallFile);
      found = evalResult.first;
      result = evalResult.second;
      result = std::regex_replace(result, std::regex("``"), "");
    }
  }
  if (found == false) {
    if (instructions.m_as_is_undefined_macro ==
        SpecialInstructions::AsIsUndefinedMacro) {
      return "`" + name;
    } else {
      return MacroNotDefined;
    }
  } else {
    return result;
  }
}

SymbolId PreprocessFile::getFileId(unsigned int line) {
  const unsigned int size = m_lineTranslationVec.size();
  if (isMacroBody() && m_macroInfo) {
    return m_macroInfo->m_file;
  } else {
    if (size) {
      if (size == 1) {
        if (line >= m_lineTranslationVec[0].m_originalLine) {
          return (m_lineTranslationVec[0].m_pretendFileId);
        }
      } else {
        for (unsigned int i = size - 1; i >= 0; i--) {
          if (line >= m_lineTranslationVec[i].m_originalLine) {
            return (m_lineTranslationVec[i].m_pretendFileId);
          }
        }
      }
      return m_fileId;
    } else {
      return m_fileId;
    }
  }
}

unsigned int PreprocessFile::getLineNb(unsigned int line) {
  if (isMacroBody() && m_macroInfo) {
    return (m_macroInfo->m_line + line - 1);
  } else {
    if (m_lineTranslationVec.size()) {
      for (unsigned int i = m_lineTranslationVec.size() - 1; i >= 0; i--) {
        if (line >= m_lineTranslationVec[i].m_originalLine) {
          return (m_lineTranslationVec[i].m_pretendLine +
                  (line - m_lineTranslationVec[i].m_originalLine));
        }
      }
      return line;
    } else {
      return line;
    }
  }
}

std::string PreprocessFile::getPreProcessedFileContent() {
  // If File is empty (Only CR) return an empty string
  bool nonEmpty = false;
  unsigned int pp_result_size = m_result.size();
  for (unsigned int i = 0; i < pp_result_size; i++) {
    if ((m_result[i] != '\n') && (m_result[i] != ' ')) {
      nonEmpty = true;
      break;
    }
  }
  if (!nonEmpty) m_result = "";
  if (m_debugPPResult) {
    const std::string fileName = getSymbol(m_fileId);
    std::string objName =
        (m_macroBody != "") ? "macro " + m_macroBody : "file " + fileName;
    std::cout << "PP RESULT for " << objName
              << " : \nvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"
              << m_result << "\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
              << std::endl;
  }
  return m_result;
}

PreprocessFile::IfElseStack& PreprocessFile::getStack() {
  PreprocessFile* tmp = this;
  while (tmp->m_includer != NULL) {
    tmp = tmp->m_includer;
  }
  // std::cout << "STACK FOR: " << tmp->m_fileName << std::endl;
  return tmp->m_ifStack;
}

void PreprocessFile::collectIncludedFiles(std::set<PreprocessFile*>& included) {
  for (std::vector<PreprocessFile*>::iterator itr = m_includes.begin();
       itr != m_includes.end(); itr++) {
    if (!(*itr)->isMacroBody()) {
      included.insert(*itr);
    }
    (*itr)->collectIncludedFiles(included);
  }
}

void PreprocessFile::saveCache() {
  if (m_macroBody == "") {
    if (!m_usingCachedVersion) {
      PPCache cache(this);
      cache.save();
    }
  }
  for (std::vector<PreprocessFile*>::iterator itr = m_includes.begin();
       itr != m_includes.end(); itr++) {
    (*itr)->saveCache();
  }
}
