summaryrefslogtreecommitdiffstats
path: root/src/org/jetbrains/java/decompiler/modules/decompiler/stats
diff options
context:
space:
mode:
Diffstat (limited to 'src/org/jetbrains/java/decompiler/modules/decompiler/stats')
-rw-r--r--src/org/jetbrains/java/decompiler/modules/decompiler/stats/BasicBlockStatement.java157
-rw-r--r--src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchAllStatement.java428
-rw-r--r--src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchStatement.java375
-rw-r--r--src/org/jetbrains/java/decompiler/modules/decompiler/stats/DoStatement.java410
-rw-r--r--src/org/jetbrains/java/decompiler/modules/decompiler/stats/GeneralStatement.java121
-rw-r--r--src/org/jetbrains/java/decompiler/modules/decompiler/stats/IfStatement.java782
-rw-r--r--src/org/jetbrains/java/decompiler/modules/decompiler/stats/RootStatement.java71
-rw-r--r--src/org/jetbrains/java/decompiler/modules/decompiler/stats/SequenceStatement.java254
-rw-r--r--src/org/jetbrains/java/decompiler/modules/decompiler/stats/Statement.java1705
-rw-r--r--src/org/jetbrains/java/decompiler/modules/decompiler/stats/SwitchStatement.java689
-rw-r--r--src/org/jetbrains/java/decompiler/modules/decompiler/stats/SynchronizedStatement.java271
11 files changed, 2638 insertions, 2625 deletions
diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/BasicBlockStatement.java b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/BasicBlockStatement.java
index 5cfa634..ddac0c5 100644
--- a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/BasicBlockStatement.java
+++ b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/BasicBlockStatement.java
@@ -1,17 +1,18 @@
/*
- * Fernflower - The Analytical Java Decompiler
- * http://www.reversed-java.com
+ * Copyright 2000-2014 JetBrains s.r.o.
*
- * (C) 2008 - 2010, Stiver
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * This software is NEITHER public domain NOR free software
- * as per GNU License. See license.txt for more details.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * This software is distributed WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
-
package org.jetbrains.java.decompiler.modules.decompiler.stats;
import org.jetbrains.java.decompiler.code.CodeConstants;
@@ -23,73 +24,73 @@ import org.jetbrains.java.decompiler.main.collectors.CounterContainer;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
public class BasicBlockStatement extends Statement {
-
- // *****************************************************************************
- // private fields
- // *****************************************************************************
-
- private BasicBlock block;
-
- // *****************************************************************************
- // constructors
- // *****************************************************************************
-
- public BasicBlockStatement(BasicBlock block) {
-
- type = Statement.TYPE_BASICBLOCK;
-
- this.block = block;
-
- id = block.id;
- CounterContainer coun = DecompilerContext.getCountercontainer();
- if(id>=coun.getCounter(CounterContainer.STATEMENT_COUNTER)) {
- coun.setCounter(CounterContainer.STATEMENT_COUNTER, id+1);
- }
-
- Instruction instr = block.getLastInstruction();
- if(instr != null) {
- if(instr.group==CodeConstants.GROUP_JUMP && instr.opcode != CodeConstants.opc_goto) {
- lastBasicType = LASTBASICTYPE_IF;
- } else if(instr.group==CodeConstants.GROUP_SWITCH) {
- lastBasicType = LASTBASICTYPE_SWITCH;
- }
- }
-
- // monitorenter and monitorexits
- buildMonitorFlags();
- }
-
- // *****************************************************************************
- // public methods
- // *****************************************************************************
-
- public String toJava(int indent) {
- return ExprProcessor.listToJava(varDefinitions, indent)+
- ExprProcessor.listToJava(exprents, indent);
- }
-
- public Statement getSimpleCopy() {
-
- BasicBlock newblock = new BasicBlock(
- DecompilerContext.getCountercontainer().getCounterAndIncrement(CounterContainer.STATEMENT_COUNTER));
-
- SimpleInstructionSequence seq = new SimpleInstructionSequence();
- for(int i=0;i<block.getSeq().length();i++) {
- seq.addInstruction(block.getSeq().getInstr(i).clone(), -1);
- }
-
- newblock.setSeq(seq);
-
- return new BasicBlockStatement(newblock);
- }
-
-
- // *****************************************************************************
- // getter and setter methods
- // *****************************************************************************
-
- public BasicBlock getBlock() {
- return block;
- }
-
+
+ // *****************************************************************************
+ // private fields
+ // *****************************************************************************
+
+ private BasicBlock block;
+
+ // *****************************************************************************
+ // constructors
+ // *****************************************************************************
+
+ public BasicBlockStatement(BasicBlock block) {
+
+ type = Statement.TYPE_BASICBLOCK;
+
+ this.block = block;
+
+ id = block.id;
+ CounterContainer coun = DecompilerContext.getCountercontainer();
+ if (id >= coun.getCounter(CounterContainer.STATEMENT_COUNTER)) {
+ coun.setCounter(CounterContainer.STATEMENT_COUNTER, id + 1);
+ }
+
+ Instruction instr = block.getLastInstruction();
+ if (instr != null) {
+ if (instr.group == CodeConstants.GROUP_JUMP && instr.opcode != CodeConstants.opc_goto) {
+ lastBasicType = LASTBASICTYPE_IF;
+ }
+ else if (instr.group == CodeConstants.GROUP_SWITCH) {
+ lastBasicType = LASTBASICTYPE_SWITCH;
+ }
+ }
+
+ // monitorenter and monitorexits
+ buildMonitorFlags();
+ }
+
+ // *****************************************************************************
+ // public methods
+ // *****************************************************************************
+
+ public String toJava(int indent) {
+ return ExprProcessor.listToJava(varDefinitions, indent) +
+ ExprProcessor.listToJava(exprents, indent);
+ }
+
+ public Statement getSimpleCopy() {
+
+ BasicBlock newblock = new BasicBlock(
+ DecompilerContext.getCountercontainer().getCounterAndIncrement(CounterContainer.STATEMENT_COUNTER));
+
+ SimpleInstructionSequence seq = new SimpleInstructionSequence();
+ for (int i = 0; i < block.getSeq().length(); i++) {
+ seq.addInstruction(block.getSeq().getInstr(i).clone(), -1);
+ }
+
+ newblock.setSeq(seq);
+
+ return new BasicBlockStatement(newblock);
+ }
+
+
+ // *****************************************************************************
+ // getter and setter methods
+ // *****************************************************************************
+
+ public BasicBlock getBlock() {
+ return block;
+ }
}
diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchAllStatement.java b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchAllStatement.java
index 25adb29..9f1a3f5 100644
--- a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchAllStatement.java
+++ b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchAllStatement.java
@@ -1,24 +1,20 @@
/*
- * Fernflower - The Analytical Java Decompiler
- * http://www.reversed-java.com
+ * Copyright 2000-2014 JetBrains s.r.o.
*
- * (C) 2008 - 2010, Stiver
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * This software is NEITHER public domain NOR free software
- * as per GNU License. See license.txt for more details.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * This software is distributed WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
-
package org.jetbrains.java.decompiler.modules.decompiler.stats;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-
import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.collectors.CounterContainer;
@@ -30,204 +26,210 @@ import org.jetbrains.java.decompiler.modules.decompiler.vars.VarProcessor;
import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+
public class CatchAllStatement extends Statement {
-
- private Statement handler;
-
- private boolean isFinally;
-
- private VarExprent monitor;
-
- private List<VarExprent> vars = new ArrayList<VarExprent>();
-
- // *****************************************************************************
- // constructors
- // *****************************************************************************
-
- private CatchAllStatement(){
- type = Statement.TYPE_CATCHALL;
- };
-
- private CatchAllStatement(Statement head, Statement handler) {
-
- this();
-
- first = head;
- stats.addWithKey(head, head.id);
-
- this.handler = handler;
- stats.addWithKey(handler, handler.id);
-
- List<StatEdge> lstSuccs = head.getSuccessorEdges(STATEDGE_DIRECT_ALL);
- if(!lstSuccs.isEmpty()) {
- StatEdge edge = lstSuccs.get(0);
- if(edge.getType() == StatEdge.TYPE_REGULAR) {
- post = edge.getDestination();
- }
- }
-
- vars.add(new VarExprent(DecompilerContext.getCountercontainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER),
- new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Throwable"),
- (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR)));
-
- }
-
-
- // *****************************************************************************
- // public methods
- // *****************************************************************************
-
- public static Statement isHead(Statement head) {
-
- if(head.getLastBasicType() != Statement.LASTBASICTYPE_GENERAL) {
- return null;
- }
-
- HashSet<Statement> setHandlers = DecHelper.getUniquePredExceptions(head);
-
- if(setHandlers.size() != 1) {
- return null;
- }
-
- for(StatEdge edge : head.getSuccessorEdges(StatEdge.TYPE_EXCEPTION)) {
- Statement exc = edge.getDestination();
-
- if(edge.getExceptions() == null && setHandlers.contains(exc) && exc.getLastBasicType() == LASTBASICTYPE_GENERAL) {
- List<StatEdge> lstSuccs = exc.getSuccessorEdges(STATEDGE_DIRECT_ALL);
- if(lstSuccs.isEmpty() || lstSuccs.get(0).getType() != StatEdge.TYPE_REGULAR) {
-
- if(head.isMonitorEnter() || exc.isMonitorEnter()) {
- return null;
- }
-
- if(DecHelper.checkStatementExceptions(Arrays.asList(new Statement[] {head, exc}))) {
- return new CatchAllStatement(head, exc);
- }
- }
- }
- }
-
- return null;
- }
-
- public String toJava(int indent) {
- String indstr = InterpreterUtil.getIndentString(indent);
- String indstr1 = null;
-
- String new_line_separator = DecompilerContext.getNewLineSeparator();
-
- StringBuffer buf = new StringBuffer();
-
- buf.append(ExprProcessor.listToJava(varDefinitions, indent));
-
- boolean labeled = isLabeled();
- if(labeled) {
- buf.append(indstr+"label"+this.id+":" + new_line_separator);
- }
-
- List<StatEdge> lstSuccs = first.getSuccessorEdges(STATEDGE_DIRECT_ALL);
- if(first.type == TYPE_TRYCATCH && first.varDefinitions.isEmpty() && isFinally &&
- !labeled && !first.isLabeled() && (lstSuccs.isEmpty() || !lstSuccs.get(0).explicit)) {
- String content = ExprProcessor.jmpWrapper(first, indent, true);
- content = content.substring(0, content.length()-new_line_separator.length());
-
- buf.append(content);
- } else {
- buf.append(indstr+"try {" + new_line_separator);
- buf.append(ExprProcessor.jmpWrapper(first, indent+1, true));
- buf.append(indstr+"}");
- }
-
- buf.append((isFinally?" finally":
- " catch ("+vars.get(0).toJava(indent)+")")+" {" + new_line_separator);
-
- if(monitor != null) {
- indstr1 = InterpreterUtil.getIndentString(indent+1);
- buf.append(indstr1+"if("+monitor.toJava(indent)+") {" + new_line_separator);
- }
-
- buf.append(ExprProcessor.jmpWrapper(handler, indent+1+(monitor != null?1:0), true));
-
- if(monitor != null) {
- buf.append(indstr1+"}" + new_line_separator);
- }
-
- buf.append(indstr+"}" + new_line_separator);
-
- return buf.toString();
- }
-
- public void replaceStatement(Statement oldstat, Statement newstat) {
-
- if(handler == oldstat) {
- handler = newstat;
- }
-
- super.replaceStatement(oldstat, newstat);
- }
-
- public Statement getSimpleCopy() {
-
- CatchAllStatement cas = new CatchAllStatement();
-
- cas.isFinally = this.isFinally;
-
- if(this.monitor != null) {
- cas.monitor = new VarExprent(DecompilerContext.getCountercontainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER),
- VarType.VARTYPE_INT,
- (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR));
- }
-
- if(!this.vars.isEmpty()) {
- // FIXME: WTF??? vars?!
- vars.add(new VarExprent(DecompilerContext.getCountercontainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER),
- new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Throwable"),
- (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR)));
- }
-
- return cas;
- }
-
- public void initSimpleCopy() {
- first = stats.get(0);
- handler = stats.get(1);
- }
-
- // *****************************************************************************
- // getter and setter methods
- // *****************************************************************************
-
- public Statement getHandler() {
- return handler;
- }
-
-
- public void setHandler(Statement handler) {
- this.handler = handler;
- }
-
-
- public boolean isFinally() {
- return isFinally;
- }
-
-
- public void setFinally(boolean isFinally) {
- this.isFinally = isFinally;
- }
-
-
- public VarExprent getMonitor() {
- return monitor;
- }
-
-
- public void setMonitor(VarExprent monitor) {
- this.monitor = monitor;
- }
-
- public List<VarExprent> getVars() {
- return vars;
- }
-
+
+ private Statement handler;
+
+ private boolean isFinally;
+
+ private VarExprent monitor;
+
+ private List<VarExprent> vars = new ArrayList<VarExprent>();
+
+ // *****************************************************************************
+ // constructors
+ // *****************************************************************************
+
+ private CatchAllStatement() {
+ type = Statement.TYPE_CATCHALL;
+ }
+
+ ;
+
+ private CatchAllStatement(Statement head, Statement handler) {
+
+ this();
+
+ first = head;
+ stats.addWithKey(head, head.id);
+
+ this.handler = handler;
+ stats.addWithKey(handler, handler.id);
+
+ List<StatEdge> lstSuccs = head.getSuccessorEdges(STATEDGE_DIRECT_ALL);
+ if (!lstSuccs.isEmpty()) {
+ StatEdge edge = lstSuccs.get(0);
+ if (edge.getType() == StatEdge.TYPE_REGULAR) {
+ post = edge.getDestination();
+ }
+ }
+
+ vars.add(new VarExprent(DecompilerContext.getCountercontainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER),
+ new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Throwable"),
+ (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR)));
+ }
+
+
+ // *****************************************************************************
+ // public methods
+ // *****************************************************************************
+
+ public static Statement isHead(Statement head) {
+
+ if (head.getLastBasicType() != Statement.LASTBASICTYPE_GENERAL) {
+ return null;
+ }
+
+ HashSet<Statement> setHandlers = DecHelper.getUniquePredExceptions(head);
+
+ if (setHandlers.size() != 1) {
+ return null;
+ }
+
+ for (StatEdge edge : head.getSuccessorEdges(StatEdge.TYPE_EXCEPTION)) {
+ Statement exc = edge.getDestination();
+
+ if (edge.getExceptions() == null && setHandlers.contains(exc) && exc.getLastBasicType() == LASTBASICTYPE_GENERAL) {
+ List<StatEdge> lstSuccs = exc.getSuccessorEdges(STATEDGE_DIRECT_ALL);
+ if (lstSuccs.isEmpty() || lstSuccs.get(0).getType() != StatEdge.TYPE_REGULAR) {
+
+ if (head.isMonitorEnter() || exc.isMonitorEnter()) {
+ return null;
+ }
+
+ if (DecHelper.checkStatementExceptions(Arrays.asList(new Statement[]{head, exc}))) {
+ return new CatchAllStatement(head, exc);
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public String toJava(int indent) {
+ String indstr = InterpreterUtil.getIndentString(indent);
+ String indstr1 = null;
+
+ String new_line_separator = DecompilerContext.getNewLineSeparator();
+
+ StringBuffer buf = new StringBuffer();
+
+ buf.append(ExprProcessor.listToJava(varDefinitions, indent));
+
+ boolean labeled = isLabeled();
+ if (labeled) {
+ buf.append(indstr + "label" + this.id + ":" + new_line_separator);
+ }
+
+ List<StatEdge> lstSuccs = first.getSuccessorEdges(STATEDGE_DIRECT_ALL);
+ if (first.type == TYPE_TRYCATCH && first.varDefinitions.isEmpty() && isFinally &&
+ !labeled && !first.isLabeled() && (lstSuccs.isEmpty() || !lstSuccs.get(0).explicit)) {
+ String content = ExprProcessor.jmpWrapper(first, indent, true);
+ content = content.substring(0, content.length() - new_line_separator.length());
+
+ buf.append(content);
+ }
+ else {
+ buf.append(indstr + "try {" + new_line_separator);
+ buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true));
+ buf.append(indstr + "}");
+ }
+
+ buf.append((isFinally ? " finally" :
+ " catch (" + vars.get(0).toJava(indent) + ")") + " {" + new_line_separator);
+
+ if (monitor != null) {
+ indstr1 = InterpreterUtil.getIndentString(indent + 1);
+ buf.append(indstr1 + "if(" + monitor.toJava(indent) + ") {" + new_line_separator);
+ }
+
+ buf.append(ExprProcessor.jmpWrapper(handler, indent + 1 + (monitor != null ? 1 : 0), true));
+
+ if (monitor != null) {
+ buf.append(indstr1 + "}" + new_line_separator);
+ }
+
+ buf.append(indstr + "}" + new_line_separator);
+
+ return buf.toString();
+ }
+
+ public void replaceStatement(Statement oldstat, Statement newstat) {
+
+ if (handler == oldstat) {
+ handler = newstat;
+ }
+
+ super.replaceStatement(oldstat, newstat);
+ }
+
+ public Statement getSimpleCopy() {
+
+ CatchAllStatement cas = new CatchAllStatement();
+
+ cas.isFinally = this.isFinally;
+
+ if (this.monitor != null) {
+ cas.monitor = new VarExprent(DecompilerContext.getCountercontainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER),
+ VarType.VARTYPE_INT,
+ (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR));
+ }
+
+ if (!this.vars.isEmpty()) {
+ // FIXME: WTF??? vars?!
+ vars.add(new VarExprent(DecompilerContext.getCountercontainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER),
+ new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Throwable"),
+ (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR)));
+ }
+
+ return cas;
+ }
+
+ public void initSimpleCopy() {
+ first = stats.get(0);
+ handler = stats.get(1);
+ }
+
+ // *****************************************************************************
+ // getter and setter methods
+ // *****************************************************************************
+
+ public Statement getHandler() {
+ return handler;
+ }
+
+
+ public void setHandler(Statement handler) {
+ this.handler = handler;
+ }
+
+
+ public boolean isFinally() {
+ return isFinally;
+ }
+
+
+ public void setFinally(boolean isFinally) {
+ this.isFinally = isFinally;
+ }
+
+
+ public VarExprent getMonitor() {
+ return monitor;
+ }
+
+
+ public void setMonitor(VarExprent monitor) {
+ this.monitor = monitor;
+ }
+
+ public List<VarExprent> getVars() {
+ return vars;
+ }
}
diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchStatement.java b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchStatement.java
index 6387d45..17f5636 100644
--- a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchStatement.java
+++ b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchStatement.java
@@ -1,23 +1,20 @@
/*
- * Fernflower - The Analytical Java Decompiler
- * http://www.reversed-java.com
+ * Copyright 2000-2014 JetBrains s.r.o.
*
- * (C) 2008 - 2010, Stiver
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * This software is NEITHER public domain NOR free software
- * as per GNU License. See license.txt for more details.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * This software is distributed WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
-
package org.jetbrains.java.decompiler.modules.decompiler.stats;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-
import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.collectors.CounterContainer;
@@ -29,178 +26,184 @@ import org.jetbrains.java.decompiler.modules.decompiler.vars.VarProcessor;
import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+
public class CatchStatement extends Statement {
-
- private List<List<String>> exctstrings = new ArrayList<List<String>>();
-
- private List<VarExprent> vars = new ArrayList<VarExprent>();
-
- // *****************************************************************************
- // constructors
- // *****************************************************************************
-
- private CatchStatement() {
- type = TYPE_TRYCATCH;
- }
-
- private CatchStatement(Statement head, Statement next, HashSet<Statement> setHandlers) {
-
- this();
-
- first = head;
- stats.addWithKey(first, first.id);
-
- for(StatEdge edge : head.getSuccessorEdges(StatEdge.TYPE_EXCEPTION)) {
- Statement stat = edge.getDestination();
-
- if(setHandlers.contains(stat)) {
- stats.addWithKey(stat, stat.id);
- exctstrings.add(new ArrayList<String>(edge.getExceptions()));
-
- vars.add(new VarExprent(DecompilerContext.getCountercontainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER),
- new VarType(CodeConstants.TYPE_OBJECT, 0, edge.getExceptions().get(0)), // FIXME: for now simply the first type. Should get the first common superclass when possible.
- (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR)));
- }
- }
-
- if(next != null) {
- post = next;
- }
-
- }
-
- // *****************************************************************************
- // public methods
- // *****************************************************************************
-
- public static Statement isHead(Statement head) {
-
- if(head.getLastBasicType() != LASTBASICTYPE_GENERAL) {
- return null;
- }
-
- HashSet<Statement> setHandlers = DecHelper.getUniquePredExceptions(head);
-
- if(!setHandlers.isEmpty()) {
-
- int hnextcount = 0; // either no statements with connection to next, or more than 1
-
- Statement next = null;
- List<StatEdge> lstHeadSuccs = head.getSuccessorEdges(STATEDGE_DIRECT_ALL);
- if(!lstHeadSuccs.isEmpty() && lstHeadSuccs.get(0).getType() == StatEdge.TYPE_REGULAR) {
- next = lstHeadSuccs.get(0).getDestination();
- hnextcount = 2;
- }
-
- for(StatEdge edge : head.getSuccessorEdges(StatEdge.TYPE_EXCEPTION)) {
- Statement stat = edge.getDestination();
-
- boolean handlerok = true;
-
- if(edge.getExceptions() != null && setHandlers.contains(stat)) {
- if(stat.getLastBasicType() != LASTBASICTYPE_GENERAL) {
- handlerok = false;
- } else {
- List<StatEdge> lstStatSuccs = stat.getSuccessorEdges(STATEDGE_DIRECT_ALL);
- if(!lstStatSuccs.isEmpty() && lstStatSuccs.get(0).getType() == StatEdge.TYPE_REGULAR) {
-
- Statement statn = lstStatSuccs.get(0).getDestination();
-
- if(next == null) {
- next = statn;
- } else if(next != statn) {
- handlerok = false;
- }
-
- if(handlerok) {
- hnextcount++;
- }
- }
- }
- } else {
- handlerok = false;
- }
-
- if(!handlerok) {
- setHandlers.remove(stat);
- }
- }
-
- if(hnextcount != 1 && !setHandlers.isEmpty()) {
- List<Statement> lst = new ArrayList<Statement>();
- lst.add(head);
- lst.addAll(setHandlers);
-
- for(Statement st : lst) {
- if(st.isMonitorEnter()) {
- return null;
- }
- }
-
- if(DecHelper.checkStatementExceptions(lst)) {
- return new CatchStatement(head, next, setHandlers);
- }
- }
- }
- 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));
-
- if(isLabeled()) {
- buf.append(indstr+"label"+this.id+":" + new_line_separator);
- }
-
- buf.append(indstr+"try {" + new_line_separator);
- buf.append(ExprProcessor.jmpWrapper(first, indent+1, true));
- buf.append(indstr+"}");
-
- for(int i=1;i<stats.size();i++) {
- List<String> exception_types = exctstrings.get(i - 1);
-
- buf.append(" catch (");
- if(exception_types.size() > 1) { // multi-catch, Java 7 style
- for(int exc_index = 1; exc_index < exception_types.size(); ++exc_index) {
- VarType exc_type = new VarType(CodeConstants.TYPE_OBJECT, 0, exception_types.get(exc_index));
- String exc_type_name = ExprProcessor.getCastTypeName(exc_type);
-
- buf.append(exc_type_name + " | ");
- }
- }
- buf.append(vars.get(i-1).toJava(indent));
- buf.append(") {"+new_line_separator+ExprProcessor.jmpWrapper(stats.get(i), indent+1, true)+indstr+"}");
- }
- buf.append(new_line_separator);
-
- return buf.toString();
- }
-
- public Statement getSimpleCopy() {
-
- CatchStatement cs = new CatchStatement();
-
- for(List<String> exc : this.exctstrings) {
- cs.exctstrings.add(new ArrayList<String>(exc));
- cs.vars.add(new VarExprent(DecompilerContext.getCountercontainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER),
- new VarType(CodeConstants.TYPE_OBJECT, 0, exc.get(0)),
- (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR)));
- }
-
- return cs;
- }
-
- // *****************************************************************************
- // getter and setter methods
- // *****************************************************************************
-
- public List<VarExprent> getVars() {
- return vars;
- }
-
+
+ private List<List<String>> exctstrings = new ArrayList<List<String>>();
+
+ private List<VarExprent> vars = new ArrayList<VarExprent>();
+
+ // *****************************************************************************
+ // constructors
+ // *****************************************************************************
+
+ private CatchStatement() {
+ type = TYPE_TRYCATCH;
+ }
+
+ private CatchStatement(Statement head, Statement next, HashSet<Statement> setHandlers) {
+
+ this();
+
+ first = head;
+ stats.addWithKey(first, first.id);
+
+ for (StatEdge edge : head.getSuccessorEdges(StatEdge.TYPE_EXCEPTION)) {
+ Statement stat = edge.getDestination();
+
+ if (setHandlers.contains(stat)) {
+ stats.addWithKey(stat, stat.id);
+ exctstrings.add(new ArrayList<String>(edge.getExceptions()));
+
+ vars.add(new VarExprent(DecompilerContext.getCountercontainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER),
+ new VarType(CodeConstants.TYPE_OBJECT, 0, edge.getExceptions().get(0)),
+ // FIXME: for now simply the first type. Should get the first common superclass when possible.
+ (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR)));
+ }
+ }
+
+ if (next != null) {
+ post = next;
+ }
+ }
+
+ // *****************************************************************************
+ // public methods
+ // *****************************************************************************
+
+ public static Statement isHead(Statement head) {
+
+ if (head.getLastBasicType() != LASTBASICTYPE_GENERAL) {
+ return null;
+ }
+
+ HashSet<Statement> setHandlers = DecHelper.getUniquePredExceptions(head);
+
+ if (!setHandlers.isEmpty()) {
+
+ int hnextcount = 0; // either no statements with connection to next, or more than 1
+
+ Statement next = null;
+ List<StatEdge> lstHeadSuccs = head.getSuccessorEdges(STATEDGE_DIRECT_ALL);
+ if (!lstHeadSuccs.isEmpty() && lstHeadSuccs.get(0).getType() == StatEdge.TYPE_REGULAR) {
+ next = lstHeadSuccs.get(0).getDestination();
+ hnextcount = 2;
+ }
+
+ for (StatEdge edge : head.getSuccessorEdges(StatEdge.TYPE_EXCEPTION)) {
+ Statement stat = edge.getDestination();
+
+ boolean handlerok = true;
+
+ if (edge.getExceptions() != null && setHandlers.contains(stat)) {
+ if (stat.getLastBasicType() != LASTBASICTYPE_GENERAL) {
+ handlerok = false;
+ }
+ else {
+ List<StatEdge> lstStatSuccs = stat.getSuccessorEdges(STATEDGE_DIRECT_ALL);
+ if (!lstStatSuccs.isEmpty() && lstStatSuccs.get(0).getType() == StatEdge.TYPE_REGULAR) {
+
+ Statement statn = lstStatSuccs.get(0).getDestination();
+
+ if (next == null) {
+ next = statn;
+ }
+ else if (next != statn) {
+ handlerok = false;
+ }
+
+ if (handlerok) {
+ hnextcount++;
+ }
+ }
+ }
+ }
+ else {
+ handlerok = false;
+ }
+
+ if (!handlerok) {
+ setHandlers.remove(stat);
+ }
+ }
+
+ if (hnextcount != 1 && !setHandlers.isEmpty()) {
+ List<Statement> lst = new ArrayList<Statement>();
+ lst.add(head);
+ lst.addAll(setHandlers);
+
+ for (Statement st : lst) {
+ if (st.isMonitorEnter()) {
+ return null;
+ }
+ }
+
+ if (DecHelper.checkStatementExceptions(lst)) {
+ return new CatchStatement(head, next, setHandlers);
+ }
+ }
+ }
+ 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));
+
+ if (isLabeled()) {
+ buf.append(indstr + "label" + this.id + ":" + new_line_separator);
+ }
+
+ buf.append(indstr + "try {" + new_line_separator);
+ buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true));
+ buf.append(indstr + "}");
+
+ for (int i = 1; i < stats.size(); i++) {
+ List<String> exception_types = exctstrings.get(i - 1);
+
+ buf.append(" catch (");
+ if (exception_types.size() > 1) { // multi-catch, Java 7 style
+ for (int exc_index = 1; exc_index < exception_types.size(); ++exc_index) {
+ VarType exc_type = new VarType(CodeConstants.TYPE_OBJECT, 0, exception_types.get(exc_index));
+ String exc_type_name = ExprProcessor.getCastTypeName(exc_type);
+
+ buf.append(exc_type_name + " | ");
+ }
+ }
+ buf.append(vars.get(i - 1).toJava(indent));
+ buf.append(") {" + new_line_separator + ExprProcessor.jmpWrapper(stats.get(i), indent + 1, true) + indstr + "}");
+ }
+ buf.append(new_line_separator);
+
+ return buf.toString();
+ }
+
+ public Statement getSimpleCopy() {
+
+ CatchStatement cs = new CatchStatement();
+
+ for (List<String> exc : this.exctstrings) {
+ cs.exctstrings.add(new ArrayList<String>(exc));
+ cs.vars.add(new VarExprent(DecompilerContext.getCountercontainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER),
+ new VarType(CodeConstants.TYPE_OBJECT, 0, exc.get(0)),
+ (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR)));
+ }
+
+ return cs;
+ }
+
+ // *****************************************************************************
+ // getter and setter methods
+ // *****************************************************************************
+
+ public List<VarExprent> getVars() {
+ return vars;
+ }
}
diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/DoStatement.java b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/DoStatement.java
index 604e36f..2bd8e3a 100644
--- a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/DoStatement.java
+++ b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/DoStatement.java
@@ -1,221 +1,221 @@
/*
- * Fernflower - The Analytical Java Decompiler
- * http://www.reversed-java.com
+ * Copyright 2000-2014 JetBrains s.r.o.
*
- * (C) 2008 - 2010, Stiver
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * This software is NEITHER public domain NOR free software
- * as per GNU License. See license.txt for more details.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * This software is distributed WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
-
package org.jetbrains.java.decompiler.modules.decompiler.stats;
-import java.util.ArrayList;
-import java.util.List;
-
import org.jetbrains.java.decompiler.main.DecompilerContext;
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.util.InterpreterUtil;
+import java.util.ArrayList;
+import java.util.List;
+
public class DoStatement extends Statement {
-
- public static final int LOOP_DO = 0;
- public static final int LOOP_DOWHILE = 1;
- public static final int LOOP_WHILE = 2;
- public static final int LOOP_FOR = 3;
-
- private int looptype;
-
- private List<Exprent> initExprent = new ArrayList<Exprent>();
- private List<Exprent> conditionExprent = new ArrayList<Exprent>();
- private List<Exprent> incExprent = new ArrayList<Exprent>();
-
- // *****************************************************************************
- // constructors
- // *****************************************************************************
-
- private DoStatement() {
- type = Statement.TYPE_DO;
- looptype = LOOP_DO;
-
- initExprent.add(null);
- conditionExprent.add(null);
- incExprent.add(null);
- }
-
- private DoStatement(Statement head) {
-
- this();
-
- first = head;
- stats.addWithKey(first, first.id);
-
- // post is always null!
- }
-
- // *****************************************************************************
- // public methods
- // *****************************************************************************
-
- public static Statement isHead(Statement head) {
-
- if(head.getLastBasicType() == LASTBASICTYPE_GENERAL && !head.isMonitorEnter()) {
-
- // at most one outgoing edge
- StatEdge edge = null;
- List<StatEdge> lstSuccs = head.getSuccessorEdges(STATEDGE_DIRECT_ALL);
- if(!lstSuccs.isEmpty()) {
- edge = lstSuccs.get(0);
- }
-
- // regular loop
- if(edge!=null && edge.getType() == StatEdge.TYPE_REGULAR && edge.getDestination() == head) {
- return new DoStatement(head);
- }
-
- // continues
- if(head.type != TYPE_DO && (edge == null || edge.getType() != StatEdge.TYPE_REGULAR) &&
- head.getContinueSet().contains(head.getBasichead())) {
- return new DoStatement(head);
- }
- }
-
- 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));
-
- if(isLabeled()) {
- buf.append(indstr+"label"+this.id+":" + new_line_separator);
- }
-
- switch(looptype) {
- case LOOP_DO:
- buf.append(indstr+"while(true) {" + new_line_separator);
- buf.append(ExprProcessor.jmpWrapper(first, indent+1, true));
- buf.append(indstr+"}" + new_line_separator);
- break;
- case LOOP_DOWHILE:
- buf.append(indstr+"do {" + new_line_separator);
- buf.append(ExprProcessor.jmpWrapper(first, indent+1, true));
- buf.append(indstr+"} while("+conditionExprent.get(0).toJava(indent)+");" + new_line_separator);
- break;
- case LOOP_WHILE:
- buf.append(indstr+"while("+conditionExprent.get(0).toJava(indent)+") {" + new_line_separator);
- buf.append(ExprProcessor.jmpWrapper(first, indent+1, true));
- buf.append(indstr+"}" + new_line_separator);
- break;
- case LOOP_FOR:
- buf.append(indstr+"for("+(initExprent.get(0)==null?"":initExprent.get(0).toJava(indent))+
- "; "+conditionExprent.get(0).toJava(indent)+"; "+incExprent.get(0).toJava(indent)+") {" + new_line_separator);
- buf.append(ExprProcessor.jmpWrapper(first, indent+1, true));
- buf.append(indstr+"}" + new_line_separator);
- }
-
- return buf.toString();
- }
-
- public List<Object> getSequentialObjects() {
-
- List<Object> lst = new ArrayList<Object>();
-
- switch(looptype) {
- case LOOP_FOR:
- if(getInitExprent() != null) {
- lst.add(getInitExprent());
- }
- case LOOP_WHILE:
- lst.add(getConditionExprent());
- }
-
- lst.add(first);
-
- switch(looptype) {
- case LOOP_DOWHILE:
- lst.add(getConditionExprent());
- break;
- case LOOP_FOR:
- lst.add(getIncExprent());
- }
-
- return lst;
- }
-
- public void replaceExprent(Exprent oldexpr, Exprent newexpr) {
- if(initExprent.get(0) == oldexpr) {
- initExprent.set(0, newexpr);
- }
- if(conditionExprent.get(0) == oldexpr) {
- conditionExprent.set(0, newexpr);
- }
- if(incExprent.get(0) == oldexpr) {
- incExprent.set(0, newexpr);
- }
- }
-
- public Statement getSimpleCopy() {
- return new DoStatement();
- }
-
- // *****************************************************************************
- // getter and setter methods
- // *****************************************************************************
-
- public List<Exprent> getInitExprentList() {
- return initExprent;
- }
-
- public List<Exprent> getConditionExprentList() {
- return conditionExprent;
- }
-
- public List<Exprent> getIncExprentList() {
- return incExprent;
- }
-
- public Exprent getConditionExprent() {
- return conditionExprent.get(0);
- }
-
- public void setConditionExprent(Exprent conditionExprent) {
- this.conditionExprent.set(0, conditionExprent);
- }
-
- public Exprent getIncExprent() {
- return incExprent.get(0);
- }
-
- public void setIncExprent(Exprent incExprent) {
- this.incExprent.set(0, incExprent);
- }
-
- public Exprent getInitExprent() {
- return initExprent.get(0);
- }
-
- public void setInitExprent(Exprent initExprent) {
- this.initExprent.set(0, initExprent);
- }
-
- public int getLooptype() {
- return looptype;
- }
-
- public void setLooptype(int looptype) {
- this.looptype = looptype;
- }
-
+
+ public static final int LOOP_DO = 0;
+ public static final int LOOP_DOWHILE = 1;
+ public static final int LOOP_WHILE = 2;
+ public static final int LOOP_FOR = 3;
+
+ private int looptype;
+
+ private List<Exprent> initExprent = new ArrayList<Exprent>();
+ private List<Exprent> conditionExprent = new ArrayList<Exprent>();
+ private List<Exprent> incExprent = new ArrayList<Exprent>();
+
+ // *****************************************************************************
+ // constructors
+ // *****************************************************************************
+
+ private DoStatement() {
+ type = Statement.TYPE_DO;
+ looptype = LOOP_DO;
+
+ initExprent.add(null);
+ conditionExprent.add(null);
+ incExprent.add(null);
+ }
+
+ private DoStatement(Statement head) {
+
+ this();
+
+ first = head;
+ stats.addWithKey(first, first.id);
+
+ // post is always null!
+ }
+
+ // *****************************************************************************
+ // public methods
+ // *****************************************************************************
+
+ public static Statement isHead(Statement head) {
+
+ if (head.getLastBasicType() == LASTBASICTYPE_GENERAL && !head.isMonitorEnter()) {
+
+ // at most one outgoing edge
+ StatEdge edge = null;
+ List<StatEdge> lstSuccs = head.getSuccessorEdges(STATEDGE_DIRECT_ALL);
+ if (!lstSuccs.isEmpty()) {
+ edge = lstSuccs.get(0);
+ }
+
+ // regular loop
+ if (edge != null && edge.getType() == StatEdge.TYPE_REGULAR && edge.getDestination() == head) {
+ return new DoStatement(head);
+ }
+
+ // continues
+ if (head.type != TYPE_DO && (edge == null || edge.getType() != StatEdge.TYPE_REGULAR) &&
+ head.getContinueSet().contains(head.getBasichead())) {
+ return new DoStatement(head);
+ }
+ }
+
+ 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));
+
+ if (isLabeled()) {
+ buf.append(indstr + "label" + this.id + ":" + new_line_separator);
+ }
+
+ switch (looptype) {
+ case LOOP_DO:
+ buf.append(indstr + "while(true) {" + new_line_separator);
+ buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true));
+ buf.append(indstr + "}" + new_line_separator);
+ break;
+ case LOOP_DOWHILE:
+ buf.append(indstr + "do {" + new_line_separator);
+ buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true));
+ buf.append(indstr + "} while(" + conditionExprent.get(0).toJava(indent) + ");" + new_line_separator);
+ break;
+ case LOOP_WHILE:
+ buf.append(indstr + "while(" + conditionExprent.get(0).toJava(indent) + ") {" + new_line_separator);
+ buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true));
+ buf.append(indstr + "}" + new_line_separator);
+ break;
+ case LOOP_FOR:
+ buf.append(indstr + "for(" + (initExprent.get(0) == null ? "" : initExprent.get(0).toJava(indent)) +
+ "; " + conditionExprent.get(0).toJava(indent) + "; " + incExprent.get(0).toJava(indent) + ") {" + new_line_separator);
+ buf.append(ExprProcessor.jmpWrapper(first, indent + 1, true));
+ buf.append(indstr + "}" + new_line_separator);
+ }
+
+ return buf.toString();
+ }
+
+ public List<Object> getSequentialObjects() {
+
+ List<Object> lst = new ArrayList<Object>();
+
+ switch (looptype) {
+ case LOOP_FOR:
+ if (getInitExprent() != null) {
+ lst.add(getInitExprent());
+ }
+ case LOOP_WHILE:
+ lst.add(getConditionExprent());
+ }
+
+ lst.add(first);
+
+ switch (looptype) {
+ case LOOP_DOWHILE:
+ lst.add(getConditionExprent());
+ break;
+ case LOOP_FOR:
+ lst.add(getIncExprent());
+ }
+
+ return lst;
+ }
+
+ public void replaceExprent(Exprent oldexpr, Exprent newexpr) {
+ if (initExprent.get(0) == oldexpr) {
+ initExprent.set(0, newexpr);
+ }
+ if (conditionExprent.get(0) == oldexpr) {
+ conditionExprent.set(0, newexpr);
+ }
+ if (incExprent.get(0) == oldexpr) {
+ incExprent.set(0, newexpr);
+ }
+ }
+
+ public Statement getSimpleCopy() {
+ return new DoStatement();
+ }
+
+ // *****************************************************************************
+ // getter and setter methods
+ // *****************************************************************************
+
+ public List<Exprent> getInitExprentList() {
+ return initExprent;
+ }
+
+ public List<Exprent> getConditionExprentList() {
+ return conditionExprent;
+ }
+
+ public List<Exprent> getIncExprentList() {
+ return incExprent;
+ }
+
+ public Exprent getConditionExprent() {
+ return conditionExprent.get(0);
+ }
+
+ public void setConditionExprent(Exprent conditionExprent) {
+ this.conditionExprent.set(0, conditionExprent);
+ }
+
+ public Exprent getIncExprent() {
+ return incExprent.get(0);
+ }
+
+ public void setIncExprent(Exprent incExprent) {
+ this.incExprent.set(0, incExprent);
+ }
+
+ public Exprent getInitExprent() {
+ return initExprent.get(0);
+ }
+
+ public void setInitExprent(Exprent initExprent) {
+ this.initExprent.set(0, initExprent);
+ }
+
+ public int getLooptype() {
+ return looptype;
+ }
+
+ public void setLooptype(int looptype) {
+ this.looptype = looptype;
+ }
}
diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/GeneralStatement.java b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/GeneralStatement.java
index 9cfaeb4..9988881 100644
--- a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/GeneralStatement.java
+++ b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/GeneralStatement.java
@@ -1,75 +1,74 @@
/*
- * Fernflower - The Analytical Java Decompiler
- * http://www.reversed-java.com
+ * Copyright 2000-2014 JetBrains s.r.o.
*
- * (C) 2008 - 2010, Stiver
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * This software is NEITHER public domain NOR free software
- * as per GNU License. See license.txt for more details.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * This software is distributed WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
-
package org.jetbrains.java.decompiler.modules.decompiler.stats;
-import java.util.Collection;
-import java.util.HashSet;
-
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
+import java.util.Collection;
+import java.util.HashSet;
public class GeneralStatement extends Statement {
-
- // *****************************************************************************
- // constructors
- // *****************************************************************************
-
- private GeneralStatement() {
- type = Statement.TYPE_GENERAL;
- }
-
- public GeneralStatement(Statement head, Collection<Statement> statements, Statement post) {
-
- this();
-
- first = head;
- stats.addWithKey(head, head.id);
-
- HashSet<Statement> set = new HashSet<Statement>(statements);
- set.remove(head);
-
- for(Statement st : set) {
- stats.addWithKey(st, st.id);
- }
-
- this.post = post;
- }
-
- // *****************************************************************************
- // public methods
- // *****************************************************************************
-
- public String toJava(int indent) {
- String indstr = InterpreterUtil.getIndentString(indent);
- StringBuffer buf = new StringBuffer();
-
- String new_line_separator = DecompilerContext.getNewLineSeparator();
-
- if(isLabeled()) {
- buf.append(indstr+"label"+this.id+":" + new_line_separator);
- }
-
- buf.append(indstr+"abstract statement {" + new_line_separator);
- for(int i=0;i<stats.size();i++) {
- buf.append(stats.get(i).toJava(indent+1));
- }
- buf.append(indstr+"}");
-
- return buf.toString();
- }
-
+
+ // *****************************************************************************
+ // constructors
+ // *****************************************************************************
+
+ private GeneralStatement() {
+ type = Statement.TYPE_GENERAL;
+ }
+
+ public GeneralStatement(Statement head, Collection<Statement> statements, Statement post) {
+
+ this();
+
+ first = head;
+ stats.addWithKey(head, head.id);
+
+ HashSet<Statement> set = new HashSet<Statement>(statements);
+ set.remove(head);
+
+ for (Statement st : set) {
+ stats.addWithKey(st, st.id);
+ }
+
+ this.post = post;
+ }
+
+ // *****************************************************************************
+ // public methods
+ // *****************************************************************************
+
+ public String toJava(int indent) {
+ String indstr = InterpreterUtil.getIndentString(indent);
+ StringBuffer buf = new StringBuffer();
+
+ String new_line_separator = DecompilerContext.getNewLineSeparator();
+
+ if (isLabeled()) {
+ buf.append(indstr + "label" + this.id + ":" + new_line_separator);
+ }
+
+ buf.append(indstr + "abstract statement {" + new_line_separator);
+ for (int i = 0; i < stats.size(); i++) {
+ buf.append(stats.get(i).toJava(indent + 1));
+ }
+ buf.append(indstr + "}");
+
+ return buf.toString();
+ }
}
diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/IfStatement.java b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/IfStatement.java
index 3e3e20b..0b05981 100644
--- a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/IfStatement.java
+++ b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/IfStatement.java
@@ -1,22 +1,20 @@
/*
- * Fernflower - The Analytical Java Decompiler
- * http://www.reversed-java.com
+ * Copyright 2000-2014 JetBrains s.r.o.
*
- * (C) 2008 - 2010, Stiver
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * This software is NEITHER public domain NOR free software
- * as per GNU License. See license.txt for more details.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * This software is distributed WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
-
package org.jetbrains.java.decompiler.modules.decompiler.stats;
-import java.util.ArrayList;
-import java.util.List;
-
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.modules.decompiler.DecHelper;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
@@ -25,380 +23,394 @@ 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;
+import java.util.ArrayList;
+import java.util.List;
+
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;
- }
+ 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;
+ }
}
diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/RootStatement.java b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/RootStatement.java
index c34888e..2a69447 100644
--- a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/RootStatement.java
+++ b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/RootStatement.java
@@ -1,17 +1,18 @@
/*
- * Fernflower - The Analytical Java Decompiler
- * http://www.reversed-java.com
+ * Copyright 2000-2014 JetBrains s.r.o.
*
- * (C) 2008 - 2010, Stiver
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * This software is NEITHER public domain NOR free software
- * as per GNU License. See license.txt for more details.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * This software is distributed WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
-
package org.jetbrains.java.decompiler.modules.decompiler.stats;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
@@ -19,31 +20,29 @@ import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
public class RootStatement extends Statement {
- private Statement dummyExit;
-
- public RootStatement(Statement head, Statement dummyExit) {
-
- type = Statement.TYPE_ROOT;
-
- first = head;
- this.dummyExit = dummyExit;
-
- stats.addWithKey(first, first.id);
- first.setParent(this);
-
- }
-
- public String toJava(int indent) {
- return ExprProcessor.listToJava(varDefinitions, indent)+
- first.toJava(indent);
- }
-
- public Statement getDummyExit() {
- return dummyExit;
- }
-
- public void setDummyExit(Statement dummyExit) {
- this.dummyExit = dummyExit;
- }
-
+ private Statement dummyExit;
+
+ public RootStatement(Statement head, Statement dummyExit) {
+
+ type = Statement.TYPE_ROOT;
+
+ first = head;
+ this.dummyExit = dummyExit;
+
+ stats.addWithKey(first, first.id);
+ first.setParent(this);
+ }
+
+ public String toJava(int indent) {
+ return ExprProcessor.listToJava(varDefinitions, indent) +
+ first.toJava(indent);
+ }
+
+ public Statement getDummyExit() {
+ return dummyExit;
+ }
+
+ public void setDummyExit(Statement dummyExit) {
+ this.dummyExit = dummyExit;
+ }
}
diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SequenceStatement.java b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SequenceStatement.java
index 79b0b19..8fd8a43 100644
--- a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SequenceStatement.java
+++ b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SequenceStatement.java
@@ -1,144 +1,144 @@
/*
- * Fernflower - The Analytical Java Decompiler
- * http://www.reversed-java.com
+ * Copyright 2000-2014 JetBrains s.r.o.
*
- * (C) 2008 - 2010, Stiver
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * This software is NEITHER public domain NOR free software
- * as per GNU License. See license.txt for more details.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * This software is distributed WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
-
package org.jetbrains.java.decompiler.modules.decompiler.stats;
-import java.util.Arrays;
-import java.util.List;
-
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.util.InterpreterUtil;
+import java.util.Arrays;
+import java.util.List;
+
public class SequenceStatement extends Statement {
-
- // *****************************************************************************
- // constructors
- // *****************************************************************************
-
- private SequenceStatement() {
- type = Statement.TYPE_SEQUENCE;
- }
-
- public SequenceStatement(List<Statement> lst) {
-
- this();
-
- lastBasicType = lst.get(lst.size()-1).getLastBasicType();
-
- for(Statement st: lst) {
- stats.addWithKey(st, st.id);
- }
-
- first = stats.get(0);
- }
-
- private SequenceStatement(Statement head, Statement tail) {
-
- this(Arrays.asList(new Statement[] {head, tail}));
-
- List<StatEdge> lstSuccs = tail.getSuccessorEdges(STATEDGE_DIRECT_ALL);
- if(!lstSuccs.isEmpty()) {
- StatEdge edge = lstSuccs.get(0);
-
- if(edge.getType() == StatEdge.TYPE_REGULAR && edge.getDestination() != head) {
- post = edge.getDestination();
- }
- }
- }
-
-
- // *****************************************************************************
- // public methods
- // *****************************************************************************
-
- public static Statement isHead2Block(Statement head) {
-
- if(head.getLastBasicType() != Statement.LASTBASICTYPE_GENERAL) {
- return null;
- }
-
- // at most one outgoing edge
- StatEdge edge = null;
- List<StatEdge> lstSuccs = head.getSuccessorEdges(STATEDGE_DIRECT_ALL);
- if(!lstSuccs.isEmpty()) {
- edge = lstSuccs.get(0);
- }
-
- if(edge != null && edge.getType() == StatEdge.TYPE_REGULAR) {
- Statement stat = edge.getDestination();
-
- if(stat != head && stat.getPredecessorEdges(StatEdge.TYPE_REGULAR).size() == 1
- && !stat.isMonitorEnter()) {
-
- if(stat.getLastBasicType() == Statement.LASTBASICTYPE_GENERAL) {
- if(DecHelper.checkStatementExceptions(Arrays.asList(new Statement[] {head, stat}))) {
- return new SequenceStatement(head, stat);
- }
- }
- }
- }
-
- return null;
- }
-
- public String toJava(int indent) {
-
- StringBuilder buf = new StringBuilder();
-
- String indstr = null;
- boolean islabeled = isLabeled();
-
- String new_line_separator = DecompilerContext.getNewLineSeparator();
-
- buf.append(ExprProcessor.listToJava(varDefinitions, indent));
-
- if(islabeled) {
- indstr = InterpreterUtil.getIndentString(indent);
- indent++;
- buf.append(indstr+"label"+this.id+": {" + new_line_separator);
- }
-
- boolean notempty = false;
-
- for(int i=0;i<stats.size();i++) {
-
- Statement st = stats.get(i);
-
- if(i>0 && notempty) {
- buf.append(new_line_separator);
- }
-
- String str = ExprProcessor.jmpWrapper(st, indent, false);
- buf.append(str);
-
- notempty = (str.trim().length() > 0);
- }
-
- if(islabeled) {
- buf.append(indstr+"}" + new_line_separator);
- }
-
- return buf.toString();
- }
-
- public Statement getSimpleCopy() {
- return new SequenceStatement();
- }
-
+
+ // *****************************************************************************
+ // constructors
+ // *****************************************************************************
+
+ private SequenceStatement() {
+ type = Statement.TYPE_SEQUENCE;
+ }
+
+ public SequenceStatement(List<Statement> lst) {
+
+ this();
+
+ lastBasicType = lst.get(lst.size() - 1).getLastBasicType();
+
+ for (Statement st : lst) {
+ stats.addWithKey(st, st.id);
+ }
+
+ first = stats.get(0);
+ }
+
+ private SequenceStatement(Statement head, Statement tail) {
+
+ this(Arrays.asList(new Statement[]{head, tail}));
+
+ List<StatEdge> lstSuccs = tail.getSuccessorEdges(STATEDGE_DIRECT_ALL);
+ if (!lstSuccs.isEmpty()) {
+ StatEdge edge = lstSuccs.get(0);
+
+ if (edge.getType() == StatEdge.TYPE_REGULAR && edge.getDestination() != head) {
+ post = edge.getDestination();
+ }
+ }
+ }
+
+
+ // *****************************************************************************
+ // public methods
+ // *****************************************************************************
+
+ public static Statement isHead2Block(Statement head) {
+
+ if (head.getLastBasicType() != Statement.LASTBASICTYPE_GENERAL) {
+ return null;
+ }
+
+ // at most one outgoing edge
+ StatEdge edge = null;
+ List<StatEdge> lstSuccs = head.getSuccessorEdges(STATEDGE_DIRECT_ALL);
+ if (!lstSuccs.isEmpty()) {
+ edge = lstSuccs.get(0);
+ }
+
+ if (edge != null && edge.getType() == StatEdge.TYPE_REGULAR) {
+ Statement stat = edge.getDestination();
+
+ if (stat != head && stat.getPredecessorEdges(StatEdge.TYPE_REGULAR).size() == 1
+ && !stat.isMonitorEnter()) {
+
+ if (stat.getLastBasicType() == Statement.LASTBASICTYPE_GENERAL) {
+ if (DecHelper.checkStatementExceptions(Arrays.asList(new Statement[]{head, stat}))) {
+ return new SequenceStatement(head, stat);
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public String toJava(int indent) {
+
+ StringBuilder buf = new StringBuilder();
+
+ String indstr = null;
+ boolean islabeled = isLabeled();
+
+ String new_line_separator = DecompilerContext.getNewLineSeparator();
+
+ buf.append(ExprProcessor.listToJava(varDefinitions, indent));
+
+ if (islabeled) {
+ indstr = InterpreterUtil.getIndentString(indent);
+ indent++;
+ buf.append(indstr + "label" + this.id + ": {" + new_line_separator);
+ }
+
+ boolean notempty = false;
+
+ for (int i = 0; i < stats.size(); i++) {
+
+ Statement st = stats.get(i);
+
+ if (i > 0 && notempty) {
+ buf.append(new_line_separator);
+ }
+
+ String str = ExprProcessor.jmpWrapper(st, indent, false);
+ buf.append(str);
+
+ notempty = (str.trim().length() > 0);
+ }
+
+ if (islabeled) {
+ buf.append(indstr + "}" + new_line_separator);
+ }
+
+ return buf.toString();
+ }
+
+ public Statement getSimpleCopy() {
+ return new SequenceStatement();
+ }
}
diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/Statement.java b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/Statement.java
index 2f64035..aceb2b8 100644
--- a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/Statement.java
+++ b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/Statement.java
@@ -1,27 +1,20 @@
/*
- * Fernflower - The Analytical Java Decompiler
- * http://www.reversed-java.com
+ * Copyright 2000-2014 JetBrains s.r.o.
*
- * (C) 2008 - 2010, Stiver
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * This software is NEITHER public domain NOR free software
- * as per GNU License. See license.txt for more details.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * This software is distributed WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
-
package org.jetbrains.java.decompiler.modules.decompiler.stats;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.code.InstructionSequence;
import org.jetbrains.java.decompiler.main.DecompilerContext;
@@ -32,840 +25,848 @@ import org.jetbrains.java.decompiler.modules.decompiler.StrongConnectivityHelper
import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent;
import org.jetbrains.java.decompiler.util.VBStyleCollection;
+import java.util.*;
+
public class Statement {
-
- public static final int STATEDGE_ALL = 1 << 31;
- public static final int STATEDGE_DIRECT_ALL = 1 << 30;
-
- public static final int DIRECTION_BACKWARD = 0;
- public static final int DIRECTION_FORWARD = 1;
-
- public static final int TYPE_GENERAL = 0;
- public static final int TYPE_IF = 2;
- public static final int TYPE_DO = 5;
- public static final int TYPE_SWITCH = 6;
- public static final int TYPE_TRYCATCH = 7;
- public static final int TYPE_BASICBLOCK = 8;
- public static final int TYPE_FINALLY = 9;
- public static final int TYPE_SYNCRONIZED = 10;
- public static final int TYPE_PLACEHOLDER = 11;
- public static final int TYPE_CATCHALL = 12;
- public static final int TYPE_ROOT = 13;
- public static final int TYPE_DUMMYEXIT = 14;
- public static final int TYPE_SEQUENCE = 15;
-
-
- public static final int LASTBASICTYPE_IF = 0;
- public static final int LASTBASICTYPE_SWITCH = 1;
- public static final int LASTBASICTYPE_GENERAL = 2;
-
-
- // *****************************************************************************
- // public fields
- // *****************************************************************************
-
- public int type;
-
- public Integer id;
-
- // *****************************************************************************
- // private fields
- // *****************************************************************************
-
- private Map<Integer, List<StatEdge>> mapSuccEdges = new HashMap<Integer, List<StatEdge>>();
- private Map<Integer, List<StatEdge>> mapPredEdges = new HashMap<Integer, List<StatEdge>>();
-
- private Map<Integer, List<Statement>> mapSuccStates = new HashMap<Integer, List<Statement>>();
- private Map<Integer, List<Statement>> mapPredStates = new HashMap<Integer, List<Statement>>();
-
- // statement as graph
- protected VBStyleCollection<Statement, Integer> stats = new VBStyleCollection<Statement, Integer>();
-
- protected Statement parent;
-
- protected Statement first;
-
- protected List<Exprent> exprents;
-
- protected HashSet<StatEdge> labelEdges = new HashSet<StatEdge>();
-
- protected List<Exprent> varDefinitions = new ArrayList<Exprent>();
-
- // copied statement, s. deobfuscating of irreducible CFGs
- private boolean copied = false;
-
- // relevant for the first stage of processing only
- // set to null after initializing of the statement structure
-
- protected Statement post;
-
- protected int lastBasicType = LASTBASICTYPE_GENERAL;
-
- protected boolean isMonitorEnter;
-
- protected boolean containsMonitorExit;
-
- protected HashSet<Statement> continueSet = new HashSet<Statement>();
-
- // *****************************************************************************
- // initializers
- // *****************************************************************************
-
- {
- // set statement id
- id = DecompilerContext.getCountercontainer().getCounterAndIncrement(CounterContainer.STATEMENT_COUNTER);
- }
-
- // *****************************************************************************
- // public methods
- // *****************************************************************************
-
- public void clearTempInformation() {
-
- post = null;
- continueSet = null;
-
- copied = false;
- // FIXME: used in FlattenStatementsHelper.flattenStatement()! check and remove
- //lastBasicType = LASTBASICTYPE_GENERAL;
- isMonitorEnter = false;;
- containsMonitorExit = false;
-
- for(Map<Integer, List<StatEdge>> map : new Map[]{mapSuccEdges, mapPredEdges}) {
- map.remove(StatEdge.TYPE_EXCEPTION);
-
- List<StatEdge> lst = map.get(STATEDGE_DIRECT_ALL);
- if(lst != null) {
- map.put(STATEDGE_ALL, new ArrayList<StatEdge>(lst));
- } else {
- map.remove(STATEDGE_ALL);
- }
- }
-
- for(Map<Integer, List<Statement>> map : new Map[]{mapSuccStates, mapPredStates}) {
- map.remove(StatEdge.TYPE_EXCEPTION);
-
- List<Statement> lst = map.get(STATEDGE_DIRECT_ALL);
- if(lst != null) {
- map.put(STATEDGE_ALL, new ArrayList<Statement>(lst));
- } else {
- map.remove(STATEDGE_ALL);
- }
- }
-
- }
-
- public void collapseNodesToStatement(Statement stat) {
-
- Statement head = stat.getFirst();
- Statement post = stat.getPost();
-
- VBStyleCollection<Statement, Integer> setNodes = stat.getStats();
-
- // post edges
- if(post != null) {
- for(StatEdge edge : post.getEdges(STATEDGE_DIRECT_ALL, DIRECTION_BACKWARD)) {
- if(stat.containsStatementStrict(edge.getSource())) {
- edge.getSource().changeEdgeType(DIRECTION_FORWARD, edge, StatEdge.TYPE_BREAK);
- stat.addLabeledEdge(edge);
- }
- }
- }
-
- // regular head edges
- for(StatEdge prededge : head.getAllPredecessorEdges()) {
-
- if(prededge.getType() != StatEdge.TYPE_EXCEPTION &&
- stat.containsStatementStrict(prededge.getSource())) {
- prededge.getSource().changeEdgeType(DIRECTION_FORWARD, prededge, StatEdge.TYPE_CONTINUE);
- stat.addLabeledEdge(prededge);
- }
-
- head.removePredecessor(prededge);
- prededge.getSource().changeEdgeNode(DIRECTION_FORWARD, prededge, stat);
- stat.addPredecessor(prededge);
- }
-
- if(setNodes.containsKey(first.id)) {
- first = stat;
- }
-
- // exception edges
- Set<Statement> setHandlers = new HashSet<Statement>(head.getNeighbours(StatEdge.TYPE_EXCEPTION, DIRECTION_FORWARD));
- for(Statement node : setNodes) {
- setHandlers.retainAll(node.getNeighbours(StatEdge.TYPE_EXCEPTION, DIRECTION_FORWARD));
- }
-
- if(!setHandlers.isEmpty()) {
-
- for(StatEdge edge : head.getEdges(StatEdge.TYPE_EXCEPTION, DIRECTION_FORWARD)) {
- Statement handler = edge.getDestination();
-
- if(setHandlers.contains(handler)) {
- if(!setNodes.containsKey(handler.id)) {
- stat.addSuccessor(new StatEdge(stat, handler, edge.getExceptions()));
- }
- }
- }
-
- for(Statement node : setNodes) {
- for(StatEdge edge : node.getEdges(StatEdge.TYPE_EXCEPTION, DIRECTION_FORWARD)) {
- if(setHandlers.contains(edge.getDestination())) {
- node.removeSuccessor(edge);
- }
- }
- }
- }
-
- if(post!=null && !stat.getNeighbours(StatEdge.TYPE_EXCEPTION, DIRECTION_FORWARD).contains(post)) { // TODO: second condition redundant?
- stat.addSuccessor(new StatEdge(StatEdge.TYPE_REGULAR, stat, post));
- }
-
-
- // adjust statement collection
- for(Statement st: setNodes) {
- stats.removeWithKey(st.id);
- }
-
- stats.addWithKey(stat, stat.id);
-
- stat.setAllParent();
- stat.setParent(this);
-
- stat.buildContinueSet();
- // monitorenter and monitorexit
- stat.buildMonitorFlags();
-
- if(stat.type == Statement.TYPE_SWITCH) {
- // special case switch, sorting leaf nodes
- ((SwitchStatement)stat).sortEdgesAndNodes();
- }
-
- }
-
- public void setAllParent() {
- for(Statement st: stats) {
- st.setParent(this);
- }
- }
-
- public void addLabeledEdge(StatEdge edge) {
-
- if(edge.closure != null) {
- edge.closure.getLabelEdges().remove(edge);
- }
- edge.closure = this;
- this.getLabelEdges().add(edge);
- }
-
- private void addEdgeDirectInternal(int direction, StatEdge edge, int edgetype) {
-
- Map<Integer, List<StatEdge>> mapEdges = direction==DIRECTION_BACKWARD?mapPredEdges:mapSuccEdges;
- Map<Integer, List<Statement>> mapStates = direction==DIRECTION_BACKWARD?mapPredStates:mapSuccStates;
-
- List<StatEdge> lst = mapEdges.get(edgetype);
- if(lst == null) {
- mapEdges.put(edgetype, lst = new ArrayList<StatEdge>());
- }
- lst.add(edge);
-
- List<Statement> lstStates = mapStates.get(edgetype);
- if(lstStates == null) {
- mapStates.put(edgetype, lstStates = new ArrayList<Statement>());
- }
- lstStates.add(direction==DIRECTION_BACKWARD?edge.getSource():edge.getDestination());
- }
-
- private void addEdgeInternal(int direction, StatEdge edge) {
-
- int type = edge.getType();
-
- int[] arrtypes;
- if(type == StatEdge.TYPE_EXCEPTION) {
- arrtypes = new int[] {STATEDGE_ALL, StatEdge.TYPE_EXCEPTION};
- } else {
- arrtypes = new int[] {STATEDGE_ALL, STATEDGE_DIRECT_ALL, type};
- }
-
- for(int edgetype : arrtypes) {
- addEdgeDirectInternal(direction, edge, edgetype);
- }
-
- }
-
- private void removeEdgeDirectInternal(int direction, StatEdge edge, int edgetype) {
-
- Map<Integer, List<StatEdge>> mapEdges = direction==DIRECTION_BACKWARD?mapPredEdges:mapSuccEdges;
- Map<Integer, List<Statement>> mapStates = direction==DIRECTION_BACKWARD?mapPredStates:mapSuccStates;
-
- List<StatEdge> lst = mapEdges.get(edgetype);
- if(lst != null) {
- int index = lst.indexOf(edge);
- if(index >= 0) {
- lst.remove(index);
- mapStates.get(edgetype).remove(index);
- }
- }
-
- }
-
- private void removeEdgeInternal(int direction, StatEdge edge) {
-
- int type = edge.getType();
-
- int[] arrtypes;
- if(type == StatEdge.TYPE_EXCEPTION) {
- arrtypes = new int[] {STATEDGE_ALL, StatEdge.TYPE_EXCEPTION};
- } else {
- arrtypes = new int[] {STATEDGE_ALL, STATEDGE_DIRECT_ALL, type};
- }
-
- for(int edgetype : arrtypes) {
- removeEdgeDirectInternal(direction, edge, edgetype);
- }
-
- }
-
- public void addPredecessor(StatEdge edge) {
- addEdgeInternal(DIRECTION_BACKWARD, edge);
- }
-
- public void removePredecessor(StatEdge edge) {
-
- if(edge == null) { // FIXME: redundant?
- return;
- }
-
- removeEdgeInternal(DIRECTION_BACKWARD, edge);
- }
-
- public void addSuccessor(StatEdge edge) {
- addEdgeInternal(DIRECTION_FORWARD, edge);
-
- if(edge.closure != null) {
- edge.closure.getLabelEdges().add(edge);
- }
-
- edge.getDestination().addPredecessor(edge);
- }
-
- public void removeSuccessor(StatEdge edge) {
-
- if(edge == null) {
- return;
- }
-
- removeEdgeInternal(DIRECTION_FORWARD, edge);
-
- if(edge.closure != null) {
- edge.closure.getLabelEdges().remove(edge);
- }
-
- if(edge.getDestination() != null) { // TODO: redundant?
- edge.getDestination().removePredecessor(edge);
- }
- }
-
- // TODO: make obsolete and remove
- public void removeAllSuccessors(Statement stat) {
-
- if(stat == null) {
- return;
- }
-
- for(StatEdge edge : getAllSuccessorEdges()) {
- if(edge.getDestination() == stat) {
- removeSuccessor(edge);
- }
- }
- }
-
- public HashSet<Statement> buildContinueSet() {
- continueSet.clear();
-
- for(Statement st: stats) {
- continueSet.addAll(st.buildContinueSet());
- if(st != first) {
- continueSet.remove(st.getBasichead());
- }
- }
-
- for(StatEdge edge: getEdges(StatEdge.TYPE_CONTINUE, DIRECTION_FORWARD)) {
- continueSet.add(edge.getDestination().getBasichead());
- }
-
- if(type == Statement.TYPE_DO) {
- continueSet.remove(first.getBasichead());
- }
-
- return continueSet;
- }
-
- public void buildMonitorFlags() {
-
- for(Statement st: stats) {
- st.buildMonitorFlags();
- }
-
- switch(type) {
- case TYPE_BASICBLOCK:
- BasicBlockStatement bblock = (BasicBlockStatement)this;
- InstructionSequence seq = bblock.getBlock().getSeq();
-
- if(seq!=null && seq.length()>0) {
- for(int i=0;i<seq.length();i++) {
- if(seq.getInstr(i).opcode == CodeConstants.opc_monitorexit) {
- containsMonitorExit = true;
- break;
- }
- }
- isMonitorEnter = (seq.getLastInstr().opcode == CodeConstants.opc_monitorenter);
- }
- break;
- case TYPE_SEQUENCE:
- case TYPE_IF:
- containsMonitorExit = false;
- for(Statement st: stats) {
- containsMonitorExit |= st.isContainsMonitorExit();
- }
-
- break;
- case TYPE_SYNCRONIZED:
- case TYPE_ROOT:
- case TYPE_GENERAL:
- break;
- default:
- containsMonitorExit = false;
- for(Statement st: stats) {
- containsMonitorExit |= st.isContainsMonitorExit();
- }
- }
- }
-
-
- public List<Statement> getReversePostOrderList() {
- return getReversePostOrderList(first);
- }
-
- public List<Statement> getReversePostOrderList(Statement stat) {
- List<Statement> res = new ArrayList<Statement>();
-
- addToReversePostOrderListIterative(stat, res);
-
- return res;
- }
-
- public List<Statement> getPostReversePostOrderList() {
- return getPostReversePostOrderList(null);
- }
-
- public List<Statement> getPostReversePostOrderList(List<Statement> lstexits) {
-
- List<Statement> res = new ArrayList<Statement>();
-
- if(lstexits == null) {
- StrongConnectivityHelper schelper = new StrongConnectivityHelper(this);
- lstexits = StrongConnectivityHelper.getExitReps(schelper.getComponents());
- }
-
- HashSet<Statement> setVisited = new HashSet<Statement>();
-
- for(Statement exit : lstexits) {
- addToPostReversePostOrderList(exit, res, setVisited);
- }
-
- if(res.size() != stats.size()) {
- DecompilerContext.getLogger().writeMessage("computing post reverse post order failed!", IFernflowerLogger.ERROR);
-
- throw new RuntimeException("parsing failure!");
- }
-
- return res;
- }
-
- public boolean containsStatement(Statement stat) {
- return this == stat || containsStatementStrict(stat);
- }
-
- public boolean containsStatementStrict(Statement stat) {
-
- if(stats.contains(stat)) {
- return true;
- }
-
- for(int i=0;i<stats.size();i++) {
- if(stats.get(i).containsStatementStrict(stat)) {
- return true;
- }
- }
-
- return false;
- }
-
- // to be overwritten
- public String toJava() {
- return toJava(0);
- }
-
- public String toJava(int indent) {
- throw new RuntimeException("not implemented");
- }
-
- // TODO: make obsolete and remove
- public List<Object> getSequentialObjects() {
- return new ArrayList<Object>(stats);
- }
-
- public void initExprents() {
- ; // do nothing
- }
-
- public void replaceExprent(Exprent oldexpr, Exprent newexpr) {
- ; // do nothing
- }
-
- public Statement getSimpleCopy() {
- throw new RuntimeException("not implemented");
- }
-
- public void initSimpleCopy() {
- if(!stats.isEmpty()) {
- first = stats.get(0);
- }
- }
-
- public void replaceStatement(Statement oldstat, Statement newstat) {
-
- for(StatEdge edge : oldstat.getAllPredecessorEdges()) {
- oldstat.removePredecessor(edge);
- edge.getSource().changeEdgeNode(DIRECTION_FORWARD, edge, newstat);
- newstat.addPredecessor(edge);
- }
-
- for(StatEdge edge : oldstat.getAllSuccessorEdges()) {
- oldstat.removeSuccessor(edge);
- edge.setSource(newstat);
- newstat.addSuccessor(edge);
- }
-
- int statindex = stats.getIndexByKey(oldstat.id);
- stats.removeWithKey(oldstat.id);
- stats.addWithKeyAndIndex(statindex, newstat, newstat.id);
-
- newstat.setParent(this);
- newstat.post = oldstat.post;
-
- if(first == oldstat) {
- first = newstat;
- }
-
- List<StatEdge> lst = new ArrayList<StatEdge>(oldstat.getLabelEdges());
-
- for(int i=lst.size()-1;i>=0;i--) {
- StatEdge edge = lst.get(i);
- if(edge.getSource() != newstat) {
- newstat.addLabeledEdge(edge);
- } else {
- if(this == edge.getDestination() || this.containsStatementStrict(edge.getDestination())) {
- edge.closure = null;
- } else {
- this.addLabeledEdge(edge);
- }
- }
- }
-
- oldstat.getLabelEdges().clear();
- }
-
-
- // *****************************************************************************
- // private methods
- // *****************************************************************************
-
- private void addToReversePostOrderListIterative(Statement root, List<Statement> lst) {
-
- LinkedList<Statement> stackNode = new LinkedList<Statement>();
- LinkedList<Integer> stackIndex = new LinkedList<Integer>();
- HashSet<Statement> setVisited = new HashSet<Statement>();
-
- stackNode.add(root);
- stackIndex.add(0);
-
- while(!stackNode.isEmpty()) {
-
- Statement node = stackNode.getLast();
- int index = stackIndex.removeLast();
-
- setVisited.add(node);
-
- List<StatEdge> lstEdges = node.getAllSuccessorEdges();
-
- for(;index<lstEdges.size();index++) {
- StatEdge edge = lstEdges.get(index);
- Statement succ = edge.getDestination();
-
- if(!setVisited.contains(succ) &&
- (edge.getType() == StatEdge.TYPE_REGULAR || edge.getType() == StatEdge.TYPE_EXCEPTION)) { // TODO: edge filter?
-
- stackIndex.add(index+1);
-
- stackNode.add(succ);
- stackIndex.add(0);
-
- break;
- }
- }
-
- if(index == lstEdges.size()) {
- lst.add(0, node);
-
- stackNode.removeLast();
- }
- }
-
- }
-
-
- private void addToPostReversePostOrderList(Statement stat, List<Statement> lst, HashSet<Statement> setVisited) {
-
- if(setVisited.contains(stat)) { // because of not considered exception edges, s. isExitComponent. Should be rewritten, if possible.
- return;
- }
- setVisited.add(stat);
-
- for(StatEdge prededge : stat.getEdges(StatEdge.TYPE_REGULAR | StatEdge.TYPE_EXCEPTION, DIRECTION_BACKWARD)) {
- Statement pred = prededge.getSource();
- if(!setVisited.contains(pred)) {
- addToPostReversePostOrderList(pred, lst, setVisited);
- }
- }
-
- lst.add(0, stat);
- }
-
- // *****************************************************************************
- // getter and setter methods
- // *****************************************************************************
-
- public void changeEdgeNode(int direction, StatEdge edge, Statement value) {
-
- Map<Integer, List<StatEdge>> mapEdges = direction==DIRECTION_BACKWARD?mapPredEdges:mapSuccEdges;
- Map<Integer, List<Statement>> mapStates = direction==DIRECTION_BACKWARD?mapPredStates:mapSuccStates;
-
- int type = edge.getType();
-
- int[] arrtypes;
- if(type == StatEdge.TYPE_EXCEPTION) {
- arrtypes = new int[] {STATEDGE_ALL, StatEdge.TYPE_EXCEPTION};
- } else {
- arrtypes = new int[] {STATEDGE_ALL, STATEDGE_DIRECT_ALL, type};
- }
-
- for(int edgetype : arrtypes) {
- List<StatEdge> lst = mapEdges.get(edgetype);
- if(lst != null) {
- int index = lst.indexOf(edge);
- if(index >= 0) {
- mapStates.get(edgetype).set(index, value);
- }
- }
- }
-
- if(direction == DIRECTION_BACKWARD) {
- edge.setSource(value);
- } else {
- edge.setDestination(value);
- }
-
- }
-
- public void changeEdgeType(int direction, StatEdge edge, int newtype) {
-
- int oldtype = edge.getType();
- if(oldtype == newtype) {
- return;
- }
-
- if(oldtype == StatEdge.TYPE_EXCEPTION || newtype == StatEdge.TYPE_EXCEPTION) {
- throw new RuntimeException("Invalid edge type!");
- }
-
- removeEdgeDirectInternal(direction, edge, oldtype);
- addEdgeDirectInternal(direction, edge, newtype);
-
- if(direction == DIRECTION_FORWARD) {
- edge.getDestination().changeEdgeType(DIRECTION_BACKWARD, edge, newtype);
- }
-
- edge.setType(newtype);
- }
-
-
- private List<StatEdge> getEdges(int type, int direction) {
-
- Map<Integer, List<StatEdge>> map = direction==DIRECTION_BACKWARD?mapPredEdges:mapSuccEdges;
-
- List<StatEdge> res;
- if((type & (type -1)) == 0) {
- res = map.get(type);
- res = res==null?new ArrayList<StatEdge>():new ArrayList<StatEdge>(res);
- } else {
- res = new ArrayList<StatEdge>();
- for(int edgetype : StatEdge.TYPES) {
- if((type & edgetype) != 0) {
- List<StatEdge> lst = map.get(edgetype);
- if(lst != null) {
- res.addAll(lst);
- }
- }
- }
- }
-
- return res;
- }
-
- public List<Statement> getNeighbours(int type, int direction) {
-
- Map<Integer, List<Statement>> map = direction==DIRECTION_BACKWARD?mapPredStates:mapSuccStates;
-
- List<Statement> res;
- if((type & (type -1)) == 0) {
- res = map.get(type);
- res = res==null?new ArrayList<Statement>():new ArrayList<Statement>(res);
- } else {
- res = new ArrayList<Statement>();
- for(int edgetype : StatEdge.TYPES) {
- if((type & edgetype) != 0) {
- List<Statement> lst = map.get(edgetype);
- if(lst != null) {
- res.addAll(lst);
- }
- }
- }
- }
-
- return res;
- }
-
- public Set<Statement> getNeighboursSet(int type, int direction) {
- return new HashSet<Statement>(getNeighbours(type, direction));
- }
-
- public List<StatEdge> getSuccessorEdges(int type) {
- return getEdges(type, DIRECTION_FORWARD);
- }
-
- public List<StatEdge> getPredecessorEdges(int type) {
- return getEdges(type, DIRECTION_BACKWARD);
- }
-
- public List<StatEdge> getAllSuccessorEdges() {
- return getEdges(STATEDGE_ALL, DIRECTION_FORWARD);
- }
-
- public List<StatEdge> getAllPredecessorEdges() {
- return getEdges(STATEDGE_ALL, DIRECTION_BACKWARD);
- }
-
- public Statement getFirst() {
- return first;
- }
-
- public void setFirst(Statement first) {
- this.first = first;
- }
-
- public Statement getPost() {
- return post;
- }
-
- public void setPost(Statement post) {
- this.post = post;
- }
-
- public VBStyleCollection<Statement, Integer> getStats() {
- return stats;
- }
-
- public int getLastBasicType() {
- return lastBasicType;
- }
-
- public HashSet<Statement> getContinueSet() {
- return continueSet;
- }
-
- public boolean isContainsMonitorExit() {
- return containsMonitorExit;
- }
-
- public boolean isMonitorEnter() {
- return isMonitorEnter;
- }
-
- public BasicBlockStatement getBasichead() {
- if(type == Statement.TYPE_BASICBLOCK) {
- return (BasicBlockStatement)this;
- } else {
- return first.getBasichead();
- }
- }
-
- public boolean isLabeled() {
-
- for(StatEdge edge: labelEdges) {
- if(edge.labeled && edge.explicit) { // FIXME: consistent setting
- return true;
- }
- }
- return false;
- }
-
- public boolean hasBasicSuccEdge() {
- boolean res = type == Statement.TYPE_BASICBLOCK || (type == Statement.TYPE_IF &&
- ((IfStatement)this).iftype == IfStatement.IFTYPE_IF) ||
- (type == Statement.TYPE_DO && ((DoStatement)this).getLooptype() != DoStatement.LOOP_DO);
-
- // FIXME: default switch
-
- return res;
- }
-
-
- public Statement getParent() {
- return parent;
- }
-
- public void setParent(Statement parent) {
- this.parent = parent;
- }
-
- public HashSet<StatEdge> getLabelEdges() { // FIXME: why HashSet?
- return labelEdges;
- }
-
- public List<Exprent> getVarDefinitions() {
- return varDefinitions;
- }
-
- public List<Exprent> getExprents() {
- return exprents;
- }
-
- public void setExprents(List<Exprent> exprents) {
- this.exprents = exprents;
- }
-
- public boolean isCopied() {
- return copied;
- }
-
- public void setCopied(boolean copied) {
- this.copied = copied;
- }
-
- // helper methods
- public String toString() {
- return id.toString();
- }
+
+ public static final int STATEDGE_ALL = 1 << 31;
+ public static final int STATEDGE_DIRECT_ALL = 1 << 30;
+
+ public static final int DIRECTION_BACKWARD = 0;
+ public static final int DIRECTION_FORWARD = 1;
+
+ public static final int TYPE_GENERAL = 0;
+ public static final int TYPE_IF = 2;
+ public static final int TYPE_DO = 5;
+ public static final int TYPE_SWITCH = 6;
+ public static final int TYPE_TRYCATCH = 7;
+ public static final int TYPE_BASICBLOCK = 8;
+ public static final int TYPE_FINALLY = 9;
+ public static final int TYPE_SYNCRONIZED = 10;
+ public static final int TYPE_PLACEHOLDER = 11;
+ public static final int TYPE_CATCHALL = 12;
+ public static final int TYPE_ROOT = 13;
+ public static final int TYPE_DUMMYEXIT = 14;
+ public static final int TYPE_SEQUENCE = 15;
+
+
+ public static final int LASTBASICTYPE_IF = 0;
+ public static final int LASTBASICTYPE_SWITCH = 1;
+ public static final int LASTBASICTYPE_GENERAL = 2;
+
+
+ // *****************************************************************************
+ // public fields
+ // *****************************************************************************
+
+ public int type;
+
+ public Integer id;
+
+ // *****************************************************************************
+ // private fields
+ // *****************************************************************************
+
+ private Map<Integer, List<StatEdge>> mapSuccEdges = new HashMap<Integer, List<StatEdge>>();
+ private Map<Integer, List<StatEdge>> mapPredEdges = new HashMap<Integer, List<StatEdge>>();
+
+ private Map<Integer, List<Statement>> mapSuccStates = new HashMap<Integer, List<Statement>>();
+ private Map<Integer, List<Statement>> mapPredStates = new HashMap<Integer, List<Statement>>();
+
+ // statement as graph
+ protected VBStyleCollection<Statement, Integer> stats = new VBStyleCollection<Statement, Integer>();
+
+ protected Statement parent;
+
+ protected Statement first;
+
+ protected List<Exprent> exprents;
+
+ protected HashSet<StatEdge> labelEdges = new HashSet<StatEdge>();
+
+ protected List<Exprent> varDefinitions = new ArrayList<Exprent>();
+
+ // copied statement, s. deobfuscating of irreducible CFGs
+ private boolean copied = false;
+
+ // relevant for the first stage of processing only
+ // set to null after initializing of the statement structure
+
+ protected Statement post;
+
+ protected int lastBasicType = LASTBASICTYPE_GENERAL;
+
+ protected boolean isMonitorEnter;
+
+ protected boolean containsMonitorExit;
+
+ protected HashSet<Statement> continueSet = new HashSet<Statement>();
+
+ // *****************************************************************************
+ // initializers
+ // *****************************************************************************
+
+ {
+ // set statement id
+ id = DecompilerContext.getCountercontainer().getCounterAndIncrement(CounterContainer.STATEMENT_COUNTER);
+ }
+
+ // *****************************************************************************
+ // public methods
+ // *****************************************************************************
+
+ public void clearTempInformation() {
+
+ post = null;
+ continueSet = null;
+
+ copied = false;
+ // FIXME: used in FlattenStatementsHelper.flattenStatement()! check and remove
+ //lastBasicType = LASTBASICTYPE_GENERAL;
+ isMonitorEnter = false;
+ ;
+ containsMonitorExit = false;
+
+ for (Map<Integer, List<StatEdge>> map : new Map[]{mapSuccEdges, mapPredEdges}) {
+ map.remove(StatEdge.TYPE_EXCEPTION);
+
+ List<StatEdge> lst = map.get(STATEDGE_DIRECT_ALL);
+ if (lst != null) {
+ map.put(STATEDGE_ALL, new ArrayList<StatEdge>(lst));
+ }
+ else {
+ map.remove(STATEDGE_ALL);
+ }
+ }
+
+ for (Map<Integer, List<Statement>> map : new Map[]{mapSuccStates, mapPredStates}) {
+ map.remove(StatEdge.TYPE_EXCEPTION);
+
+ List<Statement> lst = map.get(STATEDGE_DIRECT_ALL);
+ if (lst != null) {
+ map.put(STATEDGE_ALL, new ArrayList<Statement>(lst));
+ }
+ else {
+ map.remove(STATEDGE_ALL);
+ }
+ }
+ }
+
+ public void collapseNodesToStatement(Statement stat) {
+
+ Statement head = stat.getFirst();
+ Statement post = stat.getPost();
+
+ VBStyleCollection<Statement, Integer> setNodes = stat.getStats();
+
+ // post edges
+ if (post != null) {
+ for (StatEdge edge : post.getEdges(STATEDGE_DIRECT_ALL, DIRECTION_BACKWARD)) {
+ if (stat.containsStatementStrict(edge.getSource())) {
+ edge.getSource().changeEdgeType(DIRECTION_FORWARD, edge, StatEdge.TYPE_BREAK);
+ stat.addLabeledEdge(edge);
+ }
+ }
+ }
+
+ // regular head edges
+ for (StatEdge prededge : head.getAllPredecessorEdges()) {
+
+ if (prededge.getType() != StatEdge.TYPE_EXCEPTION &&
+ stat.containsStatementStrict(prededge.getSource())) {
+ prededge.getSource().changeEdgeType(DIRECTION_FORWARD, prededge, StatEdge.TYPE_CONTINUE);
+ stat.addLabeledEdge(prededge);
+ }
+
+ head.removePredecessor(prededge);
+ prededge.getSource().changeEdgeNode(DIRECTION_FORWARD, prededge, stat);
+ stat.addPredecessor(prededge);
+ }
+
+ if (setNodes.containsKey(first.id)) {
+ first = stat;
+ }
+
+ // exception edges
+ Set<Statement> setHandlers = new HashSet<Statement>(head.getNeighbours(StatEdge.TYPE_EXCEPTION, DIRECTION_FORWARD));
+ for (Statement node : setNodes) {
+ setHandlers.retainAll(node.getNeighbours(StatEdge.TYPE_EXCEPTION, DIRECTION_FORWARD));
+ }
+
+ if (!setHandlers.isEmpty()) {
+
+ for (StatEdge edge : head.getEdges(StatEdge.TYPE_EXCEPTION, DIRECTION_FORWARD)) {
+ Statement handler = edge.getDestination();
+
+ if (setHandlers.contains(handler)) {
+ if (!setNodes.containsKey(handler.id)) {
+ stat.addSuccessor(new StatEdge(stat, handler, edge.getExceptions()));
+ }
+ }
+ }
+
+ for (Statement node : setNodes) {
+ for (StatEdge edge : node.getEdges(StatEdge.TYPE_EXCEPTION, DIRECTION_FORWARD)) {
+ if (setHandlers.contains(edge.getDestination())) {
+ node.removeSuccessor(edge);
+ }
+ }
+ }
+ }
+
+ if (post != null &&
+ !stat.getNeighbours(StatEdge.TYPE_EXCEPTION, DIRECTION_FORWARD).contains(post)) { // TODO: second condition redundant?
+ stat.addSuccessor(new StatEdge(StatEdge.TYPE_REGULAR, stat, post));
+ }
+
+
+ // adjust statement collection
+ for (Statement st : setNodes) {
+ stats.removeWithKey(st.id);
+ }
+
+ stats.addWithKey(stat, stat.id);
+
+ stat.setAllParent();
+ stat.setParent(this);
+
+ stat.buildContinueSet();
+ // monitorenter and monitorexit
+ stat.buildMonitorFlags();
+
+ if (stat.type == Statement.TYPE_SWITCH) {
+ // special case switch, sorting leaf nodes
+ ((SwitchStatement)stat).sortEdgesAndNodes();
+ }
+ }
+
+ public void setAllParent() {
+ for (Statement st : stats) {
+ st.setParent(this);
+ }
+ }
+
+ public void addLabeledEdge(StatEdge edge) {
+
+ if (edge.closure != null) {
+ edge.closure.getLabelEdges().remove(edge);
+ }
+ edge.closure = this;
+ this.getLabelEdges().add(edge);
+ }
+
+ private void addEdgeDirectInternal(int direction, StatEdge edge, int edgetype) {
+
+ Map<Integer, List<StatEdge>> mapEdges = direction == DIRECTION_BACKWARD ? mapPredEdges : mapSuccEdges;
+ Map<Integer, List<Statement>> mapStates = direction == DIRECTION_BACKWARD ? mapPredStates : mapSuccStates;
+
+ List<StatEdge> lst = mapEdges.get(edgetype);
+ if (lst == null) {
+ mapEdges.put(edgetype, lst = new ArrayList<StatEdge>());
+ }
+ lst.add(edge);
+
+ List<Statement> lstStates = mapStates.get(edgetype);
+ if (lstStates == null) {
+ mapStates.put(edgetype, lstStates = new ArrayList<Statement>());
+ }
+ lstStates.add(direction == DIRECTION_BACKWARD ? edge.getSource() : edge.getDestination());
+ }
+
+ private void addEdgeInternal(int direction, StatEdge edge) {
+
+ int type = edge.getType();
+
+ int[] arrtypes;
+ if (type == StatEdge.TYPE_EXCEPTION) {
+ arrtypes = new int[]{STATEDGE_ALL, StatEdge.TYPE_EXCEPTION};
+ }
+ else {
+ arrtypes = new int[]{STATEDGE_ALL, STATEDGE_DIRECT_ALL, type};
+ }
+
+ for (int edgetype : arrtypes) {
+ addEdgeDirectInternal(direction, edge, edgetype);
+ }
+ }
+
+ private void removeEdgeDirectInternal(int direction, StatEdge edge, int edgetype) {
+
+ Map<Integer, List<StatEdge>> mapEdges = direction == DIRECTION_BACKWARD ? mapPredEdges : mapSuccEdges;
+ Map<Integer, List<Statement>> mapStates = direction == DIRECTION_BACKWARD ? mapPredStates : mapSuccStates;
+
+ List<StatEdge> lst = mapEdges.get(edgetype);
+ if (lst != null) {
+ int index = lst.indexOf(edge);
+ if (index >= 0) {
+ lst.remove(index);
+ mapStates.get(edgetype).remove(index);
+ }
+ }
+ }
+
+ private void removeEdgeInternal(int direction, StatEdge edge) {
+
+ int type = edge.getType();
+
+ int[] arrtypes;
+ if (type == StatEdge.TYPE_EXCEPTION) {
+ arrtypes = new int[]{STATEDGE_ALL, StatEdge.TYPE_EXCEPTION};
+ }
+ else {
+ arrtypes = new int[]{STATEDGE_ALL, STATEDGE_DIRECT_ALL, type};
+ }
+
+ for (int edgetype : arrtypes) {
+ removeEdgeDirectInternal(direction, edge, edgetype);
+ }
+ }
+
+ public void addPredecessor(StatEdge edge) {
+ addEdgeInternal(DIRECTION_BACKWARD, edge);
+ }
+
+ public void removePredecessor(StatEdge edge) {
+
+ if (edge == null) { // FIXME: redundant?
+ return;
+ }
+
+ removeEdgeInternal(DIRECTION_BACKWARD, edge);
+ }
+
+ public void addSuccessor(StatEdge edge) {
+ addEdgeInternal(DIRECTION_FORWARD, edge);
+
+ if (edge.closure != null) {
+ edge.closure.getLabelEdges().add(edge);
+ }
+
+ edge.getDestination().addPredecessor(edge);
+ }
+
+ public void removeSuccessor(StatEdge edge) {
+
+ if (edge == null) {
+ return;
+ }
+
+ removeEdgeInternal(DIRECTION_FORWARD, edge);
+
+ if (edge.closure != null) {
+ edge.closure.getLabelEdges().remove(edge);
+ }
+
+ if (edge.getDestination() != null) { // TODO: redundant?
+ edge.getDestination().removePredecessor(edge);
+ }
+ }
+
+ // TODO: make obsolete and remove
+ public void removeAllSuccessors(Statement stat) {
+
+ if (stat == null) {
+ return;
+ }
+
+ for (StatEdge edge : getAllSuccessorEdges()) {
+ if (edge.getDestination() == stat) {
+ removeSuccessor(edge);
+ }
+ }
+ }
+
+ public HashSet<Statement> buildContinueSet() {
+ continueSet.clear();
+
+ for (Statement st : stats) {
+ continueSet.addAll(st.buildContinueSet());
+ if (st != first) {
+ continueSet.remove(st.getBasichead());
+ }
+ }
+
+ for (StatEdge edge : getEdges(StatEdge.TYPE_CONTINUE, DIRECTION_FORWARD)) {
+ continueSet.add(edge.getDestination().getBasichead());
+ }
+
+ if (type == Statement.TYPE_DO) {
+ continueSet.remove(first.getBasichead());
+ }
+
+ return continueSet;
+ }
+
+ public void buildMonitorFlags() {
+
+ for (Statement st : stats) {
+ st.buildMonitorFlags();
+ }
+
+ switch (type) {
+ case TYPE_BASICBLOCK:
+ BasicBlockStatement bblock = (BasicBlockStatement)this;
+ InstructionSequence seq = bblock.getBlock().getSeq();
+
+ if (seq != null && seq.length() > 0) {
+ for (int i = 0; i < seq.length(); i++) {
+ if (seq.getInstr(i).opcode == CodeConstants.opc_monitorexit) {
+ containsMonitorExit = true;
+ break;
+ }
+ }
+ isMonitorEnter = (seq.getLastInstr().opcode == CodeConstants.opc_monitorenter);
+ }
+ break;
+ case TYPE_SEQUENCE:
+ case TYPE_IF:
+ containsMonitorExit = false;
+ for (Statement st : stats) {
+ containsMonitorExit |= st.isContainsMonitorExit();
+ }
+
+ break;
+ case TYPE_SYNCRONIZED:
+ case TYPE_ROOT:
+ case TYPE_GENERAL:
+ break;
+ default:
+ containsMonitorExit = false;
+ for (Statement st : stats) {
+ containsMonitorExit |= st.isContainsMonitorExit();
+ }
+ }
+ }
+
+
+ public List<Statement> getReversePostOrderList() {
+ return getReversePostOrderList(first);
+ }
+
+ public List<Statement> getReversePostOrderList(Statement stat) {
+ List<Statement> res = new ArrayList<Statement>();
+
+ addToReversePostOrderListIterative(stat, res);
+
+ return res;
+ }
+
+ public List<Statement> getPostReversePostOrderList() {
+ return getPostReversePostOrderList(null);
+ }
+
+ public List<Statement> getPostReversePostOrderList(List<Statement> lstexits) {
+
+ List<Statement> res = new ArrayList<Statement>();
+
+ if (lstexits == null) {
+ StrongConnectivityHelper schelper = new StrongConnectivityHelper(this);
+ lstexits = StrongConnectivityHelper.getExitReps(schelper.getComponents());
+ }
+
+ HashSet<Statement> setVisited = new HashSet<Statement>();
+
+ for (Statement exit : lstexits) {
+ addToPostReversePostOrderList(exit, res, setVisited);
+ }
+
+ if (res.size() != stats.size()) {
+ DecompilerContext.getLogger().writeMessage("computing post reverse post order failed!", IFernflowerLogger.ERROR);
+
+ throw new RuntimeException("parsing failure!");
+ }
+
+ return res;
+ }
+
+ public boolean containsStatement(Statement stat) {
+ return this == stat || containsStatementStrict(stat);
+ }
+
+ public boolean containsStatementStrict(Statement stat) {
+
+ if (stats.contains(stat)) {
+ return true;
+ }
+
+ for (int i = 0; i < stats.size(); i++) {
+ if (stats.get(i).containsStatementStrict(stat)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ // to be overwritten
+ public String toJava() {
+ return toJava(0);
+ }
+
+ public String toJava(int indent) {
+ throw new RuntimeException("not implemented");
+ }
+
+ // TODO: make obsolete and remove
+ public List<Object> getSequentialObjects() {
+ return new ArrayList<Object>(stats);
+ }
+
+ public void initExprents() {
+ ; // do nothing
+ }
+
+ public void replaceExprent(Exprent oldexpr, Exprent newexpr) {
+ ; // do nothing
+ }
+
+ public Statement getSimpleCopy() {
+ throw new RuntimeException("not implemented");
+ }
+
+ public void initSimpleCopy() {
+ if (!stats.isEmpty()) {
+ first = stats.get(0);
+ }
+ }
+
+ public void replaceStatement(Statement oldstat, Statement newstat) {
+
+ for (StatEdge edge : oldstat.getAllPredecessorEdges()) {
+ oldstat.removePredecessor(edge);
+ edge.getSource().changeEdgeNode(DIRECTION_FORWARD, edge, newstat);
+ newstat.addPredecessor(edge);
+ }
+
+ for (StatEdge edge : oldstat.getAllSuccessorEdges()) {
+ oldstat.removeSuccessor(edge);
+ edge.setSource(newstat);
+ newstat.addSuccessor(edge);
+ }
+
+ int statindex = stats.getIndexByKey(oldstat.id);
+ stats.removeWithKey(oldstat.id);
+ stats.addWithKeyAndIndex(statindex, newstat, newstat.id);
+
+ newstat.setParent(this);
+ newstat.post = oldstat.post;
+
+ if (first == oldstat) {
+ first = newstat;
+ }
+
+ List<StatEdge> lst = new ArrayList<StatEdge>(oldstat.getLabelEdges());
+
+ for (int i = lst.size() - 1; i >= 0; i--) {
+ StatEdge edge = lst.get(i);
+ if (edge.getSource() != newstat) {
+ newstat.addLabeledEdge(edge);
+ }
+ else {
+ if (this == edge.getDestination() || this.containsStatementStrict(edge.getDestination())) {
+ edge.closure = null;
+ }
+ else {
+ this.addLabeledEdge(edge);
+ }
+ }
+ }
+
+ oldstat.getLabelEdges().clear();
+ }
+
+
+ // *****************************************************************************
+ // private methods
+ // *****************************************************************************
+
+ private void addToReversePostOrderListIterative(Statement root, List<Statement> lst) {
+
+ LinkedList<Statement> stackNode = new LinkedList<Statement>();
+ LinkedList<Integer> stackIndex = new LinkedList<Integer>();
+ HashSet<Statement> setVisited = new HashSet<Statement>();
+
+ stackNode.add(root);
+ stackIndex.add(0);
+
+ while (!stackNode.isEmpty()) {
+
+ Statement node = stackNode.getLast();
+ int index = stackIndex.removeLast();
+
+ setVisited.add(node);
+
+ List<StatEdge> lstEdges = node.getAllSuccessorEdges();
+
+ for (; index < lstEdges.size(); index++) {
+ StatEdge edge = lstEdges.get(index);
+ Statement succ = edge.getDestination();
+
+ if (!setVisited.contains(succ) &&
+ (edge.getType() == StatEdge.TYPE_REGULAR || edge.getType() == StatEdge.TYPE_EXCEPTION)) { // TODO: edge filter?
+
+ stackIndex.add(index + 1);
+
+ stackNode.add(succ);
+ stackIndex.add(0);
+
+ break;
+ }
+ }
+
+ if (index == lstEdges.size()) {
+ lst.add(0, node);
+
+ stackNode.removeLast();
+ }
+ }
+ }
+
+
+ private void addToPostReversePostOrderList(Statement stat, List<Statement> lst, HashSet<Statement> setVisited) {
+
+ if (setVisited.contains(stat)) { // because of not considered exception edges, s. isExitComponent. Should be rewritten, if possible.
+ return;
+ }
+ setVisited.add(stat);
+
+ for (StatEdge prededge : stat.getEdges(StatEdge.TYPE_REGULAR | StatEdge.TYPE_EXCEPTION, DIRECTION_BACKWARD)) {
+ Statement pred = prededge.getSource();
+ if (!setVisited.contains(pred)) {
+ addToPostReversePostOrderList(pred, lst, setVisited);
+ }
+ }
+
+ lst.add(0, stat);
+ }
+
+ // *****************************************************************************
+ // getter and setter methods
+ // *****************************************************************************
+
+ public void changeEdgeNode(int direction, StatEdge edge, Statement value) {
+
+ Map<Integer, List<StatEdge>> mapEdges = direction == DIRECTION_BACKWARD ? mapPredEdges : mapSuccEdges;
+ Map<Integer, List<Statement>> mapStates = direction == DIRECTION_BACKWARD ? mapPredStates : mapSuccStates;
+
+ int type = edge.getType();
+
+ int[] arrtypes;
+ if (type == StatEdge.TYPE_EXCEPTION) {
+ arrtypes = new int[]{STATEDGE_ALL, StatEdge.TYPE_EXCEPTION};
+ }
+ else {
+ arrtypes = new int[]{STATEDGE_ALL, STATEDGE_DIRECT_ALL, type};
+ }
+
+ for (int edgetype : arrtypes) {
+ List<StatEdge> lst = mapEdges.get(edgetype);
+ if (lst != null) {
+ int index = lst.indexOf(edge);
+ if (index >= 0) {
+ mapStates.get(edgetype).set(index, value);
+ }
+ }
+ }
+
+ if (direction == DIRECTION_BACKWARD) {
+ edge.setSource(value);
+ }
+ else {
+ edge.setDestination(value);
+ }
+ }
+
+ public void changeEdgeType(int direction, StatEdge edge, int newtype) {
+
+ int oldtype = edge.getType();
+ if (oldtype == newtype) {
+ return;
+ }
+
+ if (oldtype == StatEdge.TYPE_EXCEPTION || newtype == StatEdge.TYPE_EXCEPTION) {
+ throw new RuntimeException("Invalid edge type!");
+ }
+
+ removeEdgeDirectInternal(direction, edge, oldtype);
+ addEdgeDirectInternal(direction, edge, newtype);
+
+ if (direction == DIRECTION_FORWARD) {
+ edge.getDestination().changeEdgeType(DIRECTION_BACKWARD, edge, newtype);
+ }
+
+ edge.setType(newtype);
+ }
+
+
+ private List<StatEdge> getEdges(int type, int direction) {
+
+ Map<Integer, List<StatEdge>> map = direction == DIRECTION_BACKWARD ? mapPredEdges : mapSuccEdges;
+
+ List<StatEdge> res;
+ if ((type & (type - 1)) == 0) {
+ res = map.get(type);
+ res = res == null ? new ArrayList<StatEdge>() : new ArrayList<StatEdge>(res);
+ }
+ else {
+ res = new ArrayList<StatEdge>();
+ for (int edgetype : StatEdge.TYPES) {
+ if ((type & edgetype) != 0) {
+ List<StatEdge> lst = map.get(edgetype);
+ if (lst != null) {
+ res.addAll(lst);
+ }
+ }
+ }
+ }
+
+ return res;
+ }
+
+ public List<Statement> getNeighbours(int type, int direction) {
+
+ Map<Integer, List<Statement>> map = direction == DIRECTION_BACKWARD ? mapPredStates : mapSuccStates;
+
+ List<Statement> res;
+ if ((type & (type - 1)) == 0) {
+ res = map.get(type);
+ res = res == null ? new ArrayList<Statement>() : new ArrayList<Statement>(res);
+ }
+ else {
+ res = new ArrayList<Statement>();
+ for (int edgetype : StatEdge.TYPES) {
+ if ((type & edgetype) != 0) {
+ List<Statement> lst = map.get(edgetype);
+ if (lst != null) {
+ res.addAll(lst);
+ }
+ }
+ }
+ }
+
+ return res;
+ }
+
+ public Set<Statement> getNeighboursSet(int type, int direction) {
+ return new HashSet<Statement>(getNeighbours(type, direction));
+ }
+
+ public List<StatEdge> getSuccessorEdges(int type) {
+ return getEdges(type, DIRECTION_FORWARD);
+ }
+
+ public List<StatEdge> getPredecessorEdges(int type) {
+ return getEdges(type, DIRECTION_BACKWARD);
+ }
+
+ public List<StatEdge> getAllSuccessorEdges() {
+ return getEdges(STATEDGE_ALL, DIRECTION_FORWARD);
+ }
+
+ public List<StatEdge> getAllPredecessorEdges() {
+ return getEdges(STATEDGE_ALL, DIRECTION_BACKWARD);
+ }
+
+ public Statement getFirst() {
+ return first;
+ }
+
+ public void setFirst(Statement first) {
+ this.first = first;
+ }
+
+ public Statement getPost() {
+ return post;
+ }
+
+ public void setPost(Statement post) {
+ this.post = post;
+ }
+
+ public VBStyleCollection<Statement, Integer> getStats() {
+ return stats;
+ }
+
+ public int getLastBasicType() {
+ return lastBasicType;
+ }
+
+ public HashSet<Statement> getContinueSet() {
+ return continueSet;
+ }
+
+ public boolean isContainsMonitorExit() {
+ return containsMonitorExit;
+ }
+
+ public boolean isMonitorEnter() {
+ return isMonitorEnter;
+ }
+
+ public BasicBlockStatement getBasichead() {
+ if (type == Statement.TYPE_BASICBLOCK) {
+ return (BasicBlockStatement)this;
+ }
+ else {
+ return first.getBasichead();
+ }
+ }
+
+ public boolean isLabeled() {
+
+ for (StatEdge edge : labelEdges) {
+ if (edge.labeled && edge.explicit) { // FIXME: consistent setting
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean hasBasicSuccEdge() {
+ boolean res = type == Statement.TYPE_BASICBLOCK || (type == Statement.TYPE_IF &&
+ ((IfStatement)this).iftype == IfStatement.IFTYPE_IF) ||
+ (type == Statement.TYPE_DO && ((DoStatement)this).getLooptype() != DoStatement.LOOP_DO);
+
+ // FIXME: default switch
+
+ return res;
+ }
+
+
+ public Statement getParent() {
+ return parent;
+ }
+
+ public void setParent(Statement parent) {
+ this.parent = parent;
+ }
+
+ public HashSet<StatEdge> getLabelEdges() { // FIXME: why HashSet?
+ return labelEdges;
+ }
+
+ public List<Exprent> getVarDefinitions() {
+ return varDefinitions;
+ }
+
+ public List<Exprent> getExprents() {
+ return exprents;
+ }
+
+ public void setExprents(List<Exprent> exprents) {
+ this.exprents = exprents;
+ }
+
+ public boolean isCopied() {
+ return copied;
+ }
+
+ public void setCopied(boolean copied) {
+ this.copied = copied;
+ }
+
+ // helper methods
+ public String toString() {
+ return id.toString();
+ }
}
diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SwitchStatement.java b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SwitchStatement.java
index ec03886..379d00d 100644
--- a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SwitchStatement.java
+++ b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SwitchStatement.java
@@ -1,26 +1,20 @@
/*
- * Fernflower - The Analytical Java Decompiler
- * http://www.reversed-java.com
+ * Copyright 2000-2014 JetBrains s.r.o.
*
- * (C) 2008 - 2010, Stiver
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * This software is NEITHER public domain NOR free software
- * as per GNU License. See license.txt for more details.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * This software is distributed WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
-
package org.jetbrains.java.decompiler.modules.decompiler.stats;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
import org.jetbrains.java.decompiler.code.SwitchInstruction;
import org.jetbrains.java.decompiler.code.cfg.BasicBlock;
import org.jetbrains.java.decompiler.main.DecompilerContext;
@@ -34,337 +28,340 @@ import org.jetbrains.java.decompiler.modules.decompiler.exps.SwitchExprent;
import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
+import java.util.*;
+
public class SwitchStatement extends Statement {
- // *****************************************************************************
- // private fields
- // *****************************************************************************
-
- private List<Statement> caseStatements = new ArrayList<Statement>();
-
- private List<List<StatEdge>> caseEdges = new ArrayList<List<StatEdge>>();
-
- private List<List<ConstExprent>> caseValues = new ArrayList<List<ConstExprent>>();
-
- private StatEdge default_edge;
-
- private List<Exprent> headexprent = new ArrayList<Exprent>();
-
- // *****************************************************************************
- // constructors
- // *****************************************************************************
-
- private SwitchStatement() {
- type = TYPE_SWITCH;
-
- headexprent.add(null);
- }
-
- private SwitchStatement(Statement head, Statement poststat) {
-
- this();
-
- first = head;
- stats.addWithKey(head, head.id);
-
- // find post node
- Set<Statement> lstNodes = new HashSet<Statement>(head.getNeighbours(StatEdge.TYPE_REGULAR, DIRECTION_FORWARD));
-
- // cluster nodes
- if(poststat != null) {
- post = poststat;
- lstNodes.remove(post);
- }
-
- default_edge = head.getSuccessorEdges(Statement.STATEDGE_DIRECT_ALL).get(0);
-
- for(Statement st: lstNodes) {
- stats.addWithKey(st, st.id);
- }
-
- }
-
- // *****************************************************************************
- // public methods
- // *****************************************************************************
-
- public static Statement isHead(Statement head) {
-
- if(head.type == Statement.TYPE_BASICBLOCK && head.getLastBasicType() == Statement.LASTBASICTYPE_SWITCH) {
-
- List<Statement> lst = new ArrayList<Statement>();
- if(DecHelper.isChoiceStatement(head, lst)) {
- Statement post = lst.remove(0);
-
- for(Statement st : lst) {
- if(st.isMonitorEnter()) {
- return null;
- }
- }
-
- if(DecHelper.checkStatementExceptions(lst)) {
- return new SwitchStatement(head, post);
- }
- }
- }
-
- return null;
- }
-
- public String toJava(int indent) {
-
- String indstr = InterpreterUtil.getIndentString(indent);
-
- String new_line_separator = DecompilerContext.getNewLineSeparator();
-
- StringBuilder buf = new StringBuilder();
- 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);
-
- VarType switch_type = headexprent.get(0).getExprType();
-
- for(int i=0;i<caseStatements.size();i++) {
-
- Statement stat = caseStatements.get(i);
- List<StatEdge> edges = caseEdges.get(i);
- List<ConstExprent> values = caseValues.get(i);
-
- for(int j=0;j<edges.size();j++) {
- if(edges.get(j) == default_edge) {
- buf.append(indstr+"default:" + new_line_separator);
- } else {
- ConstExprent value = (ConstExprent)values.get(j).copy();
- value.setConsttype(switch_type);
-
- buf.append(indstr+"case "+ value.toJava(indent)+":" + new_line_separator);
- }
- }
-
- buf.append(ExprProcessor.jmpWrapper(stat, indent+1, false));
- }
-
- buf.append(indstr+"}" + new_line_separator);
-
- return buf.toString();
- }
-
- public void initExprents() {
- SwitchExprent swexpr = (SwitchExprent)first.getExprents().remove(first.getExprents().size()-1);
- swexpr.setCaseValues(caseValues);
-
- headexprent.set(0, swexpr);
- }
-
- 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) {
-
- for(int i=0;i<caseStatements.size();i++) {
- if(caseStatements.get(i) == oldstat) {
- caseStatements.set(i, newstat);
- }
- }
-
- super.replaceStatement(oldstat, newstat);
- }
-
- public Statement getSimpleCopy() {
- return new SwitchStatement();
- }
-
- public void initSimpleCopy() {
- first = stats.get(0);
- default_edge = first.getSuccessorEdges(Statement.STATEDGE_DIRECT_ALL).get(0);
-
- sortEdgesAndNodes();
- }
-
- // *****************************************************************************
- // private methods
- // *****************************************************************************
-
- public void sortEdgesAndNodes() {
-
- HashMap<StatEdge, Integer> mapEdgeIndex = new HashMap<StatEdge, Integer>();
-
- List<StatEdge> lstFirstSuccs = first.getSuccessorEdges(STATEDGE_DIRECT_ALL);
- for(int i=0;i<lstFirstSuccs.size();i++) {
- mapEdgeIndex.put(lstFirstSuccs.get(i), i==0?lstFirstSuccs.size():i);
- }
-
- // case values
- BasicBlockStatement bbstat = (BasicBlockStatement)first;
- int[] values = ((SwitchInstruction)bbstat.getBlock().getLastInstruction()).getValues();
-
- List<Statement> nodes = new ArrayList<Statement>();
- List<List<Integer>> edges = new ArrayList<List<Integer>>();
-
- // collect regular edges
- for(int i=1;i<stats.size();i++) {
-
- Statement stat = stats.get(i);
-
- List<Integer> lst = new ArrayList<Integer>();
- for(StatEdge edge: stat.getPredecessorEdges(StatEdge.TYPE_REGULAR)) {
- if(edge.getSource() == first) {
- lst.add(mapEdgeIndex.get(edge));
- }
- }
- Collections.sort(lst);
-
- nodes.add(stat);
- edges.add(lst);
- }
-
- // collect exit edges
- List<StatEdge> lstExitEdges = first.getSuccessorEdges(StatEdge.TYPE_BREAK | StatEdge.TYPE_CONTINUE);
- while(!lstExitEdges.isEmpty()) {
- StatEdge edge = lstExitEdges.get(0);
-
- List<Integer> lst = new ArrayList<Integer>();
- for(int i=lstExitEdges.size()-1;i>=0;i--) {
- StatEdge edgeTemp = lstExitEdges.get(i);
- if(edgeTemp.getDestination() == edge.getDestination() && edgeTemp.getType() == edge.getType()) {
- lst.add(mapEdgeIndex.get(edgeTemp));
- lstExitEdges.remove(i);
- }
- }
- Collections.sort(lst);
-
- nodes.add(null);
- edges.add(lst);
- }
-
- // sort edges (bubblesort)
- for(int i=0;i<edges.size()-1;i++) {
- for(int j=edges.size()-1;j>i;j--) {
- if(edges.get(j-1).get(0) > edges.get(j).get(0)) {
- edges.set(j, edges.set(j-1, edges.get(j)));
- nodes.set(j, nodes.set(j-1, nodes.get(j)));
- }
- }
- }
-
- // sort statement cliques
- for(int index = 0; index < nodes.size(); index++) {
- Statement stat = nodes.get(index);
-
- if(stat != null) {
- HashSet<Statement> setPreds = new HashSet<Statement>(stat.getNeighbours(StatEdge.TYPE_REGULAR, DIRECTION_BACKWARD));
- setPreds.remove(first);
-
- if(!setPreds.isEmpty()) {
- Statement pred = setPreds.iterator().next(); // assumption: at most one predecessor node besides the head. May not hold true for obfuscated code.
- for(int j=0;j<nodes.size();j++) {
- if(j != (index - 1) && nodes.get(j) == pred) {
- nodes.add(j+1, stat);
- edges.add(j+1, edges.get(index));
-
- if(j > index) {
- nodes.remove(index);
- edges.remove(index);
- index--;
- } else {
- nodes.remove(index + 1);
- edges.remove(index + 1);
- }
- break;
- }
- }
- }
- }
- }
-
- // translate indices back into edges
- List<List<StatEdge>> lstEdges = new ArrayList<List<StatEdge>>();
- List<List<ConstExprent>> lstValues = new ArrayList<List<ConstExprent>>();
-
- for(List<Integer> lst: edges) {
- List<StatEdge> lste = new ArrayList<StatEdge>();
- List<ConstExprent> lstv = new ArrayList<ConstExprent>();
-
- List<StatEdge> lstSuccs = first.getSuccessorEdges(STATEDGE_DIRECT_ALL);
- for(Integer in: lst) {
- int index = in==lstSuccs.size()?0:in;
-
- lste.add(lstSuccs.get(index));
- lstv.add(index==0?null:new ConstExprent(values[index-1], false));
- }
- lstEdges.add(lste);
- lstValues.add(lstv);
- }
-
- // replace null statements with dummy basic blocks
- for(int i=0;i<nodes.size();i++) {
- if(nodes.get(i) == null) {
- BasicBlockStatement bstat = new BasicBlockStatement(new BasicBlock(
- DecompilerContext.getCountercontainer().getCounterAndIncrement(CounterContainer.STATEMENT_COUNTER)));
-
- StatEdge sample_edge = lstEdges.get(i).get(0);
-
- bstat.addSuccessor(new StatEdge(sample_edge.getType(), bstat, sample_edge.getDestination(), sample_edge.closure));
-
- for(StatEdge edge : lstEdges.get(i)) {
-
- edge.getSource().changeEdgeType(DIRECTION_FORWARD, edge, StatEdge.TYPE_REGULAR);
- edge.closure.getLabelEdges().remove(edge);
-
- edge.getDestination().removePredecessor(edge);
- edge.getSource().changeEdgeNode(DIRECTION_FORWARD, edge, bstat);
- bstat.addPredecessor(edge);
- }
-
- nodes.set(i, bstat);
- stats.addWithKey(bstat, bstat.id);
- bstat.setParent(this);
- }
- }
-
- caseStatements = nodes;
- caseEdges = lstEdges;
- caseValues = lstValues;
- }
-
- public List<Exprent> getHeadexprentList() {
- return headexprent;
- }
-
- public Exprent getHeadexprent() {
- return headexprent.get(0);
- }
-
- public List<List<StatEdge>> getCaseEdges() {
- return caseEdges;
- }
-
- public List<Statement> getCaseStatements() {
- return caseStatements;
- }
-
- public StatEdge getDefault_edge() {
- return default_edge;
- }
-
- public List<List<ConstExprent>> getCaseValues() {
- return caseValues;
- }
+ // *****************************************************************************
+ // private fields
+ // *****************************************************************************
+
+ private List<Statement> caseStatements = new ArrayList<Statement>();
+
+ private List<List<StatEdge>> caseEdges = new ArrayList<List<StatEdge>>();
+
+ private List<List<ConstExprent>> caseValues = new ArrayList<List<ConstExprent>>();
+
+ private StatEdge default_edge;
+
+ private List<Exprent> headexprent = new ArrayList<Exprent>();
+
+ // *****************************************************************************
+ // constructors
+ // *****************************************************************************
+
+ private SwitchStatement() {
+ type = TYPE_SWITCH;
+
+ headexprent.add(null);
+ }
+
+ private SwitchStatement(Statement head, Statement poststat) {
+
+ this();
+
+ first = head;
+ stats.addWithKey(head, head.id);
+
+ // find post node
+ Set<Statement> lstNodes = new HashSet<Statement>(head.getNeighbours(StatEdge.TYPE_REGULAR, DIRECTION_FORWARD));
+
+ // cluster nodes
+ if (poststat != null) {
+ post = poststat;
+ lstNodes.remove(post);
+ }
+
+ default_edge = head.getSuccessorEdges(Statement.STATEDGE_DIRECT_ALL).get(0);
+
+ for (Statement st : lstNodes) {
+ stats.addWithKey(st, st.id);
+ }
+ }
+
+ // *****************************************************************************
+ // public methods
+ // *****************************************************************************
+
+ public static Statement isHead(Statement head) {
+
+ if (head.type == Statement.TYPE_BASICBLOCK && head.getLastBasicType() == Statement.LASTBASICTYPE_SWITCH) {
+
+ List<Statement> lst = new ArrayList<Statement>();
+ if (DecHelper.isChoiceStatement(head, lst)) {
+ Statement post = lst.remove(0);
+
+ for (Statement st : lst) {
+ if (st.isMonitorEnter()) {
+ return null;
+ }
+ }
+
+ if (DecHelper.checkStatementExceptions(lst)) {
+ return new SwitchStatement(head, post);
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public String toJava(int indent) {
+
+ String indstr = InterpreterUtil.getIndentString(indent);
+
+ String new_line_separator = DecompilerContext.getNewLineSeparator();
+
+ StringBuilder buf = new StringBuilder();
+ 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);
+
+ VarType switch_type = headexprent.get(0).getExprType();
+
+ for (int i = 0; i < caseStatements.size(); i++) {
+
+ Statement stat = caseStatements.get(i);
+ List<StatEdge> edges = caseEdges.get(i);
+ List<ConstExprent> values = caseValues.get(i);
+
+ for (int j = 0; j < edges.size(); j++) {
+ if (edges.get(j) == default_edge) {
+ buf.append(indstr + "default:" + new_line_separator);
+ }
+ else {
+ ConstExprent value = (ConstExprent)values.get(j).copy();
+ value.setConsttype(switch_type);
+
+ buf.append(indstr + "case " + value.toJava(indent) + ":" + new_line_separator);
+ }
+ }
+
+ buf.append(ExprProcessor.jmpWrapper(stat, indent + 1, false));
+ }
+
+ buf.append(indstr + "}" + new_line_separator);
+
+ return buf.toString();
+ }
+
+ public void initExprents() {
+ SwitchExprent swexpr = (SwitchExprent)first.getExprents().remove(first.getExprents().size() - 1);
+ swexpr.setCaseValues(caseValues);
+
+ headexprent.set(0, swexpr);
+ }
+
+ 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) {
+
+ for (int i = 0; i < caseStatements.size(); i++) {
+ if (caseStatements.get(i) == oldstat) {
+ caseStatements.set(i, newstat);
+ }
+ }
+
+ super.replaceStatement(oldstat, newstat);
+ }
+
+ public Statement getSimpleCopy() {
+ return new SwitchStatement();
+ }
+
+ public void initSimpleCopy() {
+ first = stats.get(0);
+ default_edge = first.getSuccessorEdges(Statement.STATEDGE_DIRECT_ALL).get(0);
+
+ sortEdgesAndNodes();
+ }
+
+ // *****************************************************************************
+ // private methods
+ // *****************************************************************************
+
+ public void sortEdgesAndNodes() {
+
+ HashMap<StatEdge, Integer> mapEdgeIndex = new HashMap<StatEdge, Integer>();
+
+ List<StatEdge> lstFirstSuccs = first.getSuccessorEdges(STATEDGE_DIRECT_ALL);
+ for (int i = 0; i < lstFirstSuccs.size(); i++) {
+ mapEdgeIndex.put(lstFirstSuccs.get(i), i == 0 ? lstFirstSuccs.size() : i);
+ }
+
+ // case values
+ BasicBlockStatement bbstat = (BasicBlockStatement)first;
+ int[] values = ((SwitchInstruction)bbstat.getBlock().getLastInstruction()).getValues();
+
+ List<Statement> nodes = new ArrayList<Statement>();
+ List<List<Integer>> edges = new ArrayList<List<Integer>>();
+
+ // collect regular edges
+ for (int i = 1; i < stats.size(); i++) {
+
+ Statement stat = stats.get(i);
+
+ List<Integer> lst = new ArrayList<Integer>();
+ for (StatEdge edge : stat.getPredecessorEdges(StatEdge.TYPE_REGULAR)) {
+ if (edge.getSource() == first) {
+ lst.add(mapEdgeIndex.get(edge));
+ }
+ }
+ Collections.sort(lst);
+
+ nodes.add(stat);
+ edges.add(lst);
+ }
+
+ // collect exit edges
+ List<StatEdge> lstExitEdges = first.getSuccessorEdges(StatEdge.TYPE_BREAK | StatEdge.TYPE_CONTINUE);
+ while (!lstExitEdges.isEmpty()) {
+ StatEdge edge = lstExitEdges.get(0);
+
+ List<Integer> lst = new ArrayList<Integer>();
+ for (int i = lstExitEdges.size() - 1; i >= 0; i--) {
+ StatEdge edgeTemp = lstExitEdges.get(i);
+ if (edgeTemp.getDestination() == edge.getDestination() && edgeTemp.getType() == edge.getType()) {
+ lst.add(mapEdgeIndex.get(edgeTemp));
+ lstExitEdges.remove(i);
+ }
+ }
+ Collections.sort(lst);
+
+ nodes.add(null);
+ edges.add(lst);
+ }
+
+ // sort edges (bubblesort)
+ for (int i = 0; i < edges.size() - 1; i++) {
+ for (int j = edges.size() - 1; j > i; j--) {
+ if (edges.get(j - 1).get(0) > edges.get(j).get(0)) {
+ edges.set(j, edges.set(j - 1, edges.get(j)));
+ nodes.set(j, nodes.set(j - 1, nodes.get(j)));
+ }
+ }
+ }
+
+ // sort statement cliques
+ for (int index = 0; index < nodes.size(); index++) {
+ Statement stat = nodes.get(index);
+
+ if (stat != null) {
+ HashSet<Statement> setPreds = new HashSet<Statement>(stat.getNeighbours(StatEdge.TYPE_REGULAR, DIRECTION_BACKWARD));
+ setPreds.remove(first);
+
+ if (!setPreds.isEmpty()) {
+ Statement pred =
+ setPreds.iterator().next(); // assumption: at most one predecessor node besides the head. May not hold true for obfuscated code.
+ for (int j = 0; j < nodes.size(); j++) {
+ if (j != (index - 1) && nodes.get(j) == pred) {
+ nodes.add(j + 1, stat);
+ edges.add(j + 1, edges.get(index));
+
+ if (j > index) {
+ nodes.remove(index);
+ edges.remove(index);
+ index--;
+ }
+ else {
+ nodes.remove(index + 1);
+ edges.remove(index + 1);
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // translate indices back into edges
+ List<List<StatEdge>> lstEdges = new ArrayList<List<StatEdge>>();
+ List<List<ConstExprent>> lstValues = new ArrayList<List<ConstExprent>>();
+
+ for (List<Integer> lst : edges) {
+ List<StatEdge> lste = new ArrayList<StatEdge>();
+ List<ConstExprent> lstv = new ArrayList<ConstExprent>();
+
+ List<StatEdge> lstSuccs = first.getSuccessorEdges(STATEDGE_DIRECT_ALL);
+ for (Integer in : lst) {
+ int index = in == lstSuccs.size() ? 0 : in;
+
+ lste.add(lstSuccs.get(index));
+ lstv.add(index == 0 ? null : new ConstExprent(values[index - 1], false));
+ }
+ lstEdges.add(lste);
+ lstValues.add(lstv);
+ }
+
+ // replace null statements with dummy basic blocks
+ for (int i = 0; i < nodes.size(); i++) {
+ if (nodes.get(i) == null) {
+ BasicBlockStatement bstat = new BasicBlockStatement(new BasicBlock(
+ DecompilerContext.getCountercontainer().getCounterAndIncrement(CounterContainer.STATEMENT_COUNTER)));
+
+ StatEdge sample_edge = lstEdges.get(i).get(0);
+
+ bstat.addSuccessor(new StatEdge(sample_edge.getType(), bstat, sample_edge.getDestination(), sample_edge.closure));
+
+ for (StatEdge edge : lstEdges.get(i)) {
+
+ edge.getSource().changeEdgeType(DIRECTION_FORWARD, edge, StatEdge.TYPE_REGULAR);
+ edge.closure.getLabelEdges().remove(edge);
+
+ edge.getDestination().removePredecessor(edge);
+ edge.getSource().changeEdgeNode(DIRECTION_FORWARD, edge, bstat);
+ bstat.addPredecessor(edge);
+ }
+
+ nodes.set(i, bstat);
+ stats.addWithKey(bstat, bstat.id);
+ bstat.setParent(this);
+ }
+ }
+
+ caseStatements = nodes;
+ caseEdges = lstEdges;
+ caseValues = lstValues;
+ }
+
+ public List<Exprent> getHeadexprentList() {
+ return headexprent;
+ }
+
+ public Exprent getHeadexprent() {
+ return headexprent.get(0);
+ }
+
+ public List<List<StatEdge>> getCaseEdges() {
+ return caseEdges;
+ }
+
+ public List<Statement> getCaseStatements() {
+ return caseStatements;
+ }
+
+ public StatEdge getDefault_edge() {
+ return default_edge;
+ }
+ public List<List<ConstExprent>> getCaseValues() {
+ return caseValues;
+ }
}
diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SynchronizedStatement.java b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SynchronizedStatement.java
index 5336f12..3fcb042 100644
--- a/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SynchronizedStatement.java
+++ b/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SynchronizedStatement.java
@@ -1,22 +1,20 @@
/*
- * Fernflower - The Analytical Java Decompiler
- * http://www.reversed-java.com
+ * Copyright 2000-2014 JetBrains s.r.o.
*
- * (C) 2008 - 2010, Stiver
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * This software is NEITHER public domain NOR free software
- * as per GNU License. See license.txt for more details.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * This software is distributed WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
-
package org.jetbrains.java.decompiler.modules.decompiler.stats;
-import java.util.ArrayList;
-import java.util.List;
-
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
import org.jetbrains.java.decompiler.modules.decompiler.SequenceHelper;
@@ -24,131 +22,132 @@ import org.jetbrains.java.decompiler.modules.decompiler.StatEdge;
import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
+import java.util.ArrayList;
+import java.util.List;
+
public class SynchronizedStatement extends Statement {
- private Statement body;
-
- private List<Exprent> headexprent = new ArrayList<Exprent>();
-
- // *****************************************************************************
- // constructors
- // *****************************************************************************
-
- public SynchronizedStatement() {
- type = TYPE_SYNCRONIZED;
-
- headexprent.add(null);
- }
-
- public SynchronizedStatement(Statement head, Statement body, Statement exc) {
-
- this();
-
- first = head;
- stats.addWithKey(head, head.id);
-
- this.body = body;
- stats.addWithKey(body, body.id);
-
- stats.addWithKey(exc, exc.id);
-
- List<StatEdge> lstSuccs = body.getSuccessorEdges(STATEDGE_DIRECT_ALL);
- if(!lstSuccs.isEmpty()) {
- StatEdge edge = lstSuccs.get(0);
- if(edge.getType() == StatEdge.TYPE_REGULAR) {
- post = edge.getDestination();
- }
- }
-
- }
-
-
- // *****************************************************************************
- // public methods
- // *****************************************************************************
-
- public String toJava(int indent) {
- String indstr = InterpreterUtil.getIndentString(indent);
-
- String new_line_separator = DecompilerContext.getNewLineSeparator();
-
- StringBuffer buf = new StringBuffer();
- 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);
- buf.append(ExprProcessor.jmpWrapper(body, indent+1, true));
- buf.append(indstr+"}" + new_line_separator);
-
- return buf.toString();
- }
-
- public void initExprents() {
- headexprent.set(0, first.getExprents().remove(first.getExprents().size()-1));
- }
-
- 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) {
-
- if(body == oldstat) {
- body = newstat;
- }
-
- super.replaceStatement(oldstat, newstat);
- }
-
- public void removeExc() {
- Statement exc = stats.get(2);
- SequenceHelper.destroyStatementContent(exc, true);
-
- stats.removeWithKey(exc.id);
- }
-
- public Statement getSimpleCopy() {
- return new SynchronizedStatement();
- }
-
- public void initSimpleCopy() {
- first = stats.get(0);
- body = stats.get(1);
- }
-
- // *****************************************************************************
- // getter and setter methods
- // *****************************************************************************
-
- public Statement getBody() {
- return body;
- }
-
- public void setBody(Statement body) {
- this.body = body;
- }
-
- public List<Exprent> getHeadexprentList() {
- return headexprent;
- }
-
- public Exprent getHeadexprent() {
- return headexprent.get(0);
- }
-
+ private Statement body;
+
+ private List<Exprent> headexprent = new ArrayList<Exprent>();
+
+ // *****************************************************************************
+ // constructors
+ // *****************************************************************************
+
+ public SynchronizedStatement() {
+ type = TYPE_SYNCRONIZED;
+
+ headexprent.add(null);
+ }
+
+ public SynchronizedStatement(Statement head, Statement body, Statement exc) {
+
+ this();
+
+ first = head;
+ stats.addWithKey(head, head.id);
+
+ this.body = body;
+ stats.addWithKey(body, body.id);
+
+ stats.addWithKey(exc, exc.id);
+
+ List<StatEdge> lstSuccs = body.getSuccessorEdges(STATEDGE_DIRECT_ALL);
+ if (!lstSuccs.isEmpty()) {
+ StatEdge edge = lstSuccs.get(0);
+ if (edge.getType() == StatEdge.TYPE_REGULAR) {
+ post = edge.getDestination();
+ }
+ }
+ }
+
+
+ // *****************************************************************************
+ // public methods
+ // *****************************************************************************
+
+ public String toJava(int indent) {
+ String indstr = InterpreterUtil.getIndentString(indent);
+
+ String new_line_separator = DecompilerContext.getNewLineSeparator();
+
+ StringBuffer buf = new StringBuffer();
+ 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);
+ buf.append(ExprProcessor.jmpWrapper(body, indent + 1, true));
+ buf.append(indstr + "}" + new_line_separator);
+
+ return buf.toString();
+ }
+
+ public void initExprents() {
+ headexprent.set(0, first.getExprents().remove(first.getExprents().size() - 1));
+ }
+
+ 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) {
+
+ if (body == oldstat) {
+ body = newstat;
+ }
+
+ super.replaceStatement(oldstat, newstat);
+ }
+
+ public void removeExc() {
+ Statement exc = stats.get(2);
+ SequenceHelper.destroyStatementContent(exc, true);
+
+ stats.removeWithKey(exc.id);
+ }
+
+ public Statement getSimpleCopy() {
+ return new SynchronizedStatement();
+ }
+
+ public void initSimpleCopy() {
+ first = stats.get(0);
+ body = stats.get(1);
+ }
+
+ // *****************************************************************************
+ // getter and setter methods
+ // *****************************************************************************
+
+ public Statement getBody() {
+ return body;
+ }
+
+ public void setBody(Statement body) {
+ this.body = body;
+ }
+
+ public List<Exprent> getHeadexprentList() {
+ return headexprent;
+ }
+
+ public Exprent getHeadexprent() {
+ return headexprent.get(0);
+ }
}