From ba76728dedf67d37a6ccdb6c66e863c545c43d2a Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Sun, 16 Apr 2006 22:46:22 +0000 Subject: [PATCH] * symrec.pxi: Implement iterators. * symrec.h (yasm_symtab_first, yasm_symtab_next, yasm_symtab_iter_value): Supporting functions. * symrec.c (yasm_symtab_first, yasm_symtab_next, yasm_symtab_iter_value): Implement by passing through to... * hamt.h (HAMT_first, HAMT_next, HAMTEntry_get_data): New. * hamt.c (HAMT_first, HAMT_next, HAMTEntry_get_data): Implement. svn path=/trunk/yasm/; revision=1495 --- libyasm/hamt.c | 22 ++++++- libyasm/hamt.h | 20 +++++++ libyasm/symrec.c | 18 ++++++ libyasm/symrec.h | 22 +++++++ tools/python-yasm/symrec.pxi | 112 +++++++++++++++++++++++++++-------- 5 files changed, 166 insertions(+), 28 deletions(-) diff --git a/libyasm/hamt.c b/libyasm/hamt.c index 318c086f..320dbf71 100644 --- a/libyasm/hamt.c +++ b/libyasm/hamt.c @@ -37,11 +37,11 @@ #include "hamt.h" #include "_stdint.h" /* for uintptr_t */ -typedef struct HAMTEntry { +struct HAMTEntry { STAILQ_ENTRY(HAMTEntry) next; /* next hash table entry */ /*@dependent@*/ const char *str; /* string being hashed */ /*@owned@*/ void *data; /* data pointer being stored */ -} HAMTEntry; +}; typedef struct HAMTNode { unsigned long BitMapKey; /* 32 bits, bitmap or hash key */ @@ -160,6 +160,24 @@ HAMT_traverse(HAMT *hamt, void *d, return 0; } +const HAMTEntry * +HAMT_first(const HAMT *hamt) +{ + return STAILQ_FIRST(&hamt->entries); +} + +const HAMTEntry * +HAMT_next(const HAMTEntry *prev) +{ + return STAILQ_NEXT(prev, next); +} + +void * +HAMTEntry_get_data(const HAMTEntry *entry) +{ + return entry->data; +} + /*@-temptrans -kepttrans -mustfree@*/ void * HAMT_insert(HAMT *hamt, const char *str, void *data, int *replace, diff --git a/libyasm/hamt.h b/libyasm/hamt.h index 78d380e7..865844ca 100644 --- a/libyasm/hamt.h +++ b/libyasm/hamt.h @@ -36,6 +36,8 @@ /** Hash array mapped trie data structure (opaque type). */ typedef struct HAMT HAMT; +/** Hash array mapped trie entry (opaque type). */ +typedef struct HAMTEntry HAMTEntry; /** Create new, empty, HAMT. error_func() is called when an internal error is * encountered--it should NOT return to the calling function. @@ -91,4 +93,22 @@ int HAMT_traverse(HAMT *hamt, /*@null@*/ void *d, int (*func) (/*@dependent@*/ /*@null@*/ void *node, /*@null@*/ void *d)); +/** Get the first entry in a HAMT. + * \param hamt Hash array mapped trie + * \return First entry in HAMT, or NULL if HAMT is empty. + */ +const HAMTEntry *HAMT_first(const HAMT *hamt); + +/** Get the next entry in a HAMT. + * \param prev Previous entry in HAMT + * \return Next entry in HAMT, or NULL if no more entries. + */ +/*@null@*/ const HAMTEntry *HAMT_next(const HAMTEntry *prev); + +/** Get the corresponding data for a HAMT entry. + * \param entry HAMT entry (as returned by HAMT_first() and HAMT_next()) + * \return Corresponding data item. + */ +void *HAMTEntry_get_data(const HAMTEntry *entry); + #endif diff --git a/libyasm/symrec.c b/libyasm/symrec.c index 6d2f3feb..3165d00d 100644 --- a/libyasm/symrec.c +++ b/libyasm/symrec.c @@ -175,6 +175,24 @@ yasm_symtab_traverse(yasm_symtab *symtab, void *d, return HAMT_traverse(symtab->sym_table, d, (int (*) (void *, void *))func); } +const yasm_symtab_iter * +yasm_symtab_first(const yasm_symtab *symtab) +{ + return (const yasm_symtab_iter *)HAMT_first(symtab->sym_table); +} + +/*@null@*/ const yasm_symtab_iter * +yasm_symtab_next(const yasm_symtab_iter *prev) +{ + return (const yasm_symtab_iter *)HAMT_next((const HAMTEntry *)prev); +} + +yasm_symrec * +yasm_symtab_iter_value(const yasm_symtab_iter *cur) +{ + return (yasm_symrec *)HAMTEntry_get_data((const HAMTEntry *)cur); +} + yasm_symrec * yasm_symtab_use(yasm_symtab *symtab, const char *name, unsigned long line) { diff --git a/libyasm/symrec.h b/libyasm/symrec.h index da5c8ee5..9fe5d9f7 100644 --- a/libyasm/symrec.h +++ b/libyasm/symrec.h @@ -154,6 +154,28 @@ int /*@alt void@*/ yasm_symtab_traverse (yasm_symtab *symtab, /*@null@*/ void *d, yasm_symtab_traverse_callback func); +/** Symbol table iterator (opaque type). */ +typedef struct yasm_symtab_iter yasm_symtab_iter; + +/** Get an iterator pointing to the first symbol in the symbol table. + * \param symtab symbol table + * \return Iterator for the symbol table. + */ +const yasm_symtab_iter *yasm_symtab_first(const yasm_symtab *symtab); + +/** Move a symbol table iterator to the next symbol in the symbol table. + * \param prev Previous iterator value + * \return Next iterator value, or NULL if no more symbols in the table. + */ +/*@null@*/ const yasm_symtab_iter *yasm_symtab_next + (const yasm_symtab_iter *prev); + +/** Get the symbol corresponding to the current symbol table iterator value. + * \param cur iterator value + * \return Corresponding symbol. + */ +yasm_symrec *yasm_symtab_iter_value(const yasm_symtab_iter *cur); + /** Finalize symbol table after parsing stage. Checks for symbols that are * used but never defined or declared #YASM_SYM_EXTERN or #YASM_SYM_COMMON. * \param symtab symbol table diff --git a/tools/python-yasm/symrec.pxi b/tools/python-yasm/symrec.pxi index 5f8e0a93..e26c178d 100644 --- a/tools/python-yasm/symrec.pxi +++ b/tools/python-yasm/symrec.pxi @@ -43,9 +43,14 @@ cdef extern from "libyasm/symrec.h": unsigned long line) ctypedef int (*yasm_symtab_traverse_callback)(yasm_symrec *sym, void *d) - cdef int yasm_symtab_traverse(yasm_symtab *symtab, void *d, yasm_symtab_traverse_callback func) + + ctypedef struct yasm_symtab_iter + cdef yasm_symtab_iter *yasm_symtab_first(yasm_symtab *symtab) + cdef yasm_symtab_iter *yasm_symtab_next(yasm_symtab_iter *prev) + cdef yasm_symrec *yasm_symtab_iter_value(yasm_symtab_iter *cur) + cdef void yasm_symtab_parser_finalize(yasm_symtab *symtab, int undef_extern, yasm_objfmt *objfmt) cdef void yasm_symtab_print(yasm_symtab *symtab, FILE *f, int indent_level) @@ -129,23 +134,64 @@ cdef object __make_symbol(yasm_symrec *symrec): 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 class SymbolTableKeyIterator: + cdef yasm_symtab_iter *iter + + def __new__(self, symtab): + if not isinstance(symtab, SymbolTable): + raise TypeError + self.iter = yasm_symtab_first((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((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((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 class SymbolTable: cdef yasm_symtab *symtab @@ -195,18 +241,34 @@ cdef class SymbolTable: return symrec != NULL def keys(self): + cdef yasm_symtab_iter *iter l = [] - yasm_symtab_traverse(self.symtab, l, __symtab_keys_helper) + 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 = [] - yasm_symtab_traverse(self.symtab, l, __symtab_values_helper) + iter = yasm_symtab_first(self.symtab) + while iter != NULL: + l.append(__make_symbol(yasm_symtab_iter_value(iter))) + l.append(yasm_symrec_get_name(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 = [] - yasm_symtab_traverse(self.symtab, l, __symtab_items_helper) + 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))) + l.append(yasm_symrec_get_name(yasm_symtab_iter_value(iter))) + iter = yasm_symtab_next(iter) return l def has_key(self, key): @@ -221,13 +283,11 @@ cdef class SymbolTable: return x return __make_symbol(symrec) -# def iterkeys(self): pass -# -# def itervalues(self): pass + def iterkeys(self): return SymbolTableKeyIterator(self) + def itervalues(self): return SymbolTableValueIterator(self) + def iteritems(self): return SymbolTableItemIterator(self) # 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 + def __iter__(self): return SymbolTableValueIterator(self)