1 /*
   2  * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Licensed to the Apache Software Foundation (ASF) under one or more
   6  * contributor license agreements.  See the NOTICE file distributed with
   7  * this work for additional information regarding copyright ownership.
   8  * The ASF licenses this file to You under the Apache License, Version 2.0
   9  * (the "License"); you may not use this file except in compliance with
  10  * the License.  You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 
  21 package com.sun.org.apache.bcel.internal.classfile;
  22 
  23 import java.io.DataInput;
  24 import java.io.DataOutputStream;
  25 import java.io.IOException;
  26 
  27 import com.sun.org.apache.bcel.internal.Const;
  28 
  29 /**
  30  * This class represents a local variable within a method. It contains its
  31  * scope, name, signature and index on the method's frame.
  32  *
  33  * @version $Id$
  34  * @see     LocalVariableTable
  35  * @LastModified: Jun 2019
  36  */
  37 public final class LocalVariable implements Cloneable, Node {
  38 
  39     private int start_pc; // Range in which the variable is valid
  40     private int length;
  41     private int name_index; // Index in constant pool of variable name
  42     private int signature_index; // Index of variable signature
  43     private int index; /* Variable is `index'th local variable on
  44      * this method's frame.
  45      */
  46     private ConstantPool constant_pool;
  47     private int orig_index; // never changes; used to match up with LocalVariableTypeTable entries
  48 
  49 
  50     /**
  51      * Initialize from another object. Note that both objects use the same
  52      * references (shallow copy). Use copy() for a physical copy.
  53      */
  54     public LocalVariable(final LocalVariable c) {
  55         this(c.getStartPC(), c.getLength(), c.getNameIndex(), c.getSignatureIndex(), c.getIndex(),
  56                 c.getConstantPool());
  57         this.orig_index = c.getOrigIndex();
  58     }
  59 
  60 
  61     /**
  62      * Construct object from file stream.
  63      * @param file Input stream
  64      * @throws IOException
  65      */
  66     LocalVariable(final DataInput file, final ConstantPool constant_pool) throws IOException {
  67         this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), file
  68                 .readUnsignedShort(), file.readUnsignedShort(), constant_pool);
  69     }
  70 
  71 
  72     /**
  73      * @param start_pc Range in which the variable
  74      * @param length ... is valid
  75      * @param name_index Index in constant pool of variable name
  76      * @param signature_index Index of variable's signature
  77      * @param index Variable is `index'th local variable on the method's frame
  78      * @param constant_pool Array of constants
  79      */
  80     public LocalVariable(final int start_pc, final int length, final int name_index, final int signature_index, final int index,
  81             final ConstantPool constant_pool) {
  82         this.start_pc = start_pc;
  83         this.length = length;
  84         this.name_index = name_index;
  85         this.signature_index = signature_index;
  86         this.index = index;
  87         this.constant_pool = constant_pool;
  88         this.orig_index = index;
  89     }
  90 
  91 
  92     /**
  93      * @param start_pc Range in which the variable
  94      * @param length ... is valid
  95      * @param name_index Index in constant pool of variable name
  96      * @param signature_index Index of variable's signature
  97      * @param index Variable is `index'th local variable on the method's frame
  98      * @param constant_pool Array of constants
  99      * @param orig_index Variable is `index'th local variable on the method's frame prior to any changes
 100      */
 101     public LocalVariable(final int start_pc, final int length, final int name_index, final int signature_index, final int index,
 102             final ConstantPool constant_pool, final int orig_index) {
 103         this.start_pc = start_pc;
 104         this.length = length;
 105         this.name_index = name_index;
 106         this.signature_index = signature_index;
 107         this.index = index;
 108         this.constant_pool = constant_pool;
 109         this.orig_index = orig_index;
 110     }
 111 
 112 
 113     /**
 114      * Called by objects that are traversing the nodes of the tree implicitely
 115      * defined by the contents of a Java class. I.e., the hierarchy of methods,
 116      * fields, attributes, etc. spawns a tree of objects.
 117      *
 118      * @param v Visitor object
 119      */
 120     @Override
 121     public void accept( final Visitor v ) {
 122         v.visitLocalVariable(this);
 123     }
 124 
 125 
 126     /**
 127      * Dump local variable to file stream in binary format.
 128      *
 129      * @param file Output file stream
 130      * @throws IOException
 131      */
 132     public final void dump( final DataOutputStream file ) throws IOException {
 133         file.writeShort(start_pc);
 134         file.writeShort(length);
 135         file.writeShort(name_index);
 136         file.writeShort(signature_index);
 137         file.writeShort(index);
 138     }
 139 
 140 
 141     /**
 142      * @return Constant pool used by this object.
 143      */
 144     public final ConstantPool getConstantPool() {
 145         return constant_pool;
 146     }
 147 
 148 
 149     /**
 150      * @return Variable is valid within getStartPC() .. getStartPC()+getLength()
 151      */
 152     public final int getLength() {
 153         return length;
 154     }
 155 
 156 
 157     /**
 158      * @return Variable name.
 159      */
 160     public final String getName() {
 161         ConstantUtf8 c;
 162         c = (ConstantUtf8) constant_pool.getConstant(name_index, Const.CONSTANT_Utf8);
 163         return c.getBytes();
 164     }
 165 
 166 
 167     /**
 168      * @return Index in constant pool of variable name.
 169      */
 170     public final int getNameIndex() {
 171         return name_index;
 172     }
 173 
 174 
 175     /**
 176      * @return Signature.
 177      */
 178     public final String getSignature() {
 179         ConstantUtf8 c;
 180         c = (ConstantUtf8) constant_pool.getConstant(signature_index, Const.CONSTANT_Utf8);
 181         return c.getBytes();
 182     }
 183 
 184 
 185     /**
 186      * @return Index in constant pool of variable signature.
 187      */
 188     public final int getSignatureIndex() {
 189         return signature_index;
 190     }
 191 
 192 
 193     /**
 194      * @return index of register where variable is stored
 195      */
 196     public final int getIndex() {
 197         return index;
 198     }
 199 
 200 
 201     /**
 202      * @return index of register where variable was originally stored
 203      */
 204     public final int getOrigIndex() {
 205         return orig_index;
 206     }
 207 
 208 
 209     /**
 210      * @return Start of range where he variable is valid
 211      */
 212     public final int getStartPC() {
 213         return start_pc;
 214     }
 215 
 216 
 217     /*
 218      * Helper method shared with LocalVariableTypeTable
 219      */
 220     final String toStringShared( final boolean typeTable ) {
 221         final String name = getName();
 222         final String signature = Utility.signatureToString(getSignature(), false);
 223         final String label = "LocalVariable" + (typeTable ? "Types" : "" );
 224         return label + "(start_pc = " + start_pc + ", length = " + length + ", index = "
 225                 + index + ":" + signature + " " + name + ")";
 226     }
 227 
 228 
 229     /**
 230      * @param constant_pool Constant pool to be used for this object.
 231      */
 232     public final void setConstantPool( final ConstantPool constant_pool ) {
 233         this.constant_pool = constant_pool;
 234     }
 235 
 236 
 237     /**
 238      * @param length the length of this local variable
 239      */
 240     public final void setLength( final int length ) {
 241         this.length = length;
 242     }
 243 
 244 
 245     /**
 246      * @param name_index the index into the constant pool for the name of this variable
 247      */
 248     public final void setNameIndex( final int name_index ) { // TODO unused
 249         this.name_index = name_index;
 250     }
 251 
 252 
 253     /**
 254      * @param signature_index the index into the constant pool for the signature of this variable
 255      */
 256     public final void setSignatureIndex( final int signature_index ) { // TODO unused
 257         this.signature_index = signature_index;
 258     }
 259 
 260 
 261     /**
 262      * @param index the index in the local variable table of this variable
 263      */
 264     public final void setIndex( final int index ) { // TODO unused
 265         this.index = index;
 266     }
 267 
 268 
 269     /**
 270      * @param start_pc Specify range where the local variable is valid.
 271      */
 272     public final void setStartPC( final int start_pc ) { // TODO unused
 273         this.start_pc = start_pc;
 274     }
 275 
 276 
 277     /**
 278      * @return string representation.
 279      */
 280     @Override
 281     public final String toString() {
 282         return toStringShared(false);
 283     }
 284 
 285 
 286     /**
 287      * @return deep copy of this object
 288      */
 289     public LocalVariable copy() {
 290         try {
 291             return (LocalVariable) clone();
 292         } catch (final CloneNotSupportedException e) {
 293             // TODO should this throw?
 294         }
 295         return null;
 296     }
 297 }