? ihash.diff
Index: ChangeLog
===================================================================
RCS file: /cvsroot/hurd/hurd/libihash/ChangeLog,v
retrieving revision 1.9
diff -u -p -r1.9 ChangeLog
--- ChangeLog	21 Apr 2004 21:34:16 -0000	1.9
+++ ChangeLog	1 Sep 2004 10:54:30 -0000
@@ -1,3 +1,12 @@
+2004-09-01  Neal H. Walfield  <neal@cs.uml.edu>
+
+	* ihash.h (_HURD_IHASH_ITERATE_INTERNAL): New macro.  Abstract
+	HURD_IHASH_ITERATE machinery.
+	(HURD_IHASH_ITERATE): Use it.
+	(HURD_IHAHS_ITERATE_KEYS): New macro.
+	* ihash.c (hurd_ihash_destroy): Declare VALUE to comply with new
+	semantics.
+
 2004-04-21  Marcus Brinkmann  <marcus@gnu.org>
 
 	* ihash.h (HURD_IHASH_ITERATE): Don't use increment operator in
Index: ihash.c
===================================================================
RCS file: /cvsroot/hurd/hurd/libihash/ihash.c,v
retrieving revision 1.9
diff -u -p -r1.9 ihash.c
--- ihash.c	2 Apr 2004 17:01:03 -0000	1.9
+++ ihash.c	1 Sep 2004 10:54:31 -0000
@@ -186,6 +186,7 @@ hurd_ihash_destroy (hurd_ihash_t ht)
     {
       hurd_ihash_cleanup_t cleanup = ht->cleanup;
       void *cleanup_data = ht->cleanup_data;
+      hurd_ihash_value_t value;
 
       HURD_IHASH_ITERATE (ht, value)
 	(*cleanup) (value, cleanup_data);
Index: ihash.h
===================================================================
RCS file: /cvsroot/hurd/hurd/libihash/ihash.h,v
retrieving revision 1.8
diff -u -p -r1.8 ihash.h
--- ihash.h	21 Apr 2004 21:34:16 -0000	1.8
+++ ihash.h	1 Sep 2004 10:54:31 -0000
@@ -169,6 +169,8 @@ hurd_ihash_value_t hurd_ihash_find (hurd
    with a block, for example like this:
 
      error_t err;
+     hurd_ihash_value_t value;
+
      HURD_IHASH_ITERATE (ht, value)
        {
          err = foo (value);
@@ -185,38 +187,30 @@ hurd_ihash_value_t hurd_ihash_find (hurd
 
    The block will be run for every element in the hash table HT.  The
    value of the current element is available in the variable VALUE
-   (which is declared for you and local to the block).  */
+   (which is declared for you and local to the block).
+
+   HURD_IHASH_ITERATE_KEYS works in a similar fashion but returns the
+   key and its corresponding value.  */
 
 /* The implementation of this macro is peculiar.  We want the macro to
    execute a block following its invocation, so we can only prepend
-   code.  This excludes creating an outer block.  However, we must
-   define two variables: The hash value variable VALUE, and the loop
-   variable.
-
-   We can define variables inside the for-loop initializer (C99), but
-   we can only use one basic type to do that.  We can not use two
-   for-loops, because we want a break statement inside the iterator
-   block to terminate the operation.  So we must have both variables
-   of the same basic type, but we can make one (or both) of them a
-   pointer type.
-
-   The pointer to the value can be used as the loop variable.  This is
-   also the first element of the hash item, so we can cast the pointer
-   freely between these two types.  The pointer is only dereferenced
-   after the loop condition is checked (but of course the value the
-   pointer pointed to must not have an influence on the condition
-   result, so the comma operator is used to make sure this
-   subexpression is always true).  */
-#define HURD_IHASH_ITERATE(ht, val)					\
-  for (hurd_ihash_value_t val,						\
-         *_hurd_ihash_valuep = (ht)->size ? &(ht)->items[0].value : 0;	\
+   code.  This excludes creating an outer block.  */
+#define _HURD_IHASH_ITERATE_INTERNAL(ht, val, func)			\
+  for (_hurd_ihash_item_t _hurd_ihash_itemp                             \
+         = (ht)->size ? &(ht)->items[0] : 0;                            \
        (ht)->size							\
-         && ((_hurd_ihash_item_t) _hurd_ihash_valuep) - &(ht)->items[0]	\
-            < (ht)->size						\
-         && (val = *_hurd_ihash_valuep, 1);				\
-       _hurd_ihash_valuep = (hurd_ihash_value_t *)			\
-	 (((_hurd_ihash_item_t) _hurd_ihash_valuep) + 1))		\
-    if (val != _HURD_IHASH_EMPTY && val != _HURD_IHASH_DELETED)
+         && _hurd_ihash_itemp - &(ht)->items[0] < (ht)->size		\
+         && ((func), 1);						\
+       _hurd_ihash_itemp ++)                                            \
+    if ((val) != _HURD_IHASH_EMPTY && (val) != _HURD_IHASH_DELETED)
+
+#define HURD_IHASH_ITERATE(ht, v)					\
+  _HURD_IHASH_ITERATE_INTERNAL((ht), (v), ((v) = _hurd_ihash_itemp->value))
+
+#define HURD_IHASH_ITERATE_KEYS(ht, k, v)				\
+  _HURD_IHASH_ITERATE_INTERNAL((ht), (v),				\
+    (((v) = _hurd_ihash_itemp->value),                                  \
+     ((k) = _hurd_ihash_itemp->key)))
 
 /* Remove the entry with the key KEY from the hash table HT.  If such
    an entry was found and removed, 1 is returned, otherwise 0.  */
