'Disassemble a code object, returning a list of \'Token\'.
The main part of this procedure is modelled after
dis.disassemble().'

def disassemble(self, co, classname=None, deob=0):

    rv = []
    customize = {}
    Token = self.Token
    self.code = array('B', co.co_code)
    linestarts = list(dis.findlinestarts(co))
    varnames = list(co.co_varnames)
    if deob:
        linestarts = self.deobfuscate(co, linestarts, varnames)
    code = self.code
    n = len(code)
    self.prev = [0]
    for i in self.op_range(0, n):
        op = code[i]
        self.prev.append(i)
        if (op >= HAVE_ARGUMENT):
            self.prev.append(i)
            self.prev.append(i)
    self.lines = []
    linetuple = namedtuple('linetuple', ['l_no', 'next'])
    j = 0
    linestartoffsets = {a for (a, _) in linestarts}
    (prev_start_byte, prev_line_no) = linestarts[0]
    for (start_byte, line_no) in linestarts[1:]:
        while (j < start_byte):
            self.lines.append(linetuple(prev_line_no, start_byte))
            j += 1
        last_op = code[self.prev[start_byte]]
        (prev_start_byte, prev_line_no) = (start_byte, line_no)
    while (j < n):
        self.lines.append(linetuple(prev_line_no, n))
        j += 1
    if classname:
        classname = (('_' + classname.lstrip('_')) + '__')
        def unmangle(name):
            if (name.startswith(classname) and (name[(-2):] != '__')):
                return name[(len(classname) - 2):]
            return name
        free = [unmangle(name) for name in (co.co_cellvars + co.co_freevars)]
        names = [unmangle(name) for name in co.co_names]
        varnames = [unmangle(name) for name in varnames]
    else:
        free = (co.co_cellvars + co.co_freevars)
        names = co.co_names
    self.load_asserts = set()
    for i in self.op_range(0, n):
        if ((code[i] == PJIT) and (code[(i + 3)] == LOAD_GLOBAL)):
            if (names[(code[(i + 4)] + (256 * code[(i + 5)]))] == 'AssertionError'):
                self.load_asserts.add((i + 3))
    cf = self.find_jump_targets(code)
    last_stmt = self.next_stmt[0]
    i = self.next_stmt[last_stmt]
    replace = {}
    while (i < (n - 1)):
        if (self.lines[last_stmt].next > i):
            if (code[last_stmt] == PRINT_ITEM):
                if (code[i] == PRINT_ITEM):
                    replace[i] = 'PRINT_ITEM_CONT'
                elif (code[i] == PRINT_NEWLINE):
                    replace[i] = 'PRINT_NEWLINE_CONT'
        last_stmt = i
        i = self.next_stmt[i]
    imports = self.all_instr(0, n, (IMPORT_NAME, IMPORT_FROM, IMPORT_STAR))
    if (len(imports) > 1):
        last_import = imports[0]
        for i in imports[1:]:
            if (self.lines[last_import].next > i):
                if (code[last_import] == IMPORT_NAME == code[i]):
                    replace[i] = 'IMPORT_NAME_CONT'
            last_import = i
    extended_arg = 0
    for offset in self.op_range(0, n):
        if (offset in cf):
            k = 0
            for j in cf[offset]:
                rv.append(Token('COME_FROM', None, repr(j), offset=('%s_%d' % (offset, k))))
                k += 1
        op = code[offset]
        opname = dis.opname[op]
        oparg = None
        pattr = None
        if (op >= HAVE_ARGUMENT):
            oparg = ((code[(offset + 1)] + (code[(offset + 2)] * 256)) + extended_arg)
            extended_arg = 0
            if (op == dis.EXTENDED_ARG):
                extended_arg = (oparg * 65536L)
                continue
            if (op in dis.hasconst):
                const = co.co_consts[oparg]
                if (type(const) == types.CodeType):
                    oparg = const
                    if (const.co_name == '<lambda>'):
                        assert (opname == 'LOAD_CONST')
                        opname = 'LOAD_LAMBDA'
                    elif (const.co_name == '<genexpr>'):
                        opname = 'LOAD_GENEXPR'
                    elif (const.co_name == '<dictcomp>'):
                        opname = 'LOAD_DICTCOMP'
                    elif (const.co_name == '<setcomp>'):
                        opname = 'LOAD_SETCOMP'
                    pattr = (('<code_object    ' + const.co_name) + '>')
                else:
                    pattr = const
            elif (op in dis.hasname):
                pattr = names[oparg]
            elif (op in dis.hasjrel):
                pattr = repr(((offset + 3) + oparg))
            elif (op in dis.hasjabs):
                pattr = repr(oparg)
            elif (op in dis.haslocal):
                pattr = varnames[oparg]
            elif (op in dis.hascompare):
                pattr = dis.cmp_op[oparg]
            elif (op in dis.hasfree):
                pattr = free[oparg]
        if (op in (BUILD_LIST, BUILD_TUPLE, BUILD_SET, BUILD_SLICE, UNPACK_SEQUENCE, MAKE_FUNCTION, CALL_FUNCTION, MAKE_CLOSURE, CALL_FUNCTION_VAR, CALL_FUNCTION_KW, CALL_FUNCTION_VAR_KW, DUP_TOPX, RAISE_VARARGS)):
            if ((op == BUILD_TUPLE) and (code[self.prev[offset]] == LOAD_CLOSURE)):
                continue
            else:
                opname = ('%s_%d' % (opname, oparg))
                if (op != BUILD_SLICE):
                    customize[opname] = oparg
        elif (op == JA):
            target = self.get_target(offset)
            if (target < offset):
                if ((offset in self.stmts) and (code[(offset + 3)] not in (END_FINALLY, POP_BLOCK)) and (offset not in self.not_continue)):
                    opname = 'CONTINUE'
                else:
                    opname = 'JUMP_BACK'
        elif (op == LOAD_GLOBAL):
            if (offset in self.load_asserts):
                opname = 'LOAD_ASSERT'
        elif (op == RETURN_VALUE):
            if (offset in self.return_end_ifs):
                opname = 'RETURN_END_IF'
        if (offset not in replace):
            rv.append(Token(opname, oparg, pattr, offset, linestart=(offset in linestartoffsets)))
        else:
            rv.append(Token(replace[offset], oparg, pattr, offset, linestart=(offset in linestartoffsets)))
    if self.showasm:
        out = self.out
        for t in rv:
            print >>out, t
        print >>out
    return (rv, customize)
