1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.bcel.generic;
18
19 import org.apache.bcel.Constants;
20 import org.apache.bcel.classfile.LocalVariable;
21
22 /***
23 * This class represents a local variable within a method. It contains its
24 * scope, name and type. The generated LocalVariable object can be obtained
25 * with getLocalVariable which needs the instruction list and the constant
26 * pool as parameters.
27 *
28 * @version $Id: LocalVariableGen.java 386056 2006-03-15 11:31:56Z tcurdt $
29 * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
30 * @see LocalVariable
31 * @see MethodGen
32 */
33 public class LocalVariableGen implements InstructionTargeter, NamedAndTyped, Cloneable,
34 java.io.Serializable {
35
36 private int index;
37 private String name;
38 private Type type;
39 private InstructionHandle start, end;
40
41
42 /***
43 * Generate a local variable that with index `index'. Note that double and long
44 * variables need two indexs. Index indices have to be provided by the user.
45 *
46 * @param index index of local variable
47 * @param name its name
48 * @param type its type
49 * @param start from where the instruction is valid (null means from the start)
50 * @param end until where the instruction is valid (null means to the end)
51 */
52 public LocalVariableGen(int index, String name, Type type, InstructionHandle start,
53 InstructionHandle end) {
54 if ((index < 0) || (index > Constants.MAX_SHORT)) {
55 throw new ClassGenException("Invalid index index: " + index);
56 }
57 this.name = name;
58 this.type = type;
59 this.index = index;
60 setStart(start);
61 setEnd(end);
62 }
63
64
65 /***
66 * Get LocalVariable object.
67 *
68 * This relies on that the instruction list has already been dumped to byte code or
69 * or that the `setPositions' methods has been called for the instruction list.
70 *
71 * Note that for local variables whose scope end at the last
72 * instruction of the method's code, the JVM specification is ambiguous:
73 * both a start_pc+length ending at the last instruction and
74 * start_pc+length ending at first index beyond the end of the code are
75 * valid.
76 *
77 * @param cp constant pool
78 */
79 public LocalVariable getLocalVariable( ConstantPoolGen cp ) {
80 int start_pc = start.getPosition();
81 int length = end.getPosition() - start_pc;
82 if (length > 0) {
83 length += end.getInstruction().getLength();
84 }
85 int name_index = cp.addUtf8(name);
86 int signature_index = cp.addUtf8(type.getSignature());
87 return new LocalVariable(start_pc, length, name_index, signature_index, index, cp
88 .getConstantPool());
89 }
90
91
92 public void setIndex( int index ) {
93 this.index = index;
94 }
95
96
97 public int getIndex() {
98 return index;
99 }
100
101
102 public void setName( String name ) {
103 this.name = name;
104 }
105
106
107 public String getName() {
108 return name;
109 }
110
111
112 public void setType( Type type ) {
113 this.type = type;
114 }
115
116
117 public Type getType() {
118 return type;
119 }
120
121
122 public InstructionHandle getStart() {
123 return start;
124 }
125
126
127 public InstructionHandle getEnd() {
128 return end;
129 }
130
131
132 public void setStart( InstructionHandle start ) {
133 BranchInstruction.notifyTarget(this.start, start, this);
134 this.start = start;
135 }
136
137
138 public void setEnd( InstructionHandle end ) {
139 BranchInstruction.notifyTarget(this.end, end, this);
140 this.end = end;
141 }
142
143
144 /***
145 * @param old_ih old target, either start or end
146 * @param new_ih new target
147 */
148 public void updateTarget( InstructionHandle old_ih, InstructionHandle new_ih ) {
149 boolean targeted = false;
150 if (start == old_ih) {
151 targeted = true;
152 setStart(new_ih);
153 }
154 if (end == old_ih) {
155 targeted = true;
156 setEnd(new_ih);
157 }
158 if (!targeted) {
159 throw new ClassGenException("Not targeting " + old_ih + ", but {" + start + ", " + end
160 + "}");
161 }
162 }
163
164
165 /***
166 * @return true, if ih is target of this variable
167 */
168 public boolean containsTarget( InstructionHandle ih ) {
169 return (start == ih) || (end == ih);
170 }
171
172
173 /*** @return a hash code value for the object.
174 */
175 public int hashCode() {
176
177 int hc = index ^ name.hashCode() ^ type.hashCode();
178 return hc;
179 }
180
181
182 /***
183 * We consider to local variables to be equal, if the use the same index and
184 * are valid in the same range.
185 */
186 public boolean equals( Object o ) {
187 if (!(o instanceof LocalVariableGen)) {
188 return false;
189 }
190 LocalVariableGen l = (LocalVariableGen) o;
191 return (l.index == index) && (l.start == start) && (l.end == end);
192 }
193
194
195 public String toString() {
196 return "LocalVariableGen(" + name + ", " + type + ", " + start + ", " + end + ")";
197 }
198
199
200 public Object clone() {
201 try {
202 return super.clone();
203 } catch (CloneNotSupportedException e) {
204 System.err.println(e);
205 return null;
206 }
207 }
208 }