AS3 parser: XML filter

This commit is contained in:
Jindra Petk
2014-04-18 21:33:50 +02:00
parent a5b26d9176
commit ade02c38d7
8 changed files with 894 additions and 737 deletions

View File

@@ -70,7 +70,7 @@ public class AVM2Instruction implements Serializable, GraphSourceItem {
case AVM2Code.OPT_S24:
aos.writeS24(operands[i]);
break;
case AVM2Code.OPT_U30:
case AVM2Code.OPT_U30:
aos.writeU30(operands[i]);
break;
case AVM2Code.OPT_U8:

View File

@@ -22,6 +22,7 @@ import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.NotIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.ConstructIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.ConstructSuperIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewActivationIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewCatchIns;
@@ -55,10 +56,12 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopScopeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushByteIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushScopeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushStringIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushUndefinedIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushWithIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.SwapIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceAIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.xml.CheckFilterIns;
import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.BooleanAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.FloatValueAVM2Item;
@@ -262,6 +265,75 @@ public class AVM2SourceGenerator implements SourceGenerator {
}
return ret;
}
public List<GraphSourceItem> generate(SourceGeneratorLocalData localData, XMLFilterAVM2Item item) throws CompilationException {
List<GraphSourceItem> ret = new ArrayList<>();
final Reference<Integer> counterReg = new Reference<>(0);
final Reference<Integer> collectionReg = new Reference<>(0);
final Reference<Integer> xmlListReg = new Reference<>(0);
List<GraphSourceItem> xmlListSetTemp = AssignableAVM2Item.setTemp(localData, this, xmlListReg);
ret.addAll(GraphTargetItem.toSourceMerge(localData, this,
ins(new PushByteIns(), 0),
AssignableAVM2Item.setTemp(localData, this, counterReg),
item.object,
ins(new CheckFilterIns()),
NameAVM2Item.generateCoerce(this, TypeItem.UNBOUNDED),
AssignableAVM2Item.setTemp(localData, this, collectionReg),
ins(new GetLexIns(),abc.constants.getMultinameId(new Multiname(Multiname.QNAME, abc.constants.getStringId("XMLList", true), abc.constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE, abc.constants.getStringId("", true)), 0, true), 0, 0, new ArrayList<Integer>()), true)),
ins(new PushStringIns(),abc.constants.getStringId("", true)),
ins(new ConstructIns(),1),
xmlListSetTemp
));
final Reference<Integer> tempVal1 = new Reference<>(0);
final Reference<Integer> tempVal2 = new Reference<>(0);
List<AVM2Instruction> forBody = toInsList(GraphTargetItem.toSourceMerge(localData, this,
ins(new LabelIns()),
AssignableAVM2Item.getTemp(localData, this, collectionReg),
AssignableAVM2Item.getTemp(localData, this, counterReg),
ins(new NextValueIns()),
AssignableAVM2Item.dupSetTemp(localData, this, tempVal1),
AssignableAVM2Item.dupSetTemp(localData, this, tempVal2),
ins(new PushWithIns())
));
localData.scopeStack.add(new LocalRegAVM2Item(null, tempVal2.getVal(), null));
forBody.addAll(toInsList(item.value.toSource(localData, this)));
List<AVM2Instruction> trueBody = new ArrayList<>();
trueBody.addAll(toInsList(AssignableAVM2Item.getTemp(localData, this, xmlListReg)));
trueBody.addAll(toInsList(AssignableAVM2Item.getTemp(localData, this, counterReg)));
trueBody.addAll(toInsList(AssignableAVM2Item.getTemp(localData, this, tempVal1)));
int nss[] = new int[item.openedNamespaces.size()];
for(int i=0;i<item.openedNamespaces.size();i++){
nss[i] = item.openedNamespaces.get(i);
}
trueBody.add(ins(new SetPropertyIns(),abc.constants.getMultinameId(new Multiname(Multiname.MULTINAMEL, 0, 0, abc.constants.getNamespaceSetId(new NamespaceSet(nss), true), 0, new ArrayList<Integer>()), true)));
forBody.add(ins(new IfFalseIns(),insToBytes(trueBody).length));
forBody.addAll(trueBody);
forBody.add(ins(new PopScopeIns()));
localData.scopeStack.remove(localData.scopeStack.size()-1);
forBody.addAll(toInsList(AssignableAVM2Item.killTemp(localData, this, Arrays.asList(tempVal2,tempVal1))));
int forBodyLen = insToBytes(forBody).length;
AVM2Instruction forwardJump = ins(new JumpIns(), forBodyLen);
ret.add(forwardJump);
List<AVM2Instruction> expr = new ArrayList<>();
expr.add(ins(new HasNext2Ins(), collectionReg.getVal(), counterReg.getVal()));
AVM2Instruction backIf = ins(new IfTrueIns(), 0);
expr.add(backIf);
int exprLen = insToBytes(expr).length;
backIf.operands[0] = -(exprLen + forBodyLen);
ret.addAll(forBody);
ret.addAll(expr);
ret.addAll(AssignableAVM2Item.killTemp(localData, this, Arrays.asList(collectionReg, counterReg)));
ret.addAll(AssignableAVM2Item.getTemp(localData, this, xmlListReg));
ret.addAll(AssignableAVM2Item.killTemp(localData, this, Arrays.asList(xmlListReg)));
return ret;
}
@Override
public List<GraphSourceItem> generate(SourceGeneratorLocalData localData, IfItem item) throws CompilationException {

View File

@@ -121,7 +121,7 @@ import java.util.logging.Logger;
public class ActionScriptParser {
private long uniqLast = 0;
private final boolean debugMode = true;
private final boolean debugMode = false;
private static final String AS3_NAMESPACE = "http://adobe.com/AS3/2006/builtin";
private ABC abc;
@@ -202,8 +202,13 @@ public class ActionScriptParser {
private GraphTargetItem name(Reference<Boolean> needsActivation, boolean typeOnly, List<Integer> openedNamespaces, HashMap<String, Integer> registerVars, boolean inFunction, boolean inMethod, List<AssignableAVM2Item> variables, List<String> importedClasses) throws IOException, ParseException {
ParsedSymbol s = lex();
String name = "";
if(s.type == SymbolType.ATTRIBUTE){
name += "@";
s = lex();
}
expected(s, lexer.yyline(), SymbolType.IDENTIFIER, SymbolType.THIS, SymbolType.SUPER, SymbolType.STRING_OP);
String name = s.value.toString();
name += s.value.toString();
s = lex();
while (s.type == SymbolType.DOT) {
s = lex();
@@ -1440,6 +1445,12 @@ public class ActionScriptParser {
GraphTargetItem ret = null;
ParsedSymbol s = lex();
switch (s.type) {
case FILTER:
needsActivation.setVal(true);
ret = new XMLFilterAVM2Item(expr,expression(needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables), openedNamespaces);
expectedType(SymbolType.PARENT_CLOSE);
allowRemainder = true;
break;
case NAMESPACE_OP:
s = lex();
if (s.type == SymbolType.BRACKET_OPEN) {
@@ -1885,6 +1896,7 @@ public class ActionScriptParser {
case IDENTIFIER:
case THIS:
case SUPER:
case ATTRIBUTE:
lexer.pushback(s);
GraphTargetItem var = name(needsActivation, false, openedNamespaces, registerVars, inFunction, inMethod, variables, importedClasses);
var = memberOrCall(needsActivation, importedClasses, openedNamespaces, var, registerVars, inFunction, inMethod, variables);

View File

@@ -200,5 +200,6 @@ public enum SymbolType {
XML_ATTRVALVAR_BEGIN, // aaa={
XML_INSTRATTRNAMEVAR_BEGIN, // {...}=
XML_INSTRATTRVALVAR_BEGIN, // aaa={
XML_INSTRVARTAG_BEGIN // <?{
XML_INSTRVARTAG_BEGIN, // <?{
FILTER
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright (C) 2014 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.abc.avm2.parser.script;
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.graph.CompilationException;
import com.jpexs.decompiler.graph.GraphSourceItem;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.SourceGenerator;
import com.jpexs.decompiler.graph.TypeItem;
import com.jpexs.decompiler.graph.model.LocalData;
import java.util.List;
/**
*
* @author JPEXS
*/
public class XMLFilterAVM2Item extends AVM2Item
{
public List<Integer> openedNamespaces;
public GraphTargetItem object;
public XMLFilterAVM2Item(GraphTargetItem object, GraphTargetItem value,List<Integer> openedNamespaces) {
super(null, NOPRECEDENCE);
this.value = value;
this.openedNamespaces = openedNamespaces;
this.object = object;
}
@Override
public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException {
return null;
}
@Override
public boolean hasReturnValue() {
return true;
}
@Override
public GraphTargetItem returnType() {
return new TypeItem("String");
}
@Override
public List<GraphSourceItem> toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException {
return ((AVM2SourceGenerator)generator).generate(localData, this);
}
}

View File

@@ -313,6 +313,7 @@ SingleCharacter = [^\r\n\'\\]
"typeof" { return new ParsedSymbol(SymbolGroup.OPERATOR,SymbolType.TYPEOF,yytext()); }
"void" { return new ParsedSymbol(SymbolGroup.OPERATOR,SymbolType.VOID,yytext()); }
"@" { return new ParsedSymbol(SymbolGroup.OPERATOR,SymbolType.ATTRIBUTE,yytext()); }
".(" { return new ParsedSymbol(SymbolGroup.OPERATOR,SymbolType.FILTER,yytext()); }
/* string literal */
\" {

View File

@@ -1,4 +1,3 @@
TODO List for AS3 parser/compiler:
------------------------------
- XML filter - .(
- default xml namespace