Home | History | Annotate | Download | only in python-yasm
      1 # Python bindings for Yasm: Pyrex input file for symrec.h
      2 #
      3 #  Copyright (C) 2006  Michael Urman, Peter Johnson
      4 #
      5 # Redistribution and use in source and binary forms, with or without
      6 # modification, are permitted provided that the following conditions
      7 # are met:
      8 # 1. Redistributions of source code must retain the above copyright
      9 #    notice, this list of conditions and the following disclaimer.
     10 # 2. Redistributions in binary form must reproduce the above copyright
     11 #    notice, this list of conditions and the following disclaimer in the
     12 #    documentation and/or other materials provided with the distribution.
     13 #
     14 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
     15 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     16 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     17 # ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
     18 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     19 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     20 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     21 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     22 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     23 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     24 # POSSIBILITY OF SUCH DAMAGE.
     25 
     26 cdef class Symbol:
     27     cdef yasm_symrec *sym
     28 
     29     def __cinit__(self, symrec):
     30         self.sym = NULL
     31         if PyCObject_Check(symrec):
     32             self.sym = <yasm_symrec *>__get_voidp(symrec, Symbol)
     33         else:
     34             raise NotImplementedError
     35 
     36     # no deref or destroy necessary
     37 
     38     property name:
     39         def __get__(self): return yasm_symrec_get_name(self.sym)
     40 
     41     property status:
     42         def __get__(self):
     43             cdef yasm_sym_status status
     44             s = set()
     45             status = yasm_symrec_get_status(self.sym)
     46             if <int>status & <int>YASM_SYM_USED: s.add('used')
     47             if <int>status & <int>YASM_SYM_DEFINED: s.add('defined')
     48             if <int>status & <int>YASM_SYM_VALUED: s.add('valued')
     49             return s
     50 
     51     property in_table:
     52         def __get__(self):
     53             return bool(<int>yasm_symrec_get_status(self.sym) &
     54                         <int>YASM_SYM_NOTINTABLE)
     55 
     56     property visibility:
     57         def __get__(self):
     58             cdef yasm_sym_vis vis
     59             s = set()
     60             vis = yasm_symrec_get_visibility(self.sym)
     61             if <int>vis & <int>YASM_SYM_GLOBAL: s.add('global')
     62             if <int>vis & <int>YASM_SYM_COMMON: s.add('common')
     63             if <int>vis & <int>YASM_SYM_EXTERN: s.add('extern')
     64             if <int>vis & <int>YASM_SYM_DLOCAL: s.add('dlocal')
     65             return s
     66 
     67     property equ:
     68         def __get__(self):
     69             cdef yasm_expr *e
     70             e = yasm_symrec_get_equ(self.sym)
     71             if not e:
     72                 raise AttributeError("not an EQU")
     73             return __make_expression(yasm_expr_copy(e))
     74 
     75     property label:
     76         def __get__(self):
     77             cdef yasm_symrec_get_label_bytecodep bc
     78             if yasm_symrec_get_label(self.sym, &bc):
     79                 return None #Bytecode(bc)
     80             else:
     81                 raise AttributeError("not a label or not defined")
     82 
     83     property is_special:
     84         def __get__(self): return bool(yasm_symrec_is_special(self.sym))
     85 
     86     property is_curpos:
     87         def __get__(self): return bool(yasm_symrec_is_curpos(self.sym))
     88 
     89     def get_data(self): pass # TODO
     90         #return <object>(yasm_symrec_get_data(self.sym, PyYasmAssocData))
     91 
     92     def set_data(self, data): pass # TODO
     93         #yasm_symrec_set_data(self.sym, PyYasmAssocData, data)
     94 
     95 #
     96 # Use associated data mechanism to keep Symbol reference paired with symrec.
     97 #
     98 
     99 cdef void __python_symrec_cb_destroy(void *data):
    100     Py_DECREF(<object>data)
    101 cdef void __python_symrec_cb_print(void *data, FILE *f, int indent_level):
    102     pass
    103 __python_symrec_cb = __assoc_data_callback(
    104         PyCObject_FromVoidPtr(&__python_symrec_cb_destroy, NULL),
    105         PyCObject_FromVoidPtr(&__python_symrec_cb_print, NULL))
    106 
    107 cdef object __make_symbol(yasm_symrec *symrec):
    108     cdef void *data
    109     __error_check()
    110     data = yasm_symrec_get_data(symrec,
    111                                 (<__assoc_data_callback>__python_symrec_cb).cb)
    112     if data != NULL:
    113         return <object>data
    114     symbol = Symbol(__pass_voidp(symrec, Symbol))
    115     yasm_symrec_add_data(symrec,
    116                          (<__assoc_data_callback>__python_symrec_cb).cb,
    117                          <void *>symbol)
    118     Py_INCREF(symbol)       # We're keeping a reference on the C side!
    119     return symbol
    120 
    121 cdef class Bytecode
    122 cdef class SymbolTable
    123 
    124 cdef class SymbolTableKeyIterator:
    125     cdef yasm_symtab_iter *iter
    126 
    127     def __cinit__(self, symtab):
    128         if not isinstance(symtab, SymbolTable):
    129             raise TypeError
    130         self.iter = yasm_symtab_first((<SymbolTable>symtab).symtab)
    131 
    132     def __iter__(self):
    133         return self
    134 
    135     def __next__(self):
    136         if self.iter == NULL:
    137             raise StopIteration
    138         rv = yasm_symrec_get_name(yasm_symtab_iter_value(self.iter))
    139         self.iter = yasm_symtab_next(self.iter)
    140         return rv
    141 
    142 cdef class SymbolTableValueIterator:
    143     cdef yasm_symtab_iter *iter
    144 
    145     def __cinit__(self, symtab):
    146         if not isinstance(symtab, SymbolTable):
    147             raise TypeError
    148         self.iter = yasm_symtab_first((<SymbolTable>symtab).symtab)
    149 
    150     def __iter__(self):
    151         return self
    152 
    153     def __next__(self):
    154         if self.iter == NULL:
    155             raise StopIteration
    156         rv = __make_symbol(yasm_symtab_iter_value(self.iter))
    157         self.iter = yasm_symtab_next(self.iter)
    158         return rv
    159 
    160 cdef class SymbolTableItemIterator:
    161     cdef yasm_symtab_iter *iter
    162 
    163     def __cinit__(self, symtab):
    164         if not isinstance(symtab, SymbolTable):
    165             raise TypeError
    166         self.iter = yasm_symtab_first((<SymbolTable>symtab).symtab)
    167 
    168     def __iter__(self):
    169         return self
    170 
    171     def __next__(self):
    172         cdef yasm_symrec *sym
    173         if self.iter == NULL:
    174             raise StopIteration
    175         sym = yasm_symtab_iter_value(self.iter)
    176         rv = (yasm_symrec_get_name(sym), __make_symbol(sym))
    177         self.iter = yasm_symtab_next(self.iter)
    178         return rv
    179 
    180 cdef int __parse_vis(vis) except -1:
    181     if not vis or vis == 'local': return YASM_SYM_LOCAL
    182     if vis == 'global': return YASM_SYM_GLOBAL
    183     if vis == 'common': return YASM_SYM_COMMON
    184     if vis == 'extern': return YASM_SYM_EXTERN
    185     if vis == 'dlocal': return YASM_SYM_DLOCAL
    186     msg = "bad visibility value %r" % vis
    187     PyErr_SetString(ValueError, msg)
    188     return -1
    189 
    190 cdef class SymbolTable:
    191     cdef yasm_symtab *symtab
    192 
    193     def __cinit__(self):
    194         self.symtab = yasm_symtab_create()
    195 
    196     def __dealloc__(self):
    197         if self.symtab != NULL: yasm_symtab_destroy(self.symtab)
    198 
    199     def use(self, name, line):
    200         return __make_symbol(yasm_symtab_use(self.symtab, name, line))
    201 
    202     def define_equ(self, name, expr, line):
    203         if not isinstance(expr, Expression):
    204             raise TypeError
    205         return __make_symbol(yasm_symtab_define_equ(self.symtab, name,
    206                 yasm_expr_copy((<Expression>expr).expr), line))
    207 
    208     def define_label(self, name, precbc, in_table, line):
    209         if not isinstance(precbc, Bytecode):
    210             raise TypeError
    211         return __make_symbol(yasm_symtab_define_label(self.symtab, name,
    212                 (<Bytecode>precbc).bc, in_table, line))
    213 
    214     def define_special(self, name, vis):
    215         return __make_symbol(
    216             yasm_symtab_define_special(self.symtab, name,
    217                                        <yasm_sym_vis>__parse_vis(vis)))
    218 
    219     def declare(self, name, vis, line):
    220         return __make_symbol(
    221             yasm_symtab_declare(self.symtab, name,
    222                                 <yasm_sym_vis>__parse_vis(vis), line))
    223 
    224     #
    225     # Methods to make SymbolTable behave like a dictionary of Symbols.
    226     #
    227 
    228     def __getitem__(self, key):
    229         cdef yasm_symrec *symrec
    230         symrec = yasm_symtab_get(self.symtab, key)
    231         if symrec == NULL:
    232             raise KeyError
    233         return __make_symbol(symrec)
    234 
    235     def __contains__(self, key):
    236         cdef yasm_symrec *symrec
    237         symrec = yasm_symtab_get(self.symtab, key)
    238         return symrec != NULL
    239 
    240     def keys(self):
    241         cdef yasm_symtab_iter *iter
    242         l = []
    243         iter = yasm_symtab_first(self.symtab)
    244         while iter != NULL:
    245             l.append(yasm_symrec_get_name(yasm_symtab_iter_value(iter)))
    246             iter = yasm_symtab_next(iter)
    247         return l
    248 
    249     def values(self):
    250         cdef yasm_symtab_iter *iter
    251         l = []
    252         iter = yasm_symtab_first(self.symtab)
    253         while iter != NULL:
    254             l.append(__make_symbol(yasm_symtab_iter_value(iter)))
    255             iter = yasm_symtab_next(iter)
    256         return l
    257 
    258     def items(self):
    259         cdef yasm_symtab_iter *iter
    260         cdef yasm_symrec *sym
    261         l = []
    262         iter = yasm_symtab_first(self.symtab)
    263         while iter != NULL:
    264             sym = yasm_symtab_iter_value(iter)
    265             l.append((yasm_symrec_get_name(sym), __make_symbol(sym)))
    266             iter = yasm_symtab_next(iter)
    267         return l
    268 
    269     def has_key(self, key):
    270         cdef yasm_symrec *symrec
    271         symrec = yasm_symtab_get(self.symtab, key)
    272         return symrec != NULL
    273 
    274     def get(self, key, x):
    275         cdef yasm_symrec *symrec
    276         symrec = yasm_symtab_get(self.symtab, key)
    277         if symrec == NULL:
    278             return x
    279         return __make_symbol(symrec)
    280 
    281     def iterkeys(self): return SymbolTableKeyIterator(self)
    282     def itervalues(self): return SymbolTableValueIterator(self)
    283     def iteritems(self): return SymbolTableItemIterator(self)
    284     def __iter__(self): return SymbolTableKeyIterator(self)
    285 
    286