Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/chaoswg/xtc4y/classdesc/code/instructions/TableSwitchInstruction.java


1   //$Header: /cvsroot/xtc4y/xtc4y/src/com/chaoswg/xtc4y/classdesc/code/instructions/TableSwitchInstruction.java,v 1.4 2003/09/08 20:57:26 toggm Exp $
2   /******************************************************************************
3    * XTC4y - eXtreme Testing Collection 4 you                                   *
4    * -------------------------------------------------------------------------- *
5    * URL: http://www.chaoswg.com/xtc4y                                          *
6    * Author: Mike Toggweiler (2.dog@gmx.ch)                                     *
7    *                                                                            *
8    * Last Updated: $Date: 2003/09/08 20:57:26 $, by $Author: toggm $            *
9    * Version: $Revision: 1.4 $                                                  *
10   * -------------------------------------------------------------------------- *
11   * COPYRIGHT:   (c) 2003 by Mike Toggweiler                                   *
12   *                                                                            *
13   * This program is free software; you can redistribute it and/or modify       *
14   * it under the terms of the GNU General Public License as published by       *
15   * the Free Software Foundation; either version 2 of the License, or          *
16   * (at your option) any later version.                                        *
17   *****************************************************************************/
18  package com.chaoswg.xtc4y.classdesc.code.instructions;
19  
20  import java.io.DataInputStream;
21  import java.io.DataOutputStream;
22  import java.io.IOException;
23  
24  import com.chaoswg.xtc4y.classdesc.ConstantPool;
25  import com.chaoswg.xtc4y.classdesc.code.Code;
26  
27  /**
28   * A Lookup switch instruction is used to represent switch statements.
29   * It consists of the command, an int giving the start number, an int defining 
30   * the last number of table entires, an int defining the default jump address 
31   * and a set of entries where each entry consists of one int, a jump address. 
32   * The end of a TableSwitch Instruction is aligned to 4 byte and therefore 
33   * gaps are filled up with nop's.
34   * That means: (1byte+4bytes+4bytes+4bytes+(4bytes)*+((index+length)%4))
35   * TBD: add methods to instanciate a tableswitch without a stream
36   * @author Mike Toggweiler
37   **/
38  public class TableSwitchInstruction extends Instruction {
39      private int startIndex;
40      private int endIndex;
41      private int defaultJumpAdress;
42      private int[] jumps;
43      private int gap;
44  
45      private Instruction defaultInstr;
46      private Instruction[] jumpInstr;
47  
48      private DataInputStream dis;
49  
50      /**
51       * Opcode of int binary instructions
52       **/
53      public static final byte TABLESWITCH = (byte)170;
54  
55      /**
56       * Creates an LookupSwitchInstruction and initializes it from a 
57       * DataInputStream
58       * @param dis the DataInputStream to read from
59       * @param cp the constant pool to resolve indices
60       **/
61      protected TableSwitchInstruction(DataInputStream dis, 
62               ConstantPool cp) throws IOException {
63    super(TABLESWITCH);  
64  
65    //store temporary the datainputstream to read the gap from
66    this.dis = dis;
67      }
68  
69      /**
70       * Set the index of this instruction, is set by the code container
71       * @param index 
72       **/
73      public void setIndex(short index) {
74    super.setIndex(index);
75  
76    if (dis == null) {
77        return;
78    }
79    
80    //read the remaining gap, is depedant on the index of the switch 
81    //instruction
82    gap = (index % 4);
83    if (gap == 0) {
84        gap = 1;
85    }
86    else {
87        gap++;
88    }
89    gap = 4 - gap;
90    try {
91        for (int i=0; i<gap; ++i) {
92      //throw away byte
93      dis.readUnsignedByte();
94      
95        }
96  
97        defaultJumpAdress = dis.readInt();
98        startIndex = dis.readInt();
99        endIndex = dis.readInt();
100             
101       jumps = new int[endIndex-startIndex];
102       jumpInstr = new Instruction[endIndex-startIndex];
103       int i,j;
104       for (i=startIndex, j=0; i<endIndex; ++i, ++j) {
105     jumps[j] = dis.readInt();
106       }
107   }
108   catch (IOException ioe) {
109       //do nothing
110       //TBD: log
111   }
112 
113   //free dis reference
114   dis = null;
115     }
116 
117     /**
118      * Resolve indices of instructions.
119      * By default do nothing
120      * @param code the code container where to resolve the indices
121      **/
122     public void resolveIndices(Code code) {  
123   int i, j;
124   for (i=startIndex,j=0; i<endIndex; ++i, ++j) {
125       jumpInstr[j] = code.getInstructionAt((short)(jumps[j]+getIndex()));
126   }
127 
128   defaultInstr = code.getInstructionAt((short)defaultJumpAdress);
129     }
130 
131     /**
132      * Write the instruction onto the DataOutputStream, using the 
133      * constant pool to register variables. .
134      * @param dos the DataOutputStream to write on
135      * @param cp The constant pool to register variables
136      **/
137     public final void write(DataOutputStream dos, ConstantPool cp) 
138   throws IOException {
139   super.write(dos, cp);  
140   int i,j;
141   for (i=0; i<gap; ++i) {
142       dos.writeByte(UnaryInstruction.NOP);
143   }
144   dos.writeInt(startIndex);
145   dos.writeInt(endIndex);
146   dos.writeInt(defaultInstr.getIndex());  
147   for (i=startIndex, j=0; i<endIndex; ++i, ++j) {
148       dos.writeInt(jumpInstr[j].getIndex()-getIndex());
149   }
150     }
151 
152     /**
153      * @return the number of bytes used in this command
154      **/
155     public int getNumberOfUsedBytes() {
156   //return command + startIndex + endIndex + defaultJumpAddr + 
157   //numberOfEntries*(jumpAddr) + gap
158   return 1 + 4 + 4 + 4 + (endIndex-startIndex)*(4) + gap;
159     }
160 }