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 java.io.DataOutputStream;
20 import java.io.IOException;
21
22 import org.apache.bcel.Const;
23 import org.apache.bcel.util.ByteSequence;
24
25
26
27
28 public abstract class LocalVariableInstruction extends Instruction implements TypedInstruction, IndexedInstruction {
29
30
31
32
33 @Deprecated
34 protected int n = -1;
35
36 private short cTag = -1;
37 private short canonTag = -1;
38
39
40
41
42 LocalVariableInstruction() {
43 }
44
45
46
47
48
49 LocalVariableInstruction(final short canonTag, final short cTag) {
50 this.canonTag = canonTag;
51 this.cTag = cTag;
52 }
53
54
55
56
57
58
59 protected LocalVariableInstruction(final short opcode, final short cTag, final int n) {
60 super(opcode, (short) 2);
61 this.cTag = cTag;
62 canonTag = opcode;
63 setIndex(n);
64 }
65
66
67
68
69
70
71 @Override
72 public void dump(final DataOutputStream out) throws IOException {
73 if (wide()) {
74 out.writeByte(Const.WIDE);
75 }
76 out.writeByte(super.getOpcode());
77 if (super.getLength() > 1) {
78 if (wide()) {
79 out.writeShort(n);
80 } else {
81 out.writeByte(n);
82 }
83 }
84 }
85
86
87
88
89 public short getCanonicalTag() {
90 return canonTag;
91 }
92
93
94
95
96 @Override
97 public final int getIndex() {
98 return n;
99 }
100
101
102
103
104
105
106
107
108 @Override
109 public Type getType(final ConstantPoolGen cp) {
110 switch (canonTag) {
111 case Const.ILOAD:
112 case Const.ISTORE:
113 return Type.INT;
114 case Const.LLOAD:
115 case Const.LSTORE:
116 return Type.LONG;
117 case Const.DLOAD:
118 case Const.DSTORE:
119 return Type.DOUBLE;
120 case Const.FLOAD:
121 case Const.FSTORE:
122 return Type.FLOAT;
123 case Const.ALOAD:
124 case Const.ASTORE:
125 return Type.OBJECT;
126 default:
127 throw new ClassGenException("Unknown case in switch" + canonTag);
128 }
129 }
130
131
132
133
134
135
136
137
138 @Override
139 protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException {
140 if (wide) {
141 n = bytes.readUnsignedShort();
142 super.setLength(4);
143 } else {
144 final short opcode = super.getOpcode();
145 if (opcode >= Const.ILOAD && opcode <= Const.ALOAD || opcode >= Const.ISTORE && opcode <= Const.ASTORE) {
146 n = bytes.readUnsignedByte();
147 super.setLength(2);
148 } else {
149 if (opcode <= Const.ALOAD_3) {
150 n = (opcode - Const.ILOAD_0) % 4;
151 } else {
152 n = (opcode - Const.ISTORE_0) % 4;
153 }
154 super.setLength(1);
155 }
156 }
157 }
158
159
160
161
162
163
164 @Override
165 public void setIndex(final int n) {
166 if (n < 0 || n > Const.MAX_SHORT) {
167 throw new ClassGenException("Illegal value: " + n);
168 }
169 this.n = n;
170
171 if (n <= 3) {
172 super.setOpcode((short) (cTag + n));
173 super.setLength(1);
174 } else {
175 super.setOpcode(canonTag);
176 if (wide()) {
177 super.setLength(4);
178 } else {
179 super.setLength(2);
180 }
181 }
182 }
183
184
185
186
187
188
189
190 final void setIndexOnly(final int n) {
191 this.n = n;
192 }
193
194
195
196
197
198
199
200
201
202
203 @Override
204 public String toString(final boolean verbose) {
205 final short opcode = super.getOpcode();
206 if (opcode >= Const.ILOAD_0 && opcode <= Const.ALOAD_3 || opcode >= Const.ISTORE_0 && opcode <= Const.ASTORE_3) {
207 return super.toString(verbose);
208 }
209 return super.toString(verbose) + " " + n;
210 }
211
212 private boolean wide() {
213 return n > Const.MAX_BYTE;
214 }
215 }