diff options
Diffstat (limited to 'ccan/typesafe_cb')
| l--------- | ccan/typesafe_cb/LICENSE | 1 | ||||
| -rw-r--r-- | ccan/typesafe_cb/_info | 151 | ||||
| -rw-r--r-- | ccan/typesafe_cb/test/compile_fail-cast_if_type-promotable.c | 24 | ||||
| -rw-r--r-- | ccan/typesafe_cb/test/compile_fail-typesafe_cb-int.c | 28 | ||||
| -rw-r--r-- | ccan/typesafe_cb/test/compile_fail-typesafe_cb.c | 37 | ||||
| -rw-r--r-- | ccan/typesafe_cb/test/compile_fail-typesafe_cb_cast-multi.c | 44 | ||||
| -rw-r--r-- | ccan/typesafe_cb/test/compile_fail-typesafe_cb_cast.c | 26 | ||||
| -rw-r--r-- | ccan/typesafe_cb/test/compile_fail-typesafe_cb_postargs.c | 31 | ||||
| -rw-r--r-- | ccan/typesafe_cb/test/compile_fail-typesafe_cb_preargs.c | 32 | ||||
| -rw-r--r-- | ccan/typesafe_cb/test/compile_ok-typesafe_cb-NULL.c | 19 | ||||
| -rw-r--r-- | ccan/typesafe_cb/test/compile_ok-typesafe_cb-undefined.c | 60 | ||||
| -rw-r--r-- | ccan/typesafe_cb/test/compile_ok-typesafe_cb-vars.c | 63 | ||||
| -rw-r--r-- | ccan/typesafe_cb/test/compile_ok-typesafe_cb_cast.c | 42 | ||||
| -rw-r--r-- | ccan/typesafe_cb/test/run.c | 109 | ||||
| -rw-r--r-- | ccan/typesafe_cb/typesafe_cb.h | 134 |
15 files changed, 0 insertions, 801 deletions
diff --git a/ccan/typesafe_cb/LICENSE b/ccan/typesafe_cb/LICENSE deleted file mode 120000 index b7951da..0000000 --- a/ccan/typesafe_cb/LICENSE +++ /dev/null @@ -1 +0,0 @@ -../../licenses/CC0
\ No newline at end of file diff --git a/ccan/typesafe_cb/_info b/ccan/typesafe_cb/_info deleted file mode 100644 index b4f379d..0000000 --- a/ccan/typesafe_cb/_info +++ /dev/null @@ -1,151 +0,0 @@ -#include "config.h" -#include <stdio.h> -#include <string.h> - -/** - * typesafe_cb - macros for safe callbacks. - * - * The basis of the typesafe_cb header is typesafe_cb_cast(): a - * conditional cast macro. If an expression exactly matches a given - * type, it is cast to the target type, otherwise it is left alone. - * - * This allows us to create functions which take a small number of - * specific types, rather than being forced to use a void *. In - * particular, it is useful for creating typesafe callbacks as the - * helpers typesafe_cb(), typesafe_cb_preargs() and - * typesafe_cb_postargs() demonstrate. - * - * The standard way of passing arguments to callback functions in C is - * to use a void pointer, which the callback then casts back to the - * expected type. This unfortunately subverts the type checking the - * compiler would perform if it were a direct call. Here's an example: - * - * static void my_callback(void *_obj) - * { - * struct obj *obj = _obj; - * ... - * } - * ... - * register_callback(my_callback, &my_obj); - * - * If we wanted to use the natural type for my_callback (ie. "void - * my_callback(struct obj *obj)"), we could make register_callback() - * take a void * as its first argument, but this would subvert all - * type checking. We really want register_callback() to accept only - * the exactly correct function type to match the argument, or a - * function which takes a void *. - * - * This is where typesafe_cb() comes in: it uses typesafe_cb_cast() to - * cast the callback function if it matches the argument type: - * - * void _register_callback(void (*cb)(void *arg), void *arg); - * #define register_callback(cb, arg) \ - * _register_callback(typesafe_cb(void, void *, (cb), (arg)), \ - * (arg)) - * - * On compilers which don't support the extensions required - * typesafe_cb_cast() and friend become an unconditional cast, so your - * code will compile but you won't get type checking. - * - * Example: - * #include <ccan/typesafe_cb/typesafe_cb.h> - * #include <stdlib.h> - * #include <stdio.h> - * - * // Generic callback infrastructure. - * struct callback { - * struct callback *next; - * int value; - * int (*callback)(int value, void *arg); - * void *arg; - * }; - * static struct callback *callbacks; - * - * static void _register_callback(int value, int (*cb)(int, void *), - * void *arg) - * { - * struct callback *new = malloc(sizeof(*new)); - * new->next = callbacks; - * new->value = value; - * new->callback = cb; - * new->arg = arg; - * callbacks = new; - * } - * #define register_callback(value, cb, arg) \ - * _register_callback(value, \ - * typesafe_cb_preargs(int, void *, \ - * (cb), (arg), int),\ - * (arg)) - * - * static struct callback *find_callback(int value) - * { - * struct callback *i; - * - * for (i = callbacks; i; i = i->next) - * if (i->value == value) - * return i; - * return NULL; - * } - * - * // Define several silly callbacks. Note they don't use void *! - * #define DEF_CALLBACK(name, op) \ - * static int name(int val, int *arg) \ - * { \ - * printf("%s", #op); \ - * return val op *arg; \ - * } - * DEF_CALLBACK(multiply, *); - * DEF_CALLBACK(add, +); - * DEF_CALLBACK(divide, /); - * DEF_CALLBACK(sub, -); - * DEF_CALLBACK(or, |); - * DEF_CALLBACK(and, &); - * DEF_CALLBACK(xor, ^); - * DEF_CALLBACK(assign, =); - * - * // Silly game to find the longest chain of values. - * int main(int argc, char *argv[]) - * { - * int i, run = 1, num = argc > 1 ? atoi(argv[1]) : 0; - * - * for (i = 1; i < 1024;) { - * // Since run is an int, compiler checks "add" does too. - * register_callback(i++, add, &run); - * register_callback(i++, divide, &run); - * register_callback(i++, sub, &run); - * register_callback(i++, multiply, &run); - * register_callback(i++, or, &run); - * register_callback(i++, and, &run); - * register_callback(i++, xor, &run); - * register_callback(i++, assign, &run); - * } - * - * printf("%i ", num); - * while (run < 56) { - * struct callback *cb = find_callback(num % i); - * if (!cb) { - * printf("-> STOP\n"); - * return 1; - * } - * num = cb->callback(num, cb->arg); - * printf("->%i ", num); - * run++; - * } - * printf("-> Winner!\n"); - * return 0; - * } - * - * License: CC0 (Public domain) - * Author: Rusty Russell <rusty@rustcorp.com.au> - */ -int main(int argc, char *argv[]) -{ - if (argc != 2) - return 1; - - if (strcmp(argv[1], "depends") == 0) { - return 0; - } - - return 1; -} diff --git a/ccan/typesafe_cb/test/compile_fail-cast_if_type-promotable.c b/ccan/typesafe_cb/test/compile_fail-cast_if_type-promotable.c deleted file mode 100644 index 746faca..0000000 --- a/ccan/typesafe_cb/test/compile_fail-cast_if_type-promotable.c +++ /dev/null @@ -1,24 +0,0 @@ -#include <ccan/typesafe_cb/typesafe_cb.h> -#include <stdbool.h> - -static void _set_some_value(void *val) -{ - (void)val; -} - -#define set_some_value(expr) \ - _set_some_value(typesafe_cb_cast(void *, long, (expr))) - -int main(void) -{ -#ifdef FAIL - bool x = 0; -#if !HAVE_TYPEOF||!HAVE_BUILTIN_CHOOSE_EXPR||!HAVE_BUILTIN_TYPES_COMPATIBLE_P -#error "Unfortunately we don't fail if typesafe_cb_cast is a noop." -#endif -#else - long x = 0; -#endif - set_some_value(x); - return 0; -} diff --git a/ccan/typesafe_cb/test/compile_fail-typesafe_cb-int.c b/ccan/typesafe_cb/test/compile_fail-typesafe_cb-int.c deleted file mode 100644 index c9d47c5..0000000 --- a/ccan/typesafe_cb/test/compile_fail-typesafe_cb-int.c +++ /dev/null @@ -1,28 +0,0 @@ -#include <ccan/typesafe_cb/typesafe_cb.h> -#include <stdlib.h> - -void _callback(void (*fn)(void *arg), void *arg); -void _callback(void (*fn)(void *arg), void *arg) -{ - fn(arg); -} - -/* Callback is set up to warn if arg isn't a pointer (since it won't - * pass cleanly to _callback's second arg. */ -#define callback(fn, arg) \ - _callback(typesafe_cb(void, (fn), (arg)), (arg)) - -void my_callback(int something); -void my_callback(int something) -{ - (void)something; -} - -int main(void) -{ -#ifdef FAIL - /* This fails due to arg, not due to cast. */ - callback(my_callback, 100); -#endif - return 0; -} diff --git a/ccan/typesafe_cb/test/compile_fail-typesafe_cb.c b/ccan/typesafe_cb/test/compile_fail-typesafe_cb.c deleted file mode 100644 index 5717f97..0000000 --- a/ccan/typesafe_cb/test/compile_fail-typesafe_cb.c +++ /dev/null @@ -1,37 +0,0 @@ -#include <ccan/typesafe_cb/typesafe_cb.h> -#include <stdlib.h> - -static void _register_callback(void (*cb)(void *arg), void *arg) -{ - (void)cb; - (void)arg; -} - -#define register_callback(cb, arg) \ - _register_callback(typesafe_cb(void, void *, (cb), (arg)), (arg)) - -static void my_callback(char *p) -{ - (void)p; -} - -int main(void) -{ - char str[] = "hello world"; -#ifdef FAIL - int *p; -#if !HAVE_TYPEOF||!HAVE_BUILTIN_CHOOSE_EXPR||!HAVE_BUILTIN_TYPES_COMPATIBLE_P -#error "Unfortunately we don't fail if typesafe_cb_cast is a noop." -#endif -#else - char *p; -#endif - p = NULL; - - /* This should work always. */ - register_callback(my_callback, str); - - /* This will fail with FAIL defined */ - register_callback(my_callback, p); - return 0; -} diff --git a/ccan/typesafe_cb/test/compile_fail-typesafe_cb_cast-multi.c b/ccan/typesafe_cb/test/compile_fail-typesafe_cb_cast-multi.c deleted file mode 100644 index d85886c..0000000 --- a/ccan/typesafe_cb/test/compile_fail-typesafe_cb_cast-multi.c +++ /dev/null @@ -1,44 +0,0 @@ -#include <ccan/typesafe_cb/typesafe_cb.h> -#include <stdlib.h> - -struct foo { - int x; -}; - -struct bar { - int x; -}; - -struct baz { - int x; -}; - -struct any { - int x; -}; - -struct other { - int x; -}; - -static void take_any(struct any *any) -{ - (void)any; -} - -int main(void) -{ -#ifdef FAIL - struct other -#if !HAVE_TYPEOF||!HAVE_BUILTIN_CHOOSE_EXPR||!HAVE_BUILTIN_TYPES_COMPATIBLE_P -#error "Unfortunately we don't fail if typesafe_cb_cast is a noop." -#endif -#else - struct foo -#endif - *arg = NULL; - take_any(typesafe_cb_cast3(struct any *, - struct foo *, struct bar *, struct baz *, - arg)); - return 0; -} diff --git a/ccan/typesafe_cb/test/compile_fail-typesafe_cb_cast.c b/ccan/typesafe_cb/test/compile_fail-typesafe_cb_cast.c deleted file mode 100644 index 7fa596c..0000000 --- a/ccan/typesafe_cb/test/compile_fail-typesafe_cb_cast.c +++ /dev/null @@ -1,26 +0,0 @@ -#include <ccan/typesafe_cb/typesafe_cb.h> - -void _set_some_value(void *val); - -void _set_some_value(void *val) -{ - (void)val; -} - -#define set_some_value(expr) \ - _set_some_value(typesafe_cb_cast(void *, unsigned long, (expr))) - -int main(void) -{ -#ifdef FAIL - int x = 0; - set_some_value(x); -#if !HAVE_TYPEOF||!HAVE_BUILTIN_CHOOSE_EXPR||!HAVE_BUILTIN_TYPES_COMPATIBLE_P -#error "Unfortunately we don't fail if typesafe_cb_cast is a noop." -#endif -#else - void *p = 0; - set_some_value(p); -#endif - return 0; -} diff --git a/ccan/typesafe_cb/test/compile_fail-typesafe_cb_postargs.c b/ccan/typesafe_cb/test/compile_fail-typesafe_cb_postargs.c deleted file mode 100644 index 2100368..0000000 --- a/ccan/typesafe_cb/test/compile_fail-typesafe_cb_postargs.c +++ /dev/null @@ -1,31 +0,0 @@ -#include <ccan/typesafe_cb/typesafe_cb.h> -#include <stdlib.h> - -static void _register_callback(void (*cb)(void *arg, int x), void *arg) -{ - (void)cb; - (void)arg; -} -#define register_callback(cb, arg) \ - _register_callback(typesafe_cb_postargs(void, void *, (cb), (arg), int), (arg)) - -static void my_callback(char *p, int x) -{ - (void)p; - (void)x; -} - -int main(void) -{ -#ifdef FAIL - int *p; -#if !HAVE_TYPEOF||!HAVE_BUILTIN_CHOOSE_EXPR||!HAVE_BUILTIN_TYPES_COMPATIBLE_P -#error "Unfortunately we don't fail if typesafe_cb_cast is a noop." -#endif -#else - char *p; -#endif - p = NULL; - register_callback(my_callback, p); - return 0; -} diff --git a/ccan/typesafe_cb/test/compile_fail-typesafe_cb_preargs.c b/ccan/typesafe_cb/test/compile_fail-typesafe_cb_preargs.c deleted file mode 100644 index d359a77..0000000 --- a/ccan/typesafe_cb/test/compile_fail-typesafe_cb_preargs.c +++ /dev/null @@ -1,32 +0,0 @@ -#include <ccan/typesafe_cb/typesafe_cb.h> -#include <stdlib.h> - -static void _register_callback(void (*cb)(int x, void *arg), void *arg) -{ - (void)cb; - (void)arg; -} - -#define register_callback(cb, arg) \ - _register_callback(typesafe_cb_preargs(void, void *, (cb), (arg), int), (arg)) - -static void my_callback(int x, char *p) -{ - (void)p; - (void)x; -} - -int main(void) -{ -#ifdef FAIL - int *p; -#if !HAVE_TYPEOF||!HAVE_BUILTIN_CHOOSE_EXPR||!HAVE_BUILTIN_TYPES_COMPATIBLE_P -#error "Unfortunately we don't fail if typesafe_cb_cast is a noop." -#endif -#else - char *p; -#endif - p = NULL; - register_callback(my_callback, p); - return 0; -} diff --git a/ccan/typesafe_cb/test/compile_ok-typesafe_cb-NULL.c b/ccan/typesafe_cb/test/compile_ok-typesafe_cb-NULL.c deleted file mode 100644 index 738ec96..0000000 --- a/ccan/typesafe_cb/test/compile_ok-typesafe_cb-NULL.c +++ /dev/null @@ -1,19 +0,0 @@ -#include <ccan/typesafe_cb/typesafe_cb.h> -#include <stdlib.h> - -/* NULL args for callback function should be OK for normal and _def. */ - -static void _register_callback(void (*cb)(const void *arg), const void *arg) -{ - (void)cb; - (void)arg; -} - -#define register_callback(cb, arg) \ - _register_callback(typesafe_cb(void, const void *, (cb), (arg)), (arg)) - -int main(void) -{ - register_callback(NULL, "hello world"); - return 0; -} diff --git a/ccan/typesafe_cb/test/compile_ok-typesafe_cb-undefined.c b/ccan/typesafe_cb/test/compile_ok-typesafe_cb-undefined.c deleted file mode 100644 index bb71042..0000000 --- a/ccan/typesafe_cb/test/compile_ok-typesafe_cb-undefined.c +++ /dev/null @@ -1,60 +0,0 @@ -#include <ccan/typesafe_cb/typesafe_cb.h> -#include <stdlib.h> - -/* const args in callbacks should be OK. */ - -static void _register_callback(void (*cb)(void *arg), void *arg) -{ - (void)cb; - (void)arg; -} - -#define register_callback(cb, arg) \ - _register_callback(typesafe_cb(void, void *, (cb), (arg)), (arg)) - -static void _register_callback_pre(void (*cb)(int x, void *arg), void *arg) -{ - (void)cb; - (void)arg; -} - -#define register_callback_pre(cb, arg) \ - _register_callback_pre(typesafe_cb_preargs(void, void *, (cb), (arg), int), (arg)) - -static void _register_callback_post(void (*cb)(void *arg, int x), void *arg) -{ - (void)cb; - (void)arg; -} - -#define register_callback_post(cb, arg) \ - _register_callback_post(typesafe_cb_postargs(void, void *, (cb), (arg), int), (arg)) - -struct undefined; - -static void my_callback(struct undefined *undef) -{ - (void)undef; -} - -static void my_callback_pre(int x, struct undefined *undef) -{ - (void)x; - (void)undef; -} - -static void my_callback_post(struct undefined *undef, int x) -{ - (void)undef; - (void)x; -} - -int main(void) -{ - struct undefined *handle = NULL; - - register_callback(my_callback, handle); - register_callback_pre(my_callback_pre, handle); - register_callback_post(my_callback_post, handle); - return 0; -} diff --git a/ccan/typesafe_cb/test/compile_ok-typesafe_cb-vars.c b/ccan/typesafe_cb/test/compile_ok-typesafe_cb-vars.c deleted file mode 100644 index 1cb1057..0000000 --- a/ccan/typesafe_cb/test/compile_ok-typesafe_cb-vars.c +++ /dev/null @@ -1,63 +0,0 @@ -#include <ccan/typesafe_cb/typesafe_cb.h> -#include <stdlib.h> - -/* const args in callbacks should be OK. */ - -static void _register_callback(void (*cb)(void *arg), void *arg) -{ - (void)cb; - (void)arg; -} - -#define register_callback(cb, arg) \ - _register_callback(typesafe_cb(void, void *, (cb), (arg)), (arg)) - -static void _register_callback_pre(void (*cb)(int x, void *arg), void *arg) -{ - (void)cb; - (void)arg; -} - -#define register_callback_pre(cb, arg) \ - _register_callback_pre(typesafe_cb_preargs(void, void *, (cb), (arg), int), (arg)) - -static void _register_callback_post(void (*cb)(void *arg, int x), void *arg) -{ - (void)cb; - (void)arg; -} - -#define register_callback_post(cb, arg) \ - _register_callback_post(typesafe_cb_postargs(void, void *, (cb), (arg), int), (arg)) - -struct undefined; - -static void my_callback(struct undefined *undef) -{ - (void)undef; -} - -static void my_callback_pre(int x, struct undefined *undef) -{ - (void)x; - (void)undef; -} - -static void my_callback_post(struct undefined *undef, int x) -{ - (void)x; - (void)undef; -} - -int main(void) -{ - struct undefined *handle = NULL; - void (*cb)(struct undefined *undef) = my_callback; - void (*pre)(int x, struct undefined *undef) = my_callback_pre; - void (*post)(struct undefined *undef, int x) = my_callback_post; - - register_callback(cb, handle); - register_callback_pre(pre, handle); - register_callback_post(post, handle); - return 0; -} diff --git a/ccan/typesafe_cb/test/compile_ok-typesafe_cb_cast.c b/ccan/typesafe_cb/test/compile_ok-typesafe_cb_cast.c deleted file mode 100644 index bd7b7d6..0000000 --- a/ccan/typesafe_cb/test/compile_ok-typesafe_cb_cast.c +++ /dev/null @@ -1,42 +0,0 @@ -#include <ccan/typesafe_cb/typesafe_cb.h> -#include <stdlib.h> - -struct foo { - int x; -}; - -struct bar { - int x; -}; - -struct baz { - int x; -}; - -struct any { - int x; -}; - -static void take_any(struct any *any) -{ - (void)any; -} - -int main(void) -{ - /* Otherwise we get unused warnings for these. */ - struct foo *foo = NULL; - struct bar *bar = NULL; - struct baz *baz = NULL; - - take_any(typesafe_cb_cast3(struct any *, - struct foo *, struct bar *, struct baz *, - foo)); - take_any(typesafe_cb_cast3(struct any *, - struct foo *, struct bar *, struct baz *, - bar)); - take_any(typesafe_cb_cast3(struct any *, - struct foo *, struct bar *, struct baz *, - baz)); - return 0; -} diff --git a/ccan/typesafe_cb/test/run.c b/ccan/typesafe_cb/test/run.c deleted file mode 100644 index bebea40..0000000 --- a/ccan/typesafe_cb/test/run.c +++ /dev/null @@ -1,109 +0,0 @@ -#include <ccan/typesafe_cb/typesafe_cb.h> -#include <string.h> -#include <stdint.h> -#include <ccan/tap/tap.h> - -static char dummy = 0; - -/* The example usage. */ -static void _set_some_value(void *val) -{ - ok1(val == &dummy); -} - -#define set_some_value(expr) \ - _set_some_value(typesafe_cb_cast(void *, unsigned long, (expr))) - -static void _callback_onearg(void (*fn)(void *arg), void *arg) -{ - fn(arg); -} - -static void _callback_preargs(void (*fn)(int a, int b, void *arg), void *arg) -{ - fn(1, 2, arg); -} - -static void _callback_postargs(void (*fn)(void *arg, int a, int b), void *arg) -{ - fn(arg, 1, 2); -} - -#define callback_onearg(cb, arg) \ - _callback_onearg(typesafe_cb(void, void *, (cb), (arg)), (arg)) - -#define callback_preargs(cb, arg) \ - _callback_preargs(typesafe_cb_preargs(void, void *, (cb), (arg), int, int), (arg)) - -#define callback_postargs(cb, arg) \ - _callback_postargs(typesafe_cb_postargs(void, void *, (cb), (arg), int, int), (arg)) - -static void my_callback_onearg(char *p) -{ - ok1(strcmp(p, "hello world") == 0); -} - -static void my_callback_preargs(int a, int b, char *p) -{ - ok1(a == 1); - ok1(b == 2); - ok1(strcmp(p, "hello world") == 0); -} - -static void my_callback_postargs(char *p, int a, int b) -{ - ok1(a == 1); - ok1(b == 2); - ok1(strcmp(p, "hello world") == 0); -} - -/* This is simply a compile test; we promised typesafe_cb_cast can be in a - * static initializer. */ -struct callback_onearg -{ - void (*fn)(void *arg); - const void *arg; -}; - -struct callback_onearg cb_onearg -= { typesafe_cb(void, void *, my_callback_onearg, (char *)(intptr_t)"hello world"), - "hello world" }; - -struct callback_preargs -{ - void (*fn)(int a, int b, void *arg); - const void *arg; -}; - -struct callback_preargs cb_preargs -= { typesafe_cb_preargs(void, void *, my_callback_preargs, - (char *)(intptr_t)"hi", int, int), "hi" }; - -struct callback_postargs -{ - void (*fn)(void *arg, int a, int b); - const void *arg; -}; - -struct callback_postargs cb_postargs -= { typesafe_cb_postargs(void, void *, my_callback_postargs, - (char *)(intptr_t)"hi", int, int), "hi" }; - -int main(void) -{ - void *p = &dummy; - unsigned long l = (unsigned long)p; - char str[] = "hello world"; - - plan_tests(2 + 1 + 3 + 3); - set_some_value(p); - set_some_value(l); - - callback_onearg(my_callback_onearg, str); - - callback_preargs(my_callback_preargs, str); - - callback_postargs(my_callback_postargs, str); - - return exit_status(); -} diff --git a/ccan/typesafe_cb/typesafe_cb.h b/ccan/typesafe_cb/typesafe_cb.h deleted file mode 100644 index 126d325..0000000 --- a/ccan/typesafe_cb/typesafe_cb.h +++ /dev/null @@ -1,134 +0,0 @@ -/* CC0 (Public domain) - see LICENSE file for details */ -#ifndef CCAN_TYPESAFE_CB_H -#define CCAN_TYPESAFE_CB_H -#include "config.h" - -#if HAVE_TYPEOF && HAVE_BUILTIN_CHOOSE_EXPR && HAVE_BUILTIN_TYPES_COMPATIBLE_P -/** - * typesafe_cb_cast - only cast an expression if it matches a given type - * @desttype: the type to cast to - * @oktype: the type we allow - * @expr: the expression to cast - * - * This macro is used to create functions which allow multiple types. - * The result of this macro is used somewhere that a @desttype type is - * expected: if @expr is exactly of type @oktype, then it will be - * cast to @desttype type, otherwise left alone. - * - * This macro can be used in static initializers. - * - * This is merely useful for warnings: if the compiler does not - * support the primitives required for typesafe_cb_cast(), it becomes an - * unconditional cast, and the @oktype argument is not used. In - * particular, this means that @oktype can be a type which uses the - * "typeof": it will not be evaluated if typeof is not supported. - * - * Example: - * // We can take either an unsigned long or a void *. - * void _set_some_value(void *val); - * #define set_some_value(e) \ - * _set_some_value(typesafe_cb_cast(void *, unsigned long, (e))) - */ -#define typesafe_cb_cast(desttype, oktype, expr) \ - __builtin_choose_expr( \ - __builtin_types_compatible_p(__typeof__(0?(expr):(expr)), \ - oktype), \ - (desttype)(expr), (expr)) -#else -#define typesafe_cb_cast(desttype, oktype, expr) ((desttype)(expr)) -#endif - -/** - * typesafe_cb_cast3 - only cast an expression if it matches given types - * @desttype: the type to cast to - * @ok1: the first type we allow - * @ok2: the second type we allow - * @ok3: the third type we allow - * @expr: the expression to cast - * - * This is a convenient wrapper for multiple typesafe_cb_cast() calls. - * You can chain them inside each other (ie. use typesafe_cb_cast() - * for expr) if you need more than 3 arguments. - * - * Example: - * // We can take either a long, unsigned long, void * or a const void *. - * void _set_some_value(void *val); - * #define set_some_value(expr) \ - * _set_some_value(typesafe_cb_cast3(void *,, \ - * long, unsigned long, const void *,\ - * (expr))) - */ -#define typesafe_cb_cast3(desttype, ok1, ok2, ok3, expr) \ - typesafe_cb_cast(desttype, ok1, \ - typesafe_cb_cast(desttype, ok2, \ - typesafe_cb_cast(desttype, ok3, \ - (expr)))) - -/** - * typesafe_cb - cast a callback function if it matches the arg - * @rtype: the return type of the callback function - * @atype: the (pointer) type which the callback function expects. - * @fn: the callback function to cast - * @arg: the (pointer) argument to hand to the callback function. - * - * If a callback function takes a single argument, this macro does - * appropriate casts to a function which takes a single atype argument if the - * callback provided matches the @arg. - * - * It is assumed that @arg is of pointer type: usually @arg is passed - * or assigned to a void * elsewhere anyway. - * - * Example: - * void _register_callback(void (*fn)(void *arg), void *arg); - * #define register_callback(fn, arg) \ - * _register_callback(typesafe_cb(void, (fn), void*, (arg)), (arg)) - */ -#define typesafe_cb(rtype, atype, fn, arg) \ - typesafe_cb_cast(rtype (*)(atype), \ - rtype (*)(__typeof__(arg)), \ - (fn)) - -/** - * typesafe_cb_preargs - cast a callback function if it matches the arg - * @rtype: the return type of the callback function - * @atype: the (pointer) type which the callback function expects. - * @fn: the callback function to cast - * @arg: the (pointer) argument to hand to the callback function. - * - * This is a version of typesafe_cb() for callbacks that take other arguments - * before the @arg. - * - * Example: - * void _register_callback(void (*fn)(int, void *arg), void *arg); - * #define register_callback(fn, arg) \ - * _register_callback(typesafe_cb_preargs(void, void *, \ - * (fn), (arg), int), \ - * (arg)) - */ -#define typesafe_cb_preargs(rtype, atype, fn, arg, ...) \ - typesafe_cb_cast(rtype (*)(__VA_ARGS__, atype), \ - rtype (*)(__VA_ARGS__, __typeof__(arg)), \ - (fn)) - -/** - * typesafe_cb_postargs - cast a callback function if it matches the arg - * @rtype: the return type of the callback function - * @atype: the (pointer) type which the callback function expects. - * @fn: the callback function to cast - * @arg: the (pointer) argument to hand to the callback function. - * - * This is a version of typesafe_cb() for callbacks that take other arguments - * after the @arg. - * - * Example: - * void _register_callback(void (*fn)(void *arg, int), void *arg); - * #define register_callback(fn, arg) \ - * _register_callback(typesafe_cb_postargs(void, (fn), void *, \ - * (arg), int), \ - * (arg)) - */ -#define typesafe_cb_postargs(rtype, atype, fn, arg, ...) \ - typesafe_cb_cast(rtype (*)(atype, __VA_ARGS__), \ - rtype (*)(__typeof__(arg), __VA_ARGS__), \ - (fn)) -#endif /* CCAN_CAST_IF_TYPE_H */ |
