diff --git a/README.md b/README.md
index 6f717a0..bb98225 100644
--- a/README.md
+++ b/README.md
@@ -148,7 +148,15 @@ Wrapped headers and replaced functions are:
OSX10.10 |
- sys/queue.h |
+ sys/queue.h |
+ Adds SLIST_HEAD_INITIALIZER macro |
+ OSX10.4 |
+
+
+ Adds SLIST_REMOVE_AFTER macro |
+ OSX10.6 |
+
+
Adds STAILQ_FOREACH macro |
OSX10.4 |
diff --git a/include/MacportsLegacySupport.h b/include/MacportsLegacySupport.h
index 2bf8664..1e766af 100644
--- a/include/MacportsLegacySupport.h
+++ b/include/MacportsLegacySupport.h
@@ -254,8 +254,14 @@
/* PTHREAD_RWLOCK_INITIALIZER is not defined until 10.5 */
/* The addition uses an #ifndef, so no feature flag is necessary */
-/* STAILQ_FOREACH is not defined until 10.5 */
-/* The addition uses an #ifndef, so no feature flag is necessary */
+/* Macros missing from some earlier versions of sys/queue.h */
+/* All additions use #ifndef, so no feature flags are necessary. */
+
+/* Missing until 10.5 */
+/* SLIST_HEAD_INITIALIZER, STAILQ_FOREACH */
+
+/* Missing until 10.7 */
+/* SLIST_REMOVE_AFTER */
/* c++11 PPC 10.[45] and Intel 10.[4-6], GNU g++ 4.6 through 8. */
#if (__MPLS_TARGET_OSVER < 1070 \
diff --git a/include/sys/queue.h b/include/sys/queue.h
index 53157dd..be4501f 100644
--- a/include/sys/queue.h
+++ b/include/sys/queue.h
@@ -20,7 +20,28 @@
/* Include the primary system sys/queue.h */
#include_next
-/* STAILQ_FOREACH is not defined on Tiger */
+/* SLIST functions missing from earlier SDK versions */
+
+/* Missing until 10.5 */
+
+#ifndef SLIST_HEAD_INITIALIZER
+#define SLIST_HEAD_INITIALIZER(head) \
+ { NULL }
+#endif
+
+/* Missing until 10.7 */
+
+#ifndef SLIST_REMOVE_AFTER
+#define SLIST_REMOVE_AFTER(elm, field) do { \
+ SLIST_NEXT(elm, field) = \
+ SLIST_NEXT(SLIST_NEXT(elm, field), field); \
+} while (0)
+#endif
+
+/* STAILQ functions missing from earlier SDK versions */
+
+/* Missing until 10.5 */
+
#ifndef STAILQ_FOREACH
#define STAILQ_FOREACH(var, head, field) \
for((var) = STAILQ_FIRST((head)); \
diff --git a/test/test_fstatat64.c b/test/test_fstatat64.c
index b7c96d1..b0b5558 100644
--- a/test/test_fstatat64.c
+++ b/test/test_fstatat64.c
@@ -24,8 +24,6 @@
#include
#include
-#define FEEDBACK 1
-
/*
* For newer macOS releases - where this syscall is available - it's declared
* in header 'sys/sysproto.h', within 'Kernel.framework'.
@@ -33,6 +31,7 @@
* To avoid depending on that, declare it ourselves. (Remember that C/C++
* allows redundant function declarations, as long as the signatures match.)
*/
+struct stat64; /* Avoid warning on 10.4 (where this doesn't work, anyway) */
int fstatat64(int dirfd, const char *pathname, struct stat64 *buf, int flags);
int main (int argc, char **argv) {
diff --git a/test/test_queues.c b/test/test_queues.c
new file mode 100644
index 0000000..a0ae0af
--- /dev/null
+++ b/test/test_queues.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2024 Frederick H. G. Wright II
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This provides tests for some functions from sys/queue.h., currently:
+ * STAILQ_FOREACH
+ * SLIST_REMOVE_AFTER
+ */
+
+#include
+#include /* For NULL */
+#include
+
+
+/* Tests for SLIST_REMOVE_AFTER */
+
+#ifndef SLIST_REMOVE_AFTER
+#error SLIST_REMOVE_AFTER is undefined
+#endif
+
+#ifndef SLIST_HEAD_INITIALIZER
+#error SLIST_HEAD_INITIALIZER is undefined
+#endif
+
+typedef struct slist_entry_s {
+ int value;
+ SLIST_ENTRY(slist_entry_s) next;
+} slist_entry_t;
+
+typedef SLIST_HEAD(slist_head_s, slist_entry_s) slist_head_t;
+
+static slist_head_t slist_head = SLIST_HEAD_INITIALIZER(slist_head);
+
+/* Some sample entries */
+static slist_entry_t slist_entries[] = {
+ {.value = 1},
+ {.value = 2},
+ {.value = 3},
+};
+#define SLIST_NUM (sizeof(slist_entries) / sizeof(slist_entries[0]))
+
+static void
+test_slist(void)
+{
+ slist_entry_t *ep, *tp;
+
+ /* Fill the queue with the sample entries (reversed) */
+ for (ep = &slist_entries[0]; ep < &slist_entries[SLIST_NUM]; ++ep) {
+ SLIST_INSERT_HEAD(&slist_head, ep, next);
+ }
+
+ /* Get and check the first entry */
+ ep = &slist_entries[SLIST_NUM - 1];
+ tp = SLIST_FIRST(&slist_head);
+ assert(tp->value == ep->value);
+
+ /* Remove the following entry, then check the one after */
+ SLIST_REMOVE_AFTER(tp, next);
+ ep = &slist_entries[SLIST_NUM - 1 - 2];
+ tp = SLIST_NEXT(tp, next);
+ assert(tp->value == ep->value);
+}
+
+
+/* Tests for STAILQ_FOREACH */
+
+#ifndef STAILQ_FOREACH
+#error STAILQ_FOREACH is undefined
+#endif
+
+typedef struct stailq_entry_s {
+ int value;
+ STAILQ_ENTRY(stailq_entry_s) next;
+} stailq_entry_t;
+
+typedef STAILQ_HEAD(stailq_head_s, stailq_entry_s) stailq_head_t;
+
+static stailq_head_t stailq_head = STAILQ_HEAD_INITIALIZER(stailq_head);
+
+/* Some sample entries */
+static stailq_entry_t stailq_entries[] = {
+ {.value = 1},
+ {.value = 2},
+ {.value = 3},
+};
+#define STAILQ_NUM (sizeof(stailq_entries) / sizeof(stailq_entries[0]))
+
+static void
+test_stailq(void)
+{
+ stailq_entry_t *ep, *tp;
+
+ /* Fill the queue with the sample entries */
+ for (ep = &stailq_entries[0]; ep < &stailq_entries[STAILQ_NUM]; ++ep) {
+ STAILQ_INSERT_TAIL(&stailq_head, ep, next);
+ }
+
+ /* See if STAILQ_FOREACH returns expected sequence */
+ ep = &stailq_entries[0];
+ STAILQ_FOREACH(tp, &stailq_head, next) {
+ assert(tp->value == ep++->value);
+ }
+
+ /* Check expected end */
+ assert(ep == &stailq_entries[STAILQ_NUM]);
+}
+
+
+int
+main(int argc, char *argv[])
+{
+ (void) argc; (void) argv;
+
+ test_slist();
+ test_stailq();
+
+ return 0;
+}