// names are unique within a function, any valid variable name
// a jump table try, allowing return values to determine the exception thrown(index in a jump table, -1 being success for example)
// you only need to put in what you need, not all exceptions, or total exception count
#define GTRY(name, exc) void* __jt_##name[exc];int __jtix_##name = 0;
// register an exception in the jump table. you don't need to do them all
#define GTEX(name, exception) __jtix_##name;__jt_##name[__jtix_##name++] = &&__tr_##exception##name;
// resets the jump table index to a given value, useful for overwriting exceptions without a new try.
#define GTRST(name, index) __jtix_##name = index;
// a standard try, doesn't actually add anything, but for cleanliness.
#define TRY(name) ;
// throw an exception by name
#define THROW(name, exception) goto __tr_##exception##name;
// throws an exception by jump table index
#define GTHROW(name, exn) goto *__jt_##name[exn];
// begins a catch block
#define CATCH(name, exception) goto __trend_##name;__tr_##exception##name:;
// signifies where the try ends
#define ENDTRY(name) __trend_##name:;
// 'finally' blocks need only be put after an end try.
Usage Example:
int main(int argc, char* argv[]) {
TRY(magic)
THROW(magic, EOF)
CATCH(magic, EOF)
printf("eof!\n");
ENDTRY(magic)
printf("complete\n");
GTRY(fagic, 2)
int eof = GTEX(fagic, EOF)
int rst = GTEX(fagic, RST)
GTHROW(fagic, rst)
CATCH(fagic, EOF)
printf("eof2!\n");
CATCH(fagic, RST)
printf("rst\n");
ENDTRY(fagic);
//
TRY(nest) {
THROW(nest, EOF);
} CATCH(nest, EOF) {
printf("eof3!\n");
}
ENDTRY(nest)
printf("complete3\n");
return 0;
}
My purpose was to create a macro-based exception system that can run on embedded devices with ease(magic is done compile-time). There is a potential performance malice if CPUs don't support labels as values and GTRY is used.