#include #include #include #include #include struct trycatch { jmp_buf * buf; struct trycatch * prev; void * exception; } __thread * current_trycatch = NULL; #define THROW_WITH_DATA(e,d) do { \ current_trycatch->exception = d; \ longjmp (*(current_trycatch->buf), e); \ } while (0) #define THROW(e) do { \ longjmp (*(current_trycatch->buf), e); \ } while (0) #define TRY \ do { \ jmp_buf __bUf; \ struct trycatch __tRy; \ int __eRr; \ __tRy.buf = &__bUf; \ __tRy.prev = current_trycatch; \ current_trycatch = &__tRy; \ __eRr = setjmp (__bUf); \ switch (__eRr) \ { \ case 0: \ do { #define CATCH_WITH_DATA(e,d) \ } while (0); \ break; \ case e: \ do { \ void * (d) = current_trycatch->exception; #define CATCH(e) \ } while (0); \ break; \ case e: \ do { \ #define ENDTRY \ } while (0); \ break; \ default: \ if (current_trycatch->prev) \ { \ current_trycatch = current_trycatch->prev; \ THROW_WITH_DATA(__eRr, __tRy.exception); \ } \ else \ { \ fprintf (stderr, "Unhandled exception %i!\n", __eRr); \ } \ } \ current_trycatch = current_trycatch->prev; \ } while (0); long int isqrt (long int par) { if (par < 0) THROW(EDOM); return (long int) sqrt((double) par); } void nested (char * arg) { long int res; TRY { char * end; long int number = strtol (arg, &end, 10); if (*end != '\0') THROW_WITH_DATA(EINVAL, (void *) "argument contains nondecadic characters!"); res = isqrt (number); if (res > 1000) THROW(E2BIG); } CATCH (E2BIG) { printf ("number too big\n"); } ENDTRY; printf("result = %li\n\n", res); } int main (int argc, char ** argv) { TRY { if (argc != 2) THROW_WITH_DATA(EINVAL, (void *) "bad argc!"); nested (argv[1]); } CATCH_WITH_DATA (EINVAL, errstr) { printf("usage: trycatch arg - (%s)\n\n", (char *) errstr); } ENDTRY; exit (EXIT_SUCCESS); }