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