summaryrefslogtreecommitdiffstats
path: root/lib/ccan/typesafe_cb/_info
blob: 4f4570afc9b496a2273be1d1b9c8a7b977175fbc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include <stdio.h>
#include <string.h>
#include "config.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 = argv[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: LGPL (2 or any later version)
 * 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;
}