5229f3f5f23eafbd407173ea15a26e926e689a57
[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 #define PUSH_EXCEPT     (ASSERT(except_top < EXCEPT_CONTEXTS), setjmp(except_stack[except_top++]))
36 #define POP_EXCEPT      (ASSERT(except_top > 0), --except_top)
37 #define DO_EXCEPT       (ASSERT(except_top > 0), longjmp(except_stack[--except_top], true))
38
39 /**
40  * Jump buffer to use when throwing an exception or aborting an operation
41  *
42  * User code can throw exceptions like this:
43  *
44  * \code
45  *   void a_function_throwing_exceptions(void)
46  *   {
47  *       if (some_error_condition)
48  *          THROW;
49  *   }
50  * \endcode
51  *
52  * Catching exceptions (brackets are optional):
53  *
54  * \code
55  *    EXCEPT_DEFINE;
56  *
57  *    void a_function_catching_an_exception(void)
58  *    {
59  *        TRY
60  *        {
61  *            printf("Entered try block\n");
62  *            a_function_throwing_exceptions();
63  *            printf("Survived execution of critical code\n");
64  *        }
65  *        CATCH
66  *        {
67  *            printf("Exception caught!\n");
68  *        }
69  *        CATCH_END
70  *    }
71  * \endcode
72  *
73  * Simple syntax when you don't need to do anything when catching an excaption:
74  *
75  * \code
76  *    TRY
77  *        printf("Entered try block\n");
78  *        a_function_throwing_exceptions();
79  *        printf("Survived execution of critical code\n");
80  *    TRY_END
81  * \endcode
82  *
83  * You also need to declare the exception stack once in
84  * your global declarations:
85  * \code
86  *    EXCEPT_DEFINE;
87  * \endcode
88  */
89 #define TRY          if (PUSH_EXCEPT) { {
90 #define TRY_END      } POP_EXCEPT; }
91 #define CATCH        } POP_EXCEPT; } else {
92 #define CATCH_END    }
93 #define THROW        DO_EXCEPT
94
95
96 #define EXCEPT_DEFINE \
97         jmp_buf except_stack[EXCEPT_CONTEXTS]; \
98         int except_top;
99
100 #endif /* MWARE_EXCEPT_H */