1 16 17 package org.cojen.classfile.attribute; 18 19 import java.util.ArrayList ; 20 import java.util.Collections ; 21 import java.util.HashSet ; 22 import java.util.Iterator ; 23 import java.util.List ; 24 import java.util.Set ; 25 import java.io.DataInput ; 26 import java.io.DataOutput ; 27 import java.io.IOException ; 28 import org.cojen.classfile.Attribute; 29 import org.cojen.classfile.ConstantPool; 30 import org.cojen.classfile.FixedLocation; 31 import org.cojen.classfile.LocalVariable; 32 import org.cojen.classfile.Location; 33 import org.cojen.classfile.LocationRange; 34 import org.cojen.classfile.LocationRangeImpl; 35 import org.cojen.classfile.TypeDesc; 36 import org.cojen.classfile.constant.ConstantUTFInfo; 37 38 44 public class LocalVariableTableAttr extends Attribute { 45 46 private List mEntries = new ArrayList (10); 47 private List mCleanEntries; 48 private int mRangeCount; 49 50 public LocalVariableTableAttr(ConstantPool cp) { 51 super(cp, LOCAL_VARIABLE_TABLE); 52 } 53 54 public LocalVariableTableAttr(ConstantPool cp, String name) { 55 super(cp, name); 56 } 57 58 public LocalVariableTableAttr(ConstantPool cp, String name, int length, DataInput din) 59 throws IOException 60 { 61 super(cp, name); 62 63 int size = din.readUnsignedShort(); 64 for (int i=0; i<size; i++) { 65 int start_pc = din.readUnsignedShort(); 66 int end_pc = start_pc + din.readUnsignedShort() + 1; 67 int name_index = din.readUnsignedShort(); 68 int descriptor_index = din.readUnsignedShort(); 69 final int index = din.readUnsignedShort(); 70 71 final ConstantUTFInfo varName = 72 (ConstantUTFInfo)cp.getConstant(name_index); 73 final ConstantUTFInfo varDesc = 74 (ConstantUTFInfo)cp.getConstant(descriptor_index); 75 76 final Location startLocation = new FixedLocation(start_pc); 77 final Location endLocation = new FixedLocation(end_pc); 78 79 Set ranges = new HashSet (); 80 ranges.add(new LocationRangeImpl(startLocation, endLocation)); 81 final Set fRanges = Collections.unmodifiableSet(ranges); 82 83 LocalVariable localVar = new LocalVariable() { 84 private String mName; 85 private TypeDesc mType; 86 87 { 88 mName = varName.getValue(); 89 mType = TypeDesc.forDescriptor(varDesc.getValue()); 90 } 91 92 public String getName() { 93 return mName; 94 } 95 96 public void setName(String name) { 97 mName = name; 98 } 99 100 public TypeDesc getType() { 101 return mType; 102 } 103 104 public boolean isDoubleWord() { 105 return mType.isDoubleWord(); 106 } 107 108 public int getNumber() { 109 return index; 110 } 111 112 public Set getLocationRangeSet() { 113 return fRanges; 114 } 115 }; 116 117 mEntries.add(new Entry(localVar, varName, varDesc)); 118 } 119 } 120 121 124 public void addEntry(LocalVariable localVar) { 125 String varName = localVar.getName(); 126 if (varName != null) { 127 ConstantUTFInfo name = getConstantPool().addConstantUTF(varName); 128 ConstantUTFInfo descriptor = 129 getConstantPool().addConstantUTF(localVar.getType().getDescriptor()); 130 mEntries.add(new Entry(localVar, name, descriptor)); 131 } 132 133 mCleanEntries = null; 134 } 135 136 public int getLength() { 137 clean(); 138 return 2 + 10 * mRangeCount; 139 } 140 141 public void writeDataTo(DataOutput dout) throws IOException { 142 dout.writeShort(mRangeCount); 143 144 int size = mCleanEntries.size(); 145 for (int i=0; i<size; i++) { 146 Entry entry = (Entry)mEntries.get(i); 147 LocalVariable localVar = entry.mLocalVar; 148 149 Set ranges = localVar.getLocationRangeSet(); 150 if (ranges == null) { 151 continue; 152 } 153 154 int name_index = entry.mName.getIndex(); 155 int descriptor_index = entry.mDescriptor.getIndex(); 156 int index = localVar.getNumber(); 157 158 check("local variable table entry name index", name_index); 159 check("local variable table entry descriptor index", descriptor_index); 160 check("local variable table entry index", index); 161 162 Iterator it = ranges.iterator(); 163 while (it.hasNext()) { 164 LocationRange range = (LocationRange)it.next(); 165 166 Location startLocation = range.getStartLocation(); 167 Location endLocation = range.getEndLocation(); 168 169 int start_pc = startLocation.getLocation(); 170 int length = endLocation.getLocation() - start_pc - 1; 171 172 check("local variable table entry start PC", start_pc); 173 174 dout.writeShort(start_pc); 175 dout.writeShort(length); 176 dout.writeShort(name_index); 177 dout.writeShort(descriptor_index); 178 dout.writeShort(index); 179 } 180 } 181 } 182 183 private void check(String type, int addr) throws IllegalStateException { 184 if (addr < 0 || addr > 65535) { 185 throw new IllegalStateException ("Value for " + type + " out of " + 186 "valid range: " + addr); 187 } 188 } 189 190 private void clean() { 191 if (mCleanEntries != null) { 192 return; 193 } 194 195 197 int size = mEntries.size(); 198 mCleanEntries = new ArrayList (size); 199 mRangeCount = 0; 200 201 outer: 202 for (int i=0; i<size; i++) { 203 Entry entry = (Entry)mEntries.get(i); 204 LocalVariable localVar = entry.mLocalVar; 205 206 Set ranges = localVar.getLocationRangeSet(); 207 if (ranges == null || ranges.size() == 0) { 208 continue; 209 } 210 211 Iterator it = ranges.iterator(); 212 while (it.hasNext()) { 213 LocationRange range = (LocationRange)it.next(); 214 215 Location startLocation = range.getStartLocation(); 216 Location endLocation = range.getEndLocation(); 217 218 if (startLocation == null || endLocation == null) { 219 continue outer; 220 } 221 222 int start_pc = startLocation.getLocation(); 223 int length = endLocation.getLocation() - start_pc - 1; 224 225 if (length < 0) { 226 continue outer; 227 } 228 } 229 230 mCleanEntries.add(entry); 231 mRangeCount += entry.getRangeCount(); 232 } 233 } 234 235 private static class Entry { 236 public LocalVariable mLocalVar; 237 public ConstantUTFInfo mName; 238 public ConstantUTFInfo mDescriptor; 239 240 public Entry(LocalVariable localVar, 241 ConstantUTFInfo name, ConstantUTFInfo descriptor) { 242 243 mLocalVar = localVar; 244 mName = name; 245 mDescriptor = descriptor; 246 } 247 248 public int getRangeCount() { 249 return mLocalVar.getLocationRangeSet().size(); 250 } 251 } 252 } 253 | Popular Tags |