]> git.ozlabs.org Git - ccan/blob - ccan/typesafe_cb/_info
Remove unused main() args in many modules.
[ccan] / ccan / typesafe_cb / _info
1 #include "config.h"
2 #include <stdio.h>
3 #include <string.h>
4
5 /**
6  * typesafe_cb - macros for safe callbacks.
7  *
8  * The basis of the typesafe_cb header is typesafe_cb_cast(): a
9  * conditional cast macro.   If an expression exactly matches a given
10  * type, it is cast to the target type, otherwise it is left alone.
11  *
12  * This allows us to create functions which take a small number of
13  * specific types, rather than being forced to use a void *.  In
14  * particular, it is useful for creating typesafe callbacks as the
15  * helpers typesafe_cb(), typesafe_cb_preargs() and
16  * typesafe_cb_postargs() demonstrate.
17  * 
18  * The standard way of passing arguments to callback functions in C is
19  * to use a void pointer, which the callback then casts back to the
20  * expected type.  This unfortunately subverts the type checking the
21  * compiler would perform if it were a direct call.  Here's an example:
22  *
23  *      static void my_callback(void *_obj)
24  *      {
25  *              struct obj *obj = _obj;
26  *              ...
27  *      }
28  *      ...
29  *              register_callback(my_callback, &my_obj);
30  *
31  * If we wanted to use the natural type for my_callback (ie. "void
32  * my_callback(struct obj *obj)"), we could make register_callback()
33  * take a void * as its first argument, but this would subvert all
34  * type checking.  We really want register_callback() to accept only
35  * the exactly correct function type to match the argument, or a
36  * function which takes a void *.
37  *
38  * This is where typesafe_cb() comes in: it uses typesafe_cb_cast() to
39  * cast the callback function if it matches the argument type:
40  *
41  *      void _register_callback(void (*cb)(void *arg), void *arg);
42  *      #define register_callback(cb, arg)                              \
43  *              _register_callback(typesafe_cb(void, void *, (cb), (arg)), \
44  *                                 (arg))
45  *
46  * On compilers which don't support the extensions required
47  * typesafe_cb_cast() and friend become an unconditional cast, so your
48  * code will compile but you won't get type checking.
49  *
50  * Example:
51  *      #include <ccan/typesafe_cb/typesafe_cb.h>
52  *      #include <stdlib.h>
53  *      #include <stdio.h>
54  *
55  *      // Generic callback infrastructure.
56  *      struct callback {
57  *              struct callback *next;
58  *              int value;
59  *              int (*callback)(int value, void *arg);
60  *              void *arg;
61  *      };
62  *      static struct callback *callbacks;
63  *      
64  *      static void _register_callback(int value, int (*cb)(int, void *),
65  *                                     void *arg)
66  *      {
67  *              struct callback *new = malloc(sizeof(*new));
68  *              new->next = callbacks;
69  *              new->value = value;
70  *              new->callback = cb;
71  *              new->arg = arg;
72  *              callbacks = new;
73  *      }
74  *      #define register_callback(value, cb, arg)                       \
75  *              _register_callback(value,                               \
76  *                                 typesafe_cb_preargs(int, void *,     \
77  *                                                     (cb), (arg), int),\
78  *                                 (arg))
79  *      
80  *      static struct callback *find_callback(int value)
81  *      {
82  *              struct callback *i;
83  *      
84  *              for (i = callbacks; i; i = i->next)
85  *                      if (i->value == value)
86  *                              return i;
87  *              return NULL;
88  *      }   
89  *
90  *      // Define several silly callbacks.  Note they don't use void *!
91  *      #define DEF_CALLBACK(name, op)                  \
92  *              static int name(int val, int *arg)      \
93  *              {                                       \
94  *                      printf("%s", #op);              \
95  *                      return val op *arg;             \
96  *              }
97  *      DEF_CALLBACK(multiply, *);
98  *      DEF_CALLBACK(add, +);
99  *      DEF_CALLBACK(divide, /);
100  *      DEF_CALLBACK(sub, -);
101  *      DEF_CALLBACK(or, |);
102  *      DEF_CALLBACK(and, &);
103  *      DEF_CALLBACK(xor, ^);
104  *      DEF_CALLBACK(assign, =);
105  *
106  *      // Silly game to find the longest chain of values.
107  *      int main(int argc, char *argv[])
108  *      {
109  *              int i, run = 1, num = argv[1] ? atoi(argv[1]) : 0;
110  *      
111  *              for (i = 1; i < 1024;) {
112  *                      // Since run is an int, compiler checks "add" does too.
113  *                      register_callback(i++, add, &run);
114  *                      register_callback(i++, divide, &run);
115  *                      register_callback(i++, sub, &run);
116  *                      register_callback(i++, multiply, &run);
117  *                      register_callback(i++, or, &run);
118  *                      register_callback(i++, and, &run);
119  *                      register_callback(i++, xor, &run);
120  *                      register_callback(i++, assign, &run);
121  *              }
122  *      
123  *              printf("%i ", num);
124  *              while (run < 56) {
125  *                      struct callback *cb = find_callback(num % i);
126  *                      if (!cb) {
127  *                              printf("-> STOP\n");
128  *                              return 1;
129  *                      }
130  *                      num = cb->callback(num, cb->arg);
131  *                      printf("->%i ", num);
132  *                      run++;
133  *              }
134  *              printf("-> Winner!\n");
135  *              return 0;
136  *      }
137  *
138  * License: CC0 (Public domain)
139  * Author: Rusty Russell <rusty@rustcorp.com.au>
140  */
141 int main(int argc, char *argv[])
142 {
143         if (argc != 2)
144                 return 1;
145
146         if (strcmp(argv[1], "depends") == 0) {
147                 return 0;
148         }
149
150         return 1;
151 }