001: package net.sf.jdec.jvminstructions.commands;
002:
003: import java.util.ArrayList;
004:
005: import net.sf.jdec.constantpool.ClassDescription;
006: import net.sf.jdec.constantpool.ClassInfo;
007: import net.sf.jdec.constantpool.InterfaceMethodRef;
008: import net.sf.jdec.constantpool.NameAndType;
009: import net.sf.jdec.core.DecompilerHelper;
010: import net.sf.jdec.core.JvmOpCodes;
011: import net.sf.jdec.core.Operand;
012: import net.sf.jdec.core.OperandStack;
013: import net.sf.jdec.reflection.Behaviour;
014: import net.sf.jdec.util.Util;
015:
016: public class InvokeInterfaceCommand extends AbstractInstructionCommand {
017:
018: public InvokeInterfaceCommand(Behaviour context) {
019: super (context);
020:
021: }
022:
023: public int getSkipBytes() {
024: return 4;
025: }
026:
027: public void execute() {
028: boolean pushed = false;
029: byte[] info = getCode();
030: int i = getCurrentInstPosInCode();
031: int currentForIndex = i;
032: Behaviour behavior = getContext();
033: int classIndex = getGenericFinder().getOffset(i);
034: OperandStack opStack = getStack();
035: i += 2;
036: ClassDescription cd = getContext().getClassRef().getCd();
037: InterfaceMethodRef iref = cd
038: .getInterfaceMethodAtCPoolPosition(classIndex);
039: java.lang.String classname = iref.getClassname();
040: java.lang.String typeofmet = iref.getTypeofmethod();
041: Util.parseDescriptor(typeofmet);
042: ArrayList paramlist = Util.getParsedSignatureAsList();
043: boolean takeret = getStoreFinder().isNextInstAStore(
044: currentForIndex + 5);
045: int s1 = typeofmet.indexOf(")");
046: ArrayList returntype = null;
047:
048: String tempString = "";
049: java.lang.String rettp = "";
050: if (s1 != -1 && s1 + 1 < typeofmet.length()) {
051:
052: rettp = typeofmet.substring(s1 + 1);
053:
054: Util.parseReturnType(rettp);
055: returntype = Util.getreturnSignatureAsList();
056: }
057: java.lang.String pushStr = classname;
058: if (takeret && returntype != null && returntype.size() > 0) {
059: pushStr = (java.lang.String) returntype.get(0);
060: }
061: if (pushStr != null && pushStr.trim().equalsIgnoreCase("void")) {
062: pushStr = classname;
063: }
064:
065: DecompilerHelper.resetMethodParameters(opStack, paramlist,
066: currentForIndex);
067: java.lang.String argumentRetType = "";
068: int br = typeofmet.indexOf(")");
069: if (br != -1) {
070: char c;
071: if (typeofmet.length() >= (br + 1))
072: c = typeofmet.charAt(br + 1);
073: else
074: c = '?';
075: argumentRetType = "" + c;
076:
077: }
078: int nargs = paramlist.size();
079: ClassInfo clazz = cd.getClassInfoAtCPoolPosition(iref
080: .getClassPointer());
081: NameAndType nmtype = cd.getNameAndTypeAtCPoolPosition(iref
082: .getDescriptionPointer());
083: java.lang.String clazzName = cd.getUTF8String(clazz
084: .getUtf8pointer());
085: DecompilerHelper.registerInnerClassIfAny(clazzName.replace('.',
086: '/'));
087: java.lang.String description = cd.getUTF8String(nmtype
088: .getUtf8pointer());
089: int j = i + 1;
090: // int nargs=info[j]-1;
091: Operand allargs[] = new Operand[nargs];
092: int start = 0;
093:
094: int dex = 0;
095: for (int counter = nargs - 1; counter >= 0; counter--) {
096: // boolean boolparam=isParameterTypeBoolean(paramlist,counter);
097: Operand op2 = opStack.getTopOfStack();
098: DecompilerHelper.resetOperandValueIfNecessary(paramlist,
099: counter, op2);
100: allargs[dex++] = op2;
101:
102: }
103: Operand interfaceRef = opStack.getTopOfStack();
104: java.lang.String args = "";
105: java.lang.String bracket = "(";
106: for (int c = (allargs.length - 1); c >= 0; c--) {
107: args += allargs[c].getOperandValue();
108: if (c != 0)
109: args += ",";
110: }
111: if (args.length() > 0) {
112: bracket += args + ")";
113: } else
114: bracket += ")";
115: i++;
116: i++;
117: Operand op1 = new Operand();
118: op1.setOperandValue(interfaceRef.getOperandValue() + "."
119: + description + bracket);
120:
121: op1.setClassType(pushStr);
122: java.lang.String opvalue = (java.lang.String) op1
123: .getOperandValue();
124: if (opvalue.startsWith("\n")) {
125: opvalue = opvalue.trim() + "\n";
126: op1.setOperandValue(opvalue);
127: }
128: if (getStoreFinder().isInstStore0(i + 1)) {
129: pushed = true;
130: opStack.push(op1);
131: } else if (getGenericFinder().isNextInstructionInvokeStatic(
132: (info[i + 1]))
133: || getGenericFinder().isNextInstructionInvokeVirtual(
134: info[i + 1])
135: || getGenericFinder().isNextInstructionInvokeInterface(
136: info[i + 1])
137: || getGenericFinder().isNextInstructionInvokeSpecial(
138: info[i + 1])
139: || getStoreFinder().isNextInstructionStore(i + 1)
140: || getBranchFinder().isNextInstructionIf(info[i + 1])
141: || (info[(i + 1)] == JvmOpCodes.PUTFIELD)
142: || (info[(i + 1)] == JvmOpCodes.PUTSTATIC)) { // TODO need to
143: // check for
144: // other cases
145: // like switch
146:
147: if (argumentRetType.equalsIgnoreCase("V") == false
148: || argumentRetType.equalsIgnoreCase("void") == false) {
149: pushed = true;
150: opStack.push(op1);
151: // op1.setClassType(pushStr);
152: } else {
153: tempString = interfaceRef.getOperandValue() + "."
154: + description + bracket + ";\n";
155: behavior.appendToBuffer(Util
156: .formatDecompiledStatement(tempString));
157: }
158: } else if (getLoadFinder().isNextInstructionLoad(i + 1)) {
159: if (argumentRetType.equalsIgnoreCase("V") == true
160: || argumentRetType.equalsIgnoreCase("void") == true) {
161: tempString = interfaceRef.getOperandValue() + "."
162: + description + bracket + ";\n";
163: behavior.appendToBuffer(Util
164: .formatDecompiledStatement(tempString));
165: } else {
166: pushed = true;
167: opStack.push(op1);
168: // op1.setClassType(pushStr);
169: }
170:
171: } else if (getGenericFinder().isNextInstructionPop(i + 1)
172: || getBranchFinder().isNextInstructionReturn(i + 1)) {
173:
174: tempString = interfaceRef.getOperandValue() + "."
175: + description + bracket + ";\n";
176: behavior.appendToBuffer(Util
177: .formatDecompiledStatement(tempString));
178: opStack.push(op1);
179:
180: } else if (getGenericFinder().isNextInstructionConversionInst(
181: info[i + 1])) {
182: pushed = true;
183: opStack.push(op1);
184:
185: } else if (DecompilerHelper.checkForValueReturn(info, (i + 1))) {
186: pushed = true;
187: opStack.push(op1);
188:
189: } else if (getGenericFinder().checkForSomeSpecificInstructions(
190: info, (i + 1))) {
191: pushed = true;
192: opStack.push(op1);
193: // op1.setClassType(classname);
194: } else {
195: /*
196: * op1=new Operand();
197: * op1.setOperandValue(interfaceRef.getOperandValue()+"."+description+bracket+";\n");
198: * opStack.push(op1);
199: */
200: if (argumentRetType.equalsIgnoreCase("V") == false
201: && argumentRetType.equalsIgnoreCase("void") == false) {
202: opStack.push(op1);
203: pushed = true;
204: // op1.setClassType(classname);
205: } else {
206: tempString = interfaceRef.getOperandValue() + "."
207: + description + bracket + ";\n";
208: behavior.appendToBuffer(Util
209: .formatDecompiledStatement(tempString));
210: }
211: }
212:
213: // TODO check this condition whether it will apply
214: // in all cases . Why only if ot store....Check
215: /*
216: * if(isNextInstructionStore(info[i+1]) ||
217: * isNextInstructionIf(info[i+1])) { op1=new Operand();
218: * op1.setOperandValue(interfaceRef.getOperandValue()+"."+description+bracket+";\n");
219: * opStack.push(op1); } else if(info[i+1] == JvmOpCodes.POP) // TODO:
220: * Handle POP2 { op1=new Operand();
221: * op1.setOperandValue(interfaceRef.getOperandValue()+"."+description+bracket+";\n");
222: * opStack.push(op1);
223: * tempString=interfaceRef.getOperandValue()+"."+description+bracket+";\n";
224: * codeStatements+=Util.formatDecompiledStatement(tempString); } else
225: * if(info[i+1] == JvmOpCodes.CHECKCAST) // TODO: Handle POP2 { op1=new
226: * Operand();
227: * op1.setOperandValue(interfaceRef.getOperandValue()+"."+description+bracket+";\n");
228: * opStack.push(op1); } else {
229: * tempString=interfaceRef.getOperandValue()+"."+description+bracket+";\n";
230: * codeStatements+=Util.formatDecompiledStatement(tempString); }
231: */
232:
233: if (pushed) {
234: boolean r = false;// checkIFLoadInstIsPartOFTernaryCond(currentForIndex);
235: if (r) {
236: if (opStack.size() > 0) {
237: java.lang.String str1 = opStack.getTopOfStack()
238: .getOperandValue();
239: java.lang.String str2 = opStack.getTopOfStack()
240: .getOperandValue();
241: java.lang.String str = str2 + str1;
242: Operand d = createOperand(str);
243: opStack.push(d);
244: }
245: }
246: }
247:
248: }
249:
250: }
|