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; +}