summaryrefslogtreecommitdiffstats
path: root/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java
diff options
context:
space:
mode:
authorRoman Shevchenko <roman.shevchenko@jetbrains.com>2014-08-28 21:34:14 +0400
committerRoman Shevchenko <roman.shevchenko@jetbrains.com>2014-08-28 21:34:19 +0400
commit076e4393f25bf1ad1ff1bd2853153e2b595dd90b (patch)
treef1a17a12ea762525b5efbc0778b0945d906c68c9 /src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java
parent663631f0456fcc245dd835889f86541d75161c53 (diff)
downloadfernflower-076e4393f25bf1ad1ff1bd2853153e2b595dd90b.tar
fernflower-076e4393f25bf1ad1ff1bd2853153e2b595dd90b.tar.gz
fernflower-076e4393f25bf1ad1ff1bd2853153e2b595dd90b.tar.lz
fernflower-076e4393f25bf1ad1ff1bd2853153e2b595dd90b.tar.xz
fernflower-076e4393f25bf1ad1ff1bd2853153e2b595dd90b.zip
java-decompiler: post-import cleanup (formatting and copyright)
Diffstat (limited to 'src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java')
-rw-r--r--src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java1719
1 files changed, 873 insertions, 846 deletions
diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java b/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java
index 362e1a2..3b35d36 100644
--- a/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java
+++ b/src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java
@@ -1,54 +1,31 @@
/*
- * 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;
-import java.util.Arrays;
-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.Instruction;
import org.jetbrains.java.decompiler.code.InstructionSequence;
import org.jetbrains.java.decompiler.code.cfg.BasicBlock;
import org.jetbrains.java.decompiler.main.DecompilerContext;
-import org.jetbrains.java.decompiler.modules.decompiler.exps.ArrayExprent;
-import org.jetbrains.java.decompiler.modules.decompiler.exps.AssignmentExprent;
-import org.jetbrains.java.decompiler.modules.decompiler.exps.ConstExprent;
-import org.jetbrains.java.decompiler.modules.decompiler.exps.ExitExprent;
-import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent;
-import org.jetbrains.java.decompiler.modules.decompiler.exps.FieldExprent;
-import org.jetbrains.java.decompiler.modules.decompiler.exps.FunctionExprent;
-import org.jetbrains.java.decompiler.modules.decompiler.exps.IfExprent;
-import org.jetbrains.java.decompiler.modules.decompiler.exps.InvocationExprent;
-import org.jetbrains.java.decompiler.modules.decompiler.exps.MonitorExprent;
-import org.jetbrains.java.decompiler.modules.decompiler.exps.NewExprent;
-import org.jetbrains.java.decompiler.modules.decompiler.exps.SwitchExprent;
-import org.jetbrains.java.decompiler.modules.decompiler.exps.VarExprent;
+import org.jetbrains.java.decompiler.modules.decompiler.exps.*;
import org.jetbrains.java.decompiler.modules.decompiler.sforms.DirectGraph;
import org.jetbrains.java.decompiler.modules.decompiler.sforms.DirectNode;
import org.jetbrains.java.decompiler.modules.decompiler.sforms.FlattenStatementsHelper;
import org.jetbrains.java.decompiler.modules.decompiler.sforms.FlattenStatementsHelper.FinallyPathWrapper;
-import org.jetbrains.java.decompiler.modules.decompiler.stats.BasicBlockStatement;
-import org.jetbrains.java.decompiler.modules.decompiler.stats.CatchAllStatement;
-import org.jetbrains.java.decompiler.modules.decompiler.stats.CatchStatement;
-import org.jetbrains.java.decompiler.modules.decompiler.stats.RootStatement;
-import org.jetbrains.java.decompiler.modules.decompiler.stats.Statement;
+import org.jetbrains.java.decompiler.modules.decompiler.stats.*;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarProcessor;
import org.jetbrains.java.decompiler.struct.StructClass;
import org.jetbrains.java.decompiler.struct.attr.StructBootstrapMethodsAttribute;
@@ -61,826 +38,876 @@ import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor;
import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
+import java.util.*;
+
public class ExprProcessor implements CodeConstants {
- public static final String UNDEFINED_TYPE_STRING = "<undefinedtype>";
- public static final String UNKNOWN_TYPE_STRING = "<unknown>";
- public static final String NULL_TYPE_STRING = "<null>";
-
- private static final HashMap<Integer, Integer> mapConsts = new HashMap<Integer, Integer>();
+ public static final String UNDEFINED_TYPE_STRING = "<undefinedtype>";
+ public static final String UNKNOWN_TYPE_STRING = "<unknown>";
+ public static final String NULL_TYPE_STRING = "<null>";
+
+ private static final HashMap<Integer, Integer> mapConsts = new HashMap<Integer, Integer>();
+
+ static {
+
+ // mapConsts.put(new Integer(opc_i2l), new
+ // Integer(FunctionExprent.FUNCTION_I2L));
+ // mapConsts.put(new Integer(opc_i2f), new
+ // Integer(FunctionExprent.FUNCTION_I2F));
+ // mapConsts.put(new Integer(opc_i2d), new
+ // Integer(FunctionExprent.FUNCTION_I2D));
+ // mapConsts.put(new Integer(opc_l2i), new
+ // Integer(FunctionExprent.FUNCTION_L2I));
+ // mapConsts.put(new Integer(opc_l2f), new
+ // Integer(FunctionExprent.FUNCTION_L2F));
+ // mapConsts.put(new Integer(opc_l2d), new
+ // Integer(FunctionExprent.FUNCTION_L2D));
+ // mapConsts.put(new Integer(opc_f2i), new
+ // Integer(FunctionExprent.FUNCTION_F2I));
+ // mapConsts.put(new Integer(opc_f2l), new
+ // Integer(FunctionExprent.FUNCTION_F2L));
+ // mapConsts.put(new Integer(opc_f2d), new
+ // Integer(FunctionExprent.FUNCTION_F2D));
+ // mapConsts.put(new Integer(opc_d2i), new
+ // Integer(FunctionExprent.FUNCTION_D2I));
+ // mapConsts.put(new Integer(opc_d2l), new
+ // Integer(FunctionExprent.FUNCTION_D2L));
+ // mapConsts.put(new Integer(opc_d2f), new
+ // Integer(FunctionExprent.FUNCTION_D2F));
+ // mapConsts.put(new Integer(opc_i2b), new
+ // Integer(FunctionExprent.FUNCTION_I2B));
+ // mapConsts.put(new Integer(opc_i2c), new
+ // Integer(FunctionExprent.FUNCTION_I2C));
+ // mapConsts.put(new Integer(opc_i2s), new
+ // Integer(FunctionExprent.FUNCTION_I2S));
+
+ mapConsts.put(new Integer(opc_arraylength), new Integer(FunctionExprent.FUNCTION_ARRAYLENGTH));
+ mapConsts.put(new Integer(opc_checkcast), new Integer(FunctionExprent.FUNCTION_CAST));
+ mapConsts.put(new Integer(opc_instanceof), new Integer(FunctionExprent.FUNCTION_INSTANCEOF));
+ }
+
+ private static final VarType[] consts =
+ new VarType[]{VarType.VARTYPE_INT, VarType.VARTYPE_FLOAT, VarType.VARTYPE_LONG, VarType.VARTYPE_DOUBLE, VarType.VARTYPE_CLASS,
+ VarType.VARTYPE_STRING};
+
+ private static final VarType[] vartypes =
+ new VarType[]{VarType.VARTYPE_INT, VarType.VARTYPE_LONG, VarType.VARTYPE_FLOAT, VarType.VARTYPE_DOUBLE, VarType.VARTYPE_OBJECT};
+
+ private static final VarType[] arrtypes =
+ new VarType[]{VarType.VARTYPE_INT, VarType.VARTYPE_LONG, VarType.VARTYPE_FLOAT, VarType.VARTYPE_DOUBLE, VarType.VARTYPE_OBJECT,
+ VarType.VARTYPE_BOOLEAN, VarType.VARTYPE_CHAR, VarType.VARTYPE_SHORT};
+
+ private static final int[] func1 =
+ new int[]{FunctionExprent.FUNCTION_ADD, FunctionExprent.FUNCTION_SUB, FunctionExprent.FUNCTION_MUL, FunctionExprent.FUNCTION_DIV,
+ FunctionExprent.FUNCTION_REM};
+
+ private static final int[] func2 =
+ new int[]{FunctionExprent.FUNCTION_SHL, FunctionExprent.FUNCTION_SHR, FunctionExprent.FUNCTION_USHR, FunctionExprent.FUNCTION_AND,
+ FunctionExprent.FUNCTION_OR, FunctionExprent.FUNCTION_XOR};
+
+ private static final int[] func3 =
+ new int[]{FunctionExprent.FUNCTION_I2L, FunctionExprent.FUNCTION_I2F, FunctionExprent.FUNCTION_I2D, FunctionExprent.FUNCTION_L2I,
+ FunctionExprent.FUNCTION_L2F, FunctionExprent.FUNCTION_L2D, FunctionExprent.FUNCTION_F2I, FunctionExprent.FUNCTION_F2L,
+ FunctionExprent.FUNCTION_F2D,
+ FunctionExprent.FUNCTION_D2I, FunctionExprent.FUNCTION_D2L, FunctionExprent.FUNCTION_D2F, FunctionExprent.FUNCTION_I2B,
+ FunctionExprent.FUNCTION_I2C,
+ FunctionExprent.FUNCTION_I2S};
+
+ private static final int[] func4 =
+ new int[]{FunctionExprent.FUNCTION_LCMP, FunctionExprent.FUNCTION_FCMPL, FunctionExprent.FUNCTION_FCMPG, FunctionExprent.FUNCTION_DCMPL,
+ FunctionExprent.FUNCTION_DCMPG};
+
+ private static final int[] func5 =
+ new int[]{IfExprent.IF_EQ, IfExprent.IF_NE, IfExprent.IF_LT, IfExprent.IF_GE, IfExprent.IF_GT, IfExprent.IF_LE};
+
+ private static final int[] func6 =
+ new int[]{IfExprent.IF_ICMPEQ, IfExprent.IF_ICMPNE, IfExprent.IF_ICMPLT, IfExprent.IF_ICMPGE, IfExprent.IF_ICMPGT, IfExprent.IF_ICMPLE,
+ IfExprent.IF_ACMPEQ, IfExprent.IF_ACMPNE};
+
+ private static final int[] func7 = new int[]{IfExprent.IF_NULL, IfExprent.IF_NONNULL};
+
+ private static final int[] func8 = new int[]{MonitorExprent.MONITOR_ENTER, MonitorExprent.MONITOR_EXIT};
+
+ private static final int[] arr_type =
+ new int[]{CodeConstants.TYPE_BOOLEAN, CodeConstants.TYPE_CHAR, CodeConstants.TYPE_FLOAT, CodeConstants.TYPE_DOUBLE,
+ CodeConstants.TYPE_BYTE, CodeConstants.TYPE_SHORT, CodeConstants.TYPE_INT, CodeConstants.TYPE_LONG};
+
+ private static final int[] negifs =
+ new int[]{IfExprent.IF_NE, IfExprent.IF_EQ, IfExprent.IF_GE, IfExprent.IF_LT, IfExprent.IF_LE, IfExprent.IF_GT, IfExprent.IF_NONNULL,
+ IfExprent.IF_NULL, IfExprent.IF_ICMPNE, IfExprent.IF_ICMPEQ, IfExprent.IF_ICMPGE, IfExprent.IF_ICMPLT, IfExprent.IF_ICMPLE,
+ IfExprent.IF_ICMPGT, IfExprent.IF_ACMPNE,
+ IfExprent.IF_ACMPEQ};
+
+ private static final String[] typeNames = new String[]{"byte", "char", "double", "float", "int", "long", "short", "boolean",};
+
+ private VarProcessor varProcessor = (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR);
+
+ public void processStatement(RootStatement root, StructClass cl) {
+
+ FlattenStatementsHelper flatthelper = new FlattenStatementsHelper();
+ DirectGraph dgraph = flatthelper.buildDirectGraph(root);
+
+ // try {
+ // DotExporter.toDotFile(dgraph, new File("c:\\Temp\\gr12_my.dot"));
+ // } catch (Exception ex) {
+ // ex.printStackTrace();
+ // }
+
+ // collect finally entry points
+ Set<String> setFinallyShortRangeEntryPoints = new HashSet<String>();
+ for (List<FinallyPathWrapper> lst : dgraph.mapShortRangeFinallyPaths.values()) {
+ for (FinallyPathWrapper finwrap : lst) {
+ setFinallyShortRangeEntryPoints.add(finwrap.entry);
+ }
+ }
+
+ Set<String> setFinallyLongRangeEntryPaths = new HashSet<String>();
+ for (List<FinallyPathWrapper> lst : dgraph.mapLongRangeFinallyPaths.values()) {
+ for (FinallyPathWrapper finwrap : lst) {
+ setFinallyLongRangeEntryPaths.add(finwrap.source + "##" + finwrap.entry);
+ }
+ }
- static {
-
- // mapConsts.put(new Integer(opc_i2l), new
- // Integer(FunctionExprent.FUNCTION_I2L));
- // mapConsts.put(new Integer(opc_i2f), new
- // Integer(FunctionExprent.FUNCTION_I2F));
- // mapConsts.put(new Integer(opc_i2d), new
- // Integer(FunctionExprent.FUNCTION_I2D));
- // mapConsts.put(new Integer(opc_l2i), new
- // Integer(FunctionExprent.FUNCTION_L2I));
- // mapConsts.put(new Integer(opc_l2f), new
- // Integer(FunctionExprent.FUNCTION_L2F));
- // mapConsts.put(new Integer(opc_l2d), new
- // Integer(FunctionExprent.FUNCTION_L2D));
- // mapConsts.put(new Integer(opc_f2i), new
- // Integer(FunctionExprent.FUNCTION_F2I));
- // mapConsts.put(new Integer(opc_f2l), new
- // Integer(FunctionExprent.FUNCTION_F2L));
- // mapConsts.put(new Integer(opc_f2d), new
- // Integer(FunctionExprent.FUNCTION_F2D));
- // mapConsts.put(new Integer(opc_d2i), new
- // Integer(FunctionExprent.FUNCTION_D2I));
- // mapConsts.put(new Integer(opc_d2l), new
- // Integer(FunctionExprent.FUNCTION_D2L));
- // mapConsts.put(new Integer(opc_d2f), new
- // Integer(FunctionExprent.FUNCTION_D2F));
- // mapConsts.put(new Integer(opc_i2b), new
- // Integer(FunctionExprent.FUNCTION_I2B));
- // mapConsts.put(new Integer(opc_i2c), new
- // Integer(FunctionExprent.FUNCTION_I2C));
- // mapConsts.put(new Integer(opc_i2s), new
- // Integer(FunctionExprent.FUNCTION_I2S));
-
- mapConsts.put(new Integer(opc_arraylength), new Integer(FunctionExprent.FUNCTION_ARRAYLENGTH));
- mapConsts.put(new Integer(opc_checkcast), new Integer(FunctionExprent.FUNCTION_CAST));
- mapConsts.put(new Integer(opc_instanceof), new Integer(FunctionExprent.FUNCTION_INSTANCEOF));
-
- }
-
- private static final VarType[] consts = new VarType[] { VarType.VARTYPE_INT, VarType.VARTYPE_FLOAT, VarType.VARTYPE_LONG, VarType.VARTYPE_DOUBLE, VarType.VARTYPE_CLASS,
- VarType.VARTYPE_STRING };
+ Map<String, VarExprent> mapCatch = new HashMap<String, VarExprent>();
+ collectCatchVars(root, flatthelper, mapCatch);
+
+ Map<DirectNode, Map<String, PrimitiveExprsList>> mapData = new HashMap<DirectNode, Map<String, PrimitiveExprsList>>();
+
+ LinkedList<DirectNode> stack = new LinkedList<DirectNode>();
+ LinkedList<LinkedList<String>> stackEntryPoint = new LinkedList<LinkedList<String>>();
+
+ stack.add(dgraph.first);
+ stackEntryPoint.add(new LinkedList<String>());
+
+ Map<String, PrimitiveExprsList> map = new HashMap<String, PrimitiveExprsList>();
+ map.put(null, new PrimitiveExprsList());
+ mapData.put(dgraph.first, map);
+
+ while (!stack.isEmpty()) {
+
+ DirectNode node = stack.removeFirst();
+ LinkedList<String> entrypoints = stackEntryPoint.removeFirst();
+
+ PrimitiveExprsList data;
+ if (mapCatch.containsKey(node.id)) {
+ data = getExpressionData(mapCatch.get(node.id));
+ }
+ else {
+ data = mapData.get(node).get(buildEntryPointKey(entrypoints));
+ }
+
+ BasicBlockStatement block = node.block;
+ if (block != null) {
+ processBlock(block, data, cl);
+ block.setExprents(data.getLstExprents());
+ }
+
+ String currentEntrypoint = entrypoints.isEmpty() ? null : entrypoints.getLast();
+
+ for (DirectNode nd : node.succs) {
+
+ boolean isSuccessor = true;
+ if (currentEntrypoint != null && dgraph.mapLongRangeFinallyPaths.containsKey(node.id)) {
+ isSuccessor = false;
+ for (FinallyPathWrapper finwraplong : dgraph.mapLongRangeFinallyPaths.get(node.id)) {
+ if (finwraplong.source.equals(currentEntrypoint) && finwraplong.destination.equals(nd.id)) {
+ isSuccessor = true;
+ break;
+ }
+ }
+ }
+
+ if (isSuccessor) {
+
+ Map<String, PrimitiveExprsList> mapSucc = mapData.get(nd);
+ if (mapSucc == null) {
+ mapData.put(nd, mapSucc = new HashMap<String, PrimitiveExprsList>());
+ }
+
+ LinkedList<String> ndentrypoints = new LinkedList<String>(entrypoints);
+
+ if (setFinallyLongRangeEntryPaths.contains(node.id + "##" + nd.id)) {
+ ndentrypoints.addLast(node.id);
+ }
+ else if (!setFinallyShortRangeEntryPoints.contains(nd.id) && dgraph.mapLongRangeFinallyPaths.containsKey(node.id)) {
+ ndentrypoints.removeLast(); // currentEntrypoint should
+ // not be null at this point
+ }
+
+ // handling of entry point loops
+ int succ_entry_index = ndentrypoints.indexOf(nd.id);
+ if (succ_entry_index >=
+ 0) { // we are in a loop (e.g. continue in a finally block), drop all entry points in the list beginning with succ_entry_index
+ for (int elements_to_remove = ndentrypoints.size() - succ_entry_index; elements_to_remove > 0; elements_to_remove--) {
+ ndentrypoints.removeLast();
+ }
+ }
+
+ String ndentrykey = buildEntryPointKey(ndentrypoints);
+ if (!mapSucc.containsKey(ndentrykey)) {
+
+ mapSucc.put(ndentrykey, copyVarExprents(data.copyStack()));
+
+ stack.add(nd);
+ stackEntryPoint.add(ndentrypoints);
+ }
+ }
+ }
+ }
+
+ initStatementExprents(root);
+ }
+
+ // FIXME: Ugly code, to be rewritten. A tuple class is needed.
+ private String buildEntryPointKey(LinkedList<String> entrypoints) {
+ if (entrypoints.isEmpty()) {
+ return null;
+ }
+ else {
+ StringBuilder buffer = new StringBuilder();
+ for (String point : entrypoints) {
+ buffer.append(point);
+ buffer.append(":");
+ }
+ return buffer.toString();
+ }
+ }
- private static final VarType[] vartypes = new VarType[] { VarType.VARTYPE_INT, VarType.VARTYPE_LONG, VarType.VARTYPE_FLOAT, VarType.VARTYPE_DOUBLE, VarType.VARTYPE_OBJECT };
+ private PrimitiveExprsList copyVarExprents(PrimitiveExprsList data) {
+ ExprentStack stack = data.getStack();
+ for (int i = 0; i < stack.size(); i++) {
+ stack.set(i, stack.get(i).copy());
+ }
+ return data;
+ }
+
+ private void collectCatchVars(Statement stat, FlattenStatementsHelper flatthelper, Map<String, VarExprent> map) {
+
+ List<VarExprent> lst = null;
+
+ if (stat.type == Statement.TYPE_CATCHALL) {
+ CatchAllStatement catchall = (CatchAllStatement)stat;
+ if (!catchall.isFinally()) {
+ lst = catchall.getVars();
+ }
+ }
+ else if (stat.type == Statement.TYPE_TRYCATCH) {
+ lst = ((CatchStatement)stat).getVars();
+ }
+
+ if (lst != null) {
+ for (int i = 1; i < stat.getStats().size(); i++) {
+ map.put(flatthelper.getMapDestinationNodes().get(stat.getStats().get(i).id)[0], lst.get(i - 1));
+ }
+ }
+
+ for (Statement st : stat.getStats()) {
+ collectCatchVars(st, flatthelper, map);
+ }
+ }
- private static final VarType[] arrtypes = new VarType[] { VarType.VARTYPE_INT, VarType.VARTYPE_LONG, VarType.VARTYPE_FLOAT, VarType.VARTYPE_DOUBLE, VarType.VARTYPE_OBJECT,
- VarType.VARTYPE_BOOLEAN, VarType.VARTYPE_CHAR, VarType.VARTYPE_SHORT };
+ private void initStatementExprents(Statement stat) {
+ stat.initExprents();
- private static final int[] func1 = new int[] { FunctionExprent.FUNCTION_ADD, FunctionExprent.FUNCTION_SUB, FunctionExprent.FUNCTION_MUL, FunctionExprent.FUNCTION_DIV,
- FunctionExprent.FUNCTION_REM };
-
- private static final int[] func2 = new int[] { FunctionExprent.FUNCTION_SHL, FunctionExprent.FUNCTION_SHR, FunctionExprent.FUNCTION_USHR, FunctionExprent.FUNCTION_AND,
- FunctionExprent.FUNCTION_OR, FunctionExprent.FUNCTION_XOR };
-
- private static final int[] func3 = new int[] { FunctionExprent.FUNCTION_I2L, FunctionExprent.FUNCTION_I2F, FunctionExprent.FUNCTION_I2D, FunctionExprent.FUNCTION_L2I,
- FunctionExprent.FUNCTION_L2F, FunctionExprent.FUNCTION_L2D, FunctionExprent.FUNCTION_F2I, FunctionExprent.FUNCTION_F2L, FunctionExprent.FUNCTION_F2D,
- FunctionExprent.FUNCTION_D2I, FunctionExprent.FUNCTION_D2L, FunctionExprent.FUNCTION_D2F, FunctionExprent.FUNCTION_I2B, FunctionExprent.FUNCTION_I2C,
- FunctionExprent.FUNCTION_I2S };
-
- private static final int[] func4 = new int[] { FunctionExprent.FUNCTION_LCMP, FunctionExprent.FUNCTION_FCMPL, FunctionExprent.FUNCTION_FCMPG, FunctionExprent.FUNCTION_DCMPL,
- FunctionExprent.FUNCTION_DCMPG };
-
- private static final int[] func5 = new int[] { IfExprent.IF_EQ, IfExprent.IF_NE, IfExprent.IF_LT, IfExprent.IF_GE, IfExprent.IF_GT, IfExprent.IF_LE };
-
- private static final int[] func6 = new int[] { IfExprent.IF_ICMPEQ, IfExprent.IF_ICMPNE, IfExprent.IF_ICMPLT, IfExprent.IF_ICMPGE, IfExprent.IF_ICMPGT, IfExprent.IF_ICMPLE,
- IfExprent.IF_ACMPEQ, IfExprent.IF_ACMPNE };
-
- private static final int[] func7 = new int[] { IfExprent.IF_NULL, IfExprent.IF_NONNULL };
-
- private static final int[] func8 = new int[] { MonitorExprent.MONITOR_ENTER, MonitorExprent.MONITOR_EXIT };
-
- private static final int[] arr_type = new int[] { CodeConstants.TYPE_BOOLEAN, CodeConstants.TYPE_CHAR, CodeConstants.TYPE_FLOAT, CodeConstants.TYPE_DOUBLE,
- CodeConstants.TYPE_BYTE, CodeConstants.TYPE_SHORT, CodeConstants.TYPE_INT, CodeConstants.TYPE_LONG };
-
- private static final int[] negifs = new int[] { IfExprent.IF_NE, IfExprent.IF_EQ, IfExprent.IF_GE, IfExprent.IF_LT, IfExprent.IF_LE, IfExprent.IF_GT, IfExprent.IF_NONNULL,
- IfExprent.IF_NULL, IfExprent.IF_ICMPNE, IfExprent.IF_ICMPEQ, IfExprent.IF_ICMPGE, IfExprent.IF_ICMPLT, IfExprent.IF_ICMPLE, IfExprent.IF_ICMPGT, IfExprent.IF_ACMPNE,
- IfExprent.IF_ACMPEQ };
-
- private static final String[] typeNames = new String[] { "byte", "char", "double", "float", "int", "long", "short", "boolean", };
-
- private VarProcessor varProcessor = (VarProcessor) DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR);
-
- public void processStatement(RootStatement root, StructClass cl) {
-
- FlattenStatementsHelper flatthelper = new FlattenStatementsHelper();
- DirectGraph dgraph = flatthelper.buildDirectGraph(root);
-
-// try {
-// DotExporter.toDotFile(dgraph, new File("c:\\Temp\\gr12_my.dot"));
-// } catch (Exception ex) {
-// ex.printStackTrace();
-// }
-
- // collect finally entry points
- Set<String> setFinallyShortRangeEntryPoints = new HashSet<String>();
- for (List<FinallyPathWrapper> lst : dgraph.mapShortRangeFinallyPaths.values()) {
- for (FinallyPathWrapper finwrap : lst) {
- setFinallyShortRangeEntryPoints.add(finwrap.entry);
- }
- }
-
- Set<String> setFinallyLongRangeEntryPaths = new HashSet<String>();
- for (List<FinallyPathWrapper> lst : dgraph.mapLongRangeFinallyPaths.values()) {
- for (FinallyPathWrapper finwrap : lst) {
- setFinallyLongRangeEntryPaths.add(finwrap.source + "##" + finwrap.entry);
- }
- }
-
- Map<String, VarExprent> mapCatch = new HashMap<String, VarExprent>();
- collectCatchVars(root, flatthelper, mapCatch);
-
- Map<DirectNode, Map<String, PrimitiveExprsList>> mapData = new HashMap<DirectNode, Map<String, PrimitiveExprsList>>();
-
- LinkedList<DirectNode> stack = new LinkedList<DirectNode>();
- LinkedList<LinkedList<String>> stackEntryPoint = new LinkedList<LinkedList<String>>();
-
- stack.add(dgraph.first);
- stackEntryPoint.add(new LinkedList<String>());
-
- Map<String, PrimitiveExprsList> map = new HashMap<String, PrimitiveExprsList>();
- map.put(null, new PrimitiveExprsList());
- mapData.put(dgraph.first, map);
-
- while (!stack.isEmpty()) {
-
- DirectNode node = stack.removeFirst();
- LinkedList<String> entrypoints = stackEntryPoint.removeFirst();
-
- PrimitiveExprsList data;
- if (mapCatch.containsKey(node.id)) {
- data = getExpressionData(mapCatch.get(node.id));
- } else {
- data = mapData.get(node).get(buildEntryPointKey(entrypoints));
- }
-
- BasicBlockStatement block = node.block;
- if (block != null) {
- processBlock(block, data, cl);
- block.setExprents(data.getLstExprents());
- }
-
- String currentEntrypoint = entrypoints.isEmpty() ? null : entrypoints.getLast();
-
- for (DirectNode nd : node.succs) {
-
- boolean isSuccessor = true;
- if (currentEntrypoint != null && dgraph.mapLongRangeFinallyPaths.containsKey(node.id)) {
- isSuccessor = false;
- for (FinallyPathWrapper finwraplong : dgraph.mapLongRangeFinallyPaths.get(node.id)) {
- if (finwraplong.source.equals(currentEntrypoint) && finwraplong.destination.equals(nd.id)) {
- isSuccessor = true;
- break;
- }
- }
- }
-
- if (isSuccessor) {
-
- Map<String, PrimitiveExprsList> mapSucc = mapData.get(nd);
- if (mapSucc == null) {
- mapData.put(nd, mapSucc = new HashMap<String, PrimitiveExprsList>());
- }
-
- LinkedList<String> ndentrypoints = new LinkedList<String>(entrypoints);
-
- if (setFinallyLongRangeEntryPaths.contains(node.id + "##" + nd.id)) {
- ndentrypoints.addLast(node.id);
- } else if (!setFinallyShortRangeEntryPoints.contains(nd.id) && dgraph.mapLongRangeFinallyPaths.containsKey(node.id)) {
- ndentrypoints.removeLast(); // currentEntrypoint should
- // not be null at this point
- }
-
- // handling of entry point loops
- int succ_entry_index = ndentrypoints.indexOf(nd.id);
- if(succ_entry_index >= 0) { // we are in a loop (e.g. continue in a finally block), drop all entry points in the list beginning with succ_entry_index
- for(int elements_to_remove = ndentrypoints.size() - succ_entry_index; elements_to_remove > 0; elements_to_remove--) {
- ndentrypoints.removeLast();
- }
- }
-
- String ndentrykey = buildEntryPointKey(ndentrypoints);
- if (!mapSucc.containsKey(ndentrykey)) {
-
- mapSucc.put(ndentrykey, copyVarExprents(data.copyStack()));
-
- stack.add(nd);
- stackEntryPoint.add(ndentrypoints);
- }
- }
- }
- }
-
- initStatementExprents(root);
- }
-
- // FIXME: Ugly code, to be rewritten. A tuple class is needed.
- private String buildEntryPointKey(LinkedList<String> entrypoints) {
- if (entrypoints.isEmpty()) {
- return null;
- } else {
- StringBuilder buffer = new StringBuilder();
- for (String point : entrypoints) {
- buffer.append(point);
- buffer.append(":");
- }
- return buffer.toString();
- }
- }
-
- private PrimitiveExprsList copyVarExprents(PrimitiveExprsList data) {
- ExprentStack stack = data.getStack();
- for (int i = 0; i < stack.size(); i++) {
- stack.set(i, stack.get(i).copy());
- }
- return data;
- }
-
- private void collectCatchVars(Statement stat, FlattenStatementsHelper flatthelper, Map<String, VarExprent> map) {
-
- List<VarExprent> lst = null;
-
- if (stat.type == Statement.TYPE_CATCHALL) {
- CatchAllStatement catchall = (CatchAllStatement) stat;
- if (!catchall.isFinally()) {
- lst = catchall.getVars();
- }
- } else if (stat.type == Statement.TYPE_TRYCATCH) {
- lst = ((CatchStatement) stat).getVars();
- }
-
- if (lst != null) {
- for (int i = 1; i < stat.getStats().size(); i++) {
- map.put(flatthelper.getMapDestinationNodes().get(stat.getStats().get(i).id)[0], lst.get(i - 1));
- }
- }
-
- for (Statement st : stat.getStats()) {
- collectCatchVars(st, flatthelper, map);
- }
- }
-
- private void initStatementExprents(Statement stat) {
- stat.initExprents();
-
- for (Statement st : stat.getStats()) {
- initStatementExprents(st);
- }
- }
-
- public void processBlock(BasicBlockStatement stat, PrimitiveExprsList data, StructClass cl) {
-
- ConstantPool pool = cl.getPool();
- StructBootstrapMethodsAttribute bootstrap = (StructBootstrapMethodsAttribute)cl.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_BOOTSTRAP_METHODS);
-
- BasicBlock block = stat.getBlock();
-
- ExprentStack stack = data.getStack();
- List<Exprent> exprlist = data.getLstExprents();
-
- InstructionSequence seq = block.getSeq();
-
- for (int i = 0; i < seq.length(); i++) {
-
- Instruction instr = seq.getInstr(i);
-
- switch (instr.opcode) {
- case opc_aconst_null:
- pushEx(stack, exprlist, new ConstExprent(VarType.VARTYPE_NULL, null));
- break;
- case opc_bipush:
- case opc_sipush:
- pushEx(stack, exprlist, new ConstExprent(instr.getOperand(0), true));
- break;
- case opc_lconst_0:
- case opc_lconst_1:
- pushEx(stack, exprlist, new ConstExprent(VarType.VARTYPE_LONG, new Long(instr.opcode - opc_lconst_0)));
- break;
- case opc_fconst_0:
- case opc_fconst_1:
- case opc_fconst_2:
- pushEx(stack, exprlist, new ConstExprent(VarType.VARTYPE_FLOAT, new Float(instr.opcode - opc_fconst_0)));
- break;
- case opc_dconst_0:
- case opc_dconst_1:
- pushEx(stack, exprlist, new ConstExprent(VarType.VARTYPE_DOUBLE, new Double(instr.opcode - opc_dconst_0)));
- break;
- case opc_ldc:
- case opc_ldc_w:
- case opc_ldc2_w:
- PrimitiveConstant cn = pool.getPrimitiveConstant(instr.getOperand(0));
- pushEx(stack, exprlist, new ConstExprent(consts[cn.type - CONSTANT_Integer], cn.value));
- break;
- case opc_iload:
- case opc_lload:
- case opc_fload:
- case opc_dload:
- case opc_aload:
- pushEx(stack, exprlist, new VarExprent(instr.getOperand(0), vartypes[instr.opcode - opc_iload], varProcessor));
- break;
- case opc_iaload:
- case opc_laload:
- case opc_faload:
- case opc_daload:
- case opc_aaload:
- case opc_baload:
- case opc_caload:
- case opc_saload:
- Exprent index = stack.pop();
- Exprent arr = stack.pop();
-
- VarType vartype = null;
- switch (instr.opcode) {
- case opc_laload:
- vartype = VarType.VARTYPE_LONG;
- break;
- case opc_daload:
- vartype = VarType.VARTYPE_DOUBLE;
- }
- pushEx(stack, exprlist, new ArrayExprent(arr, index, arrtypes[instr.opcode - opc_iaload]), vartype);
- break;
- case opc_istore:
- case opc_lstore:
- case opc_fstore:
- case opc_dstore:
- case opc_astore:
- Exprent top = stack.pop();
- int varindex = instr.getOperand(0);
- AssignmentExprent assign = new AssignmentExprent(new VarExprent(varindex, vartypes[instr.opcode - opc_istore], varProcessor), top);
- exprlist.add(assign);
- break;
- case opc_iastore:
- case opc_lastore:
- case opc_fastore:
- case opc_dastore:
- case opc_aastore:
- case opc_bastore:
- case opc_castore:
- case opc_sastore:
- Exprent value = stack.pop();
- Exprent index_store = stack.pop();
- Exprent arr_store = stack.pop();
- AssignmentExprent arrassign = new AssignmentExprent(new ArrayExprent(arr_store, index_store, arrtypes[instr.opcode - opc_iastore]), value);
- exprlist.add(arrassign);
- break;
- case opc_iadd:
- case opc_ladd:
- case opc_fadd:
- case opc_dadd:
- case opc_isub:
- case opc_lsub:
- case opc_fsub:
- case opc_dsub:
- case opc_imul:
- case opc_lmul:
- case opc_fmul:
- case opc_dmul:
- case opc_idiv:
- case opc_ldiv:
- case opc_fdiv:
- case opc_ddiv:
- case opc_irem:
- case opc_lrem:
- case opc_frem:
- case opc_drem:
- pushEx(stack, exprlist, new FunctionExprent(func1[(instr.opcode - opc_iadd) / 4], stack));
- break;
- case opc_ishl:
- case opc_lshl:
- case opc_ishr:
- case opc_lshr:
- case opc_iushr:
- case opc_lushr:
- case opc_iand:
- case opc_land:
- case opc_ior:
- case opc_lor:
- case opc_ixor:
- case opc_lxor:
- pushEx(stack, exprlist, new FunctionExprent(func2[(instr.opcode - opc_ishl) / 2], stack));
- break;
- case opc_ineg:
- case opc_lneg:
- case opc_fneg:
- case opc_dneg:
- pushEx(stack, exprlist, new FunctionExprent(FunctionExprent.FUNCTION_NEG, stack));
- break;
- case opc_iinc:
- VarExprent vevar = new VarExprent(instr.getOperand(0), VarType.VARTYPE_INT, varProcessor);
- exprlist.add(new AssignmentExprent(vevar, new FunctionExprent(instr.getOperand(1) < 0 ? FunctionExprent.FUNCTION_SUB : FunctionExprent.FUNCTION_ADD, Arrays
- .asList(new Exprent[] { vevar.copy(), new ConstExprent(VarType.VARTYPE_INT, new Integer(Math.abs(instr.getOperand(1)))) }))));
- break;
- case opc_i2l:
- case opc_i2f:
- case opc_i2d:
- case opc_l2i:
- case opc_l2f:
- case opc_l2d:
- case opc_f2i:
- case opc_f2l:
- case opc_f2d:
- case opc_d2i:
- case opc_d2l:
- case opc_d2f:
- case opc_i2b:
- case opc_i2c:
- case opc_i2s:
- pushEx(stack, exprlist, new FunctionExprent(func3[instr.opcode - opc_i2l], stack));
- break;
- case opc_lcmp:
- case opc_fcmpl:
- case opc_fcmpg:
- case opc_dcmpl:
- case opc_dcmpg:
- pushEx(stack, exprlist, new FunctionExprent(func4[instr.opcode - opc_lcmp], stack));
- break;
- case opc_ifeq:
- case opc_ifne:
- case opc_iflt:
- case opc_ifge:
- case opc_ifgt:
- case opc_ifle:
- exprlist.add(new IfExprent(negifs[func5[instr.opcode - opc_ifeq]], stack));
- break;
- case opc_if_icmpeq:
- case opc_if_icmpne:
- case opc_if_icmplt:
- case opc_if_icmpge:
- case opc_if_icmpgt:
- case opc_if_icmple:
- case opc_if_acmpeq:
- case opc_if_acmpne:
- exprlist.add(new IfExprent(negifs[func6[instr.opcode - opc_if_icmpeq]], stack));
- break;
- case opc_ifnull:
- case opc_ifnonnull:
- exprlist.add(new IfExprent(negifs[func7[instr.opcode - opc_ifnull]], stack));
- break;
- case opc_tableswitch:
- case opc_lookupswitch:
- exprlist.add(new SwitchExprent(stack.pop()));
- break;
- case opc_ireturn:
- case opc_lreturn:
- case opc_freturn:
- case opc_dreturn:
- case opc_areturn:
- case opc_return:
- case opc_athrow:
- exprlist.add(new ExitExprent(instr.opcode == opc_athrow ? ExitExprent.EXIT_THROW : ExitExprent.EXIT_RETURN, instr.opcode == opc_return ? null : stack.pop(),
- instr.opcode == opc_athrow ? null : ((MethodDescriptor) DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD_DESCRIPTOR)).ret));
- break;
- case opc_monitorenter:
- case opc_monitorexit:
- exprlist.add(new MonitorExprent(func8[instr.opcode - opc_monitorenter], stack.pop()));
- break;
- case opc_checkcast:
- case opc_instanceof:
- stack.push(new ConstExprent(new VarType(pool.getPrimitiveConstant(instr.getOperand(0)).getString(), true), null));
- case opc_arraylength:
- pushEx(stack, exprlist, new FunctionExprent(mapConsts.get(instr.opcode).intValue(), stack));
- break;
- case opc_getstatic:
- case opc_getfield:
- pushEx(stack, exprlist, new FieldExprent(pool.getLinkConstant(instr.getOperand(0)), instr.opcode == opc_getstatic ? null : stack.pop()));
- break;
- case opc_putstatic:
- case opc_putfield:
- Exprent valfield = stack.pop();
- Exprent exprfield = new FieldExprent(pool.getLinkConstant(instr.getOperand(0)), instr.opcode == opc_putstatic ? null : stack.pop());
- exprlist.add(new AssignmentExprent(exprfield, valfield));
- break;
- case opc_invokevirtual:
- case opc_invokespecial:
- case opc_invokestatic:
- case opc_invokeinterface:
- case opc_invokedynamic:
- if(instr.opcode != opc_invokedynamic || instr.bytecode_version >= CodeConstants.BYTECODE_JAVA_7) {
-
- LinkConstant invoke_constant = pool.getLinkConstant(instr.getOperand(0));
- int dynamic_invokation_type = -1;
-
- if(instr.opcode == opc_invokedynamic && bootstrap != null) {
- List<PooledConstant> bootstrap_arguments = bootstrap.getMethodArguments(invoke_constant.index1);
- LinkConstant content_method_handle = (LinkConstant)bootstrap_arguments.get(1);
-
- dynamic_invokation_type = content_method_handle.index1;
- }
-
- InvocationExprent exprinv = new InvocationExprent(instr.opcode, invoke_constant, stack, dynamic_invokation_type);
- if (exprinv.getDescriptor().ret.type == CodeConstants.TYPE_VOID) {
- exprlist.add(exprinv);
- } else {
- pushEx(stack, exprlist, exprinv);
- }
- }
- break;
- case opc_new:
- case opc_anewarray:
- case opc_multianewarray:
- int arrdims = (instr.opcode == opc_new) ? 0 : (instr.opcode == opc_anewarray) ? 1 : instr.getOperand(1);
- VarType arrtype = new VarType(pool.getPrimitiveConstant(instr.getOperand(0)).getString(), true);
- if (instr.opcode != opc_multianewarray) {
- arrtype.arraydim += arrdims;
- }
- pushEx(stack, exprlist, new NewExprent(arrtype, stack, arrdims));
- break;
- case opc_newarray:
- pushEx(stack, exprlist, new NewExprent(new VarType(arr_type[instr.getOperand(0) - 4], 1), stack, 1));
- break;
- case opc_dup:
- pushEx(stack, exprlist, stack.getByOffset(-1).copy());
- break;
- case opc_dup_x1:
- insertByOffsetEx(-2, stack, exprlist, -1);
- break;
- case opc_dup_x2:
- if (stack.getByOffset(-2).getExprType().stack_size == 2) {
- insertByOffsetEx(-2, stack, exprlist, -1);
- } else {
- insertByOffsetEx(-3, stack, exprlist, -1);
- }
- break;
- case opc_dup2:
- if (stack.getByOffset(-1).getExprType().stack_size == 2) {
- pushEx(stack, exprlist, stack.getByOffset(-1).copy());
- } else {
- pushEx(stack, exprlist, stack.getByOffset(-2).copy());
- pushEx(stack, exprlist, stack.getByOffset(-2).copy());
- }
- break;
- case opc_dup2_x1:
- if (stack.getByOffset(-1).getExprType().stack_size == 2) {
- insertByOffsetEx(-2, stack, exprlist, -1);
- } else {
- insertByOffsetEx(-3, stack, exprlist, -2);
- insertByOffsetEx(-3, stack, exprlist, -1);
- }
- break;
- case opc_dup2_x2:
- if (stack.getByOffset(-1).getExprType().stack_size == 2) {
- if (stack.getByOffset(-2).getExprType().stack_size == 2) {
- insertByOffsetEx(-2, stack, exprlist, -1);
- } else {
- insertByOffsetEx(-3, stack, exprlist, -1);
- }
- } else {
- if (stack.getByOffset(-3).getExprType().stack_size == 2) {
- insertByOffsetEx(-3, stack, exprlist, -2);
- insertByOffsetEx(-3, stack, exprlist, -1);
- } else {
- insertByOffsetEx(-4, stack, exprlist, -2);
- insertByOffsetEx(-4, stack, exprlist, -1);
- }
- }
- break;
- case opc_swap:
- insertByOffsetEx(-2, stack, exprlist, -1);
- stack.pop();
- break;
- case opc_pop:
- case opc_pop2:
- stack.pop();
- }
-
- }
-
- }
-
- private void pushEx(ExprentStack stack, List<Exprent> exprlist, Exprent exprent) {
- pushEx(stack, exprlist, exprent, null);
- }
-
- private void pushEx(ExprentStack stack, List<Exprent> exprlist, Exprent exprent, VarType vartype) {
- int varindex = VarExprent.STACK_BASE + stack.size();
- VarExprent var = new VarExprent(varindex, vartype == null ? exprent.getExprType() : vartype, varProcessor);
- var.setStack(true);
-
- exprlist.add(new AssignmentExprent(var, exprent));
- stack.push(var.copy());
- }
-
- private void insertByOffsetEx(int offset, ExprentStack stack, List<Exprent> exprlist, int copyoffset) {
-
- int base = VarExprent.STACK_BASE + stack.size();
-
- LinkedList<VarExprent> lst = new LinkedList<VarExprent>();
-
- for (int i = -1; i >= offset; i--) {
- Exprent varex = stack.pop();
- VarExprent varnew = new VarExprent(base + i + 1, varex.getExprType(), varProcessor);
- varnew.setStack(true);
- exprlist.add(new AssignmentExprent(varnew, varex));
- lst.add(0, (VarExprent) varnew.copy());
- }
-
- Exprent exprent = lst.get(lst.size() + copyoffset).copy();
- VarExprent var = new VarExprent(base + offset, exprent.getExprType(), varProcessor);
- var.setStack(true);
- exprlist.add(new AssignmentExprent(var, exprent));
- lst.add(0, (VarExprent) var.copy());
-
- for (VarExprent expr : lst) {
- stack.push(expr);
- }
-
- }
-
- public static String getTypeName(VarType type) {
- return getTypeName(type, true);
- }
-
- public static String getTypeName(VarType type, boolean getShort) {
-
- int tp = type.type;
- if (tp <= CodeConstants.TYPE_BOOLEAN) {
- return typeNames[tp];
- } else if (tp == CodeConstants.TYPE_UNKNOWN) {
- return UNKNOWN_TYPE_STRING; // INFO: should not occur
- } else if (tp == CodeConstants.TYPE_NULL) {
- return NULL_TYPE_STRING; // INFO: should not occur
- } else if (tp == CodeConstants.TYPE_VOID) {
- return "void";
- } else if (tp == CodeConstants.TYPE_OBJECT) {
- String ret = ExprProcessor.buildJavaClassName(type.value);
- if (getShort) {
- ret = DecompilerContext.getImpcollector().getShortName(ret);
- }
-
- if (ret == null) {
- // FIXME: a warning should be logged
- ret = UNDEFINED_TYPE_STRING;
- }
- return ret;
- }
-
- throw new RuntimeException("invalid type");
- }
-
- public static String getCastTypeName(VarType type) {
- return getCastTypeName(type, true);
- }
-
- public static String getCastTypeName(VarType type, boolean getShort) {
- String s = getTypeName(type, getShort);
- int dim = type.arraydim;
- while (dim-- > 0) {
- s += "[]";
- }
- return s;
- }
-
- public static PrimitiveExprsList getExpressionData(VarExprent var) {
- PrimitiveExprsList prlst = new PrimitiveExprsList();
- VarExprent vartmp = new VarExprent(VarExprent.STACK_BASE, var.getExprType(), var.getProcessor());
- vartmp.setStack(true);
-
- prlst.getLstExprents().add(new AssignmentExprent(vartmp, var.copy()));
- prlst.getStack().push(vartmp.copy());
- return prlst;
- }
-
- public static boolean endsWithSemikolon(Exprent expr) {
- int type = expr.type;
- return !(type == Exprent.EXPRENT_SWITCH || type == Exprent.EXPRENT_MONITOR || type == Exprent.EXPRENT_IF || (type == Exprent.EXPRENT_VAR && ((VarExprent) expr)
- .isClassdef()));
- }
-
- public static String jmpWrapper(Statement stat, int indent, boolean semicolon) {
- StringBuffer buf = new StringBuffer(stat.toJava(indent));
-
- String new_line_separator = DecompilerContext.getNewLineSeparator();
-
- List<StatEdge> lstSuccs = stat.getSuccessorEdges(Statement.STATEDGE_DIRECT_ALL);
- if (lstSuccs.size() == 1) {
- StatEdge edge = lstSuccs.get(0);
- if (edge.getType() != StatEdge.TYPE_REGULAR && edge.explicit == true && edge.getDestination().type != Statement.TYPE_DUMMYEXIT) {
- buf.append(InterpreterUtil.getIndentString(indent));
-
- switch (edge.getType()) {
- case StatEdge.TYPE_BREAK:
- buf.append("break");
- break;
- case StatEdge.TYPE_CONTINUE:
- buf.append("continue");
- }
-
- if (edge.labeled) {
- buf.append(" label" + edge.closure.id);
- }
- buf.append(";" + new_line_separator);
- }
- }
-
- if (buf.length() == 0 && semicolon) {
- buf.append(InterpreterUtil.getIndentString(indent) + ";" + new_line_separator);
- }
-
- return buf.toString();
- }
-
- public static String buildJavaClassName(String name) {
- String res = name.replace('/', '.');
-
- if (res.indexOf("$") >= 0) { // attempt to invoke foreign member
- // classes correctly
- StructClass cl = DecompilerContext.getStructcontext().getClass(name);
- if (cl == null || !cl.isOwn()) {
- res = res.replace('$', '.');
- }
- }
-
- return res;
- }
-
- public static String listToJava(List<Exprent> lst, int indent) {
+ for (Statement st : stat.getStats()) {
+ initStatementExprents(st);
+ }
+ }
+
+ public void processBlock(BasicBlockStatement stat, PrimitiveExprsList data, StructClass cl) {
+
+ ConstantPool pool = cl.getPool();
+ StructBootstrapMethodsAttribute bootstrap =
+ (StructBootstrapMethodsAttribute)cl.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_BOOTSTRAP_METHODS);
+
+ BasicBlock block = stat.getBlock();
+
+ ExprentStack stack = data.getStack();
+ List<Exprent> exprlist = data.getLstExprents();
+
+ InstructionSequence seq = block.getSeq();
+
+ for (int i = 0; i < seq.length(); i++) {
+
+ Instruction instr = seq.getInstr(i);
+
+ switch (instr.opcode) {
+ case opc_aconst_null:
+ pushEx(stack, exprlist, new ConstExprent(VarType.VARTYPE_NULL, null));
+ break;
+ case opc_bipush:
+ case opc_sipush:
+ pushEx(stack, exprlist, new ConstExprent(instr.getOperand(0), true));
+ break;
+ case opc_lconst_0:
+ case opc_lconst_1:
+ pushEx(stack, exprlist, new ConstExprent(VarType.VARTYPE_LONG, new Long(instr.opcode - opc_lconst_0)));
+ break;
+ case opc_fconst_0:
+ case opc_fconst_1:
+ case opc_fconst_2:
+ pushEx(stack, exprlist, new ConstExprent(VarType.VARTYPE_FLOAT, new Float(instr.opcode - opc_fconst_0)));
+ break;
+ case opc_dconst_0:
+ case opc_dconst_1:
+ pushEx(stack, exprlist, new ConstExprent(VarType.VARTYPE_DOUBLE, new Double(instr.opcode - opc_dconst_0)));
+ break;
+ case opc_ldc:
+ case opc_ldc_w:
+ case opc_ldc2_w:
+ PrimitiveConstant cn = pool.getPrimitiveConstant(instr.getOperand(0));
+ pushEx(stack, exprlist, new ConstExprent(consts[cn.type - CONSTANT_Integer], cn.value));
+ break;
+ case opc_iload:
+ case opc_lload:
+ case opc_fload:
+ case opc_dload:
+ case opc_aload:
+ pushEx(stack, exprlist, new VarExprent(instr.getOperand(0), vartypes[instr.opcode - opc_iload], varProcessor));
+ break;
+ case opc_iaload:
+ case opc_laload:
+ case opc_faload:
+ case opc_daload:
+ case opc_aaload:
+ case opc_baload:
+ case opc_caload:
+ case opc_saload:
+ Exprent index = stack.pop();
+ Exprent arr = stack.pop();
+
+ VarType vartype = null;
+ switch (instr.opcode) {
+ case opc_laload:
+ vartype = VarType.VARTYPE_LONG;
+ break;
+ case opc_daload:
+ vartype = VarType.VARTYPE_DOUBLE;
+ }
+ pushEx(stack, exprlist, new ArrayExprent(arr, index, arrtypes[instr.opcode - opc_iaload]), vartype);
+ break;
+ case opc_istore:
+ case opc_lstore:
+ case opc_fstore:
+ case opc_dstore:
+ case opc_astore:
+ Exprent top = stack.pop();
+ int varindex = instr.getOperand(0);
+ AssignmentExprent assign =
+ new AssignmentExprent(new VarExprent(varindex, vartypes[instr.opcode - opc_istore], varProcessor), top);
+ exprlist.add(assign);
+ break;
+ case opc_iastore:
+ case opc_lastore:
+ case opc_fastore:
+ case opc_dastore:
+ case opc_aastore:
+ case opc_bastore:
+ case opc_castore:
+ case opc_sastore:
+ Exprent value = stack.pop();
+ Exprent index_store = stack.pop();
+ Exprent arr_store = stack.pop();
+ AssignmentExprent arrassign =
+ new AssignmentExprent(new ArrayExprent(arr_store, index_store, arrtypes[instr.opcode - opc_iastore]), value);
+ exprlist.add(arrassign);
+ break;
+ case opc_iadd:
+ case opc_ladd:
+ case opc_fadd:
+ case opc_dadd:
+ case opc_isub:
+ case opc_lsub:
+ case opc_fsub:
+ case opc_dsub:
+ case opc_imul:
+ case opc_lmul:
+ case opc_fmul:
+ case opc_dmul:
+ case opc_idiv:
+ case opc_ldiv:
+ case opc_fdiv:
+ case opc_ddiv:
+ case opc_irem:
+ case opc_lrem:
+ case opc_frem:
+ case opc_drem:
+ pushEx(stack, exprlist, new FunctionExprent(func1[(instr.opcode - opc_iadd) / 4], stack));
+ break;
+ case opc_ishl:
+ case opc_lshl:
+ case opc_ishr:
+ case opc_lshr:
+ case opc_iushr:
+ case opc_lushr:
+ case opc_iand:
+ case opc_land:
+ case opc_ior:
+ case opc_lor:
+ case opc_ixor:
+ case opc_lxor:
+ pushEx(stack, exprlist, new FunctionExprent(func2[(instr.opcode - opc_ishl) / 2], stack));
+ break;
+ case opc_ineg:
+ case opc_lneg:
+ case opc_fneg:
+ case opc_dneg:
+ pushEx(stack, exprlist, new FunctionExprent(FunctionExprent.FUNCTION_NEG, stack));
+ break;
+ case opc_iinc:
+ VarExprent vevar = new VarExprent(instr.getOperand(0), VarType.VARTYPE_INT, varProcessor);
+ exprlist.add(new AssignmentExprent(vevar, new FunctionExprent(
+ instr.getOperand(1) < 0 ? FunctionExprent.FUNCTION_SUB : FunctionExprent.FUNCTION_ADD, Arrays
+ .asList(new Exprent[]{vevar.copy(), new ConstExprent(VarType.VARTYPE_INT, new Integer(Math.abs(instr.getOperand(1))))}))));
+ break;
+ case opc_i2l:
+ case opc_i2f:
+ case opc_i2d:
+ case opc_l2i:
+ case opc_l2f:
+ case opc_l2d:
+ case opc_f2i:
+ case opc_f2l:
+ case opc_f2d:
+ case opc_d2i:
+ case opc_d2l:
+ case opc_d2f:
+ case opc_i2b:
+ case opc_i2c:
+ case opc_i2s:
+ pushEx(stack, exprlist, new FunctionExprent(func3[instr.opcode - opc_i2l], stack));
+ break;
+ case opc_lcmp:
+ case opc_fcmpl:
+ case opc_fcmpg:
+ case opc_dcmpl:
+ case opc_dcmpg:
+ pushEx(stack, exprlist, new FunctionExprent(func4[instr.opcode - opc_lcmp], stack));
+ break;
+ case opc_ifeq:
+ case opc_ifne:
+ case opc_iflt:
+ case opc_ifge:
+ case opc_ifgt:
+ case opc_ifle:
+ exprlist.add(new IfExprent(negifs[func5[instr.opcode - opc_ifeq]], stack));
+ break;
+ case opc_if_icmpeq:
+ case opc_if_icmpne:
+ case opc_if_icmplt:
+ case opc_if_icmpge:
+ case opc_if_icmpgt:
+ case opc_if_icmple:
+ case opc_if_acmpeq:
+ case opc_if_acmpne:
+ exprlist.add(new IfExprent(negifs[func6[instr.opcode - opc_if_icmpeq]], stack));
+ break;
+ case opc_ifnull:
+ case opc_ifnonnull:
+ exprlist.add(new IfExprent(negifs[func7[instr.opcode - opc_ifnull]], stack));
+ break;
+ case opc_tableswitch:
+ case opc_lookupswitch:
+ exprlist.add(new SwitchExprent(stack.pop()));
+ break;
+ case opc_ireturn:
+ case opc_lreturn:
+ case opc_freturn:
+ case opc_dreturn:
+ case opc_areturn:
+ case opc_return:
+ case opc_athrow:
+ exprlist.add(new ExitExprent(instr.opcode == opc_athrow ? ExitExprent.EXIT_THROW : ExitExprent.EXIT_RETURN,
+ instr.opcode == opc_return ? null : stack.pop(),
+ instr.opcode == opc_athrow
+ ? null
+ : ((MethodDescriptor)DecompilerContext
+ .getProperty(DecompilerContext.CURRENT_METHOD_DESCRIPTOR)).ret));
+ break;
+ case opc_monitorenter:
+ case opc_monitorexit:
+ exprlist.add(new MonitorExprent(func8[instr.opcode - opc_monitorenter], stack.pop()));
+ break;
+ case opc_checkcast:
+ case opc_instanceof:
+ stack.push(new ConstExprent(new VarType(pool.getPrimitiveConstant(instr.getOperand(0)).getString(), true), null));
+ case opc_arraylength:
+ pushEx(stack, exprlist, new FunctionExprent(mapConsts.get(instr.opcode).intValue(), stack));
+ break;
+ case opc_getstatic:
+ case opc_getfield:
+ pushEx(stack, exprlist,
+ new FieldExprent(pool.getLinkConstant(instr.getOperand(0)), instr.opcode == opc_getstatic ? null : stack.pop()));
+ break;
+ case opc_putstatic:
+ case opc_putfield:
+ Exprent valfield = stack.pop();
+ Exprent exprfield =
+ new FieldExprent(pool.getLinkConstant(instr.getOperand(0)), instr.opcode == opc_putstatic ? null : stack.pop());
+ exprlist.add(new AssignmentExprent(exprfield, valfield));
+ break;
+ case opc_invokevirtual:
+ case opc_invokespecial:
+ case opc_invokestatic:
+ case opc_invokeinterface:
+ case opc_invokedynamic:
+ if (instr.opcode != opc_invokedynamic || instr.bytecode_version >= CodeConstants.BYTECODE_JAVA_7) {
+
+ LinkConstant invoke_constant = pool.getLinkConstant(instr.getOperand(0));
+ int dynamic_invokation_type = -1;
+
+ if (instr.opcode == opc_invokedynamic && bootstrap != null) {
+ List<PooledConstant> bootstrap_arguments = bootstrap.getMethodArguments(invoke_constant.index1);
+ LinkConstant content_method_handle = (LinkConstant)bootstrap_arguments.get(1);
+
+ dynamic_invokation_type = content_method_handle.index1;
+ }
+
+ InvocationExprent exprinv = new InvocationExprent(instr.opcode, invoke_constant, stack, dynamic_invokation_type);
+ if (exprinv.getDescriptor().ret.type == CodeConstants.TYPE_VOID) {
+ exprlist.add(exprinv);
+ }
+ else {
+ pushEx(stack, exprlist, exprinv);
+ }
+ }
+ break;
+ case opc_new:
+ case opc_anewarray:
+ case opc_multianewarray:
+ int arrdims = (instr.opcode == opc_new) ? 0 : (instr.opcode == opc_anewarray) ? 1 : instr.getOperand(1);
+ VarType arrtype = new VarType(pool.getPrimitiveConstant(instr.getOperand(0)).getString(), true);
+ if (instr.opcode != opc_multianewarray) {
+ arrtype.arraydim += arrdims;
+ }
+ pushEx(stack, exprlist, new NewExprent(arrtype, stack, arrdims));
+ break;
+ case opc_newarray:
+ pushEx(stack, exprlist, new NewExprent(new VarType(arr_type[instr.getOperand(0) - 4], 1), stack, 1));
+ break;
+ case opc_dup:
+ pushEx(stack, exprlist, stack.getByOffset(-1).copy());
+ break;
+ case opc_dup_x1:
+ insertByOffsetEx(-2, stack, exprlist, -1);
+ break;
+ case opc_dup_x2:
+ if (stack.getByOffset(-2).getExprType().stack_size == 2) {
+ insertByOffsetEx(-2, stack, exprlist, -1);
+ }
+ else {
+ insertByOffsetEx(-3, stack, exprlist, -1);
+ }
+ break;
+ case opc_dup2:
+ if (stack.getByOffset(-1).getExprType().stack_size == 2) {
+ pushEx(stack, exprlist, stack.getByOffset(-1).copy());
+ }
+ else {
+ pushEx(stack, exprlist, stack.getByOffset(-2).copy());
+ pushEx(stack, exprlist, stack.getByOffset(-2).copy());
+ }
+ break;
+ case opc_dup2_x1:
+ if (stack.getByOffset(-1).getExprType().stack_size == 2) {
+ insertByOffsetEx(-2, stack, exprlist, -1);
+ }
+ else {
+ insertByOffsetEx(-3, stack, exprlist, -2);
+ insertByOffsetEx(-3, stack, exprlist, -1);
+ }
+ break;
+ case opc_dup2_x2:
+ if (stack.getByOffset(-1).getExprType().stack_size == 2) {
+ if (stack.getByOffset(-2).getExprType().stack_size == 2) {
+ insertByOffsetEx(-2, stack, exprlist, -1);
+ }
+ else {
+ insertByOffsetEx(-3, stack, exprlist, -1);
+ }
+ }
+ else {
+ if (stack.getByOffset(-3).getExprType().stack_size == 2) {
+ insertByOffsetEx(-3, stack, exprlist, -2);
+ insertByOffsetEx(-3, stack, exprlist, -1);
+ }
+ else {
+ insertByOffsetEx(-4, stack, exprlist, -2);
+ insertByOffsetEx(-4, stack, exprlist, -1);
+ }
+ }
+ break;
+ case opc_swap:
+ insertByOffsetEx(-2, stack, exprlist, -1);
+ stack.pop();
+ break;
+ case opc_pop:
+ case opc_pop2:
+ stack.pop();
+ }
+ }
+ }
+
+ private void pushEx(ExprentStack stack, List<Exprent> exprlist, Exprent exprent) {
+ pushEx(stack, exprlist, exprent, null);
+ }
+
+ private void pushEx(ExprentStack stack, List<Exprent> exprlist, Exprent exprent, VarType vartype) {
+ int varindex = VarExprent.STACK_BASE + stack.size();
+ VarExprent var = new VarExprent(varindex, vartype == null ? exprent.getExprType() : vartype, varProcessor);
+ var.setStack(true);
+
+ exprlist.add(new AssignmentExprent(var, exprent));
+ stack.push(var.copy());
+ }
+
+ private void insertByOffsetEx(int offset, ExprentStack stack, List<Exprent> exprlist, int copyoffset) {
+
+ int base = VarExprent.STACK_BASE + stack.size();
+
+ LinkedList<VarExprent> lst = new LinkedList<VarExprent>();
+
+ for (int i = -1; i >= offset; i--) {
+ Exprent varex = stack.pop();
+ VarExprent varnew = new VarExprent(base + i + 1, varex.getExprType(), varProcessor);
+ varnew.setStack(true);
+ exprlist.add(new AssignmentExprent(varnew, varex));
+ lst.add(0, (VarExprent)varnew.copy());
+ }
+
+ Exprent exprent = lst.get(lst.size() + copyoffset).copy();
+ VarExprent var = new VarExprent(base + offset, exprent.getExprType(), varProcessor);
+ var.setStack(true);
+ exprlist.add(new AssignmentExprent(var, exprent));
+ lst.add(0, (VarExprent)var.copy());
+
+ for (VarExprent expr : lst) {
+ stack.push(expr);
+ }
+ }
+
+ public static String getTypeName(VarType type) {
+ return getTypeName(type, true);
+ }
+
+ public static String getTypeName(VarType type, boolean getShort) {
+
+ int tp = type.type;
+ if (tp <= CodeConstants.TYPE_BOOLEAN) {
+ return typeNames[tp];
+ }
+ else if (tp == CodeConstants.TYPE_UNKNOWN) {
+ return UNKNOWN_TYPE_STRING; // INFO: should not occur
+ }
+ else if (tp == CodeConstants.TYPE_NULL) {
+ return NULL_TYPE_STRING; // INFO: should not occur
+ }
+ else if (tp == CodeConstants.TYPE_VOID) {
+ return "void";
+ }
+ else if (tp == CodeConstants.TYPE_OBJECT) {
+ String ret = ExprProcessor.buildJavaClassName(type.value);
+ if (getShort) {
+ ret = DecompilerContext.getImpcollector().getShortName(ret);
+ }
+
+ if (ret == null) {
+ // FIXME: a warning should be logged
+ ret = UNDEFINED_TYPE_STRING;
+ }
+ return ret;
+ }
+
+ throw new RuntimeException("invalid type");
+ }
+
+ public static String getCastTypeName(VarType type) {
+ return getCastTypeName(type, true);
+ }
+
+ public static String getCastTypeName(VarType type, boolean getShort) {
+ String s = getTypeName(type, getShort);
+ int dim = type.arraydim;
+ while (dim-- > 0) {
+ s += "[]";
+ }
+ return s;
+ }
+
+ public static PrimitiveExprsList getExpressionData(VarExprent var) {
+ PrimitiveExprsList prlst = new PrimitiveExprsList();
+ VarExprent vartmp = new VarExprent(VarExprent.STACK_BASE, var.getExprType(), var.getProcessor());
+ vartmp.setStack(true);
+
+ prlst.getLstExprents().add(new AssignmentExprent(vartmp, var.copy()));
+ prlst.getStack().push(vartmp.copy());
+ return prlst;
+ }
+
+ public static boolean endsWithSemikolon(Exprent expr) {
+ int type = expr.type;
+ return !(type == Exprent.EXPRENT_SWITCH ||
+ type == Exprent.EXPRENT_MONITOR ||
+ type == Exprent.EXPRENT_IF ||
+ (type == Exprent.EXPRENT_VAR && ((VarExprent)expr)
+ .isClassdef()));
+ }
+
+ public static String jmpWrapper(Statement stat, int indent, boolean semicolon) {
+ StringBuffer buf = new StringBuffer(stat.toJava(indent));
+
+ String new_line_separator = DecompilerContext.getNewLineSeparator();
+
+ List<StatEdge> lstSuccs = stat.getSuccessorEdges(Statement.STATEDGE_DIRECT_ALL);
+ if (lstSuccs.size() == 1) {
+ StatEdge edge = lstSuccs.get(0);
+ if (edge.getType() != StatEdge.TYPE_REGULAR && edge.explicit == true && edge.getDestination().type != Statement.TYPE_DUMMYEXIT) {
+ buf.append(InterpreterUtil.getIndentString(indent));
+
+ switch (edge.getType()) {
+ case StatEdge.TYPE_BREAK:
+ buf.append("break");
+ break;
+ case StatEdge.TYPE_CONTINUE:
+ buf.append("continue");
+ }
+
+ if (edge.labeled) {
+ buf.append(" label" + edge.closure.id);
+ }
+ buf.append(";" + new_line_separator);
+ }
+ }
+
+ if (buf.length() == 0 && semicolon) {
+ buf.append(InterpreterUtil.getIndentString(indent) + ";" + new_line_separator);
+ }
+
+ return buf.toString();
+ }
+
+ public static String buildJavaClassName(String name) {
+ String res = name.replace('/', '.');
+
+ if (res.indexOf("$") >= 0) { // attempt to invoke foreign member
+ // classes correctly
+ StructClass cl = DecompilerContext.getStructcontext().getClass(name);
+ if (cl == null || !cl.isOwn()) {
+ res = res.replace('$', '.');
+ }
+ }
+
+ return res;
+ }
+
+ public static String listToJava(List<Exprent> lst, int indent) {
if (lst == null || lst.isEmpty()) {
return "";
}
- String indstr = InterpreterUtil.getIndentString(indent);
- String new_line_separator = DecompilerContext.getNewLineSeparator();
-
- StringBuffer buf = new StringBuffer();
-
- for (Exprent expr : lst) {
- String content = expr.toJava(indent);
- if (content.length() > 0) {
- if (expr.type != Exprent.EXPRENT_VAR || !((VarExprent) expr).isClassdef()) {
- buf.append(indstr);
- }
- buf.append(content);
- if (expr.type == Exprent.EXPRENT_MONITOR && ((MonitorExprent) expr).getMontype() == MonitorExprent.MONITOR_ENTER) {
- buf.append("{}"); // empty synchronized block
- }
- if (ExprProcessor.endsWithSemikolon(expr)) {
- buf.append(";");
- }
- buf.append(new_line_separator);
- }
- }
-
- return buf.toString();
- }
-
- public static ConstExprent getDefaultArrayValue(VarType arrtype) {
-
- ConstExprent defaultval;
- if (arrtype.type == CodeConstants.TYPE_OBJECT || arrtype.arraydim > 0) {
- defaultval = new ConstExprent(VarType.VARTYPE_NULL, null);
- } else if (arrtype.type == CodeConstants.TYPE_FLOAT) {
- defaultval = new ConstExprent(VarType.VARTYPE_FLOAT, new Float(0));
- } else if (arrtype.type == CodeConstants.TYPE_LONG) {
- defaultval = new ConstExprent(VarType.VARTYPE_LONG, new Long(0));
- } else if (arrtype.type == CodeConstants.TYPE_DOUBLE) {
- defaultval = new ConstExprent(VarType.VARTYPE_DOUBLE, new Double(0));
- } else { // integer types
- defaultval = new ConstExprent(0, true);
- }
-
- return defaultval;
- }
-
- public static boolean getCastedExprent(Exprent exprent, VarType leftType, StringBuilder buffer, int indent, boolean castNull) {
- return getCastedExprent(exprent, leftType, buffer, indent, castNull, false);
- }
-
- public static boolean getCastedExprent(Exprent exprent, VarType leftType, StringBuilder buffer, int indent, boolean castNull, boolean castAlways) {
-
- boolean ret = false;
- VarType rightType = exprent.getExprType();
-
- String res = exprent.toJava(indent);
-
- boolean cast = !leftType.isSuperset(rightType) && (rightType.equals(VarType.VARTYPE_OBJECT) || leftType.type != CodeConstants.TYPE_OBJECT);
- cast |= castAlways;
-
- if (!cast && castNull && rightType.type == CodeConstants.TYPE_NULL) {
- // check for a nameless anonymous class
- cast = !UNDEFINED_TYPE_STRING.equals(getTypeName(leftType));
- }
- if (!cast) {
- cast = isIntConstant(exprent) && VarType.VARTYPE_INT.isStrictSuperset(leftType);
- }
-
- if (cast) {
- if (exprent.getPrecedence() >= FunctionExprent.getPrecedence(FunctionExprent.FUNCTION_CAST)) {
- res = "(" + res + ")";
- }
-
- res = "(" + ExprProcessor.getCastTypeName(leftType) + ")" + res;
- ret = true;
- }
-
- buffer.append(res);
-
- return ret;
- }
-
- private static boolean isIntConstant(Exprent exprent) {
-
- if (exprent.type == Exprent.EXPRENT_CONST) {
- ConstExprent cexpr = (ConstExprent) exprent;
- switch (cexpr.getConsttype().type) {
- case CodeConstants.TYPE_BYTE:
- case CodeConstants.TYPE_BYTECHAR:
- case CodeConstants.TYPE_SHORT:
- case CodeConstants.TYPE_SHORTCHAR:
- case CodeConstants.TYPE_INT:
- return true;
- }
- }
-
- return false;
- }
+ String indstr = InterpreterUtil.getIndentString(indent);
+ String new_line_separator = DecompilerContext.getNewLineSeparator();
+
+ StringBuffer buf = new StringBuffer();
+
+ for (Exprent expr : lst) {
+ String content = expr.toJava(indent);
+ if (content.length() > 0) {
+ if (expr.type != Exprent.EXPRENT_VAR || !((VarExprent)expr).isClassdef()) {
+ buf.append(indstr);
+ }
+ buf.append(content);
+ if (expr.type == Exprent.EXPRENT_MONITOR && ((MonitorExprent)expr).getMontype() == MonitorExprent.MONITOR_ENTER) {
+ buf.append("{}"); // empty synchronized block
+ }
+ if (ExprProcessor.endsWithSemikolon(expr)) {
+ buf.append(";");
+ }
+ buf.append(new_line_separator);
+ }
+ }
+
+ return buf.toString();
+ }
+
+ public static ConstExprent getDefaultArrayValue(VarType arrtype) {
+
+ ConstExprent defaultval;
+ if (arrtype.type == CodeConstants.TYPE_OBJECT || arrtype.arraydim > 0) {
+ defaultval = new ConstExprent(VarType.VARTYPE_NULL, null);
+ }
+ else if (arrtype.type == CodeConstants.TYPE_FLOAT) {
+ defaultval = new ConstExprent(VarType.VARTYPE_FLOAT, new Float(0));
+ }
+ else if (arrtype.type == CodeConstants.TYPE_LONG) {
+ defaultval = new ConstExprent(VarType.VARTYPE_LONG, new Long(0));
+ }
+ else if (arrtype.type == CodeConstants.TYPE_DOUBLE) {
+ defaultval = new ConstExprent(VarType.VARTYPE_DOUBLE, new Double(0));
+ }
+ else { // integer types
+ defaultval = new ConstExprent(0, true);
+ }
+
+ return defaultval;
+ }
+
+ public static boolean getCastedExprent(Exprent exprent, VarType leftType, StringBuilder buffer, int indent, boolean castNull) {
+ return getCastedExprent(exprent, leftType, buffer, indent, castNull, false);
+ }
+
+ public static boolean getCastedExprent(Exprent exprent,
+ VarType leftType,
+ StringBuilder buffer,
+ int indent,
+ boolean castNull,
+ boolean castAlways) {
+
+ boolean ret = false;
+ VarType rightType = exprent.getExprType();
+
+ String res = exprent.toJava(indent);
+
+ boolean cast =
+ !leftType.isSuperset(rightType) && (rightType.equals(VarType.VARTYPE_OBJECT) || leftType.type != CodeConstants.TYPE_OBJECT);
+ cast |= castAlways;
+
+ if (!cast && castNull && rightType.type == CodeConstants.TYPE_NULL) {
+ // check for a nameless anonymous class
+ cast = !UNDEFINED_TYPE_STRING.equals(getTypeName(leftType));
+ }
+ if (!cast) {
+ cast = isIntConstant(exprent) && VarType.VARTYPE_INT.isStrictSuperset(leftType);
+ }
+
+ if (cast) {
+ if (exprent.getPrecedence() >= FunctionExprent.getPrecedence(FunctionExprent.FUNCTION_CAST)) {
+ res = "(" + res + ")";
+ }
+
+ res = "(" + ExprProcessor.getCastTypeName(leftType) + ")" + res;
+ ret = true;
+ }
+
+ buffer.append(res);
+
+ return ret;
+ }
+
+ private static boolean isIntConstant(Exprent exprent) {
+
+ if (exprent.type == Exprent.EXPRENT_CONST) {
+ ConstExprent cexpr = (ConstExprent)exprent;
+ switch (cexpr.getConsttype().type) {
+ case CodeConstants.TYPE_BYTE:
+ case CodeConstants.TYPE_BYTECHAR:
+ case CodeConstants.TYPE_SHORT:
+ case CodeConstants.TYPE_SHORTCHAR:
+ case CodeConstants.TYPE_INT:
+ return true;
+ }
+ }
+ return false;
+ }
}