javaclass

Changeset

2:928489775f5d
2004-10-25 Paul Boddie raw files shortlog changelog graph Fixed exception table population for CodeAttributeInfo. Added specific support in other AttributeInfo classes. Introduced the class file object into constant objects so that they may more directly support get_name and other convenience methods.
classfile.py (file)
     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):