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];
|
||||
|
||||
|
||||
@@ -911,17 +911,19 @@ std::string CFalloutScript::GetSource(CNode& node, bool bLabel, uint32_t ulNumAr
|
||||
}
|
||||
if (node.m_Type == CNode::TYPE_CONDITIONAL_EXPRESSION)
|
||||
{
|
||||
if (node.m_Arguments.size() != 3)
|
||||
if (node.m_Arguments.size() != 5)
|
||||
{
|
||||
printf("Error: Invalid number of arguments in conditional expression\n");
|
||||
throw std::exception();
|
||||
}
|
||||
std::string sPostfix[] = { " if ", " else ", ""};
|
||||
uint16_t argIdx[] = {2, 1, 3};
|
||||
strResult = "";
|
||||
for(uint32_t i = 0; i < node.m_Arguments.size(); i++)
|
||||
for (uint32_t i = 0; i < 3; i++)
|
||||
{
|
||||
bool bParens = ArgNeedParens(node, node.m_Arguments[i], CFalloutScript::RIGHT_ASSOC);
|
||||
strResult += (bParens ? "(" : "") + GetSource(node.m_Arguments[i], bLabel, ulNumArgs) + (bParens ? ")" : "") + sPostfix[i];
|
||||
CNode& arg = node.m_Arguments[argIdx[i]];
|
||||
bool bParens = ArgNeedParens(node, arg, CFalloutScript::RIGHT_ASSOC);
|
||||
strResult += (bParens ? "(" : "") + GetSource(arg, bLabel, ulNumArgs) + (bParens ? ")" : "") + sPostfix[i];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -130,7 +130,9 @@ uint32_t CNode::GetTopOffset()
|
||||
|
||||
bool CNode::IsExpression() const
|
||||
{
|
||||
return (m_Opcode.GetAttributes().m_Type == COpcode::COpcodeAttributes::TYPE_EXPRESSION
|
||||
COpcode::COpcodeAttributes::Type type = m_Opcode.GetAttributes().m_Type;
|
||||
return (type == COpcode::COpcodeAttributes::TYPE_EXPRESSION
|
||||
|| type == COpcode::COpcodeAttributes::TYPE_EXPRESSIONSTATEMENT
|
||||
|| m_Type == TYPE_CONDITIONAL_EXPRESSION);
|
||||
}
|
||||
|
||||
|
||||
@@ -800,7 +800,8 @@ public:
|
||||
public:
|
||||
enum Type {
|
||||
TYPE_STATEMENT,
|
||||
TYPE_EXPRESSION
|
||||
TYPE_EXPRESSION,
|
||||
TYPE_EXPRESSIONSTATEMENT,
|
||||
};
|
||||
|
||||
enum Category {
|
||||
|
||||
@@ -79,6 +79,7 @@ uint32_t procArgs[] = {1, 2};
|
||||
COpcode::CF2OpcodeAttributesMap::CF2OpcodeAttributesMap()
|
||||
{
|
||||
COpcode::COpcodeAttributes::Type expression = COpcode::COpcodeAttributes::TYPE_EXPRESSION;
|
||||
COpcode::COpcodeAttributes::Type exprStatement = COpcode::COpcodeAttributes::TYPE_EXPRESSIONSTATEMENT;
|
||||
COpcode::COpcodeAttributes::Category infix = COpcode::COpcodeAttributes::CATEGORY_INFIX;
|
||||
|
||||
SetAt(O_NOOP, COpcodeAttributes("O_NOOP", "/* O_NOOP */", 0));
|
||||
@@ -339,7 +340,7 @@ COpcode::CF2OpcodeAttributesMap::CF2OpcodeAttributesMap()
|
||||
SetAt(O_CRITTER_ATTEMPT_PLACEMENT, COpcodeAttributes("O_CRITTER_ATTEMPT_PLACEMENT", "critter_attempt_placement", 3, expression));
|
||||
SetAt(O_OBJ_PID, COpcodeAttributes("O_OBJ_PID", "obj_pid", 1, expression));
|
||||
SetAt(O_CUR_MAP_INDEX, COpcodeAttributes("O_CUR_MAP_INDEX", "cur_map_index", 0, expression));
|
||||
SetAt(O_CRITTER_ADD_TRAIT, COpcodeAttributes("O_CRITTER_ADD_TRAIT", "critter_add_trait", 4, expression));
|
||||
SetAt(O_CRITTER_ADD_TRAIT, COpcodeAttributes("O_CRITTER_ADD_TRAIT", "critter_add_trait", 4, exprStatement));
|
||||
SetAt(O_CRITTER_RM_TRAIT, COpcodeAttributes("O_CRITTER_RM_TRAIT", "critter_rm_trait", 4, expression));
|
||||
SetAt(O_PROTO_DATA, COpcodeAttributes("O_PROTO_DATA", "proto_data", 2, expression));
|
||||
SetAt(O_MESSAGE_STR, COpcodeAttributes("O_MESSAGE_STR", "message_str", 2, expression));
|
||||
|
||||
Reference in New Issue
Block a user