You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
405 lines
9.4 KiB
405 lines
9.4 KiB
10 years ago
|
/*
|
||
|
* Fernflower - The Analytical Java Decompiler
|
||
|
* http://www.reversed-java.com
|
||
|
*
|
||
|
* (C) 2008 - 2010, Stiver
|
||
|
*
|
||
|
* This software is NEITHER public domain NOR free software
|
||
|
* as per GNU License. See license.txt for more details.
|
||
|
*
|
||
|
* This software is distributed WITHOUT ANY WARRANTY; without
|
||
|
* even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||
|
* A PARTICULAR PURPOSE.
|
||
|
*/
|
||
|
|
||
10 years ago
|
package org.jetbrains.java.decompiler.modules.decompiler.stats;
|
||
10 years ago
|
|
||
|
import java.util.ArrayList;
|
||
|
import java.util.List;
|
||
|
|
||
10 years ago
|
import org.jetbrains.java.decompiler.main.DecompilerContext;
|
||
|
import org.jetbrains.java.decompiler.modules.decompiler.DecHelper;
|
||
|
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
|
||
|
import org.jetbrains.java.decompiler.modules.decompiler.StatEdge;
|
||
|
import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent;
|
||
|
import org.jetbrains.java.decompiler.modules.decompiler.exps.IfExprent;
|
||
|
import org.jetbrains.java.decompiler.util.InterpreterUtil;
|
||
10 years ago
|
|
||
|
|
||
|
public class IfStatement extends Statement {
|
||
|
|
||
|
public static int IFTYPE_IF = 0;
|
||
|
public static int IFTYPE_IFELSE = 1;
|
||
|
|
||
|
public int iftype;
|
||
|
|
||
|
// *****************************************************************************
|
||
|
// private fields
|
||
|
// *****************************************************************************
|
||
|
|
||
|
private Statement ifstat;
|
||
|
private Statement elsestat;
|
||
|
|
||
|
private StatEdge ifedge;
|
||
|
private StatEdge elseedge;
|
||
|
|
||
|
private boolean negated = false;
|
||
|
|
||
|
private boolean iffflag;
|
||
|
|
||
|
private List<Exprent> headexprent = new ArrayList<Exprent>(); // contains IfExprent
|
||
|
|
||
|
// *****************************************************************************
|
||
|
// constructors
|
||
|
// *****************************************************************************
|
||
|
|
||
|
private IfStatement() {
|
||
|
type = TYPE_IF;
|
||
|
|
||
|
headexprent.add(null);
|
||
|
}
|
||
|
|
||
|
private IfStatement(Statement head, int regedges, Statement postst) {
|
||
|
|
||
|
this();
|
||
|
|
||
|
first = head;
|
||
|
stats.addWithKey(head, head.id);
|
||
|
|
||
|
List<StatEdge> lstHeadSuccs = head.getSuccessorEdges(STATEDGE_DIRECT_ALL);
|
||
|
|
||
|
switch(regedges) {
|
||
|
case 0:
|
||
|
ifstat = null;
|
||
|
elsestat = null;
|
||
|
|
||
|
break;
|
||
|
case 1:
|
||
|
ifstat = null;
|
||
|
elsestat = null;
|
||
|
|
||
|
StatEdge edgeif = lstHeadSuccs.get(1);
|
||
|
if(edgeif.getType() != StatEdge.TYPE_REGULAR) {
|
||
|
post = lstHeadSuccs.get(0).getDestination();
|
||
|
} else {
|
||
|
post = edgeif.getDestination();
|
||
|
negated = true;
|
||
|
}
|
||
|
break;
|
||
|
case 2:
|
||
|
elsestat = lstHeadSuccs.get(0).getDestination();
|
||
|
ifstat = lstHeadSuccs.get(1).getDestination();
|
||
|
|
||
|
List<StatEdge> lstSucc = ifstat.getSuccessorEdges(StatEdge.TYPE_REGULAR);
|
||
|
List<StatEdge> lstSucc1 = elsestat.getSuccessorEdges(StatEdge.TYPE_REGULAR);
|
||
|
|
||
|
if(ifstat.getPredecessorEdges(StatEdge.TYPE_REGULAR).size()>1 || lstSucc.size()>1) {
|
||
|
post = ifstat;
|
||
|
} else if(elsestat.getPredecessorEdges(StatEdge.TYPE_REGULAR).size()>1 || lstSucc1.size()>1) {
|
||
|
post = elsestat;
|
||
|
} else {
|
||
|
if(lstSucc.size() == 0){
|
||
|
post = elsestat;
|
||
|
} else if(lstSucc1.size() == 0){
|
||
|
post = ifstat;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(ifstat == post) {
|
||
|
if(elsestat != post) {
|
||
|
ifstat = elsestat;
|
||
|
negated = true;
|
||
|
} else {
|
||
|
ifstat = null;
|
||
|
}
|
||
|
elsestat = null;
|
||
|
} else if(elsestat == post) {
|
||
|
elsestat = null;
|
||
|
} else {
|
||
|
post = postst;
|
||
|
}
|
||
|
|
||
|
if(elsestat == null) {
|
||
|
regedges = 1; // if without else
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ifedge = lstHeadSuccs.get(negated?0:1);
|
||
|
elseedge = (regedges == 2)?lstHeadSuccs.get(negated?1:0):null;
|
||
|
|
||
|
iftype = (regedges == 2)?IFTYPE_IFELSE:IFTYPE_IF;
|
||
|
|
||
|
if(iftype == IFTYPE_IF) {
|
||
|
if(regedges == 0) {
|
||
|
StatEdge edge = lstHeadSuccs.get(0);
|
||
|
head.removeSuccessor(edge);
|
||
|
edge.setSource(this);
|
||
|
this.addSuccessor(edge);
|
||
|
} else if(regedges == 1) {
|
||
|
StatEdge edge = lstHeadSuccs.get(negated?1:0);
|
||
|
head.removeSuccessor(edge);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(ifstat != null) {
|
||
|
stats.addWithKey(ifstat, ifstat.id);
|
||
|
}
|
||
|
|
||
|
if(elsestat != null) {
|
||
|
stats.addWithKey(elsestat, elsestat.id);
|
||
|
}
|
||
|
|
||
|
if(post == head) {
|
||
|
post = this;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
// *****************************************************************************
|
||
|
// public methods
|
||
|
// *****************************************************************************
|
||
|
|
||
|
public static Statement isHead(Statement head) {
|
||
|
|
||
|
if(head.type == TYPE_BASICBLOCK && head.getLastBasicType() == LASTBASICTYPE_IF) {
|
||
|
int regsize = head.getSuccessorEdges(StatEdge.TYPE_REGULAR).size();
|
||
|
|
||
|
Statement p = null;
|
||
|
|
||
|
boolean ok = (regsize < 2);
|
||
|
if(!ok) {
|
||
|
List<Statement> lst = new ArrayList<Statement>();
|
||
|
if(DecHelper.isChoiceStatement(head, lst)) {
|
||
|
p = lst.remove(0);
|
||
|
|
||
|
for(Statement st : lst) {
|
||
|
if(st.isMonitorEnter()) {
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ok = DecHelper.checkStatementExceptions(lst);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(ok) {
|
||
|
return new IfStatement(head, regsize, p);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
public String toJava(int indent) {
|
||
|
String indstr = InterpreterUtil.getIndentString(indent);
|
||
|
StringBuffer buf = new StringBuffer();
|
||
|
|
||
|
String new_line_separator = DecompilerContext.getNewLineSeparator();
|
||
|
|
||
|
buf.append(ExprProcessor.listToJava(varDefinitions, indent));
|
||
|
buf.append(first.toJava(indent));
|
||
|
|
||
|
if(isLabeled()) {
|
||
|
buf.append(indstr+"label"+this.id+":" + new_line_separator);
|
||
|
}
|
||
|
|
||
|
buf.append(indstr+headexprent.get(0).toJava(indent)+" {" + new_line_separator);
|
||
|
|
||
|
if(ifstat==null) {
|
||
|
buf.append(InterpreterUtil.getIndentString(indent+1));
|
||
|
|
||
|
if(ifedge.explicit) {
|
||
|
if(ifedge.getType() == StatEdge.TYPE_BREAK) {
|
||
|
// break
|
||
|
buf.append("break");
|
||
|
} else {
|
||
|
// continue
|
||
|
buf.append("continue");
|
||
|
}
|
||
|
|
||
|
if(ifedge.labeled) {
|
||
|
buf.append(" label"+ifedge.closure.id);
|
||
|
}
|
||
|
}
|
||
|
buf.append(";" + new_line_separator);
|
||
|
} else {
|
||
|
buf.append(ExprProcessor.jmpWrapper(ifstat, indent+1, true));
|
||
|
}
|
||
|
|
||
|
boolean elseif = false;
|
||
|
|
||
|
if(elsestat != null) {
|
||
|
if(elsestat.type == Statement.TYPE_IF
|
||
|
&& elsestat.varDefinitions.isEmpty() && elsestat.getFirst().getExprents().isEmpty() &&
|
||
|
!elsestat.isLabeled() &&
|
||
|
(elsestat.getSuccessorEdges(STATEDGE_DIRECT_ALL).isEmpty()
|
||
|
|| !elsestat.getSuccessorEdges(STATEDGE_DIRECT_ALL).get(0).explicit)) { // else if
|
||
|
String content = ExprProcessor.jmpWrapper(elsestat, indent, false);
|
||
|
content = content.substring(indstr.length());
|
||
|
|
||
|
buf.append(indstr+"} else ");
|
||
|
buf.append(content);
|
||
|
|
||
|
elseif = true;
|
||
|
} else {
|
||
|
String content = ExprProcessor.jmpWrapper(elsestat, indent+1, false);
|
||
|
|
||
|
if(content.length() > 0) {
|
||
|
buf.append(indstr+"} else {" + new_line_separator);
|
||
|
buf.append(content);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(!elseif) {
|
||
|
buf.append(indstr+"}" + new_line_separator);
|
||
|
}
|
||
|
|
||
|
return buf.toString();
|
||
|
}
|
||
|
|
||
|
public void initExprents() {
|
||
|
|
||
|
IfExprent ifexpr = (IfExprent)first.getExprents().remove(first.getExprents().size()-1);
|
||
|
|
||
|
if(negated) {
|
||
|
ifexpr = (IfExprent)ifexpr.copy();
|
||
|
ifexpr.negateIf();
|
||
|
}
|
||
|
|
||
|
headexprent.set(0, ifexpr);
|
||
|
}
|
||
|
|
||
|
public List<Object> getSequentialObjects() {
|
||
|
|
||
|
List<Object> lst = new ArrayList<Object>(stats);
|
||
|
lst.add(1, headexprent.get(0));
|
||
|
|
||
|
return lst;
|
||
|
}
|
||
|
|
||
|
public void replaceExprent(Exprent oldexpr, Exprent newexpr) {
|
||
|
if(headexprent.get(0) == oldexpr) {
|
||
|
headexprent.set(0, newexpr);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void replaceStatement(Statement oldstat, Statement newstat) {
|
||
|
|
||
|
super.replaceStatement(oldstat, newstat);
|
||
|
|
||
|
if(ifstat == oldstat) {
|
||
|
ifstat = newstat;
|
||
|
}
|
||
|
|
||
|
if(elsestat == oldstat) {
|
||
|
elsestat = newstat;
|
||
|
}
|
||
|
|
||
|
List<StatEdge> lstSuccs = first.getSuccessorEdges(STATEDGE_DIRECT_ALL);
|
||
|
|
||
|
if(iftype == IFTYPE_IF) {
|
||
|
ifedge = lstSuccs.get(0);
|
||
|
elseedge = null;
|
||
|
} else {
|
||
|
StatEdge edge0 = lstSuccs.get(0);
|
||
|
StatEdge edge1 = lstSuccs.get(1);
|
||
|
if(edge0.getDestination() == ifstat) {
|
||
|
ifedge = edge0;
|
||
|
elseedge = edge1;
|
||
|
} else {
|
||
|
ifedge = edge1;
|
||
|
elseedge = edge0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public Statement getSimpleCopy() {
|
||
|
|
||
|
IfStatement is = new IfStatement();
|
||
|
is.iftype = this.iftype;
|
||
|
is.negated = this.negated;
|
||
|
is.iffflag = this.iffflag;
|
||
|
|
||
|
return is;
|
||
|
}
|
||
|
|
||
|
public void initSimpleCopy() {
|
||
|
|
||
|
first = stats.get(0);
|
||
|
|
||
|
List<StatEdge> lstSuccs = first.getSuccessorEdges(STATEDGE_DIRECT_ALL);
|
||
|
ifedge = lstSuccs.get((iftype == IFTYPE_IF || negated)?0:1);
|
||
|
if(stats.size() > 1) {
|
||
|
ifstat = stats.get(1);
|
||
|
}
|
||
|
|
||
|
if(iftype == IFTYPE_IFELSE) {
|
||
|
elseedge = lstSuccs.get(negated?1:0);
|
||
|
elsestat = stats.get(2);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
// *****************************************************************************
|
||
|
// getter and setter methods
|
||
|
// *****************************************************************************
|
||
|
|
||
|
public Statement getElsestat() {
|
||
|
return elsestat;
|
||
|
}
|
||
|
|
||
|
public void setElsestat(Statement elsestat) {
|
||
|
this.elsestat = elsestat;
|
||
|
}
|
||
|
|
||
|
public Statement getIfstat() {
|
||
|
return ifstat;
|
||
|
}
|
||
|
|
||
|
public void setIfstat(Statement ifstat) {
|
||
|
this.ifstat = ifstat;
|
||
|
}
|
||
|
|
||
|
public boolean isNegated() {
|
||
|
return negated;
|
||
|
}
|
||
|
|
||
|
public void setNegated(boolean negated) {
|
||
|
this.negated = negated;
|
||
|
}
|
||
|
|
||
|
public List<Exprent> getHeadexprentList() {
|
||
|
return headexprent;
|
||
|
}
|
||
|
|
||
|
public IfExprent getHeadexprent() {
|
||
|
return (IfExprent)headexprent.get(0);
|
||
|
}
|
||
|
|
||
|
public boolean isIffflag() {
|
||
|
return iffflag;
|
||
|
}
|
||
|
|
||
|
public void setIffflag(boolean iffflag) {
|
||
|
this.iffflag = iffflag;
|
||
|
}
|
||
|
|
||
|
public void setElseEdge(StatEdge elseedge) {
|
||
|
this.elseedge = elseedge;
|
||
|
}
|
||
|
|
||
|
public void setIfEdge(StatEdge ifedge) {
|
||
|
this.ifedge = ifedge;
|
||
|
}
|
||
|
|
||
|
public StatEdge getIfEdge() {
|
||
|
return ifedge;
|
||
|
}
|
||
|
|
||
|
public StatEdge getElseEdge() {
|
||
|
return elseedge;
|
||
|
}
|
||
|
}
|