#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct partially_applied {
void * data;
void (*function)(void *);
void (*store)(void *, char const *, void *);
};
typedef struct partially_applied * FUN;
#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 DATA_DEF_0(...)
#define DATA_DEF_1(type, name) type name; bool name ## _valid;
#define DATA_DEF_2(type, name, ...) type name; bool name ## _valid; DATA_DEF_1(__VA_ARGS__)
#define DATA_DEF_3(type, name, ...) type name; bool name ## _valid; DATA_DEF_2(__VA_ARGS__)
#define DATA_DEF_4(type, name, ...) type name; bool name ## _valid; DATA_DEF_3(__VA_ARGS__)
// add more to support more parameters
#define DATA_DEF(N, ...) SPLICE(DATA_DEF_,N)(__VA_ARGS__)
#define DATA_ACCESS_0(...)
#define DATA_ACCESS_1(t, name) data->name
#define DATA_ACCESS_2(t, name, ...) data->name, DATA_ACCESS_1(__VA_ARGS__)
#define DATA_ACCESS_3(t, name, ...) data->name, DATA_ACCESS_2(__VA_ARGS__)
#define DATA_ACCESS_4(t, name, ...) data->name, DATA_ACCESS_3(__VA_ARGS__)
// add more to support more parameters
#define DATA_ACCESS(N, ...) SPLICE(DATA_ACCESS_,N)(__VA_ARGS__)
#define DATA_CHECK_0(...) true
#define DATA_CHECK_1(t, name) data->name ## _valid
#define DATA_CHECK_2(t, name, ...) data->name ## _valid && DATA_CHECK_1(__VA_ARGS__)
#define DATA_CHECK_3(t, name, ...) data->name ## _valid && DATA_CHECK_2(__VA_ARGS__)
#define DATA_CHECK_4(t, name, ...) data->name ## _valid && DATA_CHECK_3(__VA_ARGS__)
// add more to support more parameters
#define DATA_CHECK(N, ...) SPLICE(DATA_CHECK_,N)(__VA_ARGS__)
#define DATA_INIT_0(...)
#define DATA_INIT_1(t, name) data->name ## _valid = false;
#define DATA_INIT_2(t, name, ...) data->name ## _valid = false; DATA_INIT_1(__VA_ARGS__)
#define DATA_INIT_3(t, name, ...) data->name ## _valid = false; DATA_INIT_2(__VA_ARGS__)
#define DATA_INIT_4(t, name, ...) data->name ## _valid = false; DATA_INIT_3(__VA_ARGS__)
// add more to support more parameters
#define DATA_INIT(N, ...) SPLICE(DATA_INIT_,N)(__VA_ARGS__)
#define DATA_STORE_CODE_OP(type, name) \
if (strcmp(id, #name) == 0) { data->name = *((type *) src); data->name ## _valid = true; return; }
#define DATA_STORE_CODE_0(...)
#define DATA_STORE_CODE_1(type, name) DATA_STORE_CODE_OP(type, name)
#define DATA_STORE_CODE_2(type, name, ...) DATA_STORE_CODE_OP(type, name) DATA_STORE_CODE_1(__VA_ARGS__)
#define DATA_STORE_CODE_3(type, name, ...) DATA_STORE_CODE_OP(type, name) DATA_STORE_CODE_2(__VA_ARGS__)
#define DATA_STORE_CODE_4(type, name, ...) DATA_STORE_CODE_OP(type, name) DATA_STORE_CODE_3(__VA_ARGS__)
// more
#define DATA_STORE_CODE(N, ...) SPLICE(DATA_STORE_CODE_,N)(__VA_ARGS__)
#define MAKE_PARTIAL(fn, N, ...) \
struct partially_applied_ ## fn ## _data { \
DATA_DEF(N, __VA_ARGS__) \
}; \
static void init_partially_applied_ ## fn ## _data (void * p) { \
struct partially_applied_ ## fn ## _data * data = p; \
DATA_INIT(N, __VA_ARGS__); \
} \
static void * allocate_partially_applied_ ## fn ## _data (void) { \
void * data = malloc(sizeof(struct partially_applied_ ## fn ## _data)); \
if (data == NULL) { \
fprintf(stderr, "Allocation failure for " #fn " data\n"); \
exit(1); \
} \
init_partially_applied_ ## fn ## _data(data); \
return data; \
} \
static void partially_applied_ ## fn (void * p) { \
struct partially_applied_ ## fn ## _data * data = p; \
if (DATA_CHECK(N, __VA_ARGS__)) { \
fn(DATA_ACCESS(N, __VA_ARGS__)); \
} else { \
fprintf(stderr, "Not all parameters for " #fn " are vaild\n"); \
} \
} \
static void partially_applied_ ## fn ## _store ( \
void * p, char const * id, void * src) { \
struct partially_applied_ ## fn ## _data * data = p; \
DATA_STORE_CODE(N, __VA_ARGS__) \
fprintf(stderr, "Cannot store %s in " #fn "!\n", id); \
}
#define DATA_STORE_OP(name, value) pfn->store(pfn->data, #name, &(value));
#define DATA_STORE_0(...)
#define DATA_STORE_1(name, value) DATA_STORE_OP(name, value)
#define DATA_STORE_2(name, value, ...) DATA_STORE_OP(name, value) DATA_STORE_1(__VA_ARGS__)
#define DATA_STORE_3(name, value, ...) DATA_STORE_OP(name, value) DATA_STORE_2(__VA_ARGS__)
#define DATA_STORE_4(name, value, ...) DATA_STORE_OP(name, value) DATA_STORE_3(__VA_ARGS__)
#define DATA_STORE(N, ...) SPLICE(DATA_STORE_,N)(__VA_ARGS__)
#define APPLY(PFN, N, ...) \
do { \
struct partially_applied * pfn = (PFN); \
DATA_STORE(N, __VA_ARGS__) \
} while(0)
FUN make_fun(void (*function)(void *), void (*store)(void *, char const *, void *), void * data) {
if (f == NULL) {
fprintf(stderr
, "Allocation of FUN failed\n"); }
f->function = function;
f->store = store;
f->data = data;
return f;
}
void free_fun(FUN f) {
}
#define PARTIAL(fn) make_fun(&(partially_applied_ ## fn), \
&(partially_applied_ ## fn ## _store), \
allocate_partially_applied_ ## fn ## _data())
#define DISCARD(fn) free_fn(fn)
#define CALL(fn) (fn)->function((fn)->data)
void foo(char * str, int i) {
printf("FOO| str = %s, i = %d\n", str
, i
); }
void bar(float f, int i, size_t s) {
printf("BAR| f = %f, i = %d, s = %zu\n", f
, i
, s
); }
MAKE_PARTIAL(foo, 2, char *, string, int, integer)
MAKE_PARTIAL(bar, 3, float, floating, int, INT, size_t, SOME_SIZE)
int main() {
FUN f = PARTIAL(foo);
char * c = "Crazy";
APPLY(f, 1, string, c);
printf("doing other stuff\n"); FUN g = PARTIAL(bar);
size_t size = 99;
APPLY(g, 1, SOME_SIZE, size);
int answer = 42;
APPLY(f, 1, integer, answer);
answer = 21;
float pi = 3.14;
APPLY(g, 2, INT, answer, floating, pi);
CALL(f);
CALL(g);
printf("now completely done\n"); return 0;
}
I2luY2x1ZGUgPHN0ZGJvb2wuaD4KI2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHN0cmluZy5oPgoKc3RydWN0IHBhcnRpYWxseV9hcHBsaWVkIHsKICB2b2lkICogZGF0YTsKICB2b2lkICgqZnVuY3Rpb24pKHZvaWQgKik7CiAgdm9pZCAoKnN0b3JlKSh2b2lkICosIGNoYXIgY29uc3QgKiwgdm9pZCAqKTsKfTsKCnR5cGVkZWYgc3RydWN0IHBhcnRpYWxseV9hcHBsaWVkICogRlVOOwoKI2RlZmluZSBTUExJQ0VfMihsLHIpIGwjI3IKI2RlZmluZSBTUExJQ0VfMShsLHIpIFNQTElDRV8yKGwscikKI2RlZmluZSBTUExJQ0UobCxyKSBTUExJQ0VfMShsLHIpCgojZGVmaW5lIERBVEFfREVGXzAoLi4uKQojZGVmaW5lIERBVEFfREVGXzEodHlwZSwgbmFtZSkgICAgICB0eXBlIG5hbWU7IGJvb2wgbmFtZSAjIyBfdmFsaWQ7CiNkZWZpbmUgREFUQV9ERUZfMih0eXBlLCBuYW1lLCAuLi4pIHR5cGUgbmFtZTsgYm9vbCBuYW1lICMjIF92YWxpZDsgREFUQV9ERUZfMShfX1ZBX0FSR1NfXykKI2RlZmluZSBEQVRBX0RFRl8zKHR5cGUsIG5hbWUsIC4uLikgdHlwZSBuYW1lOyBib29sIG5hbWUgIyMgX3ZhbGlkOyBEQVRBX0RFRl8yKF9fVkFfQVJHU19fKQojZGVmaW5lIERBVEFfREVGXzQodHlwZSwgbmFtZSwgLi4uKSB0eXBlIG5hbWU7IGJvb2wgbmFtZSAjIyBfdmFsaWQ7IERBVEFfREVGXzMoX19WQV9BUkdTX18pCi8vIGFkZCBtb3JlIHRvIHN1cHBvcnQgbW9yZSBwYXJhbWV0ZXJzCiNkZWZpbmUgREFUQV9ERUYoTiwgLi4uKSBTUExJQ0UoREFUQV9ERUZfLE4pKF9fVkFfQVJHU19fKQoKI2RlZmluZSBEQVRBX0FDQ0VTU18wKC4uLikKI2RlZmluZSBEQVRBX0FDQ0VTU18xKHQsIG5hbWUpICAgICAgZGF0YS0+bmFtZQojZGVmaW5lIERBVEFfQUNDRVNTXzIodCwgbmFtZSwgLi4uKSBkYXRhLT5uYW1lLCBEQVRBX0FDQ0VTU18xKF9fVkFfQVJHU19fKQojZGVmaW5lIERBVEFfQUNDRVNTXzModCwgbmFtZSwgLi4uKSBkYXRhLT5uYW1lLCBEQVRBX0FDQ0VTU18yKF9fVkFfQVJHU19fKQojZGVmaW5lIERBVEFfQUNDRVNTXzQodCwgbmFtZSwgLi4uKSBkYXRhLT5uYW1lLCBEQVRBX0FDQ0VTU18zKF9fVkFfQVJHU19fKQovLyBhZGQgbW9yZSB0byBzdXBwb3J0IG1vcmUgcGFyYW1ldGVycwojZGVmaW5lIERBVEFfQUNDRVNTKE4sIC4uLikgU1BMSUNFKERBVEFfQUNDRVNTXyxOKShfX1ZBX0FSR1NfXykKCiNkZWZpbmUgREFUQV9DSEVDS18wKC4uLikgdHJ1ZQojZGVmaW5lIERBVEFfQ0hFQ0tfMSh0LCBuYW1lKSAgICAgIGRhdGEtPm5hbWUgIyMgX3ZhbGlkCiNkZWZpbmUgREFUQV9DSEVDS18yKHQsIG5hbWUsIC4uLikgZGF0YS0+bmFtZSAjIyBfdmFsaWQgJiYgREFUQV9DSEVDS18xKF9fVkFfQVJHU19fKQojZGVmaW5lIERBVEFfQ0hFQ0tfMyh0LCBuYW1lLCAuLi4pIGRhdGEtPm5hbWUgIyMgX3ZhbGlkICYmIERBVEFfQ0hFQ0tfMihfX1ZBX0FSR1NfXykKI2RlZmluZSBEQVRBX0NIRUNLXzQodCwgbmFtZSwgLi4uKSBkYXRhLT5uYW1lICMjIF92YWxpZCAmJiBEQVRBX0NIRUNLXzMoX19WQV9BUkdTX18pCi8vIGFkZCBtb3JlIHRvIHN1cHBvcnQgbW9yZSBwYXJhbWV0ZXJzCiNkZWZpbmUgREFUQV9DSEVDSyhOLCAuLi4pIFNQTElDRShEQVRBX0NIRUNLXyxOKShfX1ZBX0FSR1NfXykKCiNkZWZpbmUgREFUQV9JTklUXzAoLi4uKQojZGVmaW5lIERBVEFfSU5JVF8xKHQsIG5hbWUpICAgICAgZGF0YS0+bmFtZSAjIyBfdmFsaWQgPSBmYWxzZTsKI2RlZmluZSBEQVRBX0lOSVRfMih0LCBuYW1lLCAuLi4pIGRhdGEtPm5hbWUgIyMgX3ZhbGlkID0gZmFsc2U7IERBVEFfSU5JVF8xKF9fVkFfQVJHU19fKQojZGVmaW5lIERBVEFfSU5JVF8zKHQsIG5hbWUsIC4uLikgZGF0YS0+bmFtZSAjIyBfdmFsaWQgPSBmYWxzZTsgREFUQV9JTklUXzIoX19WQV9BUkdTX18pCiNkZWZpbmUgREFUQV9JTklUXzQodCwgbmFtZSwgLi4uKSBkYXRhLT5uYW1lICMjIF92YWxpZCA9IGZhbHNlOyBEQVRBX0lOSVRfMyhfX1ZBX0FSR1NfXykKLy8gYWRkIG1vcmUgdG8gc3VwcG9ydCBtb3JlIHBhcmFtZXRlcnMKI2RlZmluZSBEQVRBX0lOSVQoTiwgLi4uKSBTUExJQ0UoREFUQV9JTklUXyxOKShfX1ZBX0FSR1NfXykKCgojZGVmaW5lIERBVEFfU1RPUkVfQ09ERV9PUCh0eXBlLCBuYW1lKSBcCmlmIChzdHJjbXAoaWQsICNuYW1lKSA9PSAwKSB7IGRhdGEtPm5hbWUgPSAqKCh0eXBlICopIHNyYyk7IGRhdGEtPm5hbWUgIyMgX3ZhbGlkID0gdHJ1ZTsgcmV0dXJuOyB9CgojZGVmaW5lIERBVEFfU1RPUkVfQ09ERV8wKC4uLikKI2RlZmluZSBEQVRBX1NUT1JFX0NPREVfMSh0eXBlLCBuYW1lKSAgICAgIERBVEFfU1RPUkVfQ09ERV9PUCh0eXBlLCBuYW1lKQojZGVmaW5lIERBVEFfU1RPUkVfQ09ERV8yKHR5cGUsIG5hbWUsIC4uLikgREFUQV9TVE9SRV9DT0RFX09QKHR5cGUsIG5hbWUpIERBVEFfU1RPUkVfQ09ERV8xKF9fVkFfQVJHU19fKQojZGVmaW5lIERBVEFfU1RPUkVfQ09ERV8zKHR5cGUsIG5hbWUsIC4uLikgREFUQV9TVE9SRV9DT0RFX09QKHR5cGUsIG5hbWUpIERBVEFfU1RPUkVfQ09ERV8yKF9fVkFfQVJHU19fKQojZGVmaW5lIERBVEFfU1RPUkVfQ09ERV80KHR5cGUsIG5hbWUsIC4uLikgREFUQV9TVE9SRV9DT0RFX09QKHR5cGUsIG5hbWUpIERBVEFfU1RPUkVfQ09ERV8zKF9fVkFfQVJHU19fKQovLyBtb3JlCiNkZWZpbmUgREFUQV9TVE9SRV9DT0RFKE4sIC4uLikgU1BMSUNFKERBVEFfU1RPUkVfQ09ERV8sTikoX19WQV9BUkdTX18pCgojZGVmaW5lIE1BS0VfUEFSVElBTChmbiwgTiwgLi4uKSBcCnN0cnVjdCBwYXJ0aWFsbHlfYXBwbGllZF8gIyMgZm4gIyMgX2RhdGEgeyBcCglEQVRBX0RFRihOLCBfX1ZBX0FSR1NfXykgXAp9OyBcCnN0YXRpYyB2b2lkIGluaXRfcGFydGlhbGx5X2FwcGxpZWRfICMjIGZuICMjIF9kYXRhICh2b2lkICogcCkgeyBcCglzdHJ1Y3QgcGFydGlhbGx5X2FwcGxpZWRfICMjIGZuICMjIF9kYXRhICogZGF0YSA9IHA7IFwKCURBVEFfSU5JVChOLCBfX1ZBX0FSR1NfXyk7IFwKfSBcCnN0YXRpYyB2b2lkICogYWxsb2NhdGVfcGFydGlhbGx5X2FwcGxpZWRfICMjIGZuICMjIF9kYXRhICh2b2lkKSB7IFwKCXZvaWQgKiBkYXRhID0gbWFsbG9jKHNpemVvZihzdHJ1Y3QgcGFydGlhbGx5X2FwcGxpZWRfICMjIGZuICMjIF9kYXRhKSk7IFwKCWlmIChkYXRhID09IE5VTEwpIHsgXAoJCWZwcmludGYoc3RkZXJyLCAiQWxsb2NhdGlvbiBmYWlsdXJlIGZvciAiICNmbiAiIGRhdGFcbiIpOyBcCgkJZXhpdCgxKTsgXAoJfSBcCglpbml0X3BhcnRpYWxseV9hcHBsaWVkXyAjIyBmbiAjIyBfZGF0YShkYXRhKTsgXAoJcmV0dXJuIGRhdGE7IFwKfSBcCnN0YXRpYyB2b2lkIHBhcnRpYWxseV9hcHBsaWVkXyAjIyBmbiAodm9pZCAqIHApIHsgXAoJc3RydWN0IHBhcnRpYWxseV9hcHBsaWVkXyAjIyBmbiAjIyBfZGF0YSAqIGRhdGEgPSBwOyBcCglpZiAoREFUQV9DSEVDSyhOLCBfX1ZBX0FSR1NfXykpIHsgXAoJCWZuKERBVEFfQUNDRVNTKE4sIF9fVkFfQVJHU19fKSk7IFwKCX0gZWxzZSB7IFwKCQlmcHJpbnRmKHN0ZGVyciwgIk5vdCBhbGwgcGFyYW1ldGVycyBmb3IgIiAjZm4gIiBhcmUgdmFpbGRcbiIpOyBcCgl9IFwKfSBcCnN0YXRpYyB2b2lkIHBhcnRpYWxseV9hcHBsaWVkXyAjIyBmbiAjIyBfc3RvcmUgKCBcCgl2b2lkICogcCwgY2hhciBjb25zdCAqIGlkLCB2b2lkICogc3JjKSB7IFwKCXN0cnVjdCBwYXJ0aWFsbHlfYXBwbGllZF8gIyMgZm4gIyMgX2RhdGEgKiBkYXRhID0gcDsgXAoJREFUQV9TVE9SRV9DT0RFKE4sIF9fVkFfQVJHU19fKSBcCglmcHJpbnRmKHN0ZGVyciwgIkNhbm5vdCBzdG9yZSAlcyBpbiAiICNmbiAiIVxuIiwgaWQpOyBcCn0KCgoKCgoKCiNkZWZpbmUgREFUQV9TVE9SRV9PUChuYW1lLCB2YWx1ZSkgcGZuLT5zdG9yZShwZm4tPmRhdGEsICNuYW1lLCAmKHZhbHVlKSk7CiNkZWZpbmUgREFUQV9TVE9SRV8wKC4uLikKI2RlZmluZSBEQVRBX1NUT1JFXzEobmFtZSwgdmFsdWUpIERBVEFfU1RPUkVfT1AobmFtZSwgdmFsdWUpCiNkZWZpbmUgREFUQV9TVE9SRV8yKG5hbWUsIHZhbHVlLCAuLi4pIERBVEFfU1RPUkVfT1AobmFtZSwgdmFsdWUpIERBVEFfU1RPUkVfMShfX1ZBX0FSR1NfXykKI2RlZmluZSBEQVRBX1NUT1JFXzMobmFtZSwgdmFsdWUsIC4uLikgREFUQV9TVE9SRV9PUChuYW1lLCB2YWx1ZSkgREFUQV9TVE9SRV8yKF9fVkFfQVJHU19fKQojZGVmaW5lIERBVEFfU1RPUkVfNChuYW1lLCB2YWx1ZSwgLi4uKSBEQVRBX1NUT1JFX09QKG5hbWUsIHZhbHVlKSBEQVRBX1NUT1JFXzMoX19WQV9BUkdTX18pCiNkZWZpbmUgREFUQV9TVE9SRShOLCAuLi4pIFNQTElDRShEQVRBX1NUT1JFXyxOKShfX1ZBX0FSR1NfXykKCgojZGVmaW5lIEFQUExZKFBGTiwgTiwgLi4uKSBcCmRvIHsgXAoJc3RydWN0IHBhcnRpYWxseV9hcHBsaWVkICogcGZuID0gKFBGTik7IFwKCURBVEFfU1RPUkUoTiwgX19WQV9BUkdTX18pIFwKfSB3aGlsZSgwKQoKCkZVTiBtYWtlX2Z1bih2b2lkICgqZnVuY3Rpb24pKHZvaWQgKiksIHZvaWQgKCpzdG9yZSkodm9pZCAqLCBjaGFyIGNvbnN0ICosIHZvaWQgKiksIHZvaWQgKiBkYXRhKSB7CglGVU4gZiA9IG1hbGxvYyhzaXplb2YoKmYpKTsKCWlmIChmID09IE5VTEwpIHsKCQlmcHJpbnRmKHN0ZGVyciwgIkFsbG9jYXRpb24gb2YgRlVOIGZhaWxlZFxuIik7CgkJZXhpdCgxKTsKCX0KCWYtPmZ1bmN0aW9uID0gZnVuY3Rpb247CglmLT5zdG9yZSA9IHN0b3JlOwoJZi0+ZGF0YSA9IGRhdGE7CglyZXR1cm4gZjsKfQp2b2lkIGZyZWVfZnVuKEZVTiBmKSB7CglmcmVlKGYtPmRhdGEpOwoJZnJlZShmKTsKfQojZGVmaW5lIFBBUlRJQUwoZm4pIG1ha2VfZnVuKCYocGFydGlhbGx5X2FwcGxpZWRfICMjIGZuKSwgXAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICYocGFydGlhbGx5X2FwcGxpZWRfICMjIGZuICMjIF9zdG9yZSksIFwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxvY2F0ZV9wYXJ0aWFsbHlfYXBwbGllZF8gIyMgZm4gIyMgX2RhdGEoKSkKCgoKCgojZGVmaW5lIERJU0NBUkQoZm4pIGZyZWVfZm4oZm4pCgojZGVmaW5lIENBTEwoZm4pIChmbiktPmZ1bmN0aW9uKChmbiktPmRhdGEpCgp2b2lkIGZvbyhjaGFyICogc3RyLCBpbnQgaSkgewoJcHJpbnRmKCJGT098IHN0ciA9ICVzLCBpID0gJWRcbiIsIHN0ciwgaSk7Cn0Kdm9pZCBiYXIoZmxvYXQgZiwgaW50IGksIHNpemVfdCBzKSB7CglwcmludGYoIkJBUnwgZiA9ICVmLCBpID0gJWQsIHMgPSAlenVcbiIsIGYsIGksIHMpOwp9Ck1BS0VfUEFSVElBTChmb28sIDIsIGNoYXIgKiwgc3RyaW5nLCBpbnQsIGludGVnZXIpCk1BS0VfUEFSVElBTChiYXIsIDMsIGZsb2F0LCBmbG9hdGluZywgaW50LCBJTlQsIHNpemVfdCwgU09NRV9TSVpFKQoKCmludCBtYWluKCkgewoJRlVOIGYgPSBQQVJUSUFMKGZvbyk7CgljaGFyICogYyA9ICJDcmF6eSI7CglBUFBMWShmLCAxLCBzdHJpbmcsIGMpOwoJcHJpbnRmKCJkb2luZyBvdGhlciBzdHVmZlxuIik7CglGVU4gZyA9IFBBUlRJQUwoYmFyKTsKCXNpemVfdCBzaXplID0gOTk7CglBUFBMWShnLCAxLCBTT01FX1NJWkUsIHNpemUpOwoJaW50IGFuc3dlciA9IDQyOwoJQVBQTFkoZiwgMSwgaW50ZWdlciwgYW5zd2VyKTsKCWFuc3dlciA9IDIxOwoJZmxvYXQgcGkgPSAzLjE0OwoJQVBQTFkoZywgMiwgSU5ULCBhbnN3ZXIsIGZsb2F0aW5nLCBwaSk7CglDQUxMKGYpOwoJcHJpbnRmKCJkb25lXG4iKTsKCUNBTEwoZyk7CglwcmludGYoIm5vdyBjb21wbGV0ZWx5IGRvbmVcbiIpOwoJcmV0dXJuIDA7Cn0=