3 ms·
Just use some macros, easy peasy. (gcc computed goto) #define DEFER_START(scope_name) void * scope_name = &&scope_name##_end; #define DEFER(scope_name
by DudeInBasement 6y ago
Just use some macros, easy peasy. (gcc computed goto)
#define DEFER_START(scope_name) void * scope_name = &&scope_name##_end;
#define DEFER(scope_name, iter_name, func) void * iter_name = scope_name; { \
scope_name = &&iter_name ##_exe; \
if (0) { iter_name##_exe: {func} goto *iter_name; } }
#define DEFER_END(scope_name) scope_name##_start: goto *scope_name; scope_name##_end: {}
#define DEFER_EXE(scope_name) goto scope_name##_start;
...
{
DEFER_START(scope);
void * p = malloc(4);
if (!p) DEFER_EXE(scope);
DEFER(scope, free_p, { printf("freep\n"); free(p); });
void * q = malloc(40);
if (!q) DEFER_EXE(scope);
DEFER(scope, free_q, { printf("freeq\n"); free(q); });
DEFER_END(scope);
}
you can even macro the free_p/ free_q names with line numbers to shorten the macros, IE DEFER(scope, {});
- DudeInBasement 6y agoAdd: If you want an easier, and use shadowed variables: #define guard_name3(name, line) name ## line #define guard_name2(name, line) guard_name3(name, line) #define guard_line_name(name) guard_name2(name, __LINE__) #define guard { void * defer_scope = &&guard_line_name(defer_scope ##_exe); \ if (0) { guard_line_name(defer_scope ##_exe) : defer_scope = 0; }\ if (defer_scope != 0) #define guard_end goto * defer_scope; } #define guard_break goto *defer_scope; #define defer(func) void * guard_line_name(defer_scope_item) = defer_scope; \ defer_scope = &&guard_line_name(defer_scope_item##_label); \ if (0) { guard_line_name(defer_scope_item##_label): { func } goto * guard_line_name(defer_scope_item); } guard { void * p = malloc(10); if (!p) guard_break; defer({ printf("freep\n"); free(p);}); void * q = malloc(10); if (!q) guard_break; defer({printf("freeq\n"); free(q);}); void * fail = 0; if (!fail) guard_break; defer({printf("freefail\n"); free(fail);}); guard_end; }