javaclass

Changeset

136:754d36821fc8
2005-01-21 Paul Boddie raw files shortlog changelog graph Moved the modules into the javaclass package. Added a setup script.
bytecode.py classfile.py classhook.py runclass.py (file) setup.py (file)
     1.1 --- a/bytecode.py	Fri Jan 21 17:04:41 2005 +0100
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,2311 +0,0 @@
     1.4 -#!/usr/bin/env python
     1.5 -
     1.6 -"""
     1.7 -Java bytecode conversion. Specification found at the following URL:
     1.8 -http://java.sun.com/docs/books/vmspec/2nd-edition/html/Instructions2.doc.html
     1.9 -
    1.10 -NOTE: Synchronized constructs are not actually supported.
    1.11 -"""
    1.12 -
    1.13 -import classfile
    1.14 -from dis import cmp_op # for access to Python bytecode values and operators
    1.15 -try:
    1.16 -    from dis import opmap
    1.17 -except ImportError:
    1.18 -    from dis import opname
    1.19 -    opmap = {}
    1.20 -    for i in range(0, len(opname)):
    1.21 -        opmap[opname[i]] = i
    1.22 -from UserDict import UserDict
    1.23 -import new
    1.24 -
    1.25 -# Bytecode production classes.
    1.26 -
    1.27 -class BytecodeWriter:
    1.28 -
    1.29 -    "A Python bytecode writer."
    1.30 -
    1.31 -    def __init__(self):
    1.32 -
    1.33 -        "Initialise the writer."
    1.34 -
    1.35 -        # A stack of loop start instructions corresponding to loop blocks.
    1.36 -        self.loops = []
    1.37 -
    1.38 -        # A stack of loop block or exception block start positions.
    1.39 -        self.blocks = []
    1.40 -
    1.41 -        # A stack of exception block handler pointers.
    1.42 -        self.exception_handlers = []
    1.43 -
    1.44 -        # A dictionary mapping labels to jump instructions referencing such labels.
    1.45 -        self.jumps = {}
    1.46 -
    1.47 -        # The output values, including "lazy" subvalues which will need evaluating.
    1.48 -        self.output = []
    1.49 -
    1.50 -        # The current Python bytecode instruction position.
    1.51 -        self.position = 0
    1.52 -
    1.53 -        # Stack depth estimation.
    1.54 -        self.stack_depth = 0
    1.55 -        self.max_stack_depth = 0
    1.56 -
    1.57 -        # Local variable estimation.
    1.58 -        self.max_locals = 0
    1.59 -
    1.60 -        # Mapping from values to indexes.
    1.61 -        self.constants = {}
    1.62 -
    1.63 -        # Mapping from names to indexes.
    1.64 -        # NOTE: This may be acquired from elsewhere.
    1.65 -        #self.globals = {}
    1.66 -
    1.67 -        # Mapping from names to indexes.
    1.68 -        self.names = {}
    1.69 -
    1.70 -        # A list of constants used as exception handler return addresses.
    1.71 -        self.constants_for_exceptions = []
    1.72 -
    1.73 -        # A list of external names.
    1.74 -        self.external_names = []
    1.75 -
    1.76 -    def get_output(self):
    1.77 -
    1.78 -        "Return the output of the writer as a string."
    1.79 -
    1.80 -        output = []
    1.81 -        for element in self.output:
    1.82 -            if isinstance(element, LazySubValue):
    1.83 -                value = element.value
    1.84 -            else:
    1.85 -                value = element
    1.86 -            # NOTE: ValueError gets raised for bad values here.
    1.87 -            output.append(chr(value))
    1.88 -        return "".join(output)
    1.89 -
    1.90 -    def get_constants(self):
    1.91 -
    1.92 -        """
    1.93 -        Return a list of constants with ordering significant to the code
    1.94 -        employing them.
    1.95 -        """
    1.96 -
    1.97 -        l = self._get_list(self._invert(self.constants))
    1.98 -        result = []
    1.99 -        for i in l:
   1.100 -            if isinstance(i, LazyValue):
   1.101 -                result.append(i.get_value())
   1.102 -            else:
   1.103 -                result.append(i)
   1.104 -        return result
   1.105 -
   1.106 -    #def get_globals(self):
   1.107 -    #    return self._get_list(self._invert(self.globals))
   1.108 -
   1.109 -    def get_names(self):
   1.110 -
   1.111 -        """
   1.112 -        Return a list of names with ordering significant to the code employing
   1.113 -        them.
   1.114 -        """
   1.115 -
   1.116 -        return self._get_list(self._invert(self.names))
   1.117 -
   1.118 -    def _invert(self, d):
   1.119 -
   1.120 -        """
   1.121 -        Return a new dictionary whose key-to-value mapping is in the inverse of
   1.122 -        that found in 'd'.
   1.123 -        """
   1.124 -
   1.125 -        inverted = {}
   1.126 -        for k, v in d.items():
   1.127 -            inverted[v] = k
   1.128 -        return inverted
   1.129 -
   1.130 -    def _get_list(self, d):
   1.131 -
   1.132 -        """
   1.133 -        Traverse the dictionary 'd' returning a list whose values appear at the
   1.134 -        position denoted by each value's key in 'd'.
   1.135 -        """
   1.136 -
   1.137 -        l = []
   1.138 -        for i in range(0, len(d.keys())):
   1.139 -            l.append(d[i])
   1.140 -        return l
   1.141 -
   1.142 -    # Administrative methods.
   1.143 -
   1.144 -    def update_stack_depth(self, change):
   1.145 -
   1.146 -        """
   1.147 -        Given the stated 'change' in stack depth, update the maximum stack depth
   1.148 -        where appropriate.
   1.149 -        """
   1.150 -
   1.151 -        self.stack_depth += change
   1.152 -        if self.stack_depth > self.max_stack_depth:
   1.153 -            self.max_stack_depth = self.stack_depth
   1.154 -
   1.155 -    def update_locals(self, index):
   1.156 -
   1.157 -        """
   1.158 -        Given the stated 'index' of a local variable, update the maximum local
   1.159 -        variable index where appropriate.
   1.160 -        """
   1.161 -
   1.162 -        if index > self.max_locals:
   1.163 -            self.max_locals = index
   1.164 -
   1.165 -    # Special methods.
   1.166 -
   1.167 -    def _write_value(self, value):
   1.168 -
   1.169 -        """
   1.170 -        Write the given 'value' at the current output position.
   1.171 -        """
   1.172 -
   1.173 -        if isinstance(value, LazyValue):
   1.174 -            # NOTE: Assume a 16-bit value.
   1.175 -            self.output.append(value.values[0])
   1.176 -            self.output.append(value.values[1])
   1.177 -            self.position += 2
   1.178 -        elif value <= 0xffff:
   1.179 -            self.output.append(value & 0xff)
   1.180 -            self.output.append((value & 0xff00) >> 8)
   1.181 -            self.position += 2
   1.182 -        else:
   1.183 -            # NOTE: EXTENDED_ARG not yet supported.
   1.184 -            raise ValueError, value
   1.185 -
   1.186 -    def _rewrite_value(self, position, value):
   1.187 -
   1.188 -        """
   1.189 -        At the given output 'position', rewrite the given 'value'.
   1.190 -        """
   1.191 -
   1.192 -        # NOTE: Assume a 16-bit value.
   1.193 -        if value <= 0xffff:
   1.194 -            self.output[position] = (value & 0xff)
   1.195 -            self.output[position + 1] = ((value & 0xff00) >> 8)
   1.196 -        else:
   1.197 -            # NOTE: EXTENDED_ARG not yet supported.
   1.198 -            raise ValueError, value
   1.199 -
   1.200 -    # Higher level methods.
   1.201 -
   1.202 -    def use_external_name(self, name):
   1.203 -        # NOTE: Remove array and object indicators.
   1.204 -        self.external_names.append(name)
   1.205 -
   1.206 -    def setup_loop(self):
   1.207 -        self.loops.append(self.position)
   1.208 -        self.output.append(opmap["SETUP_LOOP"])
   1.209 -        self.position += 1
   1.210 -        self._write_value(0) # To be filled in later
   1.211 -
   1.212 -    def end_loop(self):
   1.213 -        current_loop_start = self.loops.pop()
   1.214 -        current_loop_real_start = self.blocks.pop()
   1.215 -        #print "<", self.blocks, current_loop_real_start
   1.216 -        # Fix the iterator delta.
   1.217 -        # NOTE: Using 3 as the assumed length of the FOR_ITER instruction.
   1.218 -        self.jump_absolute(current_loop_real_start)
   1.219 -        self._rewrite_value(current_loop_real_start + 1, self.position - current_loop_real_start - 3)
   1.220 -        self.pop_block()
   1.221 -        # Fix the loop delta.
   1.222 -        # NOTE: Using 3 as the assumed length of the SETUP_LOOP instruction.
   1.223 -        self._rewrite_value(current_loop_start + 1, self.position - current_loop_start - 3)
   1.224 -
   1.225 -    def jump_to_label(self, status, name):
   1.226 -        # Record the instruction using the jump.
   1.227 -        jump_instruction = self.position
   1.228 -        if status is None:
   1.229 -            self.jump_forward()
   1.230 -        elif status:
   1.231 -            self.jump_if_true()
   1.232 -        else:
   1.233 -            self.jump_if_false()
   1.234 -        # Record the following instruction, too.
   1.235 -        if not self.jumps.has_key(name):
   1.236 -            self.jumps[name] = []
   1.237 -        self.jumps[name].append((jump_instruction, self.position))
   1.238 -
   1.239 -    def start_label(self, name):
   1.240 -        # Fill in all jump instructions.
   1.241 -        for jump_instruction, following_instruction in self.jumps[name]:
   1.242 -            self._rewrite_value(jump_instruction + 1, self.position - following_instruction)
   1.243 -        del self.jumps[name]
   1.244 -
   1.245 -    def load_const_ret(self, value):
   1.246 -        self.constants_for_exceptions.append(value)
   1.247 -        self.load_const(value)
   1.248 -
   1.249 -    def ret(self, index):
   1.250 -        self.load_fast(index)
   1.251 -
   1.252 -        # Previously, the constant stored on the stack by jsr/jsr_w was stored
   1.253 -        # in a local variable. In the JVM, extracting the value from the local
   1.254 -        # variable and jumping can be done at runtime. In the Python VM, any
   1.255 -        # jump target must be known in advance and written into the bytecode.
   1.256 -
   1.257 -        for constant in self.constants_for_exceptions:
   1.258 -            self.dup_top()              # Stack: actual-address, actual-address
   1.259 -            self.load_const(constant)   # Stack: actual-address, actual-address, suggested-address
   1.260 -            self.compare_op("==")       # Stack: actual-address, result
   1.261 -            self.jump_to_label(0, "const")
   1.262 -            self.pop_top()              # Stack: actual-address
   1.263 -            self.pop_top()              # Stack:
   1.264 -            self.jump_absolute(constant)
   1.265 -            self.start_label("const")
   1.266 -            self.pop_top()              # Stack: actual-address
   1.267 -
   1.268 -        # NOTE: If we get here, something is really wrong.
   1.269 -
   1.270 -        self.pop_top()              # Stack:
   1.271 -
   1.272 -    def setup_except(self, target):
   1.273 -        self.blocks.append(self.position)
   1.274 -        self.exception_handlers.append(target)
   1.275 -        #print "-", self.position, target
   1.276 -        self.output.append(opmap["SETUP_EXCEPT"])
   1.277 -        self.position += 1
   1.278 -        self._write_value(0) # To be filled in later
   1.279 -
   1.280 -    def setup_finally(self, target):
   1.281 -        self.blocks.append(self.position)
   1.282 -        self.exception_handlers.append(target)
   1.283 -        #print "-", self.position, target
   1.284 -        self.output.append(opmap["SETUP_FINALLY"])
   1.285 -        self.position += 1
   1.286 -        self._write_value(0) # To be filled in later
   1.287 -
   1.288 -    def end_exception(self):
   1.289 -        current_exception_start = self.blocks.pop()
   1.290 -        # Convert the "lazy" absolute value.
   1.291 -        current_exception_target = self.exception_handlers.pop()
   1.292 -        target = current_exception_target.get_value()
   1.293 -        #print "*", current_exception_start, target
   1.294 -        # NOTE: Using 3 as the assumed length of the SETUP_* instruction.
   1.295 -        self._rewrite_value(current_exception_start + 1, target - current_exception_start - 3)
   1.296 -
   1.297 -    def start_handler(self, exc_name, class_file):
   1.298 -
   1.299 -        # Where handlers are begun, produce bytecode to test the type of
   1.300 -        # the exception.
   1.301 -        # NOTE: Since RAISE_VARARGS and END_FINALLY are not really documented,
   1.302 -        # NOTE: we store the top of the stack and use it later to trigger the
   1.303 -        # NOTE: magic processes when re-raising.
   1.304 -        self.use_external_name(str(exc_name))
   1.305 -
   1.306 -        self.rot_two()                      # Stack: raised-exception, exception
   1.307 -        self.dup_top()                      # Stack: raised-exception, exception, exception
   1.308 -        # Handled exceptions are wrapped before being thrown.
   1.309 -        self.load_global("Exception")       # Stack: raised-exception, exception, exception, Exception
   1.310 -        self.compare_op("exception match")  # Stack: raised-exception, exception, result
   1.311 -        self.jump_to_label(0, "next")
   1.312 -        self.pop_top()                      # Stack: raised-exception, exception
   1.313 -        self.dup_top()                      # Stack: raised-exception, exception, exception
   1.314 -        self.load_attr("args")              # Stack: raised-exception, exception, args
   1.315 -        self.load_const(0)                  # Stack: raised-exception, exception, args, 0
   1.316 -        self.binary_subscr()                # Stack: raised-exception, exception, exception-object
   1.317 -        load_class_name(class_file, str(exc_name), self)
   1.318 -                                            # Stack: raised-exception, exception, exception-object, handled-exception
   1.319 -        self.load_global("isinstance")      # Stack: raised-exception, exception, exception-object, handled-exception, isinstance
   1.320 -        self.rot_three()                    # Stack: raised-exception, exception, isinstance, exception-object, handled-exception
   1.321 -        self.call_function(2)               # Stack: raised-exception, exception, result
   1.322 -        self.jump_to_label(1, "handler")
   1.323 -        self.start_label("next")
   1.324 -        self.pop_top()                      # Stack: raised-exception, exception
   1.325 -        self.rot_two()                      # Stack: exception, raised-exception
   1.326 -        self.end_finally()
   1.327 -        self.start_label("handler")
   1.328 -        self.pop_top()                      # Stack: raised-exception, exception
   1.329 -
   1.330 -    # Complicated methods.
   1.331 -
   1.332 -    def load_const(self, value):
   1.333 -        self.output.append(opmap["LOAD_CONST"])
   1.334 -        if not self.constants.has_key(value):
   1.335 -            self.constants[value] = len(self.constants.keys())
   1.336 -        self.position += 1
   1.337 -        self._write_value(self.constants[value])
   1.338 -        self.update_stack_depth(1)
   1.339 -
   1.340 -    def load_global(self, name):
   1.341 -        self.output.append(opmap["LOAD_GLOBAL"])
   1.342 -        if not self.names.has_key(name):
   1.343 -            self.names[name] = len(self.names.keys())
   1.344 -        self.position += 1
   1.345 -        self._write_value(self.names[name])
   1.346 -        self.update_stack_depth(1)
   1.347 -
   1.348 -    def load_attr(self, name):
   1.349 -        self.output.append(opmap["LOAD_ATTR"])
   1.350 -        if not self.names.has_key(name):
   1.351 -            self.names[name] = len(self.names.keys())
   1.352 -        self.position += 1
   1.353 -        self._write_value(self.names[name])
   1.354 -
   1.355 -    def load_name(self, name):
   1.356 -        self.output.append(opmap["LOAD_NAME"])
   1.357 -        if not self.names.has_key(name):
   1.358 -            self.names[name] = len(self.names.keys())
   1.359 -        self.position += 1
   1.360 -        self._write_value(self.names[name])
   1.361 -        self.update_stack_depth(1)
   1.362 -
   1.363 -    def load_fast(self, index):
   1.364 -        self.output.append(opmap["LOAD_FAST"])
   1.365 -        self.position += 1
   1.366 -        self._write_value(index)
   1.367 -        self.update_stack_depth(1)
   1.368 -        self.update_locals(index)
   1.369 -
   1.370 -    def store_attr(self, name):
   1.371 -        self.output.append(opmap["STORE_ATTR"])
   1.372 -        if not self.names.has_key(name):
   1.373 -            self.names[name] = len(self.names.keys())
   1.374 -        self.position += 1
   1.375 -        self._write_value(self.names[name])
   1.376 -        self.update_stack_depth(-1)
   1.377 -
   1.378 -    def store_fast(self, index):
   1.379 -        self.output.append(opmap["STORE_FAST"])
   1.380 -        self.position += 1
   1.381 -        self._write_value(index)
   1.382 -        self.update_stack_depth(-1)
   1.383 -        self.update_locals(index)
   1.384 -
   1.385 -    def for_iter(self):
   1.386 -        self.blocks.append(self.position)
   1.387 -        #print ">", self.blocks
   1.388 -        self.output.append(opmap["FOR_ITER"])
   1.389 -        self.position += 1
   1.390 -        self._write_value(0) # To be filled in later
   1.391 -        self.update_stack_depth(1)
   1.392 -
   1.393 -    def break_loop(self):
   1.394 -        self.output.append(opmap["BREAK_LOOP"])
   1.395 -        self.position += 1
   1.396 -        self.jump_absolute(self.blocks[-1])
   1.397 -
   1.398 -    # Normal bytecode generators.
   1.399 -
   1.400 -    def get_iter(self):
   1.401 -        self.output.append(opmap["GET_ITER"])
   1.402 -        self.position += 1
   1.403 -
   1.404 -    def jump_if_false(self, offset=0):
   1.405 -        self.output.append(opmap["JUMP_IF_FALSE"])
   1.406 -        self.position += 1
   1.407 -        self._write_value(offset) # May be filled in later
   1.408 -
   1.409 -    def jump_if_true(self, offset=0):
   1.410 -        self.output.append(opmap["JUMP_IF_TRUE"])
   1.411 -        self.position += 1
   1.412 -        self._write_value(offset) # May be filled in later
   1.413 -
   1.414 -    def jump_forward(self, offset=0):
   1.415 -        self.output.append(opmap["JUMP_FORWARD"])
   1.416 -        self.position += 1
   1.417 -        self._write_value(offset) # May be filled in later
   1.418 -
   1.419 -    def jump_absolute(self, address=0):
   1.420 -        self.output.append(opmap["JUMP_ABSOLUTE"])
   1.421 -        self.position += 1
   1.422 -        self._write_value(address) # May be filled in later
   1.423 -
   1.424 -    def build_tuple(self, count):
   1.425 -        self.output.append(opmap["BUILD_TUPLE"])
   1.426 -        self.position += 1
   1.427 -        self._write_value(count)
   1.428 -        self.update_stack_depth(-(count - 1))
   1.429 -
   1.430 -    def build_list(self, count):
   1.431 -        self.output.append(opmap["BUILD_LIST"])
   1.432 -        self.position += 1
   1.433 -        self._write_value(count)
   1.434 -        self.update_stack_depth(-(count - 1))
   1.435 -
   1.436 -    def pop_top(self):
   1.437 -        self.output.append(opmap["POP_TOP"])
   1.438 -        self.position += 1
   1.439 -        self.update_stack_depth(-1)
   1.440 -
   1.441 -    def dup_top(self):
   1.442 -        self.output.append(opmap["DUP_TOP"])
   1.443 -        self.position += 1
   1.444 -        self.update_stack_depth(1)
   1.445 -
   1.446 -    def dup_topx(self, count):
   1.447 -        self.output.append(opmap["DUP_TOPX"])
   1.448 -        self.position += 1
   1.449 -        self._write_value(count)
   1.450 -        self.update_stack_depth(count)
   1.451 -
   1.452 -    def rot_two(self):
   1.453 -        self.output.append(opmap["ROT_TWO"])
   1.454 -        self.position += 1
   1.455 -
   1.456 -    def rot_three(self):
   1.457 -        self.output.append(opmap["ROT_THREE"])
   1.458 -        self.position += 1
   1.459 -
   1.460 -    def rot_four(self):
   1.461 -        self.output.append(opmap["ROT_FOUR"])
   1.462 -        self.position += 1
   1.463 -
   1.464 -    def call_function(self, count):
   1.465 -        self.output.append(opmap["CALL_FUNCTION"])
   1.466 -        self.position += 1
   1.467 -        self._write_value(count)
   1.468 -        self.update_stack_depth(-count)
   1.469 -
   1.470 -    def call_function_var(self, count):
   1.471 -        self.output.append(opmap["CALL_FUNCTION_VAR"])
   1.472 -        self.position += 1
   1.473 -        self._write_value(count)
   1.474 -        self.update_stack_depth(-count-1)
   1.475 -
   1.476 -    def binary_subscr(self):
   1.477 -        self.output.append(opmap["BINARY_SUBSCR"])
   1.478 -        self.position += 1
   1.479 -        self.update_stack_depth(-1)
   1.480 -
   1.481 -    def binary_add(self):
   1.482 -        self.output.append(opmap["BINARY_ADD"])
   1.483 -        self.position += 1
   1.484 -        self.update_stack_depth(-1)
   1.485 -
   1.486 -    def binary_divide(self):
   1.487 -        self.output.append(opmap["BINARY_DIVIDE"])
   1.488 -        self.position += 1
   1.489 -        self.update_stack_depth(-1)
   1.490 -
   1.491 -    def binary_multiply(self):
   1.492 -        self.output.append(opmap["BINARY_MULTIPLY"])
   1.493 -        self.position += 1
   1.494 -        self.update_stack_depth(-1)
   1.495 -
   1.496 -    def binary_modulo(self):
   1.497 -        self.output.append(opmap["BINARY_MODULO"])
   1.498 -        self.position += 1
   1.499 -        self.update_stack_depth(-1)
   1.500 -
   1.501 -    def binary_subtract(self):
   1.502 -        self.output.append(opmap["BINARY_SUBTRACT"])
   1.503 -        self.position += 1
   1.504 -        self.update_stack_depth(-1)
   1.505 -
   1.506 -    def binary_and(self):
   1.507 -        self.output.append(opmap["BINARY_AND"])
   1.508 -        self.position += 1
   1.509 -        self.update_stack_depth(-1)
   1.510 -
   1.511 -    def binary_or(self):
   1.512 -        self.output.append(opmap["BINARY_XOR"])
   1.513 -        self.position += 1
   1.514 -        self.update_stack_depth(-1)
   1.515 -
   1.516 -    def binary_lshift(self):
   1.517 -        self.output.append(opmap["BINARY_LSHIFT"])
   1.518 -        self.position += 1
   1.519 -        self.update_stack_depth(-1)
   1.520 -
   1.521 -    def binary_rshift(self):
   1.522 -        self.output.append(opmap["BINARY_RSHIFT"])
   1.523 -        self.position += 1
   1.524 -        self.update_stack_depth(-1)
   1.525 -
   1.526 -    def binary_xor(self):
   1.527 -        self.output.append(opmap["BINARY_XOR"])
   1.528 -        self.position += 1
   1.529 -        self.update_stack_depth(-1)
   1.530 -
   1.531 -    def store_subscr(self):
   1.532 -        self.output.append(opmap["STORE_SUBSCR"])
   1.533 -        self.position += 1
   1.534 -        self.update_stack_depth(-3)
   1.535 -
   1.536 -    def unary_negative(self):
   1.537 -        self.output.append(opmap["UNARY_NEGATIVE"])
   1.538 -        self.position += 1
   1.539 -
   1.540 -    def slice_0(self):
   1.541 -        self.output.append(opmap["SLICE+0"])
   1.542 -        self.position += 1
   1.543 -
   1.544 -    def slice_1(self):
   1.545 -        self.output.append(opmap["SLICE+1"])
   1.546 -        self.position += 1
   1.547 -
   1.548 -    def compare_op(self, op):
   1.549 -        self.output.append(opmap["COMPARE_OP"])
   1.550 -        self.position += 1
   1.551 -        self._write_value(list(cmp_op).index(op))
   1.552 -        self.update_stack_depth(-1)
   1.553 -
   1.554 -    def return_value(self):
   1.555 -        self.output.append(opmap["RETURN_VALUE"])
   1.556 -        self.position += 1
   1.557 -        self.update_stack_depth(-1)
   1.558 -
   1.559 -    def raise_varargs(self, count):
   1.560 -        self.output.append(opmap["RAISE_VARARGS"])
   1.561 -        self.position += 1
   1.562 -        self._write_value(count)
   1.563 -
   1.564 -    def pop_block(self):
   1.565 -        self.output.append(opmap["POP_BLOCK"])
   1.566 -        self.position += 1
   1.567 -
   1.568 -    def end_finally(self):
   1.569 -        self.output.append(opmap["END_FINALLY"])
   1.570 -        self.position += 1
   1.571 -
   1.572 -    def unpack_sequence(self, count):
   1.573 -        self.output.append(opmap["UNPACK_SEQUENCE"])
   1.574 -        self.position += 1
   1.575 -        self._write_value(count)
   1.576 -
   1.577 -    # Debugging.
   1.578 -
   1.579 -    def print_item(self):
   1.580 -        self.output.append(opmap["PRINT_ITEM"])
   1.581 -        self.position += 1
   1.582 -
   1.583 -# Utility classes and functions.
   1.584 -
   1.585 -class LazyDict(UserDict):
   1.586 -    def __getitem__(self, key):
   1.587 -        if not self.data.has_key(key):
   1.588 -            # NOTE: Assume 16-bit value.
   1.589 -            self.data[key] = LazyValue(2)
   1.590 -        return self.data[key]
   1.591 -    def __setitem__(self, key, value):
   1.592 -        if self.data.has_key(key):
   1.593 -            existing_value = self.data[key]
   1.594 -            if isinstance(existing_value, LazyValue):
   1.595 -                existing_value.set_value(value)
   1.596 -                return
   1.597 -        self.data[key] = value
   1.598 -
   1.599 -class LazyValue:
   1.600 -    def __init__(self, nvalues):
   1.601 -        self.values = []
   1.602 -        for i in range(0, nvalues):
   1.603 -            self.values.append(LazySubValue())
   1.604 -    def set_value(self, value):
   1.605 -        # NOTE: Assume at least 16-bit value. No "filling" performed.
   1.606 -        if value <= 0xffff:
   1.607 -            self.values[0].set_value(value & 0xff)
   1.608 -            self.values[1].set_value((value & 0xff00) >> 8)
   1.609 -        else:
   1.610 -            # NOTE: EXTENDED_ARG not yet supported.
   1.611 -            raise ValueError, value
   1.612 -    def get_value(self):
   1.613 -        value = 0
   1.614 -        values = self.values[:]
   1.615 -        for i in range(0, len(values)):
   1.616 -            value = (value << 8) + values.pop().value
   1.617 -        return value
   1.618 -
   1.619 -class LazySubValue:
   1.620 -    def __init__(self):
   1.621 -        self.value = 0
   1.622 -    def set_value(self, value):
   1.623 -        self.value = value
   1.624 -
   1.625 -def signed(value, limit):
   1.626 -
   1.627 -    """
   1.628 -    Return the signed integer from the unsigned 'value', where 'limit' (a value
   1.629 -    one greater than the highest possible positive integer) is used to determine
   1.630 -    whether a negative or positive result is produced.
   1.631 -    """
   1.632 -
   1.633 -    d, r = divmod(value, limit)
   1.634 -    if d == 1:
   1.635 -        mask = limit * 2 - 1
   1.636 -        return -1 - (value ^ mask)
   1.637 -    else:
   1.638 -        return value
   1.639 -
   1.640 -def signed1(value):
   1.641 -    return signed(value, 0x80)
   1.642 -
   1.643 -def signed2(value):
   1.644 -    return signed(value, 0x8000)
   1.645 -
   1.646 -def signed4(value):
   1.647 -    return signed(value, 0x80000000)
   1.648 -
   1.649 -def load_class_name(class_file, full_class_name, program):
   1.650 -    this_class_name = str(class_file.this_class.get_python_name())
   1.651 -    this_class_parts = this_class_name.split(".")
   1.652 -    class_parts = full_class_name.split(".")
   1.653 -
   1.654 -    # Only use the full path if different from this class's path.
   1.655 -
   1.656 -    if class_parts[:-1] != this_class_parts[:-1]:
   1.657 -        program.use_external_name(full_class_name)
   1.658 -        program.load_global(class_parts[0])
   1.659 -        for class_part in class_parts[1:]:
   1.660 -            program.load_attr(class_part)   # Stack: classref
   1.661 -    else:
   1.662 -        program.load_global(class_parts[-1])
   1.663 -
   1.664 -# Bytecode conversion.
   1.665 -
   1.666 -class BytecodeReader:
   1.667 -
   1.668 -    "A generic Java bytecode reader."
   1.669 -
   1.670 -    def __init__(self, class_file):
   1.671 -
   1.672 -        """
   1.673 -        Initialise the reader with a 'class_file' containing essential
   1.674 -        information for any bytecode inspection activity.
   1.675 -        """
   1.676 -
   1.677 -        self.class_file = class_file
   1.678 -        self.position_mapping = LazyDict()
   1.679 -
   1.680 -    def process(self, method, program):
   1.681 -
   1.682 -        """
   1.683 -        Process the given 'method' (obtained from the class file), using the
   1.684 -        given 'program' to write translated Python bytecode instructions.
   1.685 -        """
   1.686 -
   1.687 -        self.java_position = 0
   1.688 -        self.in_finally = 0
   1.689 -        self.method = method
   1.690 -
   1.691 -        # NOTE: Potentially unreliable way of getting necessary information.
   1.692 -
   1.693 -        code, exception_table = None, None
   1.694 -        for attribute in method.attributes:
   1.695 -            if isinstance(attribute, classfile.CodeAttributeInfo):
   1.696 -                code, exception_table = attribute.code, attribute.exception_table
   1.697 -                break
   1.698 -
   1.699 -        # Where no code was found, write a very simple placeholder routine.
   1.700 -        # This is useful for interfaces and abstract classes.
   1.701 -        # NOTE: Assess the correctness of doing this. An exception should really
   1.702 -        # NOTE: be raised instead.
   1.703 -
   1.704 -        if code is None:
   1.705 -            program.load_const(None)
   1.706 -            program.return_value()
   1.707 -            return
   1.708 -
   1.709 -        # Produce a structure which permits fast access to exception details.
   1.710 -
   1.711 -        exception_block_start = {}
   1.712 -        exception_block_end = {}
   1.713 -        exception_block_handler = {}
   1.714 -        reversed_exception_table = exception_table[:]
   1.715 -        reversed_exception_table.reverse()
   1.716 -
   1.717 -        # Later entries have wider coverage than earlier entries.
   1.718 -
   1.719 -        for exception in reversed_exception_table:
   1.720 -
   1.721 -            # Index start positions.
   1.722 -
   1.723 -            if not exception_block_start.has_key(exception.start_pc):
   1.724 -                exception_block_start[exception.start_pc] = []
   1.725 -            exception_block_start[exception.start_pc].append(exception)
   1.726 -
   1.727 -            # Index end positions.
   1.728 -
   1.729 -            if not exception_block_end.has_key(exception.end_pc):
   1.730 -                exception_block_end[exception.end_pc] = []
   1.731 -            exception_block_end[exception.end_pc].append(exception)
   1.732 -
   1.733 -            # Index handler positions.
   1.734 -
   1.735 -            if not exception_block_handler.has_key(exception.handler_pc):
   1.736 -                exception_block_handler[exception.handler_pc] = []
   1.737 -            exception_block_handler[exception.handler_pc].append(exception)
   1.738 -
   1.739 -        # Process each instruction in the code.
   1.740 -
   1.741 -        while self.java_position < len(code):
   1.742 -            self.position_mapping[self.java_position] = program.position
   1.743 -
   1.744 -            # Insert exception handling constructs.
   1.745 -
   1.746 -            block_starts = exception_block_start.get(self.java_position, [])
   1.747 -            for exception in block_starts:
   1.748 -
   1.749 -                # Note that the absolute position is used.
   1.750 -
   1.751 -                if exception.catch_type == 0:
   1.752 -                    program.setup_finally(self.position_mapping[exception.handler_pc])
   1.753 -                else:
   1.754 -                    program.setup_except(self.position_mapping[exception.handler_pc])
   1.755 -
   1.756 -            if block_starts:
   1.757 -                self.in_finally = 0
   1.758 -
   1.759 -            # Insert exception handler details.
   1.760 -            # NOTE: Ensure that pop_block is reachable by possibly inserting it at the start of finally handlers.
   1.761 -            # NOTE: Insert a check for the correct exception at the start of each handler.
   1.762 -
   1.763 -            for exception in exception_block_handler.get(self.java_position, []):
   1.764 -                program.end_exception()
   1.765 -                if exception.catch_type == 0:
   1.766 -                    self.in_finally = 1
   1.767 -                else:
   1.768 -                    program.start_handler(self.class_file.constants[exception.catch_type - 1].get_python_name(), self.class_file)
   1.769 -
   1.770 -            # Process the bytecode at the current position.
   1.771 -
   1.772 -            bytecode = ord(code[self.java_position])
   1.773 -            mnemonic, number_of_arguments = self.java_bytecodes[bytecode]
   1.774 -            number_of_arguments = self.process_bytecode(mnemonic, number_of_arguments, code, program)
   1.775 -            next_java_position = self.java_position + 1 + number_of_arguments
   1.776 -
   1.777 -            # Insert exception block end details.
   1.778 -
   1.779 -            for exception in exception_block_end.get(next_java_position, []):
   1.780 -
   1.781 -                # NOTE: Insert jump beyond handlers.
   1.782 -                # NOTE: program.jump_forward/absolute(...)
   1.783 -                # NOTE: Insert end finally at end of handlers as well as where "ret" occurs.
   1.784 -
   1.785 -                if exception.catch_type != 0:
   1.786 -                    program.pop_block()
   1.787 -
   1.788 -            # Only advance the JVM position after sneaking in extra Python
   1.789 -            # instructions.
   1.790 -
   1.791 -            self.java_position = next_java_position
   1.792 -
   1.793 -    def process_bytecode(self, mnemonic, number_of_arguments, code, program):
   1.794 -
   1.795 -        """
   1.796 -        Process a bytecode instruction with the given 'mnemonic' and
   1.797 -        'number_of_arguments'. The 'code' parameter contains the full method
   1.798 -        code so that argument data can be inspected. The 'program' parameter is
   1.799 -        used to produce a Python translation of the instruction.
   1.800 -        """
   1.801 -
   1.802 -        if number_of_arguments is not None:
   1.803 -            arguments = []
   1.804 -            for j in range(0, number_of_arguments):
   1.805 -                arguments.append(ord(code[self.java_position + 1 + j]))
   1.806 -
   1.807 -            # Call the handler.
   1.808 -
   1.809 -            getattr(self, mnemonic)(arguments, program)
   1.810 -            return number_of_arguments
   1.811 -        else:
   1.812 -            # Call the handler.
   1.813 -
   1.814 -            return getattr(self, mnemonic)(code[self.java_position+1:], program)
   1.815 -
   1.816 -    java_bytecodes = {
   1.817 -        # code : (mnemonic, number of following bytes, change in stack)
   1.818 -        0 : ("nop", 0),
   1.819 -        1 : ("aconst_null", 0),
   1.820 -        2 : ("iconst_m1", 0),
   1.821 -        3 : ("iconst_0", 0),
   1.822 -        4 : ("iconst_1", 0),
   1.823 -        5 : ("iconst_2", 0),
   1.824 -        6 : ("iconst_3", 0),
   1.825 -        7 : ("iconst_4", 0),
   1.826 -        8 : ("iconst_5", 0),
   1.827 -        9 : ("lconst_0", 0),
   1.828 -        10 : ("lconst_1", 0),
   1.829 -        11 : ("fconst_0", 0),
   1.830 -        12 : ("fconst_1", 0),
   1.831 -        13 : ("fconst_2", 0),
   1.832 -        14 : ("dconst_0", 0),
   1.833 -        15 : ("dconst_1", 0),
   1.834 -        16 : ("bipush", 1),
   1.835 -        17 : ("sipush", 2),
   1.836 -        18 : ("ldc", 1),
   1.837 -        19 : ("ldc_w", 2),
   1.838 -        20 : ("ldc2_w", 2),
   1.839 -        21 : ("iload", 1),
   1.840 -        22 : ("lload", 1),
   1.841 -        23 : ("fload", 1),
   1.842 -        24 : ("dload", 1),
   1.843 -        25 : ("aload", 1),
   1.844 -        26 : ("iload_0", 0),
   1.845 -        27 : ("iload_1", 0),
   1.846 -        28 : ("iload_2", 0),
   1.847 -        29 : ("iload_3", 0),
   1.848 -        30 : ("lload_0", 0),
   1.849 -        31 : ("lload_1", 0),
   1.850 -        32 : ("lload_2", 0),
   1.851 -        33 : ("lload_3", 0),
   1.852 -        34 : ("fload_0", 0),
   1.853 -        35 : ("fload_1", 0),
   1.854 -        36 : ("fload_2", 0),
   1.855 -        37 : ("fload_3", 0),
   1.856 -        38 : ("dload_0", 0),
   1.857 -        39 : ("dload_1", 0),
   1.858 -        40 : ("dload_2", 0),
   1.859 -        41 : ("dload_3", 0),
   1.860 -        42 : ("aload_0", 0),
   1.861 -        43 : ("aload_1", 0),
   1.862 -        44 : ("aload_2", 0),
   1.863 -        45 : ("aload_3", 0),
   1.864 -        46 : ("iaload", 0),
   1.865 -        47 : ("laload", 0),
   1.866 -        48 : ("faload", 0),
   1.867 -        49 : ("daload", 0),
   1.868 -        50 : ("aaload", 0),
   1.869 -        51 : ("baload", 0),
   1.870 -        52 : ("caload", 0),
   1.871 -        53 : ("saload", 0),
   1.872 -        54 : ("istore", 1),
   1.873 -        55 : ("lstore", 1),
   1.874 -        56 : ("fstore", 1),
   1.875 -        57 : ("dstore", 1),
   1.876 -        58 : ("astore", 1),
   1.877 -        59 : ("istore_0", 0),
   1.878 -        60 : ("istore_1", 0),
   1.879 -        61 : ("istore_2", 0),
   1.880 -        62 : ("istore_3", 0),
   1.881 -        63 : ("lstore_0", 0),
   1.882 -        64 : ("lstore_1", 0),
   1.883 -        65 : ("lstore_2", 0),
   1.884 -        66 : ("lstore_3", 0),
   1.885 -        67 : ("fstore_0", 0),
   1.886 -        68 : ("fstore_1", 0),
   1.887 -        69 : ("fstore_2", 0),
   1.888 -        70 : ("fstore_3", 0),
   1.889 -        71 : ("dstore_0", 0),
   1.890 -        72 : ("dstore_1", 0),
   1.891 -        73 : ("dstore_2", 0),
   1.892 -        74 : ("dstore_3", 0),
   1.893 -        75 : ("astore_0", 0),
   1.894 -        76 : ("astore_1", 0),
   1.895 -        77 : ("astore_2", 0),
   1.896 -        78 : ("astore_3", 0),
   1.897 -        79 : ("iastore", 0),
   1.898 -        80 : ("lastore", 0),
   1.899 -        81 : ("fastore", 0),
   1.900 -        82 : ("dastore", 0),
   1.901 -        83 : ("aastore", 0),
   1.902 -        84 : ("bastore", 0),
   1.903 -        85 : ("castore", 0),
   1.904 -        86 : ("sastore", 0),
   1.905 -        87 : ("pop", 0),
   1.906 -        88 : ("pop2", 0),
   1.907 -        89 : ("dup", 0),
   1.908 -        90 : ("dup_x1", 0),
   1.909 -        91 : ("dup_x2", 0),
   1.910 -        92 : ("dup2", 0),
   1.911 -        93 : ("dup2_x1", 0),
   1.912 -        94 : ("dup2_x2", 0),
   1.913 -        95 : ("swap", 0),
   1.914 -        96 : ("iadd", 0),
   1.915 -        97 : ("ladd", 0),
   1.916 -        98 : ("fadd", 0),
   1.917 -        99 : ("dadd", 0),
   1.918 -        100 : ("isub", 0),
   1.919 -        101 : ("lsub", 0),
   1.920 -        102 : ("fsub", 0),
   1.921 -        103 : ("dsub", 0),
   1.922 -        104 : ("imul", 0),
   1.923 -        105 : ("lmul", 0),
   1.924 -        106 : ("fmul", 0),
   1.925 -        107 : ("dmul", 0),
   1.926 -        108 : ("idiv", 0),
   1.927 -        109 : ("ldiv", 0),
   1.928 -        110 : ("fdiv", 0),
   1.929 -        111 : ("ddiv", 0),
   1.930 -        112 : ("irem", 0),
   1.931 -        113 : ("lrem", 0),
   1.932 -        114 : ("frem", 0),
   1.933 -        115 : ("drem", 0),
   1.934 -        116 : ("ineg", 0),
   1.935 -        117 : ("lneg", 0),
   1.936 -        118 : ("fneg", 0),
   1.937 -        119 : ("dneg", 0),
   1.938 -        120 : ("ishl", 0),
   1.939 -        121 : ("lshl", 0),
   1.940 -        122 : ("ishr", 0),
   1.941 -        123 : ("lshr", 0),
   1.942 -        124 : ("iushr", 0),
   1.943 -        125 : ("lushr", 0),
   1.944 -        126 : ("iand", 0),
   1.945 -        127 : ("land", 0),
   1.946 -        128 : ("ior", 0),
   1.947 -        129 : ("lor", 0),
   1.948 -        130 : ("ixor", 0),
   1.949 -        131 : ("lxor", 0),
   1.950 -        132 : ("iinc", 2),
   1.951 -        133 : ("i2l", 0),
   1.952 -        134 : ("i2f", 0),
   1.953 -        135 : ("i2d", 0),
   1.954 -        136 : ("l2i", 0),
   1.955 -        137 : ("l2f", 0),
   1.956 -        138 : ("l2d", 0),
   1.957 -        139 : ("f2i", 0),
   1.958 -        140 : ("f2l", 0),
   1.959 -        141 : ("f2d", 0),
   1.960 -        142 : ("d2i", 0),
   1.961 -        143 : ("d2l", 0),
   1.962 -        144 : ("d2f", 0),
   1.963 -        145 : ("i2b", 0),
   1.964 -        146 : ("i2c", 0),
   1.965 -        147 : ("i2s", 0),
   1.966 -        148 : ("lcmp", 0),
   1.967 -        149 : ("fcmpl", 0),
   1.968 -        150 : ("fcmpg", 0),
   1.969 -        151 : ("dcmpl", 0),
   1.970 -        152 : ("dcmpg", 0),
   1.971 -        153 : ("ifeq", 2),
   1.972 -        154 : ("ifne", 2),
   1.973 -        155 : ("iflt", 2),
   1.974 -        156 : ("ifge", 2),
   1.975 -        157 : ("ifgt", 2),
   1.976 -        158 : ("ifle", 2),
   1.977 -        159 : ("if_icmpeq", 2),
   1.978 -        160 : ("if_icmpne", 2),
   1.979 -        161 : ("if_icmplt", 2),
   1.980 -        162 : ("if_icmpge", 2),
   1.981 -        163 : ("if_icmpgt", 2),
   1.982 -        164 : ("if_icmple", 2),
   1.983 -        165 : ("if_acmpeq", 2),
   1.984 -        166 : ("if_acmpne", 2),
   1.985 -        167 : ("goto", 2),
   1.986 -        168 : ("jsr", 2),
   1.987 -        169 : ("ret", 1),
   1.988 -        170 : ("tableswitch", None), # variable number of arguments
   1.989 -        171 : ("lookupswitch", None), # variable number of arguments
   1.990 -        172 : ("ireturn", 0),
   1.991 -        173 : ("lreturn", 0),
   1.992 -        174 : ("freturn", 0),
   1.993 -        175 : ("dreturn", 0),
   1.994 -        176 : ("areturn", 0),
   1.995 -        177 : ("return_", 0),
   1.996 -        178 : ("getstatic", 2),
   1.997 -        179 : ("putstatic", 2),
   1.998 -        180 : ("getfield", 2),
   1.999 -        181 : ("putfield", 2),
  1.1000 -        182 : ("invokevirtual", 2),
  1.1001 -        183 : ("invokespecial", 2),
  1.1002 -        184 : ("invokestatic", 2),
  1.1003 -        185 : ("invokeinterface", 4),
  1.1004 -        187 : ("new", 2),
  1.1005 -        188 : ("newarray", 1),
  1.1006 -        189 : ("anewarray", 2),
  1.1007 -        190 : ("arraylength", 0),
  1.1008 -        191 : ("athrow", 0),
  1.1009 -        192 : ("checkcast", 2),
  1.1010 -        193 : ("instanceof", 2),
  1.1011 -        194 : ("monitorenter", 0),
  1.1012 -        195 : ("monitorexit", 0),
  1.1013 -        196 : ("wide", None), # 3 or 5 arguments, stack changes according to modified element
  1.1014 -        197 : ("multianewarray", 3),
  1.1015 -        198 : ("ifnull", 2),
  1.1016 -        199 : ("ifnonnull", 2),
  1.1017 -        200 : ("goto_w", 4),
  1.1018 -        201 : ("jsr_w", 4),
  1.1019 -        }
  1.1020 -
  1.1021 -class BytecodeDisassembler(BytecodeReader):
  1.1022 -
  1.1023 -    "A Java bytecode disassembler."
  1.1024 -
  1.1025 -    bytecode_methods = [spec[0] for spec in BytecodeReader.java_bytecodes.values()]
  1.1026 -
  1.1027 -    def __getattr__(self, name):
  1.1028 -        if name in self.bytecode_methods:
  1.1029 -            print "%5s %s" % (self.java_position, name),
  1.1030 -            return self.generic
  1.1031 -        else:
  1.1032 -            raise AttributeError, name
  1.1033 -
  1.1034 -    def generic(self, arguments, program):
  1.1035 -        print arguments
  1.1036 -
  1.1037 -    def lookupswitch(self, code, program):
  1.1038 -        print "%5s lookupswitch" % (self.java_position,),
  1.1039 -        d, r = divmod(self.java_position + 1, 4)
  1.1040 -        to_boundary = (4 - r) % 4
  1.1041 -        code = code[to_boundary:]
  1.1042 -        default = classfile.u4(code[0:4])
  1.1043 -        npairs = classfile.u4(code[4:8])
  1.1044 -        print default, npairs
  1.1045 -        return to_boundary + 8 + npairs * 8
  1.1046 -
  1.1047 -    def tableswitch(self, code, program):
  1.1048 -        print "%5s tableswitch" % (self.java_position,),
  1.1049 -        d, r = divmod(self.java_position + 1, 4)
  1.1050 -        to_boundary = (4 - r) % 4
  1.1051 -        code = code[to_boundary:]
  1.1052 -        default = classfile.u4(code[0:4])
  1.1053 -        low = classfile.u4(code[4:8])
  1.1054 -        high = classfile.u4(code[8:12])
  1.1055 -        print default, low, high
  1.1056 -        return to_boundary + 12 + (high - low + 1) * 4
  1.1057 -
  1.1058 -class BytecodeDisassemblerProgram:
  1.1059 -    position = 0
  1.1060 -    def setup_except(self, target):
  1.1061 -        print "(setup_except %s)" % target
  1.1062 -    def setup_finally(self, target):
  1.1063 -        print "(setup_finally %s)" % target
  1.1064 -    def end_exception(self):
  1.1065 -        print "(end_exception)"
  1.1066 -    def start_handler(self, exc_name, class_file):
  1.1067 -        print "(start_handler %s)" % exc_name
  1.1068 -    def pop_block(self):
  1.1069 -        print "(pop_block)"
  1.1070 -
  1.1071 -class BytecodeTranslator(BytecodeReader):
  1.1072 -
  1.1073 -    "A Java bytecode translator which uses a Python bytecode writer."
  1.1074 -
  1.1075 -    def aaload(self, arguments, program):
  1.1076 -        # NOTE: No type checking performed.
  1.1077 -        program.binary_subscr()
  1.1078 -
  1.1079 -    def aastore(self, arguments, program):
  1.1080 -        # NOTE: No type checking performed.
  1.1081 -        # Stack: arrayref, index, value
  1.1082 -        program.rot_three() # Stack: value, arrayref, index
  1.1083 -        program.store_subscr()
  1.1084 -
  1.1085 -    def aconst_null(self, arguments, program):
  1.1086 -        program.load_const(None)
  1.1087 -
  1.1088 -    def aload(self, arguments, program):
  1.1089 -        program.load_fast(arguments[0])
  1.1090 -
  1.1091 -    def aload_0(self, arguments, program):
  1.1092 -        program.load_fast(0)
  1.1093 -
  1.1094 -    def aload_1(self, arguments, program):
  1.1095 -        program.load_fast(1)
  1.1096 -
  1.1097 -    def aload_2(self, arguments, program):
  1.1098 -        program.load_fast(2)
  1.1099 -
  1.1100 -    def aload_3(self, arguments, program):
  1.1101 -        program.load_fast(3)
  1.1102 -
  1.1103 -    def anewarray(self, arguments, program):
  1.1104 -        # NOTE: Does not raise NegativeArraySizeException.
  1.1105 -        # NOTE: Not using the index to type the list/array.
  1.1106 -        index = (arguments[0] << 8) + arguments[1]
  1.1107 -        self._newarray(program)
  1.1108 -
  1.1109 -    def _newarray(self, program):
  1.1110 -        program.build_list(0)       # Stack: count, list
  1.1111 -        program.rot_two()           # Stack: list, count
  1.1112 -        program.setup_loop()
  1.1113 -        program.load_global("range")
  1.1114 -        program.load_const(0)       # Stack: list, count, range, 0
  1.1115 -        program.rot_three()         # Stack: list, 0, count, range
  1.1116 -        program.rot_three()         # Stack: list, range, 0, count
  1.1117 -        program.call_function(2)    # Stack: list, range_list
  1.1118 -        program.get_iter()          # Stack: list, iter
  1.1119 -        program.for_iter()          # Stack: list, iter, value
  1.1120 -        program.pop_top()           # Stack: list, iter
  1.1121 -        program.rot_two()           # Stack: iter, list
  1.1122 -        program.dup_top()           # Stack: iter, list, list
  1.1123 -        program.load_attr("append") # Stack: iter, list, append
  1.1124 -        program.load_const(None)    # Stack: iter, list, append, None
  1.1125 -        program.call_function(1)    # Stack: iter, list, None
  1.1126 -        program.pop_top()           # Stack: iter, list
  1.1127 -        program.rot_two()           # Stack: list, iter
  1.1128 -        program.end_loop()          # Back to for_iter above
  1.1129 -
  1.1130 -    def areturn(self, arguments, program):
  1.1131 -        program.return_value()
  1.1132 -
  1.1133 -    def arraylength(self, arguments, program):
  1.1134 -        program.load_global("len")  # Stack: arrayref, len
  1.1135 -        program.rot_two()           # Stack: len, arrayref
  1.1136 -        program.call_function(1)
  1.1137 -
  1.1138 -    def astore(self, arguments, program):
  1.1139 -        program.store_fast(arguments[0])
  1.1140 -
  1.1141 -    def astore_0(self, arguments, program):
  1.1142 -        program.store_fast(0)
  1.1143 -
  1.1144 -    def astore_1(self, arguments, program):
  1.1145 -        program.store_fast(1)
  1.1146 -
  1.1147 -    def astore_2(self, arguments, program):
  1.1148 -        program.store_fast(2)
  1.1149 -
  1.1150 -    def astore_3(self, arguments, program):
  1.1151 -        program.store_fast(3)
  1.1152 -
  1.1153 -    def athrow(self, arguments, program):
  1.1154 -        # NOTE: NullPointerException not raised where null/None is found on the stack.
  1.1155 -        # If this instruction appears in a finally handler, use end_finally instead.
  1.1156 -        if self.in_finally:
  1.1157 -            program.end_finally()
  1.1158 -        else:
  1.1159 -            # Wrap the exception in a Python exception.
  1.1160 -            program.load_global("Exception")    # Stack: objectref, Exception
  1.1161 -            program.rot_two()                   # Stack: Exception, objectref
  1.1162 -            program.call_function(1)            # Stack: exception
  1.1163 -            program.raise_varargs(1)
  1.1164 -            # NOTE: This seems to put another object on the stack.
  1.1165 -
  1.1166 -    baload = aaload
  1.1167 -    bastore = aastore
  1.1168 -
  1.1169 -    def bipush(self, arguments, program):
  1.1170 -        program.load_const(signed1(arguments[0]))
  1.1171 -
  1.1172 -    caload = aaload
  1.1173 -    castore = aastore
  1.1174 -
  1.1175 -    def checkcast(self, arguments, program):
  1.1176 -        index = (arguments[0] << 8) + arguments[1]
  1.1177 -        target_name = self.class_file.constants[index - 1].get_python_name()
  1.1178 -        program.use_external_name(target_name)
  1.1179 -        program.dup_top()                   # Stack: objectref, objectref
  1.1180 -        program.load_const(None)            # Stack: objectref, objectref, None
  1.1181 -        program.compare_op("is")            # Stack: objectref, result
  1.1182 -        program.jump_to_label(1, "next")
  1.1183 -        program.pop_top()                   # Stack: objectref
  1.1184 -        program.dup_top()                   # Stack: objectref, objectref
  1.1185 -        program.load_global("isinstance")   # Stack: objectref, objectref, isinstance
  1.1186 -        program.rot_two()                   # Stack: objectref, isinstance, objectref
  1.1187 -        load_class_name(self.class_file, target_name, program)
  1.1188 -        program.call_function(2)            # Stack: objectref, result
  1.1189 -        program.jump_to_label(1, "next")
  1.1190 -        program.pop_top()                   # Stack: objectref
  1.1191 -        program.pop_top()                   # Stack:
  1.1192 -        program.use_external_name("java.lang.ClassCastException")
  1.1193 -        load_class_name(self.class_file, "java.lang.ClassCastException", program)
  1.1194 -        program.call_function(0)            # Stack: exception
  1.1195 -        # Wrap the exception in a Python exception.
  1.1196 -        program.load_global("Exception")    # Stack: exception, Exception
  1.1197 -        program.rot_two()                   # Stack: Exception, exception
  1.1198 -        program.call_function(1)            # Stack: exception
  1.1199 -        program.raise_varargs(1)
  1.1200 -        # NOTE: This seems to put another object on the stack.
  1.1201 -        program.start_label("next")
  1.1202 -        program.pop_top()                   # Stack: objectref
  1.1203 -
  1.1204 -    def d2f(self, arguments, program):
  1.1205 -        pass
  1.1206 -
  1.1207 -    def d2i(self, arguments, program):
  1.1208 -        program.load_global("int")  # Stack: value, int
  1.1209 -        program.rot_two()           # Stack: int, value
  1.1210 -        program.call_function(1)    # Stack: result
  1.1211 -
  1.1212 -    d2l = d2i # Preserving Java semantics
  1.1213 -
  1.1214 -    def dadd(self, arguments, program):
  1.1215 -        # NOTE: No type checking performed.
  1.1216 -        program.binary_add()
  1.1217 -
  1.1218 -    daload = aaload
  1.1219 -    dastore = aastore
  1.1220 -
  1.1221 -    def dcmpg(self, arguments, program):
  1.1222 -        # NOTE: No type checking performed.
  1.1223 -        program.compare_op(">")
  1.1224 -
  1.1225 -    def dcmpl(self, arguments, program):
  1.1226 -        # NOTE: No type checking performed.
  1.1227 -        program.compare_op("<")
  1.1228 -
  1.1229 -    def dconst_0(self, arguments, program):
  1.1230 -        program.load_const(0.0)
  1.1231 -
  1.1232 -    def dconst_1(self, arguments, program):
  1.1233 -        program.load_const(1.0)
  1.1234 -
  1.1235 -    def ddiv(self, arguments, program):
  1.1236 -        # NOTE: No type checking performed.
  1.1237 -        program.binary_divide()
  1.1238 -
  1.1239 -    dload = aload
  1.1240 -    dload_0 = aload_0
  1.1241 -    dload_1 = aload_1
  1.1242 -    dload_2 = aload_2
  1.1243 -    dload_3 = aload_3
  1.1244 -
  1.1245 -    def dmul(self, arguments, program):
  1.1246 -        # NOTE: No type checking performed.
  1.1247 -        program.binary_multiply()
  1.1248 -
  1.1249 -    def dneg(self, arguments, program):
  1.1250 -        # NOTE: No type checking performed.
  1.1251 -        program.unary_negative()
  1.1252 -
  1.1253 -    def drem(self, arguments, program):
  1.1254 -        # NOTE: No type checking performed.
  1.1255 -        program.binary_modulo()
  1.1256 -
  1.1257 -    dreturn = areturn
  1.1258 -    dstore = astore
  1.1259 -    dstore_0 = astore_0
  1.1260 -    dstore_1 = astore_1
  1.1261 -    dstore_2 = astore_2
  1.1262 -    dstore_3 = astore_3
  1.1263 -
  1.1264 -    def dsub(self, arguments, program):
  1.1265 -        # NOTE: No type checking performed.
  1.1266 -        program.binary_subtract()
  1.1267 -
  1.1268 -    def dup(self, arguments, program):
  1.1269 -        program.dup_top()
  1.1270 -
  1.1271 -    def dup_x1(self, arguments, program):
  1.1272 -        # Ignoring computational type categories.
  1.1273 -        program.dup_top()
  1.1274 -        program.rot_three()
  1.1275 -
  1.1276 -    def dup_x2(self, arguments, program):
  1.1277 -        # Ignoring computational type categories.
  1.1278 -        program.dup_top()
  1.1279 -        program.rot_four()
  1.1280 -
  1.1281 -    dup2 = dup # Ignoring computational type categories
  1.1282 -    dup2_x1 = dup_x1 # Ignoring computational type categories
  1.1283 -    dup2_x2 = dup_x2 # Ignoring computational type categories
  1.1284 -
  1.1285 -    def f2d(self, arguments, program):
  1.1286 -        pass # Preserving Java semantics
  1.1287 -
  1.1288 -    def f2i(self, arguments, program):
  1.1289 -        program.load_global("int")  # Stack: value, int
  1.1290 -        program.rot_two()           # Stack: int, value
  1.1291 -        program.call_function(1)    # Stack: result
  1.1292 -
  1.1293 -    f2l = f2i # Preserving Java semantics
  1.1294 -    fadd = dadd
  1.1295 -    faload = daload
  1.1296 -    fastore = dastore
  1.1297 -    fcmpg = dcmpg
  1.1298 -    fcmpl = dcmpl
  1.1299 -    fconst_0 = dconst_0
  1.1300 -    fconst_1 = dconst_1
  1.1301 -
  1.1302 -    def fconst_2(self, arguments, program):
  1.1303 -        program.load_const(2.0)
  1.1304 -
  1.1305 -    fdiv = ddiv
  1.1306 -    fload = dload
  1.1307 -    fload_0 = dload_0
  1.1308 -    fload_1 = dload_1
  1.1309 -    fload_2 = dload_2
  1.1310 -    fload_3 = dload_3
  1.1311 -    fmul = dmul
  1.1312 -    fneg = dneg
  1.1313 -    frem = drem
  1.1314 -    freturn = dreturn
  1.1315 -    fstore = dstore
  1.1316 -    fstore_0 = dstore_0
  1.1317 -    fstore_1 = dstore_1
  1.1318 -    fstore_2 = dstore_2
  1.1319 -    fstore_3 = dstore_3
  1.1320 -    fsub = dsub
  1.1321 -
  1.1322 -    def getfield(self, arguments, program):
  1.1323 -        index = (arguments[0] << 8) + arguments[1]
  1.1324 -        target_name = self.class_file.constants[index - 1].get_python_name()
  1.1325 -        # NOTE: Using the string version of the name which may contain incompatible characters.
  1.1326 -        program.load_attr(str(target_name))
  1.1327 -
  1.1328 -    def getstatic(self, arguments, program):
  1.1329 -        index = (arguments[0] << 8) + arguments[1]
  1.1330 -        target = self.class_file.constants[index - 1]
  1.1331 -        target_name = target.get_python_name()
  1.1332 -
  1.1333 -        # Get the class name instead of the fully qualified name.
  1.1334 -
  1.1335 -        full_class_name = target.get_class().get_python_name()
  1.1336 -        program.use_external_name(full_class_name)
  1.1337 -        load_class_name(self.class_file, full_class_name, program)
  1.1338 -        # NOTE: Using the string version of the name which may contain incompatible characters.
  1.1339 -        program.load_attr(str(target_name))
  1.1340 -
  1.1341 -    def goto(self, arguments, program):
  1.1342 -        offset = signed2((arguments[0] << 8) + arguments[1])
  1.1343 -        java_absolute = self.java_position + offset
  1.1344 -        program.jump_absolute(self.position_mapping[java_absolute])
  1.1345 -
  1.1346 -    def goto_w(self, arguments, program):
  1.1347 -        offset = signed4((arguments[0] << 24) + (arguments[1] << 16) + (arguments[2] << 8) + arguments[3])
  1.1348 -        java_absolute = self.java_position + offset
  1.1349 -        program.jump_absolute(self.position_mapping[java_absolute])
  1.1350 -
  1.1351 -    def i2b(self, arguments, program):
  1.1352 -        pass
  1.1353 -
  1.1354 -    def i2c(self, arguments, program):
  1.1355 -        pass
  1.1356 -
  1.1357 -    def i2d(self, arguments, program):
  1.1358 -        program.load_global("float")    # Stack: value, float
  1.1359 -        program.rot_two()               # Stack: float, value
  1.1360 -        program.call_function(1)        # Stack: result
  1.1361 -
  1.1362 -    i2f = i2d # Not distinguishing between float and double
  1.1363 -
  1.1364 -    def i2l(self, arguments, program):
  1.1365 -        pass # Preserving Java semantics
  1.1366 -
  1.1367 -    def i2s(self, arguments, program):
  1.1368 -        pass # Not distinguishing between int and short
  1.1369 -
  1.1370 -    iadd = fadd
  1.1371 -    iaload = faload
  1.1372 -
  1.1373 -    def iand(self, arguments, program):
  1.1374 -        # NOTE: No type checking performed.
  1.1375 -        program.binary_and()
  1.1376 -
  1.1377 -    iastore = fastore
  1.1378 -
  1.1379 -    def iconst_m1(self, arguments, program):
  1.1380 -        program.load_const(-1)
  1.1381 -
  1.1382 -    def iconst_0(self, arguments, program):
  1.1383 -        program.load_const(0)
  1.1384 -
  1.1385 -    def iconst_1(self, arguments, program):
  1.1386 -        program.load_const(1)
  1.1387 -
  1.1388 -    def iconst_2(self, arguments, program):
  1.1389 -        program.load_const(2)
  1.1390 -
  1.1391 -    def iconst_3(self, arguments, program):
  1.1392 -        program.load_const(3)
  1.1393 -
  1.1394 -    def iconst_4(self, arguments, program):
  1.1395 -        program.load_const(4)
  1.1396 -
  1.1397 -    def iconst_5(self, arguments, program):
  1.1398 -        program.load_const(5)
  1.1399 -
  1.1400 -    idiv = fdiv
  1.1401 -
  1.1402 -    def _if_xcmpx(self, arguments, program, op):
  1.1403 -        offset = signed2((arguments[0] << 8) + arguments[1])
  1.1404 -        java_absolute = self.java_position + offset
  1.1405 -        program.compare_op(op)
  1.1406 -        program.jump_to_label(0, "next") # skip if false
  1.1407 -        program.pop_top()
  1.1408 -        program.jump_absolute(self.position_mapping[java_absolute])
  1.1409 -        program.start_label("next")
  1.1410 -        program.pop_top()
  1.1411 -
  1.1412 -    def if_acmpeq(self, arguments, program):
  1.1413 -        # NOTE: No type checking performed.
  1.1414 -        self._if_xcmpx(arguments, program, "is")
  1.1415 -
  1.1416 -    def if_acmpne(self, arguments, program):
  1.1417 -        # NOTE: No type checking performed.
  1.1418 -        self._if_xcmpx(arguments, program, "is not")
  1.1419 -
  1.1420 -    def if_icmpeq(self, arguments, program):
  1.1421 -        # NOTE: No type checking performed.
  1.1422 -        self._if_xcmpx(arguments, program, "==")
  1.1423 -
  1.1424 -    def if_icmpne(self, arguments, program):
  1.1425 -        # NOTE: No type checking performed.
  1.1426 -        self._if_xcmpx(arguments, program, "!=")
  1.1427 -
  1.1428 -    def if_icmplt(self, arguments, program):
  1.1429 -        # NOTE: No type checking performed.
  1.1430 -        self._if_xcmpx(arguments, program, "<")
  1.1431 -
  1.1432 -    def if_icmpge(self, arguments, program):
  1.1433 -        # NOTE: No type checking performed.
  1.1434 -        self._if_xcmpx(arguments, program, ">=")
  1.1435 -
  1.1436 -    def if_icmpgt(self, arguments, program):
  1.1437 -        # NOTE: No type checking performed.
  1.1438 -        self._if_xcmpx(arguments, program, ">")
  1.1439 -
  1.1440 -    def if_icmple(self, arguments, program):
  1.1441 -        # NOTE: No type checking performed.
  1.1442 -        self._if_xcmpx(arguments, program, "<=")
  1.1443 -
  1.1444 -    def ifeq(self, arguments, program):
  1.1445 -        # NOTE: No type checking performed.
  1.1446 -        program.load_const(0)
  1.1447 -        self._if_xcmpx(arguments, program, "==")
  1.1448 -
  1.1449 -    def ifne(self, arguments, program):
  1.1450 -        # NOTE: No type checking performed.
  1.1451 -        program.load_const(0)
  1.1452 -        self._if_xcmpx(arguments, program, "!=")
  1.1453 -
  1.1454 -    def iflt(self, arguments, program):
  1.1455 -        # NOTE: No type checking performed.
  1.1456 -        program.load_const(0)
  1.1457 -        self._if_xcmpx(arguments, program, "<")
  1.1458 -
  1.1459 -    def ifge(self, arguments, program):
  1.1460 -        # NOTE: No type checking performed.
  1.1461 -        program.load_const(0)
  1.1462 -        self._if_xcmpx(arguments, program, ">=")
  1.1463 -
  1.1464 -    def ifgt(self, arguments, program):
  1.1465 -        # NOTE: No type checking performed.
  1.1466 -        program.load_const(0)
  1.1467 -        self._if_xcmpx(arguments, program, ">")
  1.1468 -
  1.1469 -    def ifle(self, arguments, program):
  1.1470 -        # NOTE: No type checking performed.
  1.1471 -        program.load_const(0)
  1.1472 -        self._if_xcmpx(arguments, program, "<=")
  1.1473 -
  1.1474 -    def ifnonnull(self, arguments, program):
  1.1475 -        # NOTE: No type checking performed.
  1.1476 -        program.load_const(None)
  1.1477 -        self._if_xcmpx(arguments, program, "is not")
  1.1478 -
  1.1479 -    def ifnull(self, arguments, program):
  1.1480 -        # NOTE: No type checking performed.
  1.1481 -        program.load_const(None)
  1.1482 -        self._if_xcmpx(arguments, program, "is")
  1.1483 -
  1.1484 -    def iinc(self, arguments, program):
  1.1485 -        # NOTE: No type checking performed.
  1.1486 -        program.load_fast(arguments[0])
  1.1487 -        program.load_const(arguments[1])
  1.1488 -        program.binary_add()
  1.1489 -        program.store_fast(arguments[0])
  1.1490 -
  1.1491 -    iload = fload
  1.1492 -    iload_0 = fload_0
  1.1493 -    iload_1 = fload_1
  1.1494 -    iload_2 = fload_2
  1.1495 -    iload_3 = fload_3
  1.1496 -    imul = fmul
  1.1497 -    ineg = fneg
  1.1498 -
  1.1499 -    def instanceof(self, arguments, program):
  1.1500 -        index = (arguments[0] << 8) + arguments[1]
  1.1501 -        target_name = self.class_file.constants[index - 1].get_python_name()
  1.1502 -        program.use_external_name(target_name)
  1.1503 -        program.load_global("isinstance")   # Stack: objectref, isinstance
  1.1504 -        program.rot_two()                   # Stack: isinstance, objectref
  1.1505 -        load_class_name(self.class_file, target_name, program)
  1.1506 -        program.call_function(2)            # Stack: result
  1.1507 -
  1.1508 -    def _invoke(self, target_name, program):
  1.1509 -        # NOTE: Using the string version of the name which may contain incompatible characters.
  1.1510 -        program.load_attr(str(target_name)) # Stack: tuple, method
  1.1511 -        program.rot_two()                   # Stack: method, tuple
  1.1512 -        program.call_function_var(0)        # Stack: result
  1.1513 -
  1.1514 -    def invokeinterface(self, arguments, program):
  1.1515 -        # NOTE: This implementation does not perform the necessary checks for
  1.1516 -        # NOTE: signature-based polymorphism.
  1.1517 -        # NOTE: Java rules not specifically obeyed.
  1.1518 -        index = (arguments[0] << 8) + arguments[1]
  1.1519 -        # NOTE: "count" == nargs + 1, apparently.
  1.1520 -        count = arguments[2] - 1
  1.1521 -        target_name = self.class_file.constants[index - 1].get_python_name()
  1.1522 -        # Stack: objectref, arg1, arg2, ...
  1.1523 -        program.build_tuple(count)          # Stack: objectref, tuple
  1.1524 -        program.rot_two()                   # Stack: tuple, objectref
  1.1525 -        # NOTE: The interface information is not used to discover the correct
  1.1526 -        # NOTE: method.
  1.1527 -        self._invoke(target_name, program)
  1.1528 -
  1.1529 -    def invokespecial(self, arguments, program):
  1.1530 -        # NOTE: This implementation does not perform the necessary checks for
  1.1531 -        # NOTE: signature-based polymorphism.
  1.1532 -        # NOTE: Java rules not specifically obeyed.
  1.1533 -        index = (arguments[0] << 8) + arguments[1]
  1.1534 -        target = self.class_file.constants[index - 1]
  1.1535 -        original_name = target.get_name()
  1.1536 -        target_name = target.get_python_name()
  1.1537 -
  1.1538 -        # Get the number of parameters from the descriptor.
  1.1539 -
  1.1540 -        count = len(target.get_descriptor()[0])
  1.1541 -
  1.1542 -        # First, we build a tuple of the reference and arguments.
  1.1543 -
  1.1544 -        program.build_tuple(count + 1)          # Stack: tuple
  1.1545 -
  1.1546 -        # Get the class name instead of the fully qualified name.
  1.1547 -        # NOTE: Not bothering with Object initialisation.
  1.1548 -
  1.1549 -        full_class_name = target.get_class().get_python_name()
  1.1550 -        if full_class_name not in ("java.lang.Object", "java.lang.Exception"):
  1.1551 -            program.use_external_name(full_class_name)
  1.1552 -            load_class_name(self.class_file, full_class_name, program)
  1.1553 -            self._invoke(target_name, program)
  1.1554 -
  1.1555 -        # Remove Python None return value.
  1.1556 -
  1.1557 -        if str(original_name) == "<init>":
  1.1558 -            program.pop_top()
  1.1559 -
  1.1560 -    def invokestatic(self, arguments, program):
  1.1561 -        # NOTE: This implementation does not perform the necessary checks for
  1.1562 -        # NOTE: signature-based polymorphism.
  1.1563 -        # NOTE: Java rules not specifically obeyed.
  1.1564 -        index = (arguments[0] << 8) + arguments[1]
  1.1565 -        target = self.class_file.constants[index - 1]
  1.1566 -        target_name = target.get_python_name()
  1.1567 -
  1.1568 -        # Get the number of parameters from the descriptor.
  1.1569 -
  1.1570 -        count = len(target.get_descriptor()[0])
  1.1571 -
  1.1572 -        # Stack: arg1, arg2, ...
  1.1573 -
  1.1574 -        program.build_tuple(count)              # Stack: tuple
  1.1575 -
  1.1576 -        # Use the class to provide access to static methods.
  1.1577 -        # Get the class name instead of the fully qualified name.
  1.1578 -
  1.1579 -        full_class_name = target.get_class().get_python_name()
  1.1580 -        if full_class_name not in ("java.lang.Object", "java.lang.Exception"):
  1.1581 -            program.use_external_name(full_class_name)
  1.1582 -            load_class_name(self.class_file, full_class_name, program)
  1.1583 -            self._invoke(target_name, program)
  1.1584 -
  1.1585 -    def invokevirtual (self, arguments, program):
  1.1586 -        # NOTE: This implementation does not perform the necessary checks for
  1.1587 -        # NOTE: signature-based polymorphism.
  1.1588 -        # NOTE: Java rules not specifically obeyed.
  1.1589 -        index = (arguments[0] << 8) + arguments[1]
  1.1590 -        target = self.class_file.constants[index - 1]
  1.1591 -        target_name = target.get_python_name()
  1.1592 -        # Get the number of parameters from the descriptor.
  1.1593 -        count = len(target.get_descriptor()[0])
  1.1594 -        # Stack: objectref, arg1, arg2, ...
  1.1595 -        program.build_tuple(count)          # Stack: objectref, tuple
  1.1596 -        program.rot_two()                   # Stack: tuple, objectref
  1.1597 -        self._invoke(target_name, program)
  1.1598 -
  1.1599 -    def ior(self, arguments, program):
  1.1600 -        # NOTE: No type checking performed.
  1.1601 -        program.binary_or()
  1.1602 -
  1.1603 -    irem = frem
  1.1604 -    ireturn = freturn
  1.1605 -
  1.1606 -    def ishl(self, arguments, program):
  1.1607 -        # NOTE: No type checking performed.
  1.1608 -        # NOTE: Not verified.
  1.1609 -        program.binary_lshift()
  1.1610 -
  1.1611 -    def ishr(self, arguments, program):
  1.1612 -        # NOTE: No type checking performed.
  1.1613 -        # NOTE: Not verified.
  1.1614 -        program.binary_rshift()
  1.1615 -
  1.1616 -    istore = fstore
  1.1617 -    istore_0 = fstore_0
  1.1618 -    istore_1 = fstore_1
  1.1619 -    istore_2 = fstore_2
  1.1620 -    istore_3 = fstore_3
  1.1621 -    isub = fsub
  1.1622 -    iushr = ishr # Ignoring distinctions between arithmetic and logical shifts
  1.1623 -
  1.1624 -    def ixor(self, arguments, program):
  1.1625 -        # NOTE: No type checking performed.
  1.1626 -        program.binary_xor()
  1.1627 -
  1.1628 -    def jsr(self, arguments, program):
  1.1629 -        offset = signed2((arguments[0] << 8) + arguments[1])
  1.1630 -        java_absolute = self.java_position + offset
  1.1631 -        # Store the address of the next instruction.
  1.1632 -        program.load_const_ret(self.position_mapping[self.java_position + 3])
  1.1633 -        program.jump_absolute(self.position_mapping[java_absolute])
  1.1634 -
  1.1635 -    def jsr_w(self, arguments, program):
  1.1636 -        offset = signed4((arguments[0] << 24) + (arguments[1] << 16) + (arguments[2] << 8) + arguments[3])
  1.1637 -        java_absolute = self.java_position + offset
  1.1638 -        # Store the address of the next instruction.
  1.1639 -        program.load_const_ret(self.position_mapping[self.java_position + 5])
  1.1640 -        program.jump_absolute(self.position_mapping[java_absolute])
  1.1641 -
  1.1642 -    l2d = i2d
  1.1643 -    l2f = i2f
  1.1644 -
  1.1645 -    def l2i(self, arguments, program):
  1.1646 -        pass # Preserving Java semantics
  1.1647 -
  1.1648 -    ladd = iadd
  1.1649 -    laload = iaload
  1.1650 -    land = iand
  1.1651 -    lastore = iastore
  1.1652 -
  1.1653 -    def lcmp(self, arguments, program):
  1.1654 -        # NOTE: No type checking performed.
  1.1655 -        program.dup_topx(2)                 # Stack: value1, value2, value1, value2
  1.1656 -        program.compare_op(">")             # Stack: value1, value2, result
  1.1657 -        program.jump_to_label(0, "equals")
  1.1658 -        # True - produce result and branch.
  1.1659 -        program.pop_top()                   # Stack: value1, value2
  1.1660 -        program.pop_top()                   # Stack: value1
  1.1661 -        program.pop_top()                   # Stack:
  1.1662 -        program.load_const(1)               # Stack: 1
  1.1663 -        program.jump_to_label(None, "next")
  1.1664 -        # False - test equality.
  1.1665 -        program.start_label("equals")
  1.1666 -        program.pop_top()                   # Stack: value1, value2
  1.1667 -        program.dup_topx(2)                 # Stack: value1, value2, value1, value2
  1.1668 -        program.compare_op("==")            # Stack: value1, value2, result
  1.1669 -        program.jump_to_label(0, "less")
  1.1670 -        # True - produce result and branch.
  1.1671 -        program.pop_top()                   # Stack: value1, value2
  1.1672 -        program.pop_top()                   # Stack: value1
  1.1673 -        program.pop_top()                   # Stack:
  1.1674 -        program.load_const(0)               # Stack: 0
  1.1675 -        program.jump_to_label(None, "next")
  1.1676 -        # False - produce result.
  1.1677 -        program.start_label("less")
  1.1678 -        program.pop_top()                   # Stack: value1, value2
  1.1679 -        program.pop_top()                   # Stack: value1
  1.1680 -        program.pop_top()                   # Stack:
  1.1681 -        program.load_const(-1)              # Stack: -1
  1.1682 -        program.start_label("next")
  1.1683 -
  1.1684 -    lconst_0 = iconst_0
  1.1685 -    lconst_1 = iconst_1
  1.1686 -
  1.1687 -    def ldc(self, arguments, program):
  1.1688 -        const = self.class_file.constants[arguments[0] - 1]
  1.1689 -        if isinstance(const, classfile.StringInfo):
  1.1690 -            program.use_external_name("java.lang.String")
  1.1691 -            program.load_global("java")
  1.1692 -            program.load_attr("lang")
  1.1693 -            program.load_attr("String")
  1.1694 -            program.load_const(const.get_value())
  1.1695 -            program.call_function(1)
  1.1696 -        else:
  1.1697 -            program.load_const(const.get_value())
  1.1698 -
  1.1699 -    def ldc_w(self, arguments, program):
  1.1700 -        const = self.class_file.constants[(arguments[0] << 8) + arguments[1] - 1]
  1.1701 -        if isinstance(const, classfile.StringInfo):
  1.1702 -            program.use_external_name("java.lang.String")
  1.1703 -            program.load_global("java")
  1.1704 -            program.load_attr("lang")
  1.1705 -            program.load_attr("String")
  1.1706 -            program.load_const(const.get_value())
  1.1707 -            program.call_function(1)
  1.1708 -        else:
  1.1709 -            program.load_const(const.get_value())
  1.1710 -
  1.1711 -    ldc2_w = ldc_w
  1.1712 -    ldiv = idiv
  1.1713 -    lload = iload
  1.1714 -    lload_0 = iload_0
  1.1715 -    lload_1 = iload_1
  1.1716 -    lload_2 = iload_2
  1.1717 -    lload_3 = iload_3
  1.1718 -    lmul = imul
  1.1719 -    lneg = ineg
  1.1720 -
  1.1721 -    def lookupswitch(self, code, program):
  1.1722 -
  1.1723 -        # Find the offset to the next 4 byte boundary in the code.
  1.1724 -
  1.1725 -        d, r = divmod(self.java_position + 1, 4)
  1.1726 -        to_boundary = (4 - r) % 4
  1.1727 -
  1.1728 -        # Get the pertinent arguments.
  1.1729 -
  1.1730 -        code = code[to_boundary:]
  1.1731 -        default = classfile.u4(code[0:4])
  1.1732 -        npairs = classfile.u4(code[4:8])
  1.1733 -
  1.1734 -        # Process the pairs.
  1.1735 -        # NOTE: This is not the most optimal implementation.
  1.1736 -
  1.1737 -        pair_index = 8
  1.1738 -        for pair in range(0, npairs):
  1.1739 -            match = classfile.u4(code[pair_index:pair_index+4])
  1.1740 -            offset = classfile.s4(code[pair_index+4:pair_index+8])
  1.1741 -            # Calculate the branch target.
  1.1742 -            java_absolute = self.java_position + offset
  1.1743 -            # Generate branching code.
  1.1744 -            program.dup_top()                                           # Stack: key, key
  1.1745 -            program.load_const(match)                                   # Stack: key, key, match
  1.1746 -            program.compare_op("==")                                    # Stack: key, result
  1.1747 -            program.jump_to_label(0, "end")
  1.1748 -            program.pop_top()                                           # Stack: key
  1.1749 -            program.pop_top()                                           # Stack:
  1.1750 -            program.jump_absolute(self.position_mapping[java_absolute])
  1.1751 -            # Generate the label for the end of the branching code.
  1.1752 -            program.start_label("end")
  1.1753 -            program.pop_top()                                           # Stack: key
  1.1754 -            # Update the index.
  1.1755 -            pair_index += 4
  1.1756 -
  1.1757 -        # Generate the default.
  1.1758 -
  1.1759 -        java_absolute = self.java_position + default
  1.1760 -        program.jump_absolute(self.position_mapping[java_absolute])
  1.1761 -        return pair_index + to_boundary
  1.1762 -
  1.1763 -    lor = ior
  1.1764 -    lrem = irem
  1.1765 -    lreturn = ireturn
  1.1766 -    lshl = ishl
  1.1767 -    lshr = ishr
  1.1768 -    lstore = istore
  1.1769 -    lstore_0 = istore_0
  1.1770 -    lstore_1 = istore_1
  1.1771 -    lstore_2 = istore_2
  1.1772 -    lstore_3 = istore_3
  1.1773 -    lsub = isub
  1.1774 -    lushr = iushr
  1.1775 -    lxor = ixor
  1.1776 -
  1.1777 -    def monitorenter(self, arguments, program):
  1.1778 -        # NOTE: To be implemented.
  1.1779 -        pass
  1.1780 -
  1.1781 -    def monitorexit(self, arguments, program):
  1.1782 -        # NOTE: To be implemented.
  1.1783 -        pass
  1.1784 -
  1.1785 -    def multianewarray(self, arguments, program):
  1.1786 -        index = (arguments[0] << 8) + arguments[1]
  1.1787 -        dimensions = arguments[2]
  1.1788 -        # Stack: count1, ..., countN-1, countN
  1.1789 -        self._newarray(program)             # Stack: count1, ..., countN-1, list
  1.1790 -        for dimension in range(1, dimensions):
  1.1791 -            program.rot_two()               # Stack: count1, ..., list, countN-1
  1.1792 -            program.build_list(0)           # Stack: count1, ..., list, countN-1, new-list
  1.1793 -            program.rot_three()             # Stack: count1, ..., new-list, list, countN-1
  1.1794 -            program.setup_loop()
  1.1795 -            program.load_const(0)           # Stack: count1, ..., new-list, list, countN-1, 0
  1.1796 -            program.rot_two()               # Stack: count1, ..., new-list, list, 0, countN-1
  1.1797 -            program.load_global("range")    # Stack: count1, ..., new-list, list, 0, countN-1, range
  1.1798 -            program.rot_three()             # Stack: count1, ..., new-list, list, range, 0, countN-1
  1.1799 -            program.call_function(2)        # Stack: count1, ..., new-list, list, range-list
  1.1800 -            program.get_iter()              # Stack: count1, ..., new-list, list, iter
  1.1801 -            program.for_iter()              # Stack: count1, ..., new-list, list, iter, value
  1.1802 -            program.pop_top()               # Stack: count1, ..., new-list, list, iter
  1.1803 -            program.rot_three()             # Stack: count1, ..., iter, new-list, list
  1.1804 -            program.slice_0()               # Stack: count1, ..., iter, new-list, list[:]
  1.1805 -            program.dup_top()               # Stack: count1, ..., iter, new-list, list[:], list[:]
  1.1806 -            program.rot_three()             # Stack: count1, ..., iter, list[:], new-list, list[:]
  1.1807 -            program.rot_two()               # Stack: count1, ..., iter, list[:], list[:], new-list
  1.1808 -            program.dup_top()               # Stack: count1, ..., iter, list[:], list[:], new-list, new-list
  1.1809 -            program.load_attr("append")     # Stack: count1, ..., iter, list[:], list[:], new-list, append
  1.1810 -            program.rot_three()             # Stack: count1, ..., iter, list[:], append, list[:], new-list
  1.1811 -            program.rot_three()             # Stack: count1, ..., iter, list[:], new-list, append, list[:]
  1.1812 -            program.call_function(1)        # Stack: count1, ..., iter, list[:], new-list, None
  1.1813 -            program.pop_top()               # Stack: count1, ..., iter, list[:], new-list
  1.1814 -            program.rot_two()               # Stack: count1, ..., iter, new-list, list[:]
  1.1815 -            program.rot_three()             # Stack: count1, ..., list[:], iter, new-list
  1.1816 -            program.rot_three()             # Stack: count1, ..., new-list, list[:], iter
  1.1817 -            program.end_loop()              # Stack: count1, ..., new-list, list[:], iter
  1.1818 -            program.pop_top()               # Stack: count1, ..., new-list
  1.1819 -
  1.1820 -    def new(self, arguments, program):
  1.1821 -        # This operation is considered to be the same as the calling of the
  1.1822 -        # initialisation method of the given class with no arguments.
  1.1823 -
  1.1824 -        index = (arguments[0] << 8) + arguments[1]
  1.1825 -        target_name = self.class_file.constants[index - 1].get_python_name()
  1.1826 -        program.use_external_name(target_name)
  1.1827 -
  1.1828 -        # NOTE: Using the string version of the name which may contain incompatible characters.
  1.1829 -        program.load_global("object")
  1.1830 -        program.load_attr("__new__")
  1.1831 -        load_class_name(self.class_file, target_name, program)
  1.1832 -        program.call_function(1)
  1.1833 -
  1.1834 -    def newarray(self, arguments, program):
  1.1835 -        # NOTE: Does not raise NegativeArraySizeException.
  1.1836 -        # NOTE: Not using the arguments to type the list/array.
  1.1837 -        self._newarray(program)
  1.1838 -
  1.1839 -    def nop(self, arguments, program):
  1.1840 -        pass
  1.1841 -
  1.1842 -    def pop(self, arguments, program):
  1.1843 -        program.pop_top()
  1.1844 -
  1.1845 -    pop2 = pop # ignoring Java stack value distinctions
  1.1846 -
  1.1847 -    def putfield(self, arguments, program):
  1.1848 -        index = (arguments[0] << 8) + arguments[1]
  1.1849 -        target_name = self.class_file.constants[index - 1].get_python_name()
  1.1850 -        program.rot_two()
  1.1851 -        # NOTE: Using the string version of the name which may contain incompatible characters.
  1.1852 -        program.store_attr(str(target_name))
  1.1853 -
  1.1854 -    def putstatic(self, arguments, program):
  1.1855 -        index = (arguments[0] << 8) + arguments[1]
  1.1856 -        target = self.class_file.constants[index - 1]
  1.1857 -        target_name = target.get_python_name()
  1.1858 -
  1.1859 -        # Get the class name instead of the fully qualified name.
  1.1860 -
  1.1861 -        full_class_name = target.get_class().get_python_name()
  1.1862 -        program.use_external_name(full_class_name)
  1.1863 -        load_class_name(self.class_file, full_class_name, program)
  1.1864 -        # NOTE: Using the string version of the name which may contain incompatible characters.
  1.1865 -        program.store_attr(str(target_name))
  1.1866 -
  1.1867 -    def ret(self, arguments, program):
  1.1868 -        program.ret(arguments[0])
  1.1869 -        # Indicate that the finally handler is probably over.
  1.1870 -        # NOTE: This is seemingly not guaranteed.
  1.1871 -        self.in_finally = 0
  1.1872 -
  1.1873 -    def return_(self, arguments, program):
  1.1874 -        program.load_const(None)
  1.1875 -        program.return_value()
  1.1876 -
  1.1877 -    saload = laload
  1.1878 -    sastore = lastore
  1.1879 -
  1.1880 -    def sipush(self, arguments, program):
  1.1881 -        program.load_const(signed2((arguments[0] << 8) + arguments[1]))
  1.1882 -
  1.1883 -    def swap(self, arguments, program):
  1.1884 -        program.rot_two()
  1.1885 -
  1.1886 -    def tableswitch(self, code, program):
  1.1887 -
  1.1888 -        # Find the offset to the next 4 byte boundary in the code.
  1.1889 -
  1.1890 -        d, r = divmod(self.java_position + 1, 4)
  1.1891 -        to_boundary = (4 - r) % 4
  1.1892 -
  1.1893 -        # Get the pertinent arguments.
  1.1894 -
  1.1895 -        code = code[to_boundary:]
  1.1896 -        default = classfile.u4(code[0:4])
  1.1897 -        low = classfile.u4(code[4:8])
  1.1898 -        high = classfile.u4(code[8:12])
  1.1899 -
  1.1900 -        # Process the jump entries.
  1.1901 -        # NOTE: This is not the most optimal implementation.
  1.1902 -
  1.1903 -        jump_index = 12
  1.1904 -        for jump in range(low, high + 1):
  1.1905 -            offset = classfile.s4(code[jump_index:jump_index + 4])
  1.1906 -
  1.1907 -            # Calculate the branch target.
  1.1908 -
  1.1909 -            java_absolute = self.java_position + offset
  1.1910 -
  1.1911 -            # Generate branching code.
  1.1912 -
  1.1913 -            program.dup_top()                                           # Stack: key, key
  1.1914 -            program.load_const(jump)                                    # Stack: key, key, jump
  1.1915 -            program.compare_op("==")                                    # Stack: key, result
  1.1916 -            program.jump_to_label(0, "end")
  1.1917 -            program.pop_top()                                           # Stack: key
  1.1918 -            program.pop_top()                                           # Stack:
  1.1919 -            program.jump_absolute(self.position_mapping[java_absolute])
  1.1920 -
  1.1921 -            # Generate the label for the end of the branching code.
  1.1922 -
  1.1923 -            program.start_label("end")
  1.1924 -            program.pop_top()                                           # Stack: key
  1.1925 -
  1.1926 -            # Update the index.
  1.1927 -
  1.1928 -            jump_index += 4
  1.1929 -
  1.1930 -        # Generate the default.
  1.1931 -
  1.1932 -        java_absolute = self.java_position + default
  1.1933 -        program.jump_absolute(self.position_mapping[java_absolute])
  1.1934 -        return jump_index + to_boundary
  1.1935 -
  1.1936 -    def wide(self, code, program):
  1.1937 -        # NOTE: To be implemented.
  1.1938 -        return number_of_arguments
  1.1939 -
  1.1940 -def disassemble(class_file, method):
  1.1941 -    disassembler = BytecodeDisassembler(class_file)
  1.1942 -    disassembler.process(method, BytecodeDisassemblerProgram())
  1.1943 -
  1.1944 -class ClassTranslator:
  1.1945 -
  1.1946 -    """
  1.1947 -    A class which provides a wrapper around a class file and the means to
  1.1948 -    translate the represented class into a Python class.
  1.1949 -    """
  1.1950 -
  1.1951 -    def __init__(self, class_file):
  1.1952 -
  1.1953 -        "Initialise the object with the given 'class_file'."
  1.1954 -
  1.1955 -        self.class_file = class_file
  1.1956 -        self.filename = ""
  1.1957 -
  1.1958 -        for attribute in self.class_file.attributes:
  1.1959 -            if isinstance(attribute, classfile.SourceFileAttributeInfo):
  1.1960 -                self.filename = str(attribute.get_name())
  1.1961 -
  1.1962 -    def translate_method(self, method):
  1.1963 -
  1.1964 -        "Translate the given 'method' - an object obtained from the class file."
  1.1965 -
  1.1966 -        translator = BytecodeTranslator(self.class_file)
  1.1967 -        writer = BytecodeWriter()
  1.1968 -        translator.process(method, writer)
  1.1969 -        return translator, writer
  1.1970 -
  1.1971 -    def make_method(self, real_method_name, methods, global_names, namespace):
  1.1972 -
  1.1973 -        """
  1.1974 -        Make a dispatcher method with the given 'real_method_name', providing
  1.1975 -        dispatch to the supplied type-sensitive 'methods', accessing the given
  1.1976 -        'global_names' where necessary, and storing the new method in the
  1.1977 -        'namespace' provided.
  1.1978 -        """
  1.1979 -
  1.1980 -        if real_method_name == "<init>":
  1.1981 -            method_name = "__init__"
  1.1982 -        else:
  1.1983 -            method_name = real_method_name
  1.1984 -
  1.1985 -        # Where only one method exists, just make an alias.
  1.1986 -
  1.1987 -        if len(methods) == 1:
  1.1988 -            method, fn = methods[0]
  1.1989 -            namespace[method_name] = fn
  1.1990 -            return
  1.1991 -
  1.1992 -        # Write a simple bytecode dispatching mechanism.
  1.1993 -
  1.1994 -        program = BytecodeWriter()
  1.1995 -
  1.1996 -        # Remember whether any of the methods are static.
  1.1997 -        # NOTE: This should be an all or nothing situation.
  1.1998 -
  1.1999 -        method_is_static = 0
  1.2000 -
  1.2001 -        # NOTE: The code below should use dictionary-based dispatch for better performance.
  1.2002 -
  1.2003 -        for method, fn in methods:
  1.2004 -            method_is_static = real_method_name != "<init>" and method_is_static or \
  1.2005 -                classfile.has_flags(method.access_flags, [classfile.STATIC])
  1.2006 -
  1.2007 -            if method_is_static:
  1.2008 -                program.load_fast(0)                # Stack: arguments
  1.2009 -            else:
  1.2010 -                program.load_fast(1)                # Stack: arguments
  1.2011 -
  1.2012 -            program.setup_loop()
  1.2013 -            program.load_const(1)                   # Stack: arguments, 1
  1.2014 -
  1.2015 -            if method_is_static:
  1.2016 -                program.store_fast(1)               # Stack: arguments (found = 1)
  1.2017 -            else:
  1.2018 -                program.store_fast(2)               # Stack: arguments (found = 1)
  1.2019 -
  1.2020 -            # Emit a list of parameter types.
  1.2021 -
  1.2022 -            descriptor_types = method.get_descriptor()[0]
  1.2023 -            for descriptor_type in descriptor_types:
  1.2024 -                base_type, object_type, array_type = descriptor_type
  1.2025 -                python_type = classfile.descriptor_base_type_mapping[base_type]
  1.2026 -                if python_type == "instance":
  1.2027 -                    # NOTE: This will need extending.
  1.2028 -                    python_type = object_type
  1.2029 -                program.load_global(python_type)    # Stack: arguments, type, ...
  1.2030 -            program.build_list(len(descriptor_types))
  1.2031 -                                                    # Stack: arguments, types
  1.2032 -            # Make a map of arguments and types.
  1.2033 -            program.load_const(None)                # Stack: arguments, types, None
  1.2034 -            program.rot_three()                     # Stack: None, arguments, types
  1.2035 -            program.build_tuple(3)                  # Stack: tuple
  1.2036 -            program.load_global("map")              # Stack: tuple, map
  1.2037 -            program.rot_two()                       # Stack: map, tuple
  1.2038 -            program.call_function_var(0)            # Stack: list (mapping arguments to types)
  1.2039 -            # Loop over each pair.
  1.2040 -            program.get_iter()                      # Stack: iter
  1.2041 -            program.for_iter()                      # Stack: iter, (argument, type)
  1.2042 -            program.unpack_sequence(2)              # Stack: iter, type, argument
  1.2043 -            program.dup_top()                       # Stack: iter, type, argument, argument
  1.2044 -            program.load_const(None)                # Stack: iter, type, argument, argument, None
  1.2045 -            program.compare_op("is")                # Stack: iter, type, argument, result
  1.2046 -            # Missing argument?
  1.2047 -            program.jump_to_label(0, "present")
  1.2048 -            program.pop_top()                       # Stack: iter, type, argument
  1.2049 -            program.pop_top()                       # Stack: iter, type
  1.2050 -            program.pop_top()                       # Stack: iter
  1.2051 -            program.load_const(0)                   # Stack: iter, 0
  1.2052 -
  1.2053 -            if method_is_static:
  1.2054 -                program.store_fast(1)               # Stack: iter (found = 0)
  1.2055 -            else:
  1.2056 -                program.store_fast(2)               # Stack: iter (found = 0)
  1.2057 -
  1.2058 -            program.break_loop()
  1.2059 -            # Argument was present.
  1.2060 -            program.start_label("present")
  1.2061 -            program.pop_top()                       # Stack: iter, type, argument
  1.2062 -            program.rot_two()                       # Stack: iter, argument, type
  1.2063 -            program.dup_top()                       # Stack: iter, argument, type, type
  1.2064 -            program.load_const(None)                # Stack: iter, argument, type, type, None
  1.2065 -            program.compare_op("is")                # Stack: iter, argument, type, result
  1.2066 -            # Missing parameter type?
  1.2067 -            program.jump_to_label(0, "present")
  1.2068 -            program.pop_top()                       # Stack: iter, argument, type
  1.2069 -            program.pop_top()                       # Stack: iter, argument
  1.2070 -            program.pop_top()                       # Stack: iter
  1.2071 -            program.load_const(0)                   # Stack: iter, 0
  1.2072 -
  1.2073 -            if method_is_static:
  1.2074 -                program.store_fast(1)               # Stack: iter (found = 0)
  1.2075 -            else:
  1.2076 -                program.store_fast(2)               # Stack: iter (found = 0)
  1.2077 -
  1.2078 -            program.break_loop()
  1.2079 -            # Parameter was present.
  1.2080 -            program.start_label("present")
  1.2081 -            program.pop_top()                       # Stack: iter, argument, type
  1.2082 -            program.build_tuple(2)                  # Stack: iter, (argument, type)
  1.2083 -            program.load_global("isinstance")       # Stack: iter, (argument, type), isinstance
  1.2084 -            program.rot_two()                       # Stack: iter, isinstance, (argument, type)
  1.2085 -            program.call_function_var(0)            # Stack: iter, result
  1.2086 -            program.jump_to_label(1, "match")
  1.2087 -            program.pop_top()                       # Stack: iter
  1.2088 -            program.load_const(0)                   # Stack: iter, 0
  1.2089 -
  1.2090 -            if method_is_static:
  1.2091 -                program.store_fast(1)               # Stack: iter (found = 0)
  1.2092 -            else:
  1.2093 -                program.store_fast(2)               # Stack: iter (found = 0)
  1.2094 -
  1.2095 -            program.break_loop()
  1.2096 -            # Argument type and parameter type matched.
  1.2097 -            program.start_label("match")
  1.2098 -            program.pop_top()                       # Stack: iter
  1.2099 -            program.end_loop()                      # Stack:
  1.2100 -            # If all the parameters matched, call the method.
  1.2101 -
  1.2102 -            if method_is_static:
  1.2103 -                program.load_fast(1)                # Stack: match
  1.2104 -            else:
  1.2105 -                program.load_fast(2)                # Stack: match
  1.2106 -
  1.2107 -            program.jump_to_label(0, "failed")
  1.2108 -            # All the parameters matched.
  1.2109 -            program.pop_top()                       # Stack:
  1.2110 -
  1.2111 -            if method_is_static:
  1.2112 -                program.load_fast(0)                # Stack: arguments
  1.2113 -                program.load_global(str(self.class_file.this_class.get_python_name()))
  1.2114 -                                                    # Stack: arguments, class
  1.2115 -            else:
  1.2116 -                program.load_fast(1)                # Stack: arguments
  1.2117 -                program.load_fast(0)                # Stack: arguments, self
  1.2118 -
  1.2119 -            program.load_attr(str(method.get_python_name()))
  1.2120 -                                                    # Stack: arguments, method
  1.2121 -            program.rot_two()                       # Stack: method, arguments
  1.2122 -            program.call_function_var(0)            # Stack: result
  1.2123 -            program.return_value()
  1.2124 -            # Try the next method if arguments or parameters were missing or incorrect.
  1.2125 -            program.start_label("failed")
  1.2126 -            program.pop_top()                       # Stack:
  1.2127 -
  1.2128 -        # Raise an exception if nothing matched.
  1.2129 -        # NOTE: Improve this.
  1.2130 -
  1.2131 -        program.load_const("No matching method")
  1.2132 -        program.raise_varargs(1)
  1.2133 -        program.load_const(None)
  1.2134 -        program.return_value()
  1.2135 -
  1.2136 -        # Add the code as a method in the namespace.
  1.2137 -        # NOTE: One actual parameter, flags as 71 apparently means that a list
  1.2138 -        # NOTE: parameter is used in a method.
  1.2139 -
  1.2140 -        if method_is_static:
  1.2141 -            nargs = 0
  1.2142 -        else:
  1.2143 -            nargs = 1
  1.2144 -        nlocals = program.max_locals + 1
  1.2145 -
  1.2146 -        code = new.code(nargs, nlocals, program.max_stack_depth, 71, program.get_output(),
  1.2147 -            tuple(program.get_constants()), tuple(program.get_names()), tuple(self.make_varnames(nlocals, method_is_static)),
  1.2148 -            self.filename, method_name, 0, "")
  1.2149 -        fn = new.function(code, global_names)
  1.2150 -
  1.2151 -        if method_is_static:
  1.2152 -            fn = staticmethod(fn)
  1.2153 -
  1.2154 -        namespace[method_name] = fn
  1.2155 -
  1.2156 -    def process(self, global_names):
  1.2157 -
  1.2158 -        """
  1.2159 -        Process the class, storing it in the 'global_names' dictionary provided.
  1.2160 -        Return a tuple containing the class and a list of external names
  1.2161 -        referenced by the class's methods.
  1.2162 -        """
  1.2163 -
  1.2164 -        namespace = {}
  1.2165 -
  1.2166 -        # Make the fields.
  1.2167 -
  1.2168 -        for field in self.class_file.fields:
  1.2169 -            if classfile.has_flags(field.access_flags, [classfile.STATIC]):
  1.2170 -                field_name = str(field.get_python_name())
  1.2171 -                namespace[field_name] = None
  1.2172 -
  1.2173 -        # Make the methods.
  1.2174 -
  1.2175 -        real_methods = {}
  1.2176 -        external_names = []
  1.2177 -
  1.2178 -        for method in self.class_file.methods:
  1.2179 -            real_method_name = str(method.get_name())
  1.2180 -            method_name = str(method.get_python_name())
  1.2181 -
  1.2182 -            translator, writer = self.translate_method(method)
  1.2183 -
  1.2184 -            # Add external names to the master list.
  1.2185 -
  1.2186 -            for external_name in writer.external_names:
  1.2187 -                if external_name not in external_names:
  1.2188 -                    external_names.append(external_name)
  1.2189 -
  1.2190 -            # Fix up special class initialisation methods and static methods.
  1.2191 -
  1.2192 -            method_is_static = real_method_name != "<init>" and classfile.has_flags(method.access_flags, [classfile.STATIC])
  1.2193 -            if method_is_static:
  1.2194 -                nargs = len(method.get_descriptor()[0])
  1.2195 -            else:
  1.2196 -                nargs = len(method.get_descriptor()[0]) + 1
  1.2197 -            nlocals = writer.max_locals + 1
  1.2198 -            flags = 67
  1.2199 -
  1.2200 -            # NOTE: Add line number table later.
  1.2201 -
  1.2202 -            code = new.code(nargs, nlocals, writer.max_stack_depth, flags, writer.get_output(),
  1.2203 -                tuple(writer.get_constants()), tuple(writer.get_names()),
  1.2204 -                tuple(self.make_varnames(nlocals, method_is_static)), self.filename, method_name, 0, "")
  1.2205 -
  1.2206 -            # NOTE: May need more globals.
  1.2207 -
  1.2208 -            fn = new.function(code, global_names)
  1.2209 -
  1.2210 -            # Fix up special class initialisation methods and static methods.
  1.2211 -
  1.2212 -            if method_is_static:
  1.2213 -                fn = staticmethod(fn)
  1.2214 -
  1.2215 -            # Remember the real method name and the corresponding methods produced.
  1.2216 -
  1.2217 -            if not real_methods.has_key(real_method_name):
  1.2218 -                real_methods[real_method_name] = []
  1.2219 -            real_methods[real_method_name].append((method, fn))
  1.2220 -
  1.2221 -            # Add the method to the class's namespace.
  1.2222 -
  1.2223 -            namespace[method_name] = fn
  1.2224 -
  1.2225 -        # Define superclasses.
  1.2226 -
  1.2227 -        bases = self.get_base_classes(global_names)
  1.2228 -
  1.2229 -        # Define method dispatchers.
  1.2230 -
  1.2231 -        for real_method_name, methods in real_methods.items():
  1.2232 -            if real_method_name != "<clinit>":
  1.2233 -                self.make_method(real_method_name, methods, global_names, namespace)
  1.2234 -
  1.2235 -        # Use only the last part of the fully qualified name.
  1.2236 -
  1.2237 -        full_class_name = str(self.class_file.this_class.get_python_name())
  1.2238 -        class_name = full_class_name.split(".")[-1]
  1.2239 -        cls = new.classobj(class_name, bases, namespace)
  1.2240 -        global_names[cls.__name__] = cls
  1.2241 -
  1.2242 -        return cls, external_names
  1.2243 -
  1.2244 -    def get_base_classes(self, global_names):
  1.2245 -
  1.2246 -        """
  1.2247 -        Identify the superclass, then either load it from the given
  1.2248 -        'global_names' if available, or import the class from its parent module.
  1.2249 -        Return a tuple containing all base classes (typically a single element
  1.2250 -        tuple).
  1.2251 -        """
  1.2252 -
  1.2253 -        original_name = str(self.class_file.super_class.get_name())
  1.2254 -        full_this_class_name = str(self.class_file.this_class.get_python_name())
  1.2255 -        this_class_name_parts = full_this_class_name.split(".")
  1.2256 -        this_class_module_name = ".".join(this_class_name_parts[:-1])
  1.2257 -        full_super_class_name = str(self.class_file.super_class.get_python_name())
  1.2258 -        super_class_name_parts = full_super_class_name.split(".")
  1.2259 -        super_class_name = super_class_name_parts[-1]
  1.2260 -        super_class_module_name = ".".join(super_class_name_parts[:-1])
  1.2261 -        if super_class_module_name == "":
  1.2262 -            obj = global_names[super_class_name]
  1.2263 -        elif super_class_module_name == this_class_module_name:
  1.2264 -            obj = global_names[super_class_name]
  1.2265 -        else:
  1.2266 -            #print "Importing", super_class_module_name, super_class_name
  1.2267 -            obj = __import__(super_class_module_name, global_names, {}, [])
  1.2268 -            for super_class_name_part in super_class_name_parts[1:] or [super_class_name]:
  1.2269 -                #print "*", obj, super_class_name_part
  1.2270 -                obj = getattr(obj, super_class_name_part)
  1.2271 -        return (obj,)
  1.2272 -
  1.2273 -    def make_varnames(self, nlocals, method_is_static=0):
  1.2274 -
  1.2275 -        """
  1.2276 -        A utility method which invents variable names for the given number -
  1.2277 -        'nlocals' - of local variables in a method. Returns a list of such
  1.2278 -        variable names.
  1.2279 -
  1.2280 -        If the optional 'method_is_static' is set to true, do not use "self" as
  1.2281 -        the first argument name.
  1.2282 -        """
  1.2283 -
  1.2284 -        if method_is_static:
  1.2285 -            l = ["cls"]
  1.2286 -        else:
  1.2287 -            l = ["self"]
  1.2288 -        for i in range(1, nlocals):
  1.2289 -            l.append("_l%s" % i)
  1.2290 -        return l[:nlocals]
  1.2291 -
  1.2292 -# Test functions, useful for tracing generated bytecode operations.
  1.2293 -
  1.2294 -def _map(*args):
  1.2295 -    print args
  1.2296 -    return apply(__builtins__.map, args)
  1.2297 -
  1.2298 -def _isinstance(*args):
  1.2299 -    print args
  1.2300 -    return apply(__builtins__.isinstance, args)
  1.2301 -
  1.2302 -if __name__ == "__main__":
  1.2303 -    import sys
  1.2304 -    import dis
  1.2305 -    global_names = globals()
  1.2306 -    #global_names["isinstance"] = _isinstance
  1.2307 -    #global_names["map"] = _map
  1.2308 -    for filename in sys.argv[1:]:
  1.2309 -        f = open(filename, "rb")
  1.2310 -        c = classfile.ClassFile(f.read())
  1.2311 -        translator = ClassTranslator(c)
  1.2312 -        cls, external_names = translator.process(global_names)
  1.2313 -
  1.2314 -# vim: tabstop=4 expandtab shiftwidth=4
     2.1 --- a/classfile.py	Fri Jan 21 17:04:41 2005 +0100
     2.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.3 @@ -1,633 +0,0 @@
     2.4 -#!/usr/bin/env python
     2.5 -
     2.6 -"""
     2.7 -Java class file decoder. Specification found at the following URL:
     2.8 -http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html
     2.9 -"""
    2.10 -
    2.11 -import struct # for general decoding of class files
    2.12 -
    2.13 -# Utility functions.
    2.14 -
    2.15 -def u1(data):
    2.16 -    return struct.unpack(">B", data[0:1])[0]
    2.17 -
    2.18 -def u2(data):
    2.19 -    return struct.unpack(">H", data[0:2])[0]
    2.20 -
    2.21 -def s2(data):
    2.22 -    return struct.unpack(">h", data[0:2])[0]
    2.23 -
    2.24 -def u4(data):
    2.25 -    return struct.unpack(">L", data[0:4])[0]
    2.26 -
    2.27 -def s4(data):
    2.28 -    return struct.unpack(">l", data[0:4])[0]
    2.29 -
    2.30 -def s8(data):
    2.31 -    return struct.unpack(">q", data[0:8])[0]
    2.32 -
    2.33 -def f4(data):
    2.34 -    return struct.unpack(">f", data[0:4])[0]
    2.35 -
    2.36 -def f8(data):
    2.37 -    return struct.unpack(">d", data[0:8])[0]
    2.38 -
    2.39 -# Useful tables and constants.
    2.40 -
    2.41 -descriptor_base_type_mapping = {
    2.42 -    "B" : "int",
    2.43 -    "C" : "str",
    2.44 -    "D" : "float",
    2.45 -    "F" : "float",
    2.46 -    "I" : "int",
    2.47 -    "J" : "int",
    2.48 -    "L" : "object",
    2.49 -    "S" : "int",
    2.50 -    "Z" : "bool",
    2.51 -    "[" : "list"
    2.52 -    }
    2.53 -
    2.54 -PUBLIC, PRIVATE, PROTECTED, STATIC, FINAL,  SUPER,  SYNCHRONIZED, VOLATILE, TRANSIENT, NATIVE, INTERFACE, ABSTRACT, STRICT = \
    2.55 -0x0001, 0x0002,  0x0004,    0x0008, 0x0010, 0x0020, 0x0020,       0x0040,   0x0080,    0x0100, 0x0200,    0x0400,   0x0800
    2.56 -
    2.57 -def has_flags(flags, desired):
    2.58 -    desired_flags = reduce(lambda a, b: a | b, desired, 0)
    2.59 -    return (flags & desired_flags) == desired_flags
    2.60 -
    2.61 -# Useful mix-ins.
    2.62 -
    2.63 -class PythonMethodUtils:
    2.64 -    symbol_sep = "___" # was "$"
    2.65 -    type_sep = "__" # replaces "/"
    2.66 -    array_sep = "_array_" # was "[]"
    2.67 -    base_seps = ("_", "_") # was "<" and ">"
    2.68 -
    2.69 -    def get_unqualified_python_name(self):
    2.70 -        name = self.get_name()
    2.71 -        if str(name) == "<init>":
    2.72 -            return "__init__"
    2.73 -        elif str(name) == "<clinit>":
    2.74 -            return "__clinit__"
    2.75 -        else:
    2.76 -            return str(name)
    2.77 -
    2.78 -    def get_python_name(self):
    2.79 -        name = self.get_unqualified_python_name()
    2.80 -        if name == "__clinit__":
    2.81 -            return name
    2.82 -        return name + self.symbol_sep + self._get_descriptor_as_name()
    2.83 -
    2.84 -    def _get_descriptor_as_name(self):
    2.85 -        l = []
    2.86 -        for descriptor_type in self.get_descriptor()[0]:
    2.87 -            l.append(self._get_type_as_name(descriptor_type))
    2.88 -        return self.symbol_sep.join(l)
    2.89 -
    2.90 -    def _get_type_as_name(self, descriptor_type, s=""):
    2.91 -        base_type, object_type, array_type = descriptor_type
    2.92 -        if base_type == "L":
    2.93 -            return object_type.replace("/", self.type_sep) + s
    2.94 -        elif base_type == "[":
    2.95 -            return self._get_type_as_name(array_type, s + self.array_sep)
    2.96 -        else:
    2.97 -            return self.base_seps[0] + base_type + self.base_seps[1] + s
    2.98 -
    2.99 -class PythonNameUtils:
   2.100 -    def get_python_name(self):
   2.101 -        # NOTE: This may not be comprehensive.
   2.102 -        if not str(self.get_name()).startswith("["):
   2.103 -            return str(self.get_name()).replace("/", ".")
   2.104 -        else:
   2.105 -            return self._get_type_name(
   2.106 -                get_field_descriptor(
   2.107 -                    str(self.get_name())
   2.108 -                    )
   2.109 -                ).replace("/", ".")
   2.110 -
   2.111 -    def _get_type_name(self, descriptor_type):
   2.112 -        base_type, object_type, array_type = descriptor_type
   2.113 -        if base_type == "L":
   2.114 -            return object_type
   2.115 -        elif base_type == "[":
   2.116 -            return self._get_type_name(array_type)
   2.117 -        else:
   2.118 -            return descriptor_base_type_mapping[base_type]
   2.119 -
   2.120 -class NameUtils:
   2.121 -    def get_name(self):
   2.122 -        if self.name_index != 0:
   2.123 -            return self.class_file.constants[self.name_index - 1]
   2.124 -        else:
   2.125 -            # Some name indexes are zero to indicate special conditions.
   2.126 -            return None
   2.127 -
   2.128 -class NameAndTypeUtils:
   2.129 -    def get_name(self):
   2.130 -        if self.name_and_type_index != 0:
   2.131 -            return self.class_file.constants[self.name_and_type_index - 1].get_name()
   2.132 -        else:
   2.133 -            # Some name indexes are zero to indicate special conditions.
   2.134 -            return None
   2.135 -
   2.136 -    def get_field_descriptor(self):
   2.137 -        if self.name_and_type_index != 0:
   2.138 -            return self.class_file.constants[self.name_and_type_index - 1].get_field_descriptor()
   2.139 -        else:
   2.140 -            # Some name indexes are zero to indicate special conditions.
   2.141 -            return None
   2.142 -
   2.143 -    def get_method_descriptor(self):
   2.144 -        if self.name_and_type_index != 0:
   2.145 -            return self.class_file.constants[self.name_and_type_index - 1].get_method_descriptor()
   2.146 -        else:
   2.147 -            # Some name indexes are zero to indicate special conditions.
   2.148 -            return None
   2.149 -
   2.150 -    def get_class(self):
   2.151 -        return self.class_file.constants[self.class_index - 1]
   2.152 -
   2.153 -# Symbol parsing.
   2.154 -
   2.155 -def get_method_descriptor(s):
   2.156 -    assert s[0] == "("
   2.157 -    params = []
   2.158 -    s = s[1:]
   2.159 -    while s[0] != ")":
   2.160 -        parameter_descriptor, s = _get_parameter_descriptor(s)
   2.161 -        params.append(parameter_descriptor)
   2.162 -    if s[1] != "V":
   2.163 -        return_type, s = _get_field_type(s[1:])
   2.164 -    else:
   2.165 -        return_type, s = None, s[1:]
   2.166 -    return params, return_type
   2.167 -
   2.168 -def get_field_descriptor(s):
   2.169 -    return _get_field_type(s)[0]
   2.170 -
   2.171 -def _get_parameter_descriptor(s):
   2.172 -    return _get_field_type(s)
   2.173 -
   2.174 -def _get_component_type(s):
   2.175 -    return _get_field_type(s)
   2.176 -
   2.177 -def _get_field_type(s):
   2.178 -    base_type, s = _get_base_type(s)
   2.179 -    object_type = None
   2.180 -    array_type = None
   2.181 -    if base_type == "L":
   2.182 -        object_type, s = _get_object_type(s)
   2.183 -    elif base_type == "[":
   2.184 -        array_type, s = _get_array_type(s)
   2.185 -    return (base_type, object_type, array_type), s
   2.186 -
   2.187 -def _get_base_type(s):
   2.188 -    if len(s) > 0:
   2.189 -        return s[0], s[1:]
   2.190 -    else:
   2.191 -        return None, s
   2.192 -
   2.193 -def _get_object_type(s):
   2.194 -    if len(s) > 0:
   2.195 -        s_end = s.find(";")
   2.196 -        assert s_end != -1
   2.197 -        return s[:s_end], s[s_end+1:]
   2.198 -    else:
   2.199 -        return None, s
   2.200 -
   2.201 -def _get_array_type(s):
   2.202 -    if len(s) > 0:
   2.203 -        return _get_component_type(s)
   2.204 -    else:
   2.205 -        return None, s
   2.206 -
   2.207 -# Constant information.
   2.208 -
   2.209 -class ClassInfo(NameUtils, PythonNameUtils):
   2.210 -    def init(self, data, class_file):
   2.211 -        self.class_file = class_file
   2.212 -        self.name_index = u2(data[0:2])
   2.213 -        return data[2:]
   2.214 -
   2.215 -class RefInfo(NameAndTypeUtils):
   2.216 -    def init(self, data, class_file):
   2.217 -        self.class_file = class_file
   2.218 -        self.class_index = u2(data[0:2])
   2.219 -        self.name_and_type_index = u2(data[2:4])
   2.220 -        return data[4:]
   2.221 -
   2.222 -class FieldRefInfo(RefInfo, PythonNameUtils):
   2.223 -    def get_descriptor(self):
   2.224 -        return RefInfo.get_field_descriptor(self)
   2.225 -
   2.226 -class MethodRefInfo(RefInfo, PythonMethodUtils):
   2.227 -    def get_descriptor(self):
   2.228 -        return RefInfo.get_method_descriptor(self)
   2.229 -
   2.230 -class InterfaceMethodRefInfo(MethodRefInfo):
   2.231 -    pass
   2.232 -
   2.233 -class NameAndTypeInfo(NameUtils, PythonNameUtils):
   2.234 -    def init(self, data, class_file):
   2.235 -        self.class_file = class_file
   2.236 -        self.name_index = u2(data[0:2])
   2.237 -        self.descriptor_index = u2(data[2:4])
   2.238 -        return data[4:]
   2.239 -
   2.240 -    def get_field_descriptor(self):
   2.241 -        return get_field_descriptor(unicode(self.class_file.constants[self.descriptor_index - 1]))
   2.242 -
   2.243 -    def get_method_descriptor(self):
   2.244 -        return get_method_descriptor(unicode(self.class_file.constants[self.descriptor_index - 1]))
   2.245 -
   2.246 -class Utf8Info:
   2.247 -    def init(self, data, class_file):
   2.248 -        self.class_file = class_file
   2.249 -        self.length = u2(data[0:2])
   2.250 -        self.bytes = data[2:2+self.length]
   2.251 -        return data[2+self.length:]
   2.252 -
   2.253 -    def __str__(self):
   2.254 -        return self.bytes
   2.255 -
   2.256 -    def __unicode__(self):
   2.257 -        return unicode(self.bytes, "utf-8")
   2.258 -
   2.259 -    def get_value(self):
   2.260 -        return str(self)
   2.261 -
   2.262 -class StringInfo:
   2.263 -    def init(self, data, class_file):
   2.264 -        self.class_file = class_file
   2.265 -        self.string_index = u2(data[0:2])
   2.266 -        return data[2:]
   2.267 -
   2.268 -    def __str__(self):
   2.269 -        return str(self.class_file.constants[self.string_index - 1])
   2.270 -
   2.271 -    def __unicode__(self):
   2.272 -        return unicode(self.class_file.constants[self.string_index - 1])
   2.273 -
   2.274 -    def get_value(self):
   2.275 -        return str(self)
   2.276 -
   2.277 -class SmallNumInfo:
   2.278 -    def init(self, data, class_file):
   2.279 -        self.class_file = class_file
   2.280 -        self.bytes = data[0:4]
   2.281 -        return data[4:]
   2.282 -
   2.283 -class IntegerInfo(SmallNumInfo):
   2.284 -    def get_value(self):
   2.285 -        return s4(self.bytes)
   2.286 -
   2.287 -class FloatInfo(SmallNumInfo):
   2.288 -    def get_value(self):
   2.289 -        return f4(self.bytes)
   2.290 -
   2.291 -class LargeNumInfo:
   2.292 -    def init(self, data, class_file):
   2.293 -        self.class_file = class_file
   2.294 -        self.high_bytes = data[0:4]
   2.295 -        self.low_bytes = data[4:8]
   2.296 -        return data[8:]
   2.297 -
   2.298 -class LongInfo(LargeNumInfo):
   2.299 -    def get_value(self):
   2.300 -        return s8(self.high_bytes + self.low_bytes)
   2.301 -
   2.302 -class DoubleInfo(LargeNumInfo):
   2.303 -    def get_value(self):
   2.304 -        return f8(self.high_bytes + self.low_bytes)
   2.305 -
   2.306 -# Other information.
   2.307 -# Objects of these classes are generally aware of the class they reside in.
   2.308 -
   2.309 -class ItemInfo(NameUtils):
   2.310 -    def init(self, data, class_file):
   2.311 -        self.class_file = class_file
   2.312 -        self.access_flags = u2(data[0:2])
   2.313 -        self.name_index = u2(data[2:4])
   2.314 -        self.descriptor_index = u2(data[4:6])
   2.315 -        self.attributes, data = self.class_file._get_attributes(data[6:])
   2.316 -        return data
   2.317 -
   2.318 -class FieldInfo(ItemInfo, PythonNameUtils):
   2.319 -    def get_descriptor(self):
   2.320 -        return get_field_descriptor(unicode(self.class_file.constants[self.descriptor_index - 1]))
   2.321 -
   2.322 -class MethodInfo(ItemInfo, PythonMethodUtils):
   2.323 -    def get_descriptor(self):
   2.324 -        return get_method_descriptor(unicode(self.class_file.constants[self.descriptor_index - 1]))
   2.325 -
   2.326 -class AttributeInfo:
   2.327 -    def init(self, data, class_file):
   2.328 -        self.attribute_length = u4(data[0:4])
   2.329 -        self.info = data[4:4+self.attribute_length]
   2.330 -        return data[4+self.attribute_length:]
   2.331 -
   2.332 -# NOTE: Decode the different attribute formats.
   2.333 -
   2.334 -class SourceFileAttributeInfo(AttributeInfo, NameUtils, PythonNameUtils):
   2.335 -    def init(self, data, class_file):
   2.336 -        self.class_file = class_file
   2.337 -        self.attribute_length = u4(data[0:4])
   2.338 -        # Permit the NameUtils mix-in.
   2.339 -        self.name_index = self.sourcefile_index = u2(data[4:6])
   2.340 -        return data[6:]
   2.341 -
   2.342 -class ConstantValueAttributeInfo(AttributeInfo):
   2.343 -    def init(self, data, class_file):
   2.344 -        self.class_file = class_file
   2.345 -        self.attribute_length = u4(data[0:4])
   2.346 -        self.constant_value_index = u2(data[4:6])
   2.347 -        assert 4+self.attribute_length == 6
   2.348 -        return data[4+self.attribute_length:]
   2.349 -
   2.350 -    def get_value(self):
   2.351 -        return self.class_file.constants[self.constant_value_index - 1].get_value()
   2.352 -
   2.353 -class CodeAttributeInfo(AttributeInfo):
   2.354 -    def init(self, data, class_file):
   2.355 -        self.class_file = class_file
   2.356 -        self.attribute_length = u4(data[0:4])
   2.357 -        self.max_stack = u2(data[4:6])
   2.358 -        self.max_locals = u2(data[6:8])
   2.359 -        self.code_length = u4(data[8:12])
   2.360 -        end_of_code = 12+self.code_length
   2.361 -        self.code = data[12:end_of_code]
   2.362 -        self.exception_table_length = u2(data[end_of_code:end_of_code+2])
   2.363 -        self.exception_table = []
   2.364 -        data = data[end_of_code + 2:]
   2.365 -        for i in range(0, self.exception_table_length):
   2.366 -            exception = ExceptionInfo()
   2.367 -            data = exception.init(data)
   2.368 -            self.exception_table.append(exception)
   2.369 -        self.attributes, data = self.class_file._get_attributes(data)
   2.370 -        return data
   2.371 -
   2.372 -class ExceptionsAttributeInfo(AttributeInfo):
   2.373 -    def init(self, data, class_file):
   2.374 -        self.class_file = class_file
   2.375 -        self.attribute_length = u4(data[0:4])
   2.376 -        self.number_of_exceptions = u2(data[4:6])
   2.377 -        self.exception_index_table = []
   2.378 -        index = 6
   2.379 -        for i in range(0, self.number_of_exceptions):
   2.380 -            self.exception_index_table.append(u2(data[index:index+2]))
   2.381 -            index += 2
   2.382 -        return data[index:]
   2.383 -
   2.384 -    def get_exception(self, i):
   2.385 -        exception_index = self.exception_index_table[i]
   2.386 -        return self.class_file.constants[exception_index - 1]
   2.387 -
   2.388 -class InnerClassesAttributeInfo(AttributeInfo):
   2.389 -    def init(self, data, class_file):
   2.390 -        self.class_file = class_file
   2.391 -        self.attribute_length = u4(data[0:4])
   2.392 -        self.number_of_classes = u2(data[4:6])
   2.393 -        self.classes = []
   2.394 -        data = data[6:]
   2.395 -        for i in range(0, self.number_of_classes):
   2.396 -            inner_class = InnerClassInfo()
   2.397 -            data = inner_class.init(data, self.class_file)
   2.398 -            self.classes.append(inner_class)
   2.399 -        return data
   2.400 -
   2.401 -class SyntheticAttributeInfo(AttributeInfo):
   2.402 -    pass
   2.403 -
   2.404 -class LineNumberAttributeInfo(AttributeInfo):
   2.405 -    def init(self, data, class_file):
   2.406 -        self.class_file = class_file
   2.407 -        self.attribute_length = u4(data[0:4])
   2.408 -        self.line_number_table_length = u2(data[4:6])
   2.409 -        self.line_number_table = []
   2.410 -        data = data[6:]
   2.411 -        for i in range(0, self.line_number_table_length):
   2.412 -            line_number = LineNumberInfo()
   2.413 -            data = line_number.init(data)
   2.414 -            self.line_number_table.append(line_number)
   2.415 -        return data
   2.416 -
   2.417 -class LocalVariableAttributeInfo(AttributeInfo):
   2.418 -    def init(self, data, class_file):
   2.419 -        self.class_file = class_file
   2.420 -        self.attribute_length = u4(data[0:4])
   2.421 -        self.local_variable_table_length = u2(data[4:6])
   2.422 -        self.local_variable_table = []
   2.423 -        data = data[6:]
   2.424 -        for i in range(0, self.local_variable_table_length):
   2.425 -            local_variable = LocalVariableInfo()
   2.426 -            data = local_variable.init(data, self.class_file)
   2.427 -            self.local_variable_table.append(local_variable)
   2.428 -        return data
   2.429 -
   2.430 -class DeprecatedAttributeInfo(AttributeInfo):
   2.431 -    pass
   2.432 -
   2.433 -# Child classes of the attribute information classes.
   2.434 -
   2.435 -class ExceptionInfo:
   2.436 -    def init(self, data):
   2.437 -        self.start_pc = u2(data[0:2])
   2.438 -        self.end_pc = u2(data[2:4])
   2.439 -        self.handler_pc = u2(data[4:6])
   2.440 -        self.catch_type = u2(data[6:8])
   2.441 -        return data[8:]
   2.442 -
   2.443 -class InnerClassInfo(NameUtils):
   2.444 -    def init(self, data, class_file):
   2.445 -        self.class_file = class_file
   2.446 -        self.inner_class_info_index = u2(data[0:2])
   2.447 -        self.outer_class_info_index = u2(data[2:4])
   2.448 -        # Permit the NameUtils mix-in.
   2.449 -        self.name_index = self.inner_name_index = u2(data[4:6])
   2.450 -        self.inner_class_access_flags = u2(data[6:8])
   2.451 -        return data[8:]
   2.452 -
   2.453 -class LineNumberInfo:
   2.454 -    def init(self, data):
   2.455 -        self.start_pc = u2(data[0:2])
   2.456 -        self.line_number = u2(data[2:4])
   2.457 -        return data[4:]
   2.458 -
   2.459 -class LocalVariableInfo(NameUtils, PythonNameUtils):
   2.460 -    def init(self, data, class_file):
   2.461 -        self.class_file = class_file
   2.462 -        self.start_pc = u2(data[0:2])
   2.463 -        self.length = u2(data[2:4])
   2.464 -        self.name_index = u2(data[4:6])
   2.465 -        self.descriptor_index = u2(data[6:8])
   2.466 -        self.index = u2(data[8:10])
   2.467 -        return data[10:]
   2.468 -
   2.469 -    def get_descriptor(self):
   2.470 -        return get_field_descriptor(unicode(self.class_file.constants[self.descriptor_index - 1]))
   2.471 -
   2.472 -# Exceptions.
   2.473 -
   2.474 -class UnknownTag(Exception):
   2.475 -    pass
   2.476 -
   2.477 -class UnknownAttribute(Exception):
   2.478 -    pass
   2.479 -
   2.480 -# Abstractions for the main structures.
   2.481 -
   2.482 -class ClassFile:
   2.483 -
   2.484 -    "A class representing a Java class file."
   2.485 -
   2.486 -    def __init__(self, s):
   2.487 -
   2.488 -        """
   2.489 -        Process the given string 's', populating the object with the class
   2.490 -        file's details.
   2.491 -        """
   2.492 -
   2.493 -        self.constants, s = self._get_constants(s[8:])
   2.494 -        self.access_flags, s = self._get_access_flags(s)
   2.495 -        self.this_class, s = self._get_this_class(s)
   2.496 -        self.super_class, s = self._get_super_class(s)
   2.497 -        self.interfaces, s = self._get_interfaces(s)
   2.498 -        self.fields, s = self._get_fields(s)
   2.499 -        self.methods, s = self._get_methods(s)
   2.500 -        self.attributes, s = self._get_attributes(s)
   2.501 -
   2.502 -    def _decode_const(self, s):
   2.503 -        tag = u1(s[0:1])
   2.504 -        if tag == 1:
   2.505 -            const = Utf8Info()
   2.506 -        elif tag == 3:
   2.507 -            const = IntegerInfo()
   2.508 -        elif tag == 4:
   2.509 -            const = FloatInfo()
   2.510 -        elif tag == 5:
   2.511 -            const = LongInfo()
   2.512 -        elif tag == 6:
   2.513 -            const = DoubleInfo()
   2.514 -        elif tag == 7:
   2.515 -            const = ClassInfo()
   2.516 -        elif tag == 8:
   2.517 -            const = StringInfo()
   2.518 -        elif tag == 9:
   2.519 -            const = FieldRefInfo()
   2.520 -        elif tag == 10:
   2.521 -            const = MethodRefInfo()
   2.522 -        elif tag == 11:
   2.523 -            const = InterfaceMethodRefInfo()
   2.524 -        elif tag == 12:
   2.525 -            const = NameAndTypeInfo()
   2.526 -        else:
   2.527 -            raise UnknownTag, tag
   2.528 -
   2.529 -        # Initialise the constant object.
   2.530 -
   2.531 -        s = const.init(s[1:], self)
   2.532 -        return const, s
   2.533 -
   2.534 -    def _get_constants_from_table(self, count, s):
   2.535 -        l = []
   2.536 -        # Have to skip certain entries specially.
   2.537 -        i = 1
   2.538 -        while i < count:
   2.539 -            c, s = self._decode_const(s)
   2.540 -            l.append(c)
   2.541 -            # Add a blank entry after "large" entries.
   2.542 -            if isinstance(c, LargeNumInfo):
   2.543 -                l.append(None)
   2.544 -                i += 1
   2.545 -            i += 1
   2.546 -        return l, s
   2.547 -
   2.548 -    def _get_items_from_table(self, cls, number, s):
   2.549 -        l = []
   2.550 -        for i in range(0, number):
   2.551 -            f = cls()
   2.552 -            s = f.init(s, self)
   2.553 -            l.append(f)
   2.554 -        return l, s
   2.555 -
   2.556 -    def _get_methods_from_table(self, number, s):
   2.557 -        return self._get_items_from_table(MethodInfo, number, s)
   2.558 -
   2.559 -    def _get_fields_from_table(self, number, s):
   2.560 -        return self._get_items_from_table(FieldInfo, number, s)
   2.561 -
   2.562 -    def _get_attribute_from_table(self, s):
   2.563 -        attribute_name_index = u2(s[0:2])
   2.564 -        constant_name = self.constants[attribute_name_index - 1].bytes
   2.565 -        if constant_name == "SourceFile":
   2.566 -            attribute = SourceFileAttributeInfo()
   2.567 -        elif constant_name == "ConstantValue":
   2.568 -            attribute = ConstantValueAttributeInfo()
   2.569 -        elif constant_name == "Code":
   2.570 -            attribute = CodeAttributeInfo()
   2.571 -        elif constant_name == "Exceptions":
   2.572 -            attribute = ExceptionsAttributeInfo()
   2.573 -        elif constant_name == "InnerClasses":
   2.574 -            attribute = InnerClassesAttributeInfo()
   2.575 -        elif constant_name == "Synthetic":
   2.576 -            attribute = SyntheticAttributeInfo()
   2.577 -        elif constant_name == "LineNumberTable":
   2.578 -            attribute = LineNumberAttributeInfo()
   2.579 -        elif constant_name == "LocalVariableTable":
   2.580 -            attribute = LocalVariableAttributeInfo()
   2.581 -        elif constant_name == "Deprecated":
   2.582 -            attribute = DeprecatedAttributeInfo()
   2.583 -        else:
   2.584 -            raise UnknownAttribute, constant_name
   2.585 -        s = attribute.init(s[2:], self)
   2.586 -        return attribute, s
   2.587 -
   2.588 -    def _get_attributes_from_table(self, number, s):
   2.589 -        attributes = []
   2.590 -        for i in range(0, number):
   2.591 -            attribute, s = self._get_attribute_from_table(s)
   2.592 -            attributes.append(attribute)
   2.593 -        return attributes, s
   2.594 -
   2.595 -    def _get_constants(self, s):
   2.596 -        count = u2(s[0:2])
   2.597 -        return self._get_constants_from_table(count, s[2:])
   2.598 -
   2.599 -    def _get_access_flags(self, s):
   2.600 -        return u2(s[0:2]), s[2:]
   2.601 -
   2.602 -    def _get_this_class(self, s):
   2.603 -        index = u2(s[0:2])
   2.604 -        return self.constants[index - 1], s[2:]
   2.605 -
   2.606 -    _get_super_class = _get_this_class
   2.607 -
   2.608 -    def _get_interfaces(self, s):
   2.609 -        interfaces = []
   2.610 -        number = u2(s[0:2])
   2.611 -        s = s[2:]
   2.612 -        for i in range(0, number):
   2.613 -            index = u2(s[0:2])
   2.614 -            interfaces.append(self.constants[index - 1])
   2.615 -            s = s[2:]
   2.616 -        return interfaces, s
   2.617 -
   2.618 -    def _get_fields(self, s):
   2.619 -        number = u2(s[0:2])
   2.620 -        return self._get_fields_from_table(number, s[2:])
   2.621 -
   2.622 -    def _get_attributes(self, s):
   2.623 -        number = u2(s[0:2])
   2.624 -        return self._get_attributes_from_table(number, s[2:])
   2.625 -
   2.626 -    def _get_methods(self, s):
   2.627 -        number = u2(s[0:2])
   2.628 -        return self._get_methods_from_table(number, s[2:])
   2.629 -
   2.630 -if __name__ == "__main__":
   2.631 -    import sys
   2.632 -    f = open(sys.argv[1], "rb")
   2.633 -    c = ClassFile(f.read())
   2.634 -    f.close()
   2.635 -
   2.636 -# vim: tabstop=4 expandtab shiftwidth=4
     3.1 --- a/classhook.py	Fri Jan 21 17:04:41 2005 +0100
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,384 +0,0 @@
     3.4 -#!/usr/bin/env python
     3.5 -
     3.6 -import ihooks # for the import machinery
     3.7 -import os, glob # for getting suitably-named files
     3.8 -from imp import PY_SOURCE, PKG_DIRECTORY, C_BUILTIN # import machinery magic
     3.9 -import classfile, bytecode # Java class support
    3.10 -import zipfile # for Java archive inspection
    3.11 -
    3.12 -# NOTE: Arbitrary constants pulled from thin air.
    3.13 -
    3.14 -JAVA_PACKAGE = 20041113
    3.15 -JAVA_CLASS = 20041114
    3.16 -JAVA_ARCHIVE = 20041115
    3.17 -
    3.18 -class ClassHooks(ihooks.Hooks):
    3.19 -
    3.20 -    "A filesystem hooks class providing information about supported files."
    3.21 -
    3.22 -    def get_suffixes(self):
    3.23 -
    3.24 -        "Return the recognised suffixes."
    3.25 -
    3.26 -        return [("", "", JAVA_PACKAGE), (os.extsep + "jar", "r", JAVA_ARCHIVE)] + ihooks.Hooks.get_suffixes(self)
    3.27 -
    3.28 -    def path_isdir(self, x, archive=None):
    3.29 -
    3.30 -        "Return whether 'x' is a directory in the given 'archive'."
    3.31 -
    3.32 -        if archive is None:
    3.33 -            return ihooks.Hooks.path_isdir(self, x)
    3.34 -
    3.35 -        return self._get_dirname(x) in archive.namelist()
    3.36 -
    3.37 -    def _get_dirname(self, x):
    3.38 -
    3.39 -        """
    3.40 -        Return the directory name for 'x'.
    3.41 -        In zip files, the presence of "/" seems to indicate a directory.
    3.42 -        """
    3.43 -
    3.44 -        if x.endswith("/"):
    3.45 -            return x
    3.46 -        else:
    3.47 -            return x + "/"
    3.48 -
    3.49 -    def listdir(self, x, archive=None):
    3.50 -
    3.51 -        "Return the contents of the directory 'x' in the given 'archive'."
    3.52 -
    3.53 -        if archive is None:
    3.54 -            return ihooks.Hooks.listdir(self, x)
    3.55 -
    3.56 -        x = self._get_dirname(x)
    3.57 -        l = []
    3.58 -        for path in archive.namelist():
    3.59 -
    3.60 -            # Find out if the path is within the given directory.
    3.61 -
    3.62 -            if path != x and path.startswith(x):
    3.63 -
    3.64 -                # Get the path below the given directory.
    3.65 -
    3.66 -                subpath = path[len(x):]
    3.67 -
    3.68 -                # Find out whether the path is an object in the current directory.
    3.69 -
    3.70 -                if subpath.count("/") == 0 or subpath.count("/") == 1 and subpath.endswith("/"):
    3.71 -                    l.append(subpath)
    3.72 -
    3.73 -        return l
    3.74 -
    3.75 -    def matching(self, dir, extension, archive=None):
    3.76 -
    3.77 -        """
    3.78 -        Return the matching files in the given directory 'dir' having the given
    3.79 -        'extension' within the given 'archive'. Produce a list containing full
    3.80 -        paths as opposed to simple filenames.
    3.81 -        """
    3.82 -
    3.83 -        if archive is None:
    3.84 -            return glob.glob(self.path_join(dir, "*" + extension))
    3.85 -
    3.86 -        dir = self._get_dirname(dir)
    3.87 -        l = []
    3.88 -        for path in self.listdir(dir, archive):
    3.89 -            if path.endswith(extension):
    3.90 -                l.append(self.path_join(dir, path))
    3.91 -        return l
    3.92 -
    3.93 -    def read(self, filename, archive=None):
    3.94 -
    3.95 -        """
    3.96 -        Return the contents of the file with the given 'filename' in the given
    3.97 -        'archive'.
    3.98 -        """
    3.99 -
   3.100 -        if archive is None:
   3.101 -            f = open(filename, "rb")
   3.102 -            s = f.read()
   3.103 -            f.close()
   3.104 -            return s
   3.105 -        return archive.read(filename)
   3.106 -
   3.107 -class ClassLoader(ihooks.ModuleLoader):
   3.108 -
   3.109 -    "A class providing support for searching directories for supported files."
   3.110 -
   3.111 -    def find_module(self, name, path=None):
   3.112 -
   3.113 -        """
   3.114 -        Find the module with the given 'name', using the given 'path' to locate
   3.115 -        it. Note that ModuleLoader.find_module is almost sufficient, but does
   3.116 -        not provide enough support for "package unions" where the root of a
   3.117 -        package hierarchy may appear in several places.
   3.118 -
   3.119 -        Return a list of locations (each being the "stuff" data structure used
   3.120 -        by load_module); this replaces the single "stuff" value or None returned
   3.121 -        by ModuleLoader.find_module.
   3.122 -        """
   3.123 -
   3.124 -        if path is None:
   3.125 -            path = [None] + self.default_path()
   3.126 -
   3.127 -        found_locations = []
   3.128 -
   3.129 -        for dir in path:
   3.130 -            stuff = self.find_module_in_dir(name, dir)
   3.131 -            if stuff:
   3.132 -                found_locations.append(stuff)
   3.133 -
   3.134 -        return found_locations
   3.135 -
   3.136 -    def find_module_in_dir(self, name, dir, allow_packages=1):
   3.137 -
   3.138 -        """
   3.139 -        Find the module with the given 'name' in the given directory 'dir'.
   3.140 -        Since Java packages/modules are directories containing class files,
   3.141 -        return the required information tuple only when the path constructed
   3.142 -        from 'dir' and 'name' refers to a directory containing class files.
   3.143 -        """
   3.144 -
   3.145 -        result = ihooks.ModuleLoader.find_module_in_dir(self, name, dir, allow_packages)
   3.146 -        if result is not None:
   3.147 -            return result
   3.148 -
   3.149 -        # An archive may be opened.
   3.150 -
   3.151 -        archive = None
   3.152 -
   3.153 -        # Provide a special name for the current directory.
   3.154 -
   3.155 -        if name == "__this__":
   3.156 -            if dir == None:
   3.157 -                return (None, ".", ("", "", JAVA_PACKAGE))
   3.158 -            else:
   3.159 -                return None
   3.160 -
   3.161 -        # Where no directory is given, return failure immediately.
   3.162 -
   3.163 -        elif dir is None:
   3.164 -            return None
   3.165 -
   3.166 -        # Detect archives.
   3.167 -
   3.168 -        else:
   3.169 -            archive, archive_path, path = self._get_archive_and_path(dir, name)
   3.170 -
   3.171 -        #print "Processing name", name, "in", dir, "producing", path, "within archive", archive
   3.172 -
   3.173 -        if self._find_module_at_path(path, archive):
   3.174 -            if archive is not None:
   3.175 -                return (archive, archive_path + ":" + path, (os.extsep + "jar", "r", JAVA_ARCHIVE))
   3.176 -            else:
   3.177 -                return (None, path, ("", "", JAVA_PACKAGE))
   3.178 -        else:
   3.179 -            return None
   3.180 -
   3.181 -    def _get_archive_and_path(self, dir, name):
   3.182 -        parts = dir.split(":")
   3.183 -        archive_path = parts[0]
   3.184 -
   3.185 -        # Archives may include an internal path, but will in any case have
   3.186 -        # a primary part ending in .jar.
   3.187 -
   3.188 -        if archive_path.endswith(os.extsep + "jar"):
   3.189 -            archive = zipfile.ZipFile(archive_path, "r")
   3.190 -            path = self.hooks.path_join(":".join(parts[1:]), name)
   3.191 -
   3.192 -        # Otherwise, produce a filesystem-based path.
   3.193 -
   3.194 -        else:
   3.195 -            archive = None
   3.196 -            path = self.hooks.path_join(dir, name)
   3.197 -
   3.198 -        return archive, archive_path, path
   3.199 -
   3.200 -    def _get_path_in_archive(self, path):
   3.201 -        parts = path.split(":")
   3.202 -        if len(parts) == 1:
   3.203 -            return parts[0]
   3.204 -        else:
   3.205 -            return ":".join(parts[1:])
   3.206 -
   3.207 -    def _find_module_at_path(self, path, archive):
   3.208 -        if self.hooks.path_isdir(path, archive):
   3.209 -            #print "Looking in", path, "using archive", archive
   3.210 -
   3.211 -            # Look for classes in the directory.
   3.212 -
   3.213 -            if len(self.hooks.matching(path, os.extsep + "class", archive)) != 0:
   3.214 -                return 1
   3.215 -
   3.216 -            # Otherwise permit importing where directories containing classes exist.
   3.217 -
   3.218 -            #print "Filenames are", self.hooks.listdir(path, archive)
   3.219 -            for filename in self.hooks.listdir(path, archive):
   3.220 -                pathname = self.hooks.path_join(path, filename)
   3.221 -                result = self._find_module_at_path(pathname, archive)
   3.222 -                if result is not None:
   3.223 -                    return result
   3.224 -
   3.225 -        return 0
   3.226 -
   3.227 -    def load_module(self, name, stuff):
   3.228 -
   3.229 -        """
   3.230 -        Load the module with the given 'name', with a list of 'stuff' items,
   3.231 -        each of which describes the location of the module and is a tuple of the
   3.232 -        form (file, filename, (suffix, mode, data type)).
   3.233 -
   3.234 -        Return a module object or raise an ImportError if a problem occurred in
   3.235 -        the import operation.
   3.236 -
   3.237 -        Note that the 'stuff' parameter is a list and not a single item as in
   3.238 -        ModuleLoader.load_module. This should still work, however, since the
   3.239 -        find_module method produces such a list.
   3.240 -        """
   3.241 -
   3.242 -        # Set up the module.
   3.243 -        # A union of all locations is placed in the module's path.
   3.244 -
   3.245 -        module = self.hooks.add_module(name)
   3.246 -        module.__path__ = [item_filename for (item_archive, item_filename, item_info) in stuff]
   3.247 -
   3.248 -        # Just go into each package and find the class files.
   3.249 -
   3.250 -        for stuff_item in stuff:
   3.251 -
   3.252 -            # Extract the details, delegating loading responsibility to the
   3.253 -            # default loader where appropriate.
   3.254 -            # NOTE: Should we not be using some saved loader remembered upon
   3.255 -            # NOTE: installation?
   3.256 -
   3.257 -            archive, filename, info = stuff_item
   3.258 -            suffix, mode, datatype = info
   3.259 -            if datatype not in (JAVA_PACKAGE, JAVA_ARCHIVE):
   3.260 -                return ihooks.ModuleLoader.load_module(self, name, stuff_item)
   3.261 -
   3.262 -            #print "Loading", archive, filename, info
   3.263 -
   3.264 -            # Prepare a dictionary of globals.
   3.265 -
   3.266 -            global_names = module.__dict__
   3.267 -            global_names["__builtins__"] = __builtins__
   3.268 -
   3.269 -            # Get the real filename.
   3.270 -
   3.271 -            filename = self._get_path_in_archive(filename)
   3.272 -            #print "Real filename", filename
   3.273 -
   3.274 -            # Load the class files.
   3.275 -
   3.276 -            class_files = {}
   3.277 -            for class_filename in self.hooks.matching(filename, os.extsep + "class", archive):
   3.278 -                #print "Loading class", class_filename
   3.279 -                s = self.hooks.read(class_filename, archive)
   3.280 -                class_file = classfile.ClassFile(s)
   3.281 -                class_files[str(class_file.this_class.get_name())] = class_file
   3.282 -
   3.283 -            # Get an index of the class files.
   3.284 -
   3.285 -            class_file_index = class_files.keys()
   3.286 -
   3.287 -            # NOTE: Unnecessary sorting for test purposes.
   3.288 -
   3.289 -            class_file_index.sort()
   3.290 -
   3.291 -            # Now go through the classes arranging them in a safe loading order.
   3.292 -
   3.293 -            position = 0
   3.294 -            while position < len(class_file_index):
   3.295 -                class_name = class_file_index[position]
   3.296 -                super_class_name = str(class_files[class_name].super_class.get_name())
   3.297 -
   3.298 -                # Discover whether the superclass appears later.
   3.299 -
   3.300 -                try:
   3.301 -                    super_class_position = class_file_index.index(super_class_name)
   3.302 -                    if super_class_position > position:
   3.303 -
   3.304 -                        # If the superclass appears later, swap this class and the
   3.305 -                        # superclass, then process the superclass.
   3.306 -
   3.307 -                        class_file_index[position] = super_class_name
   3.308 -                        class_file_index[super_class_position] = class_name
   3.309 -                        continue
   3.310 -
   3.311 -                except ValueError:
   3.312 -                    pass
   3.313 -
   3.314 -                position += 1
   3.315 -
   3.316 -            # Process each class file, producing a genuine Python class.
   3.317 -            # Create the classes, but establish a proper initialisation order.
   3.318 -
   3.319 -            class_file_init_index = []
   3.320 -            class_file_init = {}
   3.321 -
   3.322 -            for class_name in class_file_index:
   3.323 -                #print "* Class", class_name
   3.324 -                class_file = class_files[class_name]
   3.325 -                translator = bytecode.ClassTranslator(class_file)
   3.326 -                cls, external_names = translator.process(global_names)
   3.327 -                module.__dict__[cls.__name__] = cls
   3.328 -
   3.329 -                # Process external names.
   3.330 -
   3.331 -                this_class_name_parts = class_file.this_class.get_python_name().split(".")
   3.332 -                this_class_module, this_class_name = this_class_name_parts[:-1], this_class_name_parts[-1]
   3.333 -
   3.334 -                for external_name in external_names:
   3.335 -                    #print "* Name", external_name
   3.336 -                    external_name_parts = external_name.split(".")
   3.337 -                    external_class_module, external_class_name = external_name_parts[:-1], external_name_parts[-1]
   3.338 -
   3.339 -                    # Names not local to this package need importing.
   3.340 -
   3.341 -                    if len(external_name_parts) > 1 and this_class_module != external_class_module:
   3.342 -
   3.343 -                        external_module_name = ".".join(external_class_module)
   3.344 -                        #print "* Importing", external_module_name
   3.345 -                        obj = __import__(external_module_name, global_names, {}, [])
   3.346 -                        global_names[external_name_parts[0]] = obj
   3.347 -
   3.348 -                    # Names local to this package may affect initialisation order.
   3.349 -
   3.350 -                    elif external_class_name not in class_file_init_index:
   3.351 -                        try:
   3.352 -                            this_class_name_index = class_file_init_index.index(this_class_name)
   3.353 -
   3.354 -                            # Either insert this name before the current class's
   3.355 -                            # name.
   3.356 -
   3.357 -                            #print "* Inserting", external_class_name
   3.358 -                            class_file_init_index.insert(this_class_name_index, external_class_name)
   3.359 -
   3.360 -                        except ValueError:
   3.361 -
   3.362 -                            # Or add this name in anticipation of the current
   3.363 -                            # class's name appearing.
   3.364 -
   3.365 -                            #print "* Including", external_class_name
   3.366 -                            class_file_init_index.append(external_class_name)
   3.367 -
   3.368 -                # Add this class name to the initialisation index.
   3.369 -
   3.370 -                if class_name not in class_file_init_index:
   3.371 -                    class_file_init_index.append(this_class_name)
   3.372 -                class_file_init[this_class_name] = (cls, class_file)
   3.373 -
   3.374 -            # Finally, call __clinit__ methods for all relevant classes.
   3.375 -
   3.376 -            #print "** Initialisation order", class_file_init_index
   3.377 -            for class_name in class_file_init_index:
   3.378 -                cls, class_file = class_file_init[class_name]
   3.379 -                #print "**", cls, class_file
   3.380 -                if hasattr(cls, "__clinit__"):
   3.381 -                    eval(cls.__clinit__.func_code, global_names)
   3.382 -
   3.383 -        return module
   3.384 -
   3.385 -ihooks.ModuleImporter(loader=ClassLoader(hooks=ClassHooks())).install()
   3.386 -
   3.387 -# vim: tabstop=4 expandtab shiftwidth=4
     4.1 --- a/runclass.py	Fri Jan 21 17:04:41 2005 +0100
     4.2 +++ b/runclass.py	Fri Jan 21 17:05:03 2005 +0100
     4.3 @@ -2,7 +2,7 @@
     4.4  
     4.5  "A program to run Java class files."
     4.6  
     4.7 -import classhook
     4.8 +import javaclass.classhook
     4.9  import java.lang
    4.10  
    4.11  def load_class(class_name):
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/setup.py	Fri Jan 21 17:05:03 2005 +0100
     5.3 @@ -0,0 +1,14 @@
     5.4 +#! /usr/bin/env python
     5.5 +
     5.6 +from distutils.core import setup
     5.7 +
     5.8 +setup(
     5.9 +    name         = "ClassFile",
    5.10 +    description  = "A Java class and package importer and utilities.",
    5.11 +    author       = "Paul Boddie",
    5.12 +    author_email = "paul@boddie.org.uk",
    5.13 +    url          = "http://www.boddie.org.uk/python/ClassFile.html",
    5.14 +    version      = "0.1",
    5.15 +    packages     = ["java", "javaclass"],
    5.16 +    scripts      = ["runclass"]
    5.17 +    )