1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/javaclass/classfile.py Fri Jan 21 17:05:06 2005 +0100
1.3 @@ -0,0 +1,633 @@
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