| # 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) |
| |