From: Peter Johnson Date: Sun, 16 Apr 2006 08:41:41 +0000 (-0000) Subject: * symrec.pxi: Revamp to more correctly generate Symbol objects, support X-Git-Tag: v0.5.0~17^2~13 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2534dd4c5a3b620b50cb5b1e19724c87517824d0;p=yasm * symrec.pxi: Revamp to more correctly generate Symbol objects, support most dictionary functions (but not yet iterator protocol). * yasm.pyx: Add Py_INCREF, Py_DECREF, malloc, free externals. * coretype.pxi: Rename c_print to print_, add some missing yasm_expr_op enum values. svn path=/trunk/yasm/; revision=1491 --- diff --git a/tools/python-yasm/coretype.pxi b/tools/python-yasm/coretype.pxi index e79324db..0c5c5020 100644 --- a/tools/python-yasm/coretype.pxi +++ b/tools/python-yasm/coretype.pxi @@ -39,7 +39,7 @@ cdef extern from "libyasm/coretype.h": cdef struct yasm_assoc_data_callback: void (*destroy) (void *data) - void (*c_print "print") (void *data, FILE *f, int indent_level) + void (*print_ "print") (void *data, FILE *f, int indent_level) cdef struct yasm_bytecode cdef struct yasm_object @@ -79,12 +79,16 @@ cdef extern from "libyasm/coretype.h": YASM_EXPR_OR YASM_EXPR_AND YASM_EXPR_XOR + YASM_EXPR_XNOR YASM_EXPR_NOR YASM_EXPR_SHL YASM_EXPR_SHR YASM_EXPR_LOR YASM_EXPR_LAND YASM_EXPR_LNOT + YASM_EXPR_LXOR + YASM_EXPR_LXNOR + YASM_EXPR_LNOR YASM_EXPR_LT YASM_EXPR_GT YASM_EXPR_EQ diff --git a/tools/python-yasm/symrec.pxi b/tools/python-yasm/symrec.pxi index 4ba76f65..94166865 100644 --- a/tools/python-yasm/symrec.pxi +++ b/tools/python-yasm/symrec.pxi @@ -95,13 +95,61 @@ cdef class Symbol: 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 class __assoc_data_callback: + cdef yasm_assoc_data_callback *cb + def __new__(self, destroy, print_): + self.cb = malloc(sizeof(yasm_assoc_data_callback)) + self.cb.destroy = PyCObject_AsVoidPtr(destroy) + self.cb.print_ = PyCObject_AsVoidPtr(print_) + def __dealloc__(self): + free(self.cb) + +cdef void __python_symrec_cb_destroy(void *data): + Py_DECREF(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): - return Symbol(PyCObject_FromVoidPtr(symrec, NULL)) + cdef void *data + data = yasm_symrec_get_data(symrec, + (<__assoc_data_callback>__python_symrec_cb).cb) + if data != NULL: + return data + symbol = Symbol(PyCObject_FromVoidPtr(symrec, NULL)) + yasm_symrec_add_data(symrec, + (<__assoc_data_callback>__python_symrec_cb).cb, + symbol) + Py_INCREF(symbol) # We're keeping a reference on the C side! + return symbol + +# +# Helpers for dict-like functions in SymbolTable. +# + +cdef int __symtab_keys_helper(yasm_symrec *sym, void *d): + (d).append(yasm_symrec_get_name(sym)) + return 0 + +cdef int __symtab_values_helper(yasm_symrec *sym, void *d): + (d).append(__make_symbol(sym)) + return 0 + +cdef int __symtab_items_helper(yasm_symrec *sym, void *d): + (d).append((yasm_symrec_get_name(sym), __make_symbol(sym))) + return 0 cdef class Bytecode cdef class SymbolTable: cdef yasm_symtab *symtab + def __new__(self): self.symtab = yasm_symtab_create() @@ -112,25 +160,69 @@ cdef class SymbolTable: 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, (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, (precbc).bc, in_table, line)) def define_special(self, name, vis): - return __make_symbol(yasm_symtab_define_special(self.symtab, name, vis)) + return __make_symbol(yasm_symtab_define_special(self.symtab, name, + vis)) def declare(self, name, vis, line): return __make_symbol(yasm_symtab_declare(self.symtab, name, vis, line)) - #def traverse(self, func, *args, **kw): - # return yasm_symtab_traverse(self.symtab, (args, kw), func) - - #def parser_finalize(self, undef_extern, objfmt): - # yasm_symtab_parser_finalize(self.symtab, undef_extern, - # (objfmt).objfmt) # + # 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 keys(self): + l = [] + yasm_symtab_traverse(self.symtab, l, __symtab_keys_helper) + return l + + def values(self): + l = [] + yasm_symtab_traverse(self.symtab, l, __symtab_values_helper) + return l + + def items(self): + l = [] + yasm_symtab_traverse(self.symtab, l, __symtab_items_helper) + 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): pass +# +# def itervalues(self): pass + + # This doesn't follow Python's guideline to make this iterkeys() for + # mappings, but makes more sense in this context, e.g. for sym in symtab. + #def __iter__(self): return self.itervalues() +# def iteritems(self): pass diff --git a/tools/python-yasm/yasm.pyx b/tools/python-yasm/yasm.pyx index e6d91e3d..392befa0 100644 --- a/tools/python-yasm/yasm.pyx +++ b/tools/python-yasm/yasm.pyx @@ -53,6 +53,13 @@ cdef extern from "Python.h": cdef int _PyLong_AsByteArray(object v, unsigned char *bytes, unsigned int n, int little_endian, int is_signed) except -1 + cdef void Py_INCREF(object o) + cdef void Py_DECREF(object o) + +cdef extern from "stdlib.h": + cdef void *malloc(int n) + cdef void free(void *p) + cdef extern from "libyasm/compat-queue.h": pass