Structured exceptions support for C programs.
[bertos.git] / mware / except.h
1 /**
2  * \file
3  * <!--
4  * Copyright 2006 Develer S.r.l. (http://www.develer.com/)
5  * Copyright 1999 Bernardo Innocenti <bernie@develer.com>
6  * This file is part of DevLib - See README.devlib for information.
7  * -->
8  *
9  * \brief C++-like structured exception handling for C programs
10  *
11  * \version $Id$
12  * \author Bernardo Innocenti <bernie@develer.com>
13  */
14 #ifndef MWARE_EXCEPT_H
15 #define MWARE_EXCEPT_H
16
17 #include <cfg/debug.h>
18
19 #include <setjmp.h>
20
21 #define EXCEPT_CONTEXTS 8
22
23 /**
24  * A stack of jump buffers used to record try sites
25  * so they can be reached from throw sites.
26  *
27  * The stack contains return points for each nested
28  * context. jmp_buf's are pushed into the stack at
29  * try points and popped out when the try block ends
30  * normally or when an exception is thrown.
31  */
32 extern jmp_buf except_stack[EXCEPT_CONTEXTS];
33 extern int except_top;
34
35 #ifdef _DEBUG
36 #       define PUSH_ABORT       ASSERT(abort_top < ABORT_CONTEXTS), setjmp(abort_stack[abort_top++]))
37 #       define POP_ABORT        (ASSERT(abort_top > 0), --abort_top)
38 #       define DO_ABORT         (ASSERT(abort_top > 0), longjmp(abort_stack[--abort_top], true))
39 #else
40 #       define PUSH_ABORT       (setjmp(abort_stack[abort_top++]))
41 #       define POP_ABORT        (--abort_top)
42 #       define DO_ABORT         (longjmp(abort_stack[--abort_top], true))
43 #endif
44
45 /**
46  * Jump buffer to use when throwing an exception or aborting an operation
47  *
48  * User code can throw exceptions like this:
49  *
50  * \code
51  *   void a_function_throwing_exceptions(void)
52  *   {
53  *       if (some_error_condition)
54  *          THROW;
55  *   }
56  * \endcode
57  *
58  * Catching exceptions (brackets are optional):
59  *
60  * \code
61  *    EXCEPT_DEFINE;
62  *
63  *    void a_function_catching_an_exception(void)
64  *    {
65  *        TRY
66  *        {
67  *            printf("Entered try block\n");
68  *            a_function_throwing_exceptions();
69  *            printf("Survived execution of critical code\n");
70  *        }
71  *        CATCH
72  *        {
73  *            printf("Exception caught!\n");
74  *        }
75  *        CATCH_END
76  *    }
77  * \endcode
78  *
79  * Simple syntax when you don't need to do anything when catching an excaption:
80  *
81  * \code
82  *    TRY
83  *        printf("Entered try block\n");
84  *        a_function_throwing_exceptions();
85  *        printf("Survived execution of critical code\n");
86  *    TRY_END
87  * \endcode
88  *
89  * You also need to declare the exception stack once in
90  * your global declarations:
91  * \code
92  *    EXCEPT_DEFINE;
93  * \endcode
94  */
95 #define TRY          if (PUSH_ABORT) { {
96 #define TRY_END      } POP_ABORT; }
97 #define CATCH        } POP_ABORT; } else {
98 #define CATCH_END    }
99 #define THROW        DO_ABORT
100
101
102 #define EXCEPT_DEFINE \
103         jmp_buf abort_stack[ABORT_CONTEXTS]; \
104         int abort_top;
105
106 #endif /* MWARE_EXCEPT_H */