File: except.h

package info (click to toggle)
ruby-ferret 0.11.8.4%2Bdebian-2
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 4,368 kB
  • sloc: ansic: 69,786; ruby: 8,131; makefile: 5
file content (181 lines) | stat: -rw-r--r-- 5,117 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/**
 * Exception Handling Framework
 *
 * Exception Handling looks something like this;
 *
 * ### NOTE ###
 * You must use a FINALLY block if you use "default:" block. Otherwise the
 * default: block will get called in place of the FINALLY block.
 *
 *
 * <pre>
 *   FRT_TRY
 *       FRT_RAISE(FRT_EXCEPTION, msg1);
 *       break;
 *   case FRT_EXCEPTION:
 *       // This should be called
 *       exception_handled = true;
 *       FRT_HANDLED();
 *       break;
 *   default:
 *       // shouldn't enter here
 *       break;
 *   FRT_XFINALLY
 *       // this code will always be run
 *       if (close_widget_one(arg) == 0) {
 *           FRT_RAISE(EXCEPTION_CODE, msg);
 *       }
 *       // this code will also always run, even if the above exception is
 *       // raised
 *       if (close_widget_two(arg) == 0) {
 *           FRT_RAISE(EXCEPTION_CODE, msg);
 *       }
 *   FRT_XENDTRY
 * </pre>
 *
 * Basically exception handling uses the following macros;
 *
 * FRT_TRY
 *   Sets up the exception handler and need be placed before any expected
 *   exceptions would be raised.
 *
 * case <EXCEPTION_CODE>:
 *   Internally the exception handling uses a switch statement so use the case
 *   statement with the appropriate error code to catch Exceptions. Hence, if
 *   you want to catch all exceptions, use the default keyword.
 *
 * FRT_HANDLED
 *   If you catch and handle an exception you need to explicitely call
 *   FRT_HANDLED(); or the exeption will be re-raised once the current exception
 *   handling context is left.
 *
 * case FRT_FINALLY:
 *   Code in this block is always called. Use this block to close any
 *   resources opened in the Exception handling body.
 *
 * FRT_ENDTRY
 *   Must be placed at the end of all exception handling code.
 *
 * FRT_XFINALLY
 *   Similar to case FRT_FINALLY: except that it uses a fall through (ie, you must
 *   not use a break before it) instead of a jump to get to it. This saves a
 *   jump. It must be used in combination with FRT_XENDTRY and must not have any
 *   other catches. This is an optimization so should probably be not be used
 *   in most cases.
 *
 * FRT_XCATCHALL
 *   Like FRT_XFINALLY but the block is only called when an exception is raised.
 *   Must use in combination with FRT_XENDTRY and do not have any other FRT_FINALLY or
 *   catch block.
 *
 * FRT_XENDTRY
 *   Must use in combination with FRT_XFINALLY or FRT_XCATCHALL. Simply, it doesn't
 *   jump to FRT_FINALLY, making it more efficient.
 */
#ifndef FRT_EXCEPT_H
#define FRT_EXCEPT_H

#ifdef __cplusplus
extern "C" {
#endif

#include <setjmp.h>
#include "config.h"

/* TODO make this an enum */
#define FRT_BODY 0
#define FRT_FINALLY 1
#define FRT_EXCEPTION 2
#define FRT_FERRET_ERROR 2
#define FRT_IO_ERROR 3
#define FRT_FILE_NOT_FOUND_ERROR 4
#define FRT_ARG_ERROR 5
#define FRT_EOF_ERROR 6
#define FRT_UNSUPPORTED_ERROR 7
#define FRT_STATE_ERROR 8
#define FRT_PARSE_ERROR 9
#define FRT_MEM_ERROR 10
#define FRT_INDEX_ERROR 11
#define FRT_LOCK_ERROR 12

extern char *const FRT_UNSUPPORTED_ERROR_MSG;
extern char *const FRT_EOF_ERROR_MSG;

typedef struct frt_xcontext_t
{
    jmp_buf jbuf;
    struct frt_xcontext_t *next;
    const char *msg;
    volatile int excode;
    unsigned int handled : 1;
    unsigned int in_finally : 1;
} frt_xcontext_t;

#define FRT_TRY\
  do {\
    frt_xcontext_t xcontext;\
    frt_xpush_context(&xcontext);\
    switch (setjmp(xcontext.jbuf)) {\
      case FRT_BODY:


#define FRT_XENDTRY\
    }\
    frt_xpop_context();\
  } while (0);

#define FRT_ENDTRY\
    }\
    if (!xcontext.in_finally) {\
      frt_xpop_context();\
      xcontext.in_finally = 1;\
      longjmp(xcontext.jbuf, FRT_FINALLY);\
    }\
  } while (0);

#define FRT_RETURN_EARLY() frt_xpop_context()


#define FRT_XFINALLY default: xcontext.in_finally = 1;

#define FRT_XCATCHALL break; default: xcontext.in_finally = 1;

#define FRT_HANDLED() xcontext.handled = 1; /* true */

#define FRT_XMSG_BUFFER_SIZE 2048

#ifdef FRT_HAS_ISO_VARARGS
# define FRT_RAISE(excode, ...) do {\
  snprintf(frt_xmsg_buffer, FRT_XMSG_BUFFER_SIZE, __VA_ARGS__);\
  snprintf(frt_xmsg_buffer_final, FRT_XMSG_BUFFER_SIZE,\
          "Error occured in %s:%d - %s\n\t%s",\
          __FILE__, __LINE__, __func__, frt_xmsg_buffer);\
  frt_xraise(excode, frt_xmsg_buffer_final);\
} while (0)
#elif defined(FRT_HAS_GNUC_VARARGS)
# define FRT_RAISE(excode, args...) do {\
  snprintf(frt_xmsg_buffer, FRT_XMSG_BUFFER_SIZE, ##args);\
  snprintf(frt_xmsg_buffer_final, FRT_XMSG_BUFFER_SIZE,\
          "Error occured in %s:%d - %s\n\t%s\n",\
          __FILE__, __LINE__, __func__, frt_xmsg_buffer);\
  frt_xraise(excode, frt_xmsg_buffer_final);\
} while (0)

#else
extern void FRT_RAISE(int excode, const char *fmt, ...);
#endif
#define RAISE_HELL() FRT_RAISE(FRT_FERRET_ERROR, "Hell")


extern void frt_xraise(int excode, const char *const msg);
extern void frt_xpush_context(frt_xcontext_t *context);
extern void frt_xpop_context();

extern char frt_xmsg_buffer[FRT_XMSG_BUFFER_SIZE];
extern char frt_xmsg_buffer_final[FRT_XMSG_BUFFER_SIZE];

#ifdef __cplusplus
} // extern "C"
#endif

#endif