P-code parsing of NumberContext

This commit is contained in:
Jindra Petřík
2024-08-10 18:18:39 +02:00
parent 4e36416729
commit d25627460c
13 changed files with 3044 additions and 2589 deletions

View File

@@ -36,6 +36,10 @@ public class NumberContext {
public static final int USE_DOUBLE = 2;
public static final int USE_INT = 3;
public static final int USE_UINT = 4;
private static String[] usageNames = new String[]{"Number", "decimal", "double", "int", "uint"};
private static String[] roundingNames = new String[] {"CEILING", "UP", "HALF_UP", "HALF_EVEN", "HALF_DOWN", "DOWN", "FLOOR"};
/**
* Usage of the number.
@@ -72,6 +76,9 @@ public class NumberContext {
this.usage = param & 7;
this.rounding = (param >> 3) & 7;
this.precision = param >> 6;
if ((usage == USE_NUMBER || usage == USE_DECIMAL) && precision == 0) {
precision = 34;
}
}
/**
@@ -80,7 +87,7 @@ public class NumberContext {
* @param usage Usage
*/
public void setUsage(int usage) {
if (usage > 6 || usage < 0) {
if (usage > usageNames.length || usage < 0) {
throw new IllegalArgumentException("Invalid usage value :" + usage);
}
this.usage = usage;
@@ -116,6 +123,26 @@ public class NumberContext {
this.precision = precision;
}
/**
* Sets the rounding of the number.
*
* @param rounding Rounding
*/
public void setRounding(int rounding) {
if (rounding > roundingNames.length || rounding < 0) {
throw new IllegalArgumentException("Invalid rounding value :" + rounding);
}
this.rounding = rounding;
}
/**
* Gets the rounding of the number
* @return Rounding
*/
public int getRounding() {
return rounding;
}
/**
* Converts the number context to a parameter.
*
@@ -131,4 +158,36 @@ public class NumberContext {
}
return ret;
}
public static String usageToName(int usage) {
if (usage > usageNames.length || usage < 0) {
throw new IllegalArgumentException("Invalid usage value :" + usage);
}
return usageNames[usage];
}
public static String roundingToName(int rounding) {
if (rounding > roundingNames.length || rounding < 0) {
throw new IllegalArgumentException("Invalid rounding value :" + rounding);
}
return roundingNames[rounding];
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("NumberContext");
sb.append("(");
sb.append(usageToName(usage));
if (usage == USE_NUMBER || usage == USE_DECIMAL) {
sb.append(",");
sb.append(roundingToName(rounding));
if (precision < 34) {
sb.append(",");
sb.append(precision);
}
}
sb.append(")");
return sb.toString();
}
}

View File

@@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.abc.ABCOutputStream;
import com.jpexs.decompiler.flash.abc.AVM2LocalData;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.NumberContext;
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.LookupSwitchIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnValueIns;
@@ -459,6 +460,11 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem {
}
}
break;
case AVM2Code.DAT_NUMBER_CONTEXT:
NumberContext nc = new NumberContext(operands[i]);
s.append(" ");
s.append(nc.toString());
break;
case AVM2Code.DAT_OFFSET:
s.append(" ");
s.append("ofs");

View File

@@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.abc.avm2.parser.pcode;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.NumberContext;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.DeobfuscatePopIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
@@ -466,6 +467,77 @@ public class ASM3Parser {
return parseSlotConst(abc, lexer, constants, tsc);
}
private static int parseNumberContext(Flasm3Lexer lexer) throws AVM2ParseException, IOException {
ParsedSymbol s = lexer.lex();
expected(s, ParsedSymbol.TYPE_KEYWORD_NUMBERCONTEXT, "NumberContext", lexer.yyline());
expected(ParsedSymbol.TYPE_PARENT_OPEN, "(", lexer);
s = lexer.lex();
int usage;
switch (s.type) {
case ParsedSymbol.TYPE_KEYWORD_NUMBER:
usage = NumberContext.USE_NUMBER;
break;
case ParsedSymbol.TYPE_KEYWORD_DECIMAL:
usage = NumberContext.USE_DECIMAL;
break;
case ParsedSymbol.TYPE_KEYWORD_DOUBLE:
usage = NumberContext.USE_DOUBLE;
break;
case ParsedSymbol.TYPE_KEYWORD_INT:
usage = NumberContext.USE_INT;
break;
case ParsedSymbol.TYPE_KEYWORD_UINT:
usage = NumberContext.USE_UINT;
break;
default:
throw new AVM2ParseException("Usage expected - one of: Number, decimal, double, int or uint", lexer.yyline());
}
int rounding = NumberContext.ROUND_HALF_UP;
int precision = 34;
if (usage == NumberContext.USE_NUMBER || usage == NumberContext.USE_DECIMAL) {
expected(ParsedSymbol.TYPE_COMMA, ",", lexer);
s = lexer.lex();
switch (s.type) {
case ParsedSymbol.TYPE_KEYWORD_CEILING:
rounding = NumberContext.ROUND_CEILING;
break;
case ParsedSymbol.TYPE_KEYWORD_UP:
rounding = NumberContext.ROUND_UP;
break;
case ParsedSymbol.TYPE_KEYWORD_HALF_UP:
rounding = NumberContext.ROUND_HALF_UP;
break;
case ParsedSymbol.TYPE_KEYWORD_HALF_EVEN:
rounding = NumberContext.ROUND_HALF_EVEN;
break;
case ParsedSymbol.TYPE_KEYWORD_HALF_DOWN:
rounding = NumberContext.ROUND_HALF_DOWN;
break;
case ParsedSymbol.TYPE_KEYWORD_DOWN:
rounding = NumberContext.ROUND_DOWN;
break;
case ParsedSymbol.TYPE_KEYWORD_FLOOR:
rounding = NumberContext.ROUND_FLOOR;
break;
default:
throw new AVM2ParseException("Rounding expected - one of: CEILING, UP, HALF_UP, HALF_EVEN, HALF_DOWN, DOWN, FLOOR", lexer.yyline());
}
s = lexer.lex();
if (s.type == ParsedSymbol.TYPE_COMMA) {
s = lexer.lex();
precision = (int) getUInteger(s, lexer.yyline(), false);
if (precision > 34) {
throw new AVM2ParseException("Precision must not exceed 34", lexer.yyline());
}
} else {
lexer.pushback(s);
}
}
expected(ParsedSymbol.TYPE_PARENT_CLOSE, ")", lexer);
return new NumberContext(usage, precision, rounding).toParam();
}
private static int parseNamespaceSet(AVM2ConstantPool constants, Flasm3Lexer lexer) throws AVM2ParseException, IOException {
List<Integer> namespaceList = new ArrayList<>();
ParsedSymbol s = lexer.lex();
@@ -1310,6 +1382,10 @@ public class ASM3Parser {
operandsList.add(did);
}
break;
case AVM2Code.DAT_NUMBER_CONTEXT:
lexer.pushback(parsedOperand);
operandsList.add(parseNumberContext(lexer));
break;
case AVM2Code.DAT_FLOAT_INDEX:
if (parsedOperand.type == ParsedSymbol.TYPE_KEYWORD_NULL) {
operandsList.add(0);

View File

@@ -519,6 +519,61 @@ public class ParsedSymbol {
*/
public static final int TYPE_KEYWORD_PROTECTEDNS_BLOCK = 97;
/**
* Type: Keyword Number
*/
public static final int TYPE_KEYWORD_NUMBER = 98;
/**
* Type: Keyword int
*/
public static final int TYPE_KEYWORD_INT = 99;
/**
* Type: Keyword uint
*/
public static final int TYPE_KEYWORD_UINT = 100;
/**
* Type: Keyword NumberContext
*/
public static final int TYPE_KEYWORD_NUMBERCONTEXT = 101;
/**
* Type: Keyword CEILING
*/
public static final int TYPE_KEYWORD_CEILING = 102;
/**
* Type: Keyword UP
*/
public static final int TYPE_KEYWORD_UP = 103;
/**
* Type: Keyword HALF_UP
*/
public static final int TYPE_KEYWORD_HALF_UP = 104;
/**
* Type: Keyword HALF_EVEN
*/
public static final int TYPE_KEYWORD_HALF_EVEN = 105;
/**
* Type: Keyword HALF_DOWN
*/
public static final int TYPE_KEYWORD_HALF_DOWN = 106;
/**
* Type: Keyword DOWN
*/
public static final int TYPE_KEYWORD_DOWN = 107;
/**
* Type: Keyword FLOOR
*/
public static final int TYPE_KEYWORD_FLOOR = 108;
/**
* Constructor.
* @param pos Position