1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  */
18 package org.apache.bcel.generic;
19 
20 import java.io.DataOutputStream;
21 import java.io.IOException;
22 
23 /**
24  * GOTO - Branch always (to relative offset, not absolute address)
25  *
26  * @version $Id$
27  */
28 public class GOTO extends GotoInstruction implements VariableLengthInstruction {
29 
30     /**
31      * Empty constructor needed for Instruction.readInstruction.
32      * Not to be used otherwise.
33      */
GOTO()34     GOTO() {
35     }
36 
37 
GOTO(final InstructionHandle target)38     public GOTO(final InstructionHandle target) {
39         super(org.apache.bcel.Const.GOTO, target);
40     }
41 
42 
43     /**
44      * Dump instruction as byte code to stream out.
45      * @param out Output stream
46      */
47     @Override
dump( final DataOutputStream out )48     public void dump( final DataOutputStream out ) throws IOException {
49         super.setIndex(getTargetOffset());
50         final short _opcode = getOpcode();
51         if (_opcode == org.apache.bcel.Const.GOTO) {
52             super.dump(out);
53         } else { // GOTO_W
54             super.setIndex(getTargetOffset());
55             out.writeByte(_opcode);
56             out.writeInt(super.getIndex());
57         }
58     }
59 
60 
61     /**
62      * Called in pass 2 of InstructionList.setPositions() in order to update
63      * the branch target, that may shift due to variable length instructions.
64      *
65      * @param offset additional offset caused by preceding (variable length) instructions
66      * @param max_offset the maximum offset that may be caused by these instructions
67      * @return additional offset caused by possible change of this instruction's length
68      */
69     @Override
updatePosition( final int offset, final int max_offset )70     protected int updatePosition( final int offset, final int max_offset ) {
71         final int i = getTargetOffset(); // Depending on old position value
72         setPosition(getPosition() + offset); // Position may be shifted by preceding expansions
73         if (Math.abs(i) >= (Short.MAX_VALUE - max_offset)) { // to large for short (estimate)
74             super.setOpcode(org.apache.bcel.Const.GOTO_W);
75             final short old_length = (short) super.getLength();
76             super.setLength(5);
77             return super.getLength() - old_length;
78         }
79         return 0;
80     }
81 
82 
83     /**
84      * Call corresponding visitor method(s). The order is:
85      * Call visitor methods of implemented interfaces first, then
86      * call methods according to the class hierarchy in descending order,
87      * i.e., the most specific visitXXX() call comes last.
88      *
89      * @param v Visitor object
90      */
91     @Override
accept( final Visitor v )92     public void accept( final Visitor v ) {
93         v.visitVariableLengthInstruction(this);
94         v.visitUnconditionalBranch(this);
95         v.visitBranchInstruction(this);
96         v.visitGotoInstruction(this);
97         v.visitGOTO(this);
98     }
99 }
100