| /* |
| 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.h |
| * Author: alain |
| * |
| * Created on February 24, 2017, 9:37 PM |
| */ |
| |
| #ifndef PREPROCESSFILE_H |
| #define PREPROCESSFILE_H |
| #include <string> |
| #include <vector> |
| #include <map> |
| #include <set> |
| #include <stack> |
| |
| #include "parser/SV3_1aPpLexer.h" |
| #include "parser/SV3_1aPpParser.h" |
| #include "SourceCompile/CompilationUnit.h" |
| #include "Library/Library.h" |
| #include "SourceCompile/LoopCheck.h" |
| #include "SourceCompile/IncludeFileInfo.h" |
| |
| namespace SURELOG { |
| |
| class SV3_1aPpTreeShapeListener; |
| class CompileSourceFile; |
| |
| #define LINE1 1 |
| |
| /* Can be either an include file or a macro definition being evaluated */ |
| class PreprocessFile { |
| public: |
| class SpecialInstructions; |
| class DescriptiveErrorListener; |
| |
| /* Constructors */ |
| PreprocessFile(SymbolId fileId, CompileSourceFile* csf, |
| SpecialInstructions& instructions, |
| CompilationUnit* compilationUnit, Library* library); |
| PreprocessFile(SymbolId fileId, PreprocessFile* includedIn, |
| unsigned int includerLine, CompileSourceFile* csf, |
| SpecialInstructions& instructions, |
| CompilationUnit* compilationUnit, Library* library, |
| std::string macroBody = "", MacroInfo* = NULL, |
| unsigned int embeddedMacroCallLine = 0, |
| SymbolId embeddedMacroCallFile = 0); |
| PreprocessFile(const PreprocessFile& orig); |
| virtual ~PreprocessFile(); |
| |
| /* Main function */ |
| bool preprocess(); |
| std::string getPreProcessedFileContent(); |
| |
| /* Macro manipulations */ |
| void recordMacro(const std::string name, unsigned int line, |
| unsigned short int column, |
| const std::string formal_arguments, |
| const std::vector<std::string> body); |
| void recordMacro(const std::string name, unsigned int line, |
| unsigned short int column, |
| const std::vector<std::string> formal_arguments, |
| const std::vector<std::string> body); |
| std::string getMacro(const std::string name, |
| std::vector<std::string>& actual_arguments, |
| PreprocessFile* callingFile, unsigned int callingLine, |
| LoopCheck& loopChecker, |
| SpecialInstructions& instructions, |
| unsigned int embeddedMacroCallLine = 0, |
| SymbolId embeddedMacroCallFile = 0); |
| bool deleteMacro(const std::string name, std::set<PreprocessFile*>& visited); |
| void undefineAllMacros(std::set<PreprocessFile*>& visited); |
| bool isMacroBody() { return (m_macroBody != ""); } |
| std::string getMacroBody() { return m_macroBody; } |
| MacroInfo* getMacroInfo() { return m_macroInfo; } |
| SymbolId getMacroSignature(); |
| const MacroStorage& getMacros() { return m_macros; } |
| MacroInfo* getMacro(const std::string name); |
| |
| const std::string getFileName(unsigned int line); |
| |
| std::string reportIncludeInfo(); |
| |
| CompileSourceFile* getCompileSourceFile() { return m_compileSourceFile; } |
| CompilationUnit* getCompilationUnit() { return m_compilationUnit; } |
| Library* getLibrary() { return m_library; } |
| antlr4::CommonTokenStream* getTokenStream() { |
| return m_antlrParserHandler ? m_antlrParserHandler->m_pptokens : NULL; |
| } |
| |
| SymbolId getFileId(unsigned int line); |
| SymbolId getIncluderFileId(unsigned int line); |
| SymbolId getRawFileId() { return m_fileId; } |
| unsigned int getLineNb(unsigned int line); |
| PreprocessFile* getIncluder() { return m_includer; } |
| unsigned int getIncluderLine() { return m_includerLine; } |
| unsigned int getLineCount() { return m_lineCount; } |
| unsigned int getSumLineCount(); |
| std::vector<IncludeFileInfo>& getIncludeFileInfo() { |
| return m_includeFileInfo; |
| } |
| IncludeFileInfo& getIncludeFileInfo(int index) { |
| if (index >= 0 && index < ((int)m_includeFileInfo.size())) |
| return m_includeFileInfo[index]; |
| else |
| return m_badIncludeFileInfo; |
| } |
| unsigned int getEmbeddedMacroCallLine() { return m_embeddedMacroCallLine; } |
| SymbolId getEmbeddedMacroCallFile() { return m_embeddedMacroCallFile; } |
| |
| /* Markings */ |
| static std::string MacroNotDefined; |
| static std::string PP__Line__Marking; |
| static std::string PP__File__Marking; |
| |
| private: |
| SymbolId m_fileId; |
| Library* m_library; |
| std::string m_result; |
| std::string m_macroBody; |
| PreprocessFile* m_includer; |
| unsigned int m_includerLine; |
| std::vector<PreprocessFile*> m_includes; |
| CompileSourceFile* m_compileSourceFile; |
| unsigned int m_lineCount; |
| IncludeFileInfo m_badIncludeFileInfo; |
| |
| public: |
| /* Instructions passed from calling scope */ |
| class SpecialInstructions { |
| public: |
| enum TraceInstr : bool { Mute = true, DontMute = false }; |
| enum EmptyMacroInstr : bool { Mark = true, DontMark = false }; |
| enum FileLineInfoInstr : bool { Filter = true, DontFilter = false }; |
| enum CheckLoopInstr : bool { CheckLoop = true, DontCheckLoop = false }; |
| enum AsIsUndefinedMacroInstr : bool { |
| AsIsUndefinedMacro = true, |
| ComplainUndefinedMacro = false |
| }; |
| enum EvaluateInstr : bool { Evaluate = true, DontEvaluate = false }; |
| SpecialInstructions() |
| : m_mute(DontMute), |
| m_mark_empty_macro(DontMark), |
| m_filterFileLine(DontFilter), |
| m_check_macro_loop(DontCheckLoop), |
| m_as_is_undefined_macro(ComplainUndefinedMacro), |
| m_evaluate(Evaluate){} |
| SpecialInstructions(SpecialInstructions& rhs) |
| : m_mute(rhs.m_mute), |
| m_mark_empty_macro(rhs.m_mark_empty_macro), |
| m_filterFileLine(rhs.m_filterFileLine), |
| m_check_macro_loop(rhs.m_check_macro_loop), |
| m_as_is_undefined_macro(rhs.m_as_is_undefined_macro), |
| m_evaluate(rhs.m_evaluate) {} |
| SpecialInstructions(TraceInstr mute, EmptyMacroInstr mark_empty_macro, |
| FileLineInfoInstr filterFileLine, |
| CheckLoopInstr check_macro_loop, |
| AsIsUndefinedMacroInstr as_is_undefined_macro, |
| EvaluateInstr evalaute = Evaluate) |
| : m_mute(mute), |
| m_mark_empty_macro(mark_empty_macro), |
| m_filterFileLine(filterFileLine), |
| m_check_macro_loop(check_macro_loop), |
| m_as_is_undefined_macro(as_is_undefined_macro), |
| m_evaluate(evalaute) {} |
| void print() { |
| std::cout << "Trace:" << (m_mute ? "Mute" : "DontMute") |
| << ", EmptyMacro:" << (m_mark_empty_macro ? "Mark" : "DontMark") |
| << ", FileLineInfo:" |
| << (m_filterFileLine ? "Filter " : "DontFilter") |
| << ", CheckLoop:" |
| << (m_check_macro_loop ? "CheckLoop" : "DontCheckLoop") |
| << ", AsIsUndefMacro:" |
| << (m_as_is_undefined_macro ? "AsIsUndefinedMacro" |
| : "ComplainUndefinedMacro") |
| << ", Evaluate:" |
| << (m_evaluate ? "Evaluate" : "DontEvaluate") |
| << std::endl; |
| }; |
| TraceInstr m_mute; |
| EmptyMacroInstr m_mark_empty_macro; |
| FileLineInfoInstr m_filterFileLine; |
| CheckLoopInstr m_check_macro_loop; |
| AsIsUndefinedMacroInstr m_as_is_undefined_macro; |
| EvaluateInstr m_evaluate; |
| }; |
| |
| std::string evaluateMacroInstance( |
| const std::string macro_instance, PreprocessFile* callingFile, |
| unsigned int callingLine, |
| SpecialInstructions::CheckLoopInstr checkMacroLoop, |
| SpecialInstructions::AsIsUndefinedMacroInstr); |
| |
| /* Incoming `line handling */ |
| class LineTranslationInfo { |
| public: |
| LineTranslationInfo(SymbolId pretendFileId, unsigned int originalLine, |
| unsigned int pretendLine) |
| : m_pretendFileId(pretendFileId), |
| m_originalLine(originalLine), |
| m_pretendLine(pretendLine) {} |
| SymbolId m_pretendFileId; |
| unsigned int m_originalLine; |
| unsigned int m_pretendLine; |
| }; |
| |
| /* `ifdef, `ifndef, `elsif, `else Stack */ |
| class IfElseItem { |
| public: |
| enum Type { IFDEF, IFNDEF, ELSIF, ELSE }; |
| std::string m_macroName; |
| bool m_defined; |
| Type m_type; |
| bool m_previousActiveState; |
| }; |
| typedef std::vector<IfElseItem> IfElseStack; |
| IfElseStack m_ifStack; |
| IfElseStack& getStack(); |
| |
| /* Antlr parser container */ |
| class AntlrParserHandler { |
| public: |
| AntlrParserHandler() |
| : m_inputStream(NULL), |
| m_pplexer(NULL), |
| m_pptokens(NULL), |
| m_ppparser(NULL), |
| m_pptree(NULL) {} |
| ~AntlrParserHandler(); |
| antlr4::ANTLRInputStream* m_inputStream; |
| SV3_1aPpLexer* m_pplexer; |
| antlr4::CommonTokenStream* m_pptokens; |
| SV3_1aPpParser* m_ppparser; |
| antlr4::tree::ParseTree* m_pptree; |
| DescriptiveErrorListener* m_errorListener; |
| }; |
| SV3_1aPpTreeShapeListener* m_listener; |
| |
| public: |
| /* Options */ |
| void setDebug(int level); |
| bool m_debugPP; |
| bool m_debugPPResult; |
| bool m_debugPPTokens; |
| bool m_debugPPTree; |
| bool m_debugMacro; |
| |
| SpecialInstructions m_instructions; |
| |
| /* To create the preprocessed content */ |
| void append(const std::string& s); |
| void pauseAppend() { m_pauseAppend = true; } |
| void resumeAppend() { m_pauseAppend = false; } |
| |
| void addLineTranslationInfo(LineTranslationInfo& info) { |
| m_lineTranslationVec.push_back(info); |
| } |
| |
| /* Shorthand for logging an error */ |
| void addError(Error& error); |
| |
| /* Shorthands for symbol manipulations */ |
| SymbolId registerSymbol(const std::string symbol); |
| SymbolId getId(const std::string symbol); |
| const std::string getSymbol(SymbolId id); |
| |
| // For recursive macro definition detection |
| PreprocessFile* getSourceFile(); |
| LoopCheck m_loopChecker; |
| |
| // For cache processing |
| void saveCache(); |
| void collectIncludedFiles(std::set<PreprocessFile*>& included); |
| bool usingCachedVersion() { return m_usingCachedVersion; } |
| std::string getProfileInfo() { return m_profileInfo; } |
| private: |
| std::pair<bool, std::string> evaluateMacro_( |
| const std::string name, std::vector<std::string>& arguments, |
| PreprocessFile* callingFile, unsigned int callingLine, |
| LoopCheck& loopChecker, MacroInfo* macroInfo, |
| SpecialInstructions& instructions, unsigned int embeddedMacroCallLine, |
| SymbolId embeddedMacroCallFile); |
| |
| void checkMacroArguments_(const std::string& name, unsigned int line, |
| unsigned short column, |
| const std::vector<std::string>& arguments, |
| const std::vector<std::string>& tokens); |
| void forgetPreprocessor_(PreprocessFile*, PreprocessFile* pp); |
| AntlrParserHandler* m_antlrParserHandler; |
| |
| MacroInfo* m_macroInfo; /* Only used when preprocessing a macro content */ |
| MacroStorage m_macros; |
| |
| CompilationUnit* m_compilationUnit; |
| std::vector<LineTranslationInfo> m_lineTranslationVec; |
| bool m_pauseAppend; |
| bool m_usingCachedVersion; |
| std::vector<IncludeFileInfo> m_includeFileInfo; |
| unsigned int m_embeddedMacroCallLine; |
| SymbolId m_embeddedMacroCallFile; |
| std::string m_profileInfo; |
| }; |
| |
| }; // namespace SURELOG |
| |
| #endif /* PREPROCESSFILE_H */ |