00001 package de.fub.bytecode.generic;
00002
00003 import java.io.*;
00004 import de.fub.bytecode.util.ByteSequence;
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 public abstract class Select extends BranchInstruction
00016 implements VariableLengthInstruction, StackProducer
00017 {
00018 protected int[] match;
00019 protected int[] indices;
00020 protected InstructionHandle[] targets;
00021 protected int fixed_length;
00022 protected int match_length;
00023 protected int padding = 0;
00024
00025
00026
00027
00028
00029 Select() {}
00030
00031
00032
00033
00034
00035
00036
00037
00038 Select(short tag, int[] match, InstructionHandle[] targets,
00039 InstructionHandle target) {
00040 super(tag, target);
00041
00042 this.targets = targets;
00043 for(int i=0; i < targets.length; i++)
00044 notifyTarget(null, targets[i], this);
00045
00046 this.match = match;
00047
00048 if((match_length = match.length) != targets.length)
00049 throw new ClassGenException("Match and target array have not the same length");
00050
00051 indices = new int[match_length];
00052 }
00053
00054
00055
00056 public boolean containsTarget(InstructionHandle ih) {
00057 if(target == ih)
00058 return true;
00059
00060 for(int i=0; i < targets.length; i++)
00061 if(targets[i] == ih)
00062 return true;
00063
00064 return false;
00065 }
00066
00067
00068
00069 void dispose() {
00070 super.dispose();
00071
00072 for(int i=0; i < targets.length; i++)
00073 targets[i].removeTargeter(this);
00074 }
00075
00076
00077
00078
00079 public void dump(DataOutputStream out) throws IOException {
00080 out.writeByte(tag);
00081
00082 for(int i=0; i < padding; i++)
00083 out.writeByte(0);
00084
00085 index = getTargetOffset();
00086 out.writeInt(index);
00087 }
00088
00089
00090
00091 public int[] getIndices() { return indices; }
00092
00093
00094
00095 public int[] getMatchs() { return match; }
00096
00097
00098
00099 public InstructionHandle[] getTargets() { return targets; }
00100
00101
00102
00103 protected void initFromFile(ByteSequence bytes, boolean wide) throws IOException
00104 {
00105 padding = (4 - (bytes.getIndex() % 4)) % 4;
00106
00107 for(int i=0; i < padding; i++) {
00108 byte b;
00109 if((b=bytes.readByte()) != 0)
00110 throw new ClassGenException("Padding byte != 0: " + b);
00111 }
00112
00113
00114 index = bytes.readInt();
00115 }
00116
00117
00118
00119 public void setTarget(int i, InstructionHandle target) {
00120 notifyTarget(targets[i], target, this);
00121 targets[i] = target;
00122 }
00123
00124
00125
00126 public String toString(boolean verbose) {
00127 StringBuffer buf = new StringBuffer(super.toString(verbose));
00128
00129 if(verbose) {
00130 for(int i=0; i < match_length; i++) {
00131 String s = "null";
00132
00133 if(targets[i] != null)
00134 s = targets[i].getInstruction().toString();
00135
00136 buf.append("(" + match[i] + ", " + s + " = {" + indices[i] + "})");
00137 }
00138 }
00139 else
00140 buf.append(" ...");
00141
00142 return buf.toString();
00143 }
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157 protected int updatePosition(int offset, int max_offset) {
00158 position += offset;
00159
00160 short old_length = length;
00161
00162
00163
00164 padding = (4 - ((position + 1) % 4)) % 4;
00165 length = (short)(fixed_length + padding);
00166
00167 return length - old_length;
00168 }
00169
00170
00171
00172
00173 public void updateTarget(InstructionHandle old_ih, InstructionHandle new_ih) {
00174 boolean targeted = false;
00175
00176 if(target == old_ih) {
00177 targeted = true;
00178 setTarget(new_ih);
00179 }
00180
00181 for(int i=0; i < targets.length; i++) {
00182 if(targets[i] == old_ih) {
00183 targeted = true;
00184 setTarget(i, new_ih);
00185 }
00186 }
00187
00188 if(!targeted)
00189 throw new ClassGenException("Not targeting " + old_ih);
00190 }
00191 }