KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > bcel > generic > Instruction


1 /*
2  * Copyright 2000-2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */

17 package org.apache.bcel.generic;
18
19 import java.io.DataOutputStream JavaDoc;
20 import java.io.IOException JavaDoc;
21 import java.io.Serializable JavaDoc;
22 import java.util.Locale JavaDoc;
23 import org.apache.bcel.Constants;
24 import org.apache.bcel.classfile.ConstantPool;
25 import org.apache.bcel.util.ByteSequence;
26
27 /**
28  * Abstract super class for all Java byte codes.
29  *
30  * @version $Id: Instruction.java 386056 2006-03-15 11:31:56Z tcurdt $
31  * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
32  */

33 public abstract class Instruction implements Cloneable JavaDoc, Serializable JavaDoc {
34
35     protected short length = 1; // Length of instruction in bytes
36
protected short opcode = -1; // Opcode number
37
private static InstructionComparator cmp = InstructionComparator.DEFAULT;
38
39
40     /**
41      * Empty constructor needed for the Class.newInstance() statement in
42      * Instruction.readInstruction(). Not to be used otherwise.
43      */

44     Instruction() {
45     }
46
47
48     public Instruction(short opcode, short length) {
49         this.length = length;
50         this.opcode = opcode;
51     }
52
53
54     /**
55      * Dump instruction as byte code to stream out.
56      * @param out Output stream
57      */

58     public void dump( DataOutputStream JavaDoc out ) throws IOException JavaDoc {
59         out.writeByte(opcode); // Common for all instructions
60
}
61
62
63     /** @return name of instruction, i.e., opcode name
64      */

65     public String JavaDoc getName() {
66         return Constants.OPCODE_NAMES[opcode];
67     }
68
69
70     /**
71      * Long output format:
72      *
73      * &lt;name of opcode&gt; "["&lt;opcode number&gt;"]"
74      * "("&lt;length of instruction&gt;")"
75      *
76      * @param verbose long/short format switch
77      * @return mnemonic for instruction
78      */

79     public String JavaDoc toString( boolean verbose ) {
80         if (verbose) {
81             return getName() + "[" + opcode + "](" + length + ")";
82         } else {
83             return getName();
84         }
85     }
86
87
88     /**
89      * @return mnemonic for instruction in verbose format
90      */

91     public String JavaDoc toString() {
92         return toString(true);
93     }
94
95
96     /**
97      * @return mnemonic for instruction with sumbolic references resolved
98      */

99     public String JavaDoc toString( ConstantPool cp ) {
100         return toString(false);
101     }
102
103
104     /**
105      * Use with caution, since `BranchInstruction's have a `target' reference which
106      * is not copied correctly (only basic types are). This also applies for
107      * `Select' instructions with their multiple branch targets.
108      *
109      * @see BranchInstruction
110      * @return (shallow) copy of an instruction
111      */

112     public Instruction copy() {
113         Instruction i = null;
114         // "Constant" instruction, no need to duplicate
115
if (InstructionConstants.INSTRUCTIONS[this.getOpcode()] != null) {
116             i = this;
117         } else {
118             try {
119                 i = (Instruction) clone();
120             } catch (CloneNotSupportedException JavaDoc e) {
121                 System.err.println(e);
122             }
123         }
124         return i;
125     }
126
127
128     /**
129      * Read needed data (e.g. index) from file.
130      *
131      * @param bytes byte sequence to read from
132      * @param wide "wide" instruction flag
133      */

134     protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException JavaDoc {
135     }
136
137
138     /**
139      * Read an instruction from (byte code) input stream and return the
140      * appropiate object.
141      *
142      * @param bytes input stream bytes
143      * @return instruction object being read
144      */

145     public static final Instruction readInstruction( ByteSequence bytes ) throws IOException JavaDoc {
146         boolean wide = false;
147         short opcode = (short) bytes.readUnsignedByte();
148         Instruction obj = null;
149         if (opcode == Constants.WIDE) { // Read next opcode after wide byte
150
wide = true;
151             opcode = (short) bytes.readUnsignedByte();
152         }
153         if (InstructionConstants.INSTRUCTIONS[opcode] != null) {
154             return InstructionConstants.INSTRUCTIONS[opcode]; // Used predefined immutable object, if available
155
}
156         /* Find appropiate class, instantiate an (empty) instruction object
157          * and initialize it by hand.
158          */

159         Class JavaDoc clazz;
160         try {
161             clazz = Class.forName(className(opcode));
162         } catch (ClassNotFoundException JavaDoc cnfe) {
163             // If a class by that name does not exist, the opcode is illegal.
164
// Note that IMPDEP1, IMPDEP2, BREAKPOINT are also illegal in a sense.
165
throw new ClassGenException("Illegal opcode detected.");
166         }
167         try {
168             obj = (Instruction) clazz.newInstance();
169             if (wide
170                     && !((obj instanceof LocalVariableInstruction) || (obj instanceof IINC) || (obj instanceof RET))) {
171                 throw new Exception JavaDoc("Illegal opcode after wide: " + opcode);
172             }
173             obj.setOpcode(opcode);
174             obj.initFromFile(bytes, wide); // Do further initializations, if any
175
// Byte code offset set in InstructionList
176
} catch (Exception JavaDoc e) {
177             throw new ClassGenException(e.toString());
178         }
179         return obj;
180     }
181
182
183     private static final String JavaDoc className( short opcode ) {
184         String JavaDoc name = Constants.OPCODE_NAMES[opcode].toUpperCase(Locale.ENGLISH);
185         /* ICONST_0, etc. will be shortened to ICONST, etc., since ICONST_0 and the like
186          * are not implemented (directly).
187          */

188         try {
189             int len = name.length();
190             char ch1 = name.charAt(len - 2), ch2 = name.charAt(len - 1);
191             if ((ch1 == '_') && (ch2 >= '0') && (ch2 <= '5')) {
192                 name = name.substring(0, len - 2);
193             }
194             if (name.equals("ICONST_M1")) {
195                 name = "ICONST";
196             }
197         } catch (StringIndexOutOfBoundsException JavaDoc e) {
198             System.err.println(e);
199         }
200         return "org.apache.bcel.generic." + name;
201     }
202
203
204     /**
205      * This method also gives right results for instructions whose
206      * effect on the stack depends on the constant pool entry they
207      * reference.
208      * @return Number of words consumed from stack by this instruction,
209      * or Constants.UNPREDICTABLE, if this can not be computed statically
210      */

211     public int consumeStack( ConstantPoolGen cpg ) {
212         return Constants.CONSUME_STACK[opcode];
213     }
214
215
216     /**
217      * This method also gives right results for instructions whose
218      * effect on the stack depends on the constant pool entry they
219      * reference.
220      * @return Number of words produced onto stack by this instruction,
221      * or Constants.UNPREDICTABLE, if this can not be computed statically
222      */

223     public int produceStack( ConstantPoolGen cpg ) {
224         return Constants.PRODUCE_STACK[opcode];
225     }
226
227
228     /**
229      * @return this instructions opcode
230      */

231     public short getOpcode() {
232         return opcode;
233     }
234
235
236     /**
237      * @return length (in bytes) of instruction
238      */

239     public int getLength() {
240         return length;
241     }
242
243
244     /**
245      * Needed in readInstruction.
246      */

247     private void setOpcode( short opcode ) {
248         this.opcode = opcode;
249     }
250
251
252     /** Some instructions may be reused, so don't do anything by default.
253      */

254     void dispose() {
255     }
256
257
258     /**
259      * Call corresponding visitor method(s). The order is:
260      * Call visitor methods of implemented interfaces first, then
261      * call methods according to the class hierarchy in descending order,
262      * i.e., the most specific visitXXX() call comes last.
263      *
264      * @param v Visitor object
265      */

266     public abstract void accept( Visitor v );
267
268
269     /** Get Comparator object used in the equals() method to determine
270      * equality of instructions.
271      *
272      * @return currently used comparator for equals()
273      */

274     public static InstructionComparator getComparator() {
275         return cmp;
276     }
277
278
279     /** Set comparator to be used for equals().
280      */

281     public static void setComparator( InstructionComparator c ) {
282         cmp = c;
283     }
284
285
286     /** Check for equality, delegated to comparator
287      * @return true if that is an Instruction and has the same opcode
288      */

289     public boolean equals( Object JavaDoc that ) {
290         return (that instanceof Instruction) ? cmp.equals(this, (Instruction) that) : false;
291     }
292 }
293
Popular Tags