[Subversion] / PEAK / src / peak / util / _Code.pyx  

View of /PEAK/src/peak/util/_Code.pyx

Parent Directory | Revision Log
Revision: 1076 - (download)
Sat May 3 13:21:20 2003 UTC (20 years, 11 months ago) by pje
File size: 4697 byte(s)
Normalized whitespace.
cdef extern from "Python.h":
    void* PyMem_Malloc(int n) except NULL
    void* PyMem_Realloc(void *p, int n) except NULL
    void  PyMem_Free(void *p)
    int PyObject_AsReadBuffer(object obj, void **buffer, int *buffer_len) except -1

cdef extern from "opcode.h":

    unsigned char HAS_ARG(unsigned char op)

    enum:
        EXTENDED_ARG

cdef class codeIndex

cdef class opIter:

    cdef codeIndex cidx
    cdef int pos

    def __init__(self, codeIndex cidx, int pos):
        self.cidx = cidx
        self.pos  = pos

    def __iter__(self):
        return self

    def __next__(self):
        cdef int pos
        cdef codeIndex c

        pos = self.pos

        if self.pos == -1:
            raise StopIteration

        c = self.cidx   # XXX Pyrex croaks on self.cidx.opcodeChain[]
        self.pos = c.opcodeChain[pos]
        return pos


cdef class codeIndex:

    """Useful indexes over a code object

        opcodeLocations[op] -- list of instruction numbers with 'op' as opcode

        opcode[i] -- the i'th instruction's opcode

        operand[i] -- the i'th instruction's operand (or None)

        offset[i]  -- location of the i'th instruction

        byteLine[b] -- source line number that generated byte 'b'
    """


    cdef object code
    cdef int *opcodeHeads, *operands, *offsets, *byteLines, *opcodeChain
    cdef unsigned char *opcodes
    cdef int length, codelen


    def __new__(self, codeObject):
        self.opcodeHeads=NULL
        self.opcodeChain=NULL
        self.operands=NULL
        self.offsets=NULL
        self.byteLines=NULL
        self.opcodes=NULL

    def __dealloc__(self):
        if self.opcodeHeads: PyMem_Free(self.opcodeHeads)
        if self.opcodeChain: PyMem_Free(self.opcodeChain)
        if self.operands:    PyMem_Free(self.operands)
        if self.offsets:     PyMem_Free(self.offsets)
        if self.byteLines:   PyMem_Free(self.byteLines)
        if self.opcodes:     PyMem_Free(self.opcodes)




    def __init__(self, codeObject):

        self.code = codeObject
        cdef int l, s, arg, end, start, p
        cdef unsigned char *ca
        cdef unsigned char op
        PyObject_AsReadBuffer(codeObject.co_code, <void **>(&ca), &l)

        s = l * sizeof(int)
        self.opcodeHeads     = <int *>PyMem_Malloc(256 * sizeof(int))
        self.opcodeChain     = <int *>PyMem_Malloc(s)
        self.operands        = <int *>PyMem_Malloc(s)
        self.offsets         = <int *>PyMem_Malloc(s)
        self.byteLines       = <int *>PyMem_Malloc(s)
        self.opcodes         = <unsigned char *>PyMem_Malloc(l)

        p = 0
        end = 0
        start = end

        while end < l:
            op = ca[start]
            if HAS_ARG(op):
                arg = ca[start+1] | ca[start+2]<<8
                if op==EXTENDED_ARG:
                    op = ca[start+3]
                    end = start+6
                    arg = arg << 16
                    arg = arg + (ca[start+4] | ca[start+5]<<8)
                else:
                    end = start+3
            else:
                arg = 0
                end = start+1

            self.opcodes[p] = op
            self.operands[p] = arg
            self.offsets[p] = start
            p = p+1
            start = end

        self.length = p
        self.codelen = l

        PyObject_AsReadBuffer(codeObject.co_lnotab, <void **>(&ca), &end)

        p = 0
        arg = codeObject.co_firstlineno
        start = 0

        while p<end:

            for s from 0 <= s < ca[p]:
                self.byteLines[start+s] = arg

            start = start + ca[p]
            arg = arg + ca[p+1]
            p = p + 2

        while start<l:
           self.byteLines[start]=arg
           start = start + 1

        for s from 0 <= s < 256:
            self.opcodeHeads[s] = -1

        p = self.length

        while p:
            p = p - 1
            op = self.opcodes[p]
            self.opcodeChain[p] = self.opcodeHeads[op]
            self.opcodeHeads[op] = p









    def opcodeLocations(self, int op):

        if op<0 or op>255:
            raise IndexError, op

        return opIter(self, self.opcodeHeads[op])


    def operand(self, int p):

        if p<0 or p>=self.length:
            raise IndexError, p

        return self.operands[p]


    def opcode(self, int p):

        if p<0 or p>=self.length:
            raise IndexError, p

        return self.opcodes[p]


    def offset(self, int p):

        if p<0 or p>=self.length:
            raise IndexError, p

        return self.offsets[p]


    def byteLine(self, int p):

        if p<0 or p>=self.codelen:
            raise IndexError, p

        return self.byteLines[p]




cvs-admin@eby-sarna.com

Powered by ViewCVS 1.0-dev

ViewCVS and CVS Help