1 52 53 package com.go.trove.classfile; 54 55 import java.util.*; 56 import java.io.*; 57 58 66 class LocalVariableTableAttr extends Attribute { 67 private List mEntries = new ArrayList(10); 68 private List mCleanEntries; 69 private int mRangeCount; 70 71 public LocalVariableTableAttr(ConstantPool cp) { 72 super(cp, LOCAL_VARIABLE_TABLE); 73 } 74 75 78 public void addEntry(LocalVariable localVar) { 79 String varName = localVar.getName(); 80 if (varName != null) { 81 ConstantUTFInfo name = ConstantUTFInfo.make(mCp, varName); 82 ConstantUTFInfo descriptor = 83 ConstantUTFInfo.make(mCp, localVar.getType().toString()); 84 85 mEntries.add(new Entry(localVar, name, descriptor)); 86 } 87 88 mCleanEntries = null; 89 } 90 91 public int getLength() { 92 clean(); 93 return 2 + 10 * mRangeCount; 94 } 95 96 public void writeDataTo(DataOutput dout) throws IOException { 97 dout.writeShort(mRangeCount); 98 99 int size = mCleanEntries.size(); 100 for (int i=0; i<size; i++) { 101 Entry entry = (Entry)mEntries.get(i); 102 LocalVariable localVar = entry.mLocalVar; 103 104 SortedSet ranges = localVar.getLocationRangeSet(); 105 106 int name_index = entry.mName.getIndex(); 107 int descriptor_index = entry.mDescriptor.getIndex(); 108 int index = localVar.getNumber(); 109 110 check("local variable table entry name index", name_index); 111 check("local variable table entry descriptor index", 112 descriptor_index); 113 check("local variable table entry index", index); 114 115 Iterator it = ranges.iterator(); 116 while (it.hasNext()) { 117 LocationRange range = (LocationRange)it.next(); 118 119 Location startLocation = range.getStartLocation(); 120 Location endLocation = range.getEndLocation(); 121 122 int start_pc = startLocation.getLocation(); 123 int length = endLocation.getLocation() - start_pc - 1; 124 125 check("local variable table entry start PC", start_pc); 126 127 dout.writeShort(start_pc); 128 dout.writeShort(length); 129 dout.writeShort(name_index); 130 dout.writeShort(descriptor_index); 131 dout.writeShort(index); 132 } 133 } 134 } 135 136 private void check(String type, int addr) throws RuntimeException { 137 if (addr < 0 || addr > 65535) { 138 throw new RuntimeException ("Value for " + type + " out of " + 139 "valid range: " + addr); 140 } 141 } 142 143 private void clean() { 144 if (mCleanEntries != null) { 145 return; 146 } 147 148 150 int size = mEntries.size(); 151 mCleanEntries = new ArrayList(size); 152 mRangeCount = 0; 153 154 outer: 155 for (int i=0; i<size; i++) { 156 Entry entry = (Entry)mEntries.get(i); 157 LocalVariable localVar = entry.mLocalVar; 158 159 SortedSet ranges = localVar.getLocationRangeSet(); 160 if (ranges == null || ranges.size() == 0) { 161 continue; 162 } 163 164 Iterator it = ranges.iterator(); 165 while (it.hasNext()) { 166 LocationRange range = (LocationRange)it.next(); 167 168 Location startLocation = range.getStartLocation(); 169 Location endLocation = range.getEndLocation(); 170 171 if (startLocation == null || endLocation == null) { 172 continue outer; 173 } 174 175 int start_pc = startLocation.getLocation(); 176 int length = endLocation.getLocation() - start_pc - 1; 177 178 if (length < 0) { 179 continue outer; 180 } 181 } 182 183 mCleanEntries.add(entry); 184 mRangeCount += entry.getRangeCount(); 185 } 186 } 187 188 static Attribute define(ConstantPool cp, 189 String name, 190 int length, 191 DataInput din) throws IOException { 192 193 LocalVariableTableAttr locals = new LocalVariableTableAttr(cp); 194 195 int size = din.readUnsignedShort(); 196 for (int i=0; i<size; i++) { 197 int start_pc = din.readUnsignedShort(); 198 int end_pc = start_pc + din.readUnsignedShort() + 1; 199 int name_index = din.readUnsignedShort(); 200 int descriptor_index = din.readUnsignedShort(); 201 final int index = din.readUnsignedShort(); 202 203 final ConstantUTFInfo varName = 204 (ConstantUTFInfo)cp.getConstant(name_index); 205 final ConstantUTFInfo varDesc = 206 (ConstantUTFInfo)cp.getConstant(descriptor_index); 207 208 final Location startLocation = new FixedLocation(start_pc); 209 final Location endLocation = new FixedLocation(end_pc); 210 211 SortedSet ranges = new TreeSet(); 212 ranges.add(new LocationRangeImpl(startLocation, endLocation)); 213 final SortedSet fRanges = 214 Collections.unmodifiableSortedSet(ranges); 215 216 LocalVariable localVar = new LocalVariable() { 217 private String mName; 218 private TypeDescriptor mType; 219 220 { 221 mName = varName.getValue(); 222 mType = TypeDescriptor.parseTypeDesc(varDesc.getValue()); 223 } 224 225 public String getName() { 226 return mName; 227 } 228 229 public void setName(String name) { 230 mName = name; 231 } 232 233 public TypeDescriptor getType() { 234 return mType; 235 } 236 237 public boolean isDoubleWord() { 238 Class clazz = mType.getClassArg(); 239 return (clazz == double.class || clazz == long.class); 240 } 241 242 public int getNumber() { 243 return index; 244 } 245 246 public SortedSet getLocationRangeSet() { 247 return fRanges; 248 } 249 }; 250 251 Entry entry = new Entry(localVar, varName, varDesc); 252 locals.mEntries.add(entry); 253 } 254 255 return locals; 256 } 257 258 private static class Entry { 259 public LocalVariable mLocalVar; 260 public ConstantUTFInfo mName; 261 public ConstantUTFInfo mDescriptor; 262 263 public Entry(LocalVariable localVar, 264 ConstantUTFInfo name, ConstantUTFInfo descriptor) { 265 266 mLocalVar = localVar; 267 mName = name; 268 mDescriptor = descriptor; 269 } 270 271 public int getRangeCount() { 272 return mLocalVar.getLocationRangeSet().size(); 273 } 274 } 275 } 276 | Popular Tags |