core: Introduce list iteration helpers

The syntax for traversing over lists is somewhat cluttered. It could be
made much better with the use of the 'typeof' keyword, but unfortunately
this is not universally supported by all compilers. We can, however,
improve the situation by introducing some macros for the common cases.
To that end, this commit introduces a number of 'for_each' macros that
iterate over a specific linked list.

Current syntax:

  list_for_each_entry(itransfer, &ctx->flying_transfers, list, struct usbi_transfer)

New syntax:

  for_each_transfer(ctx, itransfer)

Signed-off-by: Chris Dickens <christopher.a.dickens@gmail.com>
diff --git a/libusb/core.c b/libusb/core.c
index 69e2649..89cfec3 100644
--- a/libusb/core.c
+++ b/libusb/core.c
@@ -766,11 +766,12 @@
 	struct libusb_device *ret = NULL;
 
 	usbi_mutex_lock(&ctx->usb_devs_lock);
-	list_for_each_entry(dev, &ctx->usb_devs, list, struct libusb_device)
+	for_each_device(ctx, dev) {
 		if (dev->session_data == session_id) {
 			ret = libusb_ref_device(dev);
 			break;
 		}
+	}
 	usbi_mutex_unlock(&ctx->usb_devs_lock);
 
 	return ret;
@@ -819,7 +820,7 @@
 			usbi_backend.hotplug_poll();
 
 		usbi_mutex_lock(&ctx->usb_devs_lock);
-		list_for_each_entry(dev, &ctx->usb_devs, list, struct libusb_device) {
+		for_each_device(ctx, dev) {
 			discdevs = discovered_devs_append(discdevs, dev);
 
 			if (!discdevs) {
@@ -1416,7 +1417,7 @@
 	usbi_mutex_lock(&ctx->flying_transfers_lock);
 
 	/* safe iteration because transfers may be being deleted */
-	list_for_each_entry_safe(itransfer, tmp, &ctx->flying_transfers, list, struct usbi_transfer) {
+	for_each_transfer_safe(ctx, itransfer, tmp) {
 		struct libusb_transfer *transfer =
 			USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
 
@@ -2359,7 +2360,7 @@
 	usbi_mutex_static_unlock(&active_contexts_lock);
 
 	usbi_mutex_lock(&ctx->usb_devs_lock);
-	list_for_each_entry_safe(dev, next, &ctx->usb_devs, list, struct libusb_device) {
+	for_each_device_safe(ctx, dev, next) {
 		list_del(&dev->list);
 		libusb_unref_device(dev);
 	}
@@ -2439,7 +2440,7 @@
 			libusb_handle_events_timeout(ctx, &tv);
 
 		usbi_mutex_lock(&ctx->usb_devs_lock);
-		list_for_each_entry_safe(dev, next, &ctx->usb_devs, list, struct libusb_device) {
+		for_each_device_safe(ctx, dev, next) {
 			list_del(&dev->list);
 			libusb_unref_device(dev);
 		}
diff --git a/libusb/hotplug.c b/libusb/hotplug.c
index e3e83c3..c02cc56 100644
--- a/libusb/hotplug.c
+++ b/libusb/hotplug.c
@@ -184,7 +184,7 @@
 
 	usbi_mutex_lock(&ctx->hotplug_cbs_lock);
 
-	list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) {
+	for_each_hotplug_cb_safe(ctx, hotplug_cb, next) {
 		if (hotplug_cb->flags & USBI_HOTPLUG_NEEDS_FREE) {
 			/* process deregistration in usbi_hotplug_deregister() */
 			continue;
@@ -331,7 +331,7 @@
 	ctx = usbi_get_context(ctx);
 
 	usbi_mutex_lock(&ctx->hotplug_cbs_lock);
-	list_for_each_entry(hotplug_cb, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) {
+	for_each_hotplug_cb(ctx, hotplug_cb) {
 		if (callback_handle == hotplug_cb->handle) {
 			/* Mark this callback for deregistration */
 			hotplug_cb->flags |= USBI_HOTPLUG_NEEDS_FREE;
@@ -369,7 +369,7 @@
 	ctx = usbi_get_context(ctx);
 
 	usbi_mutex_lock(&ctx->hotplug_cbs_lock);
-	list_for_each_entry(hotplug_cb, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) {
+	for_each_hotplug_cb(ctx, hotplug_cb) {
 		if (callback_handle == hotplug_cb->handle) {
 			user_data = hotplug_cb->user_data;
 		}
@@ -384,7 +384,7 @@
 	struct libusb_hotplug_callback *hotplug_cb, *next;
 
 	usbi_mutex_lock(&ctx->hotplug_cbs_lock);
-	list_for_each_entry_safe(hotplug_cb, next, &ctx->hotplug_cbs, list, struct libusb_hotplug_callback) {
+	for_each_hotplug_cb_safe(ctx, hotplug_cb, next) {
 		if (forced || (hotplug_cb->flags & USBI_HOTPLUG_NEEDS_FREE)) {
 			usbi_dbg("freeing hotplug cb %p with handle %d", hotplug_cb,
 				 hotplug_cb->handle);
diff --git a/libusb/hotplug.h b/libusb/hotplug.h
index 4335fbe..161f7e5 100644
--- a/libusb/hotplug.h
+++ b/libusb/hotplug.h
@@ -90,6 +90,12 @@
 	struct list_head list;
 };
 
+#define for_each_hotplug_cb(ctx, c) \
+	for_each_helper(c, &(ctx)->hotplug_cbs, struct libusb_hotplug_callback)
+
+#define for_each_hotplug_cb_safe(ctx, c, n) \
+	for_each_safe_helper(c, n, &(ctx)->hotplug_cbs, struct libusb_hotplug_callback)
+
 void usbi_hotplug_deregister(struct libusb_context *ctx, int forced);
 void usbi_hotplug_match(struct libusb_context *ctx, struct libusb_device *dev,
 	libusb_hotplug_event event);
diff --git a/libusb/io.c b/libusb/io.c
index b969633..27350fa 100644
--- a/libusb/io.c
+++ b/libusb/io.c
@@ -1172,7 +1172,8 @@
 static void cleanup_removed_pollfds(struct libusb_context *ctx)
 {
 	struct usbi_pollfd *ipollfd, *tmp;
-	list_for_each_entry_safe(ipollfd, tmp, &ctx->removed_ipollfds, list, struct usbi_pollfd) {
+
+	for_each_removed_pollfd_safe(ctx, ipollfd, tmp) {
 		list_del(&ipollfd->list);
 		free(ipollfd);
 	}
@@ -1344,7 +1345,7 @@
 {
 	struct usbi_transfer *itransfer;
 
-	list_for_each_entry(itransfer, &ctx->flying_transfers, list, struct usbi_transfer) {
+	for_each_transfer(ctx, itransfer) {
 		struct timespec *cur_ts = &itransfer->timeout;
 
 		/* if we've reached transfers of infinite timeout, then we have no
@@ -1405,7 +1406,7 @@
 	}
 
 	/* otherwise, find appropriate place in list */
-	list_for_each_entry(cur, &ctx->flying_transfers, list, struct usbi_transfer) {
+	for_each_transfer(ctx, cur) {
 		/* find first timeout that occurs after the transfer in question */
 		struct timespec *cur_ts = &cur->timeout;
 
@@ -2035,7 +2036,7 @@
 
 	/* iterate through flying transfers list, finding all transfers that
 	 * have expired timeouts */
-	list_for_each_entry(itransfer, &ctx->flying_transfers, list, struct usbi_transfer) {
+	for_each_transfer(ctx, itransfer) {
 		struct timespec *cur_ts = &itransfer->timeout;
 
 		/* if we've reached transfers of infinite timeout, we're all done */
@@ -2150,7 +2151,7 @@
 			goto done;
 		}
 
-		list_for_each_entry(ipollfd, &ctx->ipollfds, list, struct usbi_pollfd) {
+		for_each_pollfd(ctx, ipollfd) {
 			struct libusb_pollfd *pollfd = &ipollfd->pollfd;
 			ctx->pollfds[i].fd = pollfd->fd;
 			ctx->pollfds[i].events = pollfd->events;
@@ -2293,7 +2294,7 @@
 	}
 #endif
 
-	list_for_each_entry(ipollfd, &ctx->removed_ipollfds, list, struct usbi_pollfd) {
+	for_each_removed_pollfd(ctx, ipollfd) {
 		usbi_nfds_t n;
 
 		for (n = internal_nfds ; n < nfds ; n++) {
@@ -2611,7 +2612,7 @@
 	}
 
 	/* find next transfer which hasn't already been processed as timed out */
-	list_for_each_entry(itransfer, &ctx->flying_transfers, list, struct usbi_transfer) {
+	for_each_transfer(ctx, itransfer) {
 		if (itransfer->timeout_flags & (USBI_TRANSFER_TIMEOUT_HANDLED | USBI_TRANSFER_OS_HANDLES_TIMEOUT))
 			continue;
 
@@ -2725,11 +2726,12 @@
 
 	usbi_dbg("remove fd %d", fd);
 	usbi_mutex_lock(&ctx->event_data_lock);
-	list_for_each_entry(ipollfd, &ctx->ipollfds, list, struct usbi_pollfd)
+	for_each_pollfd(ctx, ipollfd) {
 		if (ipollfd->pollfd.fd == fd) {
 			found = 1;
 			break;
 		}
+	}
 
 	if (!found) {
 		usbi_dbg("couldn't find fd %d to remove", fd);
@@ -2779,7 +2781,7 @@
 	if (!ret)
 		goto out;
 
-	list_for_each_entry(ipollfd, &ctx->ipollfds, list, struct usbi_pollfd)
+	for_each_pollfd(ctx, ipollfd)
 		ret[i++] = (struct libusb_pollfd *)ipollfd;
 	ret[ctx->pollfds_cnt] = NULL;
 
@@ -2815,6 +2817,7 @@
  */
 void usbi_handle_disconnect(struct libusb_device_handle *dev_handle)
 {
+	struct libusb_context *ctx = HANDLE_CTX(dev_handle);
 	struct usbi_transfer *cur;
 	struct usbi_transfer *to_cancel;
 
@@ -2836,8 +2839,8 @@
 
 	while (1) {
 		to_cancel = NULL;
-		usbi_mutex_lock(&HANDLE_CTX(dev_handle)->flying_transfers_lock);
-		list_for_each_entry(cur, &HANDLE_CTX(dev_handle)->flying_transfers, list, struct usbi_transfer)
+		usbi_mutex_lock(&ctx->flying_transfers_lock);
+		for_each_transfer(ctx, cur) {
 			if (USBI_TRANSFER_TO_LIBUSB_TRANSFER(cur)->dev_handle == dev_handle) {
 				usbi_mutex_lock(&cur->lock);
 				if (cur->state_flags & USBI_TRANSFER_IN_FLIGHT)
@@ -2847,7 +2850,8 @@
 				if (to_cancel)
 					break;
 			}
-		usbi_mutex_unlock(&HANDLE_CTX(dev_handle)->flying_transfers_lock);
+		}
+		usbi_mutex_unlock(&ctx->flying_transfers_lock);
 
 		if (!to_cancel)
 			break;
diff --git a/libusb/libusbi.h b/libusb/libusbi.h
index 3c5add6..1677fda 100644
--- a/libusb/libusbi.h
+++ b/libusb/libusbi.h
@@ -139,6 +139,9 @@
 #define list_first_entry(ptr, type, member) \
 	list_entry((ptr)->next, type, member)
 
+#define list_next_entry(ptr, type, member) \
+	list_entry((ptr)->member.next, type, member)
+
 /* Get each entry from a list
  *  pos - A structure pointer has a "member" element
  *  head - list head
@@ -146,15 +149,24 @@
  *  type - the type of the first parameter
  */
 #define list_for_each_entry(pos, head, member, type)			\
-	for (pos = list_entry((head)->next, type, member);		\
+	for (pos = list_first_entry(head, type, member);		\
 		 &pos->member != (head);				\
-		 pos = list_entry(pos->member.next, type, member))
+		 pos = list_next_entry(pos, type, member))
 
 #define list_for_each_entry_safe(pos, n, head, member, type)		\
-	for (pos = list_entry((head)->next, type, member),		\
-		 n = list_entry(pos->member.next, type, member);	\
+	for (pos = list_first_entry(head, type, member),		\
+		 n = list_next_entry(pos, type, member);		\
 		 &pos->member != (head);				\
-		 pos = n, n = list_entry(n->member.next, type, member))
+		 pos = n, n = list_next_entry(n, type, member))
+
+/* Helper macros to iterate over a list. The structure pointed
+ * to by "pos" must have a list_head member named "list".
+ */
+#define for_each_helper(pos, head, type) \
+	list_for_each_entry(pos, head, list, type)
+
+#define for_each_safe_helper(pos, n, head, type) \
+	list_for_each_entry_safe(pos, n, head, list, type)
 
 #define list_empty(entry) ((entry)->next == (entry))
 
@@ -1244,6 +1256,33 @@
 extern struct list_head active_contexts_list;
 extern usbi_mutex_static_t active_contexts_lock;
 
+#define for_each_context(c) \
+	for_each_helper(c, &active_contexts_list, struct libusb_context)
+
+#define for_each_device(ctx, d) \
+	for_each_helper(d, &(ctx)->usb_devs, struct libusb_device)
+
+#define for_each_device_safe(ctx, d, n) \
+	for_each_safe_helper(d, n, &(ctx)->usb_devs, struct libusb_device)
+
+#define for_each_open_device(ctx, h) \
+	for_each_helper(h, &(ctx)->open_devs, struct libusb_device_handle)
+
+#define for_each_transfer(ctx, t) \
+	for_each_helper(t, &(ctx)->flying_transfers, struct usbi_transfer)
+
+#define for_each_transfer_safe(ctx, t, n) \
+	for_each_safe_helper(t, n, &(ctx)->flying_transfers, struct usbi_transfer)
+
+#define for_each_pollfd(ctx, p) \
+	for_each_helper(p, &(ctx)->ipollfds, struct usbi_pollfd)
+
+#define for_each_removed_pollfd(ctx, p) \
+	for_each_helper(p, &(ctx)->removed_ipollfds, struct usbi_pollfd)
+
+#define for_each_removed_pollfd_safe(ctx, p, n) \
+	for_each_safe_helper(p, n, &(ctx)->removed_ipollfds, struct usbi_pollfd)
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c
index a64d67d..5f5e71b 100644
--- a/libusb/os/darwin_usb.c
+++ b/libusb/os/darwin_usb.c
@@ -337,7 +337,7 @@
     }
 
     /* add this device to each active context's device list */
-    list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
+    for_each_context(ctx) {
       process_new_device (ctx, cached_device, old_session_id);
     }
 
@@ -403,7 +403,7 @@
       continue;
     }
 
-    list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
+    for_each_context(ctx) {
       usbi_dbg ("notifying context %p of device disconnect", ctx);
 
       dev = usbi_get_device_by_session_id(ctx, (unsigned long) session);
diff --git a/libusb/os/haiku_pollfs.cpp b/libusb/os/haiku_pollfs.cpp
index c60b3b5..cb4fda8 100644
--- a/libusb/os/haiku_pollfs.cpp
+++ b/libusb/os/haiku_pollfs.cpp
@@ -97,7 +97,7 @@
 			unsigned long session_id = (unsigned long)&fDevice;
 
 			usbi_mutex_lock(&active_contexts_lock);
-			list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
+			for_each_context(ctx) {
 				struct libusb_device *dev = usbi_get_device_by_session_id(ctx, session_id);
 				if (dev) {
 					usbi_dbg("using previously allocated device with location %lu", session_id);
@@ -172,7 +172,7 @@
 		unsigned long session_id = (unsigned long)&fDevice;
 
 		usbi_mutex_lock(&active_contexts_lock);
-		list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
+		for_each_context(ctx) {
 			dev = usbi_get_device_by_session_id(ctx, session_id);
 			if (dev != NULL) {
 				usbi_disconnect_device(dev);
diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c
index 082d726..1e727ef 100644
--- a/libusb/os/linux_usbfs.c
+++ b/libusb/os/linux_usbfs.c
@@ -991,7 +991,7 @@
 retry:
 	/* find the parent in the context */
 	usbi_mutex_lock(&ctx->usb_devs_lock);
-	list_for_each_entry(it, &ctx->usb_devs, list, struct libusb_device) {
+	for_each_device(ctx, it) {
 		struct linux_device_priv *priv = usbi_get_device_priv(it);
 
 		if (priv->sysfs_dir) {
@@ -1070,7 +1070,7 @@
 	struct libusb_context *ctx;
 
 	usbi_mutex_static_lock(&active_contexts_lock);
-	list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
+	for_each_context(ctx) {
 		linux_enumerate_device(ctx, busnum, devaddr, sys_name);
 	}
 	usbi_mutex_static_unlock(&active_contexts_lock);
@@ -1083,7 +1083,7 @@
 	unsigned long session_id = busnum << 8 | devaddr;
 
 	usbi_mutex_static_lock(&active_contexts_lock);
-	list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
+	for_each_context(ctx) {
 		dev = usbi_get_device_by_session_id(ctx, session_id);
 		if (dev) {
 			usbi_disconnect_device(dev);
@@ -2629,7 +2629,7 @@
 			continue;
 
 		num_ready--;
-		list_for_each_entry(handle, &ctx->open_devs, list, struct libusb_device_handle) {
+		for_each_open_device(ctx, handle) {
 			hpriv = usbi_get_device_handle_priv(handle);
 			if (hpriv->fd == pollfd->fd)
 				break;
diff --git a/libusb/os/windows_common.c b/libusb/os/windows_common.c
index ccf20b2..e2f9116 100644
--- a/libusb/os/windows_common.c
+++ b/libusb/os/windows_common.c
@@ -779,7 +779,7 @@
 
 		transfer_priv = NULL;
 		usbi_mutex_lock(&ctx->flying_transfers_lock);
-		list_for_each_entry(itransfer, &ctx->flying_transfers, list, struct usbi_transfer) {
+		for_each_transfer(ctx, itransfer) {
 			transfer_priv = usbi_get_transfer_priv(itransfer);
 			if (transfer_priv->pollable_fd.fd == fds[i].fd)
 				break;
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index f59eebe..d21e1b9 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 11529
+#define LIBUSB_NANO 11530