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