blob: d91fe7f578b0d1b328ce57fed1e48850c7978dc7 [file] [log] [blame]
# Python bindings for Yasm: Pyrex input file for symrec.h
#
# Copyright (C) 2006 Michael Urman, Peter Johnson
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
cdef class Symbol:
cdef yasm_symrec *sym
def __new__(self, symrec):
self.sym = NULL
if PyCObject_Check(symrec):
self.sym = <yasm_symrec *>__get_voidp(symrec, Symbol)
else:
raise NotImplementedError
# no deref or destroy necessary
property name:
def __get__(self): return yasm_symrec_get_name(self.sym)
property status:
def __get__(self):
cdef yasm_sym_status status
s = set()
status = yasm_symrec_get_status(self.sym)
if <int>status & <int>SYM_USED: s.add('used')
if <int>status & <int>SYM_DEFINED: s.add('defined')
if <int>status & <int>SYM_VALUED: s.add('valued')
return s
property in_table:
def __get__(self):
return bool(<int>yasm_symrec_get_status(self.sym) &
<int>SYM_NOTINTABLE)
property visibility:
def __get__(self):
cdef yasm_sym_vis vis
s = set()
vis = yasm_symrec_get_visibility(self.sym)
if <int>vis & <int>YASM_SYM_GLOBAL: s.add('global')
if <int>vis & <int>YASM_SYM_COMMON: s.add('common')
if <int>vis & <int>YASM_SYM_EXTERN: s.add('extern')
if <int>vis & <int>YASM_SYM_DLOCAL: s.add('dlocal')
return s
property equ:
def __get__(self):
cdef yasm_expr *e
e = yasm_symrec_get_equ(self.sym)
if not e:
raise AttributeError("not an EQU")
return __make_expression(yasm_expr_copy(e))
property label:
def __get__(self):
cdef yasm_symrec_get_label_bytecodep bc
if yasm_symrec_get_label(self.sym, &bc):
return None #Bytecode(bc)
else:
raise AttributeError("not a label or not defined")
property is_special:
def __get__(self): return bool(yasm_symrec_is_special(self.sym))
property is_curpos:
def __get__(self): return bool(yasm_symrec_is_curpos(self.sym))
def get_data(self): pass # TODO
#return <object>(yasm_symrec_get_data(self.sym, PyYasmAssocData))
def set_data(self, data): pass # TODO
#yasm_symrec_set_data(self.sym, PyYasmAssocData, data)
#
# Use associated data mechanism to keep Symbol reference paired with symrec.
#
cdef void __python_symrec_cb_destroy(void *data):
Py_DECREF(<object>data)
cdef void __python_symrec_cb_print(void *data, FILE *f, int indent_level):
pass
__python_symrec_cb = __assoc_data_callback(
PyCObject_FromVoidPtr(&__python_symrec_cb_destroy, NULL),
PyCObject_FromVoidPtr(&__python_symrec_cb_print, NULL))
cdef object __make_symbol(yasm_symrec *symrec):
cdef void *data
__error_check()
data = yasm_symrec_get_data(symrec,
(<__assoc_data_callback>__python_symrec_cb).cb)
if data != NULL:
return <object>data
symbol = Symbol(__pass_voidp(symrec, Symbol))
yasm_symrec_add_data(symrec,
(<__assoc_data_callback>__python_symrec_cb).cb,
<void *>symbol)
Py_INCREF(symbol) # We're keeping a reference on the C side!
return symbol
cdef class Bytecode
cdef class SymbolTable
cdef class SymbolTableKeyIterator:
cdef yasm_symtab_iter *iter
def __new__(self, symtab):
if not isinstance(symtab, SymbolTable):
raise TypeError
self.iter = yasm_symtab_first((<SymbolTable>symtab).symtab)
def __iter__(self):
return self
def __next__(self):
if self.iter == NULL:
raise StopIteration
rv = yasm_symrec_get_name(yasm_symtab_iter_value(self.iter))
self.iter = yasm_symtab_next(self.iter)
return rv
cdef class SymbolTableValueIterator:
cdef yasm_symtab_iter *iter
def __new__(self, symtab):
if not isinstance(symtab, SymbolTable):
raise TypeError
self.iter = yasm_symtab_first((<SymbolTable>symtab).symtab)
def __iter__(self):
return self
def __next__(self):
if self.iter == NULL:
raise StopIteration
rv = __make_symbol(yasm_symtab_iter_value(self.iter))
self.iter = yasm_symtab_next(self.iter)
return rv
cdef class SymbolTableItemIterator:
cdef yasm_symtab_iter *iter
def __new__(self, symtab):
if not isinstance(symtab, SymbolTable):
raise TypeError
self.iter = yasm_symtab_first((<SymbolTable>symtab).symtab)
def __iter__(self):
return self
def __next__(self):
cdef yasm_symrec *sym
if self.iter == NULL:
raise StopIteration
sym = yasm_symtab_iter_value(self.iter)
rv = (yasm_symrec_get_name(sym), __make_symbol(sym))
self.iter = yasm_symtab_next(self.iter)
return rv
cdef int __parse_vis(vis) except -1:
if not vis or vis == 'local': return YASM_SYM_LOCAL
if vis == 'global': return YASM_SYM_GLOBAL
if vis == 'common': return YASM_SYM_COMMON
if vis == 'extern': return YASM_SYM_EXTERN
if vis == 'dlocal': return YASM_SYM_DLOCAL
msg = "bad visibility value %r" % vis
PyErr_SetString(ValueError, msg)
return -1
cdef class SymbolTable:
cdef yasm_symtab *symtab
def __new__(self):
self.symtab = yasm_symtab_create()
def __dealloc__(self):
if self.symtab != NULL: yasm_symtab_destroy(self.symtab)
def use(self, name, line):
return __make_symbol(yasm_symtab_use(self.symtab, name, line))
def define_equ(self, name, expr, line):
if not isinstance(expr, Expression):
raise TypeError
return __make_symbol(yasm_symtab_define_equ(self.symtab, name,
yasm_expr_copy((<Expression>expr).expr), line))
def define_label(self, name, precbc, in_table, line):
if not isinstance(precbc, Bytecode):
raise TypeError
return __make_symbol(yasm_symtab_define_label(self.symtab, name,
(<Bytecode>precbc).bc, in_table, line))
def define_special(self, name, vis):
return __make_symbol(
yasm_symtab_define_special(self.symtab, name,
<yasm_sym_vis>__parse_vis(vis)))
def declare(self, name, vis, line):
return __make_symbol(
yasm_symtab_declare(self.symtab, name,
<yasm_sym_vis>__parse_vis(vis), line))
#
# Methods to make SymbolTable behave like a dictionary of Symbols.
#
def __getitem__(self, key):
cdef yasm_symrec *symrec
symrec = yasm_symtab_get(self.symtab, key)
if symrec == NULL:
raise KeyError
return __make_symbol(symrec)
def __contains__(self, key):
cdef yasm_symrec *symrec
symrec = yasm_symtab_get(self.symtab, key)
return symrec != NULL
def keys(self):
cdef yasm_symtab_iter *iter
l = []
iter = yasm_symtab_first(self.symtab)
while iter != NULL:
l.append(yasm_symrec_get_name(yasm_symtab_iter_value(iter)))
iter = yasm_symtab_next(iter)
return l
def values(self):
cdef yasm_symtab_iter *iter
l = []
iter = yasm_symtab_first(self.symtab)
while iter != NULL:
l.append(__make_symbol(yasm_symtab_iter_value(iter)))
iter = yasm_symtab_next(iter)
return l
def items(self):
cdef yasm_symtab_iter *iter
cdef yasm_symrec *sym
l = []
iter = yasm_symtab_first(self.symtab)
while iter != NULL:
sym = yasm_symtab_iter_value(iter)
l.append((yasm_symrec_get_name(sym), __make_symbol(sym)))
iter = yasm_symtab_next(iter)
return l
def has_key(self, key):
cdef yasm_symrec *symrec
symrec = yasm_symtab_get(self.symtab, key)
return symrec != NULL
def get(self, key, x):
cdef yasm_symrec *symrec
symrec = yasm_symtab_get(self.symtab, key)
if symrec == NULL:
return x
return __make_symbol(symrec)
def iterkeys(self): return SymbolTableKeyIterator(self)
def itervalues(self): return SymbolTableValueIterator(self)
def iteritems(self): return SymbolTableItemIterator(self)
def __iter__(self): return SymbolTableKeyIterator(self)