#ifndef __TUNNEL_MACRO_H__ #define __TUNNEL_MACRO_H__ #include #include #define _new(T, ...) ({ T __v = { __VA_ARGS__ }; _copy(&__v); }) #define _copy(p, ...) _copy_(p, ## __VA_ARGS__, sizeof(*p)) #define _copy_(p, n, ...) memcpy(malloc(n), p, n) #define __unused __attribute__((unused)) #define __cleanup(f) __attribute__((cleanup(f))) #define CAT(a, b) CAT_(a, b) #define CAT_(a, b) a ## b #define UNIQ(name) CAT(name, __LINE__) #define defer \ auto void UNIQ(defer_func)(int *); \ int UNIQ(defer_var) __cleanup(UNIQ(defer_func)); \ void UNIQ(defer_func)(int *p __unused) static __unused void __let_nothing(void) { } #define let(p, e, ...) let_(p, e, ## __VA_ARGS__, __let_nothing) #define let_(p, e, f, ...) \ for (int step = 1; step; ) \ for (typeof(e) p = e; step; f(p), step = 0) static inline int lenv(void **pp) { int count = 0; if (pp) { for (; *pp; pp++) count++; } return count; } #define lenv(v) lenv((void **) v) static inline void **addv(void ***v, void *p) { if (! v) { *v = calloc(2, sizeof(*v)); **v = p; } else { int len = lenv(*v); *v = realloc(*v, sizeof(*v) * (len + 2)); (*v)[len] = p; (*v)[len + 1] = NULL; } return *v; } #define addv(v, p) addv((void ***) v, p) #endif