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 package com.sun.org.apache.bcel.internal.generic;
  21 
  22 import java.io.DataOutputStream;
  23 import java.io.IOException;
  24 
  25 import com.sun.org.apache.bcel.internal.classfile.Constant;
  26 import com.sun.org.apache.bcel.internal.classfile.ConstantClass;
  27 import com.sun.org.apache.bcel.internal.classfile.ConstantPool;
  28 import com.sun.org.apache.bcel.internal.util.ByteSequence;
  29 
  30 /**
  31  * Abstract super class for instructions that use an index into the
  32  * constant pool such as LDC, INVOKEVIRTUAL, etc.
  33  *
  34  * @see ConstantPoolGen
  35  * @see LDC
  36  * @see INVOKEVIRTUAL
  37  *
  38  * @version $Id$
  39  * @LastModified: Jun 2019
  40  */
  41 public abstract class CPInstruction extends Instruction implements TypedInstruction,
  42         IndexedInstruction {
  43 
  44     private int index; // index to constant pool
  45 
  46 
  47     /**
  48      * Empty constructor needed for Instruction.readInstruction.
  49      * Not to be used otherwise.
  50      */
  51     CPInstruction() {
  52     }
  53 
  54 
  55     /**
  56      * @param index to constant pool
  57      */
  58     protected CPInstruction(final short opcode, final int index) {
  59         super(opcode, (short) 3);
  60         setIndex(index);
  61     }
  62 
  63 
  64     /**
  65      * Dump instruction as byte code to stream out.
  66      * @param out Output stream
  67      */
  68     @Override
  69     public void dump( final DataOutputStream out ) throws IOException {
  70         out.writeByte(super.getOpcode());
  71         out.writeShort(index);
  72     }
  73 
  74 
  75     /**
  76      * Long output format:
  77      *
  78      * <name of opcode> "["<opcode number>"]"
  79      * "("<length of instruction>")" "<"< constant pool index>">"
  80      *
  81      * @param verbose long/short format switch
  82      * @return mnemonic for instruction
  83      */
  84     @Override
  85     public String toString( final boolean verbose ) {
  86         return super.toString(verbose) + " " + index;
  87     }
  88 
  89 
  90     /**
  91      * @return mnemonic for instruction with symbolic references resolved
  92      */
  93     @Override
  94     public String toString( final ConstantPool cp ) {
  95         final Constant c = cp.getConstant(index);
  96         String str = cp.constantToString(c);
  97         if (c instanceof ConstantClass) {
  98             str = str.replace('.', '/');
  99         }
 100         return com.sun.org.apache.bcel.internal.Const.getOpcodeName(super.getOpcode()) + " " + str;
 101     }
 102 
 103 
 104     /**
 105      * Read needed data (i.e., index) from file.
 106      * @param bytes input stream
 107      * @param wide wide prefix?
 108      */
 109     @Override
 110     protected void initFromFile( final ByteSequence bytes, final boolean wide ) throws IOException {
 111         setIndex(bytes.readUnsignedShort());
 112         super.setLength(3);
 113     }
 114 
 115 
 116     /**
 117      * @return index in constant pool referred by this instruction.
 118      */
 119     @Override
 120     public final int getIndex() {
 121         return index;
 122     }
 123 
 124 
 125     /**
 126      * Set the index to constant pool.
 127      * @param index in  constant pool.
 128      */
 129     @Override
 130     public void setIndex( final int index ) { // TODO could be package-protected?
 131         if (index < 0) {
 132             throw new ClassGenException("Negative index value: " + index);
 133         }
 134         this.index = index;
 135     }
 136 
 137 
 138     /** @return type related with this instruction.
 139      */
 140     @Override
 141     public Type getType( final ConstantPoolGen cpg ) {
 142         final ConstantPool cp = cpg.getConstantPool();
 143         String name = cp.getConstantString(index, com.sun.org.apache.bcel.internal.Const.CONSTANT_Class);
 144         if (!name.startsWith("[")) {
 145             name = "L" + name + ";";
 146         }
 147         return Type.getType(name);
 148     }
 149 }