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.util.ByteSequence;
024
025/**
026 * RET - Return from subroutine
027 *
028 * <PRE>Stack: ... -&gt; ...</PRE>
029 *
030 */
031public class RET extends Instruction implements IndexedInstruction, TypedInstruction {
032
033    private boolean wide;
034    private int index; // index to local variable containg the return address
035
036
037    /**
038     * Empty constructor needed for Instruction.readInstruction.
039     * Not to be used otherwise.
040     */
041    RET() {
042    }
043
044
045    public RET(final int index) {
046        super(org.apache.bcel.Const.RET, (short) 2);
047        setIndex(index); // May set wide as side effect
048    }
049
050
051    /**
052     * Dump instruction as byte code to stream out.
053     * @param out Output stream
054     */
055    @Override
056    public void dump( final DataOutputStream out ) throws IOException {
057        if (wide) {
058            out.writeByte(org.apache.bcel.Const.WIDE);
059        }
060        out.writeByte(super.getOpcode());
061        if (wide) {
062            out.writeShort(index);
063        } else {
064            out.writeByte(index);
065        }
066    }
067
068
069    private void setWide() {
070        wide = index > org.apache.bcel.Const.MAX_BYTE;
071        if (wide) {
072            super.setLength(4); // Including the wide byte
073        } else {
074            super.setLength(2);
075        }
076    }
077
078
079    /**
080     * Read needed data (e.g. index) from file.
081     */
082    @Override
083    protected void initFromFile( final ByteSequence bytes, final boolean wide ) throws IOException {
084        this.wide = wide;
085        if (wide) {
086            index = bytes.readUnsignedShort();
087            super.setLength(4);
088        } else {
089            index = bytes.readUnsignedByte();
090            super.setLength(2);
091        }
092    }
093
094
095    /**
096     * @return index of local variable containg the return address
097     */
098    @Override
099    public final int getIndex() {
100        return index;
101    }
102
103
104    /**
105     * Set index of local variable containg the return address
106     */
107    @Override
108    public final void setIndex( final int n ) {
109        if (n < 0) {
110            throw new ClassGenException("Negative index value: " + n);
111        }
112        index = n;
113        setWide();
114    }
115
116
117    /**
118     * @return mnemonic for instruction
119     */
120    @Override
121    public String toString( final boolean verbose ) {
122        return super.toString(verbose) + " " + index;
123    }
124
125
126    /** @return return address type
127     */
128    @Override
129    public Type getType( final ConstantPoolGen cp ) {
130        return ReturnaddressType.NO_TARGET;
131    }
132
133
134    /**
135     * Call corresponding visitor method(s). The order is:
136     * Call visitor methods of implemented interfaces first, then
137     * call methods according to the class hierarchy in descending order,
138     * i.e., the most specific visitXXX() call comes last.
139     *
140     * @param v Visitor object
141     */
142    @Override
143    public void accept( final Visitor v ) {
144        v.visitRET(this);
145    }
146}