001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 */
018 package org.apache.bcel.classfile;
019
020 import java.io.DataInputStream;
021 import java.io.DataOutputStream;
022 import java.io.IOException;
023 import org.apache.bcel.Constants;
024
025 /**
026 * This class represents colection of local variables in a
027 * method. This attribute is contained in the <em>Code</em> attribute.
028 *
029 * @version $Id: LocalVariableTable.java 1152306 2011-07-29 17:22:24Z sebb $
030 * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
031 * @see Code
032 * @see LocalVariable
033 */
034 public class LocalVariableTable extends Attribute {
035
036 private static final long serialVersionUID = 6780929007774637689L;
037 private int local_variable_table_length; // Table of local
038 private LocalVariable[] local_variable_table; // variables
039
040
041 /**
042 * Initialize from another object. Note that both objects use the same
043 * references (shallow copy). Use copy() for a physical copy.
044 */
045 public LocalVariableTable(LocalVariableTable c) {
046 this(c.getNameIndex(), c.getLength(), c.getLocalVariableTable(), c.getConstantPool());
047 }
048
049
050 /**
051 * @param name_index Index in constant pool to `LocalVariableTable'
052 * @param length Content length in bytes
053 * @param local_variable_table Table of local variables
054 * @param constant_pool Array of constants
055 */
056 public LocalVariableTable(int name_index, int length, LocalVariable[] local_variable_table,
057 ConstantPool constant_pool) {
058 super(Constants.ATTR_LOCAL_VARIABLE_TABLE, name_index, length, constant_pool);
059 setLocalVariableTable(local_variable_table);
060 }
061
062
063 /**
064 * Construct object from file stream.
065 * @param name_index Index in constant pool
066 * @param length Content length in bytes
067 * @param file Input stream
068 * @param constant_pool Array of constants
069 * @throws IOException
070 */
071 LocalVariableTable(int name_index, int length, DataInputStream file, ConstantPool constant_pool)
072 throws IOException {
073 this(name_index, length, (LocalVariable[]) null, constant_pool);
074 local_variable_table_length = (file.readUnsignedShort());
075 local_variable_table = new LocalVariable[local_variable_table_length];
076 for (int i = 0; i < local_variable_table_length; i++) {
077 local_variable_table[i] = new LocalVariable(file, constant_pool);
078 }
079 }
080
081
082 /**
083 * Called by objects that are traversing the nodes of the tree implicitely
084 * defined by the contents of a Java class. I.e., the hierarchy of methods,
085 * fields, attributes, etc. spawns a tree of objects.
086 *
087 * @param v Visitor object
088 */
089 @Override
090 public void accept( Visitor v ) {
091 v.visitLocalVariableTable(this);
092 }
093
094
095 /**
096 * Dump local variable table attribute to file stream in binary format.
097 *
098 * @param file Output file stream
099 * @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 }