#include <stdio.h>
#include <stdlib.h>
struct Fn {
void * parameters;
void ( * function ) ( void * ) ;
struct Fn * next;
} ;
#define SPLICE_2(l,r) l##r
#define SPLICE_1(l,r) SPLICE_2(l,r)
#define SPLICE(l,r) SPLICE_1(l,r)
#define PARAM_0(...)
#define PARAM_1(type, ...) type p1; PARAM_0(__VA_ARGS__)
#define PARAM_2(type, ...) type p2; PARAM_1(__VA_ARGS__)
#define PARAM_3(type, ...) type p3; PARAM_2(__VA_ARGS__)
#define PARAM_4(type, ...) type p4; PARAM_3(__VA_ARGS__)
#define PARAMS(N, ...) SPLICE(PARAM_, N)(__VA_ARGS__)
#define CPARAM_0
#define CPARAM_1 parameters->p1
#define CPARAM_2 parameters->p2, CPARAM_1
#define CPARAM_3 parameters->p3, CPARAM_2
#define CPARAM_4 parameters->p4, CPARAM_3
#define CPARAMS(N) SPLICE(CPARAM_, N)
#define SPARAM_0(...)
#define SPARAM_1(value, ...) parameters->p1 = (value); SPARAM_0(__VA_ARGS__)
#define SPARAM_2(value, ...) parameters->p2 = (value); SPARAM_1(__VA_ARGS__)
#define SPARAM_3(value, ...) parameters->p3 = (value); SPARAM_2(__VA_ARGS__)
#define SPARAM_4(value, ...) parameters->p4 = (value); SPARAM_3(__VA_ARGS__)
#define SPARAMS(N, ...) SPLICE(SPARAM_, N)(__VA_ARGS__)
#define MAKE_DEFERRABLE(name, N, ...) \
struct deferred_ ## name ## _parameters { PARAMS(N, __VA_ARGS__) }; \
void deferred_ ## name (void * p) { \
struct deferred_ ## name ## _parameters * parameters = p; \
printf(" -- Calling deferred " #name "\n"); \
(void)name(CPARAMS(N)); \
}
struct Fn * deferred_fns = NULL;
#define DEFER(name, N, ...) \
do { \
printf(" -- Deferring a call to " #name "\n"); \
if (deferred_fns == NULL) { \
deferred_fns = malloc(sizeof(*deferred_fns)); \
deferred_fns->next = NULL; \
} else { \
struct Fn * f = malloc(sizeof(*f)); \
f->next = deferred_fns; \
deferred_fns = f; \
} \
deferred_fns->function = &(deferred_ ## name); \
struct deferred_ ## name ##_parameters * parameters = malloc(sizeof(*parameters)); \
SPARAMS(N,__VA_ARGS__); \
deferred_fns->parameters = parameters; \
} while(0)
void run_deferred_fns( void ) {
while ( deferred_fns != NULL) {
deferred_fns-> function ( deferred_fns-> parameters) ;
free ( deferred_fns
-> parameters
) ; struct Fn * bye = deferred_fns;
deferred_fns = deferred_fns-> next;
}
}
void foo( int x) {
}
void bar( void ) {
}
void baz( int x, double y) {
}
MAKE_DEFERRABLE( foo, 1 , int ) ;
MAKE_DEFERRABLE( bar, 0 ) ;
MAKE_DEFERRABLE( baz, 2 , int , double ) ;
int main( void ) {
DEFER( foo, 1 , 42 ) ;
DEFER( bar, 0 ) ;
DEFER( foo, 1 , 21 ) ;
DEFER( baz, 2 , 42 , 3.14 ) ;
run_deferred_fns( ) ;
return 0 ;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KCnN0cnVjdCBGbiB7CiAgdm9pZCAqIHBhcmFtZXRlcnM7CiAgdm9pZCAoKmZ1bmN0aW9uKSh2b2lkICopOwogIHN0cnVjdCBGbiAqIG5leHQ7Cn07CgojZGVmaW5lIFNQTElDRV8yKGwscikgbCMjcgojZGVmaW5lIFNQTElDRV8xKGwscikgU1BMSUNFXzIobCxyKQojZGVmaW5lIFNQTElDRShsLHIpIFNQTElDRV8xKGwscikKCiNkZWZpbmUgUEFSQU1fMCguLi4pCiNkZWZpbmUgUEFSQU1fMSh0eXBlLCAuLi4pIHR5cGUgcDE7IFBBUkFNXzAoX19WQV9BUkdTX18pCiNkZWZpbmUgUEFSQU1fMih0eXBlLCAuLi4pIHR5cGUgcDI7IFBBUkFNXzEoX19WQV9BUkdTX18pCiNkZWZpbmUgUEFSQU1fMyh0eXBlLCAuLi4pIHR5cGUgcDM7IFBBUkFNXzIoX19WQV9BUkdTX18pCiNkZWZpbmUgUEFSQU1fNCh0eXBlLCAuLi4pIHR5cGUgcDQ7IFBBUkFNXzMoX19WQV9BUkdTX18pCiNkZWZpbmUgUEFSQU1TKE4sIC4uLikgU1BMSUNFKFBBUkFNXywgTikoX19WQV9BUkdTX18pCgojZGVmaW5lIENQQVJBTV8wIAojZGVmaW5lIENQQVJBTV8xIHBhcmFtZXRlcnMtPnAxCiNkZWZpbmUgQ1BBUkFNXzIgcGFyYW1ldGVycy0+cDIsIENQQVJBTV8xCiNkZWZpbmUgQ1BBUkFNXzMgcGFyYW1ldGVycy0+cDMsIENQQVJBTV8yCiNkZWZpbmUgQ1BBUkFNXzQgcGFyYW1ldGVycy0+cDQsIENQQVJBTV8zCiNkZWZpbmUgQ1BBUkFNUyhOKSBTUExJQ0UoQ1BBUkFNXywgTikKCiNkZWZpbmUgU1BBUkFNXzAoLi4uKQojZGVmaW5lIFNQQVJBTV8xKHZhbHVlLCAuLi4pIHBhcmFtZXRlcnMtPnAxID0gKHZhbHVlKTsgU1BBUkFNXzAoX19WQV9BUkdTX18pCiNkZWZpbmUgU1BBUkFNXzIodmFsdWUsIC4uLikgcGFyYW1ldGVycy0+cDIgPSAodmFsdWUpOyBTUEFSQU1fMShfX1ZBX0FSR1NfXykKI2RlZmluZSBTUEFSQU1fMyh2YWx1ZSwgLi4uKSBwYXJhbWV0ZXJzLT5wMyA9ICh2YWx1ZSk7IFNQQVJBTV8yKF9fVkFfQVJHU19fKQojZGVmaW5lIFNQQVJBTV80KHZhbHVlLCAuLi4pIHBhcmFtZXRlcnMtPnA0ID0gKHZhbHVlKTsgU1BBUkFNXzMoX19WQV9BUkdTX18pCiNkZWZpbmUgU1BBUkFNUyhOLCAuLi4pIFNQTElDRShTUEFSQU1fLCBOKShfX1ZBX0FSR1NfXykKCiNkZWZpbmUgTUFLRV9ERUZFUlJBQkxFKG5hbWUsIE4sIC4uLikgXAogIHN0cnVjdCBkZWZlcnJlZF8gIyMgbmFtZSAjIyBfcGFyYW1ldGVycyB7IFBBUkFNUyhOLCBfX1ZBX0FSR1NfXykgfTsgXAogIHZvaWQgZGVmZXJyZWRfICMjIG5hbWUgKHZvaWQgKiBwKSB7IFwKICAgIHN0cnVjdCBkZWZlcnJlZF8gIyMgbmFtZSAjIyBfcGFyYW1ldGVycyAqIHBhcmFtZXRlcnMgPSBwOyBcCiAgICBwcmludGYoIiAtLSBDYWxsaW5nIGRlZmVycmVkICIgI25hbWUgIlxuIik7IFwKICAgICh2b2lkKW5hbWUoQ1BBUkFNUyhOKSk7IFwKICB9CgpzdHJ1Y3QgRm4gKiBkZWZlcnJlZF9mbnMgPSBOVUxMOwoKI2RlZmluZSBERUZFUihuYW1lLCBOLCAuLi4pIFwKICBkbyB7IFwKICAgIHByaW50ZigiIC0tIERlZmVycmluZyBhIGNhbGwgdG8gIiAjbmFtZSAiXG4iKTsgXAogICAgaWYgKGRlZmVycmVkX2ZucyA9PSBOVUxMKSB7IFwKICAgICAgZGVmZXJyZWRfZm5zID0gbWFsbG9jKHNpemVvZigqZGVmZXJyZWRfZm5zKSk7IFwKICAgICAgZGVmZXJyZWRfZm5zLT5uZXh0ID0gTlVMTDsgXAogICAgfSBlbHNlIHsgXAogICAgICBzdHJ1Y3QgRm4gKiBmID0gbWFsbG9jKHNpemVvZigqZikpOyBcCiAgICAgIGYtPm5leHQgPSBkZWZlcnJlZF9mbnM7IFwKICAgICAgZGVmZXJyZWRfZm5zID0gZjsgXAogICAgfSBcCiAgICBkZWZlcnJlZF9mbnMtPmZ1bmN0aW9uID0gJihkZWZlcnJlZF8gIyMgbmFtZSk7IFwKICAgIHN0cnVjdCBkZWZlcnJlZF8gIyMgbmFtZSAjI19wYXJhbWV0ZXJzICogcGFyYW1ldGVycyA9IG1hbGxvYyhzaXplb2YoKnBhcmFtZXRlcnMpKTsgXAogICAgU1BBUkFNUyhOLF9fVkFfQVJHU19fKTsgXAogICAgZGVmZXJyZWRfZm5zLT5wYXJhbWV0ZXJzID0gcGFyYW1ldGVyczsgXAogIH0gd2hpbGUoMCkKCgp2b2lkIHJ1bl9kZWZlcnJlZF9mbnModm9pZCkgewogIHdoaWxlIChkZWZlcnJlZF9mbnMgIT0gTlVMTCkgewogICAgZGVmZXJyZWRfZm5zLT5mdW5jdGlvbihkZWZlcnJlZF9mbnMtPnBhcmFtZXRlcnMpOwogICAgZnJlZShkZWZlcnJlZF9mbnMtPnBhcmFtZXRlcnMpOwogICAgc3RydWN0IEZuICogYnllID0gZGVmZXJyZWRfZm5zOwogICAgZGVmZXJyZWRfZm5zID0gZGVmZXJyZWRfZm5zLT5uZXh0OwogICAgZnJlZShieWUpOwogIH0KfQoKCnZvaWQgZm9vKGludCB4KSB7CglwcmludGYoImZvbzogJWRcbiIsIHgpOwp9Cgp2b2lkIGJhcih2b2lkKSB7CglwdXRzKCJiYXIiKTsKfQoKdm9pZCBiYXooaW50IHgsIGRvdWJsZSB5KSB7CglwcmludGYoImJhejogJWQgJWZcbiIsIHgsIHkpOwp9CgpNQUtFX0RFRkVSUkFCTEUoZm9vLCAxLCBpbnQpOwpNQUtFX0RFRkVSUkFCTEUoYmFyLCAwKTsKTUFLRV9ERUZFUlJBQkxFKGJheiwgMiwgaW50LCBkb3VibGUpOwoKaW50IG1haW4odm9pZCkgewogIERFRkVSKGZvbywgMSwgNDIpOwogIERFRkVSKGJhciwgMCk7CiAgREVGRVIoZm9vLCAxLCAyMSk7CiAgREVGRVIoYmF6LCAyLCA0MiwgMy4xNCk7CiAgcnVuX2RlZmVycmVkX2ZucygpOwogIHJldHVybiAwOwp9Cg==