]> granicus.if.org Git - yasm/commitdiff
* symrec.pxi: Implement iterators.
authorPeter Johnson <peter@tortall.net>
Sun, 16 Apr 2006 22:46:22 +0000 (22:46 -0000)
committerPeter Johnson <peter@tortall.net>
Sun, 16 Apr 2006 22:46:22 +0000 (22:46 -0000)
* 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
libyasm/hamt.h
libyasm/symrec.c
libyasm/symrec.h
tools/python-yasm/symrec.pxi

index 318c086fac3efdaee8a704f4ac62b9a61c335f24..320dbf71dfc72975587804849f47dd4feaedb3c5 100644 (file)
 #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,
index 78d380e705283e0499ef997a7b7d813e2bf66d30..865844caa47e65dbde24fc3df5f51390db03a475 100644 (file)
@@ -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
index 6d2f3feb987e82d796bf23ca4170767aa9ea4a08..3165d00d2a8abdf72672e88fa255453d5e6d7855 100644 (file)
@@ -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)
 {
index da5c8ee55352ba91e8623fe538529aaa9368dfc1..9fe5d9f7864bdf7a44b89640f426687f2b523899 100644 (file)
@@ -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
index 5f8e0a935d491b93dd9144107c4f914318735b2f..e26c178d3d6afa53cf7ca8ef7d76e0beaded9fbb 100644 (file)
@@ -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 class Bytecode
+cdef class SymbolTable
 
-cdef int __symtab_keys_helper(yasm_symrec *sym, void *d):
-    (<object>d).append(yasm_symrec_get_name(sym))
-    return 0
+cdef class SymbolTableKeyIterator:
+    cdef yasm_symtab_iter *iter
 
-cdef int __symtab_values_helper(yasm_symrec *sym, void *d):
-    (<object>d).append(__make_symbol(sym))
-    return 0
+    def __new__(self, symtab):
+        if not isinstance(symtab, SymbolTable):
+            raise TypeError
+        self.iter = yasm_symtab_first((<SymbolTable>symtab).symtab)
 
-cdef int __symtab_items_helper(yasm_symrec *sym, void *d):
-    (<object>d).append((yasm_symrec_get_name(sym), __make_symbol(sym)))
-    return 0
+    def __iter__(self):
+        return self
 
-cdef class Bytecode
+    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 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, <void *>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, <void *>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, <void *>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)