Project renamed to Free Flash Decompiler.

Code moved to new dir.
Version changed to 1.3
This commit is contained in:
Jindra Pet��k
2013-02-17 18:13:01 +01:00
parent 561c12426e
commit 6ca95c8e34
792 changed files with 4004 additions and 4021 deletions
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,313 @@
/*
* Copyright (C) 2011-2013 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.methodinfo_parser;
import com.jpexs.decompiler.flash.Main;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.flash.abc.types.ValueKind;
import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author JPEXS
*/
public class MethodInfoParser {
public static boolean parseSlotConst(String text, TraitSlotConst trait, ABC abc) throws ParseException {
MethodInfoLexer lexer = new MethodInfoLexer(new ByteArrayInputStream(text.getBytes()));
ParsedSymbol symb;
int type_index = -1;
ValueKind value = new ValueKind(0, 0);
try {
ParsedSymbol symbType = lexer.yylex();
if (symbType.type == ParsedSymbol.TYPE_STAR) {
type_index = 0;
} else if (symbType.type == ParsedSymbol.TYPE_MULTINAME) {
type_index = (int) (long) (Long) symbType.value;
} else {
throw new ParseException("Multiname or * expected", lexer.yyline());
}
ParsedSymbol symbEqual = lexer.yylex();
if (symbEqual.type == ParsedSymbol.TYPE_ASSIGN) {
ParsedSymbol symbValue;
String nstype = "";
do {
symbValue = lexer.yylex();
if (symbValue.type >= 8 && symbValue.type <= 13) {
nstype = nstype + symbValue.type + ":";
}
} while (symbValue.type >= 8 && symbValue.type <= 13);
if ((!nstype.equals("")) && (symbValue.type != ParsedSymbol.TYPE_NAMESPACE)) {
throw new ParseException("Namespace expected", lexer.yyline());
}
int id = 0;
switch (symbValue.type) {
case ParsedSymbol.TYPE_INTEGER:
value = new ValueKind(abc.constants.forceGetIntId((Long) symbValue.value), ValueKind.CONSTANT_Int);
break;
case ParsedSymbol.TYPE_FLOAT:
value = new ValueKind(abc.constants.forceGetDoubleId((Double) symbValue.value), ValueKind.CONSTANT_Double);
break;
case ParsedSymbol.TYPE_STRING:
value = new ValueKind(abc.constants.forceGetStringId((String) symbValue.value), ValueKind.CONSTANT_Utf8);
break;
case ParsedSymbol.TYPE_TRUE:
value = new ValueKind(0, ValueKind.CONSTANT_True);
break;
case ParsedSymbol.TYPE_FALSE:
value = new ValueKind(0, ValueKind.CONSTANT_False);
break;
case ParsedSymbol.TYPE_NULL:
value = new ValueKind(0, ValueKind.CONSTANT_Null);
break;
case ParsedSymbol.TYPE_UNDEFINED:
value = new ValueKind(0, ValueKind.CONSTANT_Undefined);
break;
case ParsedSymbol.TYPE_NAMESPACE:
if (nstype.equals("9:")) {
value = new ValueKind((int) (long) (Long) symbValue.value, ValueKind.CONSTANT_PackageNamespace);
} else if (nstype.equals("9:10:")) {
value = new ValueKind((int) (long) (Long) symbValue.value, ValueKind.CONSTANT_PackageInternalNs);
} else if (nstype.equals("13:")) {
value = new ValueKind((int) (long) (Long) symbValue.value, ValueKind.CONSTANT_ProtectedNamespace);
} else if (nstype.equals("12:")) {
value = new ValueKind((int) (long) (Long) symbValue.value, ValueKind.CONSTANT_ExplicitNamespace);
} else if (nstype.equals("11:13:")) {
value = new ValueKind((int) (long) (Long) symbValue.value, ValueKind.CONSTANT_StaticProtectedNs);
} else if (nstype.equals("8:")) {
value = new ValueKind((int) (long) (Long) symbValue.value, ValueKind.CONSTANT_PrivateNs);
} else if (nstype.equals("")) {
value = new ValueKind((int) (long) (Long) symbValue.value, ValueKind.CONSTANT_Namespace);
} else {
throw new ParseException("Invalid type of namespace", lexer.yyline());
}
break;
default:
throw new ParseException("Unexpected symbol", lexer.yyline());
}
symb = lexer.yylex();
if (symb.type != ParsedSymbol.TYPE_EOF) {
throw new ParseException("Unexpected symbol", lexer.yyline());
}
} else if (symbEqual.type == ParsedSymbol.TYPE_EOF) {
} else {
throw new ParseException("Unexpected symbol", lexer.yyline());
}
} catch (IOException ex) {
return false;
}
trait.type_index = type_index;
trait.value_kind = value.value_kind;
trait.value_index = value.value_index;
return true;
}
public static boolean parseReturnType(String text, MethodInfo update) throws ParseException {
MethodInfoLexer lexer = new MethodInfoLexer(new ByteArrayInputStream(text.getBytes()));
ParsedSymbol symb;
int type = -1;
try {
symb = lexer.yylex();
if (symb.type == ParsedSymbol.TYPE_STAR) {
type = 0;
} else if (symb.type == ParsedSymbol.TYPE_MULTINAME) {
type = (int) (long) (Long) symb.value;
} else {
throw new ParseException("Multiname or * expected", lexer.yyline());
}
symb = lexer.yylex();
if (symb.type != ParsedSymbol.TYPE_EOF) {
throw new ParseException("Only one return type allowed", lexer.yyline());
}
update.ret_type = type;
return true;
} catch (IOException ex) {
}
return false;
}
public static boolean parseParams(String text, MethodInfo update, ABC abc) throws ParseException {
MethodInfoLexer lexer = new MethodInfoLexer(new ByteArrayInputStream(text.getBytes()));
List<String> paramNames = new ArrayList<String>();
List<Long> paramTypes = new ArrayList<Long>();
List<ValueKind> optionalValues = new ArrayList<ValueKind>();
boolean hasOptional = false;
boolean needsRest = false;
try {
ParsedSymbol symb;
symb = lexer.yylex();
while (symb.type != ParsedSymbol.TYPE_EOF) {
if (symb.type == ParsedSymbol.TYPE_DOTS) {
needsRest = true;
symb = lexer.yylex();
if (symb.type != ParsedSymbol.TYPE_IDENTIFIER) {
throw new ParseException("Identifier expected", lexer.yyline());
}
symb = lexer.yylex();
if (symb.type != ParsedSymbol.TYPE_EOF) {
throw new ParseException("End expected after rest params", lexer.yyline());
}
break;
}
if (symb.type != ParsedSymbol.TYPE_IDENTIFIER) {
throw new ParseException("Identifier expected", lexer.yyline());
}
paramNames.add((String) symb.value);
symb = lexer.yylex();
if (symb.type == ParsedSymbol.TYPE_COLON) {
ParsedSymbol symbType = lexer.yylex();
if (symbType.type == ParsedSymbol.TYPE_STAR) {
paramTypes.add(new Long(0));
} else if (symbType.type == ParsedSymbol.TYPE_MULTINAME) {
paramTypes.add((Long) symbType.value);
} else {
throw new ParseException("Multiname or * expected", lexer.yyline());
}
ParsedSymbol symbEqual = lexer.yylex();
if (symbEqual.type == ParsedSymbol.TYPE_ASSIGN) {
hasOptional = true;
ParsedSymbol symbValue;
String nstype = "";
do {
symbValue = lexer.yylex();
if (symbValue.type >= 8 && symbValue.type <= 13) {
nstype = nstype + symbValue.type + ":";
}
} while (symbValue.type >= 8 && symbValue.type <= 13);
if ((!nstype.equals("")) && (symbValue.type != ParsedSymbol.TYPE_NAMESPACE)) {
throw new ParseException("Namespace expected", lexer.yyline());
}
int id = 0;
switch (symbValue.type) {
case ParsedSymbol.TYPE_INTEGER:
optionalValues.add(new ValueKind(abc.constants.forceGetIntId((Long) symbValue.value), ValueKind.CONSTANT_Int));
break;
case ParsedSymbol.TYPE_FLOAT:
optionalValues.add(new ValueKind(abc.constants.forceGetDoubleId((Double) symbValue.value), ValueKind.CONSTANT_Double));
break;
case ParsedSymbol.TYPE_STRING:
optionalValues.add(new ValueKind(abc.constants.forceGetStringId((String) symbValue.value), ValueKind.CONSTANT_Utf8));
break;
case ParsedSymbol.TYPE_TRUE:
optionalValues.add(new ValueKind(0, ValueKind.CONSTANT_True));
break;
case ParsedSymbol.TYPE_FALSE:
optionalValues.add(new ValueKind(0, ValueKind.CONSTANT_False));
break;
case ParsedSymbol.TYPE_NULL:
optionalValues.add(new ValueKind(0, ValueKind.CONSTANT_Null));
break;
case ParsedSymbol.TYPE_UNDEFINED:
optionalValues.add(new ValueKind(0, ValueKind.CONSTANT_Undefined));
break;
case ParsedSymbol.TYPE_NAMESPACE:
if (nstype.equals("9:")) {
optionalValues.add(new ValueKind((int) (long) (Long) symbValue.value, ValueKind.CONSTANT_PackageNamespace));
} else if (nstype.equals("9:10:")) {
optionalValues.add(new ValueKind((int) (long) (Long) symbValue.value, ValueKind.CONSTANT_PackageInternalNs));
} else if (nstype.equals("13:")) {
optionalValues.add(new ValueKind((int) (long) (Long) symbValue.value, ValueKind.CONSTANT_ProtectedNamespace));
} else if (nstype.equals("12:")) {
optionalValues.add(new ValueKind((int) (long) (Long) symbValue.value, ValueKind.CONSTANT_ExplicitNamespace));
} else if (nstype.equals("11:13:")) {
optionalValues.add(new ValueKind((int) (long) (Long) symbValue.value, ValueKind.CONSTANT_StaticProtectedNs));
} else if (nstype.equals("8:")) {
optionalValues.add(new ValueKind((int) (long) (Long) symbValue.value, ValueKind.CONSTANT_PrivateNs));
} else if (nstype.equals("")) {
optionalValues.add(new ValueKind((int) (long) (Long) symbValue.value, ValueKind.CONSTANT_Namespace));
} else {
throw new ParseException("Invalid type of namespace", lexer.yyline());
}
break;
default:
throw new ParseException("Unexpected symbol", lexer.yyline());
}
symb = lexer.yylex();
if (symb.type == ParsedSymbol.TYPE_COMMA) {
} else if (symb.type == ParsedSymbol.TYPE_EOF) {
break;
}
} else if (symbEqual.type == ParsedSymbol.TYPE_COMMA) {
if (hasOptional) {
throw new ParseException("Parameter must have default value", lexer.yyline());
}
} else if (symbEqual.type == ParsedSymbol.TYPE_EOF) {
if (hasOptional) {
throw new ParseException("Parameter must have default value", lexer.yyline());
}
break;
} else {
throw new ParseException("Unexpected symbol", lexer.yyline());
}
} else if (symb.type == ParsedSymbol.TYPE_COMMA) {
} else if (symb.type == ParsedSymbol.TYPE_EOF) {
break;
} else {
throw new ParseException("Unexpected symbol", lexer.yyline());
}
symb = lexer.yylex();
}
} catch (IOException iex) {
return false;
}
if (needsRest && (!optionalValues.isEmpty())) {
throw new ParseException("Rest parameter canot be combined with default values", lexer.yyline());
}
update.param_types = new int[paramTypes.size()];
for (int p = 0; p < paramTypes.size(); p++) {
update.param_types[p] = (int) (long) paramTypes.get(p);
}
update.optional = (ValueKind[]) optionalValues.toArray(new ValueKind[optionalValues.size()]);
update.unsetFlagHas_optional();
if (!optionalValues.isEmpty()) {
update.setFlagHas_optional();
}
update.unsetFlagNeed_rest();
if (needsRest) {
update.setFlagNeed_rest();
}
update.unsetFlagHas_paramnames();
update.paramNames = new int[]{};
boolean useParamNames = false;
for (int p = 0; p < paramNames.size(); p++) {
if (!paramNames.get(p).equals("param" + (p + 1))) {
useParamNames = true;
}
}
if (!Main.PARAM_NAMES_ENABLE) {
useParamNames = false;
}
if (useParamNames) {
update.setFlagHas_paramnames();
update.paramNames = new int[paramNames.size()];
for (int p = 0; p < paramNames.size(); p++) {
update.paramNames[p] = abc.constants.forceGetStringId(paramNames.get(p));
}
}
return true;
}
}
@@ -0,0 +1,29 @@
/*
* Copyright (C) 2010-2013 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.methodinfo_parser;
public class ParseException extends Exception {
public long line;
public String text;
public ParseException(String text, long line) {
super("ParseException:" + text + " on line " + line);
this.line = line;
this.text = text;
}
}
@@ -0,0 +1,55 @@
/*
* Copyright (C) 2010-2013 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.methodinfo_parser;
public class ParsedSymbol {
public int type;
public Object value;
public static final int TYPE_INTEGER = 1;
public static final int TYPE_FLOAT = 2;
public static final int TYPE_TRUE = 3;
public static final int TYPE_FALSE = 4;
public static final int TYPE_NULL = 5;
public static final int TYPE_UNDEFINED = 6;
public static final int TYPE_STRING = 7;
//8-12 namespace prefix
public static final int TYPE_PRIVATE = 8;
public static final int TYPE_PACKAGE = 9;
public static final int TYPE_INTERNAL = 10;
public static final int TYPE_STATIC = 11;
public static final int TYPE_EXPLICIT = 12;
public static final int TYPE_PROTECTED = 13;
public static final int TYPE_NAMESPACE = 14;
public static final int TYPE_COLON = 15;
public static final int TYPE_COMMA = 16;
public static final int TYPE_DOTS = 17;
public static final int TYPE_MULTINAME = 18;
public static final int TYPE_IDENTIFIER = 19;
public static final int TYPE_EOF = 20;
public static final int TYPE_STAR = 21;
public static final int TYPE_ASSIGN = 22;
public ParsedSymbol(int type, Object value) {
this.type = type;
this.value = value;
}
public ParsedSymbol(int type) {
this.type = type;
}
}
@@ -0,0 +1,160 @@
/* Method info lexer specification */
package com.jpexs.decompiler.flash.abc.methodinfo_parser;
%%
%public
%class MethodInfoLexer
%final
%unicode
%char
%line
%column
%type ParsedSymbol
%throws ParseException
%{
StringBuffer string = new StringBuffer();
boolean isMultiname=false;
long multinameId=0;
/**
* Create an empty lexer, yyrset will be called later to reset and assign
* the reader
*/
public MethodInfoLexer() {
}
public int yychar() {
return yychar;
}
public int yyline() {
return yyline+1;
}
%}
/* main character classes */
LineTerminator = \r|\n|\r\n
WhiteSpace = [ \t\f]+
/* identifiers */
Identifier = [:jletter:][:jletterdigit:]*
/* integer literals */
NumberLiteral = 0 | -?[1-9][0-9]*
PositiveNumberLiteral = 0 | [1-9][0-9]*
Multiname = m\[{PositiveNumberLiteral}\]
Namespace = ns\{PositiveNumberLiteral}\]
/* floating point literals */
FloatLiteral = -?({FLit1}|{FLit2}|{FLit3}) {Exponent}?
FLit1 = [0-9]+ \. [0-9]*
FLit2 = \. [0-9]+
FLit3 = [0-9]+
Exponent = [eE] [+-]? [0-9]+
OctDigit = [0-7]
/* string and character literals */
StringCharacter = [^\r\n\"\\]
%state STRING
%%
<YYINITIAL> {
/* whitespace */
{WhiteSpace} { }
{Multiname}\" {
isMultiname=true;
String s=yytext();
multinameId=Long.parseLong(s.substring(2,s.length()-2));
yybegin(STRING);
string.setLength(0);
}
/* string literal */
\" {
isMultiname=false;
yybegin(STRING);
string.setLength(0);
}
/* numeric literals */
{NumberLiteral} { return new ParsedSymbol(ParsedSymbol.TYPE_INTEGER,new Long(Long.parseLong((yytext())))); }
{FloatLiteral} { return new ParsedSymbol(ParsedSymbol.TYPE_FLOAT,new Double(Double.parseDouble((yytext())))); }
":" {return new ParsedSymbol(ParsedSymbol.TYPE_COLON);}
"," {return new ParsedSymbol(ParsedSymbol.TYPE_COMMA);}
"..." {return new ParsedSymbol(ParsedSymbol.TYPE_DOTS);}
"*" {return new ParsedSymbol(ParsedSymbol.TYPE_STAR);}
"=" {return new ParsedSymbol(ParsedSymbol.TYPE_ASSIGN);}
private {return new ParsedSymbol(ParsedSymbol.TYPE_PRIVATE);}
protected {return new ParsedSymbol(ParsedSymbol.TYPE_PROTECTED);}
package {return new ParsedSymbol(ParsedSymbol.TYPE_PACKAGE);}
internal {return new ParsedSymbol(ParsedSymbol.TYPE_INTERNAL);}
static {return new ParsedSymbol(ParsedSymbol.TYPE_STATIC);}
explicit {return new ParsedSymbol(ParsedSymbol.TYPE_EXPLICIT);}
{Namespace} {
String s=yytext();
long ns=Long.parseLong(s.substring(3,s.length()-2));
return new ParsedSymbol(ParsedSymbol.TYPE_NAMESPACE,new Long(ns));
}
true {return new ParsedSymbol(ParsedSymbol.TYPE_TRUE);}
false {return new ParsedSymbol(ParsedSymbol.TYPE_FALSE);}
null {return new ParsedSymbol(ParsedSymbol.TYPE_NULL);}
undefined {return new ParsedSymbol(ParsedSymbol.TYPE_UNDEFINED);}
{Identifier} {
return new ParsedSymbol(ParsedSymbol.TYPE_IDENTIFIER,yytext()); }
}
<STRING> {
\" {
yybegin(YYINITIAL);
// length also includes the trailing quote
if(isMultiname){
return new ParsedSymbol(ParsedSymbol.TYPE_MULTINAME,new Long(multinameId));
}else{
return new ParsedSymbol(ParsedSymbol.TYPE_STRING,string.toString());
}
}
{StringCharacter}+ { string.append( yytext() ); }
/* escape sequences */
"\\b" { string.append( '\b' ); }
"\\t" { string.append( '\t' ); }
"\\n" { string.append( '\n' ); }
"\\f" { string.append( '\f' ); }
"\\r" { string.append( '\r' ); }
"\\\"" { string.append( '\"' ); }
"\\'" { string.append( '\'' ); }
"\\\\" { string.append( '\\' ); }
\\[0-3]?{OctDigit}?{OctDigit} { char val = (char) Integer.parseInt(yytext().substring(1),8);
string.append( val ); }
/* error cases */
\\. { throw new ParseException("Illegal escape sequence \""+yytext()+"\"",yyline+1); }
{LineTerminator} { throw new ParseException("Unterminated string at end of line",yyline+1); }
}
/* error fallback */
.|\n { }
<<EOF>> { return new ParsedSymbol(ParsedSymbol.TYPE_EOF); }