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 */
018package org.apache.bcel.generic;
019
020import java.io.DataOutputStream;
021import java.io.IOException;
022
023import org.apache.bcel.classfile.Constant;
024import org.apache.bcel.classfile.ConstantClass;
025import org.apache.bcel.classfile.ConstantPool;
026import org.apache.bcel.util.ByteSequence;
027
028/**
029 * Abstract super class for instructions that use an index into the
030 * constant pool such as LDC, INVOKEVIRTUAL, etc.
031 *
032 * @see ConstantPoolGen
033 * @see LDC
034 * @see INVOKEVIRTUAL
035 *
036 * @version $Id: CPInstruction.java 1812166 2017-10-13 23:48:11Z ggregory $
037 */
038public abstract class CPInstruction extends Instruction implements TypedInstruction,
039        IndexedInstruction {
040
041    /**
042     * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
043     */
044    @Deprecated
045    protected int index; // index to constant pool
046
047
048    /**
049     * Empty constructor needed for Instruction.readInstruction.
050     * Not to be used otherwise.
051     */
052    CPInstruction() {
053    }
054
055
056    /**
057     * @param index to constant pool
058     */
059    protected CPInstruction(final short opcode, final int index) {
060        super(opcode, (short) 3);
061        setIndex(index);
062    }
063
064
065    /**
066     * Dump instruction as byte code to stream out.
067     * @param out Output stream
068     */
069    @Override
070    public void dump( final DataOutputStream out ) throws IOException {
071        out.writeByte(super.getOpcode());
072        out.writeShort(index);
073    }
074
075
076    /**
077     * Long output format:
078     *
079     * <name of opcode> "["<opcode number>"]"
080     * "("<length of instruction>")" "<"< constant pool index>">"
081     *
082     * @param verbose long/short format switch
083     * @return mnemonic for instruction
084     */
085    @Override
086    public String toString( final boolean verbose ) {
087        return super.toString(verbose) + " " + index;
088    }
089
090
091    /**
092     * @return mnemonic for instruction with symbolic references resolved
093     */
094    @Override
095    public String toString( final ConstantPool cp ) {
096        final Constant c = cp.getConstant(index);
097        String str = cp.constantToString(c);
098        if (c instanceof ConstantClass) {
099            str = str.replace('.', '/');
100        }
101        return org.apache.bcel.Const.getOpcodeName(super.getOpcode()) + " " + str;
102    }
103
104
105    /**
106     * Read needed data (i.e., index) from file.
107     * @param bytes input stream
108     * @param wide wide prefix?
109     */
110    @Override
111    protected void initFromFile( final ByteSequence bytes, final boolean wide ) throws IOException {
112        setIndex(bytes.readUnsignedShort());
113        super.setLength(3);
114    }
115
116
117    /**
118     * @return index in constant pool referred by this instruction.
119     */
120    @Override
121    public final int getIndex() {
122        return index;
123    }
124
125
126    /**
127     * Set the index to constant pool.
128     * @param index in  constant pool.
129     */
130    @Override
131    public void setIndex( final int index ) { // TODO could be package-protected?
132        if (index < 0) {
133            throw new ClassGenException("Negative index value: " + index);
134        }
135        this.index = index;
136    }
137
138
139    /** @return type related with this instruction.
140     */
141    @Override
142    public Type getType( final ConstantPoolGen cpg ) {
143        final ConstantPool cp = cpg.getConstantPool();
144        String name = cp.getConstantString(index, org.apache.bcel.Const.CONSTANT_Class);
145        if (!name.startsWith("[")) {
146            name = "L" + name + ";";
147        }
148        return Type.getType(name);
149    }
150}