Hash :
a0d14d15
Author :
Date :
2011-07-06T16:47:25
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;
}