1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18 package org.apache.bcel.classfile;
19
20 import java.io.DataInputStream;
21 import java.io.DataOutputStream;
22 import java.io.IOException;
23 import org.apache.bcel.Constants;
24
25 /**
26 * This class represents colection of local variables in a
27 * method. This attribute is contained in the <em>Code</em> attribute.
28 *
29 * @version $Id: LocalVariableTable.java 1152306 2011-07-29 17:22:24Z sebb $
30 * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
31 * @see Code
32 * @see LocalVariable
33 */
34 public class LocalVariableTable extends Attribute {
35
36 private static final long serialVersionUID = 6780929007774637689L;
37 private int local_variable_table_length; // Table of local
38 private LocalVariable[] local_variable_table; // variables
39
40
41 /**
42 * Initialize from another object. Note that both objects use the same
43 * references (shallow copy). Use copy() for a physical copy.
44 */
45 public LocalVariableTable(LocalVariableTable c) {
46 this(c.getNameIndex(), c.getLength(), c.getLocalVariableTable(), c.getConstantPool());
47 }
48
49
50 /**
51 * @param name_index Index in constant pool to `LocalVariableTable'
52 * @param length Content length in bytes
53 * @param local_variable_table Table of local variables
54 * @param constant_pool Array of constants
55 */
56 public LocalVariableTable(int name_index, int length, LocalVariable[] local_variable_table,
57 ConstantPool constant_pool) {
58 super(Constants.ATTR_LOCAL_VARIABLE_TABLE, name_index, length, constant_pool);
59 setLocalVariableTable(local_variable_table);
60 }
61
62
63 /**
64 * Construct object from file stream.
65 * @param name_index Index in constant pool
66 * @param length Content length in bytes
67 * @param file Input stream
68 * @param constant_pool Array of constants
69 * @throws IOException
70 */
71 LocalVariableTable(int name_index, int length, DataInputStream file, ConstantPool constant_pool)
72 throws IOException {
73 this(name_index, length, (LocalVariable[]) null, constant_pool);
74 local_variable_table_length = (file.readUnsignedShort());
75 local_variable_table = new LocalVariable[local_variable_table_length];
76 for (int i = 0; i < local_variable_table_length; i++) {
77 local_variable_table[i] = new LocalVariable(file, constant_pool);
78 }
79 }
80
81
82 /**
83 * Called by objects that are traversing the nodes of the tree implicitely
84 * defined by the contents of a Java class. I.e., the hierarchy of methods,
85 * fields, attributes, etc. spawns a tree of objects.
86 *
87 * @param v Visitor object
88 */
89 @Override
90 public void accept( Visitor v ) {
91 v.visitLocalVariableTable(this);
92 }
93
94
95 /**
96 * Dump local variable table attribute to file stream in binary format.
97 *
98 * @param file Output file stream
99 * @throws IOException
100 */
101 @Override
102 public final void dump( DataOutputStream file ) throws IOException {
103 super.dump(file);
104 file.writeShort(local_variable_table_length);
105 for (int i = 0; i < local_variable_table_length; i++) {
106 local_variable_table[i].dump(file);
107 }
108 }
109
110
111 /**
112 * @return Array of local variables of method.
113 */
114 public final LocalVariable[] getLocalVariableTable() {
115 return local_variable_table;
116 }
117
118
119 /**
120 *
121 * @param index the variable slot
122 *
123 * @return the first LocalVariable that matches the slot or null if not found
124 *
125 * @deprecated since 5.2 because multiple variables can share the
126 * same slot, use getLocalVariable(int index, int pc) instead.
127 */
128 @java.lang.Deprecated
129 public final LocalVariable getLocalVariable( int index ) {
130 for (int i = 0; i < local_variable_table_length; i++) {
131 if (local_variable_table[i].getIndex() == index) {
132 return local_variable_table[i];
133 }
134 }
135 return null;
136 }
137
138
139 /**
140 *
141 * @param index the variable slot
142 * @param pc the current pc that this variable is alive
143 *
144 * @return the LocalVariable that matches or null if not found
145 */
146 public final LocalVariable getLocalVariable( int index, int pc ) {
147 for (int i = 0; i < local_variable_table_length; i++) {
148 if (local_variable_table[i].getIndex() == index) {
149 int start_pc = local_variable_table[i].getStartPC();
150 int end_pc = start_pc + local_variable_table[i].getLength();
151 if ((pc >= start_pc) && (pc <= end_pc)) {
152 return local_variable_table[i];
153 }
154 }
155 }
156 return null;
157 }
158
159
160 public final void setLocalVariableTable( LocalVariable[] local_variable_table ) {
161 this.local_variable_table = local_variable_table;
162 local_variable_table_length = (local_variable_table == null)
163 ? 0
164 : local_variable_table.length;
165 }
166
167
168 /**
169 * @return String representation.
170 */
171 @Override
172 public final String toString() {
173 StringBuilder buf = new StringBuilder();
174 for (int i = 0; i < local_variable_table_length; i++) {
175 buf.append(local_variable_table[i].toString());
176 if (i < local_variable_table_length - 1) {
177 buf.append('\n');
178 }
179 }
180 return buf.toString();
181 }
182
183
184 /**
185 * @return deep copy of this attribute
186 */
187 @Override
188 public Attribute copy( ConstantPool _constant_pool ) {
189 LocalVariableTable c = (LocalVariableTable) clone();
190 c.local_variable_table = new LocalVariable[local_variable_table_length];
191 for (int i = 0; i < local_variable_table_length; i++) {
192 c.local_variable_table[i] = local_variable_table[i].copy();
193 }
194 c.constant_pool = _constant_pool;
195 return c;
196 }
197
198
199 public final int getTableLength() {
200 return local_variable_table_length;
201 }
202 }