1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Licensed to the Apache Software Foundation (ASF) under one or more
   7  * contributor license agreements.  See the NOTICE file distributed with
   8  * this work for additional information regarding copyright ownership.
   9  * The ASF licenses this file to You under the Apache License, Version 2.0
  10  * (the "License"); you may not use this file except in compliance with
  11  * the License.  You may obtain a copy of the License at
  12  *
  13  *      http://www.apache.org/licenses/LICENSE-2.0
  14  *
  15  * Unless required by applicable law or agreed to in writing, software
  16  * distributed under the License is distributed on an "AS IS" BASIS,
  17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18  * See the License for the specific language governing permissions and
  19  * limitations under the License.
  20  */
  21 
  22 package com.sun.org.apache.bcel.internal.generic;
  23 
  24 import java.io.*;
  25 import com.sun.org.apache.bcel.internal.util.ByteSequence;
  26 
  27 /**
  28  * IINC - Increment local variable by constant
  29  *
  30  * @author  <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
  31  */
  32 public class IINC extends LocalVariableInstruction {
  33   private boolean wide;
  34   private int     c;
  35 
  36   /**
  37    * Empty constructor needed for the Class.newInstance() statement in
  38    * Instruction.readInstruction(). Not to be used otherwise.
  39    */
  40   IINC() {}
  41 
  42   /**
  43    * @param n index of local variable
  44    * @param c increment factor
  45    */
  46   public IINC(int n, int c) {
  47     super(); // Default behaviour of LocalVariableInstruction causes error
  48 
  49     this.opcode = com.sun.org.apache.bcel.internal.Constants.IINC;
  50     this.length = (short)3;
  51 
  52     setIndex(n);    // May set wide as side effect
  53     setIncrement(c);
  54   }
  55 
  56   /**
  57    * Dump instruction as byte code to stream out.
  58    * @param out Output stream
  59    */
  60   public void dump(DataOutputStream out) throws IOException {
  61     if(wide) // Need WIDE prefix ?
  62       out.writeByte(com.sun.org.apache.bcel.internal.Constants.WIDE);
  63 
  64     out.writeByte(opcode);
  65 
  66     if(wide) {
  67       out.writeShort(n);
  68       out.writeShort(c);
  69     } else {
  70       out.writeByte(n);
  71       out.writeByte(c);
  72     }
  73   }
  74 
  75   private final void setWide() {
  76     if(wide = ((n > com.sun.org.apache.bcel.internal.Constants.MAX_SHORT) ||
  77                (Math.abs(c) > Byte.MAX_VALUE)))
  78       length = 6; // wide byte included
  79     else
  80       length = 3;
  81   }
  82 
  83   /**
  84    * Read needed data (e.g. index) from file.
  85    */
  86   protected void initFromFile(ByteSequence bytes, boolean wide) throws IOException
  87   {
  88     this.wide = wide;
  89 
  90     if(wide) {
  91       length = 6;
  92       n = bytes.readUnsignedShort();
  93       c = bytes.readShort();
  94     } else {
  95       length = 3;
  96       n = bytes.readUnsignedByte();
  97       c = bytes.readByte();
  98     }
  99   }
 100 
 101   /**
 102    * @return mnemonic for instruction
 103    */
 104   public String toString(boolean verbose) {
 105     return super.toString(verbose) + " " + c;
 106   }
 107 
 108   /**
 109    * Set index of local variable.
 110    */
 111   public final void setIndex(int n) {
 112     if(n < 0)
 113       throw new ClassGenException("Negative index value: " + n);
 114 
 115     this.n = n;
 116     setWide();
 117   }
 118 
 119   /**
 120    * @return increment factor
 121    */
 122   public final int getIncrement() { return c; }
 123 
 124   /**
 125    * Set increment factor.
 126    */
 127   public final void setIncrement(int c) {
 128     this.c = c;
 129     setWide();
 130   }
 131 
 132   /** @return int type
 133    */
 134   public Type getType(ConstantPoolGen cp) {
 135     return Type.INT;
 136   }
 137 
 138   /**
 139    * Call corresponding visitor method(s). The order is:
 140    * Call visitor methods of implemented interfaces first, then
 141    * call methods according to the class hierarchy in descending order,
 142    * i.e., the most specific visitXXX() call comes last.
 143    *
 144    * @param v Visitor object
 145    */
 146   public void accept(Visitor v) {
 147     v.visitLocalVariableInstruction(this);
 148     v.visitIINC(this);
 149   }
 150 }