001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   https://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.bcel.generic;
020
021import java.io.DataOutputStream;
022import java.io.IOException;
023
024import org.apache.bcel.Const;
025import org.apache.bcel.classfile.Constant;
026import org.apache.bcel.classfile.ConstantClass;
027import org.apache.bcel.classfile.ConstantPool;
028import org.apache.bcel.classfile.Utility;
029import org.apache.bcel.util.ByteSequence;
030
031/**
032 * Abstract superclass for instructions that use an index into the constant pool such as LDC, INVOKEVIRTUAL, and so on.
033 *
034 * @see ConstantPoolGen
035 * @see LDC
036 * @see INVOKEVIRTUAL
037 */
038public abstract class CPInstruction extends Instruction implements TypedInstruction, IndexedInstruction {
039
040    /**
041     * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
042     */
043    @Deprecated
044    protected int index; // index to constant pool
045
046    /**
047     * Empty constructor needed for Instruction.readInstruction. Not to be used otherwise.
048     */
049    CPInstruction() {
050    }
051
052    /**
053     * Constructs a CPInstruction.
054     *
055     * @param opcode The opcode.
056     * @param index to constant pool.
057     */
058    protected CPInstruction(final short opcode, final int index) {
059        super(opcode, (short) 3);
060        setIndex(index);
061    }
062
063    /**
064     * Dumps instruction as byte code to stream out.
065     *
066     * @param out Output stream.
067     */
068    @Override
069    public void dump(final DataOutputStream out) throws IOException {
070        out.writeByte(super.getOpcode());
071        out.writeShort(index);
072    }
073
074    /**
075     * Gets the constant pool index referred to by this instruction.
076     *
077     * @return index in constant pool referred by this instruction.
078     */
079    @Override
080    public final int getIndex() {
081        return index;
082    }
083
084    /**
085     * Gets the type associated with this instruction.
086     *
087     * @return type related with this instruction.
088     */
089    @Override
090    public Type getType(final ConstantPoolGen cpg) {
091        final ConstantPool cp = cpg.getConstantPool();
092        String name = cp.getConstantString(index, Const.CONSTANT_Class);
093        if (!name.startsWith("[")) {
094            name = "L" + name + ";";
095        }
096        return Type.getType(name);
097    }
098
099    /**
100     * Reads needed data (that is, index) from file.
101     *
102     * @param bytes input stream.
103     * @param wide wide prefix?.
104     */
105    @Override
106    protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException {
107        setIndex(bytes.readUnsignedShort());
108        super.setLength(3);
109    }
110
111    /**
112     * Sets the index to constant pool.
113     *
114     * @param index in constant pool.
115     * @throws ClassGenException Thrown if index is out of bounds.
116     */
117    @Override
118    public void setIndex(final int index) { // TODO could be package-protected?
119        if (!isNonNegativeUShort(index)) {
120            throw new ClassGenException("Illegal index: " + index);
121        }
122        this.index = index;
123    }
124
125    /**
126     * Long output format:
127     *
128     * <name of opcode> "["<opcode number>"]" "("<length of instruction>")" "<"< constant pool
129     * index>">"
130     *
131     * @param verbose long/short format switch.
132     * @return mnemonic for instruction.
133     */
134    @Override
135    public String toString(final boolean verbose) {
136        return super.toString(verbose) + " " + index;
137    }
138
139    /**
140     * @return mnemonic for instruction with symbolic references resolved.
141     */
142    @Override
143    public String toString(final ConstantPool cp) {
144        final Constant c = cp.getConstant(index);
145        String str = cp.constantToString(c);
146        if (c instanceof ConstantClass) {
147            str = Utility.packageToPath(str);
148        }
149        return Const.getOpcodeName(super.getOpcode()) + " " + str;
150    }
151}