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 26cdef 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 99cdef void __python_symrec_cb_destroy(void *data): 100 Py_DECREF(<object>data) 101cdef 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 107cdef 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 121cdef class Bytecode 122cdef class SymbolTable 123 124cdef 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 142cdef 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 160cdef 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 180cdef 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 190cdef 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