mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-09-26 20:41:14 +00:00
More documentation.
This commit is contained in:
@@ -19,14 +19,22 @@ package com.jpexs.decompiler.graph;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
*
|
||||
* Abstract graph target visitor.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public abstract class AbstractGraphTargetVisitor implements GraphTargetVisitorInterface {
|
||||
|
||||
/**
|
||||
* Visits a graph target item.
|
||||
* @param item Graph target item
|
||||
*/
|
||||
@Override
|
||||
public abstract void visit(GraphTargetItem item);
|
||||
|
||||
/**
|
||||
* Visits all graph target items.
|
||||
* @param items Collection of graph target items
|
||||
*/
|
||||
@Override
|
||||
public final void visitAll(Collection<GraphTargetItem> items) {
|
||||
for (GraphTargetItem item : items) {
|
||||
|
||||
@@ -17,15 +17,25 @@
|
||||
package com.jpexs.decompiler.graph;
|
||||
|
||||
import com.jpexs.decompiler.graph.model.ContinueItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* Block interface.
|
||||
* For example, a block can be a loop, if statement, or a function.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public interface Block {
|
||||
|
||||
/**
|
||||
* Gets all sub continues.
|
||||
* @return List of continues
|
||||
*/
|
||||
public List<ContinueItem> getContinues();
|
||||
|
||||
/**
|
||||
* Gets all sub blocks.
|
||||
* @return List of blocks
|
||||
*/
|
||||
public List<List<GraphTargetItem>> getSubs();
|
||||
}
|
||||
|
||||
@@ -17,15 +17,26 @@
|
||||
package com.jpexs.decompiler.graph;
|
||||
|
||||
/**
|
||||
*
|
||||
* Compilation exception.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class CompilationException extends Exception {
|
||||
|
||||
/**
|
||||
* Line number.
|
||||
*/
|
||||
public int line;
|
||||
|
||||
/**
|
||||
* Error message.
|
||||
*/
|
||||
public String text;
|
||||
|
||||
/**
|
||||
* Constructs a new compilation exception.
|
||||
* @param message Error message
|
||||
* @param line Line number
|
||||
*/
|
||||
public CompilationException(String message, int line) {
|
||||
super("Compilation error on line " + line + ": " + message);
|
||||
this.line = line;
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.jpexs.decompiler.graph;
|
||||
|
||||
import com.jpexs.decompiler.flash.IdentifiersDeobfuscation;
|
||||
import com.jpexs.helpers.Helper;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
@@ -26,11 +27,14 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
*
|
||||
* Dotted chain class.
|
||||
* Represents a chain of names separated by dots.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class DottedChain implements Serializable, Comparable<DottedChain> {
|
||||
|
||||
//Basic dotted chains
|
||||
|
||||
public static final DottedChain EMPTY = new DottedChain(true);
|
||||
|
||||
public static final DottedChain UNBOUNDED = new DottedChain(new String[]{"*"});
|
||||
@@ -65,14 +69,29 @@ public class DottedChain implements Serializable, Comparable<DottedChain> {
|
||||
|
||||
public static final DottedChain ALL = new DottedChain(new String[]{"*"});
|
||||
|
||||
/**
|
||||
* Parts of the chain.
|
||||
*/
|
||||
private List<PathPart> parts;
|
||||
|
||||
/**
|
||||
* Is this chain null?
|
||||
*/
|
||||
private boolean isNull = false;
|
||||
|
||||
/**
|
||||
* Get the namespace suffix of the part at the given index.
|
||||
* @param index Index
|
||||
* @return Namespace suffix
|
||||
*/
|
||||
public String getNamespaceSuffix(int index) {
|
||||
return parts.get(index).namespaceSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the last namespace suffix.
|
||||
* @return Last namespace suffix
|
||||
*/
|
||||
public String getLastNamespaceSuffix() {
|
||||
if (parts.isEmpty()) {
|
||||
return "";
|
||||
@@ -80,6 +99,11 @@ public class DottedChain implements Serializable, Comparable<DottedChain> {
|
||||
return parts.get(parts.size() - 1).namespaceSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a dotted chain from a string without suffix.
|
||||
* @param name Name
|
||||
* @return Dotted chain
|
||||
*/
|
||||
public static final DottedChain parseNoSuffix(String name) {
|
||||
if (name == null) {
|
||||
return DottedChain.EMPTY;
|
||||
@@ -96,6 +120,11 @@ public class DottedChain implements Serializable, Comparable<DottedChain> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a dotted chain from a string with suffix.
|
||||
* @param name Name
|
||||
* @return Dotted chain
|
||||
*/
|
||||
public static final DottedChain parseWithSuffix(String name) {
|
||||
if (name == null) {
|
||||
return DottedChain.EMPTY;
|
||||
@@ -118,25 +147,46 @@ public class DottedChain implements Serializable, Comparable<DottedChain> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new dotted chain.
|
||||
* @param isNull Whether the chain is null
|
||||
*/
|
||||
private DottedChain(boolean isNull) {
|
||||
this.isNull = isNull;
|
||||
this.parts = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new dotted chain.
|
||||
* @param src Source chain
|
||||
*/
|
||||
public DottedChain(DottedChain src) {
|
||||
this.parts = new ArrayList<>(src.parts);
|
||||
this.isNull = src.isNull;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new dotted chain.
|
||||
* @param parts Parts
|
||||
*/
|
||||
public DottedChain(String[] parts) {
|
||||
this(Arrays.asList(parts));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new dotted chain.
|
||||
* @param parts Parts
|
||||
* @param isNull Whether the chain is null
|
||||
*/
|
||||
private DottedChain(List<PathPart> parts, boolean isNull) {
|
||||
this.parts = parts;
|
||||
this.isNull = isNull;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new dotted chain.
|
||||
* @param parts Parts
|
||||
*/
|
||||
public DottedChain(List<String> parts) {
|
||||
List<PathPart> newParts = new ArrayList<>();
|
||||
for (String part : parts) {
|
||||
@@ -145,10 +195,21 @@ public class DottedChain implements Serializable, Comparable<DottedChain> {
|
||||
this.parts = newParts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new dotted chain.
|
||||
* @param parts Parts
|
||||
* @param namespaceSuffixes Namespace suffixes
|
||||
*/
|
||||
public DottedChain(String[] parts, String[] namespaceSuffixes) {
|
||||
this(new boolean[parts.length], parts, namespaceSuffixes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new dotted chain.
|
||||
* @param attributes Attributes
|
||||
* @param parts Parts
|
||||
* @param namespaceSuffixes Namespace suffixes
|
||||
*/
|
||||
public DottedChain(boolean[] attributes, String[] parts, String[] namespaceSuffixes) {
|
||||
List<PathPart> newParts = new ArrayList<>();
|
||||
for (int i = 0; i < attributes.length; i++) {
|
||||
@@ -158,18 +219,35 @@ public class DottedChain implements Serializable, Comparable<DottedChain> {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this chain is top-level.
|
||||
* @return Whether this chain is top-level
|
||||
*/
|
||||
public boolean isTopLevel() {
|
||||
return !isNull && parts.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this chain is empty.
|
||||
* @return Whether this chain is empty
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return isNull;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of parts in this chain.
|
||||
* @return Number of parts
|
||||
*/
|
||||
public int size() {
|
||||
return parts.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the part at the given index.
|
||||
* @param index Index
|
||||
* @return Part
|
||||
*/
|
||||
public String get(int index) {
|
||||
if (index >= parts.size()) {
|
||||
throw new ArrayIndexOutOfBoundsException();
|
||||
@@ -178,6 +256,11 @@ public class DottedChain implements Serializable, Comparable<DottedChain> {
|
||||
return parts.get(index).name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the part at the given index is an attribute.
|
||||
* @param index Index
|
||||
* @return Whether the part at the given index is an attribute
|
||||
*/
|
||||
public boolean isAttribute(int index) {
|
||||
if (index >= parts.size()) {
|
||||
throw new ArrayIndexOutOfBoundsException();
|
||||
@@ -185,6 +268,11 @@ public class DottedChain implements Serializable, Comparable<DottedChain> {
|
||||
return parts.get(index).attribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the sub-chain of specific length.
|
||||
* @param count Length
|
||||
* @return
|
||||
*/
|
||||
public DottedChain subChain(int count) {
|
||||
if (count > parts.size()) {
|
||||
throw new ArrayIndexOutOfBoundsException();
|
||||
@@ -193,6 +281,10 @@ public class DottedChain implements Serializable, Comparable<DottedChain> {
|
||||
return new DottedChain(new ArrayList<>(parts.subList(0, count)), isNull);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets last part.
|
||||
* @return Last part
|
||||
*/
|
||||
public String getLast() {
|
||||
if (isNull) {
|
||||
return null;
|
||||
@@ -204,6 +296,10 @@ public class DottedChain implements Serializable, Comparable<DottedChain> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the last part is an attribute.
|
||||
* @return Whether the last part is an attribute
|
||||
*/
|
||||
public boolean isLastAttribute() {
|
||||
if (isNull) {
|
||||
return false;
|
||||
@@ -215,6 +311,10 @@ public class DottedChain implements Serializable, Comparable<DottedChain> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the chain without the last part.
|
||||
* @return Chain without the last part
|
||||
*/
|
||||
public DottedChain getWithoutLast() {
|
||||
if (isNull) {
|
||||
return null;
|
||||
@@ -226,6 +326,11 @@ public class DottedChain implements Serializable, Comparable<DottedChain> {
|
||||
return subChain(parts.size() - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a part to the chain with a suffix.
|
||||
* @param name Name
|
||||
* @return New chain
|
||||
*/
|
||||
public DottedChain addWithSuffix(String name) {
|
||||
String addedNameNoSuffix = name;
|
||||
String addedNamespaceSuffix = "";
|
||||
@@ -236,10 +341,23 @@ public class DottedChain implements Serializable, Comparable<DottedChain> {
|
||||
return add(addedNameNoSuffix, addedNamespaceSuffix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a part to the chain.
|
||||
* @param name Name
|
||||
* @param namespaceSuffix Namespace suffix
|
||||
* @return New chain
|
||||
*/
|
||||
public DottedChain add(String name, String namespaceSuffix) {
|
||||
return add(false, name, namespaceSuffix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a part to the chain.
|
||||
* @param attribute Whether the part is an attribute
|
||||
* @param name Name
|
||||
* @param namespaceSuffix Namespace suffix
|
||||
* @return New chain
|
||||
*/
|
||||
public DottedChain add(boolean attribute, String name, String namespaceSuffix) {
|
||||
if (name == null) {
|
||||
return new DottedChain(this);
|
||||
@@ -249,10 +367,23 @@ public class DottedChain implements Serializable, Comparable<DottedChain> {
|
||||
return new DottedChain(newParts, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds prefix to the chain.
|
||||
* @param name Name
|
||||
* @param namespaceSuffix Namespace suffix
|
||||
* @return New chain
|
||||
*/
|
||||
public DottedChain preAdd(String name, String namespaceSuffix) {
|
||||
return preAdd(false, name, namespaceSuffix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds prefix to the chain.
|
||||
* @param attribute Whether the part is an attribute
|
||||
* @param name Name
|
||||
* @param namespaceSuffix Namespace suffix
|
||||
* @return New chain
|
||||
*/
|
||||
public DottedChain preAdd(boolean attribute, String name, String namespaceSuffix) {
|
||||
if (name == null) {
|
||||
return new DottedChain(this);
|
||||
@@ -262,11 +393,22 @@ public class DottedChain implements Serializable, Comparable<DottedChain> {
|
||||
return new DottedChain(newParts, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* To string.
|
||||
* @return String
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return toRawString();
|
||||
}
|
||||
|
||||
/**
|
||||
* To string.
|
||||
* @param as3 Whether to print as AS3
|
||||
* @param raw Whether to print raw (without deobfuscation)
|
||||
* @param withSuffix Whether to print with suffix
|
||||
* @return String
|
||||
*/
|
||||
protected String toString(boolean as3, boolean raw, boolean withSuffix) {
|
||||
if (isNull) {
|
||||
return "";
|
||||
@@ -294,6 +436,10 @@ public class DottedChain implements Serializable, Comparable<DottedChain> {
|
||||
return ret.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* To file path.
|
||||
* @return File path
|
||||
*/
|
||||
public String toFilePath() {
|
||||
if (isNull) {
|
||||
return "";
|
||||
@@ -313,6 +459,10 @@ public class DottedChain implements Serializable, Comparable<DottedChain> {
|
||||
return ret.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* To list.
|
||||
* @return List
|
||||
*/
|
||||
public List<String> toList() {
|
||||
List<String> ret = new ArrayList<>();
|
||||
for (PathPart p : parts) {
|
||||
@@ -321,14 +471,27 @@ public class DottedChain implements Serializable, Comparable<DottedChain> {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* To printable string.
|
||||
* @param as3 Whether to print as AS3
|
||||
* @return Printable string
|
||||
*/
|
||||
public String toPrintableString(boolean as3) {
|
||||
return toString(as3, false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* To raw string. (without deobfuscation)
|
||||
* @return Raw string
|
||||
*/
|
||||
public String toRawString() { //Is SUFFIX correctly handled?
|
||||
return toString(false/*ignored*/, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash code.
|
||||
* @return Hash code
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 7;
|
||||
@@ -337,6 +500,11 @@ public class DottedChain implements Serializable, Comparable<DottedChain> {
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Equals.
|
||||
* @param obj Object
|
||||
* @return Whether this object is equal to the given object
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
@@ -355,23 +523,52 @@ public class DottedChain implements Serializable, Comparable<DottedChain> {
|
||||
return Objects.equals(this.parts, other.parts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare to.
|
||||
* @param o the object to be compared.
|
||||
* @return a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(DottedChain o) {
|
||||
return toRawString().compareTo(o.toRawString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Path part class.
|
||||
*/
|
||||
private static class PathPart implements Serializable {
|
||||
|
||||
/**
|
||||
* Name.
|
||||
*/
|
||||
public String name;
|
||||
|
||||
/**
|
||||
* Is this part an attribute?
|
||||
*/
|
||||
public boolean attribute;
|
||||
|
||||
/**
|
||||
* Namespace suffix.
|
||||
*/
|
||||
public String namespaceSuffix;
|
||||
|
||||
/**
|
||||
* Constructs a new path part.
|
||||
* @param name Name
|
||||
* @param attribute Whether this part is an attribute
|
||||
* @param namespaceSuffix Namespace suffix
|
||||
*/
|
||||
public PathPart(String name, boolean attribute, String namespaceSuffix) {
|
||||
this.name = name;
|
||||
this.attribute = attribute;
|
||||
this.namespaceSuffix = namespaceSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash code.
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 5;
|
||||
@@ -381,6 +578,11 @@ public class DottedChain implements Serializable, Comparable<DottedChain> {
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Equals.
|
||||
* @param obj Object
|
||||
* @return Whether this object is equal to the given object
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
|
||||
@@ -19,7 +19,7 @@ package com.jpexs.decompiler.graph;
|
||||
import com.jpexs.decompiler.graph.model.BinaryOp;
|
||||
|
||||
/**
|
||||
*
|
||||
* Equals type item.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public interface EqualsTypeItem extends BinaryOp {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -17,15 +17,31 @@
|
||||
package com.jpexs.decompiler.graph;
|
||||
|
||||
/**
|
||||
*
|
||||
* Exception thrown in the graph.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class GraphException {
|
||||
|
||||
/**
|
||||
* Start IP of thrown block
|
||||
*/
|
||||
public int start;
|
||||
/**
|
||||
* End IP of thrown block
|
||||
*/
|
||||
public int end;
|
||||
|
||||
/**
|
||||
* Target IP to go when exception is thrown
|
||||
*/
|
||||
public int target;
|
||||
|
||||
/**
|
||||
* Constructs a new exception
|
||||
* @param start Start IP
|
||||
* @param end End IP
|
||||
* @param target Target IP
|
||||
*/
|
||||
public GraphException(int start, int end, int target) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2024 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.graph;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class GraphExceptionParts {
|
||||
|
||||
public GraphPart start;
|
||||
public GraphPart end;
|
||||
public GraphPart target;
|
||||
|
||||
public GraphExceptionParts(GraphPart start, GraphPart end, GraphPart target) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.target = target;
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.jpexs.decompiler.graph;
|
||||
|
||||
import com.jpexs.decompiler.flash.BaseLocalData;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
@@ -24,90 +25,80 @@ import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
/**
|
||||
*
|
||||
* Represents a part of a graph.
|
||||
* Block of instructions which are executed in sequence.
|
||||
* No jumps or branches are allowed inside a GraphPart.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class GraphPart implements Serializable {
|
||||
|
||||
public static final int TYPE_NONE = 0;
|
||||
|
||||
public static final int TYPE_LOOP_HEADER = 1;
|
||||
|
||||
public static final int TYPE_PRELOOP = 3;
|
||||
|
||||
public static final int TYPE_REENTRY = 2;
|
||||
|
||||
public boolean traversed = false;
|
||||
|
||||
public int DFSP_pos = 0;
|
||||
|
||||
public GraphPart iloop_header;
|
||||
|
||||
public int type = TYPE_NONE;
|
||||
|
||||
public boolean irreducible = false;
|
||||
|
||||
/**
|
||||
* Start IP
|
||||
*/
|
||||
public int start = 0;
|
||||
|
||||
/**
|
||||
* End IP
|
||||
*/
|
||||
public int end = 0;
|
||||
|
||||
public int instanceCount = 0;
|
||||
|
||||
/**
|
||||
* Next parts
|
||||
*/
|
||||
public List<GraphPart> nextParts = new ArrayList<>();
|
||||
|
||||
public int posX = -1;
|
||||
|
||||
public int posY = -1;
|
||||
|
||||
/**
|
||||
* Path
|
||||
*/
|
||||
public GraphPath path = new GraphPath();
|
||||
|
||||
/**
|
||||
* Previous parts
|
||||
*/
|
||||
public List<GraphPart> refs = new ArrayList<>();
|
||||
|
||||
public boolean ignored = false;
|
||||
|
||||
/**
|
||||
* Level in the graph
|
||||
*/
|
||||
public int level;
|
||||
|
||||
/**
|
||||
* Discovered time in DFS
|
||||
*/
|
||||
public int discoveredTime;
|
||||
|
||||
/**
|
||||
* Finished time in DFS
|
||||
* Calculated in setTime.
|
||||
*/
|
||||
public int finishedTime;
|
||||
|
||||
/**
|
||||
* Closed time.
|
||||
* The node is closed when all its input edges are already visited.
|
||||
* Calculated in Graph.calculateClosedTime.
|
||||
*/
|
||||
public int closedTime;
|
||||
|
||||
/**
|
||||
* Order in DFS.
|
||||
* Calculated in setTime.
|
||||
*/
|
||||
public int order;
|
||||
|
||||
/**
|
||||
* Number of parts following this part.
|
||||
* Calculated in setNumblocks.
|
||||
*/
|
||||
public int numBlocks = Integer.MAX_VALUE;
|
||||
|
||||
//public List<GraphPart> throwParts = new ArrayList<>();
|
||||
public enum StopPartType {
|
||||
|
||||
NONE, AND_OR, COMMONPART
|
||||
}
|
||||
|
||||
//public StopPartType stopPartType = StopPartType.NONE;
|
||||
//public TranslateStack andOrStack; // Stores stack when AND_OR stopPart has been reached
|
||||
/*public class CommonPartStack { // Stores stack when COMMONPART stopPart has been reached
|
||||
|
||||
boolean isTrueStack;
|
||||
|
||||
TranslateStack trueStack;
|
||||
|
||||
TranslateStack falseStack;
|
||||
}/
|
||||
|
||||
//public ArrayList<CommonPartStack> commonPartStacks;
|
||||
|
||||
/* public void setAndOrStack(TranslateStack stack) {
|
||||
andOrStack = stack;
|
||||
}
|
||||
|
||||
public void setCommonPartStack(TranslateStack stack) {
|
||||
CommonPartStack currentStack = commonPartStacks.get(commonPartStacks.size() - 1);
|
||||
if (currentStack.isTrueStack) {
|
||||
currentStack.trueStack = stack;
|
||||
} else {
|
||||
currentStack.falseStack = stack;
|
||||
}
|
||||
}*/
|
||||
/**
|
||||
* Sets the time of this part in DFS.
|
||||
* @param time Time
|
||||
* @param ordered Ordered parts
|
||||
* @param visited Visited parts
|
||||
* @return Time
|
||||
*/
|
||||
public int setTime(int time, List<GraphPart> ordered, List<GraphPart> visited) {
|
||||
if (visited.contains(this)) {
|
||||
return time;
|
||||
@@ -126,6 +117,10 @@ public class GraphPart implements Serializable {
|
||||
return time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of blocks following this part.
|
||||
* @param numBlocks Number of blocks
|
||||
*/
|
||||
public void setNumblocks(int numBlocks) {
|
||||
this.numBlocks = numBlocks;
|
||||
numBlocks++;
|
||||
@@ -136,72 +131,20 @@ public class GraphPart implements Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean leadsToRecursive(BaseLocalData localData, Graph gr, GraphSource code, GraphPart prev, GraphPart part, HashSet<GraphPart> visited, List<Loop> loops, List<ThrowState> throwStates, boolean useThrow) throws InterruptedException {
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
|
||||
GraphPart tpart = gr.checkPart(null, localData, prev, this, null);
|
||||
if (tpart == null) {
|
||||
return false;
|
||||
}
|
||||
if (tpart != this) {
|
||||
return tpart.leadsTo(localData, gr, code, null, part, visited, loops, throwStates, useThrow);
|
||||
}
|
||||
Loop currentLoop = null;
|
||||
for (Loop l : loops) {
|
||||
/*if(l.phase==0){
|
||||
if(l.loopContinue==this){
|
||||
l.leadsToMark = 1;
|
||||
next = l.loopBreak;
|
||||
currentLoop = l;
|
||||
continue;
|
||||
}
|
||||
}*/
|
||||
if (l.phase == 1) {
|
||||
if (l.loopContinue == this) {
|
||||
return false;
|
||||
}
|
||||
if (l.loopPreContinue == this) {
|
||||
return false;
|
||||
}
|
||||
if (l.loopBreak == this) {
|
||||
//return false; //?
|
||||
}
|
||||
}
|
||||
}
|
||||
if (visited.contains(this)) {
|
||||
return false;
|
||||
}
|
||||
/*if (loops.contains(this)) {
|
||||
return false;
|
||||
}*/
|
||||
visited.add(this);
|
||||
if (end < code.size() && code.get(end).isBranch() && (code.get(end).ignoredLoops())) {
|
||||
return false;
|
||||
}
|
||||
for (GraphPart p : nextParts) {
|
||||
if (p == part) {
|
||||
return true;
|
||||
} else if (p.leadsTo(localData, gr, code, this, part, visited, loops, throwStates, useThrow)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (ThrowState ts : throwStates) {
|
||||
if (ts.state != 1) {
|
||||
if (ts.throwingParts.contains(this)) {
|
||||
GraphPart p = ts.targetPart;
|
||||
if (p == part) {
|
||||
return true;
|
||||
} else if (p.leadsTo(localData, gr, code, this, part, visited, loops, throwStates, useThrow)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this part leads to another part.
|
||||
* @param localData Local data
|
||||
* @param gr Graph
|
||||
* @param code Code
|
||||
* @param prev Previous part
|
||||
* @param part Part to check
|
||||
* @param visited Visited parts
|
||||
* @param loops Loops
|
||||
* @param throwStates Throw states
|
||||
* @param useThrow Use throw
|
||||
* @return True if this part leads to the other part
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
private boolean leadsTo(BaseLocalData localData, Graph gr, GraphSource code, GraphPart prev, GraphPart part, HashSet<GraphPart> visited, List<Loop> loops, List<ThrowState> throwStates, boolean useThrow) throws InterruptedException {
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
throw new InterruptedException();
|
||||
@@ -271,6 +214,18 @@ public class GraphPart implements Serializable {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this part leads to another part.
|
||||
* @param localData Local data
|
||||
* @param gr Graph
|
||||
* @param code Code
|
||||
* @param part Part to check
|
||||
* @param loops Loops
|
||||
* @param throwStates Throw states
|
||||
* @param useThrow Use throw
|
||||
* @return True if this part leads to the other part
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public boolean leadsTo(BaseLocalData localData, Graph gr, GraphSource code, GraphPart part, List<Loop> loops, List<ThrowState> throwStates, boolean useThrow) throws InterruptedException {
|
||||
for (Loop l : loops) {
|
||||
l.leadsToMark = 0;
|
||||
@@ -278,71 +233,20 @@ public class GraphPart implements Serializable {
|
||||
return leadsTo(localData, gr, code, null /*???*/, part, new HashSet<>(), loops, throwStates, useThrow);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new GraphPart.
|
||||
* @param start Start IP
|
||||
* @param end End IP
|
||||
*/
|
||||
public GraphPart(int start, int end) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
private GraphPart getNextPartPath(GraphPart original, GraphPath path, List<GraphPart> visited) {
|
||||
if (visited.contains(this) && (this == original)) {
|
||||
return null;
|
||||
}
|
||||
if (visited.contains(this) && (this != original)) {
|
||||
return null;
|
||||
}
|
||||
visited.add(this);
|
||||
for (GraphPart p : nextParts) {
|
||||
if (p == original) {
|
||||
continue;
|
||||
}
|
||||
if (p.path.equals(path)) {
|
||||
return p;
|
||||
} else if (p.path.length() >= path.length()) {
|
||||
GraphPart gp = p.getNextPartPath(original, path, visited);
|
||||
if (gp != null) {
|
||||
return gp;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public GraphPart getNextPartPath(List<GraphPart> ignored) {
|
||||
List<GraphPart> visited = new ArrayList<>();
|
||||
visited.addAll(ignored);
|
||||
if (visited.contains(this)) {
|
||||
visited.remove(this);
|
||||
}
|
||||
return getNextPartPath(this, path, visited);
|
||||
}
|
||||
|
||||
public GraphPart getNextSuperPartPath(List<GraphPart> ignored) {
|
||||
List<GraphPart> visited = new ArrayList<>();
|
||||
visited.addAll(ignored);
|
||||
return getNextSuperPartPath(this, path, visited);
|
||||
}
|
||||
|
||||
private GraphPart getNextSuperPartPath(GraphPart original, GraphPath path, List<GraphPart> visited) {
|
||||
if (visited.contains(this)) {
|
||||
return null;
|
||||
}
|
||||
visited.add(this);
|
||||
for (GraphPart p : nextParts) {
|
||||
if (p == original) {
|
||||
continue;
|
||||
}
|
||||
if (p.path.length() < path.length()) {
|
||||
return p;
|
||||
} else {
|
||||
GraphPart gp = p.getNextSuperPartPath(original, path, visited);
|
||||
if (gp != null) {
|
||||
return gp;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* To string.
|
||||
* @return String representation
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
if (end < start) {
|
||||
@@ -352,47 +256,48 @@ public class GraphPart implements Serializable {
|
||||
int printEnd = end + 1;
|
||||
|
||||
return "" + (printStart < 0 ? "(" : "") + printStart + (printStart < 0 ? ")" : "")
|
||||
+ "-" + (printEnd < 0 ? "(" : "") + printEnd + (printEnd < 0 ? ")" : "") + (instanceCount > 1 ? "(" + instanceCount + " links)" : "");
|
||||
+ "-" + (printEnd < 0 ? "(" : "") + printEnd + (printEnd < 0 ? ")" : "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this part contains an IP.
|
||||
* @param ip IP
|
||||
* @return True if this part contains the IP
|
||||
*/
|
||||
public boolean containsIP(int ip) {
|
||||
return (ip >= start) && (ip <= end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the height of this part - number of instructions in this part.
|
||||
* @return Height
|
||||
*/
|
||||
public int getHeight() {
|
||||
return end - start + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets IP at offset from start.
|
||||
* @param offset Offset
|
||||
* @return IP
|
||||
*/
|
||||
public int getPosAt(int offset) {
|
||||
return start + offset;
|
||||
}
|
||||
|
||||
private boolean containsPart(GraphPart part, GraphPart what, List<GraphPart> used) {
|
||||
if (used.contains(part)) {
|
||||
return false;
|
||||
}
|
||||
used.add(part);
|
||||
for (GraphPart subpart : part.nextParts) {
|
||||
if (subpart == what) {
|
||||
return true;
|
||||
}
|
||||
if (containsPart(subpart, what, used)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean containsPart(GraphPart what) {
|
||||
return containsPart(this, what, new ArrayList<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets sub parts. Currently only self is allowed.
|
||||
*/
|
||||
public List<GraphPart> getSubParts() {
|
||||
List<GraphPart> ret = new ArrayList<>();
|
||||
ret.add(this);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash code.
|
||||
* @return Hash code
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 3;
|
||||
@@ -400,6 +305,11 @@ public class GraphPart implements Serializable {
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Equals.
|
||||
* @param obj Object
|
||||
* @return True if equals
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
|
||||
@@ -19,23 +19,43 @@ package com.jpexs.decompiler.graph;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* Exception when part of the graph is changed.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class GraphPartChangeException extends Exception {
|
||||
|
||||
/**
|
||||
* IP
|
||||
*/
|
||||
private final int ip;
|
||||
|
||||
/**
|
||||
* Output
|
||||
*/
|
||||
private final List<GraphTargetItem> output;
|
||||
|
||||
/**
|
||||
* Constructs a new GraphPartChangeException
|
||||
* @param output Output
|
||||
* @param ip IP
|
||||
*/
|
||||
public GraphPartChangeException(List<GraphTargetItem> output, int ip) {
|
||||
this.output = output;
|
||||
this.ip = ip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the IP
|
||||
* @return IP
|
||||
*/
|
||||
public int getIp() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the output
|
||||
* @return Output
|
||||
*/
|
||||
public List<GraphTargetItem> getOutput() {
|
||||
return output;
|
||||
}
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2024 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.graph;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class GraphPartDecision {
|
||||
|
||||
public GraphPart part;
|
||||
public int way;
|
||||
|
||||
public GraphPartDecision(GraphPart part, int way) {
|
||||
this.part = part;
|
||||
this.way = way;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return part.toString() + ":" + way;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 3;
|
||||
hash = 59 * hash + Objects.hashCode(this.part);
|
||||
hash = 59 * hash + this.way;
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final GraphPartDecision other = (GraphPartDecision) obj;
|
||||
if (this.way != other.way) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(this.part, other.part)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,19 +19,35 @@ package com.jpexs.decompiler.graph;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
*
|
||||
* Edge of a graph. Represents a connection between two GraphParts.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class GraphPartEdge {
|
||||
|
||||
/**
|
||||
* From part
|
||||
*/
|
||||
public GraphPart from;
|
||||
|
||||
/**
|
||||
* To part
|
||||
*/
|
||||
public GraphPart to;
|
||||
|
||||
/**
|
||||
* Constructs a new edge
|
||||
* @param from From
|
||||
* @param to To
|
||||
*/
|
||||
public GraphPartEdge(GraphPart from, GraphPart to) {
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash code
|
||||
* @return Hash code
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 3;
|
||||
@@ -40,6 +56,11 @@ public class GraphPartEdge {
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Equals
|
||||
* @param obj Object to compare
|
||||
* @return True if equals
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
@@ -61,6 +82,10 @@ public class GraphPartEdge {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* To string
|
||||
* @return String representation
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return from.toString() + " -> " + to.toString();
|
||||
|
||||
@@ -21,14 +21,25 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* List which can store parts of the graph for each element.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class GraphPartMarkedArrayList<E> extends ArrayList<E> {
|
||||
|
||||
/**
|
||||
* List of parts for each element.
|
||||
*/
|
||||
private List<List<GraphPart>> listParts = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Current parts.
|
||||
*/
|
||||
private List<GraphPart> currentParts = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Constructs GraphPartMarkedArrayList from another collection.
|
||||
* @param collection
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public GraphPartMarkedArrayList(Collection<? extends E> collection) {
|
||||
super(collection);
|
||||
@@ -44,33 +55,63 @@ public class GraphPartMarkedArrayList<E> extends ArrayList<E> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs GraphPartMarkedArrayList.
|
||||
*/
|
||||
public GraphPartMarkedArrayList() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts new part.
|
||||
* @param part Part
|
||||
*/
|
||||
public void startPart(GraphPart part) {
|
||||
currentParts.add(part);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears current parts.
|
||||
*/
|
||||
public void clearCurrentParts() {
|
||||
currentParts = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds element to the collection.
|
||||
* @param e element whose presence in this collection is to be ensured
|
||||
* @return true if this collection changed as a result of the call
|
||||
*/
|
||||
@Override
|
||||
public boolean add(E e) {
|
||||
listParts.add(currentParts);
|
||||
return super.add(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the specified position in this list.
|
||||
* @param index index at which the specified element is to be inserted
|
||||
* @param element element to be inserted
|
||||
*/
|
||||
@Override
|
||||
public void add(int index, E element) {
|
||||
listParts.add(index, currentParts);
|
||||
super.add(index, element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parts at the specified index.
|
||||
* @param index index of the element
|
||||
* @return parts at the specified index
|
||||
*/
|
||||
public List<GraphPart> getPartsAt(int index) {
|
||||
return listParts.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the index of the part in the list.
|
||||
* @param part
|
||||
* @return
|
||||
*/
|
||||
public int indexOfPart(GraphPart part) {
|
||||
for (int i = 0; i < listParts.size(); i++) {
|
||||
List<GraphPart> list = listParts.get(i);
|
||||
@@ -81,6 +122,11 @@ public class GraphPartMarkedArrayList<E> extends ArrayList<E> {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all elements from the collection to this collection.
|
||||
* @param c collection containing elements to be added to this collection
|
||||
* @return true if this collection changed as a result of the call
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends E> c) {
|
||||
@@ -96,6 +142,13 @@ public class GraphPartMarkedArrayList<E> extends ArrayList<E> {
|
||||
return super.addAll(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all elements in the specified collection into this list at the
|
||||
* @param index index at which to insert the first element from the
|
||||
* specified collection
|
||||
* @param c collection containing elements to be added to this list
|
||||
* @return true if this list changed as a result of the call
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public boolean addAll(int index, Collection<? extends E> c) {
|
||||
@@ -111,6 +164,11 @@ public class GraphPartMarkedArrayList<E> extends ArrayList<E> {
|
||||
return super.addAll(index, c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the first occurrence of the specified element from this list, if
|
||||
* @param o element to be removed from this list, if present
|
||||
* @return true if an element was removed as a result of this call
|
||||
*/
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
if (contains(o)) {
|
||||
@@ -119,18 +177,32 @@ public class GraphPartMarkedArrayList<E> extends ArrayList<E> {
|
||||
return super.remove(o);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the element at the specified position in this list. Shifts any
|
||||
* @param index the index of the element to be removed
|
||||
* @return the element that was removed from the list
|
||||
*/
|
||||
@Override
|
||||
public E remove(int index) {
|
||||
listParts.remove(index);
|
||||
return super.remove(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the list.
|
||||
*/
|
||||
@Override
|
||||
public void clear() {
|
||||
listParts.clear();
|
||||
super.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a view of the portion of this list between the specified
|
||||
* @param fromIndex low endpoint (inclusive) of the subList
|
||||
* @param toIndex high endpoint (exclusive) of the subList
|
||||
* @return a view of the specified range within this list
|
||||
*/
|
||||
@Override
|
||||
public List<E> subList(int fromIndex, int toIndex) {
|
||||
GraphPartMarkedArrayList<E> ret = new GraphPartMarkedArrayList<E>(this);
|
||||
@@ -143,11 +215,20 @@ public class GraphPartMarkedArrayList<E> extends ArrayList<E> {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a shallow copy of this ArrayList instance.
|
||||
* @return a clone of this ArrayList instance
|
||||
*/
|
||||
@Override
|
||||
public Object clone() {
|
||||
return new GraphPartMarkedArrayList<>(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes from this list all of its elements that are contained in the
|
||||
* @param c collection containing elements to be removed from this list
|
||||
* @return true if this list changed as a result of the call
|
||||
*/
|
||||
@Override
|
||||
public boolean removeAll(Collection<?> c) {
|
||||
for (Object o : c) {
|
||||
|
||||
@@ -20,17 +20,24 @@ import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
|
||||
/**
|
||||
*
|
||||
* Queue of GraphPart objects.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class GraphPartQueue extends LinkedList<GraphPart> {
|
||||
|
||||
public Loop currentLoop;
|
||||
|
||||
/**
|
||||
* Constructs a GraphPartQueue containing the elements of the specified collection.
|
||||
* @param c
|
||||
*/
|
||||
public GraphPartQueue(Collection<? extends GraphPart> c) {
|
||||
super(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an empty GraphPartQueue.
|
||||
*/
|
||||
public GraphPartQueue() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,93 +22,159 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
*
|
||||
* Represents a path in a graph.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class GraphPath implements Serializable {
|
||||
|
||||
private final List<Integer> keys = new ArrayList<>();
|
||||
/**
|
||||
* List of IPs where the Path branched
|
||||
*/
|
||||
private final List<Integer> branchIps = new ArrayList<>();
|
||||
|
||||
private final List<Integer> vals = new ArrayList<>();
|
||||
/**
|
||||
* List of branch indices of which way the path went
|
||||
*/
|
||||
private final List<Integer> branchIndices = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Name of the root
|
||||
*/
|
||||
public final String rootName;
|
||||
|
||||
public GraphPath(String rootName, List<Integer> keys, List<Integer> vals) {
|
||||
/**
|
||||
* Constructs a GraphPath with the given root name, branch IPs and branch indices.
|
||||
* @param rootName Root name
|
||||
* @param branchIps Branch IPs
|
||||
* @param branchIndices Branch indices
|
||||
*/
|
||||
public GraphPath(String rootName, List<Integer> branchIps, List<Integer> branchIndices) {
|
||||
this.rootName = rootName;
|
||||
this.keys.addAll(keys);
|
||||
this.vals.addAll(vals);
|
||||
this.branchIps.addAll(branchIps);
|
||||
this.branchIndices.addAll(branchIndices);
|
||||
}
|
||||
|
||||
public GraphPath(List<Integer> keys, List<Integer> vals) {
|
||||
/**
|
||||
* Constructs a GraphPath with the given branch IPs and branch indices.
|
||||
* @param branchIps Branch IPs
|
||||
* @param branchIndices Branch indices
|
||||
*/
|
||||
public GraphPath(List<Integer> branchIps, List<Integer> branchIndices) {
|
||||
rootName = "";
|
||||
this.keys.addAll(keys);
|
||||
this.vals.addAll(vals);
|
||||
this.branchIps.addAll(branchIps);
|
||||
this.branchIndices.addAll(branchIndices);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a GraphPath
|
||||
*/
|
||||
public GraphPath() {
|
||||
rootName = "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the path starts with the given path.
|
||||
* @param p
|
||||
* @return True if the path starts with the given path, false otherwise
|
||||
*/
|
||||
public boolean startsWith(GraphPath p) {
|
||||
if (p.length() > length()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<Integer> otherKeys = new ArrayList<>(p.keys);
|
||||
List<Integer> otherVals = new ArrayList<>(p.vals);
|
||||
List<Integer> otherKeys = new ArrayList<>(p.branchIps);
|
||||
List<Integer> otherVals = new ArrayList<>(p.branchIndices);
|
||||
|
||||
for (int i = 0; i < p.length(); i++) {
|
||||
if (!Objects.equals(keys.get(i), otherKeys.get(i))) {
|
||||
if (!Objects.equals(branchIps.get(i), otherKeys.get(i))) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(vals.get(i), otherVals.get(i))) {
|
||||
if (!Objects.equals(branchIndices.get(i), otherVals.get(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new parent GraphPath with the given length.
|
||||
* @param len Length
|
||||
* @return
|
||||
*/
|
||||
public GraphPath parent(int len) {
|
||||
GraphPath par = new GraphPath(rootName);
|
||||
for (int i = 0; i < len; i++) {
|
||||
par.keys.add(keys.get(i));
|
||||
par.vals.add(vals.get(i));
|
||||
par.branchIps.add(branchIps.get(i));
|
||||
par.branchIndices.add(branchIndices.get(i));
|
||||
}
|
||||
return par;
|
||||
}
|
||||
|
||||
public GraphPath sub(int part, int codePos) {
|
||||
GraphPath next = new GraphPath(rootName, this.keys, this.vals);
|
||||
next.keys.add(codePos);
|
||||
next.vals.add(part);
|
||||
/**
|
||||
* Returns a new sub GraphPath with the given branch index and code position.
|
||||
* @param branchIndex Branch index
|
||||
* @param codePos Code position
|
||||
* @return New sub GraphPath
|
||||
*/
|
||||
public GraphPath sub(int branchIndex, int codePos) {
|
||||
GraphPath next = new GraphPath(rootName, this.branchIps, this.branchIndices);
|
||||
next.branchIps.add(codePos);
|
||||
next.branchIndices.add(branchIndex);
|
||||
return next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a GraphPath with the given root name.
|
||||
* @param rootName Root name
|
||||
*/
|
||||
public GraphPath(String rootName) {
|
||||
this.rootName = rootName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets length of the path.
|
||||
* @return Length
|
||||
*/
|
||||
public int length() {
|
||||
return vals.size();
|
||||
return branchIndices.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the branch index at the given index.
|
||||
* @param index Index
|
||||
* @return Branch index
|
||||
*/
|
||||
public int get(int index) {
|
||||
return vals.get(index);
|
||||
return branchIndices.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the IP at the given index.
|
||||
* @param index Index
|
||||
* @return IP
|
||||
*/
|
||||
public int getKey(int index) {
|
||||
return keys.get(index);
|
||||
return branchIps.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash code.
|
||||
* @return Hash code
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 5;
|
||||
hash = 23 * hash + arrHashCode(keys);
|
||||
hash = 23 * hash + arrHashCode(vals);
|
||||
hash = 23 * hash + arrHashCode(branchIps);
|
||||
hash = 23 * hash + arrHashCode(branchIndices);
|
||||
hash = 23 * hash + Objects.hashCode(rootName);
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Equals.
|
||||
* @param obj Eq
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
@@ -126,17 +192,22 @@ public class GraphPath implements Serializable {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!arrMatch(keys, other.keys)) {
|
||||
if (!arrMatch(branchIps, other.branchIps)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!arrMatch(vals, other.vals)) {
|
||||
if (!arrMatch(branchIndices, other.branchIndices)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash code for a list of integers.
|
||||
* @param arr List of integers
|
||||
* @return Hash code
|
||||
*/
|
||||
private static int arrHashCode(List<Integer> arr) {
|
||||
if (arr == null || arr.isEmpty()) {
|
||||
return 0;
|
||||
@@ -150,6 +221,12 @@ public class GraphPath implements Serializable {
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether two lists of integers match.
|
||||
* @param arr List of integers
|
||||
* @param arr2 List of integers
|
||||
* @return True if the lists match, false otherwise
|
||||
*/
|
||||
private static boolean arrMatch(List<Integer> arr, List<Integer> arr2) {
|
||||
if (arr.size() != arr2.size()) {
|
||||
return false;
|
||||
@@ -162,11 +239,15 @@ public class GraphPath implements Serializable {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the GraphPath.
|
||||
* @return String representation
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
String ret = rootName;
|
||||
for (int i = 0; i < keys.size(); i++) {
|
||||
ret += "/" + keys.get(i) + ":" + vals.get(i);
|
||||
for (int i = 0; i < branchIps.size(); i++) {
|
||||
ret += "/" + branchIps.get(i) + ":" + branchIndices.get(i);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.jpexs.decompiler.graph;
|
||||
|
||||
import com.jpexs.decompiler.flash.BaseLocalData;
|
||||
import com.jpexs.decompiler.flash.action.Action;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -25,23 +26,67 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* Graph source abstract class
|
||||
* @author JPEXS
|
||||
*/
|
||||
public abstract class GraphSource implements Serializable {
|
||||
|
||||
/**
|
||||
* Gets the size of the graph source
|
||||
* @return The size of the graph source
|
||||
*/
|
||||
public abstract int size();
|
||||
|
||||
/**
|
||||
* Gets the graph source item at the specified position
|
||||
* @param pos Position of the graph source item
|
||||
* @return The graph source item at the specified position
|
||||
*/
|
||||
public abstract GraphSourceItem get(int pos);
|
||||
|
||||
/**
|
||||
* Checks if the graph source is empty
|
||||
* @return True if the graph source is empty, false otherwise
|
||||
*/
|
||||
public abstract boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Translates the part of the graph source
|
||||
* @param graph Graph
|
||||
* @param part Graph part
|
||||
* @param localData Local data
|
||||
* @param stack Translate stack
|
||||
* @param start Start position
|
||||
* @param end End position
|
||||
* @param staticOperation Unused
|
||||
* @param path Path
|
||||
* @return List of graph target items
|
||||
* @throws InterruptedException
|
||||
* @throws GraphPartChangeException
|
||||
*/
|
||||
public abstract List<GraphTargetItem> translatePart(Graph graph, GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException, GraphPartChangeException;
|
||||
|
||||
/**
|
||||
* Gets the important addresses
|
||||
* @return Set of important addresses
|
||||
*/
|
||||
public abstract Set<Long> getImportantAddresses();
|
||||
|
||||
/**
|
||||
* Converts instruction at the specified position to string
|
||||
* @param pos Position of the instruction
|
||||
* @return Instruction as string
|
||||
*/
|
||||
public abstract String insToString(int pos);
|
||||
|
||||
/**
|
||||
* Visits the code
|
||||
* @param ip Start position
|
||||
* @param lastIp Last position
|
||||
* @param refs References
|
||||
* @param endIp End position
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
private void visitCode(int ip, int lastIp, HashMap<Integer, List<Integer>> refs, int endIp) throws InterruptedException {
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
throw new InterruptedException();
|
||||
@@ -96,6 +141,12 @@ public abstract class GraphSource implements Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits the code
|
||||
* @param alternateEntries Alternate entries
|
||||
* @return References
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public HashMap<Integer, List<Integer>> visitCode(List<Integer> alternateEntries) throws InterruptedException {
|
||||
HashMap<Integer, List<Integer>> refs = new HashMap<>();
|
||||
int siz = size();
|
||||
@@ -111,10 +162,25 @@ public abstract class GraphSource implements Serializable {
|
||||
return refs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts address to position
|
||||
* @param adr Address
|
||||
* @return Position
|
||||
*/
|
||||
public abstract int adr2pos(long adr);
|
||||
|
||||
/**
|
||||
* Converts address to position
|
||||
* @param adr Address
|
||||
* @param nearest Nearest
|
||||
* @return Position
|
||||
*/
|
||||
public abstract int adr2pos(long adr, boolean nearest);
|
||||
|
||||
/**
|
||||
* Gets the address after the code
|
||||
* @return Address after the code
|
||||
*/
|
||||
public long getAddressAfterCode() {
|
||||
if (isEmpty()) {
|
||||
return 0;
|
||||
@@ -123,8 +189,19 @@ public abstract class GraphSource implements Serializable {
|
||||
return lastAddr + get(size() - 1).getBytesLength();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts position to address
|
||||
* @param pos Position
|
||||
* @return Address
|
||||
*/
|
||||
public abstract long pos2adr(int pos);
|
||||
|
||||
/**
|
||||
* Converts position to address
|
||||
* @param pos Position
|
||||
* @param allowPosAfterCode Allow position after code
|
||||
* @return Address
|
||||
*/
|
||||
public final long pos2adr(int pos, boolean allowPosAfterCode) {
|
||||
if (pos == size() && allowPosAfterCode) {
|
||||
return getAddressAfterCode();
|
||||
|
||||
@@ -17,62 +17,144 @@
|
||||
package com.jpexs.decompiler.graph;
|
||||
|
||||
import com.jpexs.decompiler.flash.BaseLocalData;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* Item of Graph source. Usually an instruction.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public interface GraphSourceItem extends Serializable, Cloneable {
|
||||
|
||||
/**
|
||||
* Translate the item to target items.
|
||||
* @param localData Local data
|
||||
* @param stack Stack
|
||||
* @param output Output list
|
||||
* @param staticOperation Unused
|
||||
* @param path Path
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public void translate(BaseLocalData localData, TranslateStack stack, List<GraphTargetItem> output, int staticOperation, String path) throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Gets the number of stack items that are popped by this item.
|
||||
* @param localData Local data
|
||||
* @param stack Stack
|
||||
* @return Number of stack items that are popped by this item
|
||||
*/
|
||||
public int getStackPopCount(BaseLocalData localData, TranslateStack stack);
|
||||
|
||||
/**
|
||||
* Gets the number of stack items that are pushed by this item.
|
||||
* @param localData Local data
|
||||
* @param stack Stack
|
||||
* @return Number of stack items that are pushed by this item
|
||||
*/
|
||||
public int getStackPushCount(BaseLocalData localData, TranslateStack stack);
|
||||
|
||||
/**
|
||||
* Gets file offset.
|
||||
* @return File offset
|
||||
*/
|
||||
public long getFileOffset();
|
||||
|
||||
/**
|
||||
* Checks whether this item is a jump.
|
||||
* @return True if this item is a jump, false otherwise
|
||||
*/
|
||||
public boolean isJump();
|
||||
|
||||
/**
|
||||
* Checks whether this item is a branch.
|
||||
* @return True if this item is a branch, false otherwise
|
||||
*/
|
||||
public boolean isBranch();
|
||||
|
||||
/**
|
||||
* Checks whether this item is an exit (throw, return, etc.).
|
||||
* @return True if this item is an exit, false otherwise
|
||||
*/
|
||||
public boolean isExit();
|
||||
|
||||
/**
|
||||
* Gets the address.
|
||||
* @return Address
|
||||
*/
|
||||
public long getAddress();
|
||||
|
||||
/**
|
||||
* Gets the line offset.
|
||||
* @return Line offset
|
||||
*/
|
||||
public long getLineOffset();
|
||||
|
||||
/**
|
||||
* Checks whether the loops are ignored.
|
||||
* FIXME: What is this, how to use it?
|
||||
* @return True if the loops are ignored, false otherwise
|
||||
*/
|
||||
public boolean ignoredLoops();
|
||||
|
||||
/**
|
||||
* Gets branches
|
||||
* @param code Code
|
||||
* @return List of IPs to branch to
|
||||
*/
|
||||
public List<Integer> getBranches(GraphSource code);
|
||||
|
||||
/**
|
||||
* Checks whether this item is ignored.
|
||||
* @return True if this item is ignored, false otherwise
|
||||
*/
|
||||
public boolean isIgnored();
|
||||
|
||||
/**
|
||||
* Sets whether this item is ignored.
|
||||
* @param ignored True if this item is ignored, false otherwise
|
||||
* @param pos Sub position
|
||||
*/
|
||||
public void setIgnored(boolean ignored, int pos);
|
||||
|
||||
/**
|
||||
* Checks whether this item is a DeobfuscatePop instruction.
|
||||
* It is a special instruction for deobfuscation.
|
||||
* @return True if this item is a DeobfuscatePop instruction, false otherwise
|
||||
*/
|
||||
public boolean isDeobfuscatePop();
|
||||
|
||||
/**
|
||||
* Gets the line in the high level source code.
|
||||
* @return Line
|
||||
*/
|
||||
public int getLine();
|
||||
|
||||
/**
|
||||
* Gets the high level source code file name.
|
||||
* @return File name
|
||||
*/
|
||||
public String getFile();
|
||||
|
||||
/**
|
||||
* Gets length of the item in bytes.
|
||||
* @return Length of the item in bytes
|
||||
*/
|
||||
public abstract int getBytesLength();
|
||||
|
||||
/**
|
||||
* Gets virtual address. A virtual adress can be used for storing original
|
||||
* address before applying deobfuscation
|
||||
* Gets virtual address. A virtual address can be used for storing original
|
||||
* address before applying deobfuscation.
|
||||
*
|
||||
* @return
|
||||
* @return Virtual address
|
||||
*/
|
||||
public long getVirtualAddress();
|
||||
|
||||
/**
|
||||
* Sets virtual address. A virtual adress can be used for storing original
|
||||
* address before applying deobfuscation
|
||||
* Sets virtual address. A virtual address can be used for storing original
|
||||
* address before applying deobfuscation.
|
||||
*
|
||||
* @param virtualAddress
|
||||
* @param virtualAddress Virtual address
|
||||
*/
|
||||
public void setVirtualAddress(long virtualAddress);
|
||||
}
|
||||
|
||||
@@ -17,28 +17,71 @@
|
||||
package com.jpexs.decompiler.graph;
|
||||
|
||||
import com.jpexs.decompiler.flash.action.parser.pcode.FlasmLexer;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* Container for source items.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public interface GraphSourceItemContainer {
|
||||
|
||||
/**
|
||||
* Gets the size of the header.
|
||||
* @return The size of the header.
|
||||
*/
|
||||
public long getHeaderSize();
|
||||
|
||||
/**
|
||||
* Gets the sizes of the container parts.
|
||||
* @return List of sizes of the container parts.
|
||||
*/
|
||||
public List<Long> getContainerSizes();
|
||||
|
||||
/**
|
||||
* Sets the size of the container part.
|
||||
* @param index Index of the container part.
|
||||
* @param size Size of the container part.
|
||||
*/
|
||||
public void setContainerSize(int index, long size);
|
||||
|
||||
/**
|
||||
* Gets the ASM source between the specified position.
|
||||
* @param pos Index of container part
|
||||
* @return ASM source between the specified position
|
||||
*/
|
||||
public String getASMSourceBetween(int pos);
|
||||
|
||||
/**
|
||||
* Parses the division
|
||||
* @param size Size up to this point
|
||||
* @param lexer Lexer
|
||||
* @return
|
||||
*/
|
||||
public boolean parseDivision(long size, FlasmLexer lexer);
|
||||
|
||||
/**
|
||||
* Gets the names of the registers.
|
||||
* @return The names of the registers. Map of register index and register name.
|
||||
*/
|
||||
public HashMap<Integer, String> getRegNames();
|
||||
|
||||
/**
|
||||
* Translates the container to high level code.
|
||||
* @param contents List of contents of the container parts
|
||||
* @param lineStartItem Start source item of the line
|
||||
* @param stack Stack
|
||||
* @param output Output
|
||||
* @param regNames Register names
|
||||
* @param variables Variables
|
||||
* @param functions Functions
|
||||
*/
|
||||
public void translateContainer(List<List<GraphTargetItem>> contents, GraphSourceItem lineStartItem, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions);
|
||||
|
||||
/**
|
||||
* Gets the name of the container.
|
||||
* @return The name of the container
|
||||
*/
|
||||
public String getName();
|
||||
}
|
||||
|
||||
@@ -19,15 +19,26 @@ package com.jpexs.decompiler.graph;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
*
|
||||
* Graph source item with a position.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class GraphSourceItemPos implements Serializable {
|
||||
|
||||
/**
|
||||
* Source item
|
||||
*/
|
||||
public GraphSourceItem item;
|
||||
|
||||
/**
|
||||
* Position
|
||||
*/
|
||||
public int pos;
|
||||
|
||||
/**
|
||||
* Constructs a GraphSourceItemPos
|
||||
* @param item Source item
|
||||
* @param pos Position
|
||||
*/
|
||||
public GraphSourceItemPos(GraphSourceItem item, int pos) {
|
||||
this.item = item;
|
||||
this.pos = pos;
|
||||
|
||||
@@ -17,44 +17,28 @@
|
||||
package com.jpexs.decompiler.graph;
|
||||
|
||||
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.ConvertAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.FloatValueAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.IntegerValueAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.NameValuePair;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.NewArrayAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.NewObjectAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.StringAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.UndefinedAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.*;
|
||||
import com.jpexs.decompiler.flash.action.model.DirectValueActionItem;
|
||||
import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
import com.jpexs.decompiler.flash.ecma.ArrayType;
|
||||
import com.jpexs.decompiler.flash.ecma.EcmaScript;
|
||||
import com.jpexs.decompiler.flash.ecma.Null;
|
||||
import com.jpexs.decompiler.flash.ecma.ObjectType;
|
||||
import com.jpexs.decompiler.flash.ecma.Undefined;
|
||||
import com.jpexs.decompiler.flash.ecma.*;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter;
|
||||
import com.jpexs.decompiler.flash.helpers.hilight.HighlightData;
|
||||
import com.jpexs.decompiler.graph.model.BinaryOp;
|
||||
import com.jpexs.decompiler.graph.model.FalseItem;
|
||||
import com.jpexs.decompiler.graph.model.LocalData;
|
||||
import com.jpexs.decompiler.graph.model.NotItem;
|
||||
import com.jpexs.decompiler.graph.model.TrueItem;
|
||||
import com.jpexs.decompiler.graph.model.*;
|
||||
import com.jpexs.helpers.Reference;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* Graph target item - an item in high level representation of the code.
|
||||
* Decompilation target.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
|
||||
//Precedence levels
|
||||
|
||||
public static final int PRECEDENCE_PRIMARY = 0;
|
||||
|
||||
public static final int PRECEDENCE_POSTFIX = 1;
|
||||
@@ -89,24 +73,54 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
|
||||
public static final int NOPRECEDENCE = 16;
|
||||
|
||||
/**
|
||||
* Source item
|
||||
*/
|
||||
private GraphSourceItem src;
|
||||
|
||||
/**
|
||||
* Precedence level
|
||||
*/
|
||||
protected int precedence;
|
||||
|
||||
/**
|
||||
* More source items
|
||||
*/
|
||||
private List<GraphSourceItemPos> moreSrc;
|
||||
|
||||
/**
|
||||
* First part of the graph
|
||||
*/
|
||||
public GraphPart firstPart;
|
||||
|
||||
/**
|
||||
* Value
|
||||
*/
|
||||
public GraphTargetItem value;
|
||||
|
||||
/**
|
||||
* Source hilight data
|
||||
*/
|
||||
private HighlightData srcData;
|
||||
|
||||
/**
|
||||
* Line start item
|
||||
*/
|
||||
public GraphSourceItem lineStartItem;
|
||||
|
||||
/**
|
||||
* Gets the line start item
|
||||
* @return Line start item
|
||||
*/
|
||||
public GraphSourceItem getLineStartItem() {
|
||||
return lineStartItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a value to an item
|
||||
* @param r Value
|
||||
* @return Graph target item
|
||||
*/
|
||||
protected static GraphTargetItem valToItem(Object r) {
|
||||
if (r == null) {
|
||||
return null;
|
||||
@@ -156,6 +170,12 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplifies something
|
||||
* @param it Graph target item
|
||||
* @param implicitCoerce Implicit coerce
|
||||
* @return Simplified graph target item
|
||||
*/
|
||||
public static GraphTargetItem simplifySomething(GraphTargetItem it, String implicitCoerce) {
|
||||
if ((it instanceof SimpleValue) && implicitCoerce.isEmpty()) {
|
||||
if (((SimpleValue) it).isSimpleValue()) {
|
||||
@@ -189,10 +209,19 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
return it2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simplifies this.
|
||||
* @param implicitCoerce Implicit coerce
|
||||
* @return Simplified graph target item
|
||||
*/
|
||||
public GraphTargetItem simplify(String implicitCoerce) {
|
||||
return simplifySomething(this, implicitCoerce);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets line.
|
||||
* @return Line
|
||||
*/
|
||||
public int getLine() {
|
||||
if (src != null) {
|
||||
return src.getLine();
|
||||
@@ -200,6 +229,10 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets file.
|
||||
* @return File
|
||||
*/
|
||||
public String getFile() {
|
||||
if (src != null) {
|
||||
return src.getFile();
|
||||
@@ -207,6 +240,10 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets first graph part.
|
||||
* @return First graph part
|
||||
*/
|
||||
public GraphPart getFirstPart() {
|
||||
if (value == null) {
|
||||
return firstPart;
|
||||
@@ -218,14 +255,30 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs GraphTargetItem
|
||||
*/
|
||||
public GraphTargetItem() {
|
||||
this(null, null, NOPRECEDENCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs GraphTargetItem
|
||||
* @param src Source item
|
||||
* @param lineStartItem Line start item
|
||||
* @param precedence Precedence
|
||||
*/
|
||||
public GraphTargetItem(GraphSourceItem src, GraphSourceItem lineStartItem, int precedence) {
|
||||
this(src, lineStartItem, precedence, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs GraphTargetItem
|
||||
* @param src Source item
|
||||
* @param lineStartItem Line start item
|
||||
* @param precedence Precedence
|
||||
* @param value Value
|
||||
*/
|
||||
public GraphTargetItem(GraphSourceItem src, GraphSourceItem lineStartItem, int precedence, GraphTargetItem value) {
|
||||
this.src = src;
|
||||
this.lineStartItem = lineStartItem;
|
||||
@@ -233,10 +286,18 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets source item
|
||||
* @return Source item
|
||||
*/
|
||||
public GraphSourceItem getSrc() {
|
||||
return src;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets more source items
|
||||
* @return More source items
|
||||
*/
|
||||
public List<GraphSourceItemPos> getMoreSrc() {
|
||||
if (moreSrc == null) {
|
||||
moreSrc = new ArrayList<>();
|
||||
@@ -245,6 +306,10 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
return moreSrc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets highlight src data
|
||||
* @return
|
||||
*/
|
||||
protected HighlightData getSrcData() {
|
||||
if (srcData == null) {
|
||||
srcData = new HighlightData();
|
||||
@@ -253,10 +318,18 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
return srcData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets position
|
||||
* @return Position
|
||||
*/
|
||||
protected int getPos() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets needed sources
|
||||
* @return Needed sources
|
||||
*/
|
||||
public List<GraphSourceItemPos> getNeededSources() {
|
||||
List<GraphSourceItemPos> ret = new ArrayList<>();
|
||||
ret.add(new GraphSourceItemPos(src, getPos()));
|
||||
@@ -271,6 +344,13 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this to string semicoloned.
|
||||
* @param writer Writer
|
||||
* @param localData Local data
|
||||
* @return Writer
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public GraphTextWriter toStringSemicoloned(GraphTextWriter writer, LocalData localData) throws InterruptedException {
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
throw new InterruptedException();
|
||||
@@ -285,31 +365,74 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
return writer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if semicolon is needed
|
||||
* @return True if semicolon is needed
|
||||
*/
|
||||
public boolean needsSemicolon() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this to string as Boolean.
|
||||
* @param writer Writer
|
||||
* @param localData Local data
|
||||
* @return Writer
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public GraphTextWriter toStringBoolean(GraphTextWriter writer, LocalData localData) throws InterruptedException {
|
||||
return toString(writer, localData, "Boolean");
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this to string as String.
|
||||
* @param writer Writer
|
||||
* @param localData Local data
|
||||
* @return Writer
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public GraphTextWriter toStringString(GraphTextWriter writer, LocalData localData) throws InterruptedException {
|
||||
return toString(writer, localData, "String");
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this to string as int.
|
||||
* @param writer Writer
|
||||
* @param localData Local data
|
||||
* @return Writer
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public GraphTextWriter toStringInt(GraphTextWriter writer, LocalData localData) throws InterruptedException {
|
||||
return toString(writer, localData, "int");
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this to string as Number.
|
||||
* @param writer Writer
|
||||
* @param localData Local data
|
||||
* @return Writer
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public GraphTextWriter toStringNumber(GraphTextWriter writer, LocalData localData) throws InterruptedException {
|
||||
return toString(writer, localData, "Number");
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this to string.
|
||||
* @return String
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this to string.
|
||||
* @param writer Writer
|
||||
* @param localData Local data
|
||||
* @return Writer
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public GraphTextWriter toString(GraphTextWriter writer, LocalData localData, String implicitCoerce) throws InterruptedException {
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
throw new InterruptedException();
|
||||
@@ -321,10 +444,22 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
return writer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this to string.
|
||||
* @param localData Local data
|
||||
* @return String
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public GraphTextWriter toString(GraphTextWriter writer, LocalData localData) throws InterruptedException {
|
||||
return toString(writer, localData, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this to string.
|
||||
* @param localData Local data
|
||||
* @return String
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public String toString(LocalData localData) throws InterruptedException {
|
||||
HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false);
|
||||
toString(writer, localData);
|
||||
@@ -332,12 +467,34 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
return writer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Append this to a writer.
|
||||
* @param writer Writer
|
||||
* @param localData Local data
|
||||
* @return Writer
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public abstract GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Append this to a writer.
|
||||
* @param writer Writer
|
||||
* @param localData Local data
|
||||
* @return Writer
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public GraphTextWriter appendTry(GraphTextWriter writer, LocalData localData) throws InterruptedException {
|
||||
return appendTry(writer, localData, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Append this to a writer.
|
||||
* @param writer Writer
|
||||
* @param localData Local data
|
||||
* @param implicitCoerce Implicit coerce
|
||||
* @return Writer
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public GraphTextWriter appendTry(GraphTextWriter writer, LocalData localData, String implicitCoerce) throws InterruptedException {
|
||||
GraphTargetItem t = this;
|
||||
if (!implicitCoerce.isEmpty()) { //if implicit oerce equals explicit
|
||||
@@ -366,10 +523,18 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets precedence.
|
||||
* @return Precedence
|
||||
*/
|
||||
public int getPrecedence() {
|
||||
return precedence;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this can be evaluated statically.
|
||||
* @return True if this can be evaluated statically
|
||||
*/
|
||||
public boolean isCompileTime() {
|
||||
Set<GraphTargetItem> dependencies = new HashSet<>();
|
||||
if (!((this instanceof SimpleValue) && ((SimpleValue) this).isSimpleValue())) {
|
||||
@@ -378,14 +543,29 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
return isCompileTime(dependencies);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this can be evaluated statically.
|
||||
* @param dependencies Dependencies
|
||||
* @return True if this can be evaluated statically
|
||||
*/
|
||||
public boolean isCompileTime(Set<GraphTargetItem> dependencies) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this can be evaluated statically.
|
||||
* @param dependencies Dependencies
|
||||
* @return True if this can be evaluated statically
|
||||
*/
|
||||
public boolean isConvertedCompileTime(Set<GraphTargetItem> dependencies) {
|
||||
return isCompileTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this has side effects.
|
||||
* For example function call has side effect, but variable access does not.
|
||||
* @return True if this has side effects
|
||||
*/
|
||||
public boolean hasSideEffect() {
|
||||
Reference<Boolean> ref = new Reference<>(false);
|
||||
visitRecursively(new AbstractGraphTargetVisitor() {
|
||||
@@ -399,26 +579,51 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
return ref.getVal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether it is computed via variables.
|
||||
* @return True if it is computed via variables
|
||||
*/
|
||||
public boolean isVariableComputed() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes EcmaScript result.
|
||||
* @return EcmaScript result
|
||||
*/
|
||||
public Object getResult() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes EcmaScript result as number.
|
||||
* @return EcmaScript result as number
|
||||
*/
|
||||
public Double getResultAsNumber() {
|
||||
return EcmaScript.toNumberAs2(getResult());
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes EcmaScript result as string.
|
||||
* @return EcmaScript result as string
|
||||
*/
|
||||
public String getResultAsString() {
|
||||
return EcmaScript.toString(getResult());
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes EcmaScript result as boolean.
|
||||
* @return EcmaScript result as boolean
|
||||
*/
|
||||
public Boolean getResultAsBoolean() {
|
||||
return EcmaScript.toBoolean(getResult());
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this to string without quotes.
|
||||
* @param localData Local data
|
||||
* @return String
|
||||
*/
|
||||
public String toStringNoQuotes(LocalData localData) {
|
||||
try {
|
||||
HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false);
|
||||
@@ -431,6 +636,13 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this to string without quotes.
|
||||
* @param writer Writer
|
||||
* @param localData Local data
|
||||
* @return Writer
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public GraphTextWriter toStringNoQuotes(GraphTextWriter writer, LocalData localData) throws InterruptedException {
|
||||
writer.startOffset(src, getLineStartItem(), getPos(), srcData);
|
||||
appendToNoQuotes(writer, localData);
|
||||
@@ -438,30 +650,64 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
return writer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends this to a writer without quotes.
|
||||
* @param writer Writer
|
||||
* @param localData Local data
|
||||
* @return Writer
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public GraphTextWriter appendToNoQuotes(GraphTextWriter writer, LocalData localData) throws InterruptedException {
|
||||
return toString(writer, localData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this without coercion.
|
||||
* @return This without coercion
|
||||
*/
|
||||
public GraphTargetItem getNotCoerced() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this without coercion and without duplicates.
|
||||
* @return This without coercion and without duplicates
|
||||
*/
|
||||
public GraphTargetItem getNotCoercedNoDup() {
|
||||
return getNotCoerced();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this through registers.
|
||||
* @return This through registers
|
||||
*/
|
||||
public GraphTargetItem getThroughRegister() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this needs a new line.
|
||||
* @return True if this needs a new line
|
||||
*/
|
||||
public boolean needsNewLine() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this handles new line.
|
||||
* @return True if this handles new line
|
||||
*/
|
||||
public boolean handlesNewLine() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this to string with new line.
|
||||
* @param writer Writer
|
||||
* @param localData Local data
|
||||
* @return Writer
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public GraphTextWriter toStringNL(GraphTextWriter writer, LocalData localData) throws InterruptedException {
|
||||
writer.startOffset(src, getLineStartItem(), getPos(), srcData);
|
||||
appendTry(writer, localData);
|
||||
@@ -472,26 +718,57 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
return writer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this is empty.
|
||||
* @return True if this is empty
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets through items that cannot be statically computed.
|
||||
* @return Through item that cannot be statically computed
|
||||
*/
|
||||
public GraphTargetItem getThroughNotCompilable() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets item through duplicates.
|
||||
* @return Item through duplicates
|
||||
*/
|
||||
public GraphTargetItem getThroughDuplicate() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the value equals.
|
||||
* @param target Target
|
||||
* @return True if the value equals
|
||||
*/
|
||||
public boolean valueEquals(GraphTargetItem target) {
|
||||
return equals(target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this to source (low level code).
|
||||
* @param localData Local data
|
||||
* @param generator Source generator
|
||||
* @return Source
|
||||
* @throws CompilationException
|
||||
*/
|
||||
public List<GraphSourceItem> toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this to source (low level code) and ignore return value.
|
||||
* @param localData Local data
|
||||
* @param generator Source generator
|
||||
* @return Source
|
||||
* @throws CompilationException
|
||||
*/
|
||||
public List<GraphSourceItem> toSourceIgnoreReturnValue(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException {
|
||||
if (!hasReturnValue()) {
|
||||
return toSource(localData, generator);
|
||||
@@ -499,12 +776,26 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
return generator.generateDiscardValue(localData, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this to source (low level code). with BinaryOp
|
||||
* @param op Binary operation
|
||||
* @param action Action
|
||||
* @return Source
|
||||
*/
|
||||
protected List<GraphSourceItem> toSourceBinary(BinaryOp op, GraphSourceItem action) {
|
||||
List<GraphSourceItem> ret = new ArrayList<>();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges Object list to one list of GraphTargetItems
|
||||
* @param localData Local data
|
||||
* @param gen Source generator
|
||||
* @param tar Objects
|
||||
* @return List of GraphTargetItems
|
||||
* @throws CompilationException
|
||||
*/
|
||||
public static List<GraphSourceItem> toSourceMerge(SourceGeneratorLocalData localData, SourceGenerator gen, Object... tar) throws CompilationException {
|
||||
List<GraphSourceItem> ret = new ArrayList<>();
|
||||
for (Object o : tar) {
|
||||
@@ -532,8 +823,16 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this has return value.
|
||||
* @return True if this has return value
|
||||
*/
|
||||
public abstract boolean hasReturnValue();
|
||||
|
||||
/**
|
||||
* Gets all sub items.
|
||||
* @return All sub items
|
||||
*/
|
||||
public List<GraphTargetItem> getAllSubItems() {
|
||||
List<GraphTargetItem> ret = new ArrayList<>();
|
||||
visit(new AbstractGraphTargetVisitor() {
|
||||
@@ -547,6 +846,10 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all sub items recursively.
|
||||
* @return All sub items recursively
|
||||
*/
|
||||
public Set<GraphTargetItem> getAllSubItemsRecursively() {
|
||||
Set<GraphTargetItem> ret = new HashSet<>();
|
||||
visitRecursively(new AbstractGraphTargetVisitor() {
|
||||
@@ -558,6 +861,10 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits this recursively.
|
||||
* @param visitor Visitor
|
||||
*/
|
||||
public final void visitRecursively(GraphTargetVisitorInterface visitor) {
|
||||
Set<GraphTargetItem> visitedItems = new HashSet<>();
|
||||
visit(new AbstractGraphTargetVisitor() {
|
||||
@@ -572,6 +879,10 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits this recursively without using Blocks.
|
||||
* @param visitor Visitor
|
||||
*/
|
||||
public final void visitRecursivelyNoBlock(GraphTargetVisitorInterface visitor) {
|
||||
Set<GraphTargetItem> visitedItems = new HashSet<>();
|
||||
visitNoBlock(new AbstractGraphTargetVisitor() {
|
||||
@@ -586,18 +897,34 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits this.
|
||||
* @param visitor Visitor
|
||||
*/
|
||||
public void visit(GraphTargetVisitorInterface visitor) {
|
||||
if (value != null) {
|
||||
visitor.visit(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits this without using Blocks.
|
||||
* @param visitor
|
||||
*/
|
||||
public void visitNoBlock(GraphTargetVisitorInterface visitor) {
|
||||
visit(visitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets return type.
|
||||
* @return
|
||||
*/
|
||||
public abstract GraphTargetItem returnType();
|
||||
|
||||
/**
|
||||
* Clone this.
|
||||
* @return Cloned item
|
||||
*/
|
||||
@Override
|
||||
public GraphTargetItem clone() {
|
||||
try {
|
||||
@@ -607,10 +934,25 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverts this item.
|
||||
* @param src Source item
|
||||
* @return Inverted item
|
||||
*/
|
||||
public GraphTargetItem invert(GraphSourceItem src) {
|
||||
return new NotItem(src, getLineStartItem(), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends this to a writer.
|
||||
* @param prevLineItem Previous line item
|
||||
* @param writer Writer
|
||||
* @param localData Local data
|
||||
* @param commands Commands
|
||||
* @param asBlock As block
|
||||
* @return Writer
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public GraphTextWriter appendCommands(GraphTargetItem prevLineItem, GraphTextWriter writer, LocalData localData, List<GraphTargetItem> commands, boolean asBlock) throws InterruptedException {
|
||||
|
||||
//This may be useful in the future, but we must handle obfuscated SWFs where there is only one debugline instruction on the beggining.
|
||||
@@ -642,11 +984,24 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
return writer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append this to a writer as a Block.
|
||||
* @param prevLineItem
|
||||
* @param writer
|
||||
* @param localData
|
||||
* @param commands
|
||||
* @return
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public GraphTextWriter appendBlock(GraphTargetItem prevLineItem, GraphTextWriter writer, LocalData localData, List<GraphTargetItem> commands) throws InterruptedException {
|
||||
appendCommands(prevLineItem, writer, localData, commands, true);
|
||||
return writer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this as long.
|
||||
* @return
|
||||
*/
|
||||
public long getAsLong() {
|
||||
if (this instanceof DirectValueActionItem) {
|
||||
DirectValueActionItem dvai = (DirectValueActionItem) this;
|
||||
@@ -656,10 +1011,21 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this is identical to other.
|
||||
* @param other Other
|
||||
* @return True if this is identical to other
|
||||
*/
|
||||
public boolean isIdentical(GraphTargetItem other) {
|
||||
return this == other;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alternative of Objects.equals() for GraphTargetItem.
|
||||
* @param o1 Object 1
|
||||
* @param o2 Object 2
|
||||
* @return True if objects are value equal
|
||||
*/
|
||||
public static boolean objectsValueEquals(Object o1, Object o2) {
|
||||
if (o1 == null && o2 == null) {
|
||||
return true;
|
||||
|
||||
@@ -19,12 +19,20 @@ package com.jpexs.decompiler.graph;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
*
|
||||
* Graph source visitor interface.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public interface GraphTargetVisitorInterface {
|
||||
|
||||
/**
|
||||
* Visits a graph target item.
|
||||
* @param item Graph target item
|
||||
*/
|
||||
public void visit(GraphTargetItem item);
|
||||
|
||||
/**
|
||||
* Visits all graph target items.
|
||||
* @param items Collection of graph target items
|
||||
*/
|
||||
public void visitAll(Collection<GraphTargetItem> items);
|
||||
}
|
||||
|
||||
@@ -17,48 +17,88 @@
|
||||
package com.jpexs.decompiler.graph;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* A loop in a graph.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class Loop implements Serializable {
|
||||
|
||||
/**
|
||||
* Continue part of the loop
|
||||
*/
|
||||
public GraphPart loopContinue;
|
||||
|
||||
/**
|
||||
* Break part of the loop
|
||||
*/
|
||||
public GraphPart loopBreak;
|
||||
|
||||
/**
|
||||
* Precontinue part of the loop.
|
||||
* A precontinue is a part of the loop that is executed before the continue part.
|
||||
* Example of this is a for loop with continue statement.
|
||||
*/
|
||||
public GraphPart loopPreContinue;
|
||||
|
||||
/**
|
||||
* Back edges of the loop
|
||||
*/
|
||||
public Set<GraphPart> backEdges = new HashSet<>();
|
||||
|
||||
/**
|
||||
* Break candidates of the loop
|
||||
*/
|
||||
public List<GraphPart> breakCandidates = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Levels of the break candidates
|
||||
*/
|
||||
public List<Integer> breakCandidatesLevels = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Unique id of the loop
|
||||
*/
|
||||
public final long id;
|
||||
|
||||
/**
|
||||
* Mark for leads to method
|
||||
*/
|
||||
public int leadsToMark;
|
||||
|
||||
/**
|
||||
* Mark for reachable method
|
||||
*/
|
||||
public int reachableMark;
|
||||
|
||||
/**
|
||||
* Phase of the loop.
|
||||
* The decompiler marks here whether the loop is already processed or not.
|
||||
*/
|
||||
public int phase;
|
||||
|
||||
/**
|
||||
* Break candidates are locked
|
||||
*/
|
||||
public int breakCandidatesLocked = 0;
|
||||
|
||||
public List<GraphTargetItem> precontinueCommands = null;
|
||||
|
||||
/**
|
||||
* Constructs a loop
|
||||
* @param id Unique id of the loop
|
||||
* @param loopContinue Continue part of the loop
|
||||
* @param loopBreak Break part of the loop
|
||||
*/
|
||||
public Loop(long id, GraphPart loopContinue, GraphPart loopBreak) {
|
||||
this.loopContinue = loopContinue;
|
||||
this.loopBreak = loopBreak;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* To string method
|
||||
* @return String representation of the loop
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
Set<String> edgesAsStr = new HashSet<>();
|
||||
@@ -73,6 +113,10 @@ public class Loop implements Serializable {
|
||||
return "loop(id:" + id + (loopPreContinue != null ? ",precontinue:" + loopPreContinue : "") + ",continue:" + loopContinue + ", break:" + loopBreak + ", phase:" + phase + ", backedges: " + String.join(",", edgesAsStr) + ", breakCandidates: " + String.join(",", bcAsStr) + ")";
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash code
|
||||
* @return Hash code of the loop
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 3;
|
||||
@@ -80,6 +124,11 @@ public class Loop implements Serializable {
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Equals
|
||||
* @param obj Object to compare
|
||||
* @return True if the object is equal to this loop
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
|
||||
@@ -21,37 +21,66 @@ import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.graph.model.LocalData;
|
||||
|
||||
/**
|
||||
*
|
||||
* Special item for marking a position in the graph.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class MarkItem extends GraphTargetItem {
|
||||
|
||||
/**
|
||||
* Mark string
|
||||
*/
|
||||
private final String mark;
|
||||
|
||||
/**
|
||||
* Constructs a new mark item.
|
||||
* @param mark Mark string
|
||||
*/
|
||||
public MarkItem(String mark) {
|
||||
super(null, null, NOPRECEDENCE);
|
||||
this.mark = mark;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends this item to the writer.
|
||||
* @param writer Writer
|
||||
* @param localData Local data
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) {
|
||||
return writer.append("// ").append(AppResources.translate("decompilerMark")).append(":").append(mark);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the mark string.
|
||||
* @return
|
||||
*/
|
||||
public String getMark() {
|
||||
return mark;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this item is empty.
|
||||
* @return Always true
|
||||
*/
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this item has a return value.
|
||||
* @return Always false
|
||||
*/
|
||||
@Override
|
||||
public boolean hasReturnValue() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the return type of this item.
|
||||
* @return Unbounded
|
||||
*/
|
||||
@Override
|
||||
public GraphTargetItem returnType() {
|
||||
return TypeItem.UNBOUNDED;
|
||||
|
||||
@@ -18,26 +18,46 @@ package com.jpexs.decompiler.graph;
|
||||
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.graph.model.LocalData;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* An item that cannot be statically computed.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class NotCompileTimeItem extends GraphTargetItem {
|
||||
|
||||
/**
|
||||
* Object that cannot be statically computed.
|
||||
*/
|
||||
public GraphTargetItem object;
|
||||
|
||||
/**
|
||||
* Constructs a new NotCompileTimeItem.
|
||||
* @param instruction Instruction
|
||||
* @param lineStartIns Line start instruction
|
||||
* @param object Object that cannot be statically computed
|
||||
*/
|
||||
public NotCompileTimeItem(GraphSourceItem instruction, GraphSourceItem lineStartIns, GraphTargetItem object) {
|
||||
super(instruction, lineStartIns, NOPRECEDENCE);
|
||||
this.object = object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this item can be computed statically.
|
||||
* @param dependencies Dependencies
|
||||
* @return Whether this item can be computed statically
|
||||
*/
|
||||
@Override
|
||||
public boolean isCompileTime(Set<GraphTargetItem> dependencies) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets through the object that cannot be statically computed.
|
||||
* @return Through the object that cannot be statically computed
|
||||
*/
|
||||
@Override
|
||||
public GraphTargetItem getThroughNotCompilable() {
|
||||
if (object == null) {
|
||||
@@ -46,16 +66,31 @@ public class NotCompileTimeItem extends GraphTargetItem {
|
||||
return object.getThroughNotCompilable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends this item to the writer.
|
||||
* @param writer Writer
|
||||
* @param localData Local data
|
||||
* @return Writer
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
@Override
|
||||
public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException {
|
||||
return object.toString(writer, localData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this item has a return value.
|
||||
* @return Whether this item has a return value
|
||||
*/
|
||||
@Override
|
||||
public boolean hasReturnValue() {
|
||||
return object.hasReturnValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the return type of this item.
|
||||
* @return Return type of this item
|
||||
*/
|
||||
@Override
|
||||
public GraphTargetItem returnType() {
|
||||
return TypeItem.UNBOUNDED;
|
||||
|
||||
@@ -19,7 +19,7 @@ package com.jpexs.decompiler.graph;
|
||||
import com.jpexs.decompiler.graph.model.BinaryOp;
|
||||
|
||||
/**
|
||||
*
|
||||
* Not equals type item.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public interface NotEqualsTypeItem extends BinaryOp {
|
||||
|
||||
@@ -17,15 +17,22 @@
|
||||
package com.jpexs.decompiler.graph;
|
||||
|
||||
/**
|
||||
*
|
||||
* Stack for scope.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class ScopeStack extends TranslateStack {
|
||||
|
||||
/**
|
||||
* Constructs a new ScopeStack.
|
||||
* @param allowEmpty Whether empty stack is allowed
|
||||
*/
|
||||
public ScopeStack(boolean allowEmpty) {
|
||||
super(allowEmpty ? "scope" : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new ScopeStack.
|
||||
*/
|
||||
public ScopeStack() {
|
||||
this(true);
|
||||
}
|
||||
|
||||
@@ -20,10 +20,13 @@ import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* Second pass data.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class SecondPassData {
|
||||
|
||||
/**
|
||||
* All switch parts.
|
||||
*/
|
||||
public Set<GraphPart> allSwitchParts = new HashSet<>();
|
||||
}
|
||||
|
||||
@@ -17,17 +17,28 @@
|
||||
package com.jpexs.decompiler.graph;
|
||||
|
||||
/**
|
||||
*
|
||||
* Second pass exception.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class SecondPassException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Second pass data.
|
||||
*/
|
||||
private final SecondPassData data;
|
||||
|
||||
/**
|
||||
* Constructs a new SecondPassException.
|
||||
* @param data Second pass data
|
||||
*/
|
||||
public SecondPassException(SecondPassData data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the second pass data.
|
||||
* @return Second pass data
|
||||
*/
|
||||
public SecondPassData getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
package com.jpexs.decompiler.graph;
|
||||
|
||||
/**
|
||||
*
|
||||
* Simple value interface.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public interface SimpleValue {
|
||||
|
||||
@@ -17,68 +17,194 @@
|
||||
package com.jpexs.decompiler.graph;
|
||||
|
||||
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
|
||||
import com.jpexs.decompiler.graph.model.AndItem;
|
||||
import com.jpexs.decompiler.graph.model.BreakItem;
|
||||
import com.jpexs.decompiler.graph.model.CommaExpressionItem;
|
||||
import com.jpexs.decompiler.graph.model.ContinueItem;
|
||||
import com.jpexs.decompiler.graph.model.DoWhileItem;
|
||||
import com.jpexs.decompiler.graph.model.DuplicateItem;
|
||||
import com.jpexs.decompiler.graph.model.FalseItem;
|
||||
import com.jpexs.decompiler.graph.model.ForItem;
|
||||
import com.jpexs.decompiler.graph.model.IfItem;
|
||||
import com.jpexs.decompiler.graph.model.NotItem;
|
||||
import com.jpexs.decompiler.graph.model.OrItem;
|
||||
import com.jpexs.decompiler.graph.model.PopItem;
|
||||
import com.jpexs.decompiler.graph.model.PushItem;
|
||||
import com.jpexs.decompiler.graph.model.SwitchItem;
|
||||
import com.jpexs.decompiler.graph.model.TernarOpItem;
|
||||
import com.jpexs.decompiler.graph.model.TrueItem;
|
||||
import com.jpexs.decompiler.graph.model.WhileItem;
|
||||
import com.jpexs.decompiler.graph.model.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* Source generator interface. A low-level code generator.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public interface SourceGenerator {
|
||||
|
||||
/**
|
||||
* Generates source code for PushItem.
|
||||
* @param localData Local data
|
||||
* @param item PushItem
|
||||
* @return List of GraphSourceItem
|
||||
* @throws CompilationException
|
||||
*/
|
||||
public List<GraphSourceItem> generate(SourceGeneratorLocalData localData, PushItem item) throws CompilationException;
|
||||
|
||||
/**
|
||||
* Generates source code for PopItem.
|
||||
* @param localData Local data
|
||||
* @param item PopItem
|
||||
* @return List of GraphSourceItem
|
||||
* @throws CompilationException
|
||||
*/
|
||||
public List<GraphSourceItem> generate(SourceGeneratorLocalData localData, PopItem item) throws CompilationException;
|
||||
|
||||
/**
|
||||
* Generates source code for TrueItem.
|
||||
* @param localData Local data
|
||||
* @param item TrueItem
|
||||
* @return List of GraphSourceItem
|
||||
* @throws CompilationException
|
||||
*/
|
||||
public List<GraphSourceItem> generate(SourceGeneratorLocalData localData, TrueItem item) throws CompilationException;
|
||||
|
||||
/**
|
||||
* Generates source code for FalseItem.
|
||||
* @param localData Local data
|
||||
* @param item FalseItem
|
||||
* @return List of GraphSourceItem
|
||||
* @throws CompilationException
|
||||
*/
|
||||
public List<GraphSourceItem> generate(SourceGeneratorLocalData localData, FalseItem item) throws CompilationException;
|
||||
|
||||
/**
|
||||
* Generates source code for AndItem.
|
||||
* @param localData Local data
|
||||
* @param item AndItem
|
||||
* @return List of GraphSourceItem
|
||||
* @throws CompilationException
|
||||
*/
|
||||
public List<GraphSourceItem> generate(SourceGeneratorLocalData localData, AndItem item) throws CompilationException;
|
||||
|
||||
/**
|
||||
* Generates source code for OrItem.
|
||||
* @param localData Local data
|
||||
* @param item OrItem
|
||||
* @return List of GraphSourceItem
|
||||
* @throws CompilationException
|
||||
*/
|
||||
public List<GraphSourceItem> generate(SourceGeneratorLocalData localData, OrItem item) throws CompilationException;
|
||||
|
||||
/**
|
||||
* Generates source code for IfItem.
|
||||
* @param localData Local data
|
||||
* @param item IfItem
|
||||
* @return List of GraphSourceItem
|
||||
* @throws CompilationException
|
||||
*/
|
||||
public List<GraphSourceItem> generate(SourceGeneratorLocalData localData, IfItem item) throws CompilationException;
|
||||
|
||||
/**
|
||||
* Generates source code for TernarOpItem.
|
||||
* @param localData Local data
|
||||
* @param item TernarOpItem
|
||||
* @return List of GraphSourceItem
|
||||
* @throws CompilationException
|
||||
*/
|
||||
public List<GraphSourceItem> generate(SourceGeneratorLocalData localData, TernarOpItem item) throws CompilationException;
|
||||
|
||||
/**
|
||||
* Generates source code for WhileItem.
|
||||
* @param localData Local data
|
||||
* @param item WhileItem
|
||||
* @return List of GraphSourceItem
|
||||
* @throws CompilationException
|
||||
*/
|
||||
public List<GraphSourceItem> generate(SourceGeneratorLocalData localData, WhileItem item) throws CompilationException;
|
||||
|
||||
/**
|
||||
* Generates source code for DoWhileItem.
|
||||
* @param localData Local data
|
||||
* @param item DoWhileItem
|
||||
* @return List of GraphSourceItem
|
||||
* @throws CompilationException
|
||||
*/
|
||||
public List<GraphSourceItem> generate(SourceGeneratorLocalData localData, DoWhileItem item) throws CompilationException;
|
||||
|
||||
/**
|
||||
* Generates source code for ForItem.
|
||||
* @param localData Local data
|
||||
* @param item ForItem
|
||||
* @return List of GraphSourceItem
|
||||
* @throws CompilationException
|
||||
*/
|
||||
public List<GraphSourceItem> generate(SourceGeneratorLocalData localData, ForItem item) throws CompilationException;
|
||||
|
||||
/**
|
||||
* Generates source code for SwitchItem.
|
||||
* @param localData Local data
|
||||
* @param item SwitchItem
|
||||
* @return List of GraphSourceItem
|
||||
* @throws CompilationException
|
||||
*/
|
||||
public List<GraphSourceItem> generate(SourceGeneratorLocalData localData, SwitchItem item) throws CompilationException;
|
||||
|
||||
/**
|
||||
* Generates source code for NotItem.
|
||||
* @param localData Local data
|
||||
* @param item NotItem
|
||||
* @return List of GraphSourceItem
|
||||
* @throws CompilationException
|
||||
*/
|
||||
public List<GraphSourceItem> generate(SourceGeneratorLocalData localData, NotItem item) throws CompilationException;
|
||||
|
||||
/**
|
||||
* Generates source code for DuplicateItem.
|
||||
* @param localData Local data
|
||||
* @param item DuplicateItem
|
||||
* @return List of GraphSourceItem
|
||||
* @throws CompilationException
|
||||
*/
|
||||
public List<GraphSourceItem> generate(SourceGeneratorLocalData localData, DuplicateItem item) throws CompilationException;
|
||||
|
||||
/**
|
||||
* Generates source code for BreakItem.
|
||||
* @param localData Local data
|
||||
* @param item BreakItem
|
||||
* @return List of GraphSourceItem
|
||||
* @throws CompilationException
|
||||
*/
|
||||
public List<GraphSourceItem> generate(SourceGeneratorLocalData localData, BreakItem item) throws CompilationException;
|
||||
|
||||
/**
|
||||
* Generates source code for ContinueItem.
|
||||
* @param localData Local data
|
||||
* @param item ContinueItem
|
||||
* @return List of GraphSourceItem
|
||||
* @throws CompilationException
|
||||
*/
|
||||
public List<GraphSourceItem> generate(SourceGeneratorLocalData localData, ContinueItem item) throws CompilationException;
|
||||
|
||||
/**
|
||||
* Generates source code for commands.
|
||||
* @param localData Local data
|
||||
* @param commands List of GraphTargetItem
|
||||
* @return List of GraphSourceItem
|
||||
* @throws CompilationException
|
||||
*/
|
||||
public List<GraphSourceItem> generate(SourceGeneratorLocalData localData, List<GraphTargetItem> commands) throws CompilationException;
|
||||
|
||||
/**
|
||||
* Generates source code for CommaExpressionItem.
|
||||
* @param localData Local data
|
||||
* @param item CommaExpressionItem
|
||||
* @param withReturnValue If true, the return value is used
|
||||
* @return List of GraphSourceItem
|
||||
* @throws CompilationException
|
||||
*/
|
||||
public List<GraphSourceItem> generate(SourceGeneratorLocalData localData, CommaExpressionItem item, boolean withReturnValue) throws CompilationException;
|
||||
|
||||
/**
|
||||
* Generates source code for TypeItem.
|
||||
* @param localData Local data
|
||||
* @param item TypeItem
|
||||
* @return List of GraphSourceItem
|
||||
* @throws CompilationException
|
||||
*/
|
||||
public List<GraphSourceItem> generate(SourceGeneratorLocalData localData, TypeItem item) throws CompilationException;
|
||||
|
||||
/**
|
||||
* Generates DiscardValue action.
|
||||
* @param localData Local data
|
||||
* @param item GraphTargetItem
|
||||
* @return List of GraphSourceItem
|
||||
* @throws CompilationException
|
||||
*/
|
||||
public List<GraphSourceItem> generateDiscardValue(SourceGeneratorLocalData localData, GraphTargetItem item) throws CompilationException;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
package com.jpexs.decompiler.graph;
|
||||
|
||||
/**
|
||||
*
|
||||
* Kind of stop part.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public enum StopPartKind {
|
||||
|
||||
@@ -20,19 +20,45 @@ import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* State of throwing exception in a method.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class ThrowState {
|
||||
|
||||
/**
|
||||
* Exception id
|
||||
*/
|
||||
public int exceptionId;
|
||||
|
||||
/**
|
||||
* Throw state
|
||||
*/
|
||||
public int state;
|
||||
|
||||
/**
|
||||
* Throwing parts
|
||||
*/
|
||||
public Set<GraphPart> throwingParts = new HashSet<>();
|
||||
|
||||
/**
|
||||
* Target part
|
||||
*/
|
||||
public GraphPart targetPart;
|
||||
|
||||
/**
|
||||
* Start part
|
||||
*/
|
||||
public GraphPart startPart;
|
||||
|
||||
/**
|
||||
* Catch parts
|
||||
*/
|
||||
public Set<GraphPart> catchParts = new HashSet<>();
|
||||
|
||||
/**
|
||||
* Hash code
|
||||
* @return Hash code
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 3;
|
||||
@@ -40,6 +66,11 @@ public class ThrowState {
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Equals
|
||||
* @param obj Object
|
||||
* @return True if equals
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
|
||||
@@ -17,11 +17,15 @@
|
||||
package com.jpexs.decompiler.graph;
|
||||
|
||||
/**
|
||||
*
|
||||
* Exception thrown when there is a problem with translating the graph.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class TranslateException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Constructs new TranslateException with the specified detail message.
|
||||
* @param s The detail message.
|
||||
*/
|
||||
public TranslateException(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
@@ -17,34 +17,56 @@
|
||||
package com.jpexs.decompiler.graph;
|
||||
|
||||
import com.jpexs.decompiler.graph.model.PopItem;
|
||||
|
||||
import java.util.Stack;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* Stack for translation.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class TranslateStack extends Stack<GraphTargetItem> {
|
||||
|
||||
/**
|
||||
* Pop item
|
||||
*/
|
||||
private PopItem pop;
|
||||
|
||||
/**
|
||||
* Path
|
||||
*/
|
||||
private final String path;
|
||||
|
||||
/**
|
||||
* Simplifies all items in the stack.
|
||||
*/
|
||||
public void simplify() {
|
||||
for (int i = 0; i < size(); i++) {
|
||||
set(i, get(i).simplify(""));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new TranslateStack with the specified path.
|
||||
* @param path The path.
|
||||
*/
|
||||
public TranslateStack(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the path.
|
||||
* @return The path.
|
||||
*/
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the pop item.
|
||||
* @return The pop item.
|
||||
*/
|
||||
private PopItem getPop() {
|
||||
if (pop == null) {
|
||||
pop = new PopItem(null, null); //TODO: linestart?
|
||||
@@ -53,6 +75,11 @@ public class TranslateStack extends Stack<GraphTargetItem> {
|
||||
return pop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item at the specified index.
|
||||
* @param index index of the element to return
|
||||
* @return The element at the specified position in this list
|
||||
*/
|
||||
@Override
|
||||
public synchronized GraphTargetItem get(int index) {
|
||||
if (path != null) {
|
||||
@@ -64,6 +91,10 @@ public class TranslateStack extends Stack<GraphTargetItem> {
|
||||
return super.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item at the top of the stack.
|
||||
* @return The item at the top of the stack.
|
||||
*/
|
||||
@Override
|
||||
public synchronized GraphTargetItem peek() {
|
||||
if (path != null) {
|
||||
@@ -75,6 +106,11 @@ public class TranslateStack extends Stack<GraphTargetItem> {
|
||||
return super.peek();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item at the specified index from the top of the stack.
|
||||
* @param index The index.
|
||||
* @return The item at the specified index from the top of the stack.
|
||||
*/
|
||||
public synchronized GraphTargetItem peek(int index) {
|
||||
if (path != null) {
|
||||
if (index > this.size()) {
|
||||
@@ -85,6 +121,10 @@ public class TranslateStack extends Stack<GraphTargetItem> {
|
||||
return super.get(size() - index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop the item at the top of the stack.
|
||||
* @return The item at the top of the stack.
|
||||
*/
|
||||
@Override
|
||||
public synchronized GraphTargetItem pop() {
|
||||
if (path != null) {
|
||||
|
||||
@@ -19,29 +19,40 @@ package com.jpexs.decompiler.graph;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.graph.model.LocalData;
|
||||
import com.jpexs.decompiler.graph.model.UnboundedTypeItem;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
*
|
||||
* Represents a function type.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class TypeFunctionItem extends GraphTargetItem {
|
||||
|
||||
//Basic function items
|
||||
public static TypeFunctionItem BOOLEAN = new TypeFunctionItem("Boolean");
|
||||
|
||||
public static TypeFunctionItem STRING = new TypeFunctionItem("String");
|
||||
|
||||
public static TypeFunctionItem ARRAY = new TypeFunctionItem("Array");
|
||||
|
||||
public static UnboundedTypeItem UNBOUNDED = TypeItem.UNBOUNDED;
|
||||
|
||||
/**
|
||||
* Full type name
|
||||
*/
|
||||
public String fullTypeName;
|
||||
|
||||
/**
|
||||
* Creates a new instance of TypeFunctionItem
|
||||
* @param fullTypeName Full type name
|
||||
*/
|
||||
public TypeFunctionItem(String fullTypeName) {
|
||||
super(null, null, NOPRECEDENCE);
|
||||
this.fullTypeName = fullTypeName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash code
|
||||
* @return Hash code
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 7;
|
||||
@@ -49,6 +60,11 @@ public class TypeFunctionItem extends GraphTargetItem {
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Equals
|
||||
* @param obj Object to compare
|
||||
* @return True if equal
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
@@ -61,22 +77,42 @@ public class TypeFunctionItem extends GraphTargetItem {
|
||||
return Objects.equals(fullTypeName, other.fullTypeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends to writer
|
||||
* @param writer Writer
|
||||
* @param localData Local data
|
||||
* @return Writer
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
@Override
|
||||
public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException {
|
||||
writer.append(fullTypeName);
|
||||
return writer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the return type
|
||||
* @return Return type
|
||||
*/
|
||||
@Override
|
||||
public GraphTargetItem returnType() {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks whether this function has a return value
|
||||
* @return True if has a return value
|
||||
*/
|
||||
@Override
|
||||
public boolean hasReturnValue() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of this function
|
||||
* @return String representation
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Function[" + fullTypeName + "]";
|
||||
|
||||
@@ -22,16 +22,19 @@ import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType;
|
||||
import com.jpexs.decompiler.graph.model.LocalData;
|
||||
import com.jpexs.decompiler.graph.model.UnboundedTypeItem;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
*
|
||||
* Type item.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class TypeItem extends GraphTargetItem {
|
||||
|
||||
//Basic type items
|
||||
|
||||
public static TypeItem BOOLEAN = new TypeItem(DottedChain.BOOLEAN);
|
||||
|
||||
public static TypeItem STRING = new TypeItem(DottedChain.STRING);
|
||||
@@ -50,34 +53,66 @@ public class TypeItem extends GraphTargetItem {
|
||||
|
||||
public static TypeItem UNKNOWN = new TypeItem("--UNKNOWN--");
|
||||
|
||||
/**
|
||||
* Full type name
|
||||
*/
|
||||
public final DottedChain fullTypeName;
|
||||
|
||||
public boolean printRaw = false;
|
||||
|
||||
/**
|
||||
* Namespace
|
||||
*/
|
||||
public String ns;
|
||||
|
||||
/**
|
||||
* Constructs a new instance of TypeItem
|
||||
* @param s Full type name
|
||||
*/
|
||||
public TypeItem(String s) {
|
||||
this(s, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance of TypeItem
|
||||
* @param s Full type name
|
||||
* @param ns Namespace
|
||||
*/
|
||||
public TypeItem(String s, String ns) {
|
||||
this(s == null ? new DottedChain(new String[]{}, new String[]{""}) : DottedChain.parseWithSuffix(s), ns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance of TypeItem
|
||||
* @param fullTypeName Full type name
|
||||
*/
|
||||
public TypeItem(DottedChain fullTypeName) {
|
||||
this(fullTypeName, (String) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance of TypeItem
|
||||
* @param fullTypeName Full type name
|
||||
* @param ns Namespace
|
||||
*/
|
||||
public TypeItem(DottedChain fullTypeName, String ns) {
|
||||
this(fullTypeName, new ArrayList<>(), ns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance of TypeItem
|
||||
* @param fullTypeName Full type name
|
||||
* @param subtypes Subtypes
|
||||
* @param ns Namespace
|
||||
*/
|
||||
public TypeItem(DottedChain fullTypeName, List<GraphTargetItem> subtypes, String ns) {
|
||||
super(null, null, NOPRECEDENCE);
|
||||
this.fullTypeName = fullTypeName;
|
||||
this.ns = ns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash code
|
||||
* @return Hash code
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 5;
|
||||
@@ -86,6 +121,11 @@ public class TypeItem extends GraphTargetItem {
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Equals
|
||||
* @param obj Object to compare
|
||||
* @return True if equal
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
@@ -104,6 +144,13 @@ public class TypeItem extends GraphTargetItem {
|
||||
return Objects.equals(this.fullTypeName, other.fullTypeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends to writer
|
||||
* @param writer Writer
|
||||
* @param localData Local data
|
||||
* @return Writer
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
@Override
|
||||
public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException {
|
||||
boolean as3 = localData.constantsAvm2 != null;
|
||||
@@ -117,21 +164,40 @@ public class TypeItem extends GraphTargetItem {
|
||||
return writer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the return type
|
||||
* @return Return type
|
||||
*/
|
||||
@Override
|
||||
public GraphTargetItem returnType() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this function has a return value
|
||||
* @return True if has a return value
|
||||
*/
|
||||
@Override
|
||||
public boolean hasReturnValue() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of this function
|
||||
* @return String representation
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return fullTypeName.toRawString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this item to low-level source code.
|
||||
* @param localData Local data
|
||||
* @param generator Source generator
|
||||
* @return List of graph source items
|
||||
* @throws CompilationException
|
||||
*/
|
||||
@Override
|
||||
public List<GraphSourceItem> toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException {
|
||||
return generator.generate(localData, this);
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* High-level model of the graph.
|
||||
*/
|
||||
package com.jpexs.decompiler.graph.model;
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Control flow graph and its decompiling.
|
||||
*/
|
||||
package com.jpexs.decompiler.graph;
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Detection of precontinues in loops.
|
||||
*/
|
||||
package com.jpexs.decompiler.graph.precontinues;
|
||||
Reference in New Issue
Block a user