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 * IINC - Increment local variable by constant 027 * 028 */ 029public class IINC extends LocalVariableInstruction { 030 031 private boolean wide; 032 private int c; 033 034 035 /** 036 * Empty constructor needed for Instruction.readInstruction. 037 * Not to be used otherwise. 038 */ 039 IINC() { 040 } 041 042 043 /** 044 * @param n index of local variable 045 * @param c increment factor 046 */ 047 public IINC(final int n, final int c) { 048 super(); // Default behavior of LocalVariableInstruction causes error 049 super.setOpcode(org.apache.bcel.Const.IINC); 050 super.setLength((short) 3); 051 setIndex(n); // May set wide as side effect 052 setIncrement(c); 053 } 054 055 056 /** 057 * Dump instruction as byte code to stream out. 058 * @param out Output stream 059 */ 060 @Override 061 public void dump( final DataOutputStream out ) throws IOException { 062 if (wide) { 063 out.writeByte(org.apache.bcel.Const.WIDE); 064 } 065 out.writeByte(super.getOpcode()); 066 if (wide) { 067 out.writeShort(super.getIndex()); 068 out.writeShort(c); 069 } else { 070 out.writeByte(super.getIndex()); 071 out.writeByte(c); 072 } 073 } 074 075 076 private void setWide() { 077 wide = super.getIndex() > org.apache.bcel.Const.MAX_BYTE; 078 if (c > 0) { 079 wide = wide || (c > Byte.MAX_VALUE); 080 } else { 081 wide = wide || (c < Byte.MIN_VALUE); 082 } 083 if (wide) { 084 super.setLength(6); // wide byte included 085 } else { 086 super.setLength(3); 087 } 088 } 089 090 091 /** 092 * Read needed data (e.g. index) from file. 093 */ 094 @Override 095 protected void initFromFile( final ByteSequence bytes, final boolean wide ) throws IOException { 096 this.wide = wide; 097 if (wide) { 098 super.setLength(6); 099 super.setIndexOnly(bytes.readUnsignedShort()); 100 c = bytes.readShort(); 101 } else { 102 super.setLength(3); 103 super.setIndexOnly(bytes.readUnsignedByte()); 104 c = bytes.readByte(); 105 } 106 } 107 108 109 /** 110 * @return mnemonic for instruction 111 */ 112 @Override 113 public String toString( final boolean verbose ) { 114 return super.toString(verbose) + " " + c; 115 } 116 117 118 /** 119 * Set index of local variable. 120 */ 121 @Override 122 public final void setIndex( final int n ) { 123 if (n < 0) { 124 throw new ClassGenException("Negative index value: " + n); 125 } 126 super.setIndexOnly(n); 127 setWide(); 128 } 129 130 131 /** 132 * @return increment factor 133 */ 134 public final int getIncrement() { 135 return c; 136 } 137 138 139 /** 140 * Set increment factor. 141 */ 142 public final void setIncrement( final int c ) { 143 this.c = c; 144 setWide(); 145 } 146 147 148 /** @return int type 149 */ 150 @Override 151 public Type getType( final ConstantPoolGen cp ) { 152 return Type.INT; 153 } 154 155 156 /** 157 * Call corresponding visitor method(s). The order is: 158 * Call visitor methods of implemented interfaces first, then 159 * call methods according to the class hierarchy in descending order, 160 * i.e., the most specific visitXXX() call comes last. 161 * 162 * @param v Visitor object 163 */ 164 @Override 165 public void accept( final Visitor v ) { 166 v.visitLocalVariableInstruction(this); 167 v.visitIINC(this); 168 } 169}