00001 package de.fub.bytecode.generic;
00002
00003 import de.fub.bytecode.Constants;
00004 import de.fub.bytecode.classfile.Utility;
00005 import de.fub.bytecode.classfile.ConstantPool;
00006 import java.io.*;
00007 import de.fub.bytecode.util.ByteSequence;
00008 import java.util.*;
00009
00010
00011
00012
00013
00014
00015
00016 public abstract class Instruction implements Cloneable, Serializable {
00017 protected short length = 1;
00018 protected short tag = -1;
00019
00020
00021
00022
00023
00024 Instruction() {}
00025 public Instruction(short tag, short length) {
00026 this.length = length;
00027 this.tag = tag;
00028 }
00029
00030
00031
00032
00033
00034
00035
00036
00037 public abstract void accept(Visitor v);
00038 private static final String className(short tag) {
00039 String name = Constants.OPCODE_NAMES[tag].toUpperCase();
00040
00041
00042
00043
00044 try {
00045 int len = name.length();
00046 char ch1 = name.charAt(len - 2), ch2 = name.charAt(len - 1);
00047
00048 if((ch1 == '_') && (ch2 >= '0') && (ch2 <= '5'))
00049 name = name.substring(0, len - 2);
00050
00051 if(name.equals("ICONST_M1"))
00052 name = "ICONST";
00053 } catch(StringIndexOutOfBoundsException e) { System.err.println(e); }
00054
00055 return "de.fub.bytecode.generic." + name;
00056 }
00057
00058
00059
00060 public int consumeStack() { return Constants.CONSUME_STACK[tag]; }
00061
00062
00063
00064
00065
00066 public int consumeStack(ConstantPoolGen cpg) {
00067 return consumeStack();
00068 }
00069
00070
00071
00072
00073
00074
00075
00076
00077 public Instruction copy() {
00078 Instruction i = null;
00079
00080 try {
00081 i = (Instruction)clone();
00082 } catch(CloneNotSupportedException e) {
00083 System.err.println(e);
00084 }
00085
00086 return i;
00087 }
00088
00089
00090 void dispose() { }
00091
00092
00093
00094
00095 public void dump(DataOutputStream out) throws IOException {
00096 out.writeByte(tag);
00097 }
00098
00099
00100
00101 public int getLength() { return length; }
00102
00103
00104
00105 public short getTag() { return tag; }
00106
00107
00108
00109
00110
00111
00112 protected void initFromFile(ByteSequence bytes, boolean wide)
00113 throws IOException
00114 {}
00115
00116
00117
00118 public int produceStack() { return Constants.PRODUCE_STACK[tag]; }
00119
00120
00121
00122
00123
00124 public int produceStack(ConstantPoolGen cpg) {
00125 return produceStack();
00126 }
00127
00128
00129
00130
00131
00132
00133
00134 public static final Instruction readInstruction(ByteSequence bytes)
00135 throws IOException
00136 {
00137 boolean wide = false;
00138 short tag = (short)bytes.readUnsignedByte();
00139 Instruction obj = null;
00140
00141 if(tag == Constants.WIDE) {
00142 wide = true;
00143 tag = (short)bytes.readUnsignedByte();
00144 }
00145
00146 if(InstructionConstants.INSTRUCTIONS[tag] != null)
00147 return InstructionConstants.INSTRUCTIONS[tag];
00148
00149
00150
00151
00152 try {
00153 Class clazz = Class.forName(className(tag));
00154 obj = (Instruction)clazz.newInstance();
00155
00156 if(wide && !((obj instanceof LocalVariableInstruction) || (obj instanceof IINC) ||
00157 (obj instanceof RET)))
00158 throw new Exception("Illegal opcode after wide: " + tag);
00159
00160 obj.setTag(tag);
00161 obj.initFromFile(bytes, wide);
00162
00163 } catch(Exception e) { throw new ClassGenException(e.toString()); }
00164
00165 return obj;
00166 }
00167
00168
00169
00170 private void setTag(short tag) { this.tag = tag; }
00171
00172
00173
00174 public String toString() {
00175 return toString(true);
00176 }
00177
00178
00179
00180 public String toString(ConstantPool cp) {
00181 return toString(false);
00182 }
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 public String toString(boolean verbose) {
00193 if(verbose)
00194 return Constants.OPCODE_NAMES[tag] + "[" + tag + "](" + length + ")";
00195 else
00196 return Constants.OPCODE_NAMES[tag];
00197 }
00198 }