1.1 --- a/classfile.py Sat Oct 23 21:34:47 2004 +0200
1.2 +++ b/classfile.py Mon Oct 25 20:53:58 2004 +0200
1.3 @@ -18,16 +18,28 @@
1.4 def u4(data):
1.5 return struct.unpack(">L", data[0:4])[0]
1.6
1.7 +# Useful mix-ins.
1.8 +
1.9 +class NameUtils:
1.10 + def get_name(self):
1.11 + if self.name_index != 0:
1.12 + return unicode(self.class_file.constants[self.name_index - 1])
1.13 + else:
1.14 + # Some name indexes are zero to indicate special conditions.
1.15 + return None
1.16 +
1.17 # Constant information.
1.18 # Objects of these classes are not directly aware of the class they reside in.
1.19
1.20 -class ClassInfo:
1.21 - def init(self, data):
1.22 +class ClassInfo(NameUtils):
1.23 + def init(self, data, class_file):
1.24 + self.class_file = class_file
1.25 self.name_index = u2(data[0:2])
1.26 return data[2:]
1.27
1.28 class RefInfo:
1.29 - def init(self, data):
1.30 + def init(self, data, class_file):
1.31 + self.class_file = class_file
1.32 self.class_index = u2(data[0:2])
1.33 self.name_and_type_index = u2(data[2:4])
1.34 return data[4:]
1.35 @@ -41,14 +53,16 @@
1.36 class InterfaceMethodRefInfo(RefInfo):
1.37 pass
1.38
1.39 -class NameAndTypeInfo:
1.40 - def init(self, data):
1.41 +class NameAndTypeInfo(NameUtils):
1.42 + def init(self, data, class_file):
1.43 + self.class_file = class_file
1.44 self.name_index = u2(data[0:2])
1.45 self.descriptor_index = u2(data[2:4])
1.46 return data[4:]
1.47
1.48 class Utf8Info:
1.49 - def init(self, data):
1.50 + def init(self, data, class_file):
1.51 + self.class_file = class_file
1.52 self.length = u2(data[0:2])
1.53 self.bytes = data[2:2+self.length]
1.54 return data[2+self.length:]
1.55 @@ -60,12 +74,14 @@
1.56 return unicode(self.bytes, "utf-8")
1.57
1.58 class StringInfo:
1.59 - def init(self, data):
1.60 + def init(self, data, class_file):
1.61 + self.class_file = class_file
1.62 self.string_index = u2(data[0:2])
1.63 return data[2:]
1.64
1.65 class SmallNumInfo:
1.66 - def init(self, data):
1.67 + def init(self, data, class_file):
1.68 + self.class_file = class_file
1.69 self.bytes = u4(data[0:4])
1.70 return data[4:]
1.71
1.72 @@ -76,7 +92,8 @@
1.73 pass
1.74
1.75 class LargeNumInfo:
1.76 - def init(self, data):
1.77 + def init(self, data, class_file):
1.78 + self.class_file = class_file
1.79 self.high_bytes = u4(data[0:4])
1.80 self.low_bytes = u4(data[4:8])
1.81 return data[8:]
1.82 @@ -90,7 +107,7 @@
1.83 # Other information.
1.84 # Objects of these classes are generally aware of the class they reside in.
1.85
1.86 -class ItemInfo:
1.87 +class ItemInfo(NameUtils):
1.88 def init(self, data, class_file):
1.89 self.class_file = class_file
1.90 self.access_flags = u2(data[0:2])
1.91 @@ -153,11 +170,6 @@
1.92 else:
1.93 return None, s
1.94
1.95 - # Processed details.
1.96 -
1.97 - def get_name(self):
1.98 - return unicode(self.class_file.constants[self.name_index - 1])
1.99 -
1.100 class FieldInfo(ItemInfo):
1.101 def get_descriptor(self):
1.102 return self._get_field_descriptor(unicode(self.class_file.constants[self.descriptor_index - 1]))
1.103 @@ -174,8 +186,12 @@
1.104
1.105 # NOTE: Decode the different attribute formats.
1.106
1.107 -class SourceFileAttributeInfo(AttributeInfo):
1.108 - pass
1.109 +class SourceFileAttributeInfo(AttributeInfo, NameUtils):
1.110 + def init(self, data, class_file):
1.111 + self.class_file = class_file
1.112 + self.attribute_length = u4(data[0:4])
1.113 + # Permit the NameUtils mix-in.
1.114 + self.name_index = self.sourcefile_index = u2(data[4:6])
1.115
1.116 class ConstantValueAttributeInfo(AttributeInfo):
1.117 def init(self, data, class_file):
1.118 @@ -199,6 +215,7 @@
1.119 for i in range(0, self.exception_table_length):
1.120 exception = ExceptionInfo()
1.121 data = exception.init(data)
1.122 + self.exception_table.append(exception)
1.123 self.attributes, data = self.class_file._get_attributes(data)
1.124 return data
1.125
1.126 @@ -219,24 +236,53 @@
1.127 return self.class_file.constants[exception_index - 1]
1.128
1.129 class InnerClassesAttributeInfo(AttributeInfo):
1.130 - pass
1.131 + def init(self, data, class_file):
1.132 + self.class_file = class_file
1.133 + self.attribute_length = u4(data[0:4])
1.134 + self.number_of_classes = u2(data[4:6])
1.135 + self.classes = []
1.136 + data = data[6:]
1.137 + for i in range(0, self.number_of_classes):
1.138 + inner_class = InnerClassInfo()
1.139 + data = inner_class.init(data, self.class_file)
1.140 + self.classes.append(inner_class)
1.141 + return data
1.142
1.143 class SyntheticAttributeInfo(AttributeInfo):
1.144 pass
1.145
1.146 class LineNumberAttributeInfo(AttributeInfo):
1.147 - pass
1.148 + def init(self, data, class_file):
1.149 + self.class_file = class_file
1.150 + self.attribute_length = u4(data[0:4])
1.151 + self.line_number_table_length = u2(data[4:6])
1.152 + self.line_number_table = []
1.153 + data = data[6:]
1.154 + for i in range(0, self.line_number_table_length):
1.155 + line_number = LineNumberInfo()
1.156 + data = line_number.init(data)
1.157 + self.line_number_table.append(line_number)
1.158 + return data
1.159
1.160 class LocalVariableAttributeInfo(AttributeInfo):
1.161 - pass
1.162 + def init(self, data, class_file):
1.163 + self.class_file = class_file
1.164 + self.attribute_length = u4(data[0:4])
1.165 + self.local_variable_table_length = u2(data[4:6])
1.166 + self.local_variable_table = []
1.167 + data = data[6:]
1.168 + for i in range(0, self.local_variable_table_length):
1.169 + local_variable = LocalVariableInfo()
1.170 + data = local_variable.init(data)
1.171 + self.local_variable_table.append(local_variable)
1.172 + return data
1.173
1.174 class DeprecatedAttributeInfo(AttributeInfo):
1.175 pass
1.176
1.177 +# Child classes of the attribute information classes.
1.178 +
1.179 class ExceptionInfo:
1.180 - def __init__(self):
1.181 - self.start_pc, self.end_pc, self.handler_pc, self.catch_type = None, None, None, None
1.182 -
1.183 def init(self, data):
1.184 self.start_pc = u2(data[0:2])
1.185 self.end_pc = u2(data[2:4])
1.186 @@ -244,6 +290,37 @@
1.187 self.catch_type = u2(data[6:8])
1.188 return data[8:]
1.189
1.190 +class InnerClassInfo(NameUtils):
1.191 + def init(self, data, class_file):
1.192 + self.class_file = class_file
1.193 + self.inner_class_info_index = u2(data[0:2])
1.194 + self.outer_class_info_index = u2(data[2:4])
1.195 + # Permit the NameUtils mix-in.
1.196 + self.name_index = self.inner_name_index = u2(data[4:6])
1.197 + self.inner_class_access_flags = u2(data[6:8])
1.198 + return data[8:]
1.199 +
1.200 +class LineNumberInfo:
1.201 + def init(self, data):
1.202 + self.start_pc = u2(data[0:2])
1.203 + self.line_number = u2(data[2:4])
1.204 + return data[4:]
1.205 +
1.206 +class LocalVariableInfo(NameUtils):
1.207 + def init(self, data, class_file):
1.208 + self.class_file = class_file
1.209 + self.start_pc = u2(data[0:2])
1.210 + self.length = u2(data[2:4])
1.211 + self.name_index = u2(data[4:6])
1.212 + self.descriptor_index = u2(data[6:8])
1.213 + self.index = u2(data[8:10])
1.214 + return data[10:]
1.215 +
1.216 + def get_descriptor(self):
1.217 + return self._get_field_descriptor(unicode(self.class_file.constants[self.descriptor_index - 1]))
1.218 +
1.219 +# Exceptions.
1.220 +
1.221 class UnknownTag(Exception):
1.222 pass
1.223
1.224 @@ -298,7 +375,10 @@
1.225 const = NameAndTypeInfo()
1.226 else:
1.227 raise UnknownTag, tag
1.228 - s = const.init(s[1:])
1.229 +
1.230 + # Initialise the constant object.
1.231 +
1.232 + s = const.init(s[1:], self)
1.233 return const, s
1.234
1.235 def _get_constants_from_table(self, count, s):