1 | #include "CException.h"␊ |
2 | #include "libsaio.h"␊ |
3 | ␊ |
4 | volatile CEXCEPTION_FRAME_T CExceptionFrames[CEXCEPTION_NUM_ID] = { {0} };␊ |
5 | ␊ |
6 | //------------------------------------------------------------------------------------------␊ |
7 | // Install or Restore Default handler␊ |
8 | //------------------------------------------------------------------------------------------␊ |
9 | int Install_Default_Handler(void)␊ |
10 | {␊ |
11 | #define XTRY Try␊ |
12 | #define XCATCH(e) \␊ |
13 | else { } \␊ |
14 | CExceptionFrames[MY_ID].Exception = CEXCEPTION_NONE; \␊ |
15 | } \␊ |
16 | else \␊ |
17 | { e = CExceptionFrames[MY_ID].Exception; e=e; } \␊ |
18 | CExceptionFrames[MY_ID].pFrame = PrevFrame; \␊ |
19 | } \␊ |
20 | if (CExceptionFrames[CEXCEPTION_GET_ID].Exception != CEXCEPTION_NONE)␊ |
21 | ␊ |
22 | CEXCEPTION_T e = CEXCEPTION_NONE;␊ |
23 | ␉␊ |
24 | ␉XTRY␊ |
25 | ␉{␊ |
26 | ␉}␊ |
27 | ␉XCATCH(e)␊ |
28 | ␉{␊ |
29 | halt();␊ |
30 | }␊ |
31 | return 1;␊ |
32 | }␊ |
33 | ␊ |
34 | //------------------------------------------------------------------------------------------␊ |
35 | // Throw␊ |
36 | //------------------------------------------------------------------------------------------␊ |
37 | void Throw(CEXCEPTION_T ExceptionID)␊ |
38 | {␊ |
39 | unsigned int MY_ID = CEXCEPTION_GET_ID;␊ |
40 | CExceptionFrames[MY_ID].Exception = ExceptionID;␊ |
41 | if (CExceptionFrames[MY_ID].pFrame)␊ |
42 | {␊ |
43 | longjmp(*CExceptionFrames[MY_ID].pFrame, 1);␊ |
44 | }␊ |
45 | CEXCEPTION_NO_CATCH_HANDLER(MY_ID);␊ |
46 | }␊ |
47 | ␊ |
48 | //------------------------------------------------------------------------------------------␊ |
49 | // Explanation of what it's all for:␊ |
50 | //------------------------------------------------------------------------------------------␊ |
51 | /*␊ |
52 | #define Try␊ |
53 | { <- give us some local scope. most compilers are happy with this␊ |
54 | jmp_buf *PrevFrame, NewFrame; <- prev frame points to the last try block's frame. new frame gets created on stack for this Try block␊ |
55 | unsigned int MY_ID = CEXCEPTION_GET_ID; <- look up this task's id for use in frame array. always 0 if single-tasking␊ |
56 | PrevFrame = CExceptionFrames[CEXCEPTION_GET_ID].pFrame; <- set pointer to point at old frame (which array is currently pointing at)␊ |
57 | CExceptionFrames[MY_ID].pFrame = &NewFrame; <- set array to point at my new frame instead, now␊ |
58 | CExceptionFrames[MY_ID].Exception = CEXCEPTION_NONE; <- initialize my exception id to be NONE␊ |
59 | if (setjmp(NewFrame) == 0) { <- do setjmp. it returns 1 if longjump called, otherwise 0␊ |
60 | if (1) <- this is here to force proper scoping. it requires braces or a single line to be but after Try, otherwise won't compile. This is always true at this point.␊ |
61 | if (1) is also always true and the compiler will not warn␊ |
62 | #define Catch(e)␊ |
63 | else { } <- this also forces proper scoping. Without this they could stick their own 'else' in and it would get ugly␊ |
64 | CExceptionFrames[MY_ID].Exception = CEXCEPTION_NONE; <- no errors happened, so just set the exception id to NONE (in case it was corrupted)␊ |
65 | }␊ |
66 | else <- an exception occurred␊ |
67 | { e = CExceptionFrames[MY_ID].Exception; e=e;} <- assign the caught exception id to the variable passed in.␊ |
68 | CExceptionFrames[MY_ID].pFrame = PrevFrame; <- make the pointer in the array point at the previous frame again, as if NewFrame never existed.␊ |
69 | } <- finish off that local scope we created to have our own variables␊ |
70 | if (CExceptionFrames[CEXCEPTION_GET_ID].Exception != CEXCEPTION_NONE) <- start the actual 'catch' processing if we have an exception id saved away␊ |
71 | if (Install_or_Restore_Default_Handler) <- and finally we re-install the default exceptions handler to be sure that throw, exit, assert, etc... point to the right place␊ |
72 | */␊ |
73 | ␊ |
74 | |