KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > bcel > internal > generic > Select


1 package com.sun.org.apache.bcel.internal.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 import java.io.*;
57 import com.sun.org.apache.bcel.internal.util.ByteSequence;
58
59 /**
60  * Select - Abstract super class for LOOKUPSWITCH and TABLESWITCH instructions.
61  *
62  * @version $Id: Select.java,v 1.1.1.1 2001/10/29 20:00:27 jvanzyl Exp $
63  * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
64  * @see LOOKUPSWITCH
65  * @see TABLESWITCH
66  * @see InstructionList
67  */

68 public abstract class Select extends BranchInstruction
69   implements VariableLengthInstruction, StackProducer
70 {
71   protected int[] match; // matches, i.e., case 1: ...
72
protected int[] indices; // target offsets
73
protected InstructionHandle[] targets; // target objects in instruction list
74
protected int fixed_length; // fixed length defined by subclasses
75
protected int match_length; // number of cases
76
protected int padding = 0; // number of pad bytes for alignment
77

78   /**
79    * Empty constructor needed for the Class.newInstance() statement in
80    * Instruction.readInstruction(). Not to be used otherwise.
81    */

82   Select() {}
83
84   /**
85    * (Match, target) pairs for switch.
86    * `Match' and `targets' must have the same length of course.
87    *
88    * @param match array of matching values
89    * @param targets instruction targets
90    * @param target default instruction target
91    */

92   Select(short opcode, int[] match, InstructionHandle[] targets,
93      InstructionHandle target) {
94     super(opcode, target);
95
96     this.targets = targets;
97     for(int i=0; i < targets.length; i++)
98       notifyTarget(null, targets[i], this);
99
100     this.match = match;
101
102     if((match_length = match.length) != targets.length)
103       throw new ClassGenException("Match and target array have not the same length");
104
105     indices = new int[match_length];
106   }
107
108   /**
109    * Since this is a variable length instruction, it may shift the following
110    * instructions which then need to update their position.
111    *
112    * Called by InstructionList.setPositions when setting the position for every
113    * instruction. In the presence of variable length instructions `setPositions'
114    * performs multiple passes over the instruction list to calculate the
115    * correct (byte) positions and offsets by calling this function.
116    *
117    * @param offset additional offset caused by preceding (variable length) instructions
118    * @param max_offset the maximum offset that may be caused by these instructions
119    * @return additional offset caused by possible change of this instruction's length
120    */

121   protected int updatePosition(int offset, int max_offset) {
122     position += offset; // Additional offset caused by preceding SWITCHs, GOTOs, etc.
123

124     short old_length = length;
125
126     /* Alignment on 4-byte-boundary, + 1, because of tag byte.
127      */

128     padding = (4 - ((position + 1) % 4)) % 4;
129     length = (short)(fixed_length + padding); // Update length
130

131     return length - old_length;
132   }
133
134   /**
135    * Dump instruction as byte code to stream out.
136    * @param out Output stream
137    */

138   public void dump(DataOutputStream out) throws IOException {
139     out.writeByte(opcode);
140
141     for(int i=0; i < padding; i++) // Padding bytes
142
out.writeByte(0);
143
144     index = getTargetOffset(); // Write default target offset
145
out.writeInt(index);
146   }
147
148   /**
149    * Read needed data (e.g. index) from file.
150    */

151   protected void initFromFile(ByteSequence bytes, boolean wide) throws IOException
152   {
153     padding = (4 - (bytes.getIndex() % 4)) % 4; // Compute number of pad bytes
154

155     for(int i=0; i < padding; i++) {
156       byte b;
157       if((b=bytes.readByte()) != 0)
158     throw new ClassGenException("Padding byte != 0: " + b);
159     }
160     
161     // Default branch target common for both cases (TABLESWITCH, LOOKUPSWITCH)
162
index = bytes.readInt();
163   }
164
165   /**
166    * @return mnemonic for instruction
167    */

168   public String JavaDoc toString(boolean verbose) {
169     StringBuffer JavaDoc buf = new StringBuffer JavaDoc(super.toString(verbose));
170
171     if(verbose) {
172       for(int i=0; i < match_length; i++) {
173     String JavaDoc s = "null";
174     
175     if(targets[i] != null)
176       s = targets[i].getInstruction().toString();
177     
178     buf.append("(" + match[i] + ", " + s + " = {" + indices[i] + "})");
179       }
180     }
181     else
182       buf.append(" ...");
183     
184     return buf.toString();
185   }
186
187   /**
188    * Set branch target for `i'th case
189    */

190   public void setTarget(int i, InstructionHandle target) {
191     notifyTarget(targets[i], target, this);
192     targets[i] = target;
193   }
194
195   /**
196    * @param old_ih old target
197    * @param new_ih new target
198    */

199   public void updateTarget(InstructionHandle old_ih, InstructionHandle new_ih) {
200     boolean targeted = false;
201
202     if(target == old_ih) {
203       targeted = true;
204       setTarget(new_ih);
205     }
206
207     for(int i=0; i < targets.length; i++) {
208       if(targets[i] == old_ih) {
209     targeted = true;
210     setTarget(i, new_ih);
211       }
212     }
213     
214     if(!targeted)
215       throw new ClassGenException("Not targeting " + old_ih);
216   }
217
218   /**
219    * @return true, if ih is target of this instruction
220    */

221   public boolean containsTarget(InstructionHandle ih) {
222     if(target == ih)
223       return true;
224
225     for(int i=0; i < targets.length; i++)
226       if(targets[i] == ih)
227     return true;
228
229     return false;
230   }
231
232   /**
233    * Inform targets that they're not targeted anymore.
234    */

235   void dispose() {
236     super.dispose();
237
238     for(int i=0; i < targets.length; i++)
239       targets[i].removeTargeter(this);
240   }
241
242   /**
243    * @return array of match indices
244    */

245   public int[] getMatchs() { return match; }
246
247   /**
248    * @return array of match target offsets
249    */

250   public int[] getIndices() { return indices; }
251
252   /**
253    * @return array of match targets
254    */

255   public InstructionHandle[] getTargets() { return targets; }
256 }
257
Popular Tags