mirror of
				https://github.com/Laupetin/OpenAssetTools.git
				synced 2025-10-30 18:17:15 +00:00 
			
		
		
		
	Make DefinesProxy go over a line with defines substitution multiple times until no further substitution has been done
This commit is contained in:
		| @@ -26,7 +26,7 @@ DefinesStreamProxy::Define::Define(std::string name, std::string value) | ||||
| { | ||||
| } | ||||
|  | ||||
| std::string DefinesStreamProxy::Define::Render(std::vector<std::string>& parameterValues) | ||||
| std::string DefinesStreamProxy::Define::Render(const std::vector<std::string>& parameterValues) | ||||
| { | ||||
|     if (parameterValues.empty() || m_parameter_positions.empty()) | ||||
|         return m_value; | ||||
| @@ -52,7 +52,7 @@ std::string DefinesStreamProxy::Define::Render(std::vector<std::string>& paramet | ||||
|     return str.str(); | ||||
| } | ||||
|  | ||||
| void DefinesStreamProxy::Define::IdentifyParameters(std::vector<std::string>& parameterNames) | ||||
| void DefinesStreamProxy::Define::IdentifyParameters(const std::vector<std::string>& parameterNames) | ||||
| { | ||||
|     if (parameterNames.empty()) | ||||
|         return; | ||||
| @@ -168,7 +168,7 @@ bool DefinesStreamProxy::MatchDefineDirective(const ParserLine& line, unsigned d | ||||
|  | ||||
|     const auto name = line.m_line.substr(nameStartPos, directivePosition - nameStartPos); | ||||
|  | ||||
|     auto parameters = MatchDefineParameters(line, directivePosition); | ||||
|     const auto parameters = MatchDefineParameters(line, directivePosition); | ||||
|  | ||||
|     std::string value; | ||||
|     if (directivePosition < line.m_line.size()) | ||||
| @@ -346,77 +346,88 @@ void DefinesStreamProxy::ExtractParametersFromDefineUsage(const ParserLine& line | ||||
|  | ||||
| void DefinesStreamProxy::ExpandDefines(ParserLine& line) | ||||
| { | ||||
|     auto wordStart = 0u; | ||||
|     auto lastWordEnd = 0u; | ||||
|     auto inWord = false; | ||||
|     Define* value; | ||||
|     bool usesDefines; | ||||
|     auto defineIterations = 0u; | ||||
|  | ||||
|     std::ostringstream str; | ||||
|     auto usesDefines = false; | ||||
|  | ||||
|     for (auto i = 0u; i < line.m_line.size(); i++) | ||||
|     do | ||||
|     { | ||||
|         const auto c = line.m_line[i]; | ||||
|         if (!inWord) | ||||
|         if (defineIterations > MAX_DEFINE_ITERATIONS) | ||||
|             throw ParsingException(CreatePos(line, 1), "Potential define loop? Exceeded max define iterations of " + std::to_string(MAX_DEFINE_ITERATIONS) + " iterations."); | ||||
|  | ||||
|         usesDefines = false; | ||||
|  | ||||
|         auto wordStart = 0u; | ||||
|         auto lastWordEnd = 0u; | ||||
|         auto inWord = false; | ||||
|         Define* value; | ||||
|         std::ostringstream str; | ||||
|  | ||||
|         for (auto i = 0u; i < line.m_line.size(); i++) | ||||
|         { | ||||
|             if (isalpha(c) || c == '_') | ||||
|             const auto c = line.m_line[i]; | ||||
|             if (!inWord) | ||||
|             { | ||||
|                 wordStart = i; | ||||
|                 inWord = true; | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             if (!isalnum(c) && c != '_') | ||||
|             { | ||||
|                 if (FindDefineForWord(line, wordStart, i, value)) | ||||
|                 if (isalpha(c) || c == '_') | ||||
|                 { | ||||
|                     std::vector<std::string> parameterValues; | ||||
|                     ExtractParametersFromDefineUsage(line, i, i, parameterValues); | ||||
|                     const auto defineValue = value->Render(parameterValues); | ||||
|  | ||||
|                     if (!usesDefines) | ||||
|                     { | ||||
|                         str << std::string(line.m_line, 0, wordStart) << defineValue; | ||||
|                         usesDefines = true; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         str << std::string(line.m_line, lastWordEnd, wordStart - lastWordEnd) << defineValue; | ||||
|                     } | ||||
|                     lastWordEnd = i; | ||||
|                     wordStart = i; | ||||
|                     inWord = true; | ||||
|                 } | ||||
|                 inWord = false; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (inWord) | ||||
|     { | ||||
|         if (FindDefineForWord(line, wordStart, line.m_line.size(), value)) | ||||
|         { | ||||
|             std::vector<std::string> parameterValues; | ||||
|             const auto defineValue = value->Render(parameterValues); | ||||
|  | ||||
|             if (!usesDefines) | ||||
|             { | ||||
|                 str << std::string(line.m_line, 0, wordStart) << defineValue; | ||||
|                 usesDefines = true; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 str << std::string(line.m_line, lastWordEnd, wordStart - lastWordEnd) << defineValue; | ||||
|             } | ||||
|             lastWordEnd = line.m_line.size(); | ||||
|         } | ||||
|     } | ||||
|                 if (!isalnum(c) && c != '_') | ||||
|                 { | ||||
|                     if (FindDefineForWord(line, wordStart, i, value)) | ||||
|                     { | ||||
|                         std::vector<std::string> parameterValues; | ||||
|                         ExtractParametersFromDefineUsage(line, i, i, parameterValues); | ||||
|                         const auto defineValue = value->Render(parameterValues); | ||||
|  | ||||
|     if (usesDefines) | ||||
|     { | ||||
|         if (lastWordEnd < line.m_line.size()) | ||||
|             str << std::string(line.m_line, lastWordEnd, line.m_line.size() - lastWordEnd); | ||||
|         line.m_line = str.str(); | ||||
|     } | ||||
|                         if (!usesDefines) | ||||
|                         { | ||||
|                             str << std::string(line.m_line, 0, wordStart) << defineValue; | ||||
|                             usesDefines = true; | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             str << std::string(line.m_line, lastWordEnd, wordStart - lastWordEnd) << defineValue; | ||||
|                         } | ||||
|                         lastWordEnd = i; | ||||
|                     } | ||||
|                     inWord = false; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (inWord) | ||||
|         { | ||||
|             if (FindDefineForWord(line, wordStart, line.m_line.size(), value)) | ||||
|             { | ||||
|                 const std::vector<std::string> parameterValues; | ||||
|                 const auto defineValue = value->Render(parameterValues); | ||||
|  | ||||
|                 if (!usesDefines) | ||||
|                 { | ||||
|                     str << std::string(line.m_line, 0, wordStart) << defineValue; | ||||
|                     usesDefines = true; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     str << std::string(line.m_line, lastWordEnd, wordStart - lastWordEnd) << defineValue; | ||||
|                 } | ||||
|                 lastWordEnd = line.m_line.size(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (usesDefines) | ||||
|         { | ||||
|             if (lastWordEnd < line.m_line.size()) | ||||
|                 str << std::string(line.m_line, lastWordEnd, line.m_line.size() - lastWordEnd); | ||||
|             line.m_line = str.str(); | ||||
|         } | ||||
|  | ||||
|         defineIterations++; | ||||
|     } while (usesDefines); | ||||
| } | ||||
|  | ||||
| void DefinesStreamProxy::AddDefine(Define define) | ||||
|   | ||||
| @@ -15,6 +15,8 @@ class DefinesStreamProxy final : public AbstractDirectiveStreamProxy | ||||
|     static constexpr const char* ELSE_DIRECTIVE = "else"; | ||||
|     static constexpr const char* ENDIF_DIRECTIVE = "endif"; | ||||
|  | ||||
|     static constexpr auto MAX_DEFINE_ITERATIONS = 128u; | ||||
|  | ||||
| public: | ||||
|     class DefineParameterPosition | ||||
|     { | ||||
| @@ -35,8 +37,8 @@ public: | ||||
|  | ||||
|         Define(); | ||||
|         Define(std::string name, std::string value); | ||||
|         void IdentifyParameters(std::vector<std::string>& parameterNames); | ||||
|         std::string Render(std::vector<std::string>& parameterValues); | ||||
|         void IdentifyParameters(const std::vector<std::string>& parameterNames); | ||||
|         std::string Render(const std::vector<std::string>& parameterValues); | ||||
|     }; | ||||
|  | ||||
| private: | ||||
| @@ -44,16 +46,16 @@ private: | ||||
|     std::unordered_map<std::string, Define> m_defines; | ||||
|     std::stack<bool> m_modes; | ||||
|     unsigned m_ignore_depth; | ||||
|      | ||||
|     std::vector<std::string> MatchDefineParameters(const ParserLine& line, unsigned& parameterPosition); | ||||
|  | ||||
|     static std::vector<std::string> MatchDefineParameters(const ParserLine& line, unsigned& parameterPosition); | ||||
|     _NODISCARD bool MatchDefineDirective(const ParserLine& line, unsigned directivePosition); | ||||
|     _NODISCARD bool MatchUndefDirective(const ParserLine& line, unsigned directivePosition); | ||||
|     _NODISCARD bool MatchIfdefDirective(const ParserLine& line, unsigned directivePosition); | ||||
|     _NODISCARD bool MatchElseDirective(const ParserLine& line, unsigned directivePosition); | ||||
|     _NODISCARD bool MatchEndifDirective(const ParserLine& line, unsigned directivePosition); | ||||
|     _NODISCARD bool MatchDirectives(const ParserLine& line); | ||||
|      | ||||
|     void ExtractParametersFromDefineUsage(const ParserLine& line, unsigned parameterStart, unsigned& parameterEnd, std::vector<std::string>& parameterValues); | ||||
|  | ||||
|     static void ExtractParametersFromDefineUsage(const ParserLine& line, unsigned parameterStart, unsigned& parameterEnd, std::vector<std::string>& parameterValues); | ||||
|     bool FindDefineForWord(const ParserLine& line, unsigned wordStart, unsigned wordEnd, Define*& value); | ||||
|     void ExpandDefines(ParserLine& line); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user