Search code examples
cexceptionmacrossetjmp

C macros with opening and closing tags?


I just started reading this article about exception handling in c with the use of setjmp( jmp_buf ) and longjmp( jmp_buf, int ). So I basically build the linked list that uses the local variables from type xRecord and links it to the list. (Example 2) It works just fine. But in example 3 the steps get summarized into macros (XTRY and XEND). What irritates me most is that the actual switch statement of example 2 just "vanished" in 3.

Example 2:

   #define DIVIDE_BY_ZERO -3
   int SomeFunction(int a, int b)
   {
      if (b == 0) // can't divide by 0
         XRaise(DIVIDE_BY_ZERO);
      return a / b;
   }

   void main(void)
   {
      XRecord XData;
      XLinkExceptionRecord(&XData);
      switch (setjmp(XData.Context))
      {
         case 0: // this is the code block
            {
               int Result = SomeFunction(7, 0);
               // continue working with Result
            }
            break;
         case DIVIDE_BY_ZERO:
            printf("a division by zero occurred\n");
            break;
         default:
            printf("some other error occurred\n");
            break;
         case XFINALLY:
            printf("cleaning up\n");
      }
      XUnLinkExceptionRecord(&XData);
   }

Example 3:

void main(void)
   {
      XTRY
         case XCODE: // this is the code block
            {
               int Result = SomeFunction(7, 0);
               // continue working with Result
            }
            break;
         case DIVIDE_BY_ZERO: // handler for a
                                 specific exception
            printf("a division by zero occurred\n");
            break;
         default: // default handler
            printf("some other error occurred\n");
            break;
         case XFINALLY: // finally handler
            printf("cleaning up\n");
      XEND
   }

My question is, how can I build these "opening and closing" macros?


Solution

  • If you compare the two examples, and keep in mind that C macros are simple text substitutions, what the macros should be is evident:

    #define XTRY  XRecord XData; \
                  XLinkExceptionRecord(&XData); \
                  switch (setjmp(XData.Context)) \
                  {
    
    #define XEND  } \
                  XUnLinkExceptionRecord(&XData);
    

    Note the use of \ to allow the macro to span more than one line.

    You may also want to have the macros open and close a new scope (by adding { and }), so that using the macros multiple in succession doesn't give an error due to multiple definitions of the variable XData. You can also use the do / while(0) trick to allow these macros to be placed directly inside if, for, etc. without issues.