1 package org.apache.bcel.generic;
2
3 /* ====================================================================
4 * The Apache Software License, Version 1.1
5 *
6 * Copyright (c) 2001 The Apache Software Foundation. All rights
7 * reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. The end-user documentation included with the redistribution,
22 * if any, must include the following acknowledgment:
23 * "This product includes software developed by the
24 * Apache Software Foundation (http://www.apache.org/)."
25 * Alternately, this acknowledgment may appear in the software itself,
26 * if and wherever such third-party acknowledgments normally appear.
27 *
28 * 4. The names "Apache" and "Apache Software Foundation" and
29 * "Apache BCEL" must not be used to endorse or promote products
30 * derived from this software without prior written permission. For
31 * written permission, please contact apache@apache.org.
32 *
33 * 5. Products derived from this software may not be called "Apache",
34 * "Apache BCEL", nor may "Apache" appear in their name, without
35 * prior written permission of the Apache Software Foundation.
36 *
37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 * ====================================================================
50 *
51 * This software consists of voluntary contributions made by many
52 * individuals on behalf of the Apache Software Foundation. For more
53 * information on the Apache Software Foundation, please see
54 * <http://www.apache.org/>.
55 */
56
57 import org.apache.bcel.Constants;
58 import org.apache.bcel.classfile.Utility;
59 import org.apache.bcel.classfile.ConstantPool;
60 import java.io.*;
61 import org.apache.bcel.util.ByteSequence;
62
63 /***
64 * Abstract super class for all Java byte codes.
65 *
66 * @version $Id: Instruction.java,v 1.3 2002/08/07 18:01:32 mdahm Exp $
67 * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
68 */
69 public abstract class Instruction implements Cloneable, Serializable {
70 protected short length = 1; // Length of instruction in bytes
71 protected short opcode = -1; // Opcode number
72
73 private static InstructionComparator cmp = InstructionComparator.DEFAULT;
74
75 /***
76 * Empty constructor needed for the Class.newInstance() statement in
77 * Instruction.readInstruction(). Not to be used otherwise.
78 */
79 Instruction() {}
80
81 public Instruction(short opcode, short length) {
82 this.length = length;
83 this.opcode = opcode;
84 }
85
86 /***
87 * Dump instruction as byte code to stream out.
88 * @param out Output stream
89 */
90 public void dump(DataOutputStream out) throws IOException {
91 out.writeByte(opcode); // Common for all instructions
92 }
93
94 /*** @return name of instruction, i.e., opcode name
95 */
96 public String getName() {
97 return Constants.OPCODE_NAMES[opcode];
98 }
99
100 /***
101 * Long output format:
102 *
103 * <name of opcode> "["<opcode number>"]"
104 * "("<length of instruction>")"
105 *
106 * @param verbose long/short format switch
107 * @return mnemonic for instruction
108 */
109 public String toString(boolean verbose) {
110 if(verbose)
111 return getName() + "[" + opcode + "](" + length + ")";
112 else
113 return getName();
114 }
115
116 /***
117 * @return mnemonic for instruction in verbose format
118 */
119 public String toString() {
120 return toString(true);
121 }
122
123 /***
124 * @return mnemonic for instruction with sumbolic references resolved
125 */
126 public String toString(ConstantPool cp) {
127 return toString(false);
128 }
129
130 /***
131 * Use with caution, since `BranchInstruction's have a `target' reference which
132 * is not copied correctly (only basic types are). This also applies for
133 * `Select' instructions with their multiple branch targets.
134 *
135 * @see BranchInstruction
136 * @return (shallow) copy of an instruction
137 */
138 public Instruction copy() {
139 Instruction i = null;
140
141 // "Constant" instruction, no need to duplicate
142 if(InstructionConstants.INSTRUCTIONS[this.getOpcode()] != null)
143 i = this;
144 else {
145 try {
146 i = (Instruction)clone();
147 } catch(CloneNotSupportedException e) {
148 System.err.println(e);
149 }
150 }
151
152 return i;
153 }
154
155 /***
156 * Read needed data (e.g. index) from file.
157 *
158 * @param bytes byte sequence to read from
159 * @param wide "wide" instruction flag
160 */
161 protected void initFromFile(ByteSequence bytes, boolean wide)
162 throws IOException
163 {}
164
165 /***
166 * Read an instruction from (byte code) input stream and return the
167 * appropiate object.
168 *
169 * @param file file to read from
170 * @return instruction object being read
171 */
172 public static final Instruction readInstruction(ByteSequence bytes)
173 throws IOException
174 {
175 boolean wide = false;
176 short opcode = (short)bytes.readUnsignedByte();
177 Instruction obj = null;
178
179 if(opcode == Constants.WIDE) { // Read next opcode after wide byte
180 wide = true;
181 opcode = (short)bytes.readUnsignedByte();
182 }
183
184 if(InstructionConstants.INSTRUCTIONS[opcode] != null)
185 return InstructionConstants.INSTRUCTIONS[opcode]; // Used predefined immutable object, if available
186
187 /* Find appropiate class, instantiate an (empty) instruction object
188 * and initialize it by hand.
189 */
190 Class clazz;
191
192 try {
193 clazz = Class.forName(className(opcode));
194 } catch (ClassNotFoundException cnfe){
195 // If a class by that name does not exist, the opcode is illegal.
196 // Note that IMPDEP1, IMPDEP2, BREAKPOINT are also illegal in a sense.
197 throw new ClassGenException("Illegal opcode detected.");
198 }
199
200 try {
201 obj = (Instruction)clazz.newInstance();
202
203 if(wide && !((obj instanceof LocalVariableInstruction) ||
204 (obj instanceof IINC) ||
205 (obj instanceof RET)))
206 throw new Exception("Illegal opcode after wide: " + opcode);
207
208 obj.setOpcode(opcode);
209 obj.initFromFile(bytes, wide); // Do further initializations, if any
210 // Byte code offset set in InstructionList
211 } catch(Exception e) { throw new ClassGenException(e.toString()); }
212
213 return obj;
214 }
215
216 private static final String className(short opcode) {
217 String name = Constants.OPCODE_NAMES[opcode].toUpperCase();
218
219 /* ICONST_0, etc. will be shortened to ICONST, etc., since ICONST_0 and the like
220 * are not implemented (directly).
221 */
222 try {
223 int len = name.length();
224 char ch1 = name.charAt(len - 2), ch2 = name.charAt(len - 1);
225
226 if((ch1 == '_') && (ch2 >= '0') && (ch2 <= '5'))
227 name = name.substring(0, len - 2);
228
229 if(name.equals("ICONST_M1")) // Special case
230 name = "ICONST";
231 } catch(StringIndexOutOfBoundsException e) { System.err.println(e); }
232
233 return "org.apache.bcel.generic." + name;
234 }
235
236 /***
237 * This method also gives right results for instructions whose
238 * effect on the stack depends on the constant pool entry they
239 * reference.
240 * @return Number of words consumed from stack by this instruction,
241 * or Constants.UNPREDICTABLE, if this can not be computed statically
242 */
243 public int consumeStack(ConstantPoolGen cpg) {
244 return Constants.CONSUME_STACK[opcode];
245 }
246
247 /***
248 * This method also gives right results for instructions whose
249 * effect on the stack depends on the constant pool entry they
250 * reference.
251 * @return Number of words produced onto stack by this instruction,
252 * or Constants.UNPREDICTABLE, if this can not be computed statically
253 */
254 public int produceStack(ConstantPoolGen cpg) {
255 return Constants.PRODUCE_STACK[opcode];
256 }
257
258 /***
259 * @return this instructions opcode
260 */
261 public short getOpcode() { return opcode; }
262
263 /***
264 * @return length (in bytes) of instruction
265 */
266 public int getLength() { return length; }
267
268 /***
269 * Needed in readInstruction.
270 */
271 private void setOpcode(short opcode) { this.opcode = opcode; }
272
273 /*** Some instructions may be reused, so don't do anything by default.
274 */
275 void dispose() {}
276
277 /***
278 * Call corresponding visitor method(s). The order is:
279 * Call visitor methods of implemented interfaces first, then
280 * call methods according to the class hierarchy in descending order,
281 * i.e., the most specific visitXXX() call comes last.
282 *
283 * @param v Visitor object
284 */
285 public abstract void accept(Visitor v);
286
287 /*** Get Comparator object used in the equals() method to determine
288 * equality of instructions.
289 *
290 * @return currently used comparator for equals()
291 */
292 public static InstructionComparator getComparator() { return cmp; }
293
294 /*** Set comparator to be used for equals().
295 */
296 public static void setComparator(InstructionComparator c) { cmp = c; }
297
298 /*** Check for equality, delegated to comparator
299 * @return true if that is an Instruction and has the same opcode
300 */
301 public boolean equals(Object that) {
302 return (that instanceof Instruction)?
303 cmp.equals(this, (Instruction)that) : false;
304 }
305 }
This page was automatically generated by Maven