1.1 --- a/classfile.py Fri Jan 21 17:04:41 2005 +0100
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,633 +0,0 @@
1.4 -#!/usr/bin/env python
1.5 -
1.6 -"""
1.7 -Java class file decoder. Specification found at the following URL:
1.8 -http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html
1.9 -"""
1.10 -
1.11 -import struct # for general decoding of class files
1.12 -
1.13 -# Utility functions.
1.14 -
1.15 -def u1(data):
1.16 - return struct.unpack(">B", data[0:1])[0]
1.17 -
1.18 -def u2(data):
1.19 - return struct.unpack(">H", data[0:2])[0]
1.20 -
1.21 -def s2(data):
1.22 - return struct.unpack(">h", data[0:2])[0]
1.23 -
1.24 -def u4(data):
1.25 - return struct.unpack(">L", data[0:4])[0]
1.26 -
1.27 -def s4(data):
1.28 - return struct.unpack(">l", data[0:4])[0]
1.29 -
1.30 -def s8(data):
1.31 - return struct.unpack(">q", data[0:8])[0]
1.32 -
1.33 -def f4(data):
1.34 - return struct.unpack(">f", data[0:4])[0]
1.35 -
1.36 -def f8(data):
1.37 - return struct.unpack(">d", data[0:8])[0]
1.38 -
1.39 -# Useful tables and constants.
1.40 -
1.41 -descriptor_base_type_mapping = {
1.42 - "B" : "int",
1.43 - "C" : "str",
1.44 - "D" : "float",
1.45 - "F" : "float",
1.46 - "I" : "int",
1.47 - "J" : "int",
1.48 - "L" : "object",
1.49 - "S" : "int",
1.50 - "Z" : "bool",
1.51 - "[" : "list"
1.52 - }
1.53 -
1.54 -PUBLIC, PRIVATE, PROTECTED, STATIC, FINAL, SUPER, SYNCHRONIZED, VOLATILE, TRANSIENT, NATIVE, INTERFACE, ABSTRACT, STRICT = \
1.55 -0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800
1.56 -
1.57 -def has_flags(flags, desired):
1.58 - desired_flags = reduce(lambda a, b: a | b, desired, 0)
1.59 - return (flags & desired_flags) == desired_flags
1.60 -
1.61 -# Useful mix-ins.
1.62 -
1.63 -class PythonMethodUtils:
1.64 - symbol_sep = "___" # was "$"
1.65 - type_sep = "__" # replaces "/"
1.66 - array_sep = "_array_" # was "[]"
1.67 - base_seps = ("_", "_") # was "<" and ">"
1.68 -
1.69 - def get_unqualified_python_name(self):
1.70 - name = self.get_name()
1.71 - if str(name) == "<init>":
1.72 - return "__init__"
1.73 - elif str(name) == "<clinit>":
1.74 - return "__clinit__"
1.75 - else:
1.76 - return str(name)
1.77 -
1.78 - def get_python_name(self):
1.79 - name = self.get_unqualified_python_name()
1.80 - if name == "__clinit__":
1.81 - return name
1.82 - return name + self.symbol_sep + self._get_descriptor_as_name()
1.83 -
1.84 - def _get_descriptor_as_name(self):
1.85 - l = []
1.86 - for descriptor_type in self.get_descriptor()[0]:
1.87 - l.append(self._get_type_as_name(descriptor_type))
1.88 - return self.symbol_sep.join(l)
1.89 -
1.90 - def _get_type_as_name(self, descriptor_type, s=""):
1.91 - base_type, object_type, array_type = descriptor_type
1.92 - if base_type == "L":
1.93 - return object_type.replace("/", self.type_sep) + s
1.94 - elif base_type == "[":
1.95 - return self._get_type_as_name(array_type, s + self.array_sep)
1.96 - else:
1.97 - return self.base_seps[0] + base_type + self.base_seps[1] + s
1.98 -
1.99 -class PythonNameUtils:
1.100 - def get_python_name(self):
1.101 - # NOTE: This may not be comprehensive.
1.102 - if not str(self.get_name()).startswith("["):
1.103 - return str(self.get_name()).replace("/", ".")
1.104 - else:
1.105 - return self._get_type_name(
1.106 - get_field_descriptor(
1.107 - str(self.get_name())
1.108 - )
1.109 - ).replace("/", ".")
1.110 -
1.111 - def _get_type_name(self, descriptor_type):
1.112 - base_type, object_type, array_type = descriptor_type
1.113 - if base_type == "L":
1.114 - return object_type
1.115 - elif base_type == "[":
1.116 - return self._get_type_name(array_type)
1.117 - else:
1.118 - return descriptor_base_type_mapping[base_type]
1.119 -
1.120 -class NameUtils:
1.121 - def get_name(self):
1.122 - if self.name_index != 0:
1.123 - return self.class_file.constants[self.name_index - 1]
1.124 - else:
1.125 - # Some name indexes are zero to indicate special conditions.
1.126 - return None
1.127 -
1.128 -class NameAndTypeUtils:
1.129 - def get_name(self):
1.130 - if self.name_and_type_index != 0:
1.131 - return self.class_file.constants[self.name_and_type_index - 1].get_name()
1.132 - else:
1.133 - # Some name indexes are zero to indicate special conditions.
1.134 - return None
1.135 -
1.136 - def get_field_descriptor(self):
1.137 - if self.name_and_type_index != 0:
1.138 - return self.class_file.constants[self.name_and_type_index - 1].get_field_descriptor()
1.139 - else:
1.140 - # Some name indexes are zero to indicate special conditions.
1.141 - return None
1.142 -
1.143 - def get_method_descriptor(self):
1.144 - if self.name_and_type_index != 0:
1.145 - return self.class_file.constants[self.name_and_type_index - 1].get_method_descriptor()
1.146 - else:
1.147 - # Some name indexes are zero to indicate special conditions.
1.148 - return None
1.149 -
1.150 - def get_class(self):
1.151 - return self.class_file.constants[self.class_index - 1]
1.152 -
1.153 -# Symbol parsing.
1.154 -
1.155 -def get_method_descriptor(s):
1.156 - assert s[0] == "("
1.157 - params = []
1.158 - s = s[1:]
1.159 - while s[0] != ")":
1.160 - parameter_descriptor, s = _get_parameter_descriptor(s)
1.161 - params.append(parameter_descriptor)
1.162 - if s[1] != "V":
1.163 - return_type, s = _get_field_type(s[1:])
1.164 - else:
1.165 - return_type, s = None, s[1:]
1.166 - return params, return_type
1.167 -
1.168 -def get_field_descriptor(s):
1.169 - return _get_field_type(s)[0]
1.170 -
1.171 -def _get_parameter_descriptor(s):
1.172 - return _get_field_type(s)
1.173 -
1.174 -def _get_component_type(s):
1.175 - return _get_field_type(s)
1.176 -
1.177 -def _get_field_type(s):
1.178 - base_type, s = _get_base_type(s)
1.179 - object_type = None
1.180 - array_type = None
1.181 - if base_type == "L":
1.182 - object_type, s = _get_object_type(s)
1.183 - elif base_type == "[":
1.184 - array_type, s = _get_array_type(s)
1.185 - return (base_type, object_type, array_type), s
1.186 -
1.187 -def _get_base_type(s):
1.188 - if len(s) > 0:
1.189 - return s[0], s[1:]
1.190 - else:
1.191 - return None, s
1.192 -
1.193 -def _get_object_type(s):
1.194 - if len(s) > 0:
1.195 - s_end = s.find(";")
1.196 - assert s_end != -1
1.197 - return s[:s_end], s[s_end+1:]
1.198 - else:
1.199 - return None, s
1.200 -
1.201 -def _get_array_type(s):
1.202 - if len(s) > 0:
1.203 - return _get_component_type(s)
1.204 - else:
1.205 - return None, s
1.206 -
1.207 -# Constant information.
1.208 -
1.209 -class ClassInfo(NameUtils, PythonNameUtils):
1.210 - def init(self, data, class_file):
1.211 - self.class_file = class_file
1.212 - self.name_index = u2(data[0:2])
1.213 - return data[2:]
1.214 -
1.215 -class RefInfo(NameAndTypeUtils):
1.216 - def init(self, data, class_file):
1.217 - self.class_file = class_file
1.218 - self.class_index = u2(data[0:2])
1.219 - self.name_and_type_index = u2(data[2:4])
1.220 - return data[4:]
1.221 -
1.222 -class FieldRefInfo(RefInfo, PythonNameUtils):
1.223 - def get_descriptor(self):
1.224 - return RefInfo.get_field_descriptor(self)
1.225 -
1.226 -class MethodRefInfo(RefInfo, PythonMethodUtils):
1.227 - def get_descriptor(self):
1.228 - return RefInfo.get_method_descriptor(self)
1.229 -
1.230 -class InterfaceMethodRefInfo(MethodRefInfo):
1.231 - pass
1.232 -
1.233 -class NameAndTypeInfo(NameUtils, PythonNameUtils):
1.234 - def init(self, data, class_file):
1.235 - self.class_file = class_file
1.236 - self.name_index = u2(data[0:2])
1.237 - self.descriptor_index = u2(data[2:4])
1.238 - return data[4:]
1.239 -
1.240 - def get_field_descriptor(self):
1.241 - return get_field_descriptor(unicode(self.class_file.constants[self.descriptor_index - 1]))
1.242 -
1.243 - def get_method_descriptor(self):
1.244 - return get_method_descriptor(unicode(self.class_file.constants[self.descriptor_index - 1]))
1.245 -
1.246 -class Utf8Info:
1.247 - def init(self, data, class_file):
1.248 - self.class_file = class_file
1.249 - self.length = u2(data[0:2])
1.250 - self.bytes = data[2:2+self.length]
1.251 - return data[2+self.length:]
1.252 -
1.253 - def __str__(self):
1.254 - return self.bytes
1.255 -
1.256 - def __unicode__(self):
1.257 - return unicode(self.bytes, "utf-8")
1.258 -
1.259 - def get_value(self):
1.260 - return str(self)
1.261 -
1.262 -class StringInfo:
1.263 - def init(self, data, class_file):
1.264 - self.class_file = class_file
1.265 - self.string_index = u2(data[0:2])
1.266 - return data[2:]
1.267 -
1.268 - def __str__(self):
1.269 - return str(self.class_file.constants[self.string_index - 1])
1.270 -
1.271 - def __unicode__(self):
1.272 - return unicode(self.class_file.constants[self.string_index - 1])
1.273 -
1.274 - def get_value(self):
1.275 - return str(self)
1.276 -
1.277 -class SmallNumInfo:
1.278 - def init(self, data, class_file):
1.279 - self.class_file = class_file
1.280 - self.bytes = data[0:4]
1.281 - return data[4:]
1.282 -
1.283 -class IntegerInfo(SmallNumInfo):
1.284 - def get_value(self):
1.285 - return s4(self.bytes)
1.286 -
1.287 -class FloatInfo(SmallNumInfo):
1.288 - def get_value(self):
1.289 - return f4(self.bytes)
1.290 -
1.291 -class LargeNumInfo:
1.292 - def init(self, data, class_file):
1.293 - self.class_file = class_file
1.294 - self.high_bytes = data[0:4]
1.295 - self.low_bytes = data[4:8]
1.296 - return data[8:]
1.297 -
1.298 -class LongInfo(LargeNumInfo):
1.299 - def get_value(self):
1.300 - return s8(self.high_bytes + self.low_bytes)
1.301 -
1.302 -class DoubleInfo(LargeNumInfo):
1.303 - def get_value(self):
1.304 - return f8(self.high_bytes + self.low_bytes)
1.305 -
1.306 -# Other information.
1.307 -# Objects of these classes are generally aware of the class they reside in.
1.308 -
1.309 -class ItemInfo(NameUtils):
1.310 - def init(self, data, class_file):
1.311 - self.class_file = class_file
1.312 - self.access_flags = u2(data[0:2])
1.313 - self.name_index = u2(data[2:4])
1.314 - self.descriptor_index = u2(data[4:6])
1.315 - self.attributes, data = self.class_file._get_attributes(data[6:])
1.316 - return data
1.317 -
1.318 -class FieldInfo(ItemInfo, PythonNameUtils):
1.319 - def get_descriptor(self):
1.320 - return get_field_descriptor(unicode(self.class_file.constants[self.descriptor_index - 1]))
1.321 -
1.322 -class MethodInfo(ItemInfo, PythonMethodUtils):
1.323 - def get_descriptor(self):
1.324 - return get_method_descriptor(unicode(self.class_file.constants[self.descriptor_index - 1]))
1.325 -
1.326 -class AttributeInfo:
1.327 - def init(self, data, class_file):
1.328 - self.attribute_length = u4(data[0:4])
1.329 - self.info = data[4:4+self.attribute_length]
1.330 - return data[4+self.attribute_length:]
1.331 -
1.332 -# NOTE: Decode the different attribute formats.
1.333 -
1.334 -class SourceFileAttributeInfo(AttributeInfo, NameUtils, PythonNameUtils):
1.335 - def init(self, data, class_file):
1.336 - self.class_file = class_file
1.337 - self.attribute_length = u4(data[0:4])
1.338 - # Permit the NameUtils mix-in.
1.339 - self.name_index = self.sourcefile_index = u2(data[4:6])
1.340 - return data[6:]
1.341 -
1.342 -class ConstantValueAttributeInfo(AttributeInfo):
1.343 - def init(self, data, class_file):
1.344 - self.class_file = class_file
1.345 - self.attribute_length = u4(data[0:4])
1.346 - self.constant_value_index = u2(data[4:6])
1.347 - assert 4+self.attribute_length == 6
1.348 - return data[4+self.attribute_length:]
1.349 -
1.350 - def get_value(self):
1.351 - return self.class_file.constants[self.constant_value_index - 1].get_value()
1.352 -
1.353 -class CodeAttributeInfo(AttributeInfo):
1.354 - def init(self, data, class_file):
1.355 - self.class_file = class_file
1.356 - self.attribute_length = u4(data[0:4])
1.357 - self.max_stack = u2(data[4:6])
1.358 - self.max_locals = u2(data[6:8])
1.359 - self.code_length = u4(data[8:12])
1.360 - end_of_code = 12+self.code_length
1.361 - self.code = data[12:end_of_code]
1.362 - self.exception_table_length = u2(data[end_of_code:end_of_code+2])
1.363 - self.exception_table = []
1.364 - data = data[end_of_code + 2:]
1.365 - for i in range(0, self.exception_table_length):
1.366 - exception = ExceptionInfo()
1.367 - data = exception.init(data)
1.368 - self.exception_table.append(exception)
1.369 - self.attributes, data = self.class_file._get_attributes(data)
1.370 - return data
1.371 -
1.372 -class ExceptionsAttributeInfo(AttributeInfo):
1.373 - def init(self, data, class_file):
1.374 - self.class_file = class_file
1.375 - self.attribute_length = u4(data[0:4])
1.376 - self.number_of_exceptions = u2(data[4:6])
1.377 - self.exception_index_table = []
1.378 - index = 6
1.379 - for i in range(0, self.number_of_exceptions):
1.380 - self.exception_index_table.append(u2(data[index:index+2]))
1.381 - index += 2
1.382 - return data[index:]
1.383 -
1.384 - def get_exception(self, i):
1.385 - exception_index = self.exception_index_table[i]
1.386 - return self.class_file.constants[exception_index - 1]
1.387 -
1.388 -class InnerClassesAttributeInfo(AttributeInfo):
1.389 - def init(self, data, class_file):
1.390 - self.class_file = class_file
1.391 - self.attribute_length = u4(data[0:4])
1.392 - self.number_of_classes = u2(data[4:6])
1.393 - self.classes = []
1.394 - data = data[6:]
1.395 - for i in range(0, self.number_of_classes):
1.396 - inner_class = InnerClassInfo()
1.397 - data = inner_class.init(data, self.class_file)
1.398 - self.classes.append(inner_class)
1.399 - return data
1.400 -
1.401 -class SyntheticAttributeInfo(AttributeInfo):
1.402 - pass
1.403 -
1.404 -class LineNumberAttributeInfo(AttributeInfo):
1.405 - def init(self, data, class_file):
1.406 - self.class_file = class_file
1.407 - self.attribute_length = u4(data[0:4])
1.408 - self.line_number_table_length = u2(data[4:6])
1.409 - self.line_number_table = []
1.410 - data = data[6:]
1.411 - for i in range(0, self.line_number_table_length):
1.412 - line_number = LineNumberInfo()
1.413 - data = line_number.init(data)
1.414 - self.line_number_table.append(line_number)
1.415 - return data
1.416 -
1.417 -class LocalVariableAttributeInfo(AttributeInfo):
1.418 - def init(self, data, class_file):
1.419 - self.class_file = class_file
1.420 - self.attribute_length = u4(data[0:4])
1.421 - self.local_variable_table_length = u2(data[4:6])
1.422 - self.local_variable_table = []
1.423 - data = data[6:]
1.424 - for i in range(0, self.local_variable_table_length):
1.425 - local_variable = LocalVariableInfo()
1.426 - data = local_variable.init(data, self.class_file)
1.427 - self.local_variable_table.append(local_variable)
1.428 - return data
1.429 -
1.430 -class DeprecatedAttributeInfo(AttributeInfo):
1.431 - pass
1.432 -
1.433 -# Child classes of the attribute information classes.
1.434 -
1.435 -class ExceptionInfo:
1.436 - def init(self, data):
1.437 - self.start_pc = u2(data[0:2])
1.438 - self.end_pc = u2(data[2:4])
1.439 - self.handler_pc = u2(data[4:6])
1.440 - self.catch_type = u2(data[6:8])
1.441 - return data[8:]
1.442 -
1.443 -class InnerClassInfo(NameUtils):
1.444 - def init(self, data, class_file):
1.445 - self.class_file = class_file
1.446 - self.inner_class_info_index = u2(data[0:2])
1.447 - self.outer_class_info_index = u2(data[2:4])
1.448 - # Permit the NameUtils mix-in.
1.449 - self.name_index = self.inner_name_index = u2(data[4:6])
1.450 - self.inner_class_access_flags = u2(data[6:8])
1.451 - return data[8:]
1.452 -
1.453 -class LineNumberInfo:
1.454 - def init(self, data):
1.455 - self.start_pc = u2(data[0:2])
1.456 - self.line_number = u2(data[2:4])
1.457 - return data[4:]
1.458 -
1.459 -class LocalVariableInfo(NameUtils, PythonNameUtils):
1.460 - def init(self, data, class_file):
1.461 - self.class_file = class_file
1.462 - self.start_pc = u2(data[0:2])
1.463 - self.length = u2(data[2:4])
1.464 - self.name_index = u2(data[4:6])
1.465 - self.descriptor_index = u2(data[6:8])
1.466 - self.index = u2(data[8:10])
1.467 - return data[10:]
1.468 -
1.469 - def get_descriptor(self):
1.470 - return get_field_descriptor(unicode(self.class_file.constants[self.descriptor_index - 1]))
1.471 -
1.472 -# Exceptions.
1.473 -
1.474 -class UnknownTag(Exception):
1.475 - pass
1.476 -
1.477 -class UnknownAttribute(Exception):
1.478 - pass
1.479 -
1.480 -# Abstractions for the main structures.
1.481 -
1.482 -class ClassFile:
1.483 -
1.484 - "A class representing a Java class file."
1.485 -
1.486 - def __init__(self, s):
1.487 -
1.488 - """
1.489 - Process the given string 's', populating the object with the class
1.490 - file's details.
1.491 - """
1.492 -
1.493 - self.constants, s = self._get_constants(s[8:])
1.494 - self.access_flags, s = self._get_access_flags(s)
1.495 - self.this_class, s = self._get_this_class(s)
1.496 - self.super_class, s = self._get_super_class(s)
1.497 - self.interfaces, s = self._get_interfaces(s)
1.498 - self.fields, s = self._get_fields(s)
1.499 - self.methods, s = self._get_methods(s)
1.500 - self.attributes, s = self._get_attributes(s)
1.501 -
1.502 - def _decode_const(self, s):
1.503 - tag = u1(s[0:1])
1.504 - if tag == 1:
1.505 - const = Utf8Info()
1.506 - elif tag == 3:
1.507 - const = IntegerInfo()
1.508 - elif tag == 4:
1.509 - const = FloatInfo()
1.510 - elif tag == 5:
1.511 - const = LongInfo()
1.512 - elif tag == 6:
1.513 - const = DoubleInfo()
1.514 - elif tag == 7:
1.515 - const = ClassInfo()
1.516 - elif tag == 8:
1.517 - const = StringInfo()
1.518 - elif tag == 9:
1.519 - const = FieldRefInfo()
1.520 - elif tag == 10:
1.521 - const = MethodRefInfo()
1.522 - elif tag == 11:
1.523 - const = InterfaceMethodRefInfo()
1.524 - elif tag == 12:
1.525 - const = NameAndTypeInfo()
1.526 - else:
1.527 - raise UnknownTag, tag
1.528 -
1.529 - # Initialise the constant object.
1.530 -
1.531 - s = const.init(s[1:], self)
1.532 - return const, s
1.533 -
1.534 - def _get_constants_from_table(self, count, s):
1.535 - l = []
1.536 - # Have to skip certain entries specially.
1.537 - i = 1
1.538 - while i < count:
1.539 - c, s = self._decode_const(s)
1.540 - l.append(c)
1.541 - # Add a blank entry after "large" entries.
1.542 - if isinstance(c, LargeNumInfo):
1.543 - l.append(None)
1.544 - i += 1
1.545 - i += 1
1.546 - return l, s
1.547 -
1.548 - def _get_items_from_table(self, cls, number, s):
1.549 - l = []
1.550 - for i in range(0, number):
1.551 - f = cls()
1.552 - s = f.init(s, self)
1.553 - l.append(f)
1.554 - return l, s
1.555 -
1.556 - def _get_methods_from_table(self, number, s):
1.557 - return self._get_items_from_table(MethodInfo, number, s)
1.558 -
1.559 - def _get_fields_from_table(self, number, s):
1.560 - return self._get_items_from_table(FieldInfo, number, s)
1.561 -
1.562 - def _get_attribute_from_table(self, s):
1.563 - attribute_name_index = u2(s[0:2])
1.564 - constant_name = self.constants[attribute_name_index - 1].bytes
1.565 - if constant_name == "SourceFile":
1.566 - attribute = SourceFileAttributeInfo()
1.567 - elif constant_name == "ConstantValue":
1.568 - attribute = ConstantValueAttributeInfo()
1.569 - elif constant_name == "Code":
1.570 - attribute = CodeAttributeInfo()
1.571 - elif constant_name == "Exceptions":
1.572 - attribute = ExceptionsAttributeInfo()
1.573 - elif constant_name == "InnerClasses":
1.574 - attribute = InnerClassesAttributeInfo()
1.575 - elif constant_name == "Synthetic":
1.576 - attribute = SyntheticAttributeInfo()
1.577 - elif constant_name == "LineNumberTable":
1.578 - attribute = LineNumberAttributeInfo()
1.579 - elif constant_name == "LocalVariableTable":
1.580 - attribute = LocalVariableAttributeInfo()
1.581 - elif constant_name == "Deprecated":
1.582 - attribute = DeprecatedAttributeInfo()
1.583 - else:
1.584 - raise UnknownAttribute, constant_name
1.585 - s = attribute.init(s[2:], self)
1.586 - return attribute, s
1.587 -
1.588 - def _get_attributes_from_table(self, number, s):
1.589 - attributes = []
1.590 - for i in range(0, number):
1.591 - attribute, s = self._get_attribute_from_table(s)
1.592 - attributes.append(attribute)
1.593 - return attributes, s
1.594 -
1.595 - def _get_constants(self, s):
1.596 - count = u2(s[0:2])
1.597 - return self._get_constants_from_table(count, s[2:])
1.598 -
1.599 - def _get_access_flags(self, s):
1.600 - return u2(s[0:2]), s[2:]
1.601 -
1.602 - def _get_this_class(self, s):
1.603 - index = u2(s[0:2])
1.604 - return self.constants[index - 1], s[2:]
1.605 -
1.606 - _get_super_class = _get_this_class
1.607 -
1.608 - def _get_interfaces(self, s):
1.609 - interfaces = []
1.610 - number = u2(s[0:2])
1.611 - s = s[2:]
1.612 - for i in range(0, number):
1.613 - index = u2(s[0:2])
1.614 - interfaces.append(self.constants[index - 1])
1.615 - s = s[2:]
1.616 - return interfaces, s
1.617 -
1.618 - def _get_fields(self, s):
1.619 - number = u2(s[0:2])
1.620 - return self._get_fields_from_table(number, s[2:])
1.621 -
1.622 - def _get_attributes(self, s):
1.623 - number = u2(s[0:2])
1.624 - return self._get_attributes_from_table(number, s[2:])
1.625 -
1.626 - def _get_methods(self, s):
1.627 - number = u2(s[0:2])
1.628 - return self._get_methods_from_table(number, s[2:])
1.629 -
1.630 -if __name__ == "__main__":
1.631 - import sys
1.632 - f = open(sys.argv[1], "rb")
1.633 - c = ClassFile(f.read())
1.634 - f.close()
1.635 -
1.636 -# vim: tabstop=4 expandtab shiftwidth=4