package cmd;
import clz.ClassFile;
import constant.ClassInfo;
import java.util.ArrayList;
import java.util.List;
/**
* Created by william on 2017/4/17.
*/
public class CommandParser {
public static final String aconst_null = "01";
public static final String new_object = "BB";
public static final String lstore = "37";
public static final String invokespecial = "B7";
public static final String invokevirtual = "B6";
public static final String getfield = "B4";
public static final String putfield = "B5";
public static final String getstatic = "B2";
public static final String ldc = "12";
public static final String dup = "59";
public static final String bipush = "10";
public static final String aload_0 = "2A";
public static final String aload_1 = "2B";
public static final String aload_2 = "2C";
public static final String iload = "15";
public static final String iload_1 = "1B";
public static final String iload_2 = "1C";
public static final String iload_3 = "1D";
public static final String fload_3 = "25";
public static final String voidreturn = "B1";
public static final String ireturn = "AC";
public static final String freturn = "AE";
public static final String astore_1 = "4C";
public static final String if_icmp_ge = "A2";
public static final String if_icmple = "A4";
public static final String goto_no_condition = "A7";
public static final String iconst_0 = "03";
public static final String iconst_1 = "04";
public static final String istore_1 = "3C";
public static final String istore_2 = "3D";
public static final String iadd = "60";
public static final String iinc = "84";
public static ByteCodeCommand[] parse(ClassFile clzFile, String codes) {
CommandIterator commandIterator = new CommandIterator(codes);
List<ByteCodeCommand> commandList = new ArrayList<ByteCodeCommand>();
while (commandIterator.hasNext()) {
String command = commandIterator.next2CharAsString().toUpperCase();
if (command.equals(aconst_null)) {
NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, command);
noOperandCmd.setOffset(noOperandCmd.getLength());
commandList.add(noOperandCmd);
} else if (command.equals(new_object)) {
NewObjectCmd newObjectCmd = new NewObjectCmd(clzFile, command);
newObjectCmd.setOprand1(commandIterator.next2CharAsInt());
newObjectCmd.setOprand2(commandIterator.next2CharAsInt());
newObjectCmd.setOffset(newObjectCmd.getLength());
commandList.add(newObjectCmd);
} else if (command.equals(lstore)) {
} else if (command.equals(invokespecial)) {
InvokeSpecialCmd invokeSpecialCmd = new InvokeSpecialCmd(clzFile, command);
invokeSpecialCmd.setOprand1(commandIterator.next2CharAsInt());
invokeSpecialCmd.setOprand2(commandIterator.next2CharAsInt());
invokeSpecialCmd.setOffset(invokeSpecialCmd.getLength());
commandList.add(invokeSpecialCmd);
} else if (command.equals(invokevirtual)) {
InvokeVirtualCmd invokeVirtualCmd = new InvokeVirtualCmd(clzFile, command);
invokeVirtualCmd.setOprand1(commandIterator.next2CharAsInt());
invokeVirtualCmd.setOprand2(commandIterator.next2CharAsInt());
invokeVirtualCmd.setOffset(invokeVirtualCmd.getLength());
commandList.add(invokeVirtualCmd);
} else if (command.equals(getfield)) {
GetFieldCmd getFieldCmd = new GetFieldCmd(clzFile, command);
getFieldCmd.setOprand1(commandIterator.next2CharAsInt());
getFieldCmd.setOprand2(commandIterator.next2CharAsInt());
getFieldCmd.setOffset(getFieldCmd.getLength());
commandList.add(getFieldCmd);
} else if (command.equals(putfield)) {
PutFieldCmd putFieldCmd = new PutFieldCmd(clzFile, command);
putFieldCmd.setOprand1(commandIterator.next2CharAsInt());
putFieldCmd.setOprand2(commandIterator.next2CharAsInt());
putFieldCmd.setOffset(putFieldCmd.getLength());
commandList.add(putFieldCmd);
} else if (command.equals(getstatic)) {
GetStaticFieldCmd getStaticFieldCmd = new GetStaticFieldCmd(clzFile, command);
getStaticFieldCmd.setOprand1(commandIterator.next2CharAsInt());
getStaticFieldCmd.setOprand2(commandIterator.next2CharAsInt());
getStaticFieldCmd.setOffset(getStaticFieldCmd.getLength());
commandList.add(getStaticFieldCmd);
} else if (command.equals(ldc)) {
LdcCmd ldcCmd = new LdcCmd(clzFile, command);
ldcCmd.setOperand(commandIterator.next2CharAsInt());
ldcCmd.setOffset(ldcCmd.getLength());
commandList.add(ldcCmd);
} else if (command.equals(dup)) {
NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, command);
noOperandCmd.setOffset(noOperandCmd.getLength());
commandList.add(noOperandCmd);
} else if (command.equals(bipush)) {
BiPushCmd biPushCmd = new BiPushCmd(clzFile, command);
biPushCmd.setOperand(commandIterator.next2CharAsInt());
biPushCmd.setOffset(biPushCmd.getLength());
commandList.add(biPushCmd);
} else if (command.equals(aload_0)) {
NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, command);
noOperandCmd.setOffset(noOperandCmd.getLength());
commandList.add(noOperandCmd);
} else if (command.equals(aload_1)) {
NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, command);
noOperandCmd.setOffset(noOperandCmd.getLength());
commandList.add(noOperandCmd);
} else if (command.equals(aload_2)) {
NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, command);
noOperandCmd.setOffset(noOperandCmd.getLength());
commandList.add(noOperandCmd);
} else if (command.equals(iload)) {
} else if (command.equals(iload_2)) {
NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, command);
noOperandCmd.setOffset(noOperandCmd.getLength());
commandList.add(noOperandCmd);
} else if (command.equals(iload_1)) {
NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, command);
noOperandCmd.setOffset(noOperandCmd.getLength());
commandList.add(noOperandCmd);
} else if (command.equals(iload_3)) {
NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, command);
noOperandCmd.setOffset(noOperandCmd.getLength());
commandList.add(noOperandCmd);
} else if (command.equals(fload_3)) {
} else if (command.equals(voidreturn)) {
NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, command);
noOperandCmd.setOffset(noOperandCmd.getLength());
commandList.add(noOperandCmd);
} else if (command.equals(ireturn)) {
} else if (command.equals(freturn)) {
} else if (command.equals(astore_1)) {
NoOperandCmd noOperandCmd = new NoOperandCmd(clzFile, command);
noOperandCmd.setOffset(noOperandCmd.getLength());
commandList.add(noOperandCmd);
} else if (command.equals(if_icmp_ge)) {
} else if (command.equals(if_icmple)) {
} else if (command.equals(goto_no_condition)) {
} else if (command.equals(iconst_0)) {
} else if (command.equals(iconst_1)) {
} else if (command.equals(istore_1)) {
} else if (command.equals(istore_2)) {
} else if (command.equals(iadd)) {
} else if (command.equals(iinc)) {
} else {
throw new RuntimeException("wrong command : " + command);
}
}
calcuateOffset(commandList);
return commandList.toArray(new ByteCodeCommand[commandList.size()]);
}
private static void calcuateOffset(List<ByteCodeCommand> cmds) {
int offset = 0;
for (ByteCodeCommand cmd : cmds) {
cmd.setOffset(offset);
offset += cmd.getLength();
}
}
private static class CommandIterator {
String codes = null;
int pos = 0;
CommandIterator(String codes) {
this.codes = codes;
}
public boolean hasNext() {
return pos < this.codes.length();
}
/**
* 从字符串中截取前两个字符
*
* @return
*/
public String next2CharAsString() {
String result = codes.substring(pos, pos + 2);
pos += 2;
return result;
}
public int next2CharAsInt() {
String s = this.next2CharAsString();
return Integer.valueOf(s, 16).intValue();
}
}
}