mirror of
https://github.com/sfall-team/int2ssl.git
synced 2026-07-27 16:52:42 -07:00
Handle cases where if/else block with single exprstatement was incorrectly identified as ternary operator (closes #4)
This commit is contained in:
+28
-13
@@ -539,27 +539,30 @@ uint32_t CFalloutScript::BuildTreeBranch(CNodeArray& NodeArray, uint32_t nStartI
|
||||
if (wOperator == COpcode::O_IF)
|
||||
{
|
||||
// process possible conditional expression - this may be either normal IF statement or (x IF y ELSE z) expression
|
||||
uint32_t ulElseOffset = NodeArray[j].m_Arguments[0].m_Opcode.GetArgument();
|
||||
int32_t ulElseIndex, ulSkipIndex = -1;
|
||||
CNodeArray& arguments = NodeArray[j].m_Arguments;
|
||||
uint32_t ulElseOffset = arguments[0].m_Opcode.GetArgument();
|
||||
uint32_t ulElseIndex, ulSkipIndex = 0;
|
||||
ulElseIndex = BuildTreeBranch(NodeArray, j + 1, ulElseOffset); // true branch
|
||||
if (NodeArray[ulElseIndex - 1].m_Opcode.GetOperator() == COpcode::O_JMP)
|
||||
CNode& jumpNode = NodeArray[ulElseIndex - 1];
|
||||
if (jumpNode.m_Opcode.GetOperator() == COpcode::O_JMP)
|
||||
{
|
||||
uint32_t ulSkipOffset = NodeArray[ulElseIndex - 1].m_Opcode.GetArgument();
|
||||
uint32_t ulSkipOffset = jumpNode.m_Opcode.GetArgument();
|
||||
if (ulSkipOffset > NodeArray[j].m_ulOffset)
|
||||
{
|
||||
ulSkipIndex = BuildTreeBranch(NodeArray, ulElseIndex, ulSkipOffset); // false branch
|
||||
if (NodeArray[ulElseIndex - 2].IsExpression() && NodeArray[ulSkipIndex - 1].IsExpression())
|
||||
if (ulElseIndex == j + 3 && ulSkipIndex == ulElseIndex + 1 &&
|
||||
NodeArray[ulElseIndex - 2].IsExpression() && NodeArray[ulSkipIndex - 1].IsExpression())
|
||||
{ // conditional expression
|
||||
NodeArray[j].m_Type = CNode::TYPE_CONDITIONAL_EXPRESSION;
|
||||
NodeArray[j].m_Arguments.erase(NodeArray[j].m_Arguments.begin() + 0); // address not needed anymore
|
||||
NodeArray[j].m_Arguments.insert(NodeArray[j].m_Arguments.begin() + 0, NodeArray[ulElseIndex - 2]); // true expression
|
||||
NodeArray[j].m_Arguments.insert(NodeArray[j].m_Arguments.begin() + 2, NodeArray[ulSkipIndex - 1]); // false expression
|
||||
NodeArray.erase(NodeArray.begin() + j + 1, NodeArray.begin() + j + 1 + ulSkipIndex - j - 1);
|
||||
arguments.insert(arguments.begin() + 2, NodeArray[ulElseIndex - 2]); // true expression
|
||||
arguments.insert(arguments.begin() + 3, NodeArray[ulSkipIndex - 1]); // false expression
|
||||
arguments.insert(arguments.begin() + 4, jumpNode); // jump node
|
||||
NodeArray.erase(NodeArray.begin() + j + 1, NodeArray.begin() + ulSkipIndex);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
j = ((ulSkipIndex != -1) ? ulSkipIndex : ulElseIndex) - 1; // skip already built
|
||||
j = ((ulSkipIndex > 0) ? ulSkipIndex : ulElseIndex) - 1; // skip already built
|
||||
}
|
||||
}
|
||||
|
||||
@@ -644,7 +647,7 @@ void CFalloutScript::ExtractAndReduceCondition(CNodeArray& Source, CNodeArray& D
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Destination[0].m_Opcode.GetAttributes().m_Type != COpcode::COpcodeAttributes::TYPE_EXPRESSION)
|
||||
if (!Destination[0].IsExpression())
|
||||
{
|
||||
printf("Error: Invalid condition. Expression required\n");
|
||||
throw std::exception();
|
||||
@@ -787,8 +790,20 @@ void CFalloutScript::SetBordersOfBlocks(CNodeArray& NodeArray)
|
||||
{
|
||||
if (NodeArray[i].m_Type == CNode::TYPE_CONDITIONAL_EXPRESSION)
|
||||
{
|
||||
printf("Error: Conditional expression left in stack\n");
|
||||
throw std::exception();
|
||||
CNodeArray& args = NodeArray[i].m_Arguments;
|
||||
// If both true and false expressions can be statements, we can safely decompile this
|
||||
if (args[2].m_Opcode.GetAttributes().m_Type != COpcode::COpcodeAttributes::Type::TYPE_EXPRESSIONSTATEMENT ||
|
||||
args[3].m_Opcode.GetAttributes().m_Type != COpcode::COpcodeAttributes::Type::TYPE_EXPRESSIONSTATEMENT)
|
||||
{
|
||||
printf("Error: Conditional expression left in stack.\n");
|
||||
throw std::exception();
|
||||
}
|
||||
printf("Warning: Conditional expression left in stack. Restoring as IF.\n");
|
||||
NodeArray[i].m_Type = CNode::TYPE_NORMAL;
|
||||
NodeArray.insert(NodeArray.begin() + i + 1, args[2]); // true branch
|
||||
NodeArray.insert(NodeArray.begin() + i + 2, args[4]); // jump
|
||||
NodeArray.insert(NodeArray.begin() + i + 3, args[3]); // false branch
|
||||
args.erase(args.begin() + 2, args.end());
|
||||
}
|
||||
CNode node = NodeArray[i].m_Arguments[0];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user