1 #include <errno.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <setjmp.h> 5 #include <math.h> 6 7 struct trycatch 8 { 9 jmp_buf * buf; 10 struct trycatch * prev; 11 void * exception; 12 } __thread * current_trycatch = NULL; 13 14 #define THROW_WITH_DATA(e,d) do { \ 15 current_trycatch->exception = d; \ 16 longjmp (*(current_trycatch->buf), e); \ 17 } while (0) 18 19 #define THROW(e) do { \ 20 longjmp (*(current_trycatch->buf), e); \ 21 } while (0) 22 23 #define TRY \ 24 do { \ 25 jmp_buf __bUf; \ 26 struct trycatch __tRy; \ 27 int __eRr; \ 28 __tRy.buf = &__bUf; \ 29 __tRy.prev = current_trycatch; \ 30 current_trycatch = &__tRy; \ 31 __eRr = setjmp (__bUf); \ 32 switch (__eRr) \ 33 { \ 34 case 0: \ 35 do { 36 37 #define CATCH_WITH_DATA(e,d) \ 38 } while (0); \ 39 break; \ 40 case e: \ 41 do { \ 42 void * (d) = current_trycatch->exception; 43 44 #define CATCH(e) \ 45 } while (0); \ 46 break; \ 47 case e: \ 48 do { \ 49 50 #define ENDTRY \ 51 } while (0); \ 52 break; \ 53 default: \ 54 if (current_trycatch->prev) \ 55 { \ 56 current_trycatch = current_trycatch->prev; \ 57 THROW_WITH_DATA(__eRr, __tRy.exception); \ 58 } \ 59 else \ 60 { \ 61 fprintf (stderr, "Unhandled exception %i!\n", __eRr); \ 62 } \ 63 } \ 64 current_trycatch = current_trycatch->prev; \ 65 } while (0); 66 67 long int 68 isqrt (long int par) 69 { 70 if (par < 0) 71 THROW(EDOM); 72 73 return (long int) sqrt((double) par); 74 } 75 76 void 77 nested (char * arg) 78 { 79 long int res; 80 81 TRY { 82 char * end; 83 long int number = strtol (arg, &end, 10); 84 85 if (*end != '\0') 86 THROW_WITH_DATA(EINVAL, (void *) "argument contains nondecadic characters!"); 87 88 res = isqrt (number); 89 if (res > 1000) 90 THROW(E2BIG); 91 } CATCH (E2BIG) { 92 printf ("number too big\n"); 93 } ENDTRY; 94 95 printf("result = %li\n\n", res); 96 } 97 98 int 99 main (int argc, char ** argv) 100 { 101 TRY { 102 if (argc != 2) 103 THROW_WITH_DATA(EINVAL, (void *) "bad argc!"); 104 105 nested (argv[1]); 106 107 } CATCH_WITH_DATA (EINVAL, errstr) { 108 printf("usage: trycatch arg - (%s)\n\n", (char *) errstr); 109 } ENDTRY; 110 111 exit (EXIT_SUCCESS); 112 } 113