| /* |
| 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: CompileSourceFile.cpp |
| * Author: alain |
| * |
| * Created on February 20, 2017, 9:54 PM |
| */ |
| #include "../CommandLine/CommandLineParser.hpp" |
| #include "../ErrorReporting/ErrorContainer.h" |
| #include "SymbolTable.h" |
| #include "CompilationUnit.h" |
| #include "PreprocessFile.h" |
| #include "CompilationUnit.h" |
| |
| #include "antlr4-runtime.h" |
| using namespace antlr4; |
| #include "../parser/SV3_1aLexer.h" |
| #include "../parser/SV3_1aParser.h" |
| |
| #include "AntlrParserHandler.h" |
| |
| #include "CompileSourceFile.h" |
| #include "Compiler.h" |
| #include "../Utils/StringUtils.h" |
| #include "../Utils/FileUtils.h" |
| #include <cstdlib> |
| #include <iostream> |
| #include <fstream> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| using namespace std; |
| #include "PreprocessFile.h" |
| #include "ParseFile.h" |
| #include "../API/PythonAPI.h" |
| #include "PythonListen.h" |
| #include "../Package/Precompiled.h" |
| |
| using namespace SURELOG; |
| |
| CompileSourceFile::CompileSourceFile (SymbolId fileId, CommandLineParser* clp, ErrorContainer* errors, |
| Compiler* compiler, SymbolTable* symbols, CompilationUnit* compilationUnit, Library* library) : |
| m_fileId(fileId), m_commandLineParser(clp), m_errors(errors), m_compiler(compiler), m_pp(NULL), m_symbolTable(symbols), m_parser(NULL), |
| m_compilationUnit(compilationUnit), m_action(Preprocess), m_ppResultFileId(0), m_interpState(NULL), |
| m_pythonListener(NULL), m_fileAnalyzer(NULL), m_library(library) { |
| } |
| |
| CompileSourceFile::CompileSourceFile(CompileSourceFile* parent, SymbolId ppResultFileId, unsigned int lineOffset) : |
| m_fileId(parent->m_fileId), m_commandLineParser(parent->m_commandLineParser), m_errors(parent->m_errors), |
| m_compiler(parent->m_compiler), m_pp(parent->m_pp), m_symbolTable(NULL), m_parser(NULL), |
| m_compilationUnit(parent->m_compilationUnit), m_action(Parse), m_ppResultFileId(ppResultFileId), m_interpState(parent->m_interpState), |
| m_pythonListener(NULL), m_fileAnalyzer(parent->m_fileAnalyzer), m_library(parent->m_library) { |
| m_parser = new ParseFile(this, parent->m_parser, m_ppResultFileId, lineOffset); |
| } |
| |
| |
| bool CompileSourceFile::compile (Action action) |
| { |
| m_action = action; |
| if (m_commandLineParser->verbose ()) |
| { |
| Location loc (m_fileId); |
| ErrorDefinition::ErrorType type = ErrorDefinition::PP_PROCESSING_SOURCE_FILE; |
| switch (m_action) |
| { |
| case Preprocess: |
| case PostPreprocess: |
| type = ErrorDefinition::PP_PROCESSING_SOURCE_FILE; |
| break; |
| case Parse: |
| type = ErrorDefinition::PA_PROCESSING_SOURCE_FILE; |
| break; |
| case PythonAPI: |
| type = ErrorDefinition::PY_PROCESSING_SOURCE_FILE; |
| break; |
| } |
| if (action != PostPreprocess) |
| { |
| Error err (type, loc); |
| m_errors->printMessage(m_errors->addError(err, true)); |
| } |
| } |
| |
| switch (m_action) |
| { |
| case Preprocess: |
| return preprocess_(); |
| case PostPreprocess: |
| return postPreprocess_(); |
| case Parse: |
| return parse_(); |
| case PythonAPI: |
| return pythonAPI_(); |
| } |
| return true; |
| } |
| |
| CompileSourceFile::CompileSourceFile (const CompileSourceFile& orig) { } |
| |
| CompileSourceFile::~CompileSourceFile () { |
| std::vector<PreprocessFile*>::iterator itr; |
| for (itr = m_ppIncludeVec.begin(); itr != m_ppIncludeVec.end(); itr++) |
| { |
| delete *itr; |
| } |
| |
| if (m_parser) |
| delete m_parser; |
| |
| if (m_pythonListener) |
| delete m_pythonListener; |
| |
| std::map<SymbolId, PreprocessFile::AntlrParserHandler*>::iterator itr2; |
| for (itr2 = m_antlrPpMap.begin(); itr2 != m_antlrPpMap.end(); itr2++) { |
| delete (*itr2).second; |
| } |
| |
| } |
| |
| unsigned int |
| CompileSourceFile::getJobSize (Action action) |
| { |
| switch (action) |
| { |
| case Preprocess: |
| case PostPreprocess: |
| { |
| std::string fileName = getSymbolTable()->getSymbol(m_fileId); |
| return FileUtils::fileSize (fileName); |
| } |
| case Parse: |
| { |
| std::string fileName = getSymbolTable()->getSymbol(m_ppResultFileId); |
| return FileUtils::fileSize (fileName); |
| } |
| case PythonAPI: |
| { |
| std::string fileName = getSymbolTable()->getSymbol(m_ppResultFileId); |
| return FileUtils::fileSize (fileName); |
| } |
| }; |
| return 0; |
| } |
| |
| bool |
| CompileSourceFile::pythonAPI_ () |
| { |
| |
| if (getCommandLineParser ()->pythonListener ()) |
| { |
| m_pythonListener = new PythonListen (m_parser, this); |
| if (!m_pythonListener->listen ()) |
| { |
| return false; |
| } |
| bool fatalErrors = m_errors->hasFatalErrors (); |
| if (fatalErrors) |
| { |
| return false; |
| } |
| } |
| if (getCommandLineParser ()->pythonEvalScriptPerFile ()) |
| { |
| PythonAPI::evalScriptPerFile(getCommandLineParser ()->getSymbolTable ()->getSymbol (getCommandLineParser ()->pythonEvalScriptPerFileId()), |
| m_errors, m_parser->getFileContent (), m_interpState); |
| } |
| return true; |
| } |
| |
| bool CompileSourceFile::initParser() |
| { |
| if (m_parser == NULL) |
| m_parser = new ParseFile (m_fileId, this, m_compilationUnit, m_library, m_ppResultFileId, getCommandLineParser()->pythonListener()); |
| return true; |
| } |
| |
| bool |
| CompileSourceFile::parse_ () |
| { |
| initParser(); |
| if (!m_parser->parse ()) |
| { |
| return false; |
| } |
| bool fatalErrors = m_errors->hasFatalErrors(); |
| if (fatalErrors) |
| { |
| return false; |
| } |
| return true; |
| } |
| |
| bool CompileSourceFile::preprocess_() { |
| |
| Precompiled* prec = Precompiled::getSingleton (); |
| std::string root = getSymbolTable ()->getSymbol (m_fileId); |
| root = StringUtils::getRootFileName (root); |
| |
| |
| PreprocessFile::SpecialInstructions instructions(PreprocessFile::SpecialInstructions::DontMute, |
| PreprocessFile::SpecialInstructions::DontMark, |
| m_commandLineParser->filterFileLine () ? |
| PreprocessFile::SpecialInstructions::Filter : PreprocessFile::SpecialInstructions::DontFilter, |
| PreprocessFile::SpecialInstructions::CheckLoop, |
| PreprocessFile::SpecialInstructions::ComplainUndefinedMacro); |
| m_pp = new PreprocessFile (m_fileId, this, instructions, m_compilationUnit, m_library); |
| registerPP(m_pp); |
| |
| if (!m_pp->preprocess ()) |
| { |
| return false; |
| } |
| bool fatalErrors = m_errors->hasFatalErrors(); |
| if (fatalErrors) |
| { |
| return false; |
| } |
| |
| if (m_commandLineParser->getDebugIncludeFileInfo ()) |
| std::cout << m_pp->reportIncludeInfo (); |
| |
| if ((!m_commandLineParser->createCache()) && prec->isFilePrecompiled (root)) |
| return true; |
| |
| m_pp->saveCache(); |
| return true; |
| |
| } |
| |
| bool CompileSourceFile::postPreprocess_() { |
| std::string m_pp_result = m_pp->getPreProcessedFileContent (); |
| if (m_commandLineParser->writePpOutput () || (m_commandLineParser->writePpOutputFileId() != 0)) |
| { |
| SymbolTable* symbolTable = getCompiler()->getSymbolTable(); |
| const std::string& directory = symbolTable->getSymbol(m_commandLineParser->getFullCompileDir()); |
| std::string fileName = symbolTable->getSymbol(m_fileId); |
| std::string fullPath = FileUtils::getFullPath (fileName); |
| fileName = StringUtils::eliminateRelativePath(fileName); |
| const std::string& writePpOutputFileName = symbolTable->getSymbol( m_commandLineParser->writePpOutputFileId()); |
| std::string libName = m_library->getName () + "/"; |
| string ppFileName = m_commandLineParser->writePpOutput () ? directory + libName + fileName : writePpOutputFileName; |
| std::string dirPpFile = ppFileName; |
| StringUtils::rtrim (dirPpFile,'/'); |
| SymbolId ppOutId = symbolTable->registerSymbol(ppFileName); |
| m_ppResultFileId = m_symbolTable->registerSymbol (ppFileName); |
| SymbolId ppDirId = symbolTable->registerSymbol(dirPpFile); |
| |
| if (FileUtils::mkDir (dirPpFile.c_str()) != 0) |
| { |
| Location loc (ppDirId); |
| Error err(ErrorDefinition::PP_CANNOT_CREATE_DIRECTORY, loc); |
| m_errors->addError(err); |
| return false; |
| } |
| if ((!m_pp->usingCachedVersion ()) || (!FileUtils::fileExists(ppFileName))) |
| { |
| ofstream ofs; |
| ofs.open (ppFileName); |
| if (ofs.good ()) |
| { |
| ofs << m_pp_result; |
| ofs.close (); |
| } |
| else |
| { |
| Location loc (ppOutId); |
| Error err (ErrorDefinition::PP_OPEN_FILE_FOR_WRITE, loc); |
| m_errors->addError (err); |
| return false; |
| } |
| } |
| } |
| return true; |
| } |
| |
| void CompileSourceFile::registerAntlrPpHandlerForId(SymbolId id, PreprocessFile::AntlrParserHandler* pp) { |
| std::map<SymbolId, PreprocessFile::AntlrParserHandler*>::iterator itr = m_antlrPpMap.find(id); |
| if (itr != m_antlrPpMap.end()) |
| { |
| delete (*itr).second; |
| m_antlrPpMap.erase(itr); |
| m_antlrPpMap.insert(std::make_pair(id, pp)); |
| return; |
| } |
| m_antlrPpMap.insert(std::make_pair(id, pp)); |
| } |
| |
| PreprocessFile::AntlrParserHandler* CompileSourceFile::getAntlrPpHandlerForId(SymbolId id) { |
| std::map<SymbolId, PreprocessFile::AntlrParserHandler*>::iterator itr = m_antlrPpMap.find(id); |
| if (itr != m_antlrPpMap.end()) |
| { |
| PreprocessFile::AntlrParserHandler* ptr = (*itr).second; |
| return ptr; |
| } |
| return NULL; |
| } |
| |
| void CompileSourceFile::setSymbolTable(SymbolTable* symbols) |
| { |
| m_symbolTable = symbols; |
| } |
| |
| |
| void CompileSourceFile::setPythonInterp(PyThreadState* interpState) { |
| m_interpState = interpState; |
| m_errors->setPythonInterp(interpState); |
| } |
| |
| void CompileSourceFile::shutdownPythonInterp() { |
| m_errors->setPythonInterp(NULL); |
| PythonAPI::shutdown (m_interpState); |
| m_interpState = NULL; |
| } |
| |
| |
| |
| |